diff --git a/public/Images/Images.js b/public/Images/Images.js index 3cc610c8d..e41b97ac9 100644 --- a/public/Images/Images.js +++ b/public/Images/Images.js @@ -47,6 +47,7 @@ style.setProperty('--image-file-arrow-down', 'url(\"' + new URL(new URL('arrow-d style.setProperty('--image-file-arrow-drop-down-dark', 'url(\"' + new URL(new URL('arrow-drop-down-dark.svg', import.meta.url).href, import.meta.url).toString() + '\")'); style.setProperty('--image-file-arrow-drop-down-light', 'url(\"' + new URL(new URL('arrow-drop-down-light.svg', import.meta.url).href, import.meta.url).toString() + '\")'); style.setProperty('--image-file-arrow-forward', 'url(\"' + new URL(new URL('arrow-forward.svg', import.meta.url).href, import.meta.url).toString() + '\")'); +style.setProperty('--image-file-arrow-right-circle', 'url(\"' + new URL(new URL('arrow-right-circle.svg', import.meta.url).href, import.meta.url).toString() + '\")'); style.setProperty('--image-file-arrow-up-down-circle', 'url(\"' + new URL(new URL('arrow-up-down-circle.svg', import.meta.url).href, import.meta.url).toString() + '\")'); style.setProperty('--image-file-arrow-up-down', 'url(\"' + new URL(new URL('arrow-up-down.svg', import.meta.url).href, import.meta.url).toString() + '\")'); style.setProperty('--image-file-arrow-up', 'url(\"' + new URL(new URL('arrow-up.svg', import.meta.url).href, import.meta.url).toString() + '\")'); @@ -242,7 +243,9 @@ style.setProperty('--image-file-stop', 'url(\"' + new URL(new URL('stop.svg', im style.setProperty('--image-file-symbol', 'url(\"' + new URL(new URL('symbol.svg', import.meta.url).href, import.meta.url).toString() + '\")'); style.setProperty('--image-file-sync', 'url(\"' + new URL(new URL('sync.svg', import.meta.url).href, import.meta.url).toString() + '\")'); style.setProperty('--image-file-table', 'url(\"' + new URL(new URL('table.svg', import.meta.url).href, import.meta.url).toString() + '\")'); +style.setProperty('--image-file-thumb-down-filled', 'url(\"' + new URL(new URL('thumb-down-filled.svg', import.meta.url).href, import.meta.url).toString() + '\")'); style.setProperty('--image-file-thumb-down', 'url(\"' + new URL(new URL('thumb-down.svg', import.meta.url).href, import.meta.url).toString() + '\")'); +style.setProperty('--image-file-thumb-up-filled', 'url(\"' + new URL(new URL('thumb-up-filled.svg', import.meta.url).href, import.meta.url).toString() + '\")'); style.setProperty('--image-file-thumb-up', 'url(\"' + new URL(new URL('thumb-up.svg', import.meta.url).href, import.meta.url).toString() + '\")'); style.setProperty('--image-file-top-panel-close', 'url(\"' + new URL(new URL('top-panel-close.svg', import.meta.url).href, import.meta.url).toString() + '\")'); style.setProperty('--image-file-top-panel-open', 'url(\"' + new URL(new URL('top-panel-open.svg', import.meta.url).href, import.meta.url).toString() + '\")'); diff --git a/public/Images/Images.prebundle.js b/public/Images/Images.prebundle.js index fe246e94f..8bc5cfc12 100644 --- a/public/Images/Images.prebundle.js +++ b/public/Images/Images.prebundle.js @@ -48,6 +48,7 @@ style.setProperty('--image-file-arrow-down', 'url(\"' + new URL('./src/arrow-dow style.setProperty('--image-file-arrow-drop-down-dark', 'url(\"' + new URL('./src/arrow-drop-down-dark.svg', import.meta.url).toString() + '\")'); style.setProperty('--image-file-arrow-drop-down-light', 'url(\"' + new URL('./src/arrow-drop-down-light.svg', import.meta.url).toString() + '\")'); style.setProperty('--image-file-arrow-forward', 'url(\"' + new URL('./src/arrow-forward.svg', import.meta.url).toString() + '\")'); +style.setProperty('--image-file-arrow-right-circle', 'url(\"' + new URL('./src/arrow-right-circle.svg', import.meta.url).toString() + '\")'); style.setProperty('--image-file-arrow-up-down-circle', 'url(\"' + new URL('./src/arrow-up-down-circle.svg', import.meta.url).toString() + '\")'); style.setProperty('--image-file-arrow-up-down', 'url(\"' + new URL('./src/arrow-up-down.svg', import.meta.url).toString() + '\")'); style.setProperty('--image-file-arrow-up', 'url(\"' + new URL('./src/arrow-up.svg', import.meta.url).toString() + '\")'); @@ -243,7 +244,9 @@ style.setProperty('--image-file-stop', 'url(\"' + new URL('./src/stop.svg', impo style.setProperty('--image-file-symbol', 'url(\"' + new URL('./src/symbol.svg', import.meta.url).toString() + '\")'); style.setProperty('--image-file-sync', 'url(\"' + new URL('./src/sync.svg', import.meta.url).toString() + '\")'); style.setProperty('--image-file-table', 'url(\"' + new URL('./src/table.svg', import.meta.url).toString() + '\")'); +style.setProperty('--image-file-thumb-down-filled', 'url(\"' + new URL('./src/thumb-down-filled.svg', import.meta.url).toString() + '\")'); style.setProperty('--image-file-thumb-down', 'url(\"' + new URL('./src/thumb-down.svg', import.meta.url).toString() + '\")'); +style.setProperty('--image-file-thumb-up-filled', 'url(\"' + new URL('./src/thumb-up-filled.svg', import.meta.url).toString() + '\")'); style.setProperty('--image-file-thumb-up', 'url(\"' + new URL('./src/thumb-up.svg', import.meta.url).toString() + '\")'); style.setProperty('--image-file-top-panel-close', 'url(\"' + new URL('./src/top-panel-close.svg', import.meta.url).toString() + '\")'); style.setProperty('--image-file-top-panel-open', 'url(\"' + new URL('./src/top-panel-open.svg', import.meta.url).toString() + '\")'); diff --git a/public/Images/arrow-right-circle.svg b/public/Images/arrow-right-circle.svg new file mode 100644 index 000000000..58ba1ea62 --- /dev/null +++ b/public/Images/arrow-right-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/Images/src/arrow-right-circle.svg b/public/Images/src/arrow-right-circle.svg new file mode 100644 index 000000000..026db928e --- /dev/null +++ b/public/Images/src/arrow-right-circle.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/public/Images/src/thumb-down-filled.svg b/public/Images/src/thumb-down-filled.svg new file mode 100644 index 000000000..30e0e3928 --- /dev/null +++ b/public/Images/src/thumb-down-filled.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/Images/src/thumb-up-filled.svg b/public/Images/src/thumb-up-filled.svg new file mode 100644 index 000000000..d25377ceb --- /dev/null +++ b/public/Images/src/thumb-up-filled.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/Images/thumb-down-filled.svg b/public/Images/thumb-down-filled.svg new file mode 100644 index 000000000..60baf9f2f --- /dev/null +++ b/public/Images/thumb-down-filled.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/Images/thumb-up-filled.svg b/public/Images/thumb-up-filled.svg new file mode 100644 index 000000000..d02c7741c --- /dev/null +++ b/public/Images/thumb-up-filled.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/core/common/Settings.d.ts b/public/core/common/Settings.d.ts index c14d4b7a5..9713061f1 100644 --- a/public/core/common/Settings.d.ts +++ b/public/core/common/Settings.d.ts @@ -25,6 +25,14 @@ export declare class Settings { getHostConfig(): Root.Runtime.HostConfig; private registerModuleSetting; static normalizeSettingName(name: string): string; + /** + * Prefer a module setting if this setting is one that you might not want to + * surface to the user to control themselves. Examples of these are settings + * to store UI state such as how a user choses to position a split widget or + * which panel they last opened. + * If you are creating a setting that you expect the user to control, and + * sync, prefer {@see createSetting} + */ moduleSetting(settingName: string): Setting; settingForTest(settingName: string): Setting; /** @@ -112,7 +120,7 @@ export declare class VersionController { static readonly GLOBAL_VERSION_SETTING_NAME = "inspectorVersion"; static readonly SYNCED_VERSION_SETTING_NAME = "syncedInspectorVersion"; static readonly LOCAL_VERSION_SETTING_NAME = "localInspectorVersion"; - static readonly CURRENT_VERSION = 37; + static readonly CURRENT_VERSION = 38; constructor(); /** * Force re-sets all version number settings to the current version without @@ -165,6 +173,7 @@ export declare class VersionController { updateVersionFrom34To35(): void; updateVersionFrom35To36(): void; updateVersionFrom36To37(): void; + updateVersionFrom37To38(): void; private migrateSettingsFromLocalStorage; private clearBreakpointsWhenTooMany; } diff --git a/public/core/common/Settings.js b/public/core/common/Settings.js index 89c4ced84..f2d7ff309 100644 --- a/public/core/common/Settings.js +++ b/public/core/common/Settings.js @@ -122,6 +122,14 @@ export class Settings { } return Platform.StringUtilities.toKebabCase(name); } + /** + * Prefer a module setting if this setting is one that you might not want to + * surface to the user to control themselves. Examples of these are settings + * to store UI state such as how a user choses to position a split widget or + * which panel they last opened. + * If you are creating a setting that you expect the user to control, and + * sync, prefer {@see createSetting} + */ // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration // eslint-disable-next-line @typescript-eslint/no-explicit-any moduleSetting(settingName) { @@ -540,7 +548,7 @@ export class VersionController { static GLOBAL_VERSION_SETTING_NAME = 'inspectorVersion'; static SYNCED_VERSION_SETTING_NAME = 'syncedInspectorVersion'; static LOCAL_VERSION_SETTING_NAME = 'localInspectorVersion'; - static CURRENT_VERSION = 37; + static CURRENT_VERSION = 38; #globalVersionSetting; #syncedVersionSetting; #localVersionSetting; @@ -1096,6 +1104,24 @@ export class VersionController { } } } + updateVersionFrom37To38() { + const getConsoleInsightsEnabledSetting = () => { + try { + return moduleSetting('console-insights-enabled'); + } + catch { + return; + } + }; + const consoleInsightsEnabled = getConsoleInsightsEnabledSetting(); + const onboardingFinished = Settings.instance().createLocalSetting('console-insights-onboarding-finished', false); + if (consoleInsightsEnabled && consoleInsightsEnabled.get() === true && onboardingFinished.get() === false) { + consoleInsightsEnabled.set(false); + } + if (consoleInsightsEnabled && consoleInsightsEnabled.get() === false) { + onboardingFinished.set(false); + } + } /* * Any new migration should be added before this comment. * diff --git a/public/core/common/Settings.js.map b/public/core/common/Settings.js.map index a5217cefc..40592f17c 100644 --- a/public/core/common/Settings.js.map +++ b/public/core/common/Settings.js.map @@ -1 +1 @@ -{"version":3,"file":"Settings.js","sourceRoot":"","sources":["../../../../../../front_end/core/common/Settings.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (C) 2009 Google Inc. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * * Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above\n * copyright notice, this list of conditions and the following disclaimer\n * in the documentation and/or other materials provided with the\n * distribution.\n * * Neither the name of Google Inc. nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport * as Platform from '../platform/platform.js';\nimport * as Root from '../root/root.js';\n\nimport {Console} from './Console.js';\nimport {type EventDescriptor, type EventTargetEvent, type GenericEvents} from './EventTarget.js';\nimport {ObjectWrapper} from './Object.js';\nimport {\n getLocalizedSettingsCategory,\n getRegisteredSettings as getRegisteredSettingsInternal,\n type LearnMore,\n maybeRemoveSettingExtension,\n type RegExpSettingItem,\n registerSettingExtension,\n registerSettingsForTest,\n resetSettings,\n SettingCategory,\n type SettingExtensionOption,\n type SettingRegistration,\n SettingType,\n} from './SettingRegistration.js';\n\nlet settingsInstance: Settings|undefined;\n\nexport class Settings {\n readonly #sessionStorage: SettingsStorage;\n settingNameSet: Set;\n orderValuesBySettingCategory: Map>;\n #eventSupport: ObjectWrapper;\n #registry: Map>;\n readonly moduleSettings: Map>;\n readonly #config: Root.Runtime.HostConfig;\n\n private constructor(\n readonly syncedStorage: SettingsStorage, readonly globalStorage: SettingsStorage,\n readonly localStorage: SettingsStorage, config?: Root.Runtime.HostConfig) {\n this.#sessionStorage = new SettingsStorage({});\n\n this.settingNameSet = new Set();\n\n this.orderValuesBySettingCategory = new Map();\n\n this.#eventSupport = new ObjectWrapper();\n this.#registry = new Map();\n this.moduleSettings = new Map();\n\n this.#config = config || {};\n for (const registration of this.getRegisteredSettings()) {\n const {settingName, defaultValue, storageType} = registration;\n const isRegex = registration.settingType === SettingType.REGEX;\n\n const evaluatedDefaultValue = typeof defaultValue === 'function' ? defaultValue(this.#config) : defaultValue;\n const setting = isRegex && typeof evaluatedDefaultValue === 'string' ?\n this.createRegExpSetting(settingName, evaluatedDefaultValue, undefined, storageType) :\n this.createSetting(settingName, evaluatedDefaultValue, storageType);\n\n setting.setTitleFunction(registration.title);\n if (registration.userActionCondition) {\n setting.setRequiresUserAction(Boolean(Root.Runtime.Runtime.queryParam(registration.userActionCondition)));\n }\n setting.setRegistration(registration);\n\n this.registerModuleSetting(setting);\n }\n }\n\n getRegisteredSettings(): SettingRegistration[] {\n return getRegisteredSettingsInternal(this.#config);\n }\n\n static hasInstance(): boolean {\n return typeof settingsInstance !== 'undefined';\n }\n\n static instance(opts: {\n forceNew: boolean|null,\n syncedStorage: SettingsStorage|null,\n globalStorage: SettingsStorage|null,\n localStorage: SettingsStorage|null,\n config?: Root.Runtime.HostConfig,\n } = {forceNew: null, syncedStorage: null, globalStorage: null, localStorage: null}): Settings {\n const {forceNew, syncedStorage, globalStorage, localStorage, config} = opts;\n if (!settingsInstance || forceNew) {\n if (!syncedStorage || !globalStorage || !localStorage) {\n throw new Error(`Unable to create settings: global and local storage must be provided: ${new Error().stack}`);\n }\n\n settingsInstance = new Settings(syncedStorage, globalStorage, localStorage, config);\n }\n\n return settingsInstance;\n }\n\n static removeInstance(): void {\n settingsInstance = undefined;\n }\n\n getHostConfig(): Root.Runtime.HostConfig {\n return this.#config;\n }\n\n private registerModuleSetting(setting: Setting): void {\n const settingName = setting.name;\n const category = setting.category();\n const order = setting.order();\n if (this.settingNameSet.has(settingName)) {\n throw new Error(`Duplicate Setting name '${settingName}'`);\n }\n if (category && order) {\n const orderValues = this.orderValuesBySettingCategory.get(category) || new Set();\n if (orderValues.has(order)) {\n throw new Error(`Duplicate order value '${order}' for settings category '${category}'`);\n }\n orderValues.add(order);\n this.orderValuesBySettingCategory.set(category, orderValues);\n }\n this.settingNameSet.add(settingName);\n this.moduleSettings.set(setting.name, setting);\n }\n\n static normalizeSettingName(name: string): string {\n if ([\n VersionController.GLOBAL_VERSION_SETTING_NAME,\n VersionController.SYNCED_VERSION_SETTING_NAME,\n VersionController.LOCAL_VERSION_SETTING_NAME,\n 'currentDockState',\n 'isUnderTest',\n ].includes(name)) {\n return name;\n }\n return Platform.StringUtilities.toKebabCase(name);\n }\n\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n moduleSetting(settingName: string): Setting {\n const setting = this.moduleSettings.get(settingName) as Setting;\n if (!setting) {\n throw new Error('No setting registered: ' + settingName);\n }\n return setting;\n }\n\n settingForTest(settingName: string): Setting {\n const setting = this.#registry.get(settingName);\n if (!setting) {\n throw new Error('No setting registered: ' + settingName);\n }\n return setting;\n }\n\n /**\n * Get setting via key, and create a new setting if the requested setting does not exist.\n */\n createSetting(key: string, defaultValue: T, storageType?: SettingStorageType): Setting {\n const storage = this.storageFromType(storageType);\n let setting = (this.#registry.get(key) as Setting);\n if (!setting) {\n setting = new Setting(key, defaultValue, this.#eventSupport, storage);\n this.#registry.set(key, setting);\n }\n return setting;\n }\n\n createLocalSetting(key: string, defaultValue: T): Setting {\n return this.createSetting(key, defaultValue, SettingStorageType.LOCAL);\n }\n\n createRegExpSetting(key: string, defaultValue: string, regexFlags?: string, storageType?: SettingStorageType):\n RegExpSetting {\n if (!this.#registry.get(key)) {\n this.#registry.set(\n key, new RegExpSetting(key, defaultValue, this.#eventSupport, this.storageFromType(storageType), regexFlags));\n }\n return this.#registry.get(key) as RegExpSetting;\n }\n\n clearAll(): void {\n this.globalStorage.removeAll();\n this.syncedStorage.removeAll();\n this.localStorage.removeAll();\n new VersionController().resetToCurrent();\n }\n\n private storageFromType(storageType?: SettingStorageType): SettingsStorage {\n switch (storageType) {\n case SettingStorageType.LOCAL:\n return this.localStorage;\n case SettingStorageType.SESSION:\n return this.#sessionStorage;\n case SettingStorageType.GLOBAL:\n return this.globalStorage;\n case SettingStorageType.SYNCED:\n return this.syncedStorage;\n }\n return this.globalStorage;\n }\n\n getRegistry(): Map> {\n return this.#registry;\n }\n}\n\nexport interface SettingsBackingStore {\n register(setting: string): void;\n get(setting: string): Promise;\n set(setting: string, value: string): void;\n remove(setting: string): void;\n clear(): void;\n}\n\nexport const NOOP_STORAGE: SettingsBackingStore = {\n register: () => {},\n set: () => {},\n get: () => Promise.resolve(''),\n remove: () => {},\n clear: () => {},\n};\n\nexport class SettingsStorage {\n constructor(\n private object: Record, private readonly backingStore: SettingsBackingStore = NOOP_STORAGE,\n private readonly storagePrefix: string = '') {\n }\n\n register(name: string): void {\n name = this.storagePrefix + name;\n this.backingStore.register(name);\n }\n\n set(name: string, value: string): void {\n name = this.storagePrefix + name;\n this.object[name] = value;\n this.backingStore.set(name, value);\n }\n\n has(name: string): boolean {\n name = this.storagePrefix + name;\n return name in this.object;\n }\n\n get(name: string): string {\n name = this.storagePrefix + name;\n return this.object[name];\n }\n\n async forceGet(originalName: string): Promise {\n const name = this.storagePrefix + originalName;\n const value = await this.backingStore.get(name);\n if (value && value !== this.object[name]) {\n this.set(originalName, value);\n } else if (!value) {\n this.remove(originalName);\n }\n return value;\n }\n\n remove(name: string): void {\n name = this.storagePrefix + name;\n delete this.object[name];\n this.backingStore.remove(name);\n }\n\n removeAll(): void {\n this.object = {};\n this.backingStore.clear();\n }\n\n keys(): string[] {\n return Object.keys(this.object);\n }\n\n dumpSizes(): void {\n Console.instance().log('Ten largest settings: ');\n\n const sizes: {\n [x: string]: number,\n // @ts-expect-error __proto__ optimization\n } = {__proto__: null};\n for (const key in this.object) {\n sizes[key] = this.object[key].length;\n }\n const keys = Object.keys(sizes);\n\n function comparator(key1: string, key2: string): number {\n return sizes[key2] - sizes[key1];\n }\n\n keys.sort(comparator);\n\n for (let i = 0; i < 10 && i < keys.length; ++i) {\n Console.instance().log('Setting: \\'' + keys[i] + '\\', size: ' + sizes[keys[i]]);\n }\n }\n}\n\nfunction removeSetting(setting: {name: string, storage: SettingsStorage}): void {\n const name = setting.name;\n const settings = Settings.instance();\n\n settings.getRegistry().delete(name);\n settings.moduleSettings.delete(name);\n\n setting.storage.remove(name);\n}\n\nexport class Deprecation {\n readonly disabled: boolean;\n readonly warning: Platform.UIString.LocalizedString;\n readonly experiment?: Root.Runtime.Experiment;\n\n constructor({deprecationNotice}: SettingRegistration) {\n if (!deprecationNotice) {\n throw new Error('Cannot create deprecation info for a non-deprecated setting');\n }\n this.disabled = deprecationNotice.disabled;\n this.warning = deprecationNotice.warning();\n this.experiment = deprecationNotice.experiment ?\n Root.Runtime.experiments.allConfigurableExperiments().find(e => e.name === deprecationNotice.experiment) :\n undefined;\n }\n}\n\nexport class Setting {\n #titleFunction?: () => Platform.UIString.LocalizedString;\n #titleInternal!: string;\n #registration: SettingRegistration|null = null;\n #requiresUserAction?: boolean;\n #value?: V;\n // TODO(crbug.com/1172300) Type cannot be inferred without changes to consumers. See above.\n #serializer: Serializer = JSON;\n #hadUserAction?: boolean;\n #disabled?: boolean;\n #deprecation: Deprecation|null = null;\n\n constructor(\n readonly name: string, readonly defaultValue: V, private readonly eventSupport: ObjectWrapper,\n readonly storage: SettingsStorage) {\n storage.register(this.name);\n }\n\n setSerializer(serializer: Serializer): void {\n this.#serializer = serializer;\n }\n\n addChangeListener(listener: (arg0: EventTargetEvent) => void, thisObject?: Object): EventDescriptor {\n return this.eventSupport.addEventListener(this.name, listener, thisObject);\n }\n\n removeChangeListener(listener: (arg0: EventTargetEvent) => void, thisObject?: Object): void {\n this.eventSupport.removeEventListener(this.name, listener, thisObject);\n }\n\n title(): string {\n if (this.#titleInternal) {\n return this.#titleInternal;\n }\n if (this.#titleFunction) {\n return this.#titleFunction();\n }\n return '';\n }\n\n setTitleFunction(titleFunction: (() => Platform.UIString.LocalizedString)|undefined): void {\n if (titleFunction) {\n this.#titleFunction = titleFunction;\n }\n }\n\n setTitle(title: string): void {\n this.#titleInternal = title;\n }\n\n setRequiresUserAction(requiresUserAction: boolean): void {\n this.#requiresUserAction = requiresUserAction;\n }\n\n disabled(): boolean {\n if (this.#registration?.disabledCondition) {\n const {disabled} = this.#registration.disabledCondition(Settings.instance().getHostConfig());\n // If registration does not disable it, pass through to #disabled\n // attribute check.\n if (disabled) {\n return true;\n }\n }\n return this.#disabled || false;\n }\n\n disabledReason(): string|undefined {\n if (this.#registration?.disabledCondition) {\n const result = this.#registration.disabledCondition(Settings.instance().getHostConfig());\n if (result.disabled) {\n return result.reason;\n }\n }\n return undefined;\n }\n\n setDisabled(disabled: boolean): void {\n this.#disabled = disabled;\n this.eventSupport.dispatchEventToListeners(this.name);\n }\n\n get(): V {\n if (this.#requiresUserAction && !this.#hadUserAction) {\n return this.defaultValue;\n }\n\n if (typeof this.#value !== 'undefined') {\n return this.#value;\n }\n\n this.#value = this.defaultValue;\n if (this.storage.has(this.name)) {\n try {\n this.#value = this.#serializer.parse(this.storage.get(this.name));\n } catch (e) {\n this.storage.remove(this.name);\n }\n }\n return this.#value;\n }\n\n // Prefer this getter for settings which are \"disableable\". The plain getter returns `this.#value`,\n // even if the setting is disabled, which means the callsite has to explicitly call the `disabled()`\n // getter and add its own logic for the disabled state.\n getIfNotDisabled(): V|undefined {\n if (this.disabled()) {\n return;\n }\n return this.get();\n }\n\n async forceGet(): Promise {\n const name = this.name;\n const oldValue = this.storage.get(name);\n const value = await this.storage.forceGet(name);\n this.#value = this.defaultValue;\n if (value) {\n try {\n this.#value = this.#serializer.parse(value);\n } catch (e) {\n this.storage.remove(this.name);\n }\n }\n\n if (oldValue !== value) {\n this.eventSupport.dispatchEventToListeners(this.name, this.#value);\n }\n\n return this.#value;\n }\n\n set(value: V): void {\n this.#hadUserAction = true;\n this.#value = value;\n try {\n const settingString = this.#serializer.stringify(value);\n try {\n this.storage.set(this.name, settingString);\n } catch (e) {\n this.printSettingsSavingError(e.message, this.name, settingString);\n }\n } catch (e) {\n Console.instance().error('Cannot stringify setting with name: ' + this.name + ', error: ' + e.message);\n }\n this.eventSupport.dispatchEventToListeners(this.name, value);\n }\n\n setRegistration(registration: SettingRegistration): void {\n this.#registration = registration;\n const {deprecationNotice} = registration;\n if (deprecationNotice?.disabled) {\n const experiment = deprecationNotice.experiment ?\n Root.Runtime.experiments.allConfigurableExperiments().find(e => e.name === deprecationNotice.experiment) :\n undefined;\n if ((!experiment || experiment.isEnabled())) {\n this.set(this.defaultValue);\n this.setDisabled(true);\n }\n }\n }\n\n type(): SettingType|null {\n if (this.#registration) {\n return this.#registration.settingType;\n }\n return null;\n }\n\n options(): SimpleSettingOption[] {\n if (this.#registration && this.#registration.options) {\n return this.#registration.options.map(opt => {\n const {value, title, text, raw} = opt;\n return {\n value,\n title: title(),\n text: typeof text === 'function' ? text() : text,\n raw,\n };\n });\n }\n return [];\n }\n\n reloadRequired(): boolean|null {\n if (this.#registration) {\n return this.#registration.reloadRequired || null;\n }\n return null;\n }\n\n category(): SettingCategory|null {\n if (this.#registration) {\n return this.#registration.category || null;\n }\n return null;\n }\n\n tags(): string|null {\n if (this.#registration && this.#registration.tags) {\n // Get localized keys and separate by null character to prevent fuzzy matching from matching across them.\n return this.#registration.tags.map(tag => tag()).join('\\0');\n }\n return null;\n }\n\n order(): number|null {\n if (this.#registration) {\n return this.#registration.order || null;\n }\n return null;\n }\n\n learnMore(): LearnMore|null {\n return this.#registration?.learnMore ?? null;\n }\n\n get deprecation(): Deprecation|null {\n if (!this.#registration || !this.#registration.deprecationNotice) {\n return null;\n }\n if (!this.#deprecation) {\n this.#deprecation = new Deprecation(this.#registration);\n }\n return this.#deprecation;\n }\n\n private printSettingsSavingError(message: string, name: string, value: string): void {\n const errorMessage =\n 'Error saving setting with name: ' + this.name + ', value length: ' + value.length + '. Error: ' + message;\n console.error(errorMessage);\n Console.instance().error(errorMessage);\n this.storage.dumpSizes();\n }\n}\n\n// TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport class RegExpSetting extends Setting {\n #regexFlags: string|undefined;\n #regex?: RegExp|null;\n\n constructor(\n name: string, defaultValue: string, eventSupport: ObjectWrapper, storage: SettingsStorage,\n regexFlags?: string) {\n super(name, defaultValue ? [{pattern: defaultValue}] : [], eventSupport, storage);\n this.#regexFlags = regexFlags;\n }\n\n override get(): string {\n const result = [];\n const items = this.getAsArray();\n for (let i = 0; i < items.length; ++i) {\n const item = items[i];\n if (item.pattern && !item.disabled) {\n result.push(item.pattern);\n }\n }\n return result.join('|');\n }\n\n getAsArray(): RegExpSettingItem[] {\n return super.get();\n }\n\n override set(value: string): void {\n this.setAsArray([{pattern: value, disabled: false}]);\n }\n\n setAsArray(value: RegExpSettingItem[]): void {\n this.#regex = undefined;\n super.set(value);\n }\n\n asRegExp(): RegExp|null {\n if (typeof this.#regex !== 'undefined') {\n return this.#regex;\n }\n this.#regex = null;\n try {\n const pattern = this.get();\n if (pattern) {\n this.#regex = new RegExp(pattern, this.#regexFlags || '');\n }\n } catch (e) {\n }\n return this.#regex;\n }\n}\n\nexport class VersionController {\n static readonly GLOBAL_VERSION_SETTING_NAME = 'inspectorVersion';\n static readonly SYNCED_VERSION_SETTING_NAME = 'syncedInspectorVersion';\n static readonly LOCAL_VERSION_SETTING_NAME = 'localInspectorVersion';\n\n static readonly CURRENT_VERSION = 37;\n\n readonly #globalVersionSetting: Setting;\n readonly #syncedVersionSetting: Setting;\n readonly #localVersionSetting: Setting;\n\n constructor() {\n // If no version setting is found, we initialize with the current version and don't do anything.\n this.#globalVersionSetting = Settings.instance().createSetting(\n VersionController.GLOBAL_VERSION_SETTING_NAME, VersionController.CURRENT_VERSION, SettingStorageType.GLOBAL);\n this.#syncedVersionSetting = Settings.instance().createSetting(\n VersionController.SYNCED_VERSION_SETTING_NAME, VersionController.CURRENT_VERSION, SettingStorageType.SYNCED);\n this.#localVersionSetting = Settings.instance().createSetting(\n VersionController.LOCAL_VERSION_SETTING_NAME, VersionController.CURRENT_VERSION, SettingStorageType.LOCAL);\n }\n\n /**\n * Force re-sets all version number settings to the current version without\n * running any migrations.\n */\n resetToCurrent(): void {\n this.#globalVersionSetting.set(VersionController.CURRENT_VERSION);\n this.#syncedVersionSetting.set(VersionController.CURRENT_VERSION);\n this.#localVersionSetting.set(VersionController.CURRENT_VERSION);\n }\n\n /**\n * Runs the appropriate migrations and updates the version settings accordingly.\n *\n * To determine what migrations to run we take the minimum of all version number settings.\n *\n * IMPORTANT: All migrations must be idempotent since they might be applied multiple times.\n */\n updateVersion(): void {\n const currentVersion = VersionController.CURRENT_VERSION;\n const minimumVersion =\n Math.min(this.#globalVersionSetting.get(), this.#syncedVersionSetting.get(), this.#localVersionSetting.get());\n const methodsToRun = this.methodsToRunToUpdateVersion(minimumVersion, currentVersion);\n console.assert(\n // @ts-ignore\n this[`updateVersionFrom${currentVersion}To${currentVersion + 1}`] === undefined,\n 'Unexpected migration method found. Increment CURRENT_VERSION or remove the method.');\n for (const method of methodsToRun) {\n // @ts-ignore Special version method matching\n this[method].call(this);\n }\n this.resetToCurrent();\n }\n\n private methodsToRunToUpdateVersion(oldVersion: number, currentVersion: number): string[] {\n const result = [];\n for (let i = oldVersion; i < currentVersion; ++i) {\n result.push('updateVersionFrom' + i + 'To' + (i + 1));\n }\n return result;\n }\n\n private updateVersionFrom0To1(): void {\n this.clearBreakpointsWhenTooMany(Settings.instance().createLocalSetting('breakpoints', []), 500000);\n }\n\n private updateVersionFrom1To2(): void {\n Settings.instance().createSetting('previouslyViewedFiles', []).set([]);\n }\n\n private updateVersionFrom2To3(): void {\n Settings.instance().createSetting('fileSystemMapping', {}).set({});\n removeSetting(Settings.instance().createSetting('fileMappingEntries', []));\n }\n\n private updateVersionFrom3To4(): void {\n const advancedMode = Settings.instance().createSetting('showHeaSnapshotObjectsHiddenProperties', false);\n moduleSetting('showAdvancedHeapSnapshotProperties').set(advancedMode.get());\n removeSetting(advancedMode);\n }\n\n private updateVersionFrom4To5(): void {\n const settingNames: {\n [x: string]: string,\n } = {\n FileSystemViewSidebarWidth: 'fileSystemViewSplitViewState',\n elementsSidebarWidth: 'elementsPanelSplitViewState',\n StylesPaneSplitRatio: 'stylesPaneSplitViewState',\n heapSnapshotRetainersViewSize: 'heapSnapshotSplitViewState',\n 'InspectorView.splitView': 'InspectorView.splitViewState',\n 'InspectorView.screencastSplitView': 'InspectorView.screencastSplitViewState',\n 'Inspector.drawerSplitView': 'Inspector.drawerSplitViewState',\n layerDetailsSplitView: 'layerDetailsSplitViewState',\n networkSidebarWidth: 'networkPanelSplitViewState',\n sourcesSidebarWidth: 'sourcesPanelSplitViewState',\n scriptsPanelNavigatorSidebarWidth: 'sourcesPanelNavigatorSplitViewState',\n sourcesPanelSplitSidebarRatio: 'sourcesPanelDebuggerSidebarSplitViewState',\n 'timeline-details': 'timelinePanelDetailsSplitViewState',\n 'timeline-split': 'timelinePanelRecorsSplitViewState',\n 'timeline-view': 'timelinePanelTimelineStackSplitViewState',\n auditsSidebarWidth: 'auditsPanelSplitViewState',\n layersSidebarWidth: 'layersPanelSplitViewState',\n profilesSidebarWidth: 'profilesPanelSplitViewState',\n resourcesSidebarWidth: 'resourcesPanelSplitViewState',\n };\n const empty = {};\n for (const oldName in settingNames) {\n const newName = settingNames[oldName];\n const oldNameH = oldName + 'H';\n\n let newValue: {}|null = null;\n const oldSetting = Settings.instance().createSetting(oldName, empty);\n if (oldSetting.get() !== empty) {\n newValue = newValue || {};\n // @ts-expect-error\n newValue.vertical = {};\n // @ts-expect-error\n newValue.vertical.size = oldSetting.get();\n removeSetting(oldSetting);\n }\n const oldSettingH = Settings.instance().createSetting(oldNameH, empty);\n if (oldSettingH.get() !== empty) {\n newValue = newValue || {};\n // @ts-expect-error\n newValue.horizontal = {};\n // @ts-expect-error\n newValue.horizontal.size = oldSettingH.get();\n removeSetting(oldSettingH);\n }\n if (newValue) {\n Settings.instance().createSetting(newName, {}).set(newValue);\n }\n }\n }\n\n private updateVersionFrom5To6(): void {\n const settingNames: {\n [x: string]: string,\n } = {\n debuggerSidebarHidden: 'sourcesPanelSplitViewState',\n navigatorHidden: 'sourcesPanelNavigatorSplitViewState',\n 'WebInspector.Drawer.showOnLoad': 'Inspector.drawerSplitViewState',\n };\n\n for (const oldName in settingNames) {\n const oldSetting = Settings.instance().createSetting(oldName, null);\n if (oldSetting.get() === null) {\n removeSetting(oldSetting);\n continue;\n }\n\n const newName = settingNames[oldName];\n const invert = oldName === 'WebInspector.Drawer.showOnLoad';\n const hidden = oldSetting.get() !== invert;\n removeSetting(oldSetting);\n const showMode = hidden ? 'OnlyMain' : 'Both';\n\n const newSetting = Settings.instance().createSetting(newName, {});\n const newValue = newSetting.get() || {};\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // @ts-expect-error\n newValue.vertical = newValue.vertical || {};\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // @ts-expect-error\n newValue.vertical.showMode = showMode;\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // @ts-expect-error\n newValue.horizontal = newValue.horizontal || {};\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // @ts-expect-error\n newValue.horizontal.showMode = showMode;\n newSetting.set(newValue);\n }\n }\n\n private updateVersionFrom6To7(): void {\n const settingNames = {\n sourcesPanelNavigatorSplitViewState: 'sourcesPanelNavigatorSplitViewState',\n elementsPanelSplitViewState: 'elementsPanelSplitViewState',\n stylesPaneSplitViewState: 'stylesPaneSplitViewState',\n sourcesPanelDebuggerSidebarSplitViewState: 'sourcesPanelDebuggerSidebarSplitViewState',\n };\n\n const empty = {};\n for (const name in settingNames) {\n const setting =\n Settings.instance().createSetting<{vertical?: {size?: number}, horizontal?: {size?: number}}>(name, empty);\n const value = setting.get();\n if (value === empty) {\n continue;\n }\n // Zero out saved percentage sizes, and they will be restored to defaults.\n if (value.vertical && value.vertical.size && value.vertical.size < 1) {\n value.vertical.size = 0;\n }\n if (value.horizontal && value.horizontal.size && value.horizontal.size < 1) {\n value.horizontal.size = 0;\n }\n setting.set(value);\n }\n }\n\n private updateVersionFrom7To8(): void {\n }\n\n private updateVersionFrom8To9(): void {\n const settingNames = ['skipStackFramesPattern', 'workspaceFolderExcludePattern'];\n\n for (let i = 0; i < settingNames.length; ++i) {\n const setting = Settings.instance().createSetting(settingNames[i], '');\n let value = setting.get();\n if (!value) {\n return;\n }\n if (typeof value === 'string') {\n value = [value];\n }\n for (let j = 0; j < value.length; ++j) {\n if (typeof value[j] === 'string') {\n value[j] = {pattern: value[j]};\n }\n }\n setting.set(value);\n }\n }\n\n private updateVersionFrom9To10(): void {\n // This one is localStorage specific, which is fine.\n if (!window.localStorage) {\n return;\n }\n for (const key in window.localStorage) {\n if (key.startsWith('revision-history')) {\n window.localStorage.removeItem(key);\n }\n }\n }\n\n private updateVersionFrom10To11(): void {\n const oldSettingName = 'customDevicePresets';\n const newSettingName = 'customEmulatedDeviceList';\n const oldSetting = Settings.instance().createSetting(oldSettingName, undefined);\n const list = oldSetting.get();\n if (!Array.isArray(list)) {\n return;\n }\n const newList = [];\n for (let i = 0; i < list.length; ++i) {\n const value = list[i];\n const device: {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [x: string]: any,\n } = {};\n device['title'] = value['title'];\n device['type'] = 'unknown';\n device['user-agent'] = value['userAgent'];\n device['capabilities'] = [];\n if (value['touch']) {\n device['capabilities'].push('touch');\n }\n if (value['mobile']) {\n device['capabilities'].push('mobile');\n }\n device['screen'] = {};\n device['screen']['vertical'] = {width: value['width'], height: value['height']};\n device['screen']['horizontal'] = {width: value['height'], height: value['width']};\n device['screen']['device-pixel-ratio'] = value['deviceScaleFactor'];\n device['modes'] = [];\n device['show-by-default'] = true;\n device['show'] = 'Default';\n newList.push(device);\n }\n if (newList.length) {\n Settings.instance().createSetting(newSettingName, []).set(newList);\n }\n removeSetting(oldSetting);\n }\n\n private updateVersionFrom11To12(): void {\n this.migrateSettingsFromLocalStorage();\n }\n\n private updateVersionFrom12To13(): void {\n this.migrateSettingsFromLocalStorage();\n removeSetting(Settings.instance().createSetting('timelineOverviewMode', ''));\n }\n\n private updateVersionFrom13To14(): void {\n const defaultValue = {throughput: -1, latency: 0};\n Settings.instance().createSetting('networkConditions', defaultValue).set(defaultValue);\n }\n\n private updateVersionFrom14To15(): void {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const setting = Settings.instance().createLocalSetting('workspaceExcludedFolders', {});\n const oldValue = setting.get();\n const newValue: {\n [x: string]: string[],\n } = {};\n for (const fileSystemPath in oldValue) {\n newValue[fileSystemPath] = [];\n for (const entry of oldValue[fileSystemPath]) {\n newValue[fileSystemPath].push(entry.path);\n }\n }\n setting.set(newValue);\n }\n\n private updateVersionFrom15To16(): void {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const setting = Settings.instance().createSetting('InspectorView.panelOrder', {});\n const tabOrders = setting.get();\n for (const key of Object.keys(tabOrders)) {\n tabOrders[key] = (tabOrders[key] + 1) * 10;\n }\n setting.set(tabOrders);\n }\n\n private updateVersionFrom16To17(): void {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const setting = Settings.instance().createSetting('networkConditionsCustomProfiles', []);\n const oldValue = setting.get();\n const newValue = [];\n if (Array.isArray(oldValue)) {\n for (const preset of oldValue) {\n if (typeof preset.title === 'string' && typeof preset.value === 'object' &&\n typeof preset.value.throughput === 'number' && typeof preset.value.latency === 'number') {\n newValue.push({\n title: preset.title,\n value: {download: preset.value.throughput, upload: preset.value.throughput, latency: preset.value.latency},\n });\n }\n }\n }\n setting.set(newValue);\n }\n\n private updateVersionFrom17To18(): void {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const setting = Settings.instance().createLocalSetting('workspaceExcludedFolders', {});\n const oldValue = setting.get();\n const newValue: {\n [x: string]: string,\n } = {};\n for (const oldKey in oldValue) {\n let newKey = oldKey.replace(/\\\\/g, '/');\n if (!newKey.startsWith('file://')) {\n if (newKey.startsWith('/')) {\n newKey = 'file://' + newKey;\n } else {\n newKey = 'file:///' + newKey;\n }\n }\n newValue[newKey] = oldValue[oldKey];\n }\n setting.set(newValue);\n }\n\n private updateVersionFrom18To19(): void {\n const defaultColumns = {status: true, type: true, initiator: true, size: true, time: true};\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const visibleColumnSettings = Settings.instance().createSetting('networkLogColumnsVisibility', defaultColumns);\n const visibleColumns = visibleColumnSettings.get();\n visibleColumns.name = true;\n visibleColumns.timeline = true;\n\n const configs: {\n [x: string]: {\n visible: number,\n },\n } = {};\n for (const columnId in visibleColumns) {\n if (!visibleColumns.hasOwnProperty(columnId)) {\n continue;\n }\n configs[columnId.toLowerCase()] = {visible: visibleColumns[columnId]};\n }\n const newSetting = Settings.instance().createSetting('networkLogColumns', {});\n newSetting.set(configs);\n removeSetting(visibleColumnSettings);\n }\n\n private updateVersionFrom19To20(): void {\n const oldSetting = Settings.instance().createSetting('InspectorView.panelOrder', {});\n const newSetting = Settings.instance().createSetting('panel-tabOrder', {});\n newSetting.set(oldSetting.get());\n removeSetting(oldSetting);\n }\n\n private updateVersionFrom20To21(): void {\n const networkColumns = Settings.instance().createSetting('networkLogColumns', {});\n const columns = (networkColumns.get() as {\n [x: string]: string,\n });\n delete columns['timeline'];\n delete columns['waterfall'];\n networkColumns.set(columns);\n }\n\n private updateVersionFrom21To22(): void {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const breakpointsSetting = Settings.instance().createLocalSetting('breakpoints', []);\n const breakpoints = breakpointsSetting.get();\n for (const breakpoint of breakpoints) {\n breakpoint['url'] = breakpoint['sourceFileId'];\n delete breakpoint['sourceFileId'];\n }\n breakpointsSetting.set(breakpoints);\n }\n\n private updateVersionFrom22To23(): void {\n // This update is no-op.\n }\n\n private updateVersionFrom23To24(): void {\n const oldSetting = Settings.instance().createSetting('searchInContentScripts', false);\n const newSetting = Settings.instance().createSetting('searchInAnonymousAndContentScripts', false);\n newSetting.set(oldSetting.get());\n removeSetting(oldSetting);\n }\n\n private updateVersionFrom24To25(): void {\n const defaultColumns = {status: true, type: true, initiator: true, size: true, time: true};\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const networkLogColumnsSetting = Settings.instance().createSetting('networkLogColumns', defaultColumns);\n const columns = networkLogColumnsSetting.get();\n delete columns.product;\n networkLogColumnsSetting.set(columns);\n }\n\n private updateVersionFrom25To26(): void {\n const oldSetting = Settings.instance().createSetting('messageURLFilters', {});\n const urls = Object.keys(oldSetting.get());\n const textFilter = urls.map(url => `-url:${url}`).join(' ');\n if (textFilter) {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const textFilterSetting = Settings.instance().createSetting('console.textFilter', '');\n const suffix = textFilterSetting.get() ? ` ${textFilterSetting.get()}` : '';\n textFilterSetting.set(`${textFilter}${suffix}`);\n }\n removeSetting(oldSetting);\n }\n\n private updateVersionFrom26To27(): void {\n function renameKeyInObjectSetting(settingName: string, from: string, to: string): void {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const setting = Settings.instance().createSetting(settingName, {});\n const value = setting.get();\n if (from in value) {\n value[to] = value[from];\n delete value[from];\n setting.set(value);\n }\n }\n\n function renameInStringSetting(settingName: string, from: string, to: string): void {\n const setting = Settings.instance().createSetting(settingName, '');\n const value = setting.get();\n if (value === from) {\n setting.set(to);\n }\n }\n\n renameKeyInObjectSetting('panel-tabOrder', 'audits2', 'audits');\n renameKeyInObjectSetting('panel-closeableTabs', 'audits2', 'audits');\n renameInStringSetting('panel-selectedTab', 'audits2', 'audits');\n }\n\n private updateVersionFrom27To28(): void {\n const setting = Settings.instance().createSetting('uiTheme', 'systemPreferred');\n if (setting.get() === 'default') {\n setting.set('systemPreferred');\n }\n }\n\n private updateVersionFrom28To29(): void {\n function renameKeyInObjectSetting(settingName: string, from: string, to: string): void {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const setting = Settings.instance().createSetting(settingName, {});\n const value = setting.get();\n if (from in value) {\n value[to] = value[from];\n delete value[from];\n setting.set(value);\n }\n }\n\n function renameInStringSetting(settingName: string, from: string, to: string): void {\n const setting = Settings.instance().createSetting(settingName, '');\n const value = setting.get();\n if (value === from) {\n setting.set(to);\n }\n }\n\n renameKeyInObjectSetting('panel-tabOrder', 'audits', 'lighthouse');\n renameKeyInObjectSetting('panel-closeableTabs', 'audits', 'lighthouse');\n renameInStringSetting('panel-selectedTab', 'audits', 'lighthouse');\n }\n\n private updateVersionFrom29To30(): void {\n // Create new location agnostic setting\n const closeableTabSetting = Settings.instance().createSetting('closeableTabs', {});\n\n // Read current settings\n const panelCloseableTabSetting = Settings.instance().createSetting('panel-closeableTabs', {});\n const drawerCloseableTabSetting = Settings.instance().createSetting('drawer-view-closeableTabs', {});\n const openTabsInPanel = panelCloseableTabSetting.get();\n const openTabsInDrawer = panelCloseableTabSetting.get();\n\n // Set #value of new setting\n const newValue = Object.assign(openTabsInDrawer, openTabsInPanel);\n closeableTabSetting.set(newValue);\n\n // Remove old settings\n removeSetting(panelCloseableTabSetting);\n removeSetting(drawerCloseableTabSetting);\n }\n\n private updateVersionFrom30To31(): void {\n // Remove recorder_recordings setting that was used for storing recordings\n // by an old recorder experiment.\n const recordingsSetting = Settings.instance().createSetting('recorder_recordings', []);\n removeSetting(recordingsSetting);\n }\n\n updateVersionFrom31To32(): void {\n // Introduce the new 'resourceTypeName' property on stored breakpoints. Prior to\n // this change we synchronized the breakpoint only by URL, but since we don't\n // know on which resource type the given breakpoint was set, we just assume\n // 'script' here to keep things simple.\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const breakpointsSetting = Settings.instance().createLocalSetting('breakpoints', []);\n const breakpoints = breakpointsSetting.get();\n for (const breakpoint of breakpoints) {\n breakpoint['resourceTypeName'] = 'script';\n }\n breakpointsSetting.set(breakpoints);\n }\n\n updateVersionFrom32To33(): void {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const previouslyViewedFilesSetting = Settings.instance().createLocalSetting('previouslyViewedFiles', []);\n let previouslyViewedFiles = previouslyViewedFilesSetting.get();\n\n // Discard old 'previouslyViewedFiles' items that don't have a 'url' property.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n previouslyViewedFiles = previouslyViewedFiles.filter((previouslyViewedFile: any) => 'url' in previouslyViewedFile);\n\n // Introduce the new 'resourceTypeName' property on previously viewed files.\n // Prior to this change we only keyed them based on the URL, but since we\n // don't know which resource type the given file had, we just assume 'script'\n // here to keep things simple.\n for (const previouslyViewedFile of previouslyViewedFiles) {\n previouslyViewedFile['resourceTypeName'] = 'script';\n }\n\n previouslyViewedFilesSetting.set(previouslyViewedFiles);\n }\n\n updateVersionFrom33To34(): void {\n // Introduces the 'isLogpoint' property on stored breakpoints. This information was\n // previously encoded in the 'condition' itself. This migration leaves the condition\n // alone but ensures that 'isLogpoint' is accurate for already stored breakpoints.\n // This enables us to use the 'isLogpoint' property in code.\n // A separate migration will remove the special encoding from the condition itself\n // once all refactorings are done.\n\n // The prefix/suffix are hardcoded here, since these constants will be removed in\n // the future.\n const logpointPrefix = '/** DEVTOOLS_LOGPOINT */ console.log(';\n const logpointSuffix = ')';\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const breakpointsSetting = Settings.instance().createLocalSetting('breakpoints', []);\n const breakpoints = breakpointsSetting.get();\n for (const breakpoint of breakpoints) {\n const isLogpoint =\n breakpoint.condition.startsWith(logpointPrefix) && breakpoint.condition.endsWith(logpointSuffix);\n breakpoint['isLogpoint'] = isLogpoint;\n }\n breakpointsSetting.set(breakpoints);\n }\n\n updateVersionFrom34To35(): void {\n // Uses the 'isLogpoint' property on stored breakpoints to remove the prefix/suffix\n // from logpoints. This way, we store the entered log point condition as the user\n // entered it.\n\n // The prefix/suffix are hardcoded here, since these constants will be removed in\n // the future.\n const logpointPrefix = '/** DEVTOOLS_LOGPOINT */ console.log(';\n const logpointSuffix = ')';\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const breakpointsSetting = Settings.instance().createLocalSetting('breakpoints', []);\n const breakpoints = breakpointsSetting.get();\n for (const breakpoint of breakpoints) {\n const {condition, isLogpoint} = breakpoint;\n if (isLogpoint) {\n breakpoint.condition = condition.slice(logpointPrefix.length, condition.length - logpointSuffix.length);\n }\n }\n breakpointsSetting.set(breakpoints);\n }\n\n updateVersionFrom35To36(): void {\n // We have changed the default from 'false' to 'true' and this updates the existing setting just for once.\n Settings.instance().createSetting('showThirdPartyIssues', true).set(true);\n }\n\n updateVersionFrom36To37(): void {\n const updateStorage = (storage: SettingsStorage): void => {\n for (const key of storage.keys()) {\n const normalizedKey = Settings.normalizeSettingName(key);\n if (normalizedKey !== key) {\n const value = storage.get(key);\n removeSetting({name: key, storage});\n storage.set(normalizedKey, value);\n }\n }\n };\n updateStorage(Settings.instance().globalStorage);\n updateStorage(Settings.instance().syncedStorage);\n updateStorage(Settings.instance().localStorage);\n\n for (const key of Settings.instance().globalStorage.keys()) {\n if ((key.startsWith('data-grid-') && key.endsWith('-column-weights')) || key.endsWith('-tab-order') ||\n key === 'views-location-override' || key === 'closeable-tabs') {\n const setting = Settings.instance().createSetting(key, {});\n setting.set(Platform.StringUtilities.toKebabCaseKeys(setting.get()));\n }\n if (key.endsWith('-selected-tab')) {\n const setting = Settings.instance().createSetting(key, '');\n setting.set(Platform.StringUtilities.toKebabCase(setting.get()));\n }\n }\n }\n\n /*\n * Any new migration should be added before this comment.\n *\n * IMPORTANT: Migrations must be idempotent, since they may be applied\n * multiple times! E.g. when renaming a setting one has to check that the\n * a setting with the new name does not yet exist.\n * ----------------------------------------------------------------------- */\n\n private migrateSettingsFromLocalStorage(): void {\n // This step migrates all the settings except for the ones below into the browser profile.\n const localSettings = new Set([\n 'advancedSearchConfig',\n 'breakpoints',\n 'consoleHistory',\n 'domBreakpoints',\n 'eventListenerBreakpoints',\n 'fileSystemMapping',\n 'lastSelectedSourcesSidebarPaneTab',\n 'previouslyViewedFiles',\n 'savedURLs',\n 'watchExpressions',\n 'workspaceExcludedFolders',\n 'xhrBreakpoints',\n ]);\n if (!window.localStorage) {\n return;\n }\n\n for (const key in window.localStorage) {\n if (localSettings.has(key)) {\n continue;\n }\n const value = window.localStorage[key];\n window.localStorage.removeItem(key);\n Settings.instance().globalStorage.set(key, value);\n }\n }\n\n private clearBreakpointsWhenTooMany(breakpointsSetting: Setting, maxBreakpointsCount: number): void {\n // If there are too many breakpoints in a storage, it is likely due to a recent bug that caused\n // periodical breakpoints duplication leading to inspector slowness.\n if (breakpointsSetting.get().length > maxBreakpointsCount) {\n breakpointsSetting.set([]);\n }\n }\n}\n\nexport const enum SettingStorageType {\n /**\n * Synced storage persists settings with the active Chrome profile but also\n * syncs the settings across devices via Chrome Sync.\n */\n SYNCED = 'Synced',\n /** Global storage persists settings with the active Chrome profile */\n GLOBAL = 'Global',\n /** Uses Window.localStorage */\n LOCAL = 'Local',\n /** Session storage dies when DevTools window closes */\n SESSION = 'Session',\n}\n\nexport function moduleSetting(settingName: string): Setting {\n return Settings.instance().moduleSetting(settingName);\n}\n\nexport function settingForTest(settingName: string): Setting {\n return Settings.instance().settingForTest(settingName);\n}\n\nexport {\n getLocalizedSettingsCategory,\n maybeRemoveSettingExtension,\n registerSettingExtension,\n RegExpSettingItem,\n SettingCategory,\n SettingExtensionOption,\n SettingRegistration,\n SettingType,\n registerSettingsForTest,\n resetSettings,\n};\n\nexport interface Serializer {\n stringify: (value: I) => string;\n parse: (value: string) => O;\n}\n\nexport interface SimpleSettingOption {\n value: string|boolean;\n title: string;\n text?: string;\n raw?: boolean;\n}\n"]} \ No newline at end of file +{"version":3,"file":"Settings.js","sourceRoot":"","sources":["../../../../../../front_end/core/common/Settings.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (C) 2009 Google Inc. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * * Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above\n * copyright notice, this list of conditions and the following disclaimer\n * in the documentation and/or other materials provided with the\n * distribution.\n * * Neither the name of Google Inc. nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport * as Platform from '../platform/platform.js';\nimport * as Root from '../root/root.js';\n\nimport {Console} from './Console.js';\nimport {type EventDescriptor, type EventTargetEvent, type GenericEvents} from './EventTarget.js';\nimport {ObjectWrapper} from './Object.js';\nimport {\n getLocalizedSettingsCategory,\n getRegisteredSettings as getRegisteredSettingsInternal,\n type LearnMore,\n maybeRemoveSettingExtension,\n type RegExpSettingItem,\n registerSettingExtension,\n registerSettingsForTest,\n resetSettings,\n SettingCategory,\n type SettingExtensionOption,\n type SettingRegistration,\n SettingType,\n} from './SettingRegistration.js';\n\nlet settingsInstance: Settings|undefined;\n\nexport class Settings {\n readonly #sessionStorage: SettingsStorage;\n settingNameSet: Set;\n orderValuesBySettingCategory: Map>;\n #eventSupport: ObjectWrapper;\n #registry: Map>;\n readonly moduleSettings: Map>;\n readonly #config: Root.Runtime.HostConfig;\n\n private constructor(\n readonly syncedStorage: SettingsStorage, readonly globalStorage: SettingsStorage,\n readonly localStorage: SettingsStorage, config?: Root.Runtime.HostConfig) {\n this.#sessionStorage = new SettingsStorage({});\n\n this.settingNameSet = new Set();\n\n this.orderValuesBySettingCategory = new Map();\n\n this.#eventSupport = new ObjectWrapper();\n this.#registry = new Map();\n this.moduleSettings = new Map();\n\n this.#config = config || {};\n for (const registration of this.getRegisteredSettings()) {\n const {settingName, defaultValue, storageType} = registration;\n const isRegex = registration.settingType === SettingType.REGEX;\n\n const evaluatedDefaultValue = typeof defaultValue === 'function' ? defaultValue(this.#config) : defaultValue;\n const setting = isRegex && typeof evaluatedDefaultValue === 'string' ?\n this.createRegExpSetting(settingName, evaluatedDefaultValue, undefined, storageType) :\n this.createSetting(settingName, evaluatedDefaultValue, storageType);\n\n setting.setTitleFunction(registration.title);\n if (registration.userActionCondition) {\n setting.setRequiresUserAction(Boolean(Root.Runtime.Runtime.queryParam(registration.userActionCondition)));\n }\n setting.setRegistration(registration);\n\n this.registerModuleSetting(setting);\n }\n }\n\n getRegisteredSettings(): SettingRegistration[] {\n return getRegisteredSettingsInternal(this.#config);\n }\n\n static hasInstance(): boolean {\n return typeof settingsInstance !== 'undefined';\n }\n\n static instance(opts: {\n forceNew: boolean|null,\n syncedStorage: SettingsStorage|null,\n globalStorage: SettingsStorage|null,\n localStorage: SettingsStorage|null,\n config?: Root.Runtime.HostConfig,\n } = {forceNew: null, syncedStorage: null, globalStorage: null, localStorage: null}): Settings {\n const {forceNew, syncedStorage, globalStorage, localStorage, config} = opts;\n if (!settingsInstance || forceNew) {\n if (!syncedStorage || !globalStorage || !localStorage) {\n throw new Error(`Unable to create settings: global and local storage must be provided: ${new Error().stack}`);\n }\n\n settingsInstance = new Settings(syncedStorage, globalStorage, localStorage, config);\n }\n\n return settingsInstance;\n }\n\n static removeInstance(): void {\n settingsInstance = undefined;\n }\n\n getHostConfig(): Root.Runtime.HostConfig {\n return this.#config;\n }\n\n private registerModuleSetting(setting: Setting): void {\n const settingName = setting.name;\n const category = setting.category();\n const order = setting.order();\n if (this.settingNameSet.has(settingName)) {\n throw new Error(`Duplicate Setting name '${settingName}'`);\n }\n if (category && order) {\n const orderValues = this.orderValuesBySettingCategory.get(category) || new Set();\n if (orderValues.has(order)) {\n throw new Error(`Duplicate order value '${order}' for settings category '${category}'`);\n }\n orderValues.add(order);\n this.orderValuesBySettingCategory.set(category, orderValues);\n }\n this.settingNameSet.add(settingName);\n this.moduleSettings.set(setting.name, setting);\n }\n\n static normalizeSettingName(name: string): string {\n if ([\n VersionController.GLOBAL_VERSION_SETTING_NAME,\n VersionController.SYNCED_VERSION_SETTING_NAME,\n VersionController.LOCAL_VERSION_SETTING_NAME,\n 'currentDockState',\n 'isUnderTest',\n ].includes(name)) {\n return name;\n }\n return Platform.StringUtilities.toKebabCase(name);\n }\n\n /**\n * Prefer a module setting if this setting is one that you might not want to\n * surface to the user to control themselves. Examples of these are settings\n * to store UI state such as how a user choses to position a split widget or\n * which panel they last opened.\n * If you are creating a setting that you expect the user to control, and\n * sync, prefer {@see createSetting}\n */\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n moduleSetting(settingName: string): Setting {\n const setting = this.moduleSettings.get(settingName) as Setting;\n if (!setting) {\n throw new Error('No setting registered: ' + settingName);\n }\n return setting;\n }\n\n settingForTest(settingName: string): Setting {\n const setting = this.#registry.get(settingName);\n if (!setting) {\n throw new Error('No setting registered: ' + settingName);\n }\n return setting;\n }\n\n /**\n * Get setting via key, and create a new setting if the requested setting does not exist.\n */\n createSetting(key: string, defaultValue: T, storageType?: SettingStorageType): Setting {\n const storage = this.storageFromType(storageType);\n let setting = (this.#registry.get(key) as Setting);\n if (!setting) {\n setting = new Setting(key, defaultValue, this.#eventSupport, storage);\n this.#registry.set(key, setting);\n }\n return setting;\n }\n\n createLocalSetting(key: string, defaultValue: T): Setting {\n return this.createSetting(key, defaultValue, SettingStorageType.LOCAL);\n }\n\n createRegExpSetting(key: string, defaultValue: string, regexFlags?: string, storageType?: SettingStorageType):\n RegExpSetting {\n if (!this.#registry.get(key)) {\n this.#registry.set(\n key, new RegExpSetting(key, defaultValue, this.#eventSupport, this.storageFromType(storageType), regexFlags));\n }\n return this.#registry.get(key) as RegExpSetting;\n }\n\n clearAll(): void {\n this.globalStorage.removeAll();\n this.syncedStorage.removeAll();\n this.localStorage.removeAll();\n new VersionController().resetToCurrent();\n }\n\n private storageFromType(storageType?: SettingStorageType): SettingsStorage {\n switch (storageType) {\n case SettingStorageType.LOCAL:\n return this.localStorage;\n case SettingStorageType.SESSION:\n return this.#sessionStorage;\n case SettingStorageType.GLOBAL:\n return this.globalStorage;\n case SettingStorageType.SYNCED:\n return this.syncedStorage;\n }\n return this.globalStorage;\n }\n\n getRegistry(): Map> {\n return this.#registry;\n }\n}\n\nexport interface SettingsBackingStore {\n register(setting: string): void;\n get(setting: string): Promise;\n set(setting: string, value: string): void;\n remove(setting: string): void;\n clear(): void;\n}\n\nexport const NOOP_STORAGE: SettingsBackingStore = {\n register: () => {},\n set: () => {},\n get: () => Promise.resolve(''),\n remove: () => {},\n clear: () => {},\n};\n\nexport class SettingsStorage {\n constructor(\n private object: Record, private readonly backingStore: SettingsBackingStore = NOOP_STORAGE,\n private readonly storagePrefix: string = '') {\n }\n\n register(name: string): void {\n name = this.storagePrefix + name;\n this.backingStore.register(name);\n }\n\n set(name: string, value: string): void {\n name = this.storagePrefix + name;\n this.object[name] = value;\n this.backingStore.set(name, value);\n }\n\n has(name: string): boolean {\n name = this.storagePrefix + name;\n return name in this.object;\n }\n\n get(name: string): string {\n name = this.storagePrefix + name;\n return this.object[name];\n }\n\n async forceGet(originalName: string): Promise {\n const name = this.storagePrefix + originalName;\n const value = await this.backingStore.get(name);\n if (value && value !== this.object[name]) {\n this.set(originalName, value);\n } else if (!value) {\n this.remove(originalName);\n }\n return value;\n }\n\n remove(name: string): void {\n name = this.storagePrefix + name;\n delete this.object[name];\n this.backingStore.remove(name);\n }\n\n removeAll(): void {\n this.object = {};\n this.backingStore.clear();\n }\n\n keys(): string[] {\n return Object.keys(this.object);\n }\n\n dumpSizes(): void {\n Console.instance().log('Ten largest settings: ');\n\n const sizes: {\n [x: string]: number,\n // @ts-expect-error __proto__ optimization\n } = {__proto__: null};\n for (const key in this.object) {\n sizes[key] = this.object[key].length;\n }\n const keys = Object.keys(sizes);\n\n function comparator(key1: string, key2: string): number {\n return sizes[key2] - sizes[key1];\n }\n\n keys.sort(comparator);\n\n for (let i = 0; i < 10 && i < keys.length; ++i) {\n Console.instance().log('Setting: \\'' + keys[i] + '\\', size: ' + sizes[keys[i]]);\n }\n }\n}\n\nfunction removeSetting(setting: {name: string, storage: SettingsStorage}): void {\n const name = setting.name;\n const settings = Settings.instance();\n\n settings.getRegistry().delete(name);\n settings.moduleSettings.delete(name);\n\n setting.storage.remove(name);\n}\n\nexport class Deprecation {\n readonly disabled: boolean;\n readonly warning: Platform.UIString.LocalizedString;\n readonly experiment?: Root.Runtime.Experiment;\n\n constructor({deprecationNotice}: SettingRegistration) {\n if (!deprecationNotice) {\n throw new Error('Cannot create deprecation info for a non-deprecated setting');\n }\n this.disabled = deprecationNotice.disabled;\n this.warning = deprecationNotice.warning();\n this.experiment = deprecationNotice.experiment ?\n Root.Runtime.experiments.allConfigurableExperiments().find(e => e.name === deprecationNotice.experiment) :\n undefined;\n }\n}\n\nexport class Setting {\n #titleFunction?: () => Platform.UIString.LocalizedString;\n #titleInternal!: string;\n #registration: SettingRegistration|null = null;\n #requiresUserAction?: boolean;\n #value?: V;\n // TODO(crbug.com/1172300) Type cannot be inferred without changes to consumers. See above.\n #serializer: Serializer = JSON;\n #hadUserAction?: boolean;\n #disabled?: boolean;\n #deprecation: Deprecation|null = null;\n\n constructor(\n readonly name: string, readonly defaultValue: V, private readonly eventSupport: ObjectWrapper,\n readonly storage: SettingsStorage) {\n storage.register(this.name);\n }\n\n setSerializer(serializer: Serializer): void {\n this.#serializer = serializer;\n }\n\n addChangeListener(listener: (arg0: EventTargetEvent) => void, thisObject?: Object): EventDescriptor {\n return this.eventSupport.addEventListener(this.name, listener, thisObject);\n }\n\n removeChangeListener(listener: (arg0: EventTargetEvent) => void, thisObject?: Object): void {\n this.eventSupport.removeEventListener(this.name, listener, thisObject);\n }\n\n title(): string {\n if (this.#titleInternal) {\n return this.#titleInternal;\n }\n if (this.#titleFunction) {\n return this.#titleFunction();\n }\n return '';\n }\n\n setTitleFunction(titleFunction: (() => Platform.UIString.LocalizedString)|undefined): void {\n if (titleFunction) {\n this.#titleFunction = titleFunction;\n }\n }\n\n setTitle(title: string): void {\n this.#titleInternal = title;\n }\n\n setRequiresUserAction(requiresUserAction: boolean): void {\n this.#requiresUserAction = requiresUserAction;\n }\n\n disabled(): boolean {\n if (this.#registration?.disabledCondition) {\n const {disabled} = this.#registration.disabledCondition(Settings.instance().getHostConfig());\n // If registration does not disable it, pass through to #disabled\n // attribute check.\n if (disabled) {\n return true;\n }\n }\n return this.#disabled || false;\n }\n\n disabledReason(): string|undefined {\n if (this.#registration?.disabledCondition) {\n const result = this.#registration.disabledCondition(Settings.instance().getHostConfig());\n if (result.disabled) {\n return result.reason;\n }\n }\n return undefined;\n }\n\n setDisabled(disabled: boolean): void {\n this.#disabled = disabled;\n this.eventSupport.dispatchEventToListeners(this.name);\n }\n\n get(): V {\n if (this.#requiresUserAction && !this.#hadUserAction) {\n return this.defaultValue;\n }\n\n if (typeof this.#value !== 'undefined') {\n return this.#value;\n }\n\n this.#value = this.defaultValue;\n if (this.storage.has(this.name)) {\n try {\n this.#value = this.#serializer.parse(this.storage.get(this.name));\n } catch (e) {\n this.storage.remove(this.name);\n }\n }\n return this.#value;\n }\n\n // Prefer this getter for settings which are \"disableable\". The plain getter returns `this.#value`,\n // even if the setting is disabled, which means the callsite has to explicitly call the `disabled()`\n // getter and add its own logic for the disabled state.\n getIfNotDisabled(): V|undefined {\n if (this.disabled()) {\n return;\n }\n return this.get();\n }\n\n async forceGet(): Promise {\n const name = this.name;\n const oldValue = this.storage.get(name);\n const value = await this.storage.forceGet(name);\n this.#value = this.defaultValue;\n if (value) {\n try {\n this.#value = this.#serializer.parse(value);\n } catch (e) {\n this.storage.remove(this.name);\n }\n }\n\n if (oldValue !== value) {\n this.eventSupport.dispatchEventToListeners(this.name, this.#value);\n }\n\n return this.#value;\n }\n\n set(value: V): void {\n this.#hadUserAction = true;\n this.#value = value;\n try {\n const settingString = this.#serializer.stringify(value);\n try {\n this.storage.set(this.name, settingString);\n } catch (e) {\n this.printSettingsSavingError(e.message, this.name, settingString);\n }\n } catch (e) {\n Console.instance().error('Cannot stringify setting with name: ' + this.name + ', error: ' + e.message);\n }\n this.eventSupport.dispatchEventToListeners(this.name, value);\n }\n\n setRegistration(registration: SettingRegistration): void {\n this.#registration = registration;\n const {deprecationNotice} = registration;\n if (deprecationNotice?.disabled) {\n const experiment = deprecationNotice.experiment ?\n Root.Runtime.experiments.allConfigurableExperiments().find(e => e.name === deprecationNotice.experiment) :\n undefined;\n if ((!experiment || experiment.isEnabled())) {\n this.set(this.defaultValue);\n this.setDisabled(true);\n }\n }\n }\n\n type(): SettingType|null {\n if (this.#registration) {\n return this.#registration.settingType;\n }\n return null;\n }\n\n options(): SimpleSettingOption[] {\n if (this.#registration && this.#registration.options) {\n return this.#registration.options.map(opt => {\n const {value, title, text, raw} = opt;\n return {\n value,\n title: title(),\n text: typeof text === 'function' ? text() : text,\n raw,\n };\n });\n }\n return [];\n }\n\n reloadRequired(): boolean|null {\n if (this.#registration) {\n return this.#registration.reloadRequired || null;\n }\n return null;\n }\n\n category(): SettingCategory|null {\n if (this.#registration) {\n return this.#registration.category || null;\n }\n return null;\n }\n\n tags(): string|null {\n if (this.#registration && this.#registration.tags) {\n // Get localized keys and separate by null character to prevent fuzzy matching from matching across them.\n return this.#registration.tags.map(tag => tag()).join('\\0');\n }\n return null;\n }\n\n order(): number|null {\n if (this.#registration) {\n return this.#registration.order || null;\n }\n return null;\n }\n\n learnMore(): LearnMore|null {\n return this.#registration?.learnMore ?? null;\n }\n\n get deprecation(): Deprecation|null {\n if (!this.#registration || !this.#registration.deprecationNotice) {\n return null;\n }\n if (!this.#deprecation) {\n this.#deprecation = new Deprecation(this.#registration);\n }\n return this.#deprecation;\n }\n\n private printSettingsSavingError(message: string, name: string, value: string): void {\n const errorMessage =\n 'Error saving setting with name: ' + this.name + ', value length: ' + value.length + '. Error: ' + message;\n console.error(errorMessage);\n Console.instance().error(errorMessage);\n this.storage.dumpSizes();\n }\n}\n\n// TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport class RegExpSetting extends Setting {\n #regexFlags: string|undefined;\n #regex?: RegExp|null;\n\n constructor(\n name: string, defaultValue: string, eventSupport: ObjectWrapper, storage: SettingsStorage,\n regexFlags?: string) {\n super(name, defaultValue ? [{pattern: defaultValue}] : [], eventSupport, storage);\n this.#regexFlags = regexFlags;\n }\n\n override get(): string {\n const result = [];\n const items = this.getAsArray();\n for (let i = 0; i < items.length; ++i) {\n const item = items[i];\n if (item.pattern && !item.disabled) {\n result.push(item.pattern);\n }\n }\n return result.join('|');\n }\n\n getAsArray(): RegExpSettingItem[] {\n return super.get();\n }\n\n override set(value: string): void {\n this.setAsArray([{pattern: value, disabled: false}]);\n }\n\n setAsArray(value: RegExpSettingItem[]): void {\n this.#regex = undefined;\n super.set(value);\n }\n\n asRegExp(): RegExp|null {\n if (typeof this.#regex !== 'undefined') {\n return this.#regex;\n }\n this.#regex = null;\n try {\n const pattern = this.get();\n if (pattern) {\n this.#regex = new RegExp(pattern, this.#regexFlags || '');\n }\n } catch (e) {\n }\n return this.#regex;\n }\n}\n\nexport class VersionController {\n static readonly GLOBAL_VERSION_SETTING_NAME = 'inspectorVersion';\n static readonly SYNCED_VERSION_SETTING_NAME = 'syncedInspectorVersion';\n static readonly LOCAL_VERSION_SETTING_NAME = 'localInspectorVersion';\n\n static readonly CURRENT_VERSION = 38;\n\n readonly #globalVersionSetting: Setting;\n readonly #syncedVersionSetting: Setting;\n readonly #localVersionSetting: Setting;\n\n constructor() {\n // If no version setting is found, we initialize with the current version and don't do anything.\n this.#globalVersionSetting = Settings.instance().createSetting(\n VersionController.GLOBAL_VERSION_SETTING_NAME, VersionController.CURRENT_VERSION, SettingStorageType.GLOBAL);\n this.#syncedVersionSetting = Settings.instance().createSetting(\n VersionController.SYNCED_VERSION_SETTING_NAME, VersionController.CURRENT_VERSION, SettingStorageType.SYNCED);\n this.#localVersionSetting = Settings.instance().createSetting(\n VersionController.LOCAL_VERSION_SETTING_NAME, VersionController.CURRENT_VERSION, SettingStorageType.LOCAL);\n }\n\n /**\n * Force re-sets all version number settings to the current version without\n * running any migrations.\n */\n resetToCurrent(): void {\n this.#globalVersionSetting.set(VersionController.CURRENT_VERSION);\n this.#syncedVersionSetting.set(VersionController.CURRENT_VERSION);\n this.#localVersionSetting.set(VersionController.CURRENT_VERSION);\n }\n\n /**\n * Runs the appropriate migrations and updates the version settings accordingly.\n *\n * To determine what migrations to run we take the minimum of all version number settings.\n *\n * IMPORTANT: All migrations must be idempotent since they might be applied multiple times.\n */\n updateVersion(): void {\n const currentVersion = VersionController.CURRENT_VERSION;\n const minimumVersion =\n Math.min(this.#globalVersionSetting.get(), this.#syncedVersionSetting.get(), this.#localVersionSetting.get());\n const methodsToRun = this.methodsToRunToUpdateVersion(minimumVersion, currentVersion);\n console.assert(\n // @ts-ignore\n this[`updateVersionFrom${currentVersion}To${currentVersion + 1}`] === undefined,\n 'Unexpected migration method found. Increment CURRENT_VERSION or remove the method.');\n for (const method of methodsToRun) {\n // @ts-ignore Special version method matching\n this[method].call(this);\n }\n this.resetToCurrent();\n }\n\n private methodsToRunToUpdateVersion(oldVersion: number, currentVersion: number): string[] {\n const result = [];\n for (let i = oldVersion; i < currentVersion; ++i) {\n result.push('updateVersionFrom' + i + 'To' + (i + 1));\n }\n return result;\n }\n\n private updateVersionFrom0To1(): void {\n this.clearBreakpointsWhenTooMany(Settings.instance().createLocalSetting('breakpoints', []), 500000);\n }\n\n private updateVersionFrom1To2(): void {\n Settings.instance().createSetting('previouslyViewedFiles', []).set([]);\n }\n\n private updateVersionFrom2To3(): void {\n Settings.instance().createSetting('fileSystemMapping', {}).set({});\n removeSetting(Settings.instance().createSetting('fileMappingEntries', []));\n }\n\n private updateVersionFrom3To4(): void {\n const advancedMode = Settings.instance().createSetting('showHeaSnapshotObjectsHiddenProperties', false);\n moduleSetting('showAdvancedHeapSnapshotProperties').set(advancedMode.get());\n removeSetting(advancedMode);\n }\n\n private updateVersionFrom4To5(): void {\n const settingNames: {\n [x: string]: string,\n } = {\n FileSystemViewSidebarWidth: 'fileSystemViewSplitViewState',\n elementsSidebarWidth: 'elementsPanelSplitViewState',\n StylesPaneSplitRatio: 'stylesPaneSplitViewState',\n heapSnapshotRetainersViewSize: 'heapSnapshotSplitViewState',\n 'InspectorView.splitView': 'InspectorView.splitViewState',\n 'InspectorView.screencastSplitView': 'InspectorView.screencastSplitViewState',\n 'Inspector.drawerSplitView': 'Inspector.drawerSplitViewState',\n layerDetailsSplitView: 'layerDetailsSplitViewState',\n networkSidebarWidth: 'networkPanelSplitViewState',\n sourcesSidebarWidth: 'sourcesPanelSplitViewState',\n scriptsPanelNavigatorSidebarWidth: 'sourcesPanelNavigatorSplitViewState',\n sourcesPanelSplitSidebarRatio: 'sourcesPanelDebuggerSidebarSplitViewState',\n 'timeline-details': 'timelinePanelDetailsSplitViewState',\n 'timeline-split': 'timelinePanelRecorsSplitViewState',\n 'timeline-view': 'timelinePanelTimelineStackSplitViewState',\n auditsSidebarWidth: 'auditsPanelSplitViewState',\n layersSidebarWidth: 'layersPanelSplitViewState',\n profilesSidebarWidth: 'profilesPanelSplitViewState',\n resourcesSidebarWidth: 'resourcesPanelSplitViewState',\n };\n const empty = {};\n for (const oldName in settingNames) {\n const newName = settingNames[oldName];\n const oldNameH = oldName + 'H';\n\n let newValue: {}|null = null;\n const oldSetting = Settings.instance().createSetting(oldName, empty);\n if (oldSetting.get() !== empty) {\n newValue = newValue || {};\n // @ts-expect-error\n newValue.vertical = {};\n // @ts-expect-error\n newValue.vertical.size = oldSetting.get();\n removeSetting(oldSetting);\n }\n const oldSettingH = Settings.instance().createSetting(oldNameH, empty);\n if (oldSettingH.get() !== empty) {\n newValue = newValue || {};\n // @ts-expect-error\n newValue.horizontal = {};\n // @ts-expect-error\n newValue.horizontal.size = oldSettingH.get();\n removeSetting(oldSettingH);\n }\n if (newValue) {\n Settings.instance().createSetting(newName, {}).set(newValue);\n }\n }\n }\n\n private updateVersionFrom5To6(): void {\n const settingNames: {\n [x: string]: string,\n } = {\n debuggerSidebarHidden: 'sourcesPanelSplitViewState',\n navigatorHidden: 'sourcesPanelNavigatorSplitViewState',\n 'WebInspector.Drawer.showOnLoad': 'Inspector.drawerSplitViewState',\n };\n\n for (const oldName in settingNames) {\n const oldSetting = Settings.instance().createSetting(oldName, null);\n if (oldSetting.get() === null) {\n removeSetting(oldSetting);\n continue;\n }\n\n const newName = settingNames[oldName];\n const invert = oldName === 'WebInspector.Drawer.showOnLoad';\n const hidden = oldSetting.get() !== invert;\n removeSetting(oldSetting);\n const showMode = hidden ? 'OnlyMain' : 'Both';\n\n const newSetting = Settings.instance().createSetting(newName, {});\n const newValue = newSetting.get() || {};\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // @ts-expect-error\n newValue.vertical = newValue.vertical || {};\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // @ts-expect-error\n newValue.vertical.showMode = showMode;\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // @ts-expect-error\n newValue.horizontal = newValue.horizontal || {};\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // @ts-expect-error\n newValue.horizontal.showMode = showMode;\n newSetting.set(newValue);\n }\n }\n\n private updateVersionFrom6To7(): void {\n const settingNames = {\n sourcesPanelNavigatorSplitViewState: 'sourcesPanelNavigatorSplitViewState',\n elementsPanelSplitViewState: 'elementsPanelSplitViewState',\n stylesPaneSplitViewState: 'stylesPaneSplitViewState',\n sourcesPanelDebuggerSidebarSplitViewState: 'sourcesPanelDebuggerSidebarSplitViewState',\n };\n\n const empty = {};\n for (const name in settingNames) {\n const setting =\n Settings.instance().createSetting<{vertical?: {size?: number}, horizontal?: {size?: number}}>(name, empty);\n const value = setting.get();\n if (value === empty) {\n continue;\n }\n // Zero out saved percentage sizes, and they will be restored to defaults.\n if (value.vertical && value.vertical.size && value.vertical.size < 1) {\n value.vertical.size = 0;\n }\n if (value.horizontal && value.horizontal.size && value.horizontal.size < 1) {\n value.horizontal.size = 0;\n }\n setting.set(value);\n }\n }\n\n private updateVersionFrom7To8(): void {\n }\n\n private updateVersionFrom8To9(): void {\n const settingNames = ['skipStackFramesPattern', 'workspaceFolderExcludePattern'];\n\n for (let i = 0; i < settingNames.length; ++i) {\n const setting = Settings.instance().createSetting(settingNames[i], '');\n let value = setting.get();\n if (!value) {\n return;\n }\n if (typeof value === 'string') {\n value = [value];\n }\n for (let j = 0; j < value.length; ++j) {\n if (typeof value[j] === 'string') {\n value[j] = {pattern: value[j]};\n }\n }\n setting.set(value);\n }\n }\n\n private updateVersionFrom9To10(): void {\n // This one is localStorage specific, which is fine.\n if (!window.localStorage) {\n return;\n }\n for (const key in window.localStorage) {\n if (key.startsWith('revision-history')) {\n window.localStorage.removeItem(key);\n }\n }\n }\n\n private updateVersionFrom10To11(): void {\n const oldSettingName = 'customDevicePresets';\n const newSettingName = 'customEmulatedDeviceList';\n const oldSetting = Settings.instance().createSetting(oldSettingName, undefined);\n const list = oldSetting.get();\n if (!Array.isArray(list)) {\n return;\n }\n const newList = [];\n for (let i = 0; i < list.length; ++i) {\n const value = list[i];\n const device: {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [x: string]: any,\n } = {};\n device['title'] = value['title'];\n device['type'] = 'unknown';\n device['user-agent'] = value['userAgent'];\n device['capabilities'] = [];\n if (value['touch']) {\n device['capabilities'].push('touch');\n }\n if (value['mobile']) {\n device['capabilities'].push('mobile');\n }\n device['screen'] = {};\n device['screen']['vertical'] = {width: value['width'], height: value['height']};\n device['screen']['horizontal'] = {width: value['height'], height: value['width']};\n device['screen']['device-pixel-ratio'] = value['deviceScaleFactor'];\n device['modes'] = [];\n device['show-by-default'] = true;\n device['show'] = 'Default';\n newList.push(device);\n }\n if (newList.length) {\n Settings.instance().createSetting(newSettingName, []).set(newList);\n }\n removeSetting(oldSetting);\n }\n\n private updateVersionFrom11To12(): void {\n this.migrateSettingsFromLocalStorage();\n }\n\n private updateVersionFrom12To13(): void {\n this.migrateSettingsFromLocalStorage();\n removeSetting(Settings.instance().createSetting('timelineOverviewMode', ''));\n }\n\n private updateVersionFrom13To14(): void {\n const defaultValue = {throughput: -1, latency: 0};\n Settings.instance().createSetting('networkConditions', defaultValue).set(defaultValue);\n }\n\n private updateVersionFrom14To15(): void {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const setting = Settings.instance().createLocalSetting('workspaceExcludedFolders', {});\n const oldValue = setting.get();\n const newValue: {\n [x: string]: string[],\n } = {};\n for (const fileSystemPath in oldValue) {\n newValue[fileSystemPath] = [];\n for (const entry of oldValue[fileSystemPath]) {\n newValue[fileSystemPath].push(entry.path);\n }\n }\n setting.set(newValue);\n }\n\n private updateVersionFrom15To16(): void {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const setting = Settings.instance().createSetting('InspectorView.panelOrder', {});\n const tabOrders = setting.get();\n for (const key of Object.keys(tabOrders)) {\n tabOrders[key] = (tabOrders[key] + 1) * 10;\n }\n setting.set(tabOrders);\n }\n\n private updateVersionFrom16To17(): void {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const setting = Settings.instance().createSetting('networkConditionsCustomProfiles', []);\n const oldValue = setting.get();\n const newValue = [];\n if (Array.isArray(oldValue)) {\n for (const preset of oldValue) {\n if (typeof preset.title === 'string' && typeof preset.value === 'object' &&\n typeof preset.value.throughput === 'number' && typeof preset.value.latency === 'number') {\n newValue.push({\n title: preset.title,\n value: {download: preset.value.throughput, upload: preset.value.throughput, latency: preset.value.latency},\n });\n }\n }\n }\n setting.set(newValue);\n }\n\n private updateVersionFrom17To18(): void {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const setting = Settings.instance().createLocalSetting('workspaceExcludedFolders', {});\n const oldValue = setting.get();\n const newValue: {\n [x: string]: string,\n } = {};\n for (const oldKey in oldValue) {\n let newKey = oldKey.replace(/\\\\/g, '/');\n if (!newKey.startsWith('file://')) {\n if (newKey.startsWith('/')) {\n newKey = 'file://' + newKey;\n } else {\n newKey = 'file:///' + newKey;\n }\n }\n newValue[newKey] = oldValue[oldKey];\n }\n setting.set(newValue);\n }\n\n private updateVersionFrom18To19(): void {\n const defaultColumns = {status: true, type: true, initiator: true, size: true, time: true};\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const visibleColumnSettings = Settings.instance().createSetting('networkLogColumnsVisibility', defaultColumns);\n const visibleColumns = visibleColumnSettings.get();\n visibleColumns.name = true;\n visibleColumns.timeline = true;\n\n const configs: {\n [x: string]: {\n visible: number,\n },\n } = {};\n for (const columnId in visibleColumns) {\n if (!visibleColumns.hasOwnProperty(columnId)) {\n continue;\n }\n configs[columnId.toLowerCase()] = {visible: visibleColumns[columnId]};\n }\n const newSetting = Settings.instance().createSetting('networkLogColumns', {});\n newSetting.set(configs);\n removeSetting(visibleColumnSettings);\n }\n\n private updateVersionFrom19To20(): void {\n const oldSetting = Settings.instance().createSetting('InspectorView.panelOrder', {});\n const newSetting = Settings.instance().createSetting('panel-tabOrder', {});\n newSetting.set(oldSetting.get());\n removeSetting(oldSetting);\n }\n\n private updateVersionFrom20To21(): void {\n const networkColumns = Settings.instance().createSetting('networkLogColumns', {});\n const columns = (networkColumns.get() as {\n [x: string]: string,\n });\n delete columns['timeline'];\n delete columns['waterfall'];\n networkColumns.set(columns);\n }\n\n private updateVersionFrom21To22(): void {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const breakpointsSetting = Settings.instance().createLocalSetting('breakpoints', []);\n const breakpoints = breakpointsSetting.get();\n for (const breakpoint of breakpoints) {\n breakpoint['url'] = breakpoint['sourceFileId'];\n delete breakpoint['sourceFileId'];\n }\n breakpointsSetting.set(breakpoints);\n }\n\n private updateVersionFrom22To23(): void {\n // This update is no-op.\n }\n\n private updateVersionFrom23To24(): void {\n const oldSetting = Settings.instance().createSetting('searchInContentScripts', false);\n const newSetting = Settings.instance().createSetting('searchInAnonymousAndContentScripts', false);\n newSetting.set(oldSetting.get());\n removeSetting(oldSetting);\n }\n\n private updateVersionFrom24To25(): void {\n const defaultColumns = {status: true, type: true, initiator: true, size: true, time: true};\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const networkLogColumnsSetting = Settings.instance().createSetting('networkLogColumns', defaultColumns);\n const columns = networkLogColumnsSetting.get();\n delete columns.product;\n networkLogColumnsSetting.set(columns);\n }\n\n private updateVersionFrom25To26(): void {\n const oldSetting = Settings.instance().createSetting('messageURLFilters', {});\n const urls = Object.keys(oldSetting.get());\n const textFilter = urls.map(url => `-url:${url}`).join(' ');\n if (textFilter) {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const textFilterSetting = Settings.instance().createSetting('console.textFilter', '');\n const suffix = textFilterSetting.get() ? ` ${textFilterSetting.get()}` : '';\n textFilterSetting.set(`${textFilter}${suffix}`);\n }\n removeSetting(oldSetting);\n }\n\n private updateVersionFrom26To27(): void {\n function renameKeyInObjectSetting(settingName: string, from: string, to: string): void {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const setting = Settings.instance().createSetting(settingName, {});\n const value = setting.get();\n if (from in value) {\n value[to] = value[from];\n delete value[from];\n setting.set(value);\n }\n }\n\n function renameInStringSetting(settingName: string, from: string, to: string): void {\n const setting = Settings.instance().createSetting(settingName, '');\n const value = setting.get();\n if (value === from) {\n setting.set(to);\n }\n }\n\n renameKeyInObjectSetting('panel-tabOrder', 'audits2', 'audits');\n renameKeyInObjectSetting('panel-closeableTabs', 'audits2', 'audits');\n renameInStringSetting('panel-selectedTab', 'audits2', 'audits');\n }\n\n private updateVersionFrom27To28(): void {\n const setting = Settings.instance().createSetting('uiTheme', 'systemPreferred');\n if (setting.get() === 'default') {\n setting.set('systemPreferred');\n }\n }\n\n private updateVersionFrom28To29(): void {\n function renameKeyInObjectSetting(settingName: string, from: string, to: string): void {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const setting = Settings.instance().createSetting(settingName, {});\n const value = setting.get();\n if (from in value) {\n value[to] = value[from];\n delete value[from];\n setting.set(value);\n }\n }\n\n function renameInStringSetting(settingName: string, from: string, to: string): void {\n const setting = Settings.instance().createSetting(settingName, '');\n const value = setting.get();\n if (value === from) {\n setting.set(to);\n }\n }\n\n renameKeyInObjectSetting('panel-tabOrder', 'audits', 'lighthouse');\n renameKeyInObjectSetting('panel-closeableTabs', 'audits', 'lighthouse');\n renameInStringSetting('panel-selectedTab', 'audits', 'lighthouse');\n }\n\n private updateVersionFrom29To30(): void {\n // Create new location agnostic setting\n const closeableTabSetting = Settings.instance().createSetting('closeableTabs', {});\n\n // Read current settings\n const panelCloseableTabSetting = Settings.instance().createSetting('panel-closeableTabs', {});\n const drawerCloseableTabSetting = Settings.instance().createSetting('drawer-view-closeableTabs', {});\n const openTabsInPanel = panelCloseableTabSetting.get();\n const openTabsInDrawer = panelCloseableTabSetting.get();\n\n // Set #value of new setting\n const newValue = Object.assign(openTabsInDrawer, openTabsInPanel);\n closeableTabSetting.set(newValue);\n\n // Remove old settings\n removeSetting(panelCloseableTabSetting);\n removeSetting(drawerCloseableTabSetting);\n }\n\n private updateVersionFrom30To31(): void {\n // Remove recorder_recordings setting that was used for storing recordings\n // by an old recorder experiment.\n const recordingsSetting = Settings.instance().createSetting('recorder_recordings', []);\n removeSetting(recordingsSetting);\n }\n\n updateVersionFrom31To32(): void {\n // Introduce the new 'resourceTypeName' property on stored breakpoints. Prior to\n // this change we synchronized the breakpoint only by URL, but since we don't\n // know on which resource type the given breakpoint was set, we just assume\n // 'script' here to keep things simple.\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const breakpointsSetting = Settings.instance().createLocalSetting('breakpoints', []);\n const breakpoints = breakpointsSetting.get();\n for (const breakpoint of breakpoints) {\n breakpoint['resourceTypeName'] = 'script';\n }\n breakpointsSetting.set(breakpoints);\n }\n\n updateVersionFrom32To33(): void {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const previouslyViewedFilesSetting = Settings.instance().createLocalSetting('previouslyViewedFiles', []);\n let previouslyViewedFiles = previouslyViewedFilesSetting.get();\n\n // Discard old 'previouslyViewedFiles' items that don't have a 'url' property.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n previouslyViewedFiles = previouslyViewedFiles.filter((previouslyViewedFile: any) => 'url' in previouslyViewedFile);\n\n // Introduce the new 'resourceTypeName' property on previously viewed files.\n // Prior to this change we only keyed them based on the URL, but since we\n // don't know which resource type the given file had, we just assume 'script'\n // here to keep things simple.\n for (const previouslyViewedFile of previouslyViewedFiles) {\n previouslyViewedFile['resourceTypeName'] = 'script';\n }\n\n previouslyViewedFilesSetting.set(previouslyViewedFiles);\n }\n\n updateVersionFrom33To34(): void {\n // Introduces the 'isLogpoint' property on stored breakpoints. This information was\n // previously encoded in the 'condition' itself. This migration leaves the condition\n // alone but ensures that 'isLogpoint' is accurate for already stored breakpoints.\n // This enables us to use the 'isLogpoint' property in code.\n // A separate migration will remove the special encoding from the condition itself\n // once all refactorings are done.\n\n // The prefix/suffix are hardcoded here, since these constants will be removed in\n // the future.\n const logpointPrefix = '/** DEVTOOLS_LOGPOINT */ console.log(';\n const logpointSuffix = ')';\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const breakpointsSetting = Settings.instance().createLocalSetting('breakpoints', []);\n const breakpoints = breakpointsSetting.get();\n for (const breakpoint of breakpoints) {\n const isLogpoint =\n breakpoint.condition.startsWith(logpointPrefix) && breakpoint.condition.endsWith(logpointSuffix);\n breakpoint['isLogpoint'] = isLogpoint;\n }\n breakpointsSetting.set(breakpoints);\n }\n\n updateVersionFrom34To35(): void {\n // Uses the 'isLogpoint' property on stored breakpoints to remove the prefix/suffix\n // from logpoints. This way, we store the entered log point condition as the user\n // entered it.\n\n // The prefix/suffix are hardcoded here, since these constants will be removed in\n // the future.\n const logpointPrefix = '/** DEVTOOLS_LOGPOINT */ console.log(';\n const logpointSuffix = ')';\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const breakpointsSetting = Settings.instance().createLocalSetting('breakpoints', []);\n const breakpoints = breakpointsSetting.get();\n for (const breakpoint of breakpoints) {\n const {condition, isLogpoint} = breakpoint;\n if (isLogpoint) {\n breakpoint.condition = condition.slice(logpointPrefix.length, condition.length - logpointSuffix.length);\n }\n }\n breakpointsSetting.set(breakpoints);\n }\n\n updateVersionFrom35To36(): void {\n // We have changed the default from 'false' to 'true' and this updates the existing setting just for once.\n Settings.instance().createSetting('showThirdPartyIssues', true).set(true);\n }\n\n updateVersionFrom36To37(): void {\n const updateStorage = (storage: SettingsStorage): void => {\n for (const key of storage.keys()) {\n const normalizedKey = Settings.normalizeSettingName(key);\n if (normalizedKey !== key) {\n const value = storage.get(key);\n removeSetting({name: key, storage});\n storage.set(normalizedKey, value);\n }\n }\n };\n updateStorage(Settings.instance().globalStorage);\n updateStorage(Settings.instance().syncedStorage);\n updateStorage(Settings.instance().localStorage);\n\n for (const key of Settings.instance().globalStorage.keys()) {\n if ((key.startsWith('data-grid-') && key.endsWith('-column-weights')) || key.endsWith('-tab-order') ||\n key === 'views-location-override' || key === 'closeable-tabs') {\n const setting = Settings.instance().createSetting(key, {});\n setting.set(Platform.StringUtilities.toKebabCaseKeys(setting.get()));\n }\n if (key.endsWith('-selected-tab')) {\n const setting = Settings.instance().createSetting(key, '');\n setting.set(Platform.StringUtilities.toKebabCase(setting.get()));\n }\n }\n }\n\n updateVersionFrom37To38(): void {\n const getConsoleInsightsEnabledSetting = (): Setting|undefined => {\n try {\n return moduleSetting('console-insights-enabled') as Setting;\n } catch {\n return;\n }\n };\n\n const consoleInsightsEnabled = getConsoleInsightsEnabledSetting();\n const onboardingFinished = Settings.instance().createLocalSetting('console-insights-onboarding-finished', false);\n\n if (consoleInsightsEnabled && consoleInsightsEnabled.get() === true && onboardingFinished.get() === false) {\n consoleInsightsEnabled.set(false);\n }\n if (consoleInsightsEnabled && consoleInsightsEnabled.get() === false) {\n onboardingFinished.set(false);\n }\n }\n\n /*\n * Any new migration should be added before this comment.\n *\n * IMPORTANT: Migrations must be idempotent, since they may be applied\n * multiple times! E.g. when renaming a setting one has to check that the\n * a setting with the new name does not yet exist.\n * ----------------------------------------------------------------------- */\n\n private migrateSettingsFromLocalStorage(): void {\n // This step migrates all the settings except for the ones below into the browser profile.\n const localSettings = new Set([\n 'advancedSearchConfig',\n 'breakpoints',\n 'consoleHistory',\n 'domBreakpoints',\n 'eventListenerBreakpoints',\n 'fileSystemMapping',\n 'lastSelectedSourcesSidebarPaneTab',\n 'previouslyViewedFiles',\n 'savedURLs',\n 'watchExpressions',\n 'workspaceExcludedFolders',\n 'xhrBreakpoints',\n ]);\n if (!window.localStorage) {\n return;\n }\n\n for (const key in window.localStorage) {\n if (localSettings.has(key)) {\n continue;\n }\n const value = window.localStorage[key];\n window.localStorage.removeItem(key);\n Settings.instance().globalStorage.set(key, value);\n }\n }\n\n private clearBreakpointsWhenTooMany(breakpointsSetting: Setting, maxBreakpointsCount: number): void {\n // If there are too many breakpoints in a storage, it is likely due to a recent bug that caused\n // periodical breakpoints duplication leading to inspector slowness.\n if (breakpointsSetting.get().length > maxBreakpointsCount) {\n breakpointsSetting.set([]);\n }\n }\n}\n\nexport const enum SettingStorageType {\n /**\n * Synced storage persists settings with the active Chrome profile but also\n * syncs the settings across devices via Chrome Sync.\n */\n SYNCED = 'Synced',\n /** Global storage persists settings with the active Chrome profile */\n GLOBAL = 'Global',\n /** Uses Window.localStorage */\n LOCAL = 'Local',\n /** Session storage dies when DevTools window closes */\n SESSION = 'Session',\n}\n\nexport function moduleSetting(settingName: string): Setting {\n return Settings.instance().moduleSetting(settingName);\n}\n\nexport function settingForTest(settingName: string): Setting {\n return Settings.instance().settingForTest(settingName);\n}\n\nexport {\n getLocalizedSettingsCategory,\n maybeRemoveSettingExtension,\n registerSettingExtension,\n RegExpSettingItem,\n SettingCategory,\n SettingExtensionOption,\n SettingRegistration,\n SettingType,\n registerSettingsForTest,\n resetSettings,\n};\n\nexport interface Serializer {\n stringify: (value: I) => string;\n parse: (value: string) => O;\n}\n\nexport interface SimpleSettingOption {\n value: string|boolean;\n title: string;\n text?: string;\n raw?: boolean;\n}\n"]} \ No newline at end of file diff --git a/public/core/common/Settings.test.js b/public/core/common/Settings.test.js index daeff174f..e69a60ee5 100644 --- a/public/core/common/Settings.test.js +++ b/public/core/common/Settings.test.js @@ -458,4 +458,64 @@ describe('VersionController', () => { }); }); }); +describe('updateVersionFrom37To38', () => { + let settings; + beforeEach(() => { + const mockStore = new MockStore(); + const syncedStorage = new Common.Settings.SettingsStorage({}, mockStore); + const globalStorage = new Common.Settings.SettingsStorage({}, mockStore); + const localStorage = new Common.Settings.SettingsStorage({}, mockStore); + Common.Settings.registerSettingExtension({ + settingName: 'console-insights-enabled', + settingType: "boolean" /* Common.Settings.SettingType.BOOLEAN */, + defaultValue: true, + }); + settings = Common.Settings.Settings.instance({ + forceNew: true, + syncedStorage, + globalStorage, + localStorage, + }); + }); + afterEach(() => { + Common.Settings.Settings.removeInstance(); + Common.Settings.resetSettings(); // Clear SettingsRegistrations. + }); + it('disables console insights setting if onboarding not done', () => { + const versionController = new VersionController(); + const consoleInsightsEnabled = settings.moduleSetting('console-insights-enabled'); + consoleInsightsEnabled.set(true); + const onboardingFinished = settings.createLocalSetting('console-insights-onboarding-finished', false); + versionController.updateVersionFrom37To38(); + assert.isFalse(consoleInsightsEnabled.get()); + assert.isFalse(onboardingFinished.get()); + }); + it('preserves state if console insights disabled and not onboarded ', () => { + const versionController = new VersionController(); + const consoleInsightsEnabled = settings.moduleSetting('console-insights-enabled'); + consoleInsightsEnabled.set(false); + const onboardingFinished = settings.createLocalSetting('console-insights-onboarding-finished', false); + versionController.updateVersionFrom37To38(); + assert.isFalse(consoleInsightsEnabled.get()); + assert.isFalse(onboardingFinished.get()); + }); + it('preserves state if console insights enabled and onboarded', () => { + const versionController = new VersionController(); + const consoleInsightsEnabled = settings.moduleSetting('console-insights-enabled'); + consoleInsightsEnabled.set(true); + const onboardingFinished = settings.createLocalSetting('console-insights-onboarding-finished', true); + versionController.updateVersionFrom37To38(); + assert.isTrue(consoleInsightsEnabled.get()); + assert.isTrue(onboardingFinished.get()); + }); + it('resets onboarding if console insights setting is disabled', () => { + const versionController = new VersionController(); + const consoleInsightsEnabled = settings.moduleSetting('console-insights-enabled'); + consoleInsightsEnabled.set(false); + const onboardingFinished = settings.createLocalSetting('console-insights-onboarding-finished', true); + versionController.updateVersionFrom37To38(); + assert.isFalse(consoleInsightsEnabled.get()); + assert.isFalse(onboardingFinished.get()); + }); +}); //# sourceMappingURL=Settings.test.js.map \ No newline at end of file diff --git a/public/core/common/Settings.test.js.map b/public/core/common/Settings.test.js.map index ae833f0e4..2464666a3 100644 --- a/public/core/common/Settings.test.js.map +++ b/public/core/common/Settings.test.js.map @@ -1 +1 @@ -{"version":3,"file":"Settings.test.js","sourceRoot":"","sources":["../../../../../../front_end/core/common/Settings.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2019 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from './common.js';\n\nconst SettingsStorage = Common.Settings.SettingsStorage;\nconst VersionController = Common.Settings.VersionController;\n\nclass MockStore implements Common.Settings.SettingsBackingStore {\n #store = new Map();\n register() {\n }\n set(key: string, value: string) {\n this.#store.set(key, value);\n }\n get(key: string) {\n return this.#store.get(key);\n }\n remove(key: string) {\n this.#store.delete(key);\n }\n clear() {\n this.#store.clear();\n }\n}\n\ndescribe('SettingsStorage class', () => {\n it('is able to set a name', () => {\n const settingsStorage = new SettingsStorage({});\n settingsStorage.set('Test Name', 'Test Value');\n assert.strictEqual(settingsStorage.get('Test Name'), 'Test Value', 'Name was not retrieve correctly');\n });\n\n it('is able to check if a name that it has exists', () => {\n const settingsStorage = new SettingsStorage({});\n settingsStorage.set('Test Name', 'Test Value');\n assert.isTrue(settingsStorage.has('Test Name'), 'the class should have that name');\n });\n\n it('is able to check if a name that it does not have exists', () => {\n const settingsStorage = new SettingsStorage({});\n assert.isFalse(settingsStorage.has('Test Name'), 'the class should not have that name');\n });\n\n it('is able to remove a name', () => {\n const settingsStorage = new SettingsStorage({});\n settingsStorage.set('Test Name', 'Test Value');\n settingsStorage.remove('Test Name');\n assert.isFalse(settingsStorage.has('Test Name'), 'the class should not have that name');\n });\n\n it('is able to remove all names', () => {\n const settingsStorage = new SettingsStorage({});\n settingsStorage.set('Test Name 1', 'Test Value 1');\n settingsStorage.set('Test Name 2', 'Test Value 2');\n settingsStorage.removeAll();\n assert.isFalse(settingsStorage.has('Test Name 1'), 'the class should not have any names');\n assert.isFalse(settingsStorage.has('Test Name 2'), 'the class should not have any names');\n });\n\n describe('forceGet', () => {\n it('returns the value of the backing store, not the cached one', async () => {\n const mockStore = new MockStore();\n const settingsStorage = new SettingsStorage({}, mockStore);\n settingsStorage.set('test', 'value');\n\n mockStore.set('test', 'changed');\n\n assert.strictEqual(await settingsStorage.forceGet('test'), 'changed');\n assert.strictEqual(await settingsStorage.forceGet('test'), 'changed');\n });\n it('updates the cached value of a SettingsStorage', async () => {\n const mockStore = new MockStore();\n const settingsStorage = new SettingsStorage({}, mockStore);\n settingsStorage.set('test', 'value');\n mockStore.set('test', 'changed');\n assert.strictEqual(settingsStorage.get('test'), 'value');\n\n await settingsStorage.forceGet('test');\n\n assert.strictEqual(settingsStorage.get('test'), 'changed');\n });\n it('leaves the cached value alone if the backing store has the same value', async () => {\n const mockStore = new MockStore();\n const settingsStorage = new SettingsStorage({}, mockStore);\n\n mockStore.set('test', 'value');\n settingsStorage.set('test', 'value');\n\n assert.strictEqual(mockStore.get('test'), 'value');\n assert.strictEqual(await settingsStorage.forceGet('test'), 'value');\n assert.strictEqual(mockStore.get('test'), 'value');\n assert.strictEqual(await settingsStorage.forceGet('test'), 'value');\n });\n });\n});\n\ndescribe('Settings instance', () => {\n afterEach(() => {\n Common.Settings.Settings.removeInstance();\n Common.Settings.resetSettings(); // Clear SettingsRegistrations.\n });\n\n it('can be instantiated in a test', () => {\n const dummyStorage = new SettingsStorage({});\n\n const settings = Common.Settings.Settings.instance({\n forceNew: true,\n syncedStorage: dummyStorage,\n globalStorage: dummyStorage,\n localStorage: dummyStorage,\n });\n\n assert.isOk(settings);\n });\n\n it('throws when constructed without storage', () => {\n assert.throws(() => Common.Settings.Settings.instance());\n assert.throws(\n () => Common.Settings.Settings.instance(\n {forceNew: true, syncedStorage: null, globalStorage: null, localStorage: null}));\n });\n\n it('stores synced settings in the correct storage', () => {\n const syncedStorage = new SettingsStorage({});\n const dummyStorage = new SettingsStorage({});\n Common.Settings.registerSettingExtension({\n settingName: 'static-synced-setting',\n settingType: Common.Settings.SettingType.BOOLEAN,\n defaultValue: false,\n storageType: Common.Settings.SettingStorageType.SYNCED,\n });\n const settings = Common.Settings.Settings.instance(\n {forceNew: true, syncedStorage, globalStorage: dummyStorage, localStorage: dummyStorage});\n\n const dynamicSetting: Common.Settings.Setting =\n settings.createSetting('dynamic-synced-setting', 'default val', Common.Settings.SettingStorageType.SYNCED);\n dynamicSetting.set('foo value');\n const staticSetting: Common.Settings.Setting = settings.moduleSetting('static-synced-setting');\n staticSetting.set(true);\n\n assert.isFalse(dummyStorage.has('dynamic-synced-setting'));\n assert.isFalse(dummyStorage.has('static-synced-setting'));\n assert.strictEqual(syncedStorage.get('dynamic-synced-setting'), '\"foo value\"');\n assert.strictEqual(syncedStorage.get('static-synced-setting'), 'true');\n });\n\n it('registers settings with the backing store when creating them', () => {\n const registeredSettings = new Set();\n const mockBackingStore: Common.Settings.SettingsBackingStore = {\n ...Common.Settings.NOOP_STORAGE,\n register: (name: string) => registeredSettings.add(name),\n };\n const storage = new SettingsStorage({}, mockBackingStore, '__prefix__.');\n Common.Settings.registerSettingExtension({\n settingName: 'static-global-setting',\n settingType: Common.Settings.SettingType.BOOLEAN,\n defaultValue: false,\n storageType: Common.Settings.SettingStorageType.GLOBAL,\n });\n\n const settings = Common.Settings.Settings.instance(\n {forceNew: true, syncedStorage: storage, globalStorage: storage, localStorage: storage});\n settings.createSetting('dynamic-local-setting', 42, Common.Settings.SettingStorageType.LOCAL);\n settings.createSetting('dynamic-synced-setting', 'foo', Common.Settings.SettingStorageType.SYNCED);\n\n assert.isTrue(registeredSettings.has('__prefix__.static-global-setting'));\n assert.isTrue(registeredSettings.has('__prefix__.dynamic-local-setting'));\n assert.isTrue(registeredSettings.has('__prefix__.dynamic-synced-setting'));\n });\n\n describe('forceGet', () => {\n it('triggers a setting changed event in case the value in the backing store got updated and we update the cached value',\n async () => {\n const mockStore = new MockStore();\n const settingsStorage = new SettingsStorage({}, mockStore);\n mockStore.set('test', '\"old\"');\n const settings = Common.Settings.Settings.instance({\n forceNew: true,\n syncedStorage: settingsStorage,\n globalStorage: settingsStorage,\n localStorage: settingsStorage,\n });\n const testSetting: Common.Settings.Setting =\n settings.createSetting('test', 'default val', Common.Settings.SettingStorageType.GLOBAL);\n const changes: string[] = [];\n testSetting.addChangeListener((event: Common.EventTarget.EventTargetEvent) => {\n changes.push(event.data);\n });\n mockStore.set('test', '\"new\"');\n assert.strictEqual(await testSetting.forceGet(), 'new');\n assert.deepEqual(changes, ['new']);\n assert.strictEqual(mockStore.get('test'), '\"new\"');\n assert.strictEqual(await settingsStorage.forceGet('test'), '\"new\"');\n assert.strictEqual(await testSetting.forceGet(), 'new');\n });\n });\n\n it('getIfNotDisabled returns the setting\\'s value only if the setting is not disabled', async () => {\n const registeredSettings = new Set();\n const mockBackingStore: Common.Settings.SettingsBackingStore = {\n ...Common.Settings.NOOP_STORAGE,\n register: (name: string) => registeredSettings.add(name),\n };\n const storage = new SettingsStorage({}, mockBackingStore, '__prefix__.');\n const settings = Common.Settings.Settings.instance(\n {forceNew: true, syncedStorage: storage, globalStorage: storage, localStorage: storage});\n const testSetting = settings.createSetting('test-setting', 'some value');\n assert.strictEqual(testSetting.getIfNotDisabled(), 'some value');\n\n testSetting.setDisabled(true);\n assert.isUndefined(testSetting.getIfNotDisabled());\n\n testSetting.setDisabled(false);\n assert.strictEqual(testSetting.getIfNotDisabled(), 'some value');\n });\n});\n\ndescribe('VersionController', () => {\n let settings: Common.Settings.Settings;\n let syncedStorage: Common.Settings.SettingsStorage;\n let globalStorage: Common.Settings.SettingsStorage;\n let localStorage: Common.Settings.SettingsStorage;\n\n beforeEach(() => {\n const mockStore = new MockStore();\n syncedStorage = new Common.Settings.SettingsStorage({}, mockStore);\n globalStorage = new Common.Settings.SettingsStorage({}, mockStore);\n localStorage = new Common.Settings.SettingsStorage({}, mockStore);\n settings = Common.Settings.Settings.instance({\n forceNew: true,\n syncedStorage,\n globalStorage,\n localStorage,\n });\n });\n\n afterEach(() => {\n Common.Settings.Settings.removeInstance();\n });\n\n describe('updateVersion', () => {\n it('initializes version settings with the current version if the setting doesn\\'t exist yet', () => {\n assert.isFalse(globalStorage.has(VersionController.GLOBAL_VERSION_SETTING_NAME));\n assert.isFalse(syncedStorage.has(VersionController.SYNCED_VERSION_SETTING_NAME));\n assert.isFalse(localStorage.has(VersionController.LOCAL_VERSION_SETTING_NAME));\n\n new VersionController().updateVersion();\n\n const currentVersion = VersionController.CURRENT_VERSION.toString();\n assert.strictEqual(globalStorage.get(VersionController.GLOBAL_VERSION_SETTING_NAME), currentVersion);\n assert.strictEqual(syncedStorage.get(VersionController.SYNCED_VERSION_SETTING_NAME), currentVersion);\n assert.strictEqual(localStorage.get(VersionController.LOCAL_VERSION_SETTING_NAME), currentVersion);\n });\n\n function spyAllUpdateMethods(versionController: Common.Settings.VersionController) {\n const spies: Array> = [];\n for (let i = 0; i < VersionController.CURRENT_VERSION; ++i) {\n spies.push(\n sinon.spy(versionController, `updateVersionFrom${i}To${i + 1}` as keyof Common.Settings.VersionController));\n }\n assert.lengthOf(spies, VersionController.CURRENT_VERSION);\n return spies;\n }\n\n it('does not run any update* methods if no version setting exist yet', () => {\n const versionController = new VersionController();\n const spies = spyAllUpdateMethods(versionController);\n\n versionController.updateVersion();\n\n for (const spy of spies) {\n assert.isFalse(spy.called);\n }\n });\n\n it('does not run any update* methods if all version settings are already current', () => {\n const currentVersion = VersionController.CURRENT_VERSION.toString();\n globalStorage.set(VersionController.GLOBAL_VERSION_SETTING_NAME, currentVersion);\n syncedStorage.set(VersionController.SYNCED_VERSION_SETTING_NAME, currentVersion);\n localStorage.set(VersionController.LOCAL_VERSION_SETTING_NAME, currentVersion);\n const versionController = new VersionController();\n const spies = spyAllUpdateMethods(versionController);\n\n versionController.updateVersion();\n\n for (const spy of spies) {\n assert.isFalse(spy.called);\n }\n });\n\n it('runs correct update* methods if the local bucket lags behind', () => {\n const currentVersion = VersionController.CURRENT_VERSION.toString();\n const localVersion = (VersionController.CURRENT_VERSION - 3).toString();\n globalStorage.set(VersionController.GLOBAL_VERSION_SETTING_NAME, currentVersion);\n syncedStorage.set(VersionController.SYNCED_VERSION_SETTING_NAME, currentVersion);\n localStorage.set(VersionController.LOCAL_VERSION_SETTING_NAME, localVersion);\n const versionController = new VersionController();\n const spies = spyAllUpdateMethods(versionController);\n\n versionController.updateVersion();\n\n const expectedUncalledSpies = spies.slice(0, -3);\n for (const spy of expectedUncalledSpies) {\n assert.isFalse(spy.called);\n }\n\n const expectedCalledSpies = spies.slice(-3);\n for (const spy of expectedCalledSpies) {\n assert.isTrue(spy.called);\n }\n });\n\n it('runs correct update* methods if the synced bucket runs ahead', () => {\n const currentVersion = VersionController.CURRENT_VERSION.toString();\n const oldVersion = (VersionController.CURRENT_VERSION - 1).toString();\n globalStorage.set(VersionController.GLOBAL_VERSION_SETTING_NAME, oldVersion);\n syncedStorage.set(VersionController.SYNCED_VERSION_SETTING_NAME, currentVersion);\n localStorage.set(VersionController.LOCAL_VERSION_SETTING_NAME, oldVersion);\n const versionController = new VersionController();\n const spies = spyAllUpdateMethods(versionController);\n\n versionController.updateVersion();\n\n const expectedUncalledSpies = spies.slice(0, -1);\n for (const spy of expectedUncalledSpies) {\n assert.isFalse(spy.called);\n }\n\n const expectedCalledSpies = spies.slice(-1);\n for (const spy of expectedCalledSpies) {\n assert.isTrue(spy.called);\n }\n });\n });\n\n describe('updateVersionFrom31To32', () => {\n it('correctly adds resourceTypeName to breakpoints', () => {\n const versionController = new VersionController();\n const breakpointsSetting = settings.createLocalSetting('breakpoints', [\n {url: 'webpack:///src/foo.ts', lineNumber: 4, condition: '', enabled: false},\n {url: 'foo.js', lineNumber: 1, columnNumber: 42, condition: 'false', enabled: true},\n ]);\n versionController.updateVersionFrom31To32();\n const breakpoints = breakpointsSetting.get();\n assert.lengthOf(breakpoints, 2);\n assert.propertyVal(breakpoints[0], 'url', 'webpack:///src/foo.ts');\n assert.propertyVal(breakpoints[0], 'resourceTypeName', 'script');\n assert.propertyVal(breakpoints[0], 'lineNumber', 4);\n assert.notProperty(breakpoints[0], 'columnNumber');\n assert.propertyVal(breakpoints[0], 'condition', '');\n assert.propertyVal(breakpoints[0], 'enabled', false);\n assert.propertyVal(breakpoints[1], 'url', 'foo.js');\n assert.propertyVal(breakpoints[1], 'resourceTypeName', 'script');\n assert.propertyVal(breakpoints[1], 'lineNumber', 1);\n assert.propertyVal(breakpoints[1], 'columnNumber', 42);\n assert.propertyVal(breakpoints[1], 'condition', 'false');\n assert.propertyVal(breakpoints[1], 'enabled', true);\n });\n });\n\n describe('updateVersionFrom32To33', () => {\n it('correctly discards previously viewed files without url properties', () => {\n const versionController = new VersionController();\n const previouslyViewedFilesSetting = settings.createLocalSetting('previouslyViewedFiles', [\n {url: 'http://localhost:3000', scrollLineNumber: 1},\n {scrollLineNumber: 1},\n {},\n {url: 'webpack:///src/foo.ts'},\n ]);\n versionController.updateVersionFrom32To33();\n const previouslyViewedFiles = previouslyViewedFilesSetting.get();\n assert.lengthOf(previouslyViewedFiles, 2);\n assert.propertyVal(previouslyViewedFiles[0], 'url', 'http://localhost:3000');\n assert.notProperty(previouslyViewedFiles[0], 'selectionRange');\n assert.propertyVal(previouslyViewedFiles[0], 'scrollLineNumber', 1);\n assert.propertyVal(previouslyViewedFiles[1], 'url', 'webpack:///src/foo.ts');\n assert.notProperty(previouslyViewedFiles[1], 'selectionRange');\n assert.notProperty(previouslyViewedFiles[1], 'scrollLineNumber');\n });\n\n it('correctly adds resourceTypeName to previously viewed files', () => {\n const versionController = new VersionController();\n const previouslyViewedFilesSetting = settings.createLocalSetting('previouslyViewedFiles', [\n {url: 'http://localhost:3000', scrollLineNumber: 1},\n {url: 'webpack:///src/foo.ts'},\n ]);\n versionController.updateVersionFrom32To33();\n const previouslyViewedFiles = previouslyViewedFilesSetting.get();\n assert.lengthOf(previouslyViewedFiles, 2);\n assert.propertyVal(previouslyViewedFiles[0], 'url', 'http://localhost:3000');\n assert.propertyVal(previouslyViewedFiles[0], 'resourceTypeName', 'script');\n assert.notProperty(previouslyViewedFiles[0], 'selectionRange');\n assert.propertyVal(previouslyViewedFiles[0], 'scrollLineNumber', 1);\n assert.propertyVal(previouslyViewedFiles[1], 'url', 'webpack:///src/foo.ts');\n assert.propertyVal(previouslyViewedFiles[1], 'resourceTypeName', 'script');\n assert.notProperty(previouslyViewedFiles[1], 'selectionRange');\n assert.notProperty(previouslyViewedFiles[1], 'scrollLineNumber');\n });\n });\n\n describe('updateVersionFrom33To34', () => {\n it('correctly adds isLogpoint to breakpoints', () => {\n const versionController = new VersionController();\n const breakpointsSetting = settings.createLocalSetting('breakpoints', [\n {\n url: 'webpack:///src/foo.ts',\n lineNumber: 4,\n resourceTypeName: 'script',\n condition: '/** DEVTOOLS_LOGPOINT */ console.log(foo.property)',\n enabled: true,\n },\n {\n url: 'foo.js',\n lineNumber: 1,\n columnNumber: 42,\n resourceTypeName: 'script',\n condition: 'x === 42',\n enabled: true,\n },\n {url: 'bar.js', lineNumber: 5, columnNumber: 1, resourceTypeName: 'script', condition: '', enabled: true},\n ]);\n\n versionController.updateVersionFrom33To34();\n const breakpoints = breakpointsSetting.get();\n\n assert.propertyVal(breakpoints[0], 'isLogpoint', true);\n assert.propertyVal(breakpoints[1], 'isLogpoint', false);\n assert.propertyVal(breakpoints[2], 'isLogpoint', false);\n });\n });\n\n describe('updateVersionFrom34To35', () => {\n it('removes the logpoint prefix/suffix from logpoints', () => {\n const versionController = new VersionController();\n const breakpointsSetting =\n settings.createLocalSetting('breakpoints', [{\n url: 'webpack:///src/foo.ts',\n lineNumber: 4,\n resourceTypeName: 'script',\n condition: '/** DEVTOOLS_LOGPOINT */ console.log(foo.property)',\n enabled: true,\n isLogpoint: true,\n }]);\n\n versionController.updateVersionFrom34To35();\n\n const breakpoints = breakpointsSetting.get();\n assert.lengthOf(breakpoints, 1);\n assert.propertyVal(breakpoints[0], 'condition', 'foo.property');\n });\n\n it('leaves conditional breakpoints alone', () => {\n const versionController = new VersionController();\n const breakpointsSetting = settings.createLocalSetting('breakpoints', [{\n url: 'webpack:///src/foo.ts',\n lineNumber: 4,\n resourceTypeName: 'script',\n condition: 'x === 42',\n enabled: true,\n isLogpoint: false,\n }]);\n\n versionController.updateVersionFrom34To35();\n\n const breakpoints = breakpointsSetting.get();\n assert.lengthOf(breakpoints, 1);\n assert.propertyVal(breakpoints[0], 'condition', 'x === 42');\n });\n });\n\n describe('updateVersionFrom35To36', () => {\n it('update showThirdPartyIssues setting value to true', () => {\n const versionController = new VersionController();\n const showThirdPartyIssuesSetting = settings.createLocalSetting('showThirdPartyIssues', false);\n versionController.updateVersionFrom35To36();\n assert.isTrue(showThirdPartyIssuesSetting.get());\n });\n });\n\n describe('updateVersionFrom36To37', () => {\n it('updates all keys to kebab case', () => {\n const versionController = new VersionController();\n settings.globalStorage.set('globalSetting1', '');\n settings.globalStorage.set('globalSetting2', '');\n settings.localStorage.set('localSetting', '');\n settings.syncedStorage.set('syncedSetting', '');\n\n versionController.updateVersionFrom36To37();\n\n assert.deepEqual(settings.globalStorage.keys(), ['global-setting-1', 'global-setting-2']);\n assert.deepEqual(settings.localStorage.keys(), ['local-setting']);\n assert.deepEqual(settings.syncedStorage.keys(), ['synced-setting']);\n });\n\n it('keeps kebab case settings as is', () => {\n const versionController = new VersionController();\n settings.globalStorage.set('setting', '123');\n settings.localStorage.set('another-setting', '456');\n\n versionController.updateVersionFrom36To37();\n\n assert.deepEqual(settings.globalStorage.keys(), ['setting']);\n assert.strictEqual(settings.globalStorage.get('setting'), '123');\n assert.strictEqual(settings.localStorage.get('another-setting'), '456');\n });\n\n it('update data grid column weights value', () => {\n const versionController = new VersionController();\n settings.globalStorage.set('dataGrid-foo-columnWeights', JSON.stringify({\n columnOne: 1,\n columnTwo: 2,\n }));\n\n versionController.updateVersionFrom36To37();\n\n const setting = settings.createSetting('data-grid-foo-column-weights', {});\n\n assert.deepEqual(setting.get(), {'column-one': 1, 'column-two': 2});\n });\n\n it('update view manager settings values', () => {\n const versionController = new VersionController();\n settings.globalStorage.set('viewsLocationOverride', JSON.stringify({\n somePanel: 'main',\n other_panel: 'drawer',\n }));\n settings.globalStorage.set('closeableTabs', JSON.stringify({\n somePanel: false,\n other_panel: true,\n }));\n settings.globalStorage.set('main-tabOrder', JSON.stringify({\n somePanel: 2,\n other_panel: 1,\n }));\n settings.globalStorage.set('main-selectedTab', JSON.stringify('somePanel'));\n\n versionController.updateVersionFrom36To37();\n\n assert.deepEqual(\n settings.createSetting('views-location-override', {}).get(), {'some-panel': 'main', 'other-panel': 'drawer'});\n assert.deepEqual(settings.createSetting('closeable-tabs', {}).get(), {'some-panel': false, 'other-panel': true});\n assert.deepEqual(settings.createSetting('main-tab-order', {}).get(), {'some-panel': 2, 'other-panel': 1});\n assert.deepEqual(settings.createSetting('main-selected-tab', '').get(), 'some-panel');\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"Settings.test.js","sourceRoot":"","sources":["../../../../../../front_end/core/common/Settings.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2019 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from './common.js';\n\nconst SettingsStorage = Common.Settings.SettingsStorage;\nconst VersionController = Common.Settings.VersionController;\n\nclass MockStore implements Common.Settings.SettingsBackingStore {\n #store = new Map();\n register() {\n }\n set(key: string, value: string) {\n this.#store.set(key, value);\n }\n get(key: string) {\n return this.#store.get(key);\n }\n remove(key: string) {\n this.#store.delete(key);\n }\n clear() {\n this.#store.clear();\n }\n}\n\ndescribe('SettingsStorage class', () => {\n it('is able to set a name', () => {\n const settingsStorage = new SettingsStorage({});\n settingsStorage.set('Test Name', 'Test Value');\n assert.strictEqual(settingsStorage.get('Test Name'), 'Test Value', 'Name was not retrieve correctly');\n });\n\n it('is able to check if a name that it has exists', () => {\n const settingsStorage = new SettingsStorage({});\n settingsStorage.set('Test Name', 'Test Value');\n assert.isTrue(settingsStorage.has('Test Name'), 'the class should have that name');\n });\n\n it('is able to check if a name that it does not have exists', () => {\n const settingsStorage = new SettingsStorage({});\n assert.isFalse(settingsStorage.has('Test Name'), 'the class should not have that name');\n });\n\n it('is able to remove a name', () => {\n const settingsStorage = new SettingsStorage({});\n settingsStorage.set('Test Name', 'Test Value');\n settingsStorage.remove('Test Name');\n assert.isFalse(settingsStorage.has('Test Name'), 'the class should not have that name');\n });\n\n it('is able to remove all names', () => {\n const settingsStorage = new SettingsStorage({});\n settingsStorage.set('Test Name 1', 'Test Value 1');\n settingsStorage.set('Test Name 2', 'Test Value 2');\n settingsStorage.removeAll();\n assert.isFalse(settingsStorage.has('Test Name 1'), 'the class should not have any names');\n assert.isFalse(settingsStorage.has('Test Name 2'), 'the class should not have any names');\n });\n\n describe('forceGet', () => {\n it('returns the value of the backing store, not the cached one', async () => {\n const mockStore = new MockStore();\n const settingsStorage = new SettingsStorage({}, mockStore);\n settingsStorage.set('test', 'value');\n\n mockStore.set('test', 'changed');\n\n assert.strictEqual(await settingsStorage.forceGet('test'), 'changed');\n assert.strictEqual(await settingsStorage.forceGet('test'), 'changed');\n });\n it('updates the cached value of a SettingsStorage', async () => {\n const mockStore = new MockStore();\n const settingsStorage = new SettingsStorage({}, mockStore);\n settingsStorage.set('test', 'value');\n mockStore.set('test', 'changed');\n assert.strictEqual(settingsStorage.get('test'), 'value');\n\n await settingsStorage.forceGet('test');\n\n assert.strictEqual(settingsStorage.get('test'), 'changed');\n });\n it('leaves the cached value alone if the backing store has the same value', async () => {\n const mockStore = new MockStore();\n const settingsStorage = new SettingsStorage({}, mockStore);\n\n mockStore.set('test', 'value');\n settingsStorage.set('test', 'value');\n\n assert.strictEqual(mockStore.get('test'), 'value');\n assert.strictEqual(await settingsStorage.forceGet('test'), 'value');\n assert.strictEqual(mockStore.get('test'), 'value');\n assert.strictEqual(await settingsStorage.forceGet('test'), 'value');\n });\n });\n});\n\ndescribe('Settings instance', () => {\n afterEach(() => {\n Common.Settings.Settings.removeInstance();\n Common.Settings.resetSettings(); // Clear SettingsRegistrations.\n });\n\n it('can be instantiated in a test', () => {\n const dummyStorage = new SettingsStorage({});\n\n const settings = Common.Settings.Settings.instance({\n forceNew: true,\n syncedStorage: dummyStorage,\n globalStorage: dummyStorage,\n localStorage: dummyStorage,\n });\n\n assert.isOk(settings);\n });\n\n it('throws when constructed without storage', () => {\n assert.throws(() => Common.Settings.Settings.instance());\n assert.throws(\n () => Common.Settings.Settings.instance(\n {forceNew: true, syncedStorage: null, globalStorage: null, localStorage: null}));\n });\n\n it('stores synced settings in the correct storage', () => {\n const syncedStorage = new SettingsStorage({});\n const dummyStorage = new SettingsStorage({});\n Common.Settings.registerSettingExtension({\n settingName: 'static-synced-setting',\n settingType: Common.Settings.SettingType.BOOLEAN,\n defaultValue: false,\n storageType: Common.Settings.SettingStorageType.SYNCED,\n });\n const settings = Common.Settings.Settings.instance(\n {forceNew: true, syncedStorage, globalStorage: dummyStorage, localStorage: dummyStorage});\n\n const dynamicSetting: Common.Settings.Setting =\n settings.createSetting('dynamic-synced-setting', 'default val', Common.Settings.SettingStorageType.SYNCED);\n dynamicSetting.set('foo value');\n const staticSetting: Common.Settings.Setting = settings.moduleSetting('static-synced-setting');\n staticSetting.set(true);\n\n assert.isFalse(dummyStorage.has('dynamic-synced-setting'));\n assert.isFalse(dummyStorage.has('static-synced-setting'));\n assert.strictEqual(syncedStorage.get('dynamic-synced-setting'), '\"foo value\"');\n assert.strictEqual(syncedStorage.get('static-synced-setting'), 'true');\n });\n\n it('registers settings with the backing store when creating them', () => {\n const registeredSettings = new Set();\n const mockBackingStore: Common.Settings.SettingsBackingStore = {\n ...Common.Settings.NOOP_STORAGE,\n register: (name: string) => registeredSettings.add(name),\n };\n const storage = new SettingsStorage({}, mockBackingStore, '__prefix__.');\n Common.Settings.registerSettingExtension({\n settingName: 'static-global-setting',\n settingType: Common.Settings.SettingType.BOOLEAN,\n defaultValue: false,\n storageType: Common.Settings.SettingStorageType.GLOBAL,\n });\n\n const settings = Common.Settings.Settings.instance(\n {forceNew: true, syncedStorage: storage, globalStorage: storage, localStorage: storage});\n settings.createSetting('dynamic-local-setting', 42, Common.Settings.SettingStorageType.LOCAL);\n settings.createSetting('dynamic-synced-setting', 'foo', Common.Settings.SettingStorageType.SYNCED);\n\n assert.isTrue(registeredSettings.has('__prefix__.static-global-setting'));\n assert.isTrue(registeredSettings.has('__prefix__.dynamic-local-setting'));\n assert.isTrue(registeredSettings.has('__prefix__.dynamic-synced-setting'));\n });\n\n describe('forceGet', () => {\n it('triggers a setting changed event in case the value in the backing store got updated and we update the cached value',\n async () => {\n const mockStore = new MockStore();\n const settingsStorage = new SettingsStorage({}, mockStore);\n mockStore.set('test', '\"old\"');\n const settings = Common.Settings.Settings.instance({\n forceNew: true,\n syncedStorage: settingsStorage,\n globalStorage: settingsStorage,\n localStorage: settingsStorage,\n });\n const testSetting: Common.Settings.Setting =\n settings.createSetting('test', 'default val', Common.Settings.SettingStorageType.GLOBAL);\n const changes: string[] = [];\n testSetting.addChangeListener((event: Common.EventTarget.EventTargetEvent) => {\n changes.push(event.data);\n });\n mockStore.set('test', '\"new\"');\n assert.strictEqual(await testSetting.forceGet(), 'new');\n assert.deepEqual(changes, ['new']);\n assert.strictEqual(mockStore.get('test'), '\"new\"');\n assert.strictEqual(await settingsStorage.forceGet('test'), '\"new\"');\n assert.strictEqual(await testSetting.forceGet(), 'new');\n });\n });\n\n it('getIfNotDisabled returns the setting\\'s value only if the setting is not disabled', async () => {\n const registeredSettings = new Set();\n const mockBackingStore: Common.Settings.SettingsBackingStore = {\n ...Common.Settings.NOOP_STORAGE,\n register: (name: string) => registeredSettings.add(name),\n };\n const storage = new SettingsStorage({}, mockBackingStore, '__prefix__.');\n const settings = Common.Settings.Settings.instance(\n {forceNew: true, syncedStorage: storage, globalStorage: storage, localStorage: storage});\n const testSetting = settings.createSetting('test-setting', 'some value');\n assert.strictEqual(testSetting.getIfNotDisabled(), 'some value');\n\n testSetting.setDisabled(true);\n assert.isUndefined(testSetting.getIfNotDisabled());\n\n testSetting.setDisabled(false);\n assert.strictEqual(testSetting.getIfNotDisabled(), 'some value');\n });\n});\n\ndescribe('VersionController', () => {\n let settings: Common.Settings.Settings;\n let syncedStorage: Common.Settings.SettingsStorage;\n let globalStorage: Common.Settings.SettingsStorage;\n let localStorage: Common.Settings.SettingsStorage;\n\n beforeEach(() => {\n const mockStore = new MockStore();\n syncedStorage = new Common.Settings.SettingsStorage({}, mockStore);\n globalStorage = new Common.Settings.SettingsStorage({}, mockStore);\n localStorage = new Common.Settings.SettingsStorage({}, mockStore);\n settings = Common.Settings.Settings.instance({\n forceNew: true,\n syncedStorage,\n globalStorage,\n localStorage,\n });\n });\n\n afterEach(() => {\n Common.Settings.Settings.removeInstance();\n });\n\n describe('updateVersion', () => {\n it('initializes version settings with the current version if the setting doesn\\'t exist yet', () => {\n assert.isFalse(globalStorage.has(VersionController.GLOBAL_VERSION_SETTING_NAME));\n assert.isFalse(syncedStorage.has(VersionController.SYNCED_VERSION_SETTING_NAME));\n assert.isFalse(localStorage.has(VersionController.LOCAL_VERSION_SETTING_NAME));\n\n new VersionController().updateVersion();\n\n const currentVersion = VersionController.CURRENT_VERSION.toString();\n assert.strictEqual(globalStorage.get(VersionController.GLOBAL_VERSION_SETTING_NAME), currentVersion);\n assert.strictEqual(syncedStorage.get(VersionController.SYNCED_VERSION_SETTING_NAME), currentVersion);\n assert.strictEqual(localStorage.get(VersionController.LOCAL_VERSION_SETTING_NAME), currentVersion);\n });\n\n function spyAllUpdateMethods(versionController: Common.Settings.VersionController) {\n const spies: Array> = [];\n for (let i = 0; i < VersionController.CURRENT_VERSION; ++i) {\n spies.push(\n sinon.spy(versionController, `updateVersionFrom${i}To${i + 1}` as keyof Common.Settings.VersionController));\n }\n assert.lengthOf(spies, VersionController.CURRENT_VERSION);\n return spies;\n }\n\n it('does not run any update* methods if no version setting exist yet', () => {\n const versionController = new VersionController();\n const spies = spyAllUpdateMethods(versionController);\n\n versionController.updateVersion();\n\n for (const spy of spies) {\n assert.isFalse(spy.called);\n }\n });\n\n it('does not run any update* methods if all version settings are already current', () => {\n const currentVersion = VersionController.CURRENT_VERSION.toString();\n globalStorage.set(VersionController.GLOBAL_VERSION_SETTING_NAME, currentVersion);\n syncedStorage.set(VersionController.SYNCED_VERSION_SETTING_NAME, currentVersion);\n localStorage.set(VersionController.LOCAL_VERSION_SETTING_NAME, currentVersion);\n const versionController = new VersionController();\n const spies = spyAllUpdateMethods(versionController);\n\n versionController.updateVersion();\n\n for (const spy of spies) {\n assert.isFalse(spy.called);\n }\n });\n\n it('runs correct update* methods if the local bucket lags behind', () => {\n const currentVersion = VersionController.CURRENT_VERSION.toString();\n const localVersion = (VersionController.CURRENT_VERSION - 3).toString();\n globalStorage.set(VersionController.GLOBAL_VERSION_SETTING_NAME, currentVersion);\n syncedStorage.set(VersionController.SYNCED_VERSION_SETTING_NAME, currentVersion);\n localStorage.set(VersionController.LOCAL_VERSION_SETTING_NAME, localVersion);\n const versionController = new VersionController();\n const spies = spyAllUpdateMethods(versionController);\n\n versionController.updateVersion();\n\n const expectedUncalledSpies = spies.slice(0, -3);\n for (const spy of expectedUncalledSpies) {\n assert.isFalse(spy.called);\n }\n\n const expectedCalledSpies = spies.slice(-3);\n for (const spy of expectedCalledSpies) {\n assert.isTrue(spy.called);\n }\n });\n\n it('runs correct update* methods if the synced bucket runs ahead', () => {\n const currentVersion = VersionController.CURRENT_VERSION.toString();\n const oldVersion = (VersionController.CURRENT_VERSION - 1).toString();\n globalStorage.set(VersionController.GLOBAL_VERSION_SETTING_NAME, oldVersion);\n syncedStorage.set(VersionController.SYNCED_VERSION_SETTING_NAME, currentVersion);\n localStorage.set(VersionController.LOCAL_VERSION_SETTING_NAME, oldVersion);\n const versionController = new VersionController();\n const spies = spyAllUpdateMethods(versionController);\n\n versionController.updateVersion();\n\n const expectedUncalledSpies = spies.slice(0, -1);\n for (const spy of expectedUncalledSpies) {\n assert.isFalse(spy.called);\n }\n\n const expectedCalledSpies = spies.slice(-1);\n for (const spy of expectedCalledSpies) {\n assert.isTrue(spy.called);\n }\n });\n });\n\n describe('updateVersionFrom31To32', () => {\n it('correctly adds resourceTypeName to breakpoints', () => {\n const versionController = new VersionController();\n const breakpointsSetting = settings.createLocalSetting('breakpoints', [\n {url: 'webpack:///src/foo.ts', lineNumber: 4, condition: '', enabled: false},\n {url: 'foo.js', lineNumber: 1, columnNumber: 42, condition: 'false', enabled: true},\n ]);\n versionController.updateVersionFrom31To32();\n const breakpoints = breakpointsSetting.get();\n assert.lengthOf(breakpoints, 2);\n assert.propertyVal(breakpoints[0], 'url', 'webpack:///src/foo.ts');\n assert.propertyVal(breakpoints[0], 'resourceTypeName', 'script');\n assert.propertyVal(breakpoints[0], 'lineNumber', 4);\n assert.notProperty(breakpoints[0], 'columnNumber');\n assert.propertyVal(breakpoints[0], 'condition', '');\n assert.propertyVal(breakpoints[0], 'enabled', false);\n assert.propertyVal(breakpoints[1], 'url', 'foo.js');\n assert.propertyVal(breakpoints[1], 'resourceTypeName', 'script');\n assert.propertyVal(breakpoints[1], 'lineNumber', 1);\n assert.propertyVal(breakpoints[1], 'columnNumber', 42);\n assert.propertyVal(breakpoints[1], 'condition', 'false');\n assert.propertyVal(breakpoints[1], 'enabled', true);\n });\n });\n\n describe('updateVersionFrom32To33', () => {\n it('correctly discards previously viewed files without url properties', () => {\n const versionController = new VersionController();\n const previouslyViewedFilesSetting = settings.createLocalSetting('previouslyViewedFiles', [\n {url: 'http://localhost:3000', scrollLineNumber: 1},\n {scrollLineNumber: 1},\n {},\n {url: 'webpack:///src/foo.ts'},\n ]);\n versionController.updateVersionFrom32To33();\n const previouslyViewedFiles = previouslyViewedFilesSetting.get();\n assert.lengthOf(previouslyViewedFiles, 2);\n assert.propertyVal(previouslyViewedFiles[0], 'url', 'http://localhost:3000');\n assert.notProperty(previouslyViewedFiles[0], 'selectionRange');\n assert.propertyVal(previouslyViewedFiles[0], 'scrollLineNumber', 1);\n assert.propertyVal(previouslyViewedFiles[1], 'url', 'webpack:///src/foo.ts');\n assert.notProperty(previouslyViewedFiles[1], 'selectionRange');\n assert.notProperty(previouslyViewedFiles[1], 'scrollLineNumber');\n });\n\n it('correctly adds resourceTypeName to previously viewed files', () => {\n const versionController = new VersionController();\n const previouslyViewedFilesSetting = settings.createLocalSetting('previouslyViewedFiles', [\n {url: 'http://localhost:3000', scrollLineNumber: 1},\n {url: 'webpack:///src/foo.ts'},\n ]);\n versionController.updateVersionFrom32To33();\n const previouslyViewedFiles = previouslyViewedFilesSetting.get();\n assert.lengthOf(previouslyViewedFiles, 2);\n assert.propertyVal(previouslyViewedFiles[0], 'url', 'http://localhost:3000');\n assert.propertyVal(previouslyViewedFiles[0], 'resourceTypeName', 'script');\n assert.notProperty(previouslyViewedFiles[0], 'selectionRange');\n assert.propertyVal(previouslyViewedFiles[0], 'scrollLineNumber', 1);\n assert.propertyVal(previouslyViewedFiles[1], 'url', 'webpack:///src/foo.ts');\n assert.propertyVal(previouslyViewedFiles[1], 'resourceTypeName', 'script');\n assert.notProperty(previouslyViewedFiles[1], 'selectionRange');\n assert.notProperty(previouslyViewedFiles[1], 'scrollLineNumber');\n });\n });\n\n describe('updateVersionFrom33To34', () => {\n it('correctly adds isLogpoint to breakpoints', () => {\n const versionController = new VersionController();\n const breakpointsSetting = settings.createLocalSetting('breakpoints', [\n {\n url: 'webpack:///src/foo.ts',\n lineNumber: 4,\n resourceTypeName: 'script',\n condition: '/** DEVTOOLS_LOGPOINT */ console.log(foo.property)',\n enabled: true,\n },\n {\n url: 'foo.js',\n lineNumber: 1,\n columnNumber: 42,\n resourceTypeName: 'script',\n condition: 'x === 42',\n enabled: true,\n },\n {url: 'bar.js', lineNumber: 5, columnNumber: 1, resourceTypeName: 'script', condition: '', enabled: true},\n ]);\n\n versionController.updateVersionFrom33To34();\n const breakpoints = breakpointsSetting.get();\n\n assert.propertyVal(breakpoints[0], 'isLogpoint', true);\n assert.propertyVal(breakpoints[1], 'isLogpoint', false);\n assert.propertyVal(breakpoints[2], 'isLogpoint', false);\n });\n });\n\n describe('updateVersionFrom34To35', () => {\n it('removes the logpoint prefix/suffix from logpoints', () => {\n const versionController = new VersionController();\n const breakpointsSetting =\n settings.createLocalSetting('breakpoints', [{\n url: 'webpack:///src/foo.ts',\n lineNumber: 4,\n resourceTypeName: 'script',\n condition: '/** DEVTOOLS_LOGPOINT */ console.log(foo.property)',\n enabled: true,\n isLogpoint: true,\n }]);\n\n versionController.updateVersionFrom34To35();\n\n const breakpoints = breakpointsSetting.get();\n assert.lengthOf(breakpoints, 1);\n assert.propertyVal(breakpoints[0], 'condition', 'foo.property');\n });\n\n it('leaves conditional breakpoints alone', () => {\n const versionController = new VersionController();\n const breakpointsSetting = settings.createLocalSetting('breakpoints', [{\n url: 'webpack:///src/foo.ts',\n lineNumber: 4,\n resourceTypeName: 'script',\n condition: 'x === 42',\n enabled: true,\n isLogpoint: false,\n }]);\n\n versionController.updateVersionFrom34To35();\n\n const breakpoints = breakpointsSetting.get();\n assert.lengthOf(breakpoints, 1);\n assert.propertyVal(breakpoints[0], 'condition', 'x === 42');\n });\n });\n\n describe('updateVersionFrom35To36', () => {\n it('update showThirdPartyIssues setting value to true', () => {\n const versionController = new VersionController();\n const showThirdPartyIssuesSetting = settings.createLocalSetting('showThirdPartyIssues', false);\n versionController.updateVersionFrom35To36();\n assert.isTrue(showThirdPartyIssuesSetting.get());\n });\n });\n\n describe('updateVersionFrom36To37', () => {\n it('updates all keys to kebab case', () => {\n const versionController = new VersionController();\n settings.globalStorage.set('globalSetting1', '');\n settings.globalStorage.set('globalSetting2', '');\n settings.localStorage.set('localSetting', '');\n settings.syncedStorage.set('syncedSetting', '');\n\n versionController.updateVersionFrom36To37();\n\n assert.deepEqual(settings.globalStorage.keys(), ['global-setting-1', 'global-setting-2']);\n assert.deepEqual(settings.localStorage.keys(), ['local-setting']);\n assert.deepEqual(settings.syncedStorage.keys(), ['synced-setting']);\n });\n\n it('keeps kebab case settings as is', () => {\n const versionController = new VersionController();\n settings.globalStorage.set('setting', '123');\n settings.localStorage.set('another-setting', '456');\n\n versionController.updateVersionFrom36To37();\n\n assert.deepEqual(settings.globalStorage.keys(), ['setting']);\n assert.strictEqual(settings.globalStorage.get('setting'), '123');\n assert.strictEqual(settings.localStorage.get('another-setting'), '456');\n });\n\n it('update data grid column weights value', () => {\n const versionController = new VersionController();\n settings.globalStorage.set('dataGrid-foo-columnWeights', JSON.stringify({\n columnOne: 1,\n columnTwo: 2,\n }));\n\n versionController.updateVersionFrom36To37();\n\n const setting = settings.createSetting('data-grid-foo-column-weights', {});\n\n assert.deepEqual(setting.get(), {'column-one': 1, 'column-two': 2});\n });\n\n it('update view manager settings values', () => {\n const versionController = new VersionController();\n settings.globalStorage.set('viewsLocationOverride', JSON.stringify({\n somePanel: 'main',\n other_panel: 'drawer',\n }));\n settings.globalStorage.set('closeableTabs', JSON.stringify({\n somePanel: false,\n other_panel: true,\n }));\n settings.globalStorage.set('main-tabOrder', JSON.stringify({\n somePanel: 2,\n other_panel: 1,\n }));\n settings.globalStorage.set('main-selectedTab', JSON.stringify('somePanel'));\n\n versionController.updateVersionFrom36To37();\n\n assert.deepEqual(\n settings.createSetting('views-location-override', {}).get(), {'some-panel': 'main', 'other-panel': 'drawer'});\n assert.deepEqual(settings.createSetting('closeable-tabs', {}).get(), {'some-panel': false, 'other-panel': true});\n assert.deepEqual(settings.createSetting('main-tab-order', {}).get(), {'some-panel': 2, 'other-panel': 1});\n assert.deepEqual(settings.createSetting('main-selected-tab', '').get(), 'some-panel');\n });\n });\n});\n\ndescribe('updateVersionFrom37To38', () => {\n let settings: Common.Settings.Settings;\n\n beforeEach(() => {\n const mockStore = new MockStore();\n const syncedStorage = new Common.Settings.SettingsStorage({}, mockStore);\n const globalStorage = new Common.Settings.SettingsStorage({}, mockStore);\n const localStorage = new Common.Settings.SettingsStorage({}, mockStore);\n\n Common.Settings.registerSettingExtension({\n settingName: 'console-insights-enabled',\n settingType: Common.Settings.SettingType.BOOLEAN,\n defaultValue: true,\n });\n\n settings = Common.Settings.Settings.instance({\n forceNew: true,\n syncedStorage,\n globalStorage,\n localStorage,\n });\n });\n\n afterEach(() => {\n Common.Settings.Settings.removeInstance();\n Common.Settings.resetSettings(); // Clear SettingsRegistrations.\n });\n\n it('disables console insights setting if onboarding not done', () => {\n const versionController = new VersionController();\n const consoleInsightsEnabled: Common.Settings.Setting = settings.moduleSetting('console-insights-enabled');\n consoleInsightsEnabled.set(true);\n const onboardingFinished = settings.createLocalSetting('console-insights-onboarding-finished', false);\n\n versionController.updateVersionFrom37To38();\n assert.isFalse(consoleInsightsEnabled.get());\n assert.isFalse(onboardingFinished.get());\n });\n\n it('preserves state if console insights disabled and not onboarded ', () => {\n const versionController = new VersionController();\n const consoleInsightsEnabled: Common.Settings.Setting = settings.moduleSetting('console-insights-enabled');\n consoleInsightsEnabled.set(false);\n const onboardingFinished = settings.createLocalSetting('console-insights-onboarding-finished', false);\n\n versionController.updateVersionFrom37To38();\n assert.isFalse(consoleInsightsEnabled.get());\n assert.isFalse(onboardingFinished.get());\n });\n\n it('preserves state if console insights enabled and onboarded', () => {\n const versionController = new VersionController();\n const consoleInsightsEnabled: Common.Settings.Setting = settings.moduleSetting('console-insights-enabled');\n consoleInsightsEnabled.set(true);\n const onboardingFinished = settings.createLocalSetting('console-insights-onboarding-finished', true);\n\n versionController.updateVersionFrom37To38();\n assert.isTrue(consoleInsightsEnabled.get());\n assert.isTrue(onboardingFinished.get());\n });\n\n it('resets onboarding if console insights setting is disabled', () => {\n const versionController = new VersionController();\n const consoleInsightsEnabled: Common.Settings.Setting = settings.moduleSetting('console-insights-enabled');\n consoleInsightsEnabled.set(false);\n const onboardingFinished = settings.createLocalSetting('console-insights-onboarding-finished', true);\n\n versionController.updateVersionFrom37To38();\n assert.isFalse(consoleInsightsEnabled.get());\n assert.isFalse(onboardingFinished.get());\n });\n});\n"]} \ No newline at end of file diff --git a/public/core/host/AidaClient.d.ts b/public/core/host/AidaClient.d.ts index 37a6997dc..a7abdaaf8 100644 --- a/public/core/host/AidaClient.d.ts +++ b/public/core/host/AidaClient.d.ts @@ -25,6 +25,7 @@ export declare enum ClientFeature { export declare enum UserTier { USER_TIER_UNSPECIFIED = 0, TESTERS = 1, + BETA = 2, PUBLIC = 3 } export interface AidaRequest { @@ -88,10 +89,14 @@ export declare const enum AidaAccessPreconditions { NO_INTERNET = "no-internet" } export declare const CLIENT_NAME = "CHROME_DEVTOOLS"; +export declare class AidaAbortError extends Error { +} export declare class AidaClient { static buildConsoleInsightsRequest(input: string): AidaRequest; static checkAccessPreconditions(): Promise; - fetch(request: AidaRequest): AsyncGenerator; + fetch(request: AidaRequest, options?: { + signal?: AbortSignal; + }): AsyncGenerator; registerClientEvent(clientEvent: AidaDoConversationClientEvent): Promise; } export declare function convertToUserTierEnum(userTier: string | undefined): UserTier; diff --git a/public/core/host/AidaClient.js b/public/core/host/AidaClient.js index 8d0a3d445..44c195499 100644 --- a/public/core/host/AidaClient.js +++ b/public/core/host/AidaClient.js @@ -34,6 +34,8 @@ export var UserTier; UserTier[UserTier["USER_TIER_UNSPECIFIED"] = 0] = "USER_TIER_UNSPECIFIED"; // Users who are internal testers. UserTier[UserTier["TESTERS"] = 1] = "TESTERS"; + // Users who are early adopters. + UserTier[UserTier["BETA"] = 2] = "BETA"; // Users in the general public. UserTier[UserTier["PUBLIC"] = 3] = "PUBLIC"; })(UserTier || (UserTier = {})); @@ -47,6 +49,8 @@ export var RecitationAction; })(RecitationAction || (RecitationAction = {})); export const CLIENT_NAME = 'CHROME_DEVTOOLS'; const CODE_CHUNK_SEPARATOR = '\n`````\n'; +export class AidaAbortError extends Error { +} export class AidaClient { static buildConsoleInsightsRequest(input) { const request = { @@ -91,12 +95,15 @@ export class AidaClient { } return "available" /* AidaAccessPreconditions.AVAILABLE */; } - async *fetch(request) { + async *fetch(request, options) { if (!InspectorFrontendHostInstance.doAidaConversation) { throw new Error('doAidaConversation is not available'); } const stream = (() => { let { promise, resolve, reject } = Promise.withResolvers(); + options?.signal?.addEventListener('abort', () => { + reject(new AidaAbortError()); + }); return { write: async (data) => { resolve(data); @@ -218,10 +225,12 @@ export function convertToUserTierEnum(userTier) { switch (userTier) { case 'TESTERS': return UserTier.TESTERS; + case 'BETA': + return UserTier.BETA; case 'PUBLIC': return UserTier.PUBLIC; } } - return UserTier.TESTERS; + return UserTier.BETA; } //# sourceMappingURL=AidaClient.js.map \ No newline at end of file diff --git a/public/core/host/AidaClient.js.map b/public/core/host/AidaClient.js.map index af7182845..3dbc511e0 100644 --- a/public/core/host/AidaClient.js.map +++ b/public/core/host/AidaClient.js.map @@ -1 +1 @@ -{"version":3,"file":"AidaClient.js","sourceRoot":"","sources":["../../../../../../front_end/core/host/AidaClient.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../common/common.js';\n\nimport {InspectorFrontendHostInstance} from './InspectorFrontendHost.js';\nimport {type AidaClientResult, type SyncInformation} from './InspectorFrontendHostAPI.js';\nimport {bindOutputStream} from './ResourceLoader.js';\n\nexport enum Entity {\n UNKNOWN = 0,\n USER = 1,\n SYSTEM = 2,\n}\n\nexport const enum Rating {\n POSITIVE = 'POSITIVE',\n NEGATIVE = 'NEGATIVE',\n}\n\nexport interface Chunk {\n text: string;\n entity: Entity;\n}\n\nexport enum FunctionalityType {\n // Unspecified functionality type.\n FUNCTIONALITY_TYPE_UNSPECIFIED = 0,\n // The generic AI chatbot functionality.\n CHAT = 1,\n // The explain error functionality.\n EXPLAIN_ERROR = 2,\n}\n\nexport enum ClientFeature {\n // Unspecified client feature.\n CLIENT_FEATURE_UNSPECIFIED = 0,\n // Chrome console insights feature.\n CHROME_CONSOLE_INSIGHTS = 1,\n // Chrome freestyler.\n CHROME_FREESTYLER = 2,\n}\n\nexport enum UserTier {\n // Unspecified user tier.\n USER_TIER_UNSPECIFIED = 0,\n // Users who are internal testers.\n TESTERS = 1,\n // Users in the general public.\n PUBLIC = 3,\n}\n\nexport interface AidaRequest {\n input: string;\n preamble?: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n chat_history?: Chunk[];\n client: string;\n options?: {\n temperature?: Number,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n model_id?: string,\n };\n metadata?: {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n disable_user_content_logging: boolean,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n string_session_id?: string,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n user_tier?: UserTier,\n };\n // eslint-disable-next-line @typescript-eslint/naming-convention\n functionality_type?: FunctionalityType;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n client_feature?: ClientFeature;\n}\n\nexport interface AidaDoConversationClientEvent {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n corresponding_aida_rpc_global_id: number;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n disable_user_content_logging: boolean;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n do_conversation_client_event: {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n user_feedback: {\n sentiment?: Rating,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n user_input?: {\n comment?: string,\n },\n },\n };\n}\n\nexport enum RecitationAction {\n ACTION_UNSPECIFIED = 'ACTION_UNSPECIFIED',\n CITE = 'CITE',\n BLOCK = 'BLOCK',\n NO_ACTION = 'NO_ACTION',\n EXEMPT_FOUND_IN_PROMPT = 'EXEMPT_FOUND_IN_PROMPT',\n}\n\nexport interface Citation {\n startIndex: number;\n endIndex: number;\n url: string;\n}\n\nexport interface AttributionMetadata {\n attributionAction: RecitationAction;\n citations: Citation[];\n}\n\nexport interface AidaResponseMetadata {\n rpcGlobalId?: number;\n attributionMetadata?: AttributionMetadata[];\n}\n\nexport interface AidaResponse {\n explanation: string;\n metadata: AidaResponseMetadata;\n completed: boolean;\n}\n\nexport const enum AidaAccessPreconditions {\n AVAILABLE = 'available',\n NO_ACCOUNT_EMAIL = 'no-account-email',\n NO_ACTIVE_SYNC = 'no-active-sync',\n NO_INTERNET = 'no-internet',\n}\n\nexport const CLIENT_NAME = 'CHROME_DEVTOOLS';\n\nconst CODE_CHUNK_SEPARATOR = '\\n`````\\n';\n\nexport class AidaClient {\n static buildConsoleInsightsRequest(input: string): AidaRequest {\n const request: AidaRequest = {\n input,\n client: CLIENT_NAME,\n functionality_type: FunctionalityType.EXPLAIN_ERROR,\n client_feature: ClientFeature.CHROME_CONSOLE_INSIGHTS,\n };\n const config = Common.Settings.Settings.instance().getHostConfig();\n let temperature = NaN;\n let modelId = '';\n if (config.devToolsConsoleInsights?.enabled) {\n temperature = config.devToolsConsoleInsights.temperature || 0;\n modelId = config.devToolsConsoleInsights.modelId || '';\n }\n const disallowLogging = config.aidaAvailability?.disallowLogging ?? true;\n\n if (!isNaN(temperature)) {\n request.options ??= {};\n request.options.temperature = temperature;\n }\n if (modelId) {\n request.options ??= {};\n request.options.model_id = modelId;\n }\n if (disallowLogging) {\n request.metadata = {\n disable_user_content_logging: true,\n };\n }\n return request;\n }\n\n static async checkAccessPreconditions(): Promise {\n if (!navigator.onLine) {\n return AidaAccessPreconditions.NO_INTERNET;\n }\n\n const syncInfo = await new Promise(\n resolve => InspectorFrontendHostInstance.getSyncInformation(syncInfo => resolve(syncInfo)));\n if (!syncInfo.accountEmail) {\n return AidaAccessPreconditions.NO_ACCOUNT_EMAIL;\n }\n\n if (!syncInfo.isSyncActive) {\n return AidaAccessPreconditions.NO_ACTIVE_SYNC;\n }\n\n return AidaAccessPreconditions.AVAILABLE;\n }\n\n async * fetch(request: AidaRequest): AsyncGenerator {\n if (!InspectorFrontendHostInstance.doAidaConversation) {\n throw new Error('doAidaConversation is not available');\n }\n const stream = (() => {\n let {promise, resolve, reject} = Promise.withResolvers();\n return {\n write: async(data: string): Promise => {\n resolve(data);\n ({promise, resolve, reject} = Promise.withResolvers());\n },\n close: async(): Promise => {\n resolve(null);\n },\n read: (): Promise => {\n return promise;\n },\n fail: (e: Error) => reject(e),\n };\n })();\n const streamId = bindOutputStream(stream);\n InspectorFrontendHostInstance.doAidaConversation(JSON.stringify(request), streamId, result => {\n if (result.statusCode === 403) {\n stream.fail(new Error('Server responded: permission denied'));\n } else if (result.error) {\n stream.fail(new Error(`Cannot send request: ${result.error} ${result.detail || ''}`));\n } else if (result.statusCode !== 200) {\n stream.fail(new Error(`Request failed: ${JSON.stringify(result)}`));\n } else {\n void stream.close();\n }\n });\n let chunk;\n const text = [];\n let inCodeChunk = false;\n const metadata: AidaResponseMetadata = {rpcGlobalId: 0};\n while ((chunk = await stream.read())) {\n let textUpdated = false;\n // The AIDA response is a JSON array of objects, split at the object\n // boundary. Therefore each chunk may start with `[` or `,` and possibly\n // followed by `]`. Each chunk may include one or more objects, so we\n // make sure that each chunk becomes a well-formed JSON array when we\n // parse it by adding `[` and `]` and removing `,` where appropriate.\n if (!chunk.length) {\n continue;\n }\n if (chunk.startsWith(',')) {\n chunk = chunk.slice(1);\n }\n if (!chunk.startsWith('[')) {\n chunk = '[' + chunk;\n }\n if (!chunk.endsWith(']')) {\n chunk = chunk + ']';\n }\n let results;\n try {\n results = JSON.parse(chunk);\n } catch (error) {\n throw new Error('Cannot parse chunk: ' + chunk, {cause: error});\n }\n\n for (const result of results) {\n if ('metadata' in result) {\n metadata.rpcGlobalId = result.metadata.rpcGlobalId;\n if ('attributionMetadata' in result.metadata) {\n if (!metadata.attributionMetadata) {\n metadata.attributionMetadata = [];\n }\n metadata.attributionMetadata.push(result.metadata.attributionMetadata);\n }\n }\n if ('textChunk' in result) {\n if (inCodeChunk) {\n text.push(CODE_CHUNK_SEPARATOR);\n inCodeChunk = false;\n }\n text.push(result.textChunk.text);\n textUpdated = true;\n } else if ('codeChunk' in result) {\n if (!inCodeChunk) {\n text.push(CODE_CHUNK_SEPARATOR);\n inCodeChunk = true;\n }\n text.push(result.codeChunk.code);\n textUpdated = true;\n } else if ('error' in result) {\n throw new Error(`Server responded: ${JSON.stringify(result)}`);\n } else {\n throw new Error('Unknown chunk result');\n }\n }\n if (textUpdated) {\n yield {\n explanation: text.join('') + (inCodeChunk ? CODE_CHUNK_SEPARATOR : ''),\n metadata,\n completed: false,\n };\n }\n }\n yield {\n explanation: text.join('') + (inCodeChunk ? CODE_CHUNK_SEPARATOR : ''),\n metadata,\n completed: true,\n };\n }\n\n registerClientEvent(clientEvent: AidaDoConversationClientEvent): Promise {\n const {promise, resolve} = Promise.withResolvers();\n InspectorFrontendHostInstance.registerAidaClientEvent(\n JSON.stringify({\n client: CLIENT_NAME,\n event_time: new Date().toISOString(),\n ...clientEvent,\n }),\n resolve,\n );\n\n return promise;\n }\n}\n\nexport function convertToUserTierEnum(userTier: string|undefined): UserTier {\n if (userTier) {\n switch (userTier) {\n case 'TESTERS':\n return UserTier.TESTERS;\n case 'PUBLIC':\n return UserTier.PUBLIC;\n }\n }\n return UserTier.TESTERS;\n}\n"]} \ No newline at end of file +{"version":3,"file":"AidaClient.js","sourceRoot":"","sources":["../../../../../../front_end/core/host/AidaClient.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../common/common.js';\n\nimport {InspectorFrontendHostInstance} from './InspectorFrontendHost.js';\nimport {type AidaClientResult, type SyncInformation} from './InspectorFrontendHostAPI.js';\nimport {bindOutputStream} from './ResourceLoader.js';\n\nexport enum Entity {\n UNKNOWN = 0,\n USER = 1,\n SYSTEM = 2,\n}\n\nexport const enum Rating {\n POSITIVE = 'POSITIVE',\n NEGATIVE = 'NEGATIVE',\n}\n\nexport interface Chunk {\n text: string;\n entity: Entity;\n}\n\nexport enum FunctionalityType {\n // Unspecified functionality type.\n FUNCTIONALITY_TYPE_UNSPECIFIED = 0,\n // The generic AI chatbot functionality.\n CHAT = 1,\n // The explain error functionality.\n EXPLAIN_ERROR = 2,\n}\n\nexport enum ClientFeature {\n // Unspecified client feature.\n CLIENT_FEATURE_UNSPECIFIED = 0,\n // Chrome console insights feature.\n CHROME_CONSOLE_INSIGHTS = 1,\n // Chrome freestyler.\n CHROME_FREESTYLER = 2,\n}\n\nexport enum UserTier {\n // Unspecified user tier.\n USER_TIER_UNSPECIFIED = 0,\n // Users who are internal testers.\n TESTERS = 1,\n // Users who are early adopters.\n BETA = 2,\n // Users in the general public.\n PUBLIC = 3,\n}\n\nexport interface AidaRequest {\n input: string;\n preamble?: string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n chat_history?: Chunk[];\n client: string;\n options?: {\n temperature?: Number,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n model_id?: string,\n };\n metadata?: {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n disable_user_content_logging: boolean,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n string_session_id?: string,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n user_tier?: UserTier,\n };\n // eslint-disable-next-line @typescript-eslint/naming-convention\n functionality_type?: FunctionalityType;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n client_feature?: ClientFeature;\n}\n\nexport interface AidaDoConversationClientEvent {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n corresponding_aida_rpc_global_id: number;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n disable_user_content_logging: boolean;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n do_conversation_client_event: {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n user_feedback: {\n sentiment?: Rating,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n user_input?: {\n comment?: string,\n },\n },\n };\n}\n\nexport enum RecitationAction {\n ACTION_UNSPECIFIED = 'ACTION_UNSPECIFIED',\n CITE = 'CITE',\n BLOCK = 'BLOCK',\n NO_ACTION = 'NO_ACTION',\n EXEMPT_FOUND_IN_PROMPT = 'EXEMPT_FOUND_IN_PROMPT',\n}\n\nexport interface Citation {\n startIndex: number;\n endIndex: number;\n url: string;\n}\n\nexport interface AttributionMetadata {\n attributionAction: RecitationAction;\n citations: Citation[];\n}\n\nexport interface AidaResponseMetadata {\n rpcGlobalId?: number;\n attributionMetadata?: AttributionMetadata[];\n}\n\nexport interface AidaResponse {\n explanation: string;\n metadata: AidaResponseMetadata;\n completed: boolean;\n}\n\nexport const enum AidaAccessPreconditions {\n AVAILABLE = 'available',\n NO_ACCOUNT_EMAIL = 'no-account-email',\n NO_ACTIVE_SYNC = 'no-active-sync',\n NO_INTERNET = 'no-internet',\n}\n\nexport const CLIENT_NAME = 'CHROME_DEVTOOLS';\n\nconst CODE_CHUNK_SEPARATOR = '\\n`````\\n';\n\nexport class AidaAbortError extends Error {}\n\nexport class AidaClient {\n static buildConsoleInsightsRequest(input: string): AidaRequest {\n const request: AidaRequest = {\n input,\n client: CLIENT_NAME,\n functionality_type: FunctionalityType.EXPLAIN_ERROR,\n client_feature: ClientFeature.CHROME_CONSOLE_INSIGHTS,\n };\n const config = Common.Settings.Settings.instance().getHostConfig();\n let temperature = NaN;\n let modelId = '';\n if (config.devToolsConsoleInsights?.enabled) {\n temperature = config.devToolsConsoleInsights.temperature || 0;\n modelId = config.devToolsConsoleInsights.modelId || '';\n }\n const disallowLogging = config.aidaAvailability?.disallowLogging ?? true;\n\n if (!isNaN(temperature)) {\n request.options ??= {};\n request.options.temperature = temperature;\n }\n if (modelId) {\n request.options ??= {};\n request.options.model_id = modelId;\n }\n if (disallowLogging) {\n request.metadata = {\n disable_user_content_logging: true,\n };\n }\n return request;\n }\n\n static async checkAccessPreconditions(): Promise {\n if (!navigator.onLine) {\n return AidaAccessPreconditions.NO_INTERNET;\n }\n\n const syncInfo = await new Promise(\n resolve => InspectorFrontendHostInstance.getSyncInformation(syncInfo => resolve(syncInfo)));\n if (!syncInfo.accountEmail) {\n return AidaAccessPreconditions.NO_ACCOUNT_EMAIL;\n }\n\n if (!syncInfo.isSyncActive) {\n return AidaAccessPreconditions.NO_ACTIVE_SYNC;\n }\n\n return AidaAccessPreconditions.AVAILABLE;\n }\n\n async * fetch(request: AidaRequest, options?: {signal?: AbortSignal}): AsyncGenerator {\n if (!InspectorFrontendHostInstance.doAidaConversation) {\n throw new Error('doAidaConversation is not available');\n }\n const stream = (() => {\n let {promise, resolve, reject} = Promise.withResolvers();\n options?.signal?.addEventListener('abort', () => {\n reject(new AidaAbortError());\n });\n return {\n write: async(data: string): Promise => {\n resolve(data);\n ({promise, resolve, reject} = Promise.withResolvers());\n },\n close: async(): Promise => {\n resolve(null);\n },\n read: (): Promise => {\n return promise;\n },\n fail: (e: Error) => reject(e),\n };\n })();\n const streamId = bindOutputStream(stream);\n InspectorFrontendHostInstance.doAidaConversation(JSON.stringify(request), streamId, result => {\n if (result.statusCode === 403) {\n stream.fail(new Error('Server responded: permission denied'));\n } else if (result.error) {\n stream.fail(new Error(`Cannot send request: ${result.error} ${result.detail || ''}`));\n } else if (result.statusCode !== 200) {\n stream.fail(new Error(`Request failed: ${JSON.stringify(result)}`));\n } else {\n void stream.close();\n }\n });\n let chunk;\n const text = [];\n let inCodeChunk = false;\n const metadata: AidaResponseMetadata = {rpcGlobalId: 0};\n while ((chunk = await stream.read())) {\n let textUpdated = false;\n // The AIDA response is a JSON array of objects, split at the object\n // boundary. Therefore each chunk may start with `[` or `,` and possibly\n // followed by `]`. Each chunk may include one or more objects, so we\n // make sure that each chunk becomes a well-formed JSON array when we\n // parse it by adding `[` and `]` and removing `,` where appropriate.\n if (!chunk.length) {\n continue;\n }\n if (chunk.startsWith(',')) {\n chunk = chunk.slice(1);\n }\n if (!chunk.startsWith('[')) {\n chunk = '[' + chunk;\n }\n if (!chunk.endsWith(']')) {\n chunk = chunk + ']';\n }\n let results;\n try {\n results = JSON.parse(chunk);\n } catch (error) {\n throw new Error('Cannot parse chunk: ' + chunk, {cause: error});\n }\n\n for (const result of results) {\n if ('metadata' in result) {\n metadata.rpcGlobalId = result.metadata.rpcGlobalId;\n if ('attributionMetadata' in result.metadata) {\n if (!metadata.attributionMetadata) {\n metadata.attributionMetadata = [];\n }\n metadata.attributionMetadata.push(result.metadata.attributionMetadata);\n }\n }\n if ('textChunk' in result) {\n if (inCodeChunk) {\n text.push(CODE_CHUNK_SEPARATOR);\n inCodeChunk = false;\n }\n text.push(result.textChunk.text);\n textUpdated = true;\n } else if ('codeChunk' in result) {\n if (!inCodeChunk) {\n text.push(CODE_CHUNK_SEPARATOR);\n inCodeChunk = true;\n }\n text.push(result.codeChunk.code);\n textUpdated = true;\n } else if ('error' in result) {\n throw new Error(`Server responded: ${JSON.stringify(result)}`);\n } else {\n throw new Error('Unknown chunk result');\n }\n }\n if (textUpdated) {\n yield {\n explanation: text.join('') + (inCodeChunk ? CODE_CHUNK_SEPARATOR : ''),\n metadata,\n completed: false,\n };\n }\n }\n yield {\n explanation: text.join('') + (inCodeChunk ? CODE_CHUNK_SEPARATOR : ''),\n metadata,\n completed: true,\n };\n }\n\n registerClientEvent(clientEvent: AidaDoConversationClientEvent): Promise {\n const {promise, resolve} = Promise.withResolvers();\n InspectorFrontendHostInstance.registerAidaClientEvent(\n JSON.stringify({\n client: CLIENT_NAME,\n event_time: new Date().toISOString(),\n ...clientEvent,\n }),\n resolve,\n );\n\n return promise;\n }\n}\n\nexport function convertToUserTierEnum(userTier: string|undefined): UserTier {\n if (userTier) {\n switch (userTier) {\n case 'TESTERS':\n return UserTier.TESTERS;\n case 'BETA':\n return UserTier.BETA;\n case 'PUBLIC':\n return UserTier.PUBLIC;\n }\n }\n return UserTier.BETA;\n}\n"]} \ No newline at end of file diff --git a/public/core/host/UserMetrics.d.ts b/public/core/host/UserMetrics.d.ts index efa495a8e..2e776c925 100644 --- a/public/core/host/UserMetrics.d.ts +++ b/public/core/host/UserMetrics.d.ts @@ -657,7 +657,8 @@ export declare enum DevtoolsExperiments { 'gen-ai-settings-panel' = 97, 'timeline-server-timings' = 98, 'timeline-layout-shift-details' = 99, - MAX_VALUE = 100 + 'extension-storage-viewer' = 100, + MAX_VALUE = 101 } export declare const enum ColorPickerOpenedFrom { SOURCES_PANEL = 0, diff --git a/public/core/host/UserMetrics.js b/public/core/host/UserMetrics.js index 85ade0c23..f721b9d2c 100644 --- a/public/core/host/UserMetrics.js +++ b/public/core/host/UserMetrics.js @@ -907,9 +907,10 @@ export var DevtoolsExperiments; DevtoolsExperiments[DevtoolsExperiments["gen-ai-settings-panel"] = 97] = "gen-ai-settings-panel"; DevtoolsExperiments[DevtoolsExperiments["timeline-server-timings"] = 98] = "timeline-server-timings"; DevtoolsExperiments[DevtoolsExperiments["timeline-layout-shift-details"] = 99] = "timeline-layout-shift-details"; + DevtoolsExperiments[DevtoolsExperiments["extension-storage-viewer"] = 100] = "extension-storage-viewer"; /* eslint-enable @typescript-eslint/naming-convention */ // Increment this when new experiments are added. - DevtoolsExperiments[DevtoolsExperiments["MAX_VALUE"] = 100] = "MAX_VALUE"; + DevtoolsExperiments[DevtoolsExperiments["MAX_VALUE"] = 101] = "MAX_VALUE"; })(DevtoolsExperiments || (DevtoolsExperiments = {})); // Update DevToolsIssuesPanelIssueExpanded from tools/metrics/histograms/enums.xml if new enum is added. export var IssueExpanded; diff --git a/public/core/host/UserMetrics.js.map b/public/core/host/UserMetrics.js.map index 5ab8dd712..530385ad4 100644 --- a/public/core/host/UserMetrics.js.map +++ b/public/core/host/UserMetrics.js.map @@ -1 +1 @@ -{"version":3,"file":"UserMetrics.js","sourceRoot":"","sources":["../../../../../../front_end/core/host/UserMetrics.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (C) 2011 Google Inc. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * * Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above\n * copyright notice, this list of conditions and the following disclaimer\n * in the documentation and/or other materials provided with the\n * distribution.\n * * Neither the name of Google Inc. nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport {InspectorFrontendHostInstance} from './InspectorFrontendHost.js';\nimport {EnumeratedHistogram} from './InspectorFrontendHostAPI.js';\n\nexport class UserMetrics {\n #panelChangedSinceLaunch: boolean;\n #firedLaunchHistogram: boolean;\n #launchPanelName: string;\n constructor() {\n this.#panelChangedSinceLaunch = false;\n this.#firedLaunchHistogram = false;\n this.#launchPanelName = '';\n }\n\n panelShown(panelName: string, isLaunching?: boolean): void {\n const code = PanelCodes[panelName as keyof typeof PanelCodes] || 0;\n InspectorFrontendHostInstance.recordEnumeratedHistogram(EnumeratedHistogram.PanelShown, code, PanelCodes.MAX_VALUE);\n InspectorFrontendHostInstance.recordUserMetricsAction('DevTools_PanelShown_' + panelName);\n // Store that the user has changed the panel so we know launch histograms should not be fired.\n if (!isLaunching) {\n this.#panelChangedSinceLaunch = true;\n }\n }\n\n panelShownInLocation(panelName: string, location: 'main'|'drawer'): void {\n const panelWithLocationName = `${panelName}-${location}`;\n const panelWithLocation = PanelWithLocation[panelWithLocationName as keyof typeof PanelWithLocation] || 0;\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.PanelShownInLocation,\n panelWithLocation,\n PanelWithLocation.MAX_VALUE,\n );\n }\n\n settingsPanelShown(settingsViewId: string): void {\n this.panelShown('settings-' + settingsViewId);\n }\n\n sourcesPanelFileDebugged(mediaType?: string): void {\n const code = (mediaType && MediaTypes[mediaType as keyof typeof MediaTypes]) || MediaTypes.Unknown;\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.SourcesPanelFileDebugged, code, MediaTypes.MAX_VALUE);\n }\n\n sourcesPanelFileOpened(mediaType?: string): void {\n const code = (mediaType && MediaTypes[mediaType as keyof typeof MediaTypes]) || MediaTypes.Unknown;\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.SourcesPanelFileOpened, code, MediaTypes.MAX_VALUE);\n }\n\n networkPanelResponsePreviewOpened(mediaType: string): void {\n const code = (mediaType && MediaTypes[mediaType as keyof typeof MediaTypes]) || MediaTypes.Unknown;\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.NetworkPanelResponsePreviewOpened, code, MediaTypes.MAX_VALUE);\n }\n\n actionTaken(action: Action): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(EnumeratedHistogram.ActionTaken, action, Action.MAX_VALUE);\n }\n\n panelLoaded(panelName: string, histogramName: string): void {\n if (this.#firedLaunchHistogram || panelName !== this.#launchPanelName) {\n return;\n }\n\n this.#firedLaunchHistogram = true;\n // Use rAF and window.setTimeout to ensure the marker is fired after layout and rendering.\n // This will give the most accurate representation of the tool being ready for a user.\n requestAnimationFrame(() => {\n window.setTimeout(() => {\n // Mark the load time so that we can pinpoint it more easily in a trace.\n performance.mark(histogramName);\n // If the user has switched panel before we finished loading, ignore the histogram,\n // since the launch timings will have been affected and are no longer valid.\n if (this.#panelChangedSinceLaunch) {\n return;\n }\n // This fires the event for the appropriate launch histogram.\n // The duration is measured as the time elapsed since the time origin of the document.\n InspectorFrontendHostInstance.recordPerformanceHistogram(histogramName, performance.now());\n }, 0);\n });\n }\n\n setLaunchPanel(panelName: string|null): void {\n this.#launchPanelName = (panelName as string);\n }\n\n performanceTraceLoad(measure: PerformanceMeasure): void {\n InspectorFrontendHostInstance.recordPerformanceHistogram('DevTools.TraceLoad', measure.duration);\n }\n\n keybindSetSettingChanged(keybindSet: string): void {\n const value = KeybindSetSettings[keybindSet as keyof typeof KeybindSetSettings] || 0;\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.KeybindSetSettingChanged, value, KeybindSetSettings.MAX_VALUE);\n }\n\n keyboardShortcutFired(actionId: string): void {\n const action =\n KeyboardShortcutAction[actionId as keyof typeof KeyboardShortcutAction] || KeyboardShortcutAction.OtherShortcut;\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.KeyboardShortcutFired, action, KeyboardShortcutAction.MAX_VALUE);\n }\n\n issuesPanelOpenedFrom(issueOpener: IssueOpener): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.IssuesPanelOpenedFrom, issueOpener, IssueOpener.MAX_VALUE);\n }\n\n issuesPanelIssueExpanded(issueExpandedCategory: string|undefined): void {\n if (issueExpandedCategory === undefined) {\n return;\n }\n\n const issueExpanded = IssueExpanded[issueExpandedCategory as keyof typeof IssueExpanded];\n\n if (issueExpanded === undefined) {\n return;\n }\n\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.IssuesPanelIssueExpanded, issueExpanded, IssueExpanded.MAX_VALUE);\n }\n\n issuesPanelResourceOpened(issueCategory: string, type: string): void {\n const key = issueCategory + type;\n const value = IssueResourceOpened[key as keyof typeof IssueResourceOpened];\n\n if (value === undefined) {\n return;\n }\n\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.IssuesPanelResourceOpened, value, IssueResourceOpened.MAX_VALUE);\n }\n\n issueCreated(code: string): void {\n const issueCreated = IssueCreated[code as keyof typeof IssueCreated];\n if (issueCreated === undefined) {\n return;\n }\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.IssueCreated, issueCreated, IssueCreated.MAX_VALUE);\n }\n\n experimentEnabledAtLaunch(experimentId: string): void {\n const experiment = DevtoolsExperiments[experimentId as keyof typeof DevtoolsExperiments];\n if (experiment === undefined) {\n return;\n }\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.ExperimentEnabledAtLaunch, experiment, DevtoolsExperiments.MAX_VALUE);\n }\n\n experimentDisabledAtLaunch(experimentId: string): void {\n const experiment = DevtoolsExperiments[experimentId as keyof typeof DevtoolsExperiments];\n if (experiment === undefined) {\n return;\n }\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.ExperimentDisabledAtLaunch, experiment, DevtoolsExperiments.MAX_VALUE);\n }\n\n experimentChanged(experimentId: string, isEnabled: boolean): void {\n const experiment = DevtoolsExperiments[experimentId as keyof typeof DevtoolsExperiments];\n if (experiment === undefined) {\n return;\n }\n const actionName = isEnabled ? EnumeratedHistogram.ExperimentEnabled : EnumeratedHistogram.ExperimentDisabled;\n InspectorFrontendHostInstance.recordEnumeratedHistogram(actionName, experiment, DevtoolsExperiments.MAX_VALUE);\n }\n\n developerResourceLoaded(developerResourceLoaded: DeveloperResourceLoaded): void {\n if (developerResourceLoaded >= DeveloperResourceLoaded.MAX_VALUE) {\n return;\n }\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.DeveloperResourceLoaded, developerResourceLoaded, DeveloperResourceLoaded.MAX_VALUE);\n }\n\n developerResourceScheme(developerResourceScheme: DeveloperResourceScheme): void {\n if (developerResourceScheme >= DeveloperResourceScheme.MAX_VALUE) {\n return;\n }\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.DeveloperResourceScheme, developerResourceScheme, DeveloperResourceScheme.MAX_VALUE);\n }\n\n language(language: Intl.UnicodeBCP47LocaleIdentifier): void {\n const languageCode = Language[language as keyof typeof Language];\n if (languageCode === undefined) {\n return;\n }\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.Language, languageCode, Language.MAX_VALUE);\n }\n\n syncSetting(devtoolsSyncSettingEnabled: boolean): void {\n InspectorFrontendHostInstance.getSyncInformation(syncInfo => {\n let settingValue = SyncSetting.CHROME_SYNC_DISABLED;\n if (syncInfo.isSyncActive && !syncInfo.arePreferencesSynced) {\n settingValue = SyncSetting.CHROME_SYNC_SETTINGS_DISABLED;\n } else if (syncInfo.isSyncActive && syncInfo.arePreferencesSynced) {\n settingValue = devtoolsSyncSettingEnabled ? SyncSetting.DEVTOOLS_SYNC_SETTING_ENABLED :\n SyncSetting.DEVTOOLS_SYNC_SETTING_DISABLED;\n }\n\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.SyncSetting, settingValue, SyncSetting.MAX_VALUE);\n });\n }\n\n recordingAssertion(value: RecordingAssertion): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.RecordingAssertion, value, RecordingAssertion.MAX_VALUE);\n }\n\n recordingToggled(value: RecordingToggled): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.RecordingToggled, value, RecordingToggled.MAX_VALUE);\n }\n\n recordingReplayFinished(value: RecordingReplayFinished): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.RecordingReplayFinished, value, RecordingReplayFinished.MAX_VALUE);\n }\n\n recordingReplaySpeed(value: RecordingReplaySpeed): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.RecordingReplaySpeed, value, RecordingReplaySpeed.MAX_VALUE);\n }\n\n recordingReplayStarted(value: RecordingReplayStarted): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.RecordingReplayStarted, value, RecordingReplayStarted.MAX_VALUE);\n }\n\n recordingEdited(value: RecordingEdited): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.RecordingEdited, value, RecordingEdited.MAX_VALUE);\n }\n\n recordingExported(value: RecordingExported): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.RecordingExported, value, RecordingExported.MAX_VALUE);\n }\n\n recordingCodeToggled(value: RecordingCodeToggled): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.RecordingCodeToggled, value, RecordingCodeToggled.MAX_VALUE);\n }\n\n recordingCopiedToClipboard(value: RecordingCopiedToClipboard): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.RecordingCopiedToClipboard, value, RecordingCopiedToClipboard.MAX_VALUE);\n }\n\n styleTextCopied(value: StyleTextCopied): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.StyleTextCopied, value, StyleTextCopied.MAX_VALUE);\n }\n\n manifestSectionSelected(sectionTitle: string): void {\n const code =\n ManifestSectionCodes[sectionTitle as keyof typeof ManifestSectionCodes] || ManifestSectionCodes.OtherSection;\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.ManifestSectionSelected, code, ManifestSectionCodes.MAX_VALUE);\n }\n\n cssHintShown(type: CSSHintType): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.CSSHintShown, type, CSSHintType.MAX_VALUE);\n }\n\n lighthouseModeRun(type: LighthouseModeRun): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.LighthouseModeRun, type, LighthouseModeRun.MAX_VALUE);\n }\n\n lighthouseCategoryUsed(type: LighthouseCategoryUsed): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.LighthouseCategoryUsed, type, LighthouseCategoryUsed.MAX_VALUE);\n }\n\n colorPickerOpenedFrom(type: ColorPickerOpenedFrom): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.ColorPickerOpenedFrom, type, ColorPickerOpenedFrom.MAX_VALUE);\n }\n\n cssPropertyDocumentation(type: CSSPropertyDocumentation): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.CSSPropertyDocumentation, type, CSSPropertyDocumentation.MAX_VALUE);\n }\n\n swatchActivated(swatch: SwatchType): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.SwatchActivated, swatch, SwatchType.MAX_VALUE);\n }\n\n animationPlaybackRateChanged(playbackRate: AnimationsPlaybackRate): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.AnimationPlaybackRateChanged, playbackRate, AnimationsPlaybackRate.MAX_VALUE);\n }\n\n animationPointDragged(dragType: AnimationPointDragType): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.AnimationPointDragged, dragType, AnimationPointDragType.MAX_VALUE);\n }\n\n workspacesPopulated(wallClockTimeInMilliseconds: number): void {\n InspectorFrontendHostInstance.recordPerformanceHistogram(\n 'DevTools.Workspaces.PopulateWallClocktime', wallClockTimeInMilliseconds);\n }\n\n visualLoggingProcessingDone(timeInMilliseconds: number): void {\n InspectorFrontendHostInstance.recordPerformanceHistogram(\n 'DevTools.VisualLogging.ProcessingTime', timeInMilliseconds);\n }\n\n legacyResourceTypeFilterNumberOfSelectedChanged(itemCount: number): void {\n const boundItemCount = Math.max(Math.min(itemCount, ResourceType.MAX_VALUE - 1), 1);\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.LegacyResourceTypeFilterNumberOfSelectedChanged, boundItemCount, ResourceType.MAX_VALUE);\n }\n\n legacyResourceTypeFilterItemSelected(resourceTypeName: string): void {\n const resourceType = ResourceType[resourceTypeName as keyof typeof ResourceType];\n if (resourceType === undefined) {\n return;\n }\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.LegacyResourceTypeFilterItemSelected, resourceType, ResourceType.MAX_VALUE);\n }\n\n resourceTypeFilterNumberOfSelectedChanged(itemCount: number): void {\n const boundItemCount = Math.max(Math.min(itemCount, ResourceType.MAX_VALUE - 1), 1);\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.ResourceTypeFilterNumberOfSelectedChanged, boundItemCount, ResourceType.MAX_VALUE);\n }\n\n resourceTypeFilterItemSelected(resourceTypeName: string): void {\n const resourceType = ResourceType[resourceTypeName as keyof typeof ResourceType];\n if (resourceType === undefined) {\n return;\n }\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.ResourceTypeFilterItemSelected, resourceType, ResourceType.MAX_VALUE);\n }\n\n networkPanelMoreFiltersNumberOfSelectedChanged(itemCount: number): void {\n const boundItemCount = Math.max(Math.min(itemCount, NetworkPanelMoreFilters.MAX_VALUE), 0);\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.NetworkPanelMoreFiltersNumberOfSelectedChanged, boundItemCount,\n NetworkPanelMoreFilters.MAX_VALUE);\n }\n\n networkPanelMoreFiltersItemSelected(filterName: string): void {\n const filter = NetworkPanelMoreFilters[filterName as keyof typeof NetworkPanelMoreFilters];\n if (filter === undefined) {\n return;\n }\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.NetworkPanelMoreFiltersItemSelected, filter, NetworkPanelMoreFilters.MAX_VALUE);\n }\n}\n\n/**\n * The numeric enum values are not necessarily continuous! It is possible that\n * values have been removed, which results in gaps in the sequence of values.\n * When adding a new value:\n * 1. Add an entry to the bottom of the enum before 'MAX_VALUE'.\n * 2. Set the value of the new entry to the current value of 'MAX_VALUE'.\n * 2. Increment the value of 'MAX_VALUE' by 1.\n * When removing a value which is no longer needed:\n * 1. Delete the line with the unneeded value\n * 2. Do not update any 'MAX_VALUE' or any other value.\n */\n\n// Codes below are used to collect UMA histograms in the Chromium port.\n// Do not change the values below, additional actions are needed on the Chromium side\n// in order to add more codes.\nexport enum Action {\n /* eslint-disable @typescript-eslint/naming-convention */\n WindowDocked = 1,\n WindowUndocked = 2,\n ScriptsBreakpointSet = 3,\n TimelineStarted = 4,\n ProfilesCPUProfileTaken = 5,\n ProfilesHeapProfileTaken = 6,\n ConsoleEvaluated = 8,\n FileSavedInWorkspace = 9,\n DeviceModeEnabled = 10,\n AnimationsPlaybackRateChanged = 11,\n RevisionApplied = 12,\n FileSystemDirectoryContentReceived = 13,\n StyleRuleEdited = 14,\n CommandEvaluatedInConsolePanel = 15,\n DOMPropertiesExpanded = 16,\n ResizedViewInResponsiveMode = 17,\n TimelinePageReloadStarted = 18,\n ConnectToNodeJSFromFrontend = 19,\n ConnectToNodeJSDirectly = 20,\n CpuThrottlingEnabled = 21,\n CpuProfileNodeFocused = 22,\n CpuProfileNodeExcluded = 23,\n SelectFileFromFilePicker = 24,\n SelectCommandFromCommandMenu = 25,\n ChangeInspectedNodeInElementsPanel = 26,\n StyleRuleCopied = 27,\n CoverageStarted = 28,\n LighthouseStarted = 29,\n LighthouseFinished = 30,\n ShowedThirdPartyBadges = 31,\n LighthouseViewTrace = 32,\n FilmStripStartedRecording = 33,\n CoverageReportFiltered = 34,\n CoverageStartedPerBlock = 35,\n 'SettingsOpenedFromGear-deprecated' = 36,\n 'SettingsOpenedFromMenu-deprecated' = 37,\n 'SettingsOpenedFromCommandMenu-deprecated' = 38,\n TabMovedToDrawer = 39,\n TabMovedToMainPanel = 40,\n CaptureCssOverviewClicked = 41,\n VirtualAuthenticatorEnvironmentEnabled = 42,\n SourceOrderViewActivated = 43,\n UserShortcutAdded = 44,\n ShortcutRemoved = 45,\n ShortcutModified = 46,\n CustomPropertyLinkClicked = 47,\n CustomPropertyEdited = 48,\n ServiceWorkerNetworkRequestClicked = 49,\n ServiceWorkerNetworkRequestClosedQuickly = 50,\n NetworkPanelServiceWorkerRespondWith = 51,\n NetworkPanelCopyValue = 52,\n ConsoleSidebarOpened = 53,\n PerfPanelTraceImported = 54,\n PerfPanelTraceExported = 55,\n StackFrameRestarted = 56,\n CaptureTestProtocolClicked = 57,\n BreakpointRemovedFromRemoveButton = 58,\n BreakpointGroupExpandedStateChanged = 59,\n HeaderOverrideFileCreated = 60,\n HeaderOverrideEnableEditingClicked = 61,\n HeaderOverrideHeaderAdded = 62,\n HeaderOverrideHeaderEdited = 63,\n HeaderOverrideHeaderRemoved = 64,\n HeaderOverrideHeadersFileEdited = 65,\n PersistenceNetworkOverridesEnabled = 66,\n PersistenceNetworkOverridesDisabled = 67,\n BreakpointRemovedFromContextMenu = 68,\n BreakpointsInFileRemovedFromRemoveButton = 69,\n BreakpointsInFileRemovedFromContextMenu = 70,\n BreakpointsInFileCheckboxToggled = 71,\n BreakpointsInFileEnabledDisabledFromContextMenu = 72,\n BreakpointConditionEditedFromSidebar = 73,\n WorkspaceTabAddFolder = 74,\n WorkspaceTabRemoveFolder = 75,\n OverrideTabAddFolder = 76,\n OverrideTabRemoveFolder = 77,\n WorkspaceSourceSelected = 78,\n OverridesSourceSelected = 79,\n StyleSheetInitiatorLinkClicked = 80,\n BreakpointRemovedFromGutterContextMenu = 81,\n BreakpointRemovedFromGutterToggle = 82,\n StylePropertyInsideKeyframeEdited = 83,\n OverrideContentFromSourcesContextMenu = 84,\n OverrideContentFromNetworkContextMenu = 85,\n OverrideScript = 86,\n OverrideStyleSheet = 87,\n OverrideDocument = 88,\n OverrideFetchXHR = 89,\n OverrideImage = 90,\n OverrideFont = 91,\n OverrideContentContextMenuSetup = 92,\n OverrideContentContextMenuAbandonSetup = 93,\n OverrideContentContextMenuActivateDisabled = 94,\n OverrideContentContextMenuOpenExistingFile = 95,\n OverrideContentContextMenuSaveNewFile = 96,\n ShowAllOverridesFromSourcesContextMenu = 97,\n ShowAllOverridesFromNetworkContextMenu = 98,\n AnimationGroupsCleared = 99,\n AnimationsPaused = 100,\n AnimationsResumed = 101,\n AnimatedNodeDescriptionClicked = 102,\n AnimationGroupScrubbed = 103,\n AnimationGroupReplayed = 104,\n OverrideTabDeleteFolderContextMenu = 105,\n WorkspaceDropFolder = 107,\n WorkspaceSelectFolder = 108,\n OverrideContentContextMenuSourceMappedWarning = 109,\n OverrideContentContextMenuRedirectToDeployed = 110,\n NewStyleRuleAdded = 111,\n TraceExpanded = 112,\n InsightConsoleMessageShown = 113,\n InsightRequestedViaContextMenu = 114,\n InsightRequestedViaHoverButton = 115,\n InsightRatedPositive = 117,\n InsightRatedNegative = 118,\n InsightClosed = 119,\n InsightErrored = 120,\n InsightHoverButtonShown = 121,\n SelfXssWarningConsoleMessageShown = 122,\n SelfXssWarningDialogShown = 123,\n SelfXssAllowPastingInConsole = 124,\n SelfXssAllowPastingInDialog = 125,\n ToggleEmulateFocusedPageFromStylesPaneOn = 126,\n ToggleEmulateFocusedPageFromStylesPaneOff = 127,\n ToggleEmulateFocusedPageFromRenderingTab = 128,\n ToggleEmulateFocusedPageFromCommandMenu = 129,\n InsightGenerated = 130,\n InsightErroredApi = 131,\n InsightErroredMarkdown = 132,\n ToggleShowWebVitals = 133,\n InsightErroredPermissionDenied = 134,\n InsightErroredCannotSend = 135,\n InsightErroredRequestFailed = 136,\n InsightErroredCannotParseChunk = 137,\n InsightErroredUnknownChunk = 138,\n InsightErroredOther = 139,\n AutofillReceived = 140,\n AutofillReceivedAndTabAutoOpened = 141,\n AnimationGroupSelected = 142,\n ScrollDrivenAnimationGroupSelected = 143,\n ScrollDrivenAnimationGroupScrubbed = 144,\n FreestylerOpenedFromElementsPanel = 145,\n FreestylerOpenedFromStylesTab = 146,\n ConsoleFilterByContext = 147,\n ConsoleFilterBySource = 148,\n ConsoleFilterByUrl = 149,\n InsightConsentReminderShown = 150,\n InsightConsentReminderCanceled = 151,\n InsightConsentReminderConfirmed = 152,\n InsightsOnboardingShown = 153,\n InsightsOnboardingCanceledOnPage1 = 154,\n InsightsOnboardingCanceledOnPage2 = 155,\n InsightsOnboardingConfirmed = 156,\n InsightsOnboardingNextPage = 157,\n InsightsOnboardingPrevPage = 158,\n InsightsOnboardingFeatureDisabled = 159,\n InsightsOptInTeaserShown = 160,\n InsightsOptInTeaserSettingsLinkClicked = 161,\n InsightsOptInTeaserConfirmedInSettings = 162,\n InsightsReminderTeaserShown = 163,\n InsightsReminderTeaserConfirmed = 164,\n InsightsReminderTeaserCanceled = 165,\n InsightsReminderTeaserSettingsLinkClicked = 166,\n InsightsReminderTeaserAbortedInSettings = 167,\n GeneratingInsightWithoutDisclaimer = 168,\n MAX_VALUE = 169,\n /* eslint-enable @typescript-eslint/naming-convention */\n}\n\nexport enum PanelCodes {\n /* eslint-disable @typescript-eslint/naming-convention */\n elements = 1,\n resources = 2,\n network = 3,\n sources = 4,\n timeline = 5,\n 'heap-profiler' = 6,\n console = 8,\n layers = 9,\n 'console-view' = 10,\n 'animations' = 11,\n 'network.config' = 12,\n 'rendering' = 13,\n 'sensors' = 14,\n 'sources.search' = 15,\n security = 16,\n 'js-profiler' = 17,\n lighthouse = 18,\n 'coverage' = 19,\n 'protocol-monitor' = 20,\n 'remote-devices' = 21,\n 'web-audio' = 22,\n 'changes.changes' = 23,\n 'performance.monitor' = 24,\n 'release-note' = 25,\n 'live-heap-profile' = 26,\n 'sources.quick' = 27,\n 'network.blocked-urls' = 28,\n 'settings-preferences' = 29,\n 'settings-workspace' = 30,\n 'settings-experiments' = 31,\n 'settings-blackbox' = 32,\n 'settings-devices' = 33,\n 'settings-throttling-conditions' = 34,\n 'settings-emulation-locations' = 35,\n 'settings-shortcuts' = 36,\n 'issues-pane' = 37,\n 'settings-keybinds' = 38,\n 'cssoverview' = 39,\n 'chrome-recorder' = 40,\n 'trust-tokens' = 41,\n 'reporting-api' = 42,\n 'interest-groups' = 43,\n 'back-forward-cache' = 44,\n 'service-worker-cache' = 45,\n 'background-service-background-fetch' = 46,\n 'background-service-background-sync' = 47,\n 'background-service-push-messaging' = 48,\n 'background-service-notifications' = 49,\n 'background-service-payment-handler' = 50,\n 'background-service-periodic-background-sync' = 51,\n 'service-workers' = 52,\n 'app-manifest' = 53,\n 'storage' = 54,\n 'cookies' = 55,\n 'frame-details' = 56,\n 'frame-resource' = 57,\n 'frame-window' = 58,\n 'frame-worker' = 59,\n 'dom-storage' = 60,\n 'indexed-db' = 61,\n 'web-sql' = 62,\n 'performance-insights' = 63,\n 'preloading' = 64,\n 'bounce-tracking-mitigations' = 65,\n 'developer-resources' = 66,\n 'autofill-view' = 67,\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 68,\n}\n\nexport enum PanelWithLocation {\n /* eslint-disable @typescript-eslint/naming-convention */\n 'elements-main' = 1,\n 'elements-drawer' = 2,\n 'resources-main' = 3,\n 'resources-drawer' = 4,\n 'network-main' = 5,\n 'network-drawer' = 6,\n 'sources-main' = 7,\n 'sources-drawer' = 8,\n 'timeline-main' = 9,\n 'timeline-drawer' = 10,\n 'heap_profiler-main' = 11,\n 'heap_profiler-drawer' = 12,\n 'console-main' = 13,\n 'console-drawer' = 14,\n 'layers-main' = 15,\n 'layers-drawer' = 16,\n 'console-view-main' = 17,\n 'console-view-drawer' = 18,\n 'animations-main' = 19,\n 'animations-drawer' = 20,\n 'network.config-main' = 21,\n 'network.config-drawer' = 22,\n 'rendering-main' = 23,\n 'rendering-drawer' = 24,\n 'sensors-main' = 25,\n 'sensors-drawer' = 26,\n 'sources.search-main' = 27,\n 'sources.search-drawer' = 28,\n 'security-main' = 29,\n 'security-drawer' = 30,\n 'lighthouse-main' = 33,\n 'lighthouse-drawer' = 34,\n 'coverage-main' = 35,\n 'coverage-drawer' = 36,\n 'protocol-monitor-main' = 37,\n 'protocol-monitor-drawer' = 38,\n 'remote-devices-main' = 39,\n 'remote-devices-drawer' = 40,\n 'web-audio-main' = 41,\n 'web-audio-drawer' = 42,\n 'changes.changes-main' = 43,\n 'changes.changes-drawer' = 44,\n 'performance.monitor-main' = 45,\n 'performance.monitor-drawer' = 46,\n 'release-note-main' = 47,\n 'release-note-drawer' = 48,\n 'live_heap_profile-main' = 49,\n 'live_heap_profile-drawer' = 50,\n 'sources.quick-main' = 51,\n 'sources.quick-drawer' = 52,\n 'network.blocked-urls-main' = 53,\n 'network.blocked-urls-drawer' = 54,\n 'settings-preferences-main' = 55,\n 'settings-preferences-drawer' = 56,\n 'settings-workspace-main' = 57,\n 'settings-workspace-drawer' = 58,\n 'settings-experiments-main' = 59,\n 'settings-experiments-drawer' = 60,\n 'settings-blackbox-main' = 61,\n 'settings-blackbox-drawer' = 62,\n 'settings-devices-main' = 63,\n 'settings-devices-drawer' = 64,\n 'settings-throttling-conditions-main' = 65,\n 'settings-throttling-conditions-drawer' = 66,\n 'settings-emulation-locations-main' = 67,\n 'settings-emulation-locations-drawer' = 68,\n 'settings-shortcuts-main' = 69,\n 'settings-shortcuts-drawer' = 70,\n 'issues-pane-main' = 71,\n 'issues-pane-drawer' = 72,\n 'settings-keybinds-main' = 73,\n 'settings-keybinds-drawer' = 74,\n 'cssoverview-main' = 75,\n 'cssoverview-drawer' = 76,\n 'chrome_recorder-main' = 77,\n 'chrome_recorder-drawer' = 78,\n 'trust_tokens-main' = 79,\n 'trust_tokens-drawer' = 80,\n 'reporting_api-main' = 81,\n 'reporting_api-drawer' = 82,\n 'interest_groups-main' = 83,\n 'interest_groups-drawer' = 84,\n 'back_forward_cache-main' = 85,\n 'back_forward_cache-drawer' = 86,\n 'service_worker_cache-main' = 87,\n 'service_worker_cache-drawer' = 88,\n 'background_service_backgroundFetch-main' = 89,\n 'background_service_backgroundFetch-drawer' = 90,\n 'background_service_backgroundSync-main' = 91,\n 'background_service_backgroundSync-drawer' = 92,\n 'background_service_pushMessaging-main' = 93,\n 'background_service_pushMessaging-drawer' = 94,\n 'background_service_notifications-main' = 95,\n 'background_service_notifications-drawer' = 96,\n 'background_service_paymentHandler-main' = 97,\n 'background_service_paymentHandler-drawer' = 98,\n 'background_service_periodicBackgroundSync-main' = 99,\n 'background_service_periodicBackgroundSync-drawer' = 100,\n 'service_workers-main' = 101,\n 'service_workers-drawer' = 102,\n 'app_manifest-main' = 103,\n 'app_manifest-drawer' = 104,\n 'storage-main' = 105,\n 'storage-drawer' = 106,\n 'cookies-main' = 107,\n 'cookies-drawer' = 108,\n 'frame_details-main' = 109,\n 'frame_details-drawer' = 110,\n 'frame_resource-main' = 111,\n 'frame_resource-drawer' = 112,\n 'frame_window-main' = 113,\n 'frame_window-drawer' = 114,\n 'frame_worker-main' = 115,\n 'frame_worker-drawer' = 116,\n 'dom_storage-main' = 117,\n 'dom_storage-drawer' = 118,\n 'indexed_db-main' = 119,\n 'indexed_db-drawer' = 120,\n 'web_sql-main' = 121,\n 'web_sql-drawer' = 122,\n 'performance_insights-main' = 123,\n 'performance_insights-drawer' = 124,\n 'preloading-main' = 125,\n 'preloading-drawer' = 126,\n 'bounce_tracking_mitigations-main' = 127,\n 'bounce_tracking_mitigations-drawer' = 128,\n 'developer-resources-main' = 129,\n 'developer-resources-drawer' = 130,\n 'autofill-view-main' = 131,\n 'autofill-view-drawer' = 132,\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 133,\n}\n\nexport enum ElementsSidebarTabCodes {\n /* eslint-disable @typescript-eslint/naming-convention */\n 'OtherSidebarPane' = 0,\n 'styles' = 1,\n 'computed' = 2,\n 'elements.layout' = 3,\n 'elements.event-listeners' = 4,\n 'elements.dom-breakpoints' = 5,\n 'elements.dom-properties' = 6,\n 'accessibility.view' = 7,\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 8,\n}\n\nexport enum MediaTypes {\n /* eslint-disable @typescript-eslint/naming-convention */\n Unknown = 0,\n 'text/css' = 2,\n 'text/html' = 3,\n 'application/xml' = 4,\n 'application/wasm' = 5,\n 'application/manifest+json' = 6,\n 'application/x-aspx' = 7,\n 'application/jsp' = 8,\n 'text/x-c++src' = 9,\n 'text/x-coffeescript' = 10,\n 'application/vnd.dart' = 11,\n 'text/typescript' = 12,\n 'text/typescript-jsx' = 13,\n 'application/json' = 14,\n 'text/x-csharp' = 15,\n 'text/x-java' = 16,\n 'text/x-less' = 17,\n 'application/x-httpd-php' = 18,\n 'text/x-python' = 19,\n 'text/x-sh' = 20,\n 'text/x-gss' = 21,\n 'text/x-sass' = 22,\n 'text/x-scss' = 23,\n 'text/markdown' = 24,\n 'text/x-clojure' = 25,\n 'text/jsx' = 26,\n 'text/x-go' = 27,\n 'text/x-kotlin' = 28,\n 'text/x-scala' = 29,\n 'text/x.svelte' = 30,\n 'text/javascript+plain' = 31,\n 'text/javascript+minified' = 32,\n 'text/javascript+sourcemapped' = 33,\n 'text/x.angular' = 34,\n 'text/x.vue' = 35,\n 'text/javascript+snippet' = 36,\n 'text/javascript+eval' = 37, // Scripts resulting from console inputs or page \"eval\"s with no sourceUrl comment.\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 38,\n}\n\nexport enum KeybindSetSettings {\n /* eslint-disable @typescript-eslint/naming-convention */\n 'devToolsDefault' = 0,\n 'vsCode' = 1,\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 2,\n}\n\nexport enum KeyboardShortcutAction {\n /* eslint-disable @typescript-eslint/naming-convention */\n OtherShortcut = 0,\n 'quick-open.show-command-menu' = 1,\n 'console.clear' = 2,\n 'console.toggle' = 3,\n 'debugger.step' = 4,\n 'debugger.step-into' = 5,\n 'debugger.step-out' = 6,\n 'debugger.step-over' = 7,\n 'debugger.toggle-breakpoint' = 8,\n 'debugger.toggle-breakpoint-enabled' = 9,\n 'debugger.toggle-pause' = 10,\n 'elements.edit-as-html' = 11,\n 'elements.hide-element' = 12,\n 'elements.redo' = 13,\n 'elements.toggle-element-search' = 14,\n 'elements.undo' = 15,\n 'main.search-in-panel.find' = 16,\n 'main.toggle-drawer' = 17,\n 'network.hide-request-details' = 18,\n 'network.search' = 19,\n 'network.toggle-recording' = 20,\n 'quick-open.show' = 21,\n 'settings.show' = 22,\n 'sources.search' = 23,\n 'background-service.toggle-recording' = 24,\n 'components.collect-garbage' = 25,\n 'console.clear.history' = 26,\n 'console.create-pin' = 27,\n 'coverage.start-with-reload' = 28,\n 'coverage.toggle-recording' = 29,\n 'debugger.breakpoint-input-window' = 30,\n 'debugger.evaluate-selection' = 31,\n 'debugger.next-call-frame' = 32,\n 'debugger.previous-call-frame' = 33,\n 'debugger.run-snippet' = 34,\n 'debugger.toggle-breakpoints-active' = 35,\n 'elements.capture-area-screenshot' = 36,\n 'emulation.capture-full-height-screenshot' = 37,\n 'emulation.capture-node-screenshot' = 38,\n 'emulation.capture-screenshot' = 39,\n 'emulation.show-sensors' = 40,\n 'emulation.toggle-device-mode' = 41,\n 'help.release-notes' = 42,\n 'help.report-issue' = 43,\n 'input.start-replaying' = 44,\n 'input.toggle-pause' = 45,\n 'input.toggle-recording' = 46,\n 'inspector-main.focus-debuggee' = 47,\n 'inspector-main.hard-reload' = 48,\n 'inspector-main.reload' = 49,\n 'live-heap-profile.start-with-reload' = 50,\n 'live-heap-profile.toggle-recording' = 51,\n 'main.debug-reload' = 52,\n 'main.next-tab' = 53,\n 'main.previous-tab' = 54,\n 'main.search-in-panel.cancel' = 55,\n 'main.search-in-panel.find-next' = 56,\n 'main.search-in-panel.find-previous' = 57,\n 'main.toggle-dock' = 58,\n 'main.zoom-in' = 59,\n 'main.zoom-out' = 60,\n 'main.zoom-reset' = 61,\n 'network-conditions.network-low-end-mobile' = 62,\n 'network-conditions.network-mid-tier-mobile' = 63,\n 'network-conditions.network-offline' = 64,\n 'network-conditions.network-online' = 65,\n 'profiler.heap-toggle-recording' = 66,\n 'profiler.js-toggle-recording' = 67,\n 'resources.clear' = 68,\n 'settings.documentation' = 69,\n 'settings.shortcuts' = 70,\n 'sources.add-folder-to-workspace' = 71,\n 'sources.add-to-watch' = 72,\n 'sources.close-all' = 73,\n 'sources.close-editor-tab' = 74,\n 'sources.create-snippet' = 75,\n 'sources.go-to-line' = 76,\n 'sources.go-to-member' = 77,\n 'sources.jump-to-next-location' = 78,\n 'sources.jump-to-previous-location' = 79,\n 'sources.rename' = 80,\n 'sources.save' = 81,\n 'sources.save-all' = 82,\n 'sources.switch-file' = 83,\n 'timeline.jump-to-next-frame' = 84,\n 'timeline.jump-to-previous-frame' = 85,\n 'timeline.load-from-file' = 86,\n 'timeline.next-recording' = 87,\n 'timeline.previous-recording' = 88,\n 'timeline.record-reload' = 89,\n 'timeline.save-to-file' = 90,\n 'timeline.show-history' = 91,\n 'timeline.toggle-recording' = 92,\n 'sources.increment-css' = 93,\n 'sources.increment-css-by-ten' = 94,\n 'sources.decrement-css' = 95,\n 'sources.decrement-css-by-ten' = 96,\n 'layers.reset-view' = 97,\n 'layers.pan-mode' = 98,\n 'layers.rotate-mode' = 99,\n 'layers.zoom-in' = 100,\n 'layers.zoom-out' = 101,\n 'layers.up' = 102,\n 'layers.down' = 103,\n 'layers.left' = 104,\n 'layers.right' = 105,\n 'help.report-translation-issue' = 106,\n 'rendering.toggle-prefers-color-scheme' = 107,\n 'chrome-recorder.start-recording' = 108,\n 'chrome-recorder.replay-recording' = 109,\n 'chrome-recorder.toggle-code-view' = 110,\n 'chrome-recorder.copy-recording-or-step' = 111,\n 'changes.revert' = 112,\n 'changes.copy' = 113,\n 'elements.new-style-rule' = 114,\n 'elements.refresh-event-listeners' = 115,\n 'coverage.clear' = 116,\n 'coverage.export' = 117,\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 118,\n}\n\nexport const enum IssueOpener {\n CONSOLE_INFO_BAR = 0,\n LEARN_MORE_LINK_COEP = 1,\n STATUS_BAR_ISSUES_COUNTER = 2,\n HAMBURGER_MENU = 3,\n ADORNER = 4,\n COMMAND_MENU = 5,\n MAX_VALUE = 6,\n}\n\n/**\n * This list should contain the currently active Devtools Experiments,\n * gaps are expected.\n */\nexport enum DevtoolsExperiments {\n /* eslint-disable @typescript-eslint/naming-convention */\n 'apply-custom-stylesheet' = 0,\n 'capture-node-creation-stacks' = 1,\n 'live-heap-profile' = 11,\n 'protocol-monitor' = 13,\n 'sampling-heap-profiler-timeline' = 17,\n 'show-option-tp-expose-internals-in-heap-snapshot' = 18,\n 'timeline-invalidation-tracking' = 26,\n 'timeline-show-all-events' = 27,\n 'timeline-v8-runtime-call-stats' = 28,\n 'apca' = 39,\n 'font-editor' = 41,\n 'full-accessibility-tree' = 42,\n 'contrast-issues' = 44,\n 'experimental-cookie-features' = 45,\n 'styles-pane-css-changes' = 55,\n 'instrumentation-breakpoints' = 61,\n 'authored-deployed-grouping' = 63,\n 'just-my-code' = 65,\n 'highlight-errors-elements-panel' = 73,\n 'use-source-map-scopes' = 76,\n 'network-panel-filter-bar-redesign' = 79,\n 'autofill-view' = 82,\n 'css-type-component-length-deprecate' = 85,\n 'timeline-show-postmessage-events' = 86,\n 'timeline-enhanced-traces' = 90,\n 'timeline-compiled-sources' = 91,\n 'timeline-debug-mode' = 93,\n 'perf-panel-annotations' = 94,\n 'timeline-rpp-sidebar' = 95,\n 'timeline-observations' = 96,\n 'gen-ai-settings-panel' = 97,\n 'timeline-server-timings' = 98,\n 'timeline-layout-shift-details' = 99,\n /* eslint-enable @typescript-eslint/naming-convention */\n\n // Increment this when new experiments are added.\n MAX_VALUE = 100,\n}\n\nexport const enum ColorPickerOpenedFrom {\n SOURCES_PANEL = 0,\n STYLES_TAB = 1,\n MAX_VALUE = 2,\n}\n\nexport const enum CSSPropertyDocumentation {\n SHOWN = 0,\n TOGGLED_ON = 1,\n TOGGLED_OFF = 2,\n MAX_VALUE = 3,\n}\n\n// Update DevToolsIssuesPanelIssueExpanded from tools/metrics/histograms/enums.xml if new enum is added.\nexport enum IssueExpanded {\n /* eslint-disable @typescript-eslint/naming-convention */\n CrossOriginEmbedderPolicy = 0,\n MixedContent = 1,\n SameSiteCookie = 2,\n HeavyAd = 3,\n ContentSecurityPolicy = 4,\n Other = 5,\n Generic = 6,\n ThirdPartyPhaseoutCookie = 7,\n GenericCookie = 8,\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 9,\n}\n\nexport enum IssueResourceOpened {\n /* eslint-disable @typescript-eslint/naming-convention */\n CrossOriginEmbedderPolicyRequest = 0,\n CrossOriginEmbedderPolicyElement = 1,\n MixedContentRequest = 2,\n SameSiteCookieCookie = 3,\n SameSiteCookieRequest = 4,\n HeavyAdElement = 5,\n ContentSecurityPolicyDirective = 6,\n ContentSecurityPolicyElement = 7,\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 13,\n}\n\n/**\n * This list should contain the currently active issue types,\n * gaps are expected.\n */\nexport enum IssueCreated {\n /* eslint-disable @typescript-eslint/naming-convention */\n MixedContentIssue = 0,\n 'ContentSecurityPolicyIssue::kInlineViolation' = 1,\n 'ContentSecurityPolicyIssue::kEvalViolation' = 2,\n 'ContentSecurityPolicyIssue::kURLViolation' = 3,\n 'ContentSecurityPolicyIssue::kTrustedTypesSinkViolation' = 4,\n 'ContentSecurityPolicyIssue::kTrustedTypesPolicyViolation' = 5,\n 'HeavyAdIssue::NetworkTotalLimit' = 6,\n 'HeavyAdIssue::CpuTotalLimit' = 7,\n 'HeavyAdIssue::CpuPeakLimit' = 8,\n 'CrossOriginEmbedderPolicyIssue::CoepFrameResourceNeedsCoepHeader' = 9,\n 'CrossOriginEmbedderPolicyIssue::CoopSandboxedIFrameCannotNavigateToCoopPage' = 10,\n 'CrossOriginEmbedderPolicyIssue::CorpNotSameOrigin' = 11,\n 'CrossOriginEmbedderPolicyIssue::CorpNotSameOriginAfterDefaultedToSameOriginByCoep' = 12,\n 'CrossOriginEmbedderPolicyIssue::CorpNotSameSite' = 13,\n 'CookieIssue::ExcludeSameSiteNoneInsecure::ReadCookie' = 14,\n 'CookieIssue::ExcludeSameSiteNoneInsecure::SetCookie' = 15,\n 'CookieIssue::WarnSameSiteNoneInsecure::ReadCookie' = 16,\n 'CookieIssue::WarnSameSiteNoneInsecure::SetCookie' = 17,\n 'CookieIssue::WarnSameSiteStrictLaxDowngradeStrict::Secure' = 18,\n 'CookieIssue::WarnSameSiteStrictLaxDowngradeStrict::Insecure' = 19,\n 'CookieIssue::WarnCrossDowngrade::ReadCookie::Secure' = 20,\n 'CookieIssue::WarnCrossDowngrade::ReadCookie::Insecure' = 21,\n 'CookieIssue::WarnCrossDowngrade::SetCookie::Secure' = 22,\n 'CookieIssue::WarnCrossDowngrade::SetCookie::Insecure' = 23,\n 'CookieIssue::ExcludeNavigationContextDowngrade::Secure' = 24,\n 'CookieIssue::ExcludeNavigationContextDowngrade::Insecure' = 25,\n 'CookieIssue::ExcludeContextDowngrade::ReadCookie::Secure' = 26,\n 'CookieIssue::ExcludeContextDowngrade::ReadCookie::Insecure' = 27,\n 'CookieIssue::ExcludeContextDowngrade::SetCookie::Secure' = 28,\n 'CookieIssue::ExcludeContextDowngrade::SetCookie::Insecure' = 29,\n 'CookieIssue::ExcludeSameSiteUnspecifiedTreatedAsLax::ReadCookie' = 30,\n 'CookieIssue::ExcludeSameSiteUnspecifiedTreatedAsLax::SetCookie' = 31,\n 'CookieIssue::WarnSameSiteUnspecifiedLaxAllowUnsafe::ReadCookie' = 32,\n 'CookieIssue::WarnSameSiteUnspecifiedLaxAllowUnsafe::SetCookie' = 33,\n 'CookieIssue::WarnSameSiteUnspecifiedCrossSiteContext::ReadCookie' = 34,\n 'CookieIssue::WarnSameSiteUnspecifiedCrossSiteContext::SetCookie' = 35,\n 'SharedArrayBufferIssue::TransferIssue' = 36,\n 'SharedArrayBufferIssue::CreationIssue' = 37,\n LowTextContrastIssue = 41,\n 'CorsIssue::InsecurePrivateNetwork' = 42,\n 'CorsIssue::InvalidHeaders' = 44,\n 'CorsIssue::WildcardOriginWithCredentials' = 45,\n 'CorsIssue::PreflightResponseInvalid' = 46,\n 'CorsIssue::OriginMismatch' = 47,\n 'CorsIssue::AllowCredentialsRequired' = 48,\n 'CorsIssue::MethodDisallowedByPreflightResponse' = 49,\n 'CorsIssue::HeaderDisallowedByPreflightResponse' = 50,\n 'CorsIssue::RedirectContainsCredentials' = 51,\n 'CorsIssue::DisallowedByMode' = 52,\n 'CorsIssue::CorsDisabledScheme' = 53,\n 'CorsIssue::PreflightMissingAllowExternal' = 54,\n 'CorsIssue::PreflightInvalidAllowExternal' = 55,\n 'CorsIssue::NoCorsRedirectModeNotFollow' = 57,\n 'QuirksModeIssue::QuirksMode' = 58,\n 'QuirksModeIssue::LimitedQuirksMode' = 59,\n DeprecationIssue = 60,\n 'ClientHintIssue::MetaTagAllowListInvalidOrigin' = 61,\n 'ClientHintIssue::MetaTagModifiedHTML' = 62,\n 'CorsIssue::PreflightAllowPrivateNetworkError' = 63,\n 'GenericIssue::CrossOriginPortalPostMessageError' = 64,\n 'GenericIssue::FormLabelForNameError' = 65,\n 'GenericIssue::FormDuplicateIdForInputError' = 66,\n 'GenericIssue::FormInputWithNoLabelError' = 67,\n 'GenericIssue::FormAutocompleteAttributeEmptyError' = 68,\n 'GenericIssue::FormEmptyIdAndNameAttributesForInputError' = 69,\n 'GenericIssue::FormAriaLabelledByToNonExistingId' = 70,\n 'GenericIssue::FormInputAssignedAutocompleteValueToIdOrNameAttributeError' = 71,\n 'GenericIssue::FormLabelHasNeitherForNorNestedInput' = 72,\n 'GenericIssue::FormLabelForMatchesNonExistingIdError' = 73,\n 'GenericIssue::FormHasPasswordFieldWithoutUsernameFieldError' = 74,\n 'GenericIssue::FormInputHasWrongButWellIntendedAutocompleteValueError' = 75,\n 'StylesheetLoadingIssue::LateImportRule' = 76,\n 'StylesheetLoadingIssue::RequestFailed' = 77,\n 'CorsIssue::PreflightMissingPrivateNetworkAccessId' = 78,\n 'CorsIssue::PreflightMissingPrivateNetworkAccessName' = 79,\n 'CorsIssue::PrivateNetworkAccessPermissionUnavailable' = 80,\n 'CorsIssue::PrivateNetworkAccessPermissionDenied' = 81,\n 'CookieIssue::WarnThirdPartyPhaseout::ReadCookie' = 82,\n 'CookieIssue::WarnThirdPartyPhaseout::SetCookie' = 83,\n 'CookieIssue::ExcludeThirdPartyPhaseout::ReadCookie' = 84,\n 'CookieIssue::ExcludeThirdPartyPhaseout::SetCookie' = 85,\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 86,\n}\n\nexport const enum DeveloperResourceLoaded {\n LOAD_THROUGH_PAGE_VIA_TARGET = 0,\n LOAD_THROUGH_PAGE_VIA_FRAME = 1,\n LOAD_THROUGH_PAGE_FAILURE = 2,\n LOAD_THROUGH_PAGE_FALLBACK = 3,\n FALLBACK_AFTER_FAILURE = 4,\n FALLBACK_PER_OVERRIDE = 5,\n FALLBACK_PER_PROTOCOL = 6,\n FALLBACK_FAILURE = 7,\n MAX_VALUE = 8,\n}\n\nexport const enum DeveloperResourceScheme {\n OTHER = 0,\n UKNOWN = 1,\n HTTP = 2,\n HTTPS = 3,\n HTTP_LOCALHOST = 4,\n HTTPS_LOCALHOST = 5,\n DATA = 6,\n FILE = 7,\n BLOB = 8,\n MAX_VALUE = 9,\n}\n\nexport enum ResourceType {\n /* eslint-disable @typescript-eslint/naming-convention -- Used by web_tests. */\n all = 0,\n Document = 1,\n JavaScript = 2,\n 'Fetch and XHR' = 3,\n CSS = 4,\n Font = 5,\n Image = 6,\n Media = 7,\n Manifest = 8,\n WebSocket = 9,\n WebAssembly = 10,\n Other = 11,\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 12,\n}\n\nexport enum NetworkPanelMoreFilters {\n /* eslint-disable @typescript-eslint/naming-convention */\n 'Hide data URLs' = 0,\n 'Hide extension URLs' = 1,\n 'Blocked response cookies' = 2,\n 'Blocked requests' = 3,\n '3rd-party requests' = 4,\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 5,\n}\n\nexport enum Language {\n /* eslint-disable @typescript-eslint/naming-convention */\n 'af' = 1,\n 'am' = 2,\n 'ar' = 3,\n 'as' = 4,\n 'az' = 5,\n 'be' = 6,\n 'bg' = 7,\n 'bn' = 8,\n 'bs' = 9,\n 'ca' = 10,\n 'cs' = 11,\n 'cy' = 12,\n 'da' = 13,\n 'de' = 14,\n 'el' = 15,\n 'en-GB' = 16,\n 'en-US' = 17,\n 'es-419' = 18,\n 'es' = 19,\n 'et' = 20,\n 'eu' = 21,\n 'fa' = 22,\n 'fi' = 23,\n 'fil' = 24,\n 'fr-CA' = 25,\n 'fr' = 26,\n 'gl' = 27,\n 'gu' = 28,\n 'he' = 29,\n 'hi' = 30,\n 'hr' = 31,\n 'hu' = 32,\n 'hy' = 33,\n 'id' = 34,\n 'is' = 35,\n 'it' = 36,\n 'ja' = 37,\n 'ka' = 38,\n 'kk' = 39,\n 'km' = 40,\n 'kn' = 41,\n 'ko' = 42,\n 'ky' = 43,\n 'lo' = 44,\n 'lt' = 45,\n 'lv' = 46,\n 'mk' = 47,\n 'ml' = 48,\n 'mn' = 49,\n 'mr' = 50,\n 'ms' = 51,\n 'my' = 52,\n 'ne' = 53,\n 'nl' = 54,\n 'no' = 55,\n 'or' = 56,\n 'pa' = 57,\n 'pl' = 58,\n 'pt-PT' = 59,\n 'pt' = 60,\n 'ro' = 61,\n 'ru' = 62,\n 'si' = 63,\n 'sk' = 64,\n 'sl' = 65,\n 'sq' = 66,\n 'sr-Latn' = 67,\n 'sr' = 68,\n 'sv' = 69,\n 'sw' = 70,\n 'ta' = 71,\n 'te' = 72,\n 'th' = 73,\n 'tr' = 74,\n 'uk' = 75,\n 'ur' = 76,\n 'uz' = 77,\n 'vi' = 78,\n 'zh' = 79,\n 'zh-HK' = 80,\n 'zh-TW' = 81,\n 'zu' = 82,\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 83,\n}\n\nexport const enum SyncSetting {\n CHROME_SYNC_DISABLED = 1,\n CHROME_SYNC_SETTINGS_DISABLED = 2,\n DEVTOOLS_SYNC_SETTING_DISABLED = 3,\n DEVTOOLS_SYNC_SETTING_ENABLED = 4,\n MAX_VALUE = 5,\n}\n\nexport const enum RecordingToggled {\n RECORDING_STARTED = 1,\n RECORDING_FINISHED = 2,\n MAX_VALUE = 3,\n}\n\nexport const enum RecordingAssertion {\n ASSERTION_ADDED = 1,\n PROPERTY_ASSERTION_EDITED = 2,\n ATTRIBUTE_ASSERTION_EDITED = 3,\n MAX_VALUE = 4,\n}\n\nexport const enum RecordingReplayFinished {\n SUCCESS = 1,\n TIMEOUT_ERROR_SELECTORS = 2,\n TIMEOUT_ERROR_TARGET = 3,\n OTHER_ERROR = 4,\n MAX_VALUE = 5,\n}\n\nexport const enum RecordingReplaySpeed {\n NORMAL = 1,\n SLOW = 2,\n VERY_SLOW = 3,\n EXTREMELY_SLOW = 4,\n MAX_VALUE = 5,\n}\n\nexport const enum RecordingReplayStarted {\n REPLAY_ONLY = 1,\n REPLAY_WITH_PERFORMANCE_TRACING = 2,\n REPLAY_VIA_EXTENSION = 3,\n MAX_VALUE = 4,\n}\n\nexport const enum RecordingEdited {\n SELECTOR_PICKER_USED = 1,\n STEP_ADDED = 2,\n STEP_REMOVED = 3,\n SELECTOR_ADDED = 4,\n SELECTOR_REMOVED = 5,\n SELECTOR_PART_ADDED = 6,\n SELECTOR_PART_EDITED = 7,\n SELECTOR_PART_REMOVED = 8,\n TYPE_CHANGED = 9,\n OTHER_EDITING = 10,\n MAX_VALUE = 11,\n}\n\nexport const enum RecordingExported {\n TO_PUPPETEER = 1,\n TO_JSON = 2,\n TO_PUPPETEER_REPLAY = 3,\n TO_EXTENSION = 4,\n TO_LIGHTHOUSE = 5,\n MAX_VALUE = 6,\n}\n\nexport const enum RecordingCodeToggled {\n CODE_SHOWN = 1,\n CODE_HIDDEN = 2,\n MAX_VALUE = 3,\n}\n\nexport const enum RecordingCopiedToClipboard {\n COPIED_RECORDING_WITH_PUPPETEER = 1,\n COPIED_RECORDING_WITH_JSON = 2,\n COPIED_RECORDING_WITH_REPLAY = 3,\n COPIED_RECORDING_WITH_EXTENSION = 4,\n COPIED_STEP_WITH_PUPPETEER = 5,\n COPIED_STEP_WITH_JSON = 6,\n COPIED_STEP_WITH_REPLAY = 7,\n COPIED_STEP_WITH_EXTENSION = 8,\n MAX_VALUE = 9,\n}\n\nexport const enum StyleTextCopied {\n DECLARATION_VIA_CHANGED_LINE = 1,\n ALL_CHANGES_VIA_STYLES_TAB = 2,\n DECLARATION_VIA_CONTEXT_MENU = 3,\n PROPERTY_VIA_CONTEXT_MENU = 4,\n VALUE_VIA_CONTEXT_MENU = 5,\n DECLARATION_AS_JS_VIA_CONTEXT_MENU = 6,\n RULE_VIA_CONTEXT_MENU = 7,\n ALL_DECLARATIONS_VIA_CONTEXT_MENU = 8,\n ALL_DECLARATINS_AS_JS_VIA_CONTEXT_MENU = 9,\n SELECTOR_VIA_CONTEXT_MENU = 10,\n MAX_VALUE = 11,\n}\n\nexport enum ManifestSectionCodes {\n /* eslint-disable @typescript-eslint/naming-convention -- Indexed access. */\n OtherSection = 0,\n 'Identity' = 1,\n 'Presentation' = 2,\n 'Protocol Handlers' = 3,\n 'Icons' = 4,\n 'Window Controls Overlay' = 5,\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 6,\n}\n\n// The names here match the CSSRuleValidator names in CSSRuleValidator.ts.\nexport const enum CSSHintType {\n OTHER = 0,\n ALIGN_CONTENT = 1,\n FLEX_ITEM = 2,\n FLEX_CONTAINER = 3,\n GRID_CONTAINER = 4,\n GRID_ITEM = 5,\n FLEX_GRID = 6,\n MULTICOL_FLEX_GRID = 7,\n PADDING = 8,\n POSITION = 9,\n Z_INDEX = 10,\n SIZING = 11,\n FLEX_OR_GRID_ITEM = 12,\n FONT_VARIATION_SETTINGS = 13,\n MAX_VALUE = 14,\n}\n\nexport const enum LighthouseModeRun {\n NAVIGATION = 0,\n TIMESPAN = 1,\n SNAPSHOT = 2,\n LEGACY_NAVIGATION = 3,\n MAX_VALUE = 4,\n}\n\nexport const enum LighthouseCategoryUsed {\n PERFORMANCE = 0,\n ACCESSIBILITY = 1,\n BEST_PRACTICES = 2,\n SEO = 3,\n PWA = 4,\n PUB_ADS = 5,\n MAX_VALUE = 6,\n}\n\nexport const enum SwatchType {\n VAR_LINK = 0,\n ANIMATION_NAME_LINK = 1,\n COLOR = 2,\n ANIMATION_TIMING = 3,\n SHADOW = 4,\n GRID = 5,\n FLEX = 6,\n ANGLE = 7,\n LENGTH = 8,\n POSITION_TRY_LINK = 10,\n MAX_VALUE = 11,\n}\n\nexport const enum BadgeType {\n GRID = 0,\n SUBGRID = 1,\n FLEX = 2,\n AD = 3,\n SCROLL_SNAP = 4,\n CONTAINER = 5,\n SLOT = 6,\n TOP_LAYER = 7,\n REVEAL = 8,\n MAX_VALUE = 9,\n}\n\nexport const enum AnimationsPlaybackRate {\n PERCENT_100 = 0,\n PERCENT_25 = 1,\n PERCENT_10 = 2,\n OTHER = 3,\n MAX_VALUE = 4,\n}\n\nexport const enum AnimationPointDragType {\n // Animation is dragged as a whole in the Animations panel.\n ANIMATION_DRAG = 0,\n // A keyframe point inside animation timeline is dragged.\n KEYFRAME_MOVE = 1,\n // Start point of the animation inside animation timeline is dragged.\n START_ENDPOINT_MOVE = 2,\n // Finish point of the animation inside animation timeline is dragged.\n FINISH_ENDPOINT_MOVE = 3,\n OTHER = 4,\n MAX_VALUE = 5,\n}\n"]} \ No newline at end of file +{"version":3,"file":"UserMetrics.js","sourceRoot":"","sources":["../../../../../../front_end/core/host/UserMetrics.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (C) 2011 Google Inc. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * * Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above\n * copyright notice, this list of conditions and the following disclaimer\n * in the documentation and/or other materials provided with the\n * distribution.\n * * Neither the name of Google Inc. nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport {InspectorFrontendHostInstance} from './InspectorFrontendHost.js';\nimport {EnumeratedHistogram} from './InspectorFrontendHostAPI.js';\n\nexport class UserMetrics {\n #panelChangedSinceLaunch: boolean;\n #firedLaunchHistogram: boolean;\n #launchPanelName: string;\n constructor() {\n this.#panelChangedSinceLaunch = false;\n this.#firedLaunchHistogram = false;\n this.#launchPanelName = '';\n }\n\n panelShown(panelName: string, isLaunching?: boolean): void {\n const code = PanelCodes[panelName as keyof typeof PanelCodes] || 0;\n InspectorFrontendHostInstance.recordEnumeratedHistogram(EnumeratedHistogram.PanelShown, code, PanelCodes.MAX_VALUE);\n InspectorFrontendHostInstance.recordUserMetricsAction('DevTools_PanelShown_' + panelName);\n // Store that the user has changed the panel so we know launch histograms should not be fired.\n if (!isLaunching) {\n this.#panelChangedSinceLaunch = true;\n }\n }\n\n panelShownInLocation(panelName: string, location: 'main'|'drawer'): void {\n const panelWithLocationName = `${panelName}-${location}`;\n const panelWithLocation = PanelWithLocation[panelWithLocationName as keyof typeof PanelWithLocation] || 0;\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.PanelShownInLocation,\n panelWithLocation,\n PanelWithLocation.MAX_VALUE,\n );\n }\n\n settingsPanelShown(settingsViewId: string): void {\n this.panelShown('settings-' + settingsViewId);\n }\n\n sourcesPanelFileDebugged(mediaType?: string): void {\n const code = (mediaType && MediaTypes[mediaType as keyof typeof MediaTypes]) || MediaTypes.Unknown;\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.SourcesPanelFileDebugged, code, MediaTypes.MAX_VALUE);\n }\n\n sourcesPanelFileOpened(mediaType?: string): void {\n const code = (mediaType && MediaTypes[mediaType as keyof typeof MediaTypes]) || MediaTypes.Unknown;\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.SourcesPanelFileOpened, code, MediaTypes.MAX_VALUE);\n }\n\n networkPanelResponsePreviewOpened(mediaType: string): void {\n const code = (mediaType && MediaTypes[mediaType as keyof typeof MediaTypes]) || MediaTypes.Unknown;\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.NetworkPanelResponsePreviewOpened, code, MediaTypes.MAX_VALUE);\n }\n\n actionTaken(action: Action): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(EnumeratedHistogram.ActionTaken, action, Action.MAX_VALUE);\n }\n\n panelLoaded(panelName: string, histogramName: string): void {\n if (this.#firedLaunchHistogram || panelName !== this.#launchPanelName) {\n return;\n }\n\n this.#firedLaunchHistogram = true;\n // Use rAF and window.setTimeout to ensure the marker is fired after layout and rendering.\n // This will give the most accurate representation of the tool being ready for a user.\n requestAnimationFrame(() => {\n window.setTimeout(() => {\n // Mark the load time so that we can pinpoint it more easily in a trace.\n performance.mark(histogramName);\n // If the user has switched panel before we finished loading, ignore the histogram,\n // since the launch timings will have been affected and are no longer valid.\n if (this.#panelChangedSinceLaunch) {\n return;\n }\n // This fires the event for the appropriate launch histogram.\n // The duration is measured as the time elapsed since the time origin of the document.\n InspectorFrontendHostInstance.recordPerformanceHistogram(histogramName, performance.now());\n }, 0);\n });\n }\n\n setLaunchPanel(panelName: string|null): void {\n this.#launchPanelName = (panelName as string);\n }\n\n performanceTraceLoad(measure: PerformanceMeasure): void {\n InspectorFrontendHostInstance.recordPerformanceHistogram('DevTools.TraceLoad', measure.duration);\n }\n\n keybindSetSettingChanged(keybindSet: string): void {\n const value = KeybindSetSettings[keybindSet as keyof typeof KeybindSetSettings] || 0;\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.KeybindSetSettingChanged, value, KeybindSetSettings.MAX_VALUE);\n }\n\n keyboardShortcutFired(actionId: string): void {\n const action =\n KeyboardShortcutAction[actionId as keyof typeof KeyboardShortcutAction] || KeyboardShortcutAction.OtherShortcut;\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.KeyboardShortcutFired, action, KeyboardShortcutAction.MAX_VALUE);\n }\n\n issuesPanelOpenedFrom(issueOpener: IssueOpener): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.IssuesPanelOpenedFrom, issueOpener, IssueOpener.MAX_VALUE);\n }\n\n issuesPanelIssueExpanded(issueExpandedCategory: string|undefined): void {\n if (issueExpandedCategory === undefined) {\n return;\n }\n\n const issueExpanded = IssueExpanded[issueExpandedCategory as keyof typeof IssueExpanded];\n\n if (issueExpanded === undefined) {\n return;\n }\n\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.IssuesPanelIssueExpanded, issueExpanded, IssueExpanded.MAX_VALUE);\n }\n\n issuesPanelResourceOpened(issueCategory: string, type: string): void {\n const key = issueCategory + type;\n const value = IssueResourceOpened[key as keyof typeof IssueResourceOpened];\n\n if (value === undefined) {\n return;\n }\n\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.IssuesPanelResourceOpened, value, IssueResourceOpened.MAX_VALUE);\n }\n\n issueCreated(code: string): void {\n const issueCreated = IssueCreated[code as keyof typeof IssueCreated];\n if (issueCreated === undefined) {\n return;\n }\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.IssueCreated, issueCreated, IssueCreated.MAX_VALUE);\n }\n\n experimentEnabledAtLaunch(experimentId: string): void {\n const experiment = DevtoolsExperiments[experimentId as keyof typeof DevtoolsExperiments];\n if (experiment === undefined) {\n return;\n }\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.ExperimentEnabledAtLaunch, experiment, DevtoolsExperiments.MAX_VALUE);\n }\n\n experimentDisabledAtLaunch(experimentId: string): void {\n const experiment = DevtoolsExperiments[experimentId as keyof typeof DevtoolsExperiments];\n if (experiment === undefined) {\n return;\n }\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.ExperimentDisabledAtLaunch, experiment, DevtoolsExperiments.MAX_VALUE);\n }\n\n experimentChanged(experimentId: string, isEnabled: boolean): void {\n const experiment = DevtoolsExperiments[experimentId as keyof typeof DevtoolsExperiments];\n if (experiment === undefined) {\n return;\n }\n const actionName = isEnabled ? EnumeratedHistogram.ExperimentEnabled : EnumeratedHistogram.ExperimentDisabled;\n InspectorFrontendHostInstance.recordEnumeratedHistogram(actionName, experiment, DevtoolsExperiments.MAX_VALUE);\n }\n\n developerResourceLoaded(developerResourceLoaded: DeveloperResourceLoaded): void {\n if (developerResourceLoaded >= DeveloperResourceLoaded.MAX_VALUE) {\n return;\n }\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.DeveloperResourceLoaded, developerResourceLoaded, DeveloperResourceLoaded.MAX_VALUE);\n }\n\n developerResourceScheme(developerResourceScheme: DeveloperResourceScheme): void {\n if (developerResourceScheme >= DeveloperResourceScheme.MAX_VALUE) {\n return;\n }\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.DeveloperResourceScheme, developerResourceScheme, DeveloperResourceScheme.MAX_VALUE);\n }\n\n language(language: Intl.UnicodeBCP47LocaleIdentifier): void {\n const languageCode = Language[language as keyof typeof Language];\n if (languageCode === undefined) {\n return;\n }\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.Language, languageCode, Language.MAX_VALUE);\n }\n\n syncSetting(devtoolsSyncSettingEnabled: boolean): void {\n InspectorFrontendHostInstance.getSyncInformation(syncInfo => {\n let settingValue = SyncSetting.CHROME_SYNC_DISABLED;\n if (syncInfo.isSyncActive && !syncInfo.arePreferencesSynced) {\n settingValue = SyncSetting.CHROME_SYNC_SETTINGS_DISABLED;\n } else if (syncInfo.isSyncActive && syncInfo.arePreferencesSynced) {\n settingValue = devtoolsSyncSettingEnabled ? SyncSetting.DEVTOOLS_SYNC_SETTING_ENABLED :\n SyncSetting.DEVTOOLS_SYNC_SETTING_DISABLED;\n }\n\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.SyncSetting, settingValue, SyncSetting.MAX_VALUE);\n });\n }\n\n recordingAssertion(value: RecordingAssertion): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.RecordingAssertion, value, RecordingAssertion.MAX_VALUE);\n }\n\n recordingToggled(value: RecordingToggled): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.RecordingToggled, value, RecordingToggled.MAX_VALUE);\n }\n\n recordingReplayFinished(value: RecordingReplayFinished): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.RecordingReplayFinished, value, RecordingReplayFinished.MAX_VALUE);\n }\n\n recordingReplaySpeed(value: RecordingReplaySpeed): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.RecordingReplaySpeed, value, RecordingReplaySpeed.MAX_VALUE);\n }\n\n recordingReplayStarted(value: RecordingReplayStarted): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.RecordingReplayStarted, value, RecordingReplayStarted.MAX_VALUE);\n }\n\n recordingEdited(value: RecordingEdited): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.RecordingEdited, value, RecordingEdited.MAX_VALUE);\n }\n\n recordingExported(value: RecordingExported): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.RecordingExported, value, RecordingExported.MAX_VALUE);\n }\n\n recordingCodeToggled(value: RecordingCodeToggled): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.RecordingCodeToggled, value, RecordingCodeToggled.MAX_VALUE);\n }\n\n recordingCopiedToClipboard(value: RecordingCopiedToClipboard): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.RecordingCopiedToClipboard, value, RecordingCopiedToClipboard.MAX_VALUE);\n }\n\n styleTextCopied(value: StyleTextCopied): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.StyleTextCopied, value, StyleTextCopied.MAX_VALUE);\n }\n\n manifestSectionSelected(sectionTitle: string): void {\n const code =\n ManifestSectionCodes[sectionTitle as keyof typeof ManifestSectionCodes] || ManifestSectionCodes.OtherSection;\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.ManifestSectionSelected, code, ManifestSectionCodes.MAX_VALUE);\n }\n\n cssHintShown(type: CSSHintType): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.CSSHintShown, type, CSSHintType.MAX_VALUE);\n }\n\n lighthouseModeRun(type: LighthouseModeRun): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.LighthouseModeRun, type, LighthouseModeRun.MAX_VALUE);\n }\n\n lighthouseCategoryUsed(type: LighthouseCategoryUsed): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.LighthouseCategoryUsed, type, LighthouseCategoryUsed.MAX_VALUE);\n }\n\n colorPickerOpenedFrom(type: ColorPickerOpenedFrom): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.ColorPickerOpenedFrom, type, ColorPickerOpenedFrom.MAX_VALUE);\n }\n\n cssPropertyDocumentation(type: CSSPropertyDocumentation): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.CSSPropertyDocumentation, type, CSSPropertyDocumentation.MAX_VALUE);\n }\n\n swatchActivated(swatch: SwatchType): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.SwatchActivated, swatch, SwatchType.MAX_VALUE);\n }\n\n animationPlaybackRateChanged(playbackRate: AnimationsPlaybackRate): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.AnimationPlaybackRateChanged, playbackRate, AnimationsPlaybackRate.MAX_VALUE);\n }\n\n animationPointDragged(dragType: AnimationPointDragType): void {\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.AnimationPointDragged, dragType, AnimationPointDragType.MAX_VALUE);\n }\n\n workspacesPopulated(wallClockTimeInMilliseconds: number): void {\n InspectorFrontendHostInstance.recordPerformanceHistogram(\n 'DevTools.Workspaces.PopulateWallClocktime', wallClockTimeInMilliseconds);\n }\n\n visualLoggingProcessingDone(timeInMilliseconds: number): void {\n InspectorFrontendHostInstance.recordPerformanceHistogram(\n 'DevTools.VisualLogging.ProcessingTime', timeInMilliseconds);\n }\n\n legacyResourceTypeFilterNumberOfSelectedChanged(itemCount: number): void {\n const boundItemCount = Math.max(Math.min(itemCount, ResourceType.MAX_VALUE - 1), 1);\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.LegacyResourceTypeFilterNumberOfSelectedChanged, boundItemCount, ResourceType.MAX_VALUE);\n }\n\n legacyResourceTypeFilterItemSelected(resourceTypeName: string): void {\n const resourceType = ResourceType[resourceTypeName as keyof typeof ResourceType];\n if (resourceType === undefined) {\n return;\n }\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.LegacyResourceTypeFilterItemSelected, resourceType, ResourceType.MAX_VALUE);\n }\n\n resourceTypeFilterNumberOfSelectedChanged(itemCount: number): void {\n const boundItemCount = Math.max(Math.min(itemCount, ResourceType.MAX_VALUE - 1), 1);\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.ResourceTypeFilterNumberOfSelectedChanged, boundItemCount, ResourceType.MAX_VALUE);\n }\n\n resourceTypeFilterItemSelected(resourceTypeName: string): void {\n const resourceType = ResourceType[resourceTypeName as keyof typeof ResourceType];\n if (resourceType === undefined) {\n return;\n }\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.ResourceTypeFilterItemSelected, resourceType, ResourceType.MAX_VALUE);\n }\n\n networkPanelMoreFiltersNumberOfSelectedChanged(itemCount: number): void {\n const boundItemCount = Math.max(Math.min(itemCount, NetworkPanelMoreFilters.MAX_VALUE), 0);\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.NetworkPanelMoreFiltersNumberOfSelectedChanged, boundItemCount,\n NetworkPanelMoreFilters.MAX_VALUE);\n }\n\n networkPanelMoreFiltersItemSelected(filterName: string): void {\n const filter = NetworkPanelMoreFilters[filterName as keyof typeof NetworkPanelMoreFilters];\n if (filter === undefined) {\n return;\n }\n InspectorFrontendHostInstance.recordEnumeratedHistogram(\n EnumeratedHistogram.NetworkPanelMoreFiltersItemSelected, filter, NetworkPanelMoreFilters.MAX_VALUE);\n }\n}\n\n/**\n * The numeric enum values are not necessarily continuous! It is possible that\n * values have been removed, which results in gaps in the sequence of values.\n * When adding a new value:\n * 1. Add an entry to the bottom of the enum before 'MAX_VALUE'.\n * 2. Set the value of the new entry to the current value of 'MAX_VALUE'.\n * 2. Increment the value of 'MAX_VALUE' by 1.\n * When removing a value which is no longer needed:\n * 1. Delete the line with the unneeded value\n * 2. Do not update any 'MAX_VALUE' or any other value.\n */\n\n// Codes below are used to collect UMA histograms in the Chromium port.\n// Do not change the values below, additional actions are needed on the Chromium side\n// in order to add more codes.\nexport enum Action {\n /* eslint-disable @typescript-eslint/naming-convention */\n WindowDocked = 1,\n WindowUndocked = 2,\n ScriptsBreakpointSet = 3,\n TimelineStarted = 4,\n ProfilesCPUProfileTaken = 5,\n ProfilesHeapProfileTaken = 6,\n ConsoleEvaluated = 8,\n FileSavedInWorkspace = 9,\n DeviceModeEnabled = 10,\n AnimationsPlaybackRateChanged = 11,\n RevisionApplied = 12,\n FileSystemDirectoryContentReceived = 13,\n StyleRuleEdited = 14,\n CommandEvaluatedInConsolePanel = 15,\n DOMPropertiesExpanded = 16,\n ResizedViewInResponsiveMode = 17,\n TimelinePageReloadStarted = 18,\n ConnectToNodeJSFromFrontend = 19,\n ConnectToNodeJSDirectly = 20,\n CpuThrottlingEnabled = 21,\n CpuProfileNodeFocused = 22,\n CpuProfileNodeExcluded = 23,\n SelectFileFromFilePicker = 24,\n SelectCommandFromCommandMenu = 25,\n ChangeInspectedNodeInElementsPanel = 26,\n StyleRuleCopied = 27,\n CoverageStarted = 28,\n LighthouseStarted = 29,\n LighthouseFinished = 30,\n ShowedThirdPartyBadges = 31,\n LighthouseViewTrace = 32,\n FilmStripStartedRecording = 33,\n CoverageReportFiltered = 34,\n CoverageStartedPerBlock = 35,\n 'SettingsOpenedFromGear-deprecated' = 36,\n 'SettingsOpenedFromMenu-deprecated' = 37,\n 'SettingsOpenedFromCommandMenu-deprecated' = 38,\n TabMovedToDrawer = 39,\n TabMovedToMainPanel = 40,\n CaptureCssOverviewClicked = 41,\n VirtualAuthenticatorEnvironmentEnabled = 42,\n SourceOrderViewActivated = 43,\n UserShortcutAdded = 44,\n ShortcutRemoved = 45,\n ShortcutModified = 46,\n CustomPropertyLinkClicked = 47,\n CustomPropertyEdited = 48,\n ServiceWorkerNetworkRequestClicked = 49,\n ServiceWorkerNetworkRequestClosedQuickly = 50,\n NetworkPanelServiceWorkerRespondWith = 51,\n NetworkPanelCopyValue = 52,\n ConsoleSidebarOpened = 53,\n PerfPanelTraceImported = 54,\n PerfPanelTraceExported = 55,\n StackFrameRestarted = 56,\n CaptureTestProtocolClicked = 57,\n BreakpointRemovedFromRemoveButton = 58,\n BreakpointGroupExpandedStateChanged = 59,\n HeaderOverrideFileCreated = 60,\n HeaderOverrideEnableEditingClicked = 61,\n HeaderOverrideHeaderAdded = 62,\n HeaderOverrideHeaderEdited = 63,\n HeaderOverrideHeaderRemoved = 64,\n HeaderOverrideHeadersFileEdited = 65,\n PersistenceNetworkOverridesEnabled = 66,\n PersistenceNetworkOverridesDisabled = 67,\n BreakpointRemovedFromContextMenu = 68,\n BreakpointsInFileRemovedFromRemoveButton = 69,\n BreakpointsInFileRemovedFromContextMenu = 70,\n BreakpointsInFileCheckboxToggled = 71,\n BreakpointsInFileEnabledDisabledFromContextMenu = 72,\n BreakpointConditionEditedFromSidebar = 73,\n WorkspaceTabAddFolder = 74,\n WorkspaceTabRemoveFolder = 75,\n OverrideTabAddFolder = 76,\n OverrideTabRemoveFolder = 77,\n WorkspaceSourceSelected = 78,\n OverridesSourceSelected = 79,\n StyleSheetInitiatorLinkClicked = 80,\n BreakpointRemovedFromGutterContextMenu = 81,\n BreakpointRemovedFromGutterToggle = 82,\n StylePropertyInsideKeyframeEdited = 83,\n OverrideContentFromSourcesContextMenu = 84,\n OverrideContentFromNetworkContextMenu = 85,\n OverrideScript = 86,\n OverrideStyleSheet = 87,\n OverrideDocument = 88,\n OverrideFetchXHR = 89,\n OverrideImage = 90,\n OverrideFont = 91,\n OverrideContentContextMenuSetup = 92,\n OverrideContentContextMenuAbandonSetup = 93,\n OverrideContentContextMenuActivateDisabled = 94,\n OverrideContentContextMenuOpenExistingFile = 95,\n OverrideContentContextMenuSaveNewFile = 96,\n ShowAllOverridesFromSourcesContextMenu = 97,\n ShowAllOverridesFromNetworkContextMenu = 98,\n AnimationGroupsCleared = 99,\n AnimationsPaused = 100,\n AnimationsResumed = 101,\n AnimatedNodeDescriptionClicked = 102,\n AnimationGroupScrubbed = 103,\n AnimationGroupReplayed = 104,\n OverrideTabDeleteFolderContextMenu = 105,\n WorkspaceDropFolder = 107,\n WorkspaceSelectFolder = 108,\n OverrideContentContextMenuSourceMappedWarning = 109,\n OverrideContentContextMenuRedirectToDeployed = 110,\n NewStyleRuleAdded = 111,\n TraceExpanded = 112,\n InsightConsoleMessageShown = 113,\n InsightRequestedViaContextMenu = 114,\n InsightRequestedViaHoverButton = 115,\n InsightRatedPositive = 117,\n InsightRatedNegative = 118,\n InsightClosed = 119,\n InsightErrored = 120,\n InsightHoverButtonShown = 121,\n SelfXssWarningConsoleMessageShown = 122,\n SelfXssWarningDialogShown = 123,\n SelfXssAllowPastingInConsole = 124,\n SelfXssAllowPastingInDialog = 125,\n ToggleEmulateFocusedPageFromStylesPaneOn = 126,\n ToggleEmulateFocusedPageFromStylesPaneOff = 127,\n ToggleEmulateFocusedPageFromRenderingTab = 128,\n ToggleEmulateFocusedPageFromCommandMenu = 129,\n InsightGenerated = 130,\n InsightErroredApi = 131,\n InsightErroredMarkdown = 132,\n ToggleShowWebVitals = 133,\n InsightErroredPermissionDenied = 134,\n InsightErroredCannotSend = 135,\n InsightErroredRequestFailed = 136,\n InsightErroredCannotParseChunk = 137,\n InsightErroredUnknownChunk = 138,\n InsightErroredOther = 139,\n AutofillReceived = 140,\n AutofillReceivedAndTabAutoOpened = 141,\n AnimationGroupSelected = 142,\n ScrollDrivenAnimationGroupSelected = 143,\n ScrollDrivenAnimationGroupScrubbed = 144,\n FreestylerOpenedFromElementsPanel = 145,\n FreestylerOpenedFromStylesTab = 146,\n ConsoleFilterByContext = 147,\n ConsoleFilterBySource = 148,\n ConsoleFilterByUrl = 149,\n InsightConsentReminderShown = 150,\n InsightConsentReminderCanceled = 151,\n InsightConsentReminderConfirmed = 152,\n InsightsOnboardingShown = 153,\n InsightsOnboardingCanceledOnPage1 = 154,\n InsightsOnboardingCanceledOnPage2 = 155,\n InsightsOnboardingConfirmed = 156,\n InsightsOnboardingNextPage = 157,\n InsightsOnboardingPrevPage = 158,\n InsightsOnboardingFeatureDisabled = 159,\n InsightsOptInTeaserShown = 160,\n InsightsOptInTeaserSettingsLinkClicked = 161,\n InsightsOptInTeaserConfirmedInSettings = 162,\n InsightsReminderTeaserShown = 163,\n InsightsReminderTeaserConfirmed = 164,\n InsightsReminderTeaserCanceled = 165,\n InsightsReminderTeaserSettingsLinkClicked = 166,\n InsightsReminderTeaserAbortedInSettings = 167,\n GeneratingInsightWithoutDisclaimer = 168,\n MAX_VALUE = 169,\n /* eslint-enable @typescript-eslint/naming-convention */\n}\n\nexport enum PanelCodes {\n /* eslint-disable @typescript-eslint/naming-convention */\n elements = 1,\n resources = 2,\n network = 3,\n sources = 4,\n timeline = 5,\n 'heap-profiler' = 6,\n console = 8,\n layers = 9,\n 'console-view' = 10,\n 'animations' = 11,\n 'network.config' = 12,\n 'rendering' = 13,\n 'sensors' = 14,\n 'sources.search' = 15,\n security = 16,\n 'js-profiler' = 17,\n lighthouse = 18,\n 'coverage' = 19,\n 'protocol-monitor' = 20,\n 'remote-devices' = 21,\n 'web-audio' = 22,\n 'changes.changes' = 23,\n 'performance.monitor' = 24,\n 'release-note' = 25,\n 'live-heap-profile' = 26,\n 'sources.quick' = 27,\n 'network.blocked-urls' = 28,\n 'settings-preferences' = 29,\n 'settings-workspace' = 30,\n 'settings-experiments' = 31,\n 'settings-blackbox' = 32,\n 'settings-devices' = 33,\n 'settings-throttling-conditions' = 34,\n 'settings-emulation-locations' = 35,\n 'settings-shortcuts' = 36,\n 'issues-pane' = 37,\n 'settings-keybinds' = 38,\n 'cssoverview' = 39,\n 'chrome-recorder' = 40,\n 'trust-tokens' = 41,\n 'reporting-api' = 42,\n 'interest-groups' = 43,\n 'back-forward-cache' = 44,\n 'service-worker-cache' = 45,\n 'background-service-background-fetch' = 46,\n 'background-service-background-sync' = 47,\n 'background-service-push-messaging' = 48,\n 'background-service-notifications' = 49,\n 'background-service-payment-handler' = 50,\n 'background-service-periodic-background-sync' = 51,\n 'service-workers' = 52,\n 'app-manifest' = 53,\n 'storage' = 54,\n 'cookies' = 55,\n 'frame-details' = 56,\n 'frame-resource' = 57,\n 'frame-window' = 58,\n 'frame-worker' = 59,\n 'dom-storage' = 60,\n 'indexed-db' = 61,\n 'web-sql' = 62,\n 'performance-insights' = 63,\n 'preloading' = 64,\n 'bounce-tracking-mitigations' = 65,\n 'developer-resources' = 66,\n 'autofill-view' = 67,\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 68,\n}\n\nexport enum PanelWithLocation {\n /* eslint-disable @typescript-eslint/naming-convention */\n 'elements-main' = 1,\n 'elements-drawer' = 2,\n 'resources-main' = 3,\n 'resources-drawer' = 4,\n 'network-main' = 5,\n 'network-drawer' = 6,\n 'sources-main' = 7,\n 'sources-drawer' = 8,\n 'timeline-main' = 9,\n 'timeline-drawer' = 10,\n 'heap_profiler-main' = 11,\n 'heap_profiler-drawer' = 12,\n 'console-main' = 13,\n 'console-drawer' = 14,\n 'layers-main' = 15,\n 'layers-drawer' = 16,\n 'console-view-main' = 17,\n 'console-view-drawer' = 18,\n 'animations-main' = 19,\n 'animations-drawer' = 20,\n 'network.config-main' = 21,\n 'network.config-drawer' = 22,\n 'rendering-main' = 23,\n 'rendering-drawer' = 24,\n 'sensors-main' = 25,\n 'sensors-drawer' = 26,\n 'sources.search-main' = 27,\n 'sources.search-drawer' = 28,\n 'security-main' = 29,\n 'security-drawer' = 30,\n 'lighthouse-main' = 33,\n 'lighthouse-drawer' = 34,\n 'coverage-main' = 35,\n 'coverage-drawer' = 36,\n 'protocol-monitor-main' = 37,\n 'protocol-monitor-drawer' = 38,\n 'remote-devices-main' = 39,\n 'remote-devices-drawer' = 40,\n 'web-audio-main' = 41,\n 'web-audio-drawer' = 42,\n 'changes.changes-main' = 43,\n 'changes.changes-drawer' = 44,\n 'performance.monitor-main' = 45,\n 'performance.monitor-drawer' = 46,\n 'release-note-main' = 47,\n 'release-note-drawer' = 48,\n 'live_heap_profile-main' = 49,\n 'live_heap_profile-drawer' = 50,\n 'sources.quick-main' = 51,\n 'sources.quick-drawer' = 52,\n 'network.blocked-urls-main' = 53,\n 'network.blocked-urls-drawer' = 54,\n 'settings-preferences-main' = 55,\n 'settings-preferences-drawer' = 56,\n 'settings-workspace-main' = 57,\n 'settings-workspace-drawer' = 58,\n 'settings-experiments-main' = 59,\n 'settings-experiments-drawer' = 60,\n 'settings-blackbox-main' = 61,\n 'settings-blackbox-drawer' = 62,\n 'settings-devices-main' = 63,\n 'settings-devices-drawer' = 64,\n 'settings-throttling-conditions-main' = 65,\n 'settings-throttling-conditions-drawer' = 66,\n 'settings-emulation-locations-main' = 67,\n 'settings-emulation-locations-drawer' = 68,\n 'settings-shortcuts-main' = 69,\n 'settings-shortcuts-drawer' = 70,\n 'issues-pane-main' = 71,\n 'issues-pane-drawer' = 72,\n 'settings-keybinds-main' = 73,\n 'settings-keybinds-drawer' = 74,\n 'cssoverview-main' = 75,\n 'cssoverview-drawer' = 76,\n 'chrome_recorder-main' = 77,\n 'chrome_recorder-drawer' = 78,\n 'trust_tokens-main' = 79,\n 'trust_tokens-drawer' = 80,\n 'reporting_api-main' = 81,\n 'reporting_api-drawer' = 82,\n 'interest_groups-main' = 83,\n 'interest_groups-drawer' = 84,\n 'back_forward_cache-main' = 85,\n 'back_forward_cache-drawer' = 86,\n 'service_worker_cache-main' = 87,\n 'service_worker_cache-drawer' = 88,\n 'background_service_backgroundFetch-main' = 89,\n 'background_service_backgroundFetch-drawer' = 90,\n 'background_service_backgroundSync-main' = 91,\n 'background_service_backgroundSync-drawer' = 92,\n 'background_service_pushMessaging-main' = 93,\n 'background_service_pushMessaging-drawer' = 94,\n 'background_service_notifications-main' = 95,\n 'background_service_notifications-drawer' = 96,\n 'background_service_paymentHandler-main' = 97,\n 'background_service_paymentHandler-drawer' = 98,\n 'background_service_periodicBackgroundSync-main' = 99,\n 'background_service_periodicBackgroundSync-drawer' = 100,\n 'service_workers-main' = 101,\n 'service_workers-drawer' = 102,\n 'app_manifest-main' = 103,\n 'app_manifest-drawer' = 104,\n 'storage-main' = 105,\n 'storage-drawer' = 106,\n 'cookies-main' = 107,\n 'cookies-drawer' = 108,\n 'frame_details-main' = 109,\n 'frame_details-drawer' = 110,\n 'frame_resource-main' = 111,\n 'frame_resource-drawer' = 112,\n 'frame_window-main' = 113,\n 'frame_window-drawer' = 114,\n 'frame_worker-main' = 115,\n 'frame_worker-drawer' = 116,\n 'dom_storage-main' = 117,\n 'dom_storage-drawer' = 118,\n 'indexed_db-main' = 119,\n 'indexed_db-drawer' = 120,\n 'web_sql-main' = 121,\n 'web_sql-drawer' = 122,\n 'performance_insights-main' = 123,\n 'performance_insights-drawer' = 124,\n 'preloading-main' = 125,\n 'preloading-drawer' = 126,\n 'bounce_tracking_mitigations-main' = 127,\n 'bounce_tracking_mitigations-drawer' = 128,\n 'developer-resources-main' = 129,\n 'developer-resources-drawer' = 130,\n 'autofill-view-main' = 131,\n 'autofill-view-drawer' = 132,\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 133,\n}\n\nexport enum ElementsSidebarTabCodes {\n /* eslint-disable @typescript-eslint/naming-convention */\n 'OtherSidebarPane' = 0,\n 'styles' = 1,\n 'computed' = 2,\n 'elements.layout' = 3,\n 'elements.event-listeners' = 4,\n 'elements.dom-breakpoints' = 5,\n 'elements.dom-properties' = 6,\n 'accessibility.view' = 7,\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 8,\n}\n\nexport enum MediaTypes {\n /* eslint-disable @typescript-eslint/naming-convention */\n Unknown = 0,\n 'text/css' = 2,\n 'text/html' = 3,\n 'application/xml' = 4,\n 'application/wasm' = 5,\n 'application/manifest+json' = 6,\n 'application/x-aspx' = 7,\n 'application/jsp' = 8,\n 'text/x-c++src' = 9,\n 'text/x-coffeescript' = 10,\n 'application/vnd.dart' = 11,\n 'text/typescript' = 12,\n 'text/typescript-jsx' = 13,\n 'application/json' = 14,\n 'text/x-csharp' = 15,\n 'text/x-java' = 16,\n 'text/x-less' = 17,\n 'application/x-httpd-php' = 18,\n 'text/x-python' = 19,\n 'text/x-sh' = 20,\n 'text/x-gss' = 21,\n 'text/x-sass' = 22,\n 'text/x-scss' = 23,\n 'text/markdown' = 24,\n 'text/x-clojure' = 25,\n 'text/jsx' = 26,\n 'text/x-go' = 27,\n 'text/x-kotlin' = 28,\n 'text/x-scala' = 29,\n 'text/x.svelte' = 30,\n 'text/javascript+plain' = 31,\n 'text/javascript+minified' = 32,\n 'text/javascript+sourcemapped' = 33,\n 'text/x.angular' = 34,\n 'text/x.vue' = 35,\n 'text/javascript+snippet' = 36,\n 'text/javascript+eval' = 37, // Scripts resulting from console inputs or page \"eval\"s with no sourceUrl comment.\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 38,\n}\n\nexport enum KeybindSetSettings {\n /* eslint-disable @typescript-eslint/naming-convention */\n 'devToolsDefault' = 0,\n 'vsCode' = 1,\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 2,\n}\n\nexport enum KeyboardShortcutAction {\n /* eslint-disable @typescript-eslint/naming-convention */\n OtherShortcut = 0,\n 'quick-open.show-command-menu' = 1,\n 'console.clear' = 2,\n 'console.toggle' = 3,\n 'debugger.step' = 4,\n 'debugger.step-into' = 5,\n 'debugger.step-out' = 6,\n 'debugger.step-over' = 7,\n 'debugger.toggle-breakpoint' = 8,\n 'debugger.toggle-breakpoint-enabled' = 9,\n 'debugger.toggle-pause' = 10,\n 'elements.edit-as-html' = 11,\n 'elements.hide-element' = 12,\n 'elements.redo' = 13,\n 'elements.toggle-element-search' = 14,\n 'elements.undo' = 15,\n 'main.search-in-panel.find' = 16,\n 'main.toggle-drawer' = 17,\n 'network.hide-request-details' = 18,\n 'network.search' = 19,\n 'network.toggle-recording' = 20,\n 'quick-open.show' = 21,\n 'settings.show' = 22,\n 'sources.search' = 23,\n 'background-service.toggle-recording' = 24,\n 'components.collect-garbage' = 25,\n 'console.clear.history' = 26,\n 'console.create-pin' = 27,\n 'coverage.start-with-reload' = 28,\n 'coverage.toggle-recording' = 29,\n 'debugger.breakpoint-input-window' = 30,\n 'debugger.evaluate-selection' = 31,\n 'debugger.next-call-frame' = 32,\n 'debugger.previous-call-frame' = 33,\n 'debugger.run-snippet' = 34,\n 'debugger.toggle-breakpoints-active' = 35,\n 'elements.capture-area-screenshot' = 36,\n 'emulation.capture-full-height-screenshot' = 37,\n 'emulation.capture-node-screenshot' = 38,\n 'emulation.capture-screenshot' = 39,\n 'emulation.show-sensors' = 40,\n 'emulation.toggle-device-mode' = 41,\n 'help.release-notes' = 42,\n 'help.report-issue' = 43,\n 'input.start-replaying' = 44,\n 'input.toggle-pause' = 45,\n 'input.toggle-recording' = 46,\n 'inspector-main.focus-debuggee' = 47,\n 'inspector-main.hard-reload' = 48,\n 'inspector-main.reload' = 49,\n 'live-heap-profile.start-with-reload' = 50,\n 'live-heap-profile.toggle-recording' = 51,\n 'main.debug-reload' = 52,\n 'main.next-tab' = 53,\n 'main.previous-tab' = 54,\n 'main.search-in-panel.cancel' = 55,\n 'main.search-in-panel.find-next' = 56,\n 'main.search-in-panel.find-previous' = 57,\n 'main.toggle-dock' = 58,\n 'main.zoom-in' = 59,\n 'main.zoom-out' = 60,\n 'main.zoom-reset' = 61,\n 'network-conditions.network-low-end-mobile' = 62,\n 'network-conditions.network-mid-tier-mobile' = 63,\n 'network-conditions.network-offline' = 64,\n 'network-conditions.network-online' = 65,\n 'profiler.heap-toggle-recording' = 66,\n 'profiler.js-toggle-recording' = 67,\n 'resources.clear' = 68,\n 'settings.documentation' = 69,\n 'settings.shortcuts' = 70,\n 'sources.add-folder-to-workspace' = 71,\n 'sources.add-to-watch' = 72,\n 'sources.close-all' = 73,\n 'sources.close-editor-tab' = 74,\n 'sources.create-snippet' = 75,\n 'sources.go-to-line' = 76,\n 'sources.go-to-member' = 77,\n 'sources.jump-to-next-location' = 78,\n 'sources.jump-to-previous-location' = 79,\n 'sources.rename' = 80,\n 'sources.save' = 81,\n 'sources.save-all' = 82,\n 'sources.switch-file' = 83,\n 'timeline.jump-to-next-frame' = 84,\n 'timeline.jump-to-previous-frame' = 85,\n 'timeline.load-from-file' = 86,\n 'timeline.next-recording' = 87,\n 'timeline.previous-recording' = 88,\n 'timeline.record-reload' = 89,\n 'timeline.save-to-file' = 90,\n 'timeline.show-history' = 91,\n 'timeline.toggle-recording' = 92,\n 'sources.increment-css' = 93,\n 'sources.increment-css-by-ten' = 94,\n 'sources.decrement-css' = 95,\n 'sources.decrement-css-by-ten' = 96,\n 'layers.reset-view' = 97,\n 'layers.pan-mode' = 98,\n 'layers.rotate-mode' = 99,\n 'layers.zoom-in' = 100,\n 'layers.zoom-out' = 101,\n 'layers.up' = 102,\n 'layers.down' = 103,\n 'layers.left' = 104,\n 'layers.right' = 105,\n 'help.report-translation-issue' = 106,\n 'rendering.toggle-prefers-color-scheme' = 107,\n 'chrome-recorder.start-recording' = 108,\n 'chrome-recorder.replay-recording' = 109,\n 'chrome-recorder.toggle-code-view' = 110,\n 'chrome-recorder.copy-recording-or-step' = 111,\n 'changes.revert' = 112,\n 'changes.copy' = 113,\n 'elements.new-style-rule' = 114,\n 'elements.refresh-event-listeners' = 115,\n 'coverage.clear' = 116,\n 'coverage.export' = 117,\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 118,\n}\n\nexport const enum IssueOpener {\n CONSOLE_INFO_BAR = 0,\n LEARN_MORE_LINK_COEP = 1,\n STATUS_BAR_ISSUES_COUNTER = 2,\n HAMBURGER_MENU = 3,\n ADORNER = 4,\n COMMAND_MENU = 5,\n MAX_VALUE = 6,\n}\n\n/**\n * This list should contain the currently active Devtools Experiments,\n * gaps are expected.\n */\nexport enum DevtoolsExperiments {\n /* eslint-disable @typescript-eslint/naming-convention */\n 'apply-custom-stylesheet' = 0,\n 'capture-node-creation-stacks' = 1,\n 'live-heap-profile' = 11,\n 'protocol-monitor' = 13,\n 'sampling-heap-profiler-timeline' = 17,\n 'show-option-tp-expose-internals-in-heap-snapshot' = 18,\n 'timeline-invalidation-tracking' = 26,\n 'timeline-show-all-events' = 27,\n 'timeline-v8-runtime-call-stats' = 28,\n 'apca' = 39,\n 'font-editor' = 41,\n 'full-accessibility-tree' = 42,\n 'contrast-issues' = 44,\n 'experimental-cookie-features' = 45,\n 'styles-pane-css-changes' = 55,\n 'instrumentation-breakpoints' = 61,\n 'authored-deployed-grouping' = 63,\n 'just-my-code' = 65,\n 'highlight-errors-elements-panel' = 73,\n 'use-source-map-scopes' = 76,\n 'network-panel-filter-bar-redesign' = 79,\n 'autofill-view' = 82,\n 'css-type-component-length-deprecate' = 85,\n 'timeline-show-postmessage-events' = 86,\n 'timeline-enhanced-traces' = 90,\n 'timeline-compiled-sources' = 91,\n 'timeline-debug-mode' = 93,\n 'perf-panel-annotations' = 94,\n 'timeline-rpp-sidebar' = 95,\n 'timeline-observations' = 96,\n 'gen-ai-settings-panel' = 97,\n 'timeline-server-timings' = 98,\n 'timeline-layout-shift-details' = 99,\n 'extension-storage-viewer' = 100,\n /* eslint-enable @typescript-eslint/naming-convention */\n\n // Increment this when new experiments are added.\n MAX_VALUE = 101,\n}\n\nexport const enum ColorPickerOpenedFrom {\n SOURCES_PANEL = 0,\n STYLES_TAB = 1,\n MAX_VALUE = 2,\n}\n\nexport const enum CSSPropertyDocumentation {\n SHOWN = 0,\n TOGGLED_ON = 1,\n TOGGLED_OFF = 2,\n MAX_VALUE = 3,\n}\n\n// Update DevToolsIssuesPanelIssueExpanded from tools/metrics/histograms/enums.xml if new enum is added.\nexport enum IssueExpanded {\n /* eslint-disable @typescript-eslint/naming-convention */\n CrossOriginEmbedderPolicy = 0,\n MixedContent = 1,\n SameSiteCookie = 2,\n HeavyAd = 3,\n ContentSecurityPolicy = 4,\n Other = 5,\n Generic = 6,\n ThirdPartyPhaseoutCookie = 7,\n GenericCookie = 8,\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 9,\n}\n\nexport enum IssueResourceOpened {\n /* eslint-disable @typescript-eslint/naming-convention */\n CrossOriginEmbedderPolicyRequest = 0,\n CrossOriginEmbedderPolicyElement = 1,\n MixedContentRequest = 2,\n SameSiteCookieCookie = 3,\n SameSiteCookieRequest = 4,\n HeavyAdElement = 5,\n ContentSecurityPolicyDirective = 6,\n ContentSecurityPolicyElement = 7,\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 13,\n}\n\n/**\n * This list should contain the currently active issue types,\n * gaps are expected.\n */\nexport enum IssueCreated {\n /* eslint-disable @typescript-eslint/naming-convention */\n MixedContentIssue = 0,\n 'ContentSecurityPolicyIssue::kInlineViolation' = 1,\n 'ContentSecurityPolicyIssue::kEvalViolation' = 2,\n 'ContentSecurityPolicyIssue::kURLViolation' = 3,\n 'ContentSecurityPolicyIssue::kTrustedTypesSinkViolation' = 4,\n 'ContentSecurityPolicyIssue::kTrustedTypesPolicyViolation' = 5,\n 'HeavyAdIssue::NetworkTotalLimit' = 6,\n 'HeavyAdIssue::CpuTotalLimit' = 7,\n 'HeavyAdIssue::CpuPeakLimit' = 8,\n 'CrossOriginEmbedderPolicyIssue::CoepFrameResourceNeedsCoepHeader' = 9,\n 'CrossOriginEmbedderPolicyIssue::CoopSandboxedIFrameCannotNavigateToCoopPage' = 10,\n 'CrossOriginEmbedderPolicyIssue::CorpNotSameOrigin' = 11,\n 'CrossOriginEmbedderPolicyIssue::CorpNotSameOriginAfterDefaultedToSameOriginByCoep' = 12,\n 'CrossOriginEmbedderPolicyIssue::CorpNotSameSite' = 13,\n 'CookieIssue::ExcludeSameSiteNoneInsecure::ReadCookie' = 14,\n 'CookieIssue::ExcludeSameSiteNoneInsecure::SetCookie' = 15,\n 'CookieIssue::WarnSameSiteNoneInsecure::ReadCookie' = 16,\n 'CookieIssue::WarnSameSiteNoneInsecure::SetCookie' = 17,\n 'CookieIssue::WarnSameSiteStrictLaxDowngradeStrict::Secure' = 18,\n 'CookieIssue::WarnSameSiteStrictLaxDowngradeStrict::Insecure' = 19,\n 'CookieIssue::WarnCrossDowngrade::ReadCookie::Secure' = 20,\n 'CookieIssue::WarnCrossDowngrade::ReadCookie::Insecure' = 21,\n 'CookieIssue::WarnCrossDowngrade::SetCookie::Secure' = 22,\n 'CookieIssue::WarnCrossDowngrade::SetCookie::Insecure' = 23,\n 'CookieIssue::ExcludeNavigationContextDowngrade::Secure' = 24,\n 'CookieIssue::ExcludeNavigationContextDowngrade::Insecure' = 25,\n 'CookieIssue::ExcludeContextDowngrade::ReadCookie::Secure' = 26,\n 'CookieIssue::ExcludeContextDowngrade::ReadCookie::Insecure' = 27,\n 'CookieIssue::ExcludeContextDowngrade::SetCookie::Secure' = 28,\n 'CookieIssue::ExcludeContextDowngrade::SetCookie::Insecure' = 29,\n 'CookieIssue::ExcludeSameSiteUnspecifiedTreatedAsLax::ReadCookie' = 30,\n 'CookieIssue::ExcludeSameSiteUnspecifiedTreatedAsLax::SetCookie' = 31,\n 'CookieIssue::WarnSameSiteUnspecifiedLaxAllowUnsafe::ReadCookie' = 32,\n 'CookieIssue::WarnSameSiteUnspecifiedLaxAllowUnsafe::SetCookie' = 33,\n 'CookieIssue::WarnSameSiteUnspecifiedCrossSiteContext::ReadCookie' = 34,\n 'CookieIssue::WarnSameSiteUnspecifiedCrossSiteContext::SetCookie' = 35,\n 'SharedArrayBufferIssue::TransferIssue' = 36,\n 'SharedArrayBufferIssue::CreationIssue' = 37,\n LowTextContrastIssue = 41,\n 'CorsIssue::InsecurePrivateNetwork' = 42,\n 'CorsIssue::InvalidHeaders' = 44,\n 'CorsIssue::WildcardOriginWithCredentials' = 45,\n 'CorsIssue::PreflightResponseInvalid' = 46,\n 'CorsIssue::OriginMismatch' = 47,\n 'CorsIssue::AllowCredentialsRequired' = 48,\n 'CorsIssue::MethodDisallowedByPreflightResponse' = 49,\n 'CorsIssue::HeaderDisallowedByPreflightResponse' = 50,\n 'CorsIssue::RedirectContainsCredentials' = 51,\n 'CorsIssue::DisallowedByMode' = 52,\n 'CorsIssue::CorsDisabledScheme' = 53,\n 'CorsIssue::PreflightMissingAllowExternal' = 54,\n 'CorsIssue::PreflightInvalidAllowExternal' = 55,\n 'CorsIssue::NoCorsRedirectModeNotFollow' = 57,\n 'QuirksModeIssue::QuirksMode' = 58,\n 'QuirksModeIssue::LimitedQuirksMode' = 59,\n DeprecationIssue = 60,\n 'ClientHintIssue::MetaTagAllowListInvalidOrigin' = 61,\n 'ClientHintIssue::MetaTagModifiedHTML' = 62,\n 'CorsIssue::PreflightAllowPrivateNetworkError' = 63,\n 'GenericIssue::CrossOriginPortalPostMessageError' = 64,\n 'GenericIssue::FormLabelForNameError' = 65,\n 'GenericIssue::FormDuplicateIdForInputError' = 66,\n 'GenericIssue::FormInputWithNoLabelError' = 67,\n 'GenericIssue::FormAutocompleteAttributeEmptyError' = 68,\n 'GenericIssue::FormEmptyIdAndNameAttributesForInputError' = 69,\n 'GenericIssue::FormAriaLabelledByToNonExistingId' = 70,\n 'GenericIssue::FormInputAssignedAutocompleteValueToIdOrNameAttributeError' = 71,\n 'GenericIssue::FormLabelHasNeitherForNorNestedInput' = 72,\n 'GenericIssue::FormLabelForMatchesNonExistingIdError' = 73,\n 'GenericIssue::FormHasPasswordFieldWithoutUsernameFieldError' = 74,\n 'GenericIssue::FormInputHasWrongButWellIntendedAutocompleteValueError' = 75,\n 'StylesheetLoadingIssue::LateImportRule' = 76,\n 'StylesheetLoadingIssue::RequestFailed' = 77,\n 'CorsIssue::PreflightMissingPrivateNetworkAccessId' = 78,\n 'CorsIssue::PreflightMissingPrivateNetworkAccessName' = 79,\n 'CorsIssue::PrivateNetworkAccessPermissionUnavailable' = 80,\n 'CorsIssue::PrivateNetworkAccessPermissionDenied' = 81,\n 'CookieIssue::WarnThirdPartyPhaseout::ReadCookie' = 82,\n 'CookieIssue::WarnThirdPartyPhaseout::SetCookie' = 83,\n 'CookieIssue::ExcludeThirdPartyPhaseout::ReadCookie' = 84,\n 'CookieIssue::ExcludeThirdPartyPhaseout::SetCookie' = 85,\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 86,\n}\n\nexport const enum DeveloperResourceLoaded {\n LOAD_THROUGH_PAGE_VIA_TARGET = 0,\n LOAD_THROUGH_PAGE_VIA_FRAME = 1,\n LOAD_THROUGH_PAGE_FAILURE = 2,\n LOAD_THROUGH_PAGE_FALLBACK = 3,\n FALLBACK_AFTER_FAILURE = 4,\n FALLBACK_PER_OVERRIDE = 5,\n FALLBACK_PER_PROTOCOL = 6,\n FALLBACK_FAILURE = 7,\n MAX_VALUE = 8,\n}\n\nexport const enum DeveloperResourceScheme {\n OTHER = 0,\n UKNOWN = 1,\n HTTP = 2,\n HTTPS = 3,\n HTTP_LOCALHOST = 4,\n HTTPS_LOCALHOST = 5,\n DATA = 6,\n FILE = 7,\n BLOB = 8,\n MAX_VALUE = 9,\n}\n\nexport enum ResourceType {\n /* eslint-disable @typescript-eslint/naming-convention -- Used by web_tests. */\n all = 0,\n Document = 1,\n JavaScript = 2,\n 'Fetch and XHR' = 3,\n CSS = 4,\n Font = 5,\n Image = 6,\n Media = 7,\n Manifest = 8,\n WebSocket = 9,\n WebAssembly = 10,\n Other = 11,\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 12,\n}\n\nexport enum NetworkPanelMoreFilters {\n /* eslint-disable @typescript-eslint/naming-convention */\n 'Hide data URLs' = 0,\n 'Hide extension URLs' = 1,\n 'Blocked response cookies' = 2,\n 'Blocked requests' = 3,\n '3rd-party requests' = 4,\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 5,\n}\n\nexport enum Language {\n /* eslint-disable @typescript-eslint/naming-convention */\n 'af' = 1,\n 'am' = 2,\n 'ar' = 3,\n 'as' = 4,\n 'az' = 5,\n 'be' = 6,\n 'bg' = 7,\n 'bn' = 8,\n 'bs' = 9,\n 'ca' = 10,\n 'cs' = 11,\n 'cy' = 12,\n 'da' = 13,\n 'de' = 14,\n 'el' = 15,\n 'en-GB' = 16,\n 'en-US' = 17,\n 'es-419' = 18,\n 'es' = 19,\n 'et' = 20,\n 'eu' = 21,\n 'fa' = 22,\n 'fi' = 23,\n 'fil' = 24,\n 'fr-CA' = 25,\n 'fr' = 26,\n 'gl' = 27,\n 'gu' = 28,\n 'he' = 29,\n 'hi' = 30,\n 'hr' = 31,\n 'hu' = 32,\n 'hy' = 33,\n 'id' = 34,\n 'is' = 35,\n 'it' = 36,\n 'ja' = 37,\n 'ka' = 38,\n 'kk' = 39,\n 'km' = 40,\n 'kn' = 41,\n 'ko' = 42,\n 'ky' = 43,\n 'lo' = 44,\n 'lt' = 45,\n 'lv' = 46,\n 'mk' = 47,\n 'ml' = 48,\n 'mn' = 49,\n 'mr' = 50,\n 'ms' = 51,\n 'my' = 52,\n 'ne' = 53,\n 'nl' = 54,\n 'no' = 55,\n 'or' = 56,\n 'pa' = 57,\n 'pl' = 58,\n 'pt-PT' = 59,\n 'pt' = 60,\n 'ro' = 61,\n 'ru' = 62,\n 'si' = 63,\n 'sk' = 64,\n 'sl' = 65,\n 'sq' = 66,\n 'sr-Latn' = 67,\n 'sr' = 68,\n 'sv' = 69,\n 'sw' = 70,\n 'ta' = 71,\n 'te' = 72,\n 'th' = 73,\n 'tr' = 74,\n 'uk' = 75,\n 'ur' = 76,\n 'uz' = 77,\n 'vi' = 78,\n 'zh' = 79,\n 'zh-HK' = 80,\n 'zh-TW' = 81,\n 'zu' = 82,\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 83,\n}\n\nexport const enum SyncSetting {\n CHROME_SYNC_DISABLED = 1,\n CHROME_SYNC_SETTINGS_DISABLED = 2,\n DEVTOOLS_SYNC_SETTING_DISABLED = 3,\n DEVTOOLS_SYNC_SETTING_ENABLED = 4,\n MAX_VALUE = 5,\n}\n\nexport const enum RecordingToggled {\n RECORDING_STARTED = 1,\n RECORDING_FINISHED = 2,\n MAX_VALUE = 3,\n}\n\nexport const enum RecordingAssertion {\n ASSERTION_ADDED = 1,\n PROPERTY_ASSERTION_EDITED = 2,\n ATTRIBUTE_ASSERTION_EDITED = 3,\n MAX_VALUE = 4,\n}\n\nexport const enum RecordingReplayFinished {\n SUCCESS = 1,\n TIMEOUT_ERROR_SELECTORS = 2,\n TIMEOUT_ERROR_TARGET = 3,\n OTHER_ERROR = 4,\n MAX_VALUE = 5,\n}\n\nexport const enum RecordingReplaySpeed {\n NORMAL = 1,\n SLOW = 2,\n VERY_SLOW = 3,\n EXTREMELY_SLOW = 4,\n MAX_VALUE = 5,\n}\n\nexport const enum RecordingReplayStarted {\n REPLAY_ONLY = 1,\n REPLAY_WITH_PERFORMANCE_TRACING = 2,\n REPLAY_VIA_EXTENSION = 3,\n MAX_VALUE = 4,\n}\n\nexport const enum RecordingEdited {\n SELECTOR_PICKER_USED = 1,\n STEP_ADDED = 2,\n STEP_REMOVED = 3,\n SELECTOR_ADDED = 4,\n SELECTOR_REMOVED = 5,\n SELECTOR_PART_ADDED = 6,\n SELECTOR_PART_EDITED = 7,\n SELECTOR_PART_REMOVED = 8,\n TYPE_CHANGED = 9,\n OTHER_EDITING = 10,\n MAX_VALUE = 11,\n}\n\nexport const enum RecordingExported {\n TO_PUPPETEER = 1,\n TO_JSON = 2,\n TO_PUPPETEER_REPLAY = 3,\n TO_EXTENSION = 4,\n TO_LIGHTHOUSE = 5,\n MAX_VALUE = 6,\n}\n\nexport const enum RecordingCodeToggled {\n CODE_SHOWN = 1,\n CODE_HIDDEN = 2,\n MAX_VALUE = 3,\n}\n\nexport const enum RecordingCopiedToClipboard {\n COPIED_RECORDING_WITH_PUPPETEER = 1,\n COPIED_RECORDING_WITH_JSON = 2,\n COPIED_RECORDING_WITH_REPLAY = 3,\n COPIED_RECORDING_WITH_EXTENSION = 4,\n COPIED_STEP_WITH_PUPPETEER = 5,\n COPIED_STEP_WITH_JSON = 6,\n COPIED_STEP_WITH_REPLAY = 7,\n COPIED_STEP_WITH_EXTENSION = 8,\n MAX_VALUE = 9,\n}\n\nexport const enum StyleTextCopied {\n DECLARATION_VIA_CHANGED_LINE = 1,\n ALL_CHANGES_VIA_STYLES_TAB = 2,\n DECLARATION_VIA_CONTEXT_MENU = 3,\n PROPERTY_VIA_CONTEXT_MENU = 4,\n VALUE_VIA_CONTEXT_MENU = 5,\n DECLARATION_AS_JS_VIA_CONTEXT_MENU = 6,\n RULE_VIA_CONTEXT_MENU = 7,\n ALL_DECLARATIONS_VIA_CONTEXT_MENU = 8,\n ALL_DECLARATINS_AS_JS_VIA_CONTEXT_MENU = 9,\n SELECTOR_VIA_CONTEXT_MENU = 10,\n MAX_VALUE = 11,\n}\n\nexport enum ManifestSectionCodes {\n /* eslint-disable @typescript-eslint/naming-convention -- Indexed access. */\n OtherSection = 0,\n 'Identity' = 1,\n 'Presentation' = 2,\n 'Protocol Handlers' = 3,\n 'Icons' = 4,\n 'Window Controls Overlay' = 5,\n /* eslint-enable @typescript-eslint/naming-convention */\n MAX_VALUE = 6,\n}\n\n// The names here match the CSSRuleValidator names in CSSRuleValidator.ts.\nexport const enum CSSHintType {\n OTHER = 0,\n ALIGN_CONTENT = 1,\n FLEX_ITEM = 2,\n FLEX_CONTAINER = 3,\n GRID_CONTAINER = 4,\n GRID_ITEM = 5,\n FLEX_GRID = 6,\n MULTICOL_FLEX_GRID = 7,\n PADDING = 8,\n POSITION = 9,\n Z_INDEX = 10,\n SIZING = 11,\n FLEX_OR_GRID_ITEM = 12,\n FONT_VARIATION_SETTINGS = 13,\n MAX_VALUE = 14,\n}\n\nexport const enum LighthouseModeRun {\n NAVIGATION = 0,\n TIMESPAN = 1,\n SNAPSHOT = 2,\n LEGACY_NAVIGATION = 3,\n MAX_VALUE = 4,\n}\n\nexport const enum LighthouseCategoryUsed {\n PERFORMANCE = 0,\n ACCESSIBILITY = 1,\n BEST_PRACTICES = 2,\n SEO = 3,\n PWA = 4,\n PUB_ADS = 5,\n MAX_VALUE = 6,\n}\n\nexport const enum SwatchType {\n VAR_LINK = 0,\n ANIMATION_NAME_LINK = 1,\n COLOR = 2,\n ANIMATION_TIMING = 3,\n SHADOW = 4,\n GRID = 5,\n FLEX = 6,\n ANGLE = 7,\n LENGTH = 8,\n POSITION_TRY_LINK = 10,\n MAX_VALUE = 11,\n}\n\nexport const enum BadgeType {\n GRID = 0,\n SUBGRID = 1,\n FLEX = 2,\n AD = 3,\n SCROLL_SNAP = 4,\n CONTAINER = 5,\n SLOT = 6,\n TOP_LAYER = 7,\n REVEAL = 8,\n MAX_VALUE = 9,\n}\n\nexport const enum AnimationsPlaybackRate {\n PERCENT_100 = 0,\n PERCENT_25 = 1,\n PERCENT_10 = 2,\n OTHER = 3,\n MAX_VALUE = 4,\n}\n\nexport const enum AnimationPointDragType {\n // Animation is dragged as a whole in the Animations panel.\n ANIMATION_DRAG = 0,\n // A keyframe point inside animation timeline is dragged.\n KEYFRAME_MOVE = 1,\n // Start point of the animation inside animation timeline is dragged.\n START_ENDPOINT_MOVE = 2,\n // Finish point of the animation inside animation timeline is dragged.\n FINISH_ENDPOINT_MOVE = 3,\n OTHER = 4,\n MAX_VALUE = 5,\n}\n"]} \ No newline at end of file diff --git a/public/core/i18n/locales/en-US.json b/public/core/i18n/locales/en-US.json index cc78938a3..a8938ec6f 100644 --- a/public/core/i18n/locales/en-US.json +++ b/public/core/i18n/locales/en-US.json @@ -1 +1 @@ -{"core/common/ResourceType.ts | cspviolationreport":{"message":"CSPViolationReport"},"core/common/ResourceType.ts | css":{"message":"CSS"},"core/common/ResourceType.ts | doc":{"message":"Doc"},"core/common/ResourceType.ts | document":{"message":"Document"},"core/common/ResourceType.ts | eventsource":{"message":"EventSource"},"core/common/ResourceType.ts | fetch":{"message":"Fetch"},"core/common/ResourceType.ts | fetchAndXHR":{"message":"Fetch and XHR"},"core/common/ResourceType.ts | font":{"message":"Font"},"core/common/ResourceType.ts | image":{"message":"Image"},"core/common/ResourceType.ts | img":{"message":"Img"},"core/common/ResourceType.ts | javascript":{"message":"JavaScript"},"core/common/ResourceType.ts | js":{"message":"JS"},"core/common/ResourceType.ts | manifest":{"message":"Manifest"},"core/common/ResourceType.ts | media":{"message":"Media"},"core/common/ResourceType.ts | other":{"message":"Other"},"core/common/ResourceType.ts | ping":{"message":"Ping"},"core/common/ResourceType.ts | preflight":{"message":"Preflight"},"core/common/ResourceType.ts | script":{"message":"Script"},"core/common/ResourceType.ts | signedexchange":{"message":"SignedExchange"},"core/common/ResourceType.ts | stylesheet":{"message":"Stylesheet"},"core/common/ResourceType.ts | texttrack":{"message":"TextTrack"},"core/common/ResourceType.ts | wasm":{"message":"Wasm"},"core/common/ResourceType.ts | webassembly":{"message":"WebAssembly"},"core/common/ResourceType.ts | webbundle":{"message":"WebBundle"},"core/common/ResourceType.ts | websocket":{"message":"WebSocket"},"core/common/ResourceType.ts | webtransport":{"message":"WebTransport"},"core/common/ResourceType.ts | ws":{"message":"WS"},"core/common/Revealer.ts | applicationPanel":{"message":"Application panel"},"core/common/Revealer.ts | changesDrawer":{"message":"Changes drawer"},"core/common/Revealer.ts | developerResourcesPanel":{"message":"Developer Resources panel"},"core/common/Revealer.ts | elementsPanel":{"message":"Elements panel"},"core/common/Revealer.ts | issuesView":{"message":"Issues view"},"core/common/Revealer.ts | memoryInspectorPanel":{"message":"Memory inspector panel"},"core/common/Revealer.ts | networkPanel":{"message":"Network panel"},"core/common/Revealer.ts | sourcesPanel":{"message":"Sources panel"},"core/common/Revealer.ts | stylesSidebar":{"message":"styles sidebar"},"core/common/Revealer.ts | timelinePanel":{"message":"Performance panel"},"core/common/SettingRegistration.ts | adorner":{"message":"Adorner"},"core/common/SettingRegistration.ts | appearance":{"message":"Appearance"},"core/common/SettingRegistration.ts | console":{"message":"Console"},"core/common/SettingRegistration.ts | debugger":{"message":"Debugger"},"core/common/SettingRegistration.ts | elements":{"message":"Elements"},"core/common/SettingRegistration.ts | extension":{"message":"Extension"},"core/common/SettingRegistration.ts | global":{"message":"Global"},"core/common/SettingRegistration.ts | grid":{"message":"Grid"},"core/common/SettingRegistration.ts | memory":{"message":"Memory"},"core/common/SettingRegistration.ts | mobile":{"message":"Mobile"},"core/common/SettingRegistration.ts | network":{"message":"Network"},"core/common/SettingRegistration.ts | performance":{"message":"Performance"},"core/common/SettingRegistration.ts | persistence":{"message":"Persistence"},"core/common/SettingRegistration.ts | rendering":{"message":"Rendering"},"core/common/SettingRegistration.ts | sources":{"message":"Sources"},"core/common/SettingRegistration.ts | sync":{"message":"Sync"},"core/host/InspectorFrontendHost.ts | devtoolsS":{"message":"DevTools - {PH1}"},"core/host/ResourceLoader.ts | cacheError":{"message":"Cache error"},"core/host/ResourceLoader.ts | certificateError":{"message":"Certificate error"},"core/host/ResourceLoader.ts | certificateManagerError":{"message":"Certificate manager error"},"core/host/ResourceLoader.ts | connectionError":{"message":"Connection error"},"core/host/ResourceLoader.ts | decodingDataUrlFailed":{"message":"Decoding Data URL failed"},"core/host/ResourceLoader.ts | dnsResolverError":{"message":"DNS resolver error"},"core/host/ResourceLoader.ts | ftpError":{"message":"FTP error"},"core/host/ResourceLoader.ts | httpError":{"message":"HTTP error"},"core/host/ResourceLoader.ts | httpErrorStatusCodeSS":{"message":"HTTP error: status code {PH1}, {PH2}"},"core/host/ResourceLoader.ts | invalidUrl":{"message":"Invalid URL"},"core/host/ResourceLoader.ts | signedExchangeError":{"message":"Signed Exchange error"},"core/host/ResourceLoader.ts | systemError":{"message":"System error"},"core/host/ResourceLoader.ts | unknownError":{"message":"Unknown error"},"core/i18n/time-utilities.ts | fdays":{"message":"{PH1} days"},"core/i18n/time-utilities.ts | fhrs":{"message":"{PH1} hrs"},"core/i18n/time-utilities.ts | fmin":{"message":"{PH1} min"},"core/i18n/time-utilities.ts | fmms":{"message":"{PH1} μs"},"core/i18n/time-utilities.ts | fms":{"message":"{PH1} ms"},"core/i18n/time-utilities.ts | fs":{"message":"{PH1} s"},"core/sdk/ChildTargetManager.ts | main":{"message":"Main"},"core/sdk/CompilerSourceMappingContentProvider.ts | couldNotLoadContentForSS":{"message":"Could not load content for {PH1} ({PH2})"},"core/sdk/ConsoleModel.ts | bfcacheNavigation":{"message":"Navigation to {PH1} was restored from back/forward cache (see https://web.dev/bfcache/)"},"core/sdk/ConsoleModel.ts | failedToSaveToTempVariable":{"message":"Failed to save to temp variable."},"core/sdk/ConsoleModel.ts | navigatedToS":{"message":"Navigated to {PH1}"},"core/sdk/ConsoleModel.ts | profileSFinished":{"message":"Profile ''{PH1}'' finished."},"core/sdk/ConsoleModel.ts | profileSStarted":{"message":"Profile ''{PH1}'' started."},"core/sdk/CPUProfilerModel.ts | profileD":{"message":"Profile {PH1}"},"core/sdk/CSSStyleSheetHeader.ts | couldNotFindTheOriginalStyle":{"message":"Could not find the original style sheet."},"core/sdk/CSSStyleSheetHeader.ts | thereWasAnErrorRetrievingThe":{"message":"There was an error retrieving the source styles."},"core/sdk/DebuggerModel.ts | block":{"message":"Block"},"core/sdk/DebuggerModel.ts | catchBlock":{"message":"Catch block"},"core/sdk/DebuggerModel.ts | closure":{"message":"Closure"},"core/sdk/DebuggerModel.ts | exception":{"message":"Exception"},"core/sdk/DebuggerModel.ts | expression":{"message":"Expression"},"core/sdk/DebuggerModel.ts | global":{"message":"Global"},"core/sdk/DebuggerModel.ts | local":{"message":"Local"},"core/sdk/DebuggerModel.ts | module":{"message":"Module"},"core/sdk/DebuggerModel.ts | returnValue":{"message":"Return value"},"core/sdk/DebuggerModel.ts | script":{"message":"Script"},"core/sdk/DebuggerModel.ts | withBlock":{"message":"With block"},"core/sdk/NetworkManager.ts | fast4G":{"message":"Fast 4G"},"core/sdk/NetworkManager.ts | fastG":{"message":"Slow 4G"},"core/sdk/NetworkManager.ts | noContentForPreflight":{"message":"No content available for preflight request"},"core/sdk/NetworkManager.ts | noContentForRedirect":{"message":"No content available because this request was redirected"},"core/sdk/NetworkManager.ts | noContentForWebSocket":{"message":"Content for WebSockets is currently not supported"},"core/sdk/NetworkManager.ts | noThrottling":{"message":"No throttling"},"core/sdk/NetworkManager.ts | offline":{"message":"Offline"},"core/sdk/NetworkManager.ts | requestWasBlockedByDevtoolsS":{"message":"Request was blocked by DevTools: \"{PH1}\""},"core/sdk/NetworkManager.ts | sFailedLoadingSS":{"message":"{PH1} failed loading: {PH2} \"{PH3}\"."},"core/sdk/NetworkManager.ts | sFinishedLoadingSS":{"message":"{PH1} finished loading: {PH2} \"{PH3}\"."},"core/sdk/NetworkManager.ts | slowG":{"message":"3G"},"core/sdk/NetworkRequest.ts | anUnknownErrorWasEncounteredWhenTrying":{"message":"An unknown error was encountered when trying to store this cookie."},"core/sdk/NetworkRequest.ts | binary":{"message":"(binary)"},"core/sdk/NetworkRequest.ts | blockedReasonInvalidDomain":{"message":"This attempt to set a cookie via a Set-Cookie header was blocked because its Domain attribute was invalid with regards to the current host url."},"core/sdk/NetworkRequest.ts | blockedReasonInvalidPrefix":{"message":"This attempt to set a cookie via a Set-Cookie header was blocked because it used the \"__Secure-\" or \"__Host-\" prefix in its name and broke the additional rules applied to cookies with these prefixes as defined in https://tools.ietf.org/html/draft-west-cookie-prefixes-05."},"core/sdk/NetworkRequest.ts | blockedReasonOverwriteSecure":{"message":"This attempt to set a cookie via a Set-Cookie header was blocked because it was not sent over a secure connection and would have overwritten a cookie with the Secure attribute."},"core/sdk/NetworkRequest.ts | blockedReasonSameSiteNoneInsecure":{"message":"This attempt to set a cookie via a Set-Cookie header was blocked because it had the \"SameSite=None\" attribute but did not have the \"Secure\" attribute, which is required in order to use \"SameSite=None\"."},"core/sdk/NetworkRequest.ts | blockedReasonSameSiteStrictLax":{"message":"This attempt to set a cookie via a Set-Cookie header was blocked because it had the \"{PH1}\" attribute but came from a cross-site response which was not the response to a top-level navigation."},"core/sdk/NetworkRequest.ts | blockedReasonSameSiteUnspecifiedTreatedAsLax":{"message":"This Set-Cookie header didn't specify a \"SameSite\" attribute and was defaulted to \"SameSite=Lax,\" and was blocked because it came from a cross-site response which was not the response to a top-level navigation. The Set-Cookie had to have been set with \"SameSite=None\" to enable cross-site usage."},"core/sdk/NetworkRequest.ts | blockedReasonSecureOnly":{"message":"This attempt to set a cookie via a Set-Cookie header was blocked because it had the \"Secure\" attribute but was not received over a secure connection."},"core/sdk/NetworkRequest.ts | domainMismatch":{"message":"This cookie was blocked because neither did the request URL's domain exactly match the cookie's domain, nor was the request URL's domain a subdomain of the cookie's Domain attribute value."},"core/sdk/NetworkRequest.ts | exemptionReasonEnterprisePolicy":{"message":"This cookie is allowed by Chrome Enterprise policy. Learn more: goo.gle/ce-3pc"},"core/sdk/NetworkRequest.ts | exemptionReasonScheme":{"message":"This cookie is allowed by the top-level url scheme"},"core/sdk/NetworkRequest.ts | exemptionReasonStorageAccessAPI":{"message":"This cookie is allowed by the Storage Access API. Learn more: goo.gle/saa"},"core/sdk/NetworkRequest.ts | exemptionReasonTopLevelStorageAccessAPI":{"message":"This cookie is allowed by the top-level Storage Access API. Learn more: goo.gle/saa-top"},"core/sdk/NetworkRequest.ts | exemptionReasonTopLevelTPCDDeprecationTrial":{"message":"This cookie is allowed by top-level third-party cookie deprecation trial. Learn more: goo.gle/ps-dt."},"core/sdk/NetworkRequest.ts | exemptionReasonTPCDDeprecationTrial":{"message":"This cookie is allowed by third-party cookie deprecation trial. Learn more: goo.gle/ps-dt."},"core/sdk/NetworkRequest.ts | exemptionReasonTPCDHeuristics":{"message":"This cookie is allowed by third-party cookie heuristics. Learn more: goo.gle/hbe"},"core/sdk/NetworkRequest.ts | exemptionReasonTPCDMetadata":{"message":"This cookie is allowed by a third-party cookie deprecation trial grace period. Learn more: goo.gle/dt-grace."},"core/sdk/NetworkRequest.ts | exemptionReasonUserSetting":{"message":"This cookie is allowed by user preference."},"core/sdk/NetworkRequest.ts | nameValuePairExceedsMaxSize":{"message":"This cookie was blocked because it was too large. The combined size of the name and value must be less than or equal to 4096 characters."},"core/sdk/NetworkRequest.ts | notOnPath":{"message":"This cookie was blocked because its path was not an exact match for or a superdirectory of the request url's path."},"core/sdk/NetworkRequest.ts | samePartyFromCrossPartyContext":{"message":"This cookie was blocked because it had the \"SameParty\" attribute but the request was cross-party. The request was considered cross-party because the domain of the resource's URL and the domains of the resource's enclosing frames/documents are neither owners nor members in the same First-Party Set."},"core/sdk/NetworkRequest.ts | sameSiteLax":{"message":"This cookie was blocked because it had the \"SameSite=Lax\" attribute and the request was made from a different site and was not initiated by a top-level navigation."},"core/sdk/NetworkRequest.ts | sameSiteNoneInsecure":{"message":"This cookie was blocked because it had the \"SameSite=None\" attribute but was not marked \"Secure\". Cookies without SameSite restrictions must be marked \"Secure\" and sent over a secure connection."},"core/sdk/NetworkRequest.ts | sameSiteStrict":{"message":"This cookie was blocked because it had the \"SameSite=Strict\" attribute and the request was made from a different site. This includes top-level navigation requests initiated by other sites."},"core/sdk/NetworkRequest.ts | sameSiteUnspecifiedTreatedAsLax":{"message":"This cookie didn't specify a \"SameSite\" attribute when it was stored and was defaulted to \"SameSite=Lax,\" and was blocked because the request was made from a different site and was not initiated by a top-level navigation. The cookie had to have been set with \"SameSite=None\" to enable cross-site usage."},"core/sdk/NetworkRequest.ts | schemefulSameSiteLax":{"message":"This cookie was blocked because it had the \"SameSite=Lax\" attribute but the request was cross-site and was not initiated by a top-level navigation. This request is considered cross-site because the URL has a different scheme than the current site."},"core/sdk/NetworkRequest.ts | schemefulSameSiteStrict":{"message":"This cookie was blocked because it had the \"SameSite=Strict\" attribute but the request was cross-site. This includes top-level navigation requests initiated by other sites. This request is considered cross-site because the URL has a different scheme than the current site."},"core/sdk/NetworkRequest.ts | schemefulSameSiteUnspecifiedTreatedAsLax":{"message":"This cookie didn't specify a \"SameSite\" attribute when it was stored, was defaulted to \"SameSite=Lax\", and was blocked because the request was cross-site and was not initiated by a top-level navigation. This request is considered cross-site because the URL has a different scheme than the current site."},"core/sdk/NetworkRequest.ts | secureOnly":{"message":"This cookie was blocked because it had the \"Secure\" attribute and the connection was not secure."},"core/sdk/NetworkRequest.ts | setcookieHeaderIsIgnoredIn":{"message":"Set-Cookie header is ignored in response from url: {PH1}. The combined size of the name and value must be less than or equal to 4096 characters."},"core/sdk/NetworkRequest.ts | theSchemeOfThisConnectionIsNot":{"message":"The scheme of this connection is not allowed to store cookies."},"core/sdk/NetworkRequest.ts | thirdPartyPhaseout":{"message":"This cookie was blocked either because of Chrome flags or browser configuration. Learn more in the Issues panel."},"core/sdk/NetworkRequest.ts | thisSetcookieDidntSpecifyASamesite":{"message":"This Set-Cookie header didn't specify a \"SameSite\" attribute, was defaulted to \"SameSite=Lax\", and was blocked because it came from a cross-site response which was not the response to a top-level navigation. This response is considered cross-site because the URL has a different scheme than the current site."},"core/sdk/NetworkRequest.ts | thisSetcookieHadADisallowedCharacter":{"message":"This Set-Cookie header contained a disallowed character (a forbidden ASCII control character, or the tab character if it appears in the middle of the cookie name, value, an attribute name, or an attribute value)."},"core/sdk/NetworkRequest.ts | thisSetcookieHadInvalidSyntax":{"message":"This Set-Cookie header had invalid syntax."},"core/sdk/NetworkRequest.ts | thisSetcookieWasBlockedBecauseItHadTheSameparty":{"message":"This attempt to set a cookie via a Set-Cookie header was blocked because it had the \"SameParty\" attribute but the request was cross-party. The request was considered cross-party because the domain of the resource's URL and the domains of the resource's enclosing frames/documents are neither owners nor members in the same First-Party Set."},"core/sdk/NetworkRequest.ts | thisSetcookieWasBlockedBecauseItHadTheSamepartyAttribute":{"message":"This attempt to set a cookie via a Set-Cookie header was blocked because it had the \"SameParty\" attribute but also had other conflicting attributes. Chrome requires cookies that use the \"SameParty\" attribute to also have the \"Secure\" attribute, and to not be restricted to \"SameSite=Strict\"."},"core/sdk/NetworkRequest.ts | thisSetcookieWasBlockedBecauseItHadTheSamesiteStrictLax":{"message":"This attempt to set a cookie via a Set-Cookie header was blocked because it had the \"{PH1}\" attribute but came from a cross-site response which was not the response to a top-level navigation. This response is considered cross-site because the URL has a different scheme than the current site."},"core/sdk/NetworkRequest.ts | thisSetcookieWasBlockedBecauseTheNameValuePairExceedsMaxSize":{"message":"This attempt to set a cookie via a Set-Cookie header was blocked because the cookie was too large. The combined size of the name and value must be less than or equal to 4096 characters."},"core/sdk/NetworkRequest.ts | thisSetcookieWasBlockedDueThirdPartyPhaseout":{"message":"Setting this cookie was blocked either because of Chrome flags or browser configuration. Learn more in the Issues panel."},"core/sdk/NetworkRequest.ts | thisSetcookieWasBlockedDueToUser":{"message":"This attempt to set a cookie via a Set-Cookie header was blocked due to user preferences."},"core/sdk/NetworkRequest.ts | unknownError":{"message":"An unknown error was encountered when trying to send this cookie."},"core/sdk/NetworkRequest.ts | userPreferences":{"message":"This cookie was blocked due to user preferences."},"core/sdk/OverlayModel.ts | pausedInDebugger":{"message":"Paused in debugger"},"core/sdk/PageResourceLoader.ts | loadCanceledDueToReloadOf":{"message":"Load canceled due to reload of inspected page"},"core/sdk/Script.ts | scriptRemovedOrDeleted":{"message":"Script removed or deleted."},"core/sdk/Script.ts | unableToFetchScriptSource":{"message":"Unable to fetch script source."},"core/sdk/sdk-meta.ts | achromatopsia":{"message":"Achromatopsia (no color)"},"core/sdk/sdk-meta.ts | blurredVision":{"message":"Blurred vision"},"core/sdk/sdk-meta.ts | captureAsyncStackTraces":{"message":"Capture async stack traces"},"core/sdk/sdk-meta.ts | customFormatters":{"message":"Custom formatters"},"core/sdk/sdk-meta.ts | deuteranopia":{"message":"Deuteranopia (no green)"},"core/sdk/sdk-meta.ts | disableAsyncStackTraces":{"message":"Disable async stack traces"},"core/sdk/sdk-meta.ts | disableAvifFormat":{"message":"Disable AVIF format"},"core/sdk/sdk-meta.ts | disableCache":{"message":"Disable cache (while DevTools is open)"},"core/sdk/sdk-meta.ts | disableJavascript":{"message":"Disable JavaScript"},"core/sdk/sdk-meta.ts | disableLocalFonts":{"message":"Disable local fonts"},"core/sdk/sdk-meta.ts | disableNetworkRequestBlocking":{"message":"Disable network request blocking"},"core/sdk/sdk-meta.ts | disableWebpFormat":{"message":"Disable WebP format"},"core/sdk/sdk-meta.ts | doNotCaptureAsyncStackTraces":{"message":"Do not capture async stack traces"},"core/sdk/sdk-meta.ts | doNotEmulateAFocusedPage":{"message":"Do not emulate a focused page"},"core/sdk/sdk-meta.ts | doNotEmulateAnyVisionDeficiency":{"message":"Do not emulate any vision deficiency"},"core/sdk/sdk-meta.ts | doNotEmulateCss":{"message":"Do not emulate CSS {PH1}"},"core/sdk/sdk-meta.ts | doNotEmulateCssMediaType":{"message":"Do not emulate CSS media type"},"core/sdk/sdk-meta.ts | doNotExtendGridLines":{"message":"Do not extend grid lines"},"core/sdk/sdk-meta.ts | doNotHighlightAdFrames":{"message":"Do not highlight ad frames"},"core/sdk/sdk-meta.ts | doNotPauseOnExceptions":{"message":"Do not pause on exceptions"},"core/sdk/sdk-meta.ts | doNotPreserveLogUponNavigation":{"message":"Do not preserve log upon navigation"},"core/sdk/sdk-meta.ts | doNotShowGridNamedAreas":{"message":"Do not show grid named areas"},"core/sdk/sdk-meta.ts | doNotShowGridTrackSizes":{"message":"Do not show grid track sizes"},"core/sdk/sdk-meta.ts | doNotShowRulersOnHover":{"message":"Do not show rulers on hover"},"core/sdk/sdk-meta.ts | emulateAchromatopsia":{"message":"Emulate achromatopsia (no color)"},"core/sdk/sdk-meta.ts | emulateAFocusedPage":{"message":"Emulate a focused page"},"core/sdk/sdk-meta.ts | emulateAutoDarkMode":{"message":"Emulate auto dark mode"},"core/sdk/sdk-meta.ts | emulateBlurredVision":{"message":"Emulate blurred vision"},"core/sdk/sdk-meta.ts | emulateCss":{"message":"Emulate CSS {PH1}"},"core/sdk/sdk-meta.ts | emulateCssMediaFeature":{"message":"Emulate CSS media feature {PH1}"},"core/sdk/sdk-meta.ts | emulateCssMediaType":{"message":"Emulate CSS media type"},"core/sdk/sdk-meta.ts | emulateCssPrintMediaType":{"message":"Emulate CSS print media type"},"core/sdk/sdk-meta.ts | emulateCssScreenMediaType":{"message":"Emulate CSS screen media type"},"core/sdk/sdk-meta.ts | emulateDeuteranopia":{"message":"Emulate deuteranopia (no green)"},"core/sdk/sdk-meta.ts | emulateProtanopia":{"message":"Emulate protanopia (no red)"},"core/sdk/sdk-meta.ts | emulateReducedContrast":{"message":"Emulate reduced contrast"},"core/sdk/sdk-meta.ts | emulateTritanopia":{"message":"Emulate tritanopia (no blue)"},"core/sdk/sdk-meta.ts | emulateVisionDeficiencies":{"message":"Emulate vision deficiencies"},"core/sdk/sdk-meta.ts | enableAvifFormat":{"message":"Enable AVIF format"},"core/sdk/sdk-meta.ts | enableCache":{"message":"Enable cache"},"core/sdk/sdk-meta.ts | enableJavascript":{"message":"Enable JavaScript"},"core/sdk/sdk-meta.ts | enableLocalFonts":{"message":"Enable local fonts"},"core/sdk/sdk-meta.ts | enableNetworkRequestBlocking":{"message":"Enable network request blocking"},"core/sdk/sdk-meta.ts | enableRemoteFileLoading":{"message":"Allow DevTools to load resources, such as source maps, from remote file paths. Disabled by default for security reasons."},"core/sdk/sdk-meta.ts | enableWebpFormat":{"message":"Enable WebP format"},"core/sdk/sdk-meta.ts | extendGridLines":{"message":"Extend grid lines"},"core/sdk/sdk-meta.ts | hideCoreWebVitalsOverlay":{"message":"Hide Core Web Vitals overlay"},"core/sdk/sdk-meta.ts | hideFramesPerSecondFpsMeter":{"message":"Hide frames per second (FPS) meter"},"core/sdk/sdk-meta.ts | hideLayerBorders":{"message":"Hide layer borders"},"core/sdk/sdk-meta.ts | hideLayoutShiftRegions":{"message":"Hide layout shift regions"},"core/sdk/sdk-meta.ts | hideLineLabels":{"message":"Hide line labels"},"core/sdk/sdk-meta.ts | hidePaintFlashingRectangles":{"message":"Hide paint flashing rectangles"},"core/sdk/sdk-meta.ts | hideScrollPerformanceBottlenecks":{"message":"Hide scroll performance bottlenecks"},"core/sdk/sdk-meta.ts | highlightAdFrames":{"message":"Highlight ad frames"},"core/sdk/sdk-meta.ts | networkRequestBlocking":{"message":"Network request blocking"},"core/sdk/sdk-meta.ts | noEmulation":{"message":"No emulation"},"core/sdk/sdk-meta.ts | pauseOnExceptions":{"message":"Pause on exceptions"},"core/sdk/sdk-meta.ts | preserveLogUponNavigation":{"message":"Preserve log upon navigation"},"core/sdk/sdk-meta.ts | print":{"message":"print"},"core/sdk/sdk-meta.ts | protanopia":{"message":"Protanopia (no red)"},"core/sdk/sdk-meta.ts | query":{"message":"query"},"core/sdk/sdk-meta.ts | reducedContrast":{"message":"Reduced contrast"},"core/sdk/sdk-meta.ts | screen":{"message":"screen"},"core/sdk/sdk-meta.ts | showAreaNames":{"message":"Show area names"},"core/sdk/sdk-meta.ts | showCoreWebVitalsOverlay":{"message":"Show Core Web Vitals overlay"},"core/sdk/sdk-meta.ts | showFramesPerSecondFpsMeter":{"message":"Show frames per second (FPS) meter"},"core/sdk/sdk-meta.ts | showGridNamedAreas":{"message":"Show grid named areas"},"core/sdk/sdk-meta.ts | showGridTrackSizes":{"message":"Show grid track sizes"},"core/sdk/sdk-meta.ts | showLayerBorders":{"message":"Show layer borders"},"core/sdk/sdk-meta.ts | showLayoutShiftRegions":{"message":"Show layout shift regions"},"core/sdk/sdk-meta.ts | showLineLabels":{"message":"Show line labels"},"core/sdk/sdk-meta.ts | showLineNames":{"message":"Show line names"},"core/sdk/sdk-meta.ts | showLineNumbers":{"message":"Show line numbers"},"core/sdk/sdk-meta.ts | showPaintFlashingRectangles":{"message":"Show paint flashing rectangles"},"core/sdk/sdk-meta.ts | showRulersOnHover":{"message":"Show rulers on hover"},"core/sdk/sdk-meta.ts | showScrollPerformanceBottlenecks":{"message":"Show scroll performance bottlenecks"},"core/sdk/sdk-meta.ts | showTrackSizes":{"message":"Show track sizes"},"core/sdk/sdk-meta.ts | tritanopia":{"message":"Tritanopia (no blue)"},"core/sdk/ServerTiming.ts | deprecatedSyntaxFoundPleaseUse":{"message":"Deprecated syntax found. Please use: ;dur=;desc="},"core/sdk/ServerTiming.ts | duplicateParameterSIgnored":{"message":"Duplicate parameter \"{PH1}\" ignored."},"core/sdk/ServerTiming.ts | extraneousTrailingCharacters":{"message":"Extraneous trailing characters."},"core/sdk/ServerTiming.ts | noValueFoundForParameterS":{"message":"No value found for parameter \"{PH1}\"."},"core/sdk/ServerTiming.ts | unableToParseSValueS":{"message":"Unable to parse \"{PH1}\" value \"{PH2}\"."},"core/sdk/ServerTiming.ts | unrecognizedParameterS":{"message":"Unrecognized parameter \"{PH1}\"."},"core/sdk/ServiceWorkerCacheModel.ts | serviceworkercacheagentError":{"message":"ServiceWorkerCacheAgent error deleting cache entry {PH1} in cache: {PH2}"},"core/sdk/ServiceWorkerManager.ts | activated":{"message":"activated"},"core/sdk/ServiceWorkerManager.ts | activating":{"message":"activating"},"core/sdk/ServiceWorkerManager.ts | installed":{"message":"installed"},"core/sdk/ServiceWorkerManager.ts | installing":{"message":"installing"},"core/sdk/ServiceWorkerManager.ts | new":{"message":"new"},"core/sdk/ServiceWorkerManager.ts | redundant":{"message":"redundant"},"core/sdk/ServiceWorkerManager.ts | running":{"message":"running"},"core/sdk/ServiceWorkerManager.ts | sSS":{"message":"{PH1} #{PH2} ({PH3})"},"core/sdk/ServiceWorkerManager.ts | starting":{"message":"starting"},"core/sdk/ServiceWorkerManager.ts | stopped":{"message":"stopped"},"core/sdk/ServiceWorkerManager.ts | stopping":{"message":"stopping"},"core/sdk/SourceMapScopeChainEntry.ts | block":{"message":"Block"},"core/sdk/SourceMapScopeChainEntry.ts | closure":{"message":"Closure"},"core/sdk/SourceMapScopeChainEntry.ts | global":{"message":"Global"},"core/sdk/SourceMapScopeChainEntry.ts | local":{"message":"Local"},"core/sdk/SourceMapScopeChainEntry.ts | returnValue":{"message":"Return value"},"entrypoints/inspector_main/inspector_main-meta.ts | autoOpenDevTools":{"message":"Auto-open DevTools for popups"},"entrypoints/inspector_main/inspector_main-meta.ts | blockAds":{"message":"Block ads on this site"},"entrypoints/inspector_main/inspector_main-meta.ts | colorVisionDeficiency":{"message":"color vision deficiency"},"entrypoints/inspector_main/inspector_main-meta.ts | cssMediaFeature":{"message":"CSS media feature"},"entrypoints/inspector_main/inspector_main-meta.ts | cssMediaType":{"message":"CSS media type"},"entrypoints/inspector_main/inspector_main-meta.ts | disablePaused":{"message":"Disable paused state overlay"},"entrypoints/inspector_main/inspector_main-meta.ts | doNotAutoOpen":{"message":"Do not auto-open DevTools for popups"},"entrypoints/inspector_main/inspector_main-meta.ts | forceAdBlocking":{"message":"Force ad blocking on this site"},"entrypoints/inspector_main/inspector_main-meta.ts | fps":{"message":"fps"},"entrypoints/inspector_main/inspector_main-meta.ts | hardReloadPage":{"message":"Hard reload page"},"entrypoints/inspector_main/inspector_main-meta.ts | layout":{"message":"layout"},"entrypoints/inspector_main/inspector_main-meta.ts | paint":{"message":"paint"},"entrypoints/inspector_main/inspector_main-meta.ts | reloadPage":{"message":"Reload page"},"entrypoints/inspector_main/inspector_main-meta.ts | rendering":{"message":"Rendering"},"entrypoints/inspector_main/inspector_main-meta.ts | showAds":{"message":"Show ads on this site, if allowed"},"entrypoints/inspector_main/inspector_main-meta.ts | showRendering":{"message":"Show Rendering"},"entrypoints/inspector_main/inspector_main-meta.ts | toggleCssPrefersColorSchemeMedia":{"message":"Toggle CSS media feature prefers-color-scheme"},"entrypoints/inspector_main/inspector_main-meta.ts | visionDeficiency":{"message":"vision deficiency"},"entrypoints/inspector_main/InspectorMain.ts | javascriptIsDisabled":{"message":"JavaScript is disabled"},"entrypoints/inspector_main/InspectorMain.ts | main":{"message":"Main"},"entrypoints/inspector_main/InspectorMain.ts | openDedicatedTools":{"message":"Open dedicated DevTools for Node.js"},"entrypoints/inspector_main/InspectorMain.ts | tab":{"message":"Tab"},"entrypoints/inspector_main/OutermostTargetSelector.ts | targetNotSelected":{"message":"Page: Not selected"},"entrypoints/inspector_main/OutermostTargetSelector.ts | targetS":{"message":"Page: {PH1}"},"entrypoints/inspector_main/RenderingOptions.ts | coreWebVitals":{"message":"Core Web Vitals"},"entrypoints/inspector_main/RenderingOptions.ts | disableAvifImageFormat":{"message":"Disable AVIF image format"},"entrypoints/inspector_main/RenderingOptions.ts | disableLocalFonts":{"message":"Disable local fonts"},"entrypoints/inspector_main/RenderingOptions.ts | disablesLocalSourcesInFontface":{"message":"Disables local() sources in @font-face rules. Requires a page reload to apply."},"entrypoints/inspector_main/RenderingOptions.ts | disableWebpImageFormat":{"message":"Disable WebP image format"},"entrypoints/inspector_main/RenderingOptions.ts | emulateAFocusedPage":{"message":"Emulate a focused page"},"entrypoints/inspector_main/RenderingOptions.ts | emulateAutoDarkMode":{"message":"Enable automatic dark mode"},"entrypoints/inspector_main/RenderingOptions.ts | emulatesAFocusedPage":{"message":"Keep page focused. Commonly used for debugging disappearing elements."},"entrypoints/inspector_main/RenderingOptions.ts | emulatesAutoDarkMode":{"message":"Enables automatic dark mode and sets prefers-color-scheme to dark."},"entrypoints/inspector_main/RenderingOptions.ts | forcesCssColorgamutMediaFeature":{"message":"Forces CSS color-gamut media feature"},"entrypoints/inspector_main/RenderingOptions.ts | forcesCssForcedColors":{"message":"Forces CSS forced-colors media feature"},"entrypoints/inspector_main/RenderingOptions.ts | forcesCssPreferscolorschemeMedia":{"message":"Forces CSS prefers-color-scheme media feature"},"entrypoints/inspector_main/RenderingOptions.ts | forcesCssPreferscontrastMedia":{"message":"Forces CSS prefers-contrast media feature"},"entrypoints/inspector_main/RenderingOptions.ts | forcesCssPrefersreduceddataMedia":{"message":"Forces CSS prefers-reduced-data media feature"},"entrypoints/inspector_main/RenderingOptions.ts | forcesCssPrefersreducedmotion":{"message":"Forces CSS prefers-reduced-motion media feature"},"entrypoints/inspector_main/RenderingOptions.ts | forcesCssPrefersreducedtransparencyMedia":{"message":"Forces CSS prefers-reduced-transparency media feature"},"entrypoints/inspector_main/RenderingOptions.ts | forcesMediaTypeForTestingPrint":{"message":"Forces media type for testing print and screen styles"},"entrypoints/inspector_main/RenderingOptions.ts | forcesVisionDeficiencyEmulation":{"message":"Forces vision deficiency emulation"},"entrypoints/inspector_main/RenderingOptions.ts | frameRenderingStats":{"message":"Frame Rendering Stats"},"entrypoints/inspector_main/RenderingOptions.ts | highlightAdFrames":{"message":"Highlight ad frames"},"entrypoints/inspector_main/RenderingOptions.ts | highlightsAreasOfThePageBlueThat":{"message":"Highlights areas of the page (blue) that were shifted. May not be suitable for people prone to photosensitive epilepsy."},"entrypoints/inspector_main/RenderingOptions.ts | highlightsAreasOfThePageGreen":{"message":"Highlights areas of the page (green) that need to be repainted. May not be suitable for people prone to photosensitive epilepsy."},"entrypoints/inspector_main/RenderingOptions.ts | highlightsElementsTealThatCan":{"message":"Highlights elements (teal) that can slow down scrolling, including touch & wheel event handlers and other main-thread scrolling situations."},"entrypoints/inspector_main/RenderingOptions.ts | highlightsFramesRedDetectedToBe":{"message":"Highlights frames (red) detected to be ads."},"entrypoints/inspector_main/RenderingOptions.ts | layerBorders":{"message":"Layer borders"},"entrypoints/inspector_main/RenderingOptions.ts | layoutShiftRegions":{"message":"Layout shift regions"},"entrypoints/inspector_main/RenderingOptions.ts | paintFlashing":{"message":"Paint flashing"},"entrypoints/inspector_main/RenderingOptions.ts | plotsFrameThroughputDropped":{"message":"Plots frame throughput, dropped frames distribution, and GPU memory."},"entrypoints/inspector_main/RenderingOptions.ts | requiresAPageReloadToApplyAnd":{"message":"Requires a page reload to apply and disables caching for image requests."},"entrypoints/inspector_main/RenderingOptions.ts | scrollingPerformanceIssues":{"message":"Scrolling performance issues"},"entrypoints/inspector_main/RenderingOptions.ts | showsAnOverlayWithCoreWebVitals":{"message":"Shows an overlay with Core Web Vitals."},"entrypoints/inspector_main/RenderingOptions.ts | showsLayerBordersOrangeoliveAnd":{"message":"Shows layer borders (orange/olive) and tiles (cyan)."},"entrypoints/js_app/js_app.ts | main":{"message":"Main"},"entrypoints/js_app/js_app.ts | networkTitle":{"message":"Scripts"},"entrypoints/js_app/js_app.ts | showNode":{"message":"Show Scripts"},"entrypoints/main/main-meta.ts | auto":{"message":"auto"},"entrypoints/main/main-meta.ts | bottom":{"message":"Bottom"},"entrypoints/main/main-meta.ts | browserLanguage":{"message":"Browser UI language"},"entrypoints/main/main-meta.ts | browserPreference":{"message":"Browser preference"},"entrypoints/main/main-meta.ts | cancelSearch":{"message":"Cancel search"},"entrypoints/main/main-meta.ts | darkCapital":{"message":"Dark"},"entrypoints/main/main-meta.ts | darkLower":{"message":"dark"},"entrypoints/main/main-meta.ts | devtoolsDefault":{"message":"DevTools (Default)"},"entrypoints/main/main-meta.ts | dockToBottom":{"message":"Dock to bottom"},"entrypoints/main/main-meta.ts | dockToLeft":{"message":"Dock to left"},"entrypoints/main/main-meta.ts | dockToRight":{"message":"Dock to right"},"entrypoints/main/main-meta.ts | enableCtrlShortcutToSwitchPanels":{"message":"Enable Ctrl + 1-9 shortcut to switch panels"},"entrypoints/main/main-meta.ts | enableShortcutToSwitchPanels":{"message":"Enable ⌘ + 1-9 shortcut to switch panels"},"entrypoints/main/main-meta.ts | enableSync":{"message":"Enable settings sync"},"entrypoints/main/main-meta.ts | findNextResult":{"message":"Find next result"},"entrypoints/main/main-meta.ts | findPreviousResult":{"message":"Find previous result"},"entrypoints/main/main-meta.ts | focusDebuggee":{"message":"Focus page"},"entrypoints/main/main-meta.ts | horizontal":{"message":"horizontal"},"entrypoints/main/main-meta.ts | language":{"message":"Language:"},"entrypoints/main/main-meta.ts | left":{"message":"Left"},"entrypoints/main/main-meta.ts | lightCapital":{"message":"Light"},"entrypoints/main/main-meta.ts | lightLower":{"message":"light"},"entrypoints/main/main-meta.ts | matchChromeColorScheme":{"message":"Match Chrome color scheme"},"entrypoints/main/main-meta.ts | matchChromeColorSchemeDocumentation":{"message":"Match DevTools colors to your customized Chrome theme (when enabled)"},"entrypoints/main/main-meta.ts | nextPanel":{"message":"Next panel"},"entrypoints/main/main-meta.ts | panelLayout":{"message":"Panel layout:"},"entrypoints/main/main-meta.ts | previousPanel":{"message":"Previous panel"},"entrypoints/main/main-meta.ts | reloadDevtools":{"message":"Reload DevTools"},"entrypoints/main/main-meta.ts | resetZoomLevel":{"message":"Reset zoom level"},"entrypoints/main/main-meta.ts | restoreLastDockPosition":{"message":"Restore last dock position"},"entrypoints/main/main-meta.ts | right":{"message":"Right"},"entrypoints/main/main-meta.ts | searchAsYouTypeCommand":{"message":"Enable search as you type"},"entrypoints/main/main-meta.ts | searchAsYouTypeSetting":{"message":"Search as you type"},"entrypoints/main/main-meta.ts | searchInPanel":{"message":"Search in panel"},"entrypoints/main/main-meta.ts | searchOnEnterCommand":{"message":"Disable search as you type (press Enter to search)"},"entrypoints/main/main-meta.ts | switchToBrowserPreferredColor":{"message":"Switch to browser's preferred color theme"},"entrypoints/main/main-meta.ts | switchToDarkTheme":{"message":"Switch to dark theme"},"entrypoints/main/main-meta.ts | switchToLightTheme":{"message":"Switch to light theme"},"entrypoints/main/main-meta.ts | theme":{"message":"Theme:"},"entrypoints/main/main-meta.ts | toggleDrawer":{"message":"Toggle drawer"},"entrypoints/main/main-meta.ts | undocked":{"message":"Undocked"},"entrypoints/main/main-meta.ts | undockIntoSeparateWindow":{"message":"Undock into separate window"},"entrypoints/main/main-meta.ts | useAutomaticPanelLayout":{"message":"Use automatic panel layout"},"entrypoints/main/main-meta.ts | useHorizontalPanelLayout":{"message":"Use horizontal panel layout"},"entrypoints/main/main-meta.ts | useVerticalPanelLayout":{"message":"Use vertical panel layout"},"entrypoints/main/main-meta.ts | vertical":{"message":"vertical"},"entrypoints/main/main-meta.ts | zoomIn":{"message":"Zoom in"},"entrypoints/main/main-meta.ts | zoomOut":{"message":"Zoom out"},"entrypoints/main/MainImpl.ts | customizeAndControlDevtools":{"message":"Customize and control DevTools"},"entrypoints/main/MainImpl.ts | dockSide":{"message":"Dock side"},"entrypoints/main/MainImpl.ts | dockSideNaviation":{"message":"Use left and right arrow keys to navigate the options"},"entrypoints/main/MainImpl.ts | dockToBottom":{"message":"Dock to bottom"},"entrypoints/main/MainImpl.ts | dockToLeft":{"message":"Dock to left"},"entrypoints/main/MainImpl.ts | dockToRight":{"message":"Dock to right"},"entrypoints/main/MainImpl.ts | focusDebuggee":{"message":"Focus page"},"entrypoints/main/MainImpl.ts | help":{"message":"Help"},"entrypoints/main/MainImpl.ts | hideConsoleDrawer":{"message":"Hide console drawer"},"entrypoints/main/MainImpl.ts | moreTools":{"message":"More tools"},"entrypoints/main/MainImpl.ts | placementOfDevtoolsRelativeToThe":{"message":"Placement of DevTools relative to the page. ({PH1} to restore last position)"},"entrypoints/main/MainImpl.ts | showConsoleDrawer":{"message":"Show console drawer"},"entrypoints/main/MainImpl.ts | undockIntoSeparateWindow":{"message":"Undock into separate window"},"entrypoints/node_app/node_app.ts | connection":{"message":"Connection"},"entrypoints/node_app/node_app.ts | networkTitle":{"message":"Node"},"entrypoints/node_app/node_app.ts | node":{"message":"node"},"entrypoints/node_app/node_app.ts | showConnection":{"message":"Show Connection"},"entrypoints/node_app/node_app.ts | showNode":{"message":"Show Node"},"entrypoints/node_app/NodeConnectionsPanel.ts | addConnection":{"message":"Add connection"},"entrypoints/node_app/NodeConnectionsPanel.ts | networkAddressEgLocalhost":{"message":"Network address (e.g. localhost:9229)"},"entrypoints/node_app/NodeConnectionsPanel.ts | noConnectionsSpecified":{"message":"No connections specified"},"entrypoints/node_app/NodeConnectionsPanel.ts | nodejsDebuggingGuide":{"message":"Node.js debugging guide"},"entrypoints/node_app/NodeConnectionsPanel.ts | specifyNetworkEndpointAnd":{"message":"Specify network endpoint and DevTools will connect to it automatically. Read {PH1} to learn more."},"entrypoints/node_app/NodeMain.ts | main":{"message":"Main"},"entrypoints/node_app/NodeMain.ts | nodejsS":{"message":"Node.js: {PH1}"},"entrypoints/worker_app/WorkerMain.ts | main":{"message":"Main"},"generated/Deprecation.ts | AuthorizationCoveredByWildcard":{"message":"Authorization will not be covered by the wildcard symbol (*) in CORS Access-Control-Allow-Headers handling."},"generated/Deprecation.ts | CanRequestURLHTTPContainingNewline":{"message":"Resource requests whose URLs contained both removed whitespace \\(n|r|t) characters and less-than characters (<) are blocked. Please remove newlines and encode less-than characters from places like element attribute values in order to load these resources."},"generated/Deprecation.ts | ChromeLoadTimesConnectionInfo":{"message":"chrome.loadTimes() is deprecated, instead use standardized API: Navigation Timing 2."},"generated/Deprecation.ts | ChromeLoadTimesFirstPaintAfterLoadTime":{"message":"chrome.loadTimes() is deprecated, instead use standardized API: Paint Timing."},"generated/Deprecation.ts | ChromeLoadTimesWasAlternateProtocolAvailable":{"message":"chrome.loadTimes() is deprecated, instead use standardized API: nextHopProtocol in Navigation Timing 2."},"generated/Deprecation.ts | CookieWithTruncatingChar":{"message":"Cookies containing a \\(0|r|n) character will be rejected instead of truncated."},"generated/Deprecation.ts | CrossOriginAccessBasedOnDocumentDomain":{"message":"Relaxing the same-origin policy by setting document.domain is deprecated, and will be disabled by default. This deprecation warning is for a cross-origin access that was enabled by setting document.domain."},"generated/Deprecation.ts | CrossOriginWindowAlert":{"message":"Triggering window.alert from cross origin iframes has been deprecated and will be removed in the future."},"generated/Deprecation.ts | CrossOriginWindowConfirm":{"message":"Triggering window.confirm from cross origin iframes has been deprecated and will be removed in the future."},"generated/Deprecation.ts | CSSCustomStateDeprecatedSyntax":{"message":":--customstatename is deprecated. Please use the :state(customstatename) syntax instead."},"generated/Deprecation.ts | CSSInsetAreaProperty":{"message":"The inset-area property is deprecated. Please use the position-area property instead."},"generated/Deprecation.ts | CSSSelectorInternalMediaControlsOverlayCastButton":{"message":"The disableRemotePlayback attribute should be used in order to disable the default Cast integration instead of using -internal-media-controls-overlay-cast-button selector."},"generated/Deprecation.ts | CSSValueAppearanceSliderVertical":{"message":"CSS appearance value slider-vertical is not standardized and will be removed."},"generated/Deprecation.ts | DataUrlInSvgUse":{"message":"Support for data: URLs in SVGUseElement is deprecated and it will be removed in the future."},"generated/Deprecation.ts | DOMMutationEvents":{"message":"DOM Mutation Events, including DOMSubtreeModified, DOMNodeInserted, DOMNodeRemoved, DOMNodeRemovedFromDocument, DOMNodeInsertedIntoDocument, and DOMCharacterDataModified are deprecated (https://w3c.github.io/uievents/#legacy-event-types) and will be removed. Please use MutationObserver instead."},"generated/Deprecation.ts | GeolocationInsecureOrigin":{"message":"getCurrentPosition() and watchPosition() no longer work on insecure origins. To use this feature, you should consider switching your application to a secure origin, such as HTTPS. See https://goo.gle/chrome-insecure-origins for more details."},"generated/Deprecation.ts | GeolocationInsecureOriginDeprecatedNotRemoved":{"message":"getCurrentPosition() and watchPosition() are deprecated on insecure origins. To use this feature, you should consider switching your application to a secure origin, such as HTTPS. See https://goo.gle/chrome-insecure-origins for more details."},"generated/Deprecation.ts | GetInnerHTML":{"message":"The getInnerHTML() function is deprecated, and will be removed from this browser very soon. Please use getHTML() instead."},"generated/Deprecation.ts | GetUserMediaInsecureOrigin":{"message":"getUserMedia() no longer works on insecure origins. To use this feature, you should consider switching your application to a secure origin, such as HTTPS. See https://goo.gle/chrome-insecure-origins for more details."},"generated/Deprecation.ts | HostCandidateAttributeGetter":{"message":"RTCPeerConnectionIceErrorEvent.hostCandidate is deprecated. Please use RTCPeerConnectionIceErrorEvent.address or RTCPeerConnectionIceErrorEvent.port instead."},"generated/Deprecation.ts | IdentityInCanMakePaymentEvent":{"message":"The merchant origin and arbitrary data from the canmakepayment service worker event are deprecated and will be removed: topOrigin, paymentRequestOrigin, methodData, modifiers."},"generated/Deprecation.ts | InsecurePrivateNetworkSubresourceRequest":{"message":"The website requested a subresource from a network that it could only access because of its users' privileged network position. These requests expose non-public devices and servers to the internet, increasing the risk of a cross-site request forgery (CSRF) attack, and/or information leakage. To mitigate these risks, Chrome deprecates requests to non-public subresources when initiated from non-secure contexts, and will start blocking them."},"generated/Deprecation.ts | InterestGroupDailyUpdateUrl":{"message":"The dailyUpdateUrl field of InterestGroups passed to joinAdInterestGroup() has been renamed to updateUrl, to more accurately reflect its behavior."},"generated/Deprecation.ts | LocalCSSFileExtensionRejected":{"message":"CSS cannot be loaded from file: URLs unless they end in a .css file extension."},"generated/Deprecation.ts | MediaSourceAbortRemove":{"message":"Using SourceBuffer.abort() to abort remove()'s asynchronous range removal is deprecated due to specification change. Support will be removed in the future. You should listen to the updateend event instead. abort() is intended to only abort an asynchronous media append or reset parser state."},"generated/Deprecation.ts | MediaSourceDurationTruncatingBuffered":{"message":"Setting MediaSource.duration below the highest presentation timestamp of any buffered coded frames is deprecated due to specification change. Support for implicit removal of truncated buffered media will be removed in the future. You should instead perform explicit remove(newDuration, oldDuration) on all sourceBuffers, where newDuration < oldDuration."},"generated/Deprecation.ts | NoSysexWebMIDIWithoutPermission":{"message":"Web MIDI will ask a permission to use even if the sysex is not specified in the MIDIOptions."},"generated/Deprecation.ts | NotificationInsecureOrigin":{"message":"The Notification API may no longer be used from insecure origins. You should consider switching your application to a secure origin, such as HTTPS. See https://goo.gle/chrome-insecure-origins for more details."},"generated/Deprecation.ts | NotificationPermissionRequestedIframe":{"message":"Permission for the Notification API may no longer be requested from a cross-origin iframe. You should consider requesting permission from a top-level frame or opening a new window instead."},"generated/Deprecation.ts | ObsoleteCreateImageBitmapImageOrientationNone":{"message":"Option imageOrientation: 'none' in createImageBitmap is deprecated. Please use createImageBitmap with option {imageOrientation: 'from-image'} instead."},"generated/Deprecation.ts | ObsoleteWebRtcCipherSuite":{"message":"Your partner is negotiating an obsolete (D)TLS version. Please check with your partner to have this fixed."},"generated/Deprecation.ts | OverflowVisibleOnReplacedElement":{"message":"Specifying overflow: visible on img, video and canvas tags may cause them to produce visual content outside of the element bounds. See https://github.com/WICG/shared-element-transitions/blob/main/debugging_overflow_on_images.md."},"generated/Deprecation.ts | PaymentInstruments":{"message":"paymentManager.instruments is deprecated. Please use just-in-time install for payment handlers instead."},"generated/Deprecation.ts | PaymentRequestCSPViolation":{"message":"Your PaymentRequest call bypassed Content-Security-Policy (CSP) connect-src directive. This bypass is deprecated. Please add the payment method identifier from the PaymentRequest API (in supportedMethods field) to your CSP connect-src directive."},"generated/Deprecation.ts | PersistentQuotaType":{"message":"StorageType.persistent is deprecated. Please use standardized navigator.storage instead."},"generated/Deprecation.ts | PictureSourceSrc":{"message":" with a parent is invalid and therefore ignored. Please use instead."},"generated/Deprecation.ts | PrefixedCancelAnimationFrame":{"message":"webkitCancelAnimationFrame is vendor-specific. Please use the standard cancelAnimationFrame instead."},"generated/Deprecation.ts | PrefixedRequestAnimationFrame":{"message":"webkitRequestAnimationFrame is vendor-specific. Please use the standard requestAnimationFrame instead."},"generated/Deprecation.ts | PrefixedVideoDisplayingFullscreen":{"message":"HTMLVideoElement.webkitDisplayingFullscreen is deprecated. Please use Document.fullscreenElement instead."},"generated/Deprecation.ts | PrefixedVideoEnterFullscreen":{"message":"HTMLVideoElement.webkitEnterFullscreen() is deprecated. Please use Element.requestFullscreen() instead."},"generated/Deprecation.ts | PrefixedVideoEnterFullScreen":{"message":"HTMLVideoElement.webkitEnterFullScreen() is deprecated. Please use Element.requestFullscreen() instead."},"generated/Deprecation.ts | PrefixedVideoExitFullscreen":{"message":"HTMLVideoElement.webkitExitFullscreen() is deprecated. Please use Document.exitFullscreen() instead."},"generated/Deprecation.ts | PrefixedVideoExitFullScreen":{"message":"HTMLVideoElement.webkitExitFullScreen() is deprecated. Please use Document.exitFullscreen() instead."},"generated/Deprecation.ts | PrefixedVideoSupportsFullscreen":{"message":"HTMLVideoElement.webkitSupportsFullscreen is deprecated. Please use Document.fullscreenEnabled instead."},"generated/Deprecation.ts | PrivacySandboxExtensionsAPI":{"message":"We're deprecating the API chrome.privacy.websites.privacySandboxEnabled, though it will remain active for backward compatibility until release M113. Instead, please use chrome.privacy.websites.topicsEnabled, chrome.privacy.websites.fledgeEnabled and chrome.privacy.websites.adMeasurementEnabled. See https://developer.chrome.com/docs/extensions/reference/privacy/#property-websites-privacySandboxEnabled."},"generated/Deprecation.ts | RangeExpand":{"message":"Range.expand() is deprecated. Please use Selection.modify() instead."},"generated/Deprecation.ts | RequestedSubresourceWithEmbeddedCredentials":{"message":"Subresource requests whose URLs contain embedded credentials (e.g. https://user:pass@host/) are blocked."},"generated/Deprecation.ts | RTCConstraintEnableDtlsSrtpFalse":{"message":"The constraint DtlsSrtpKeyAgreement is removed. You have specified a false value for this constraint, which is interpreted as an attempt to use the removed SDES key negotiation method. This functionality is removed; use a service that supports DTLS key negotiation instead."},"generated/Deprecation.ts | RTCConstraintEnableDtlsSrtpTrue":{"message":"The constraint DtlsSrtpKeyAgreement is removed. You have specified a true value for this constraint, which had no effect, but you can remove this constraint for tidiness."},"generated/Deprecation.ts | RTCPeerConnectionGetStatsLegacyNonCompliant":{"message":"The callback-based getStats() is deprecated and will be removed. Use the spec-compliant getStats() instead."},"generated/Deprecation.ts | RtcpMuxPolicyNegotiate":{"message":"The rtcpMuxPolicy option is deprecated and will be removed."},"generated/Deprecation.ts | SharedArrayBufferConstructedWithoutIsolation":{"message":"SharedArrayBuffer will require cross-origin isolation. See https://developer.chrome.com/blog/enabling-shared-array-buffer/ for more details."},"generated/Deprecation.ts | TextToSpeech_DisallowedByAutoplay":{"message":"speechSynthesis.speak() without user activation is deprecated and will be removed."},"generated/Deprecation.ts | UnloadHandler":{"message":"Unload event listeners are deprecated and will be removed."},"generated/Deprecation.ts | V8GPUAdapter_RequestAdapterInfo_Method":{"message":"The GPUAdapter requestAdapterInfo() method is deprecated, instead use the GPUAdapter info attribute."},"generated/Deprecation.ts | V8SharedArrayBufferConstructedInExtensionWithoutIsolation":{"message":"Extensions should opt into cross-origin isolation to continue using SharedArrayBuffer. See https://developer.chrome.com/docs/extensions/mv3/cross-origin-isolation/."},"generated/Deprecation.ts | WebSQL":{"message":"Web SQL is deprecated. Please use SQLite WebAssembly or Indexed Database"},"generated/Deprecation.ts | XHRJSONEncodingDetection":{"message":"UTF-16 is not supported by response json in XMLHttpRequest"},"generated/Deprecation.ts | XMLHttpRequestSynchronousInNonWorkerOutsideBeforeUnload":{"message":"Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/."},"generated/Deprecation.ts | XRSupportsSession":{"message":"supportsSession() is deprecated. Please use isSessionSupported() and check the resolved boolean value instead."},"models/bindings/ContentProviderBasedProject.ts | unknownErrorLoadingFile":{"message":"Unknown error loading file"},"models/bindings/DebuggerLanguagePlugins.ts | debugSymbolsIncomplete":{"message":"The debug information for function {PH1} is incomplete"},"models/bindings/DebuggerLanguagePlugins.ts | errorInDebuggerLanguagePlugin":{"message":"Error in debugger language plugin: {PH1}"},"models/bindings/DebuggerLanguagePlugins.ts | failedToLoadDebugSymbolsFor":{"message":"[{PH1}] Failed to load debug symbols for {PH2} ({PH3})"},"models/bindings/DebuggerLanguagePlugins.ts | failedToLoadDebugSymbolsForFunction":{"message":"No debug information for function \"{PH1}\""},"models/bindings/DebuggerLanguagePlugins.ts | loadedDebugSymbolsForButDidnt":{"message":"[{PH1}] Loaded debug symbols for {PH2}, but didn't find any source files"},"models/bindings/DebuggerLanguagePlugins.ts | loadedDebugSymbolsForFound":{"message":"[{PH1}] Loaded debug symbols for {PH2}, found {PH3} source file(s)"},"models/bindings/DebuggerLanguagePlugins.ts | loadingDebugSymbolsFor":{"message":"[{PH1}] Loading debug symbols for {PH2}..."},"models/bindings/DebuggerLanguagePlugins.ts | loadingDebugSymbolsForVia":{"message":"[{PH1}] Loading debug symbols for {PH2} (via {PH3})..."},"models/bindings/IgnoreListManager.ts | addAllContentScriptsToIgnoreList":{"message":"Add all extension scripts to ignore list"},"models/bindings/IgnoreListManager.ts | addAllThirdPartyScriptsToIgnoreList":{"message":"Add all third-party scripts to ignore list"},"models/bindings/IgnoreListManager.ts | addDirectoryToIgnoreList":{"message":"Add directory to ignore list"},"models/bindings/IgnoreListManager.ts | addScriptToIgnoreList":{"message":"Add script to ignore list"},"models/bindings/IgnoreListManager.ts | removeFromIgnoreList":{"message":"Remove from ignore list"},"models/bindings/ResourceScriptMapping.ts | liveEditCompileFailed":{"message":"LiveEdit compile failed: {PH1}"},"models/bindings/ResourceScriptMapping.ts | liveEditFailed":{"message":"LiveEdit failed: {PH1}"},"models/emulation/DeviceModeModel.ts | devicePixelRatioMustBeANumberOr":{"message":"Device pixel ratio must be a number or blank."},"models/emulation/DeviceModeModel.ts | devicePixelRatioMustBeGreater":{"message":"Device pixel ratio must be greater than or equal to {PH1}."},"models/emulation/DeviceModeModel.ts | devicePixelRatioMustBeLessThanOr":{"message":"Device pixel ratio must be less than or equal to {PH1}."},"models/emulation/DeviceModeModel.ts | heightCannotBeEmpty":{"message":"Height cannot be empty."},"models/emulation/DeviceModeModel.ts | heightMustBeANumber":{"message":"Height must be a number."},"models/emulation/DeviceModeModel.ts | heightMustBeGreaterThanOrEqualTo":{"message":"Height must be greater than or equal to {PH1}."},"models/emulation/DeviceModeModel.ts | heightMustBeLessThanOrEqualToS":{"message":"Height must be less than or equal to {PH1}."},"models/emulation/DeviceModeModel.ts | widthCannotBeEmpty":{"message":"Width cannot be empty."},"models/emulation/DeviceModeModel.ts | widthMustBeANumber":{"message":"Width must be a number."},"models/emulation/DeviceModeModel.ts | widthMustBeGreaterThanOrEqualToS":{"message":"Width must be greater than or equal to {PH1}."},"models/emulation/DeviceModeModel.ts | widthMustBeLessThanOrEqualToS":{"message":"Width must be less than or equal to {PH1}."},"models/emulation/EmulatedDevices.ts | laptopWithHiDPIScreen":{"message":"Laptop with HiDPI screen"},"models/emulation/EmulatedDevices.ts | laptopWithMDPIScreen":{"message":"Laptop with MDPI screen"},"models/emulation/EmulatedDevices.ts | laptopWithTouch":{"message":"Laptop with touch"},"models/har/Writer.ts | collectingContent":{"message":"Collecting content…"},"models/har/Writer.ts | writingFile":{"message":"Writing file…"},"models/issues_manager/BounceTrackingIssue.ts | bounceTrackingMitigations":{"message":"Bounce tracking mitigations"},"models/issues_manager/ClientHintIssue.ts | clientHintsInfrastructure":{"message":"Client Hints Infrastructure"},"models/issues_manager/ContentSecurityPolicyIssue.ts | contentSecurityPolicyEval":{"message":"Content Security Policy - Eval"},"models/issues_manager/ContentSecurityPolicyIssue.ts | contentSecurityPolicyInlineCode":{"message":"Content Security Policy - Inline Code"},"models/issues_manager/ContentSecurityPolicyIssue.ts | contentSecurityPolicySource":{"message":"Content Security Policy - Source Allowlists"},"models/issues_manager/ContentSecurityPolicyIssue.ts | trustedTypesFixViolations":{"message":"Trusted Types - Fix violations"},"models/issues_manager/ContentSecurityPolicyIssue.ts | trustedTypesPolicyViolation":{"message":"Trusted Types - Policy violation"},"models/issues_manager/CookieDeprecationMetadataIssue.ts | thirdPartyPhaseoutExplained":{"message":"Changes to Chrome's treatment of third-party cookies"},"models/issues_manager/CookieIssue.ts | anInsecure":{"message":"an insecure"},"models/issues_manager/CookieIssue.ts | aSecure":{"message":"a secure"},"models/issues_manager/CookieIssue.ts | consoleTpcdErrorMessage":{"message":"Third-party cookie is blocked in Chrome either because of Chrome flags or browser configuration."},"models/issues_manager/CookieIssue.ts | consoleTpcdWarningMessage":{"message":"Chrome is moving towards a new experience that allows users to choose to browse without third-party cookies."},"models/issues_manager/CookieIssue.ts | fileCrosSiteRedirectBug":{"message":"File a bug"},"models/issues_manager/CookieIssue.ts | firstPartySetsExplained":{"message":"First-Party Sets and the SameParty attribute"},"models/issues_manager/CookieIssue.ts | howSchemefulSamesiteWorks":{"message":"How Schemeful Same-Site Works"},"models/issues_manager/CookieIssue.ts | samesiteCookiesExplained":{"message":"SameSite cookies explained"},"models/issues_manager/CookieIssue.ts | thirdPartyPhaseoutExplained":{"message":"Changes to Chrome's treatment of third-party cookies"},"models/issues_manager/CorsIssue.ts | CORS":{"message":"Cross-Origin Resource Sharing (CORS)"},"models/issues_manager/CorsIssue.ts | corsPrivateNetworkAccess":{"message":"Private Network Access"},"models/issues_manager/CrossOriginEmbedderPolicyIssue.ts | coopAndCoep":{"message":"COOP and COEP"},"models/issues_manager/CrossOriginEmbedderPolicyIssue.ts | samesiteAndSameorigin":{"message":"Same-Site and Same-Origin"},"models/issues_manager/DeprecationIssue.ts | feature":{"message":"Check the feature status page for more details."},"models/issues_manager/DeprecationIssue.ts | milestone":{"message":"This change will go into effect with milestone {milestone}."},"models/issues_manager/DeprecationIssue.ts | title":{"message":"Deprecated feature used"},"models/issues_manager/FederatedAuthRequestIssue.ts | fedCm":{"message":"Federated Credential Management API"},"models/issues_manager/FederatedAuthUserInfoRequestIssue.ts | fedCmUserInfo":{"message":"Federated Credential Management User Info API"},"models/issues_manager/GenericIssue.ts | autocompleteAttributePageTitle":{"message":"HTML attribute: autocomplete"},"models/issues_manager/GenericIssue.ts | corbExplainerPageTitle":{"message":"CORB explainer"},"models/issues_manager/GenericIssue.ts | howDoesAutofillWorkPageTitle":{"message":"How does autofill work?"},"models/issues_manager/GenericIssue.ts | inputFormElementPageTitle":{"message":"The form input element"},"models/issues_manager/GenericIssue.ts | labelFormlementsPageTitle":{"message":"The label elements"},"models/issues_manager/HeavyAdIssue.ts | handlingHeavyAdInterventions":{"message":"Handling Heavy Ad Interventions"},"models/issues_manager/Issue.ts | breakingChangeIssue":{"message":"A breaking change issue: the page may stop working in an upcoming version of Chrome"},"models/issues_manager/Issue.ts | breakingChanges":{"message":"Breaking Changes"},"models/issues_manager/Issue.ts | improvementIssue":{"message":"An improvement issue: there is an opportunity to improve the page"},"models/issues_manager/Issue.ts | improvements":{"message":"Improvements"},"models/issues_manager/Issue.ts | pageErrorIssue":{"message":"A page error issue: the page is not working correctly"},"models/issues_manager/Issue.ts | pageErrors":{"message":"Page Errors"},"models/issues_manager/LowTextContrastIssue.ts | colorAndContrastAccessibility":{"message":"Color and contrast accessibility"},"models/issues_manager/MixedContentIssue.ts | preventingMixedContent":{"message":"Preventing mixed content"},"models/issues_manager/QuirksModeIssue.ts | documentCompatibilityMode":{"message":"Document compatibility mode"},"models/issues_manager/SharedArrayBufferIssue.ts | enablingSharedArrayBuffer":{"message":"Enabling SharedArrayBuffer"},"models/issues_manager/SharedDictionaryIssue.ts | compressionDictionaryTransport":{"message":"Compression Dictionary Transport"},"models/logs/logs-meta.ts | clear":{"message":"clear"},"models/logs/logs-meta.ts | doNotPreserveLogOnPageReload":{"message":"Do not preserve log on page reload / navigation"},"models/logs/logs-meta.ts | preserve":{"message":"preserve"},"models/logs/logs-meta.ts | preserveLog":{"message":"Preserve log"},"models/logs/logs-meta.ts | preserveLogOnPageReload":{"message":"Preserve log on page reload / navigation"},"models/logs/logs-meta.ts | recordNetworkLog":{"message":"Record network log"},"models/logs/logs-meta.ts | reset":{"message":"reset"},"models/logs/NetworkLog.ts | anonymous":{"message":""},"models/persistence/EditFileSystemView.ts | add":{"message":"Add"},"models/persistence/EditFileSystemView.ts | enterAPath":{"message":"Enter a path"},"models/persistence/EditFileSystemView.ts | enterAUniquePath":{"message":"Enter a unique path"},"models/persistence/EditFileSystemView.ts | excludedFolders":{"message":"Excluded folders"},"models/persistence/EditFileSystemView.ts | folderPath":{"message":"Folder path"},"models/persistence/EditFileSystemView.ts | none":{"message":"None"},"models/persistence/EditFileSystemView.ts | sViaDevtools":{"message":"{PH1} (via .devtools)"},"models/persistence/IsolatedFileSystem.ts | blobCouldNotBeLoaded":{"message":"Blob could not be loaded."},"models/persistence/IsolatedFileSystem.ts | cantReadFileSS":{"message":"Can't read file: {PH1}: {PH2}"},"models/persistence/IsolatedFileSystem.ts | fileSystemErrorS":{"message":"File system error: {PH1}"},"models/persistence/IsolatedFileSystem.ts | linkedToS":{"message":"Linked to {PH1}"},"models/persistence/IsolatedFileSystemManager.ts | unableToAddFilesystemS":{"message":"Unable to add filesystem: {PH1}"},"models/persistence/persistence-meta.ts | disableOverrideNetworkRequests":{"message":"Disable override network requests"},"models/persistence/persistence-meta.ts | enableLocalOverrides":{"message":"Enable Local Overrides"},"models/persistence/persistence-meta.ts | enableOverrideNetworkRequests":{"message":"Enable override network requests"},"models/persistence/persistence-meta.ts | interception":{"message":"interception"},"models/persistence/persistence-meta.ts | network":{"message":"network"},"models/persistence/persistence-meta.ts | override":{"message":"override"},"models/persistence/persistence-meta.ts | request":{"message":"request"},"models/persistence/persistence-meta.ts | rewrite":{"message":"rewrite"},"models/persistence/persistence-meta.ts | showWorkspace":{"message":"Show Workspace settings"},"models/persistence/persistence-meta.ts | workspace":{"message":"Workspace"},"models/persistence/PersistenceActions.ts | openInContainingFolder":{"message":"Open in containing folder"},"models/persistence/PersistenceActions.ts | overrideContent":{"message":"Override content"},"models/persistence/PersistenceActions.ts | overrideSourceMappedFileExplanation":{"message":"‘{PH1}’ is a source mapped file and cannot be overridden."},"models/persistence/PersistenceActions.ts | overrideSourceMappedFileWarning":{"message":"Override ‘{PH1}’ instead?"},"models/persistence/PersistenceActions.ts | saveAs":{"message":"Save as..."},"models/persistence/PersistenceActions.ts | saveImage":{"message":"Save image"},"models/persistence/PersistenceActions.ts | saveWasmFailed":{"message":"Unable to save WASM module to disk. Most likely the module is too large."},"models/persistence/PersistenceActions.ts | showOverrides":{"message":"Show all overrides"},"models/persistence/PersistenceUtils.ts | linkedToS":{"message":"Linked to {PH1}"},"models/persistence/PersistenceUtils.ts | linkedToSourceMapS":{"message":"Linked to source map: {PH1}"},"models/persistence/PlatformFileSystem.ts | unableToReadFilesWithThis":{"message":"PlatformFileSystem cannot read files."},"models/persistence/WorkspaceSettingsTab.ts | addFolder":{"message":"Add folder…"},"models/persistence/WorkspaceSettingsTab.ts | folderExcludePattern":{"message":"Folder exclude pattern"},"models/persistence/WorkspaceSettingsTab.ts | mappingsAreInferredAutomatically":{"message":"Mappings are inferred automatically."},"models/persistence/WorkspaceSettingsTab.ts | remove":{"message":"Remove"},"models/persistence/WorkspaceSettingsTab.ts | workspace":{"message":"Workspace"},"models/timeline_model/TimelineJSProfile.ts | threadS":{"message":"Thread {PH1}"},"models/workspace/UISourceCode.ts | index":{"message":"(index)"},"models/workspace/UISourceCode.ts | thisFileWasChangedExternally":{"message":"This file was changed externally. Would you like to reload it?"},"panels/accessibility/accessibility-meta.ts | accessibility":{"message":"Accessibility"},"panels/accessibility/accessibility-meta.ts | shoAccessibility":{"message":"Show Accessibility"},"panels/accessibility/AccessibilityNodeView.ts | accessibilityNodeNotExposed":{"message":"Accessibility node not exposed"},"panels/accessibility/AccessibilityNodeView.ts | ancestorChildrenAreAll":{"message":"Ancestor's children are all presentational: "},"panels/accessibility/AccessibilityNodeView.ts | computedProperties":{"message":"Computed Properties"},"panels/accessibility/AccessibilityNodeView.ts | elementHasEmptyAltText":{"message":"Element has empty alt text."},"panels/accessibility/AccessibilityNodeView.ts | elementHasPlaceholder":{"message":"Element has {PH1}."},"panels/accessibility/AccessibilityNodeView.ts | elementIsHiddenBy":{"message":"Element is hidden by active modal dialog: "},"panels/accessibility/AccessibilityNodeView.ts | elementIsHiddenByChildTree":{"message":"Element is hidden by child tree: "},"panels/accessibility/AccessibilityNodeView.ts | elementIsInAnInertSubTree":{"message":"Element is in an inert subtree from "},"panels/accessibility/AccessibilityNodeView.ts | elementIsInert":{"message":"Element is inert."},"panels/accessibility/AccessibilityNodeView.ts | elementIsNotRendered":{"message":"Element is not rendered."},"panels/accessibility/AccessibilityNodeView.ts | elementIsNotVisible":{"message":"Element is not visible."},"panels/accessibility/AccessibilityNodeView.ts | elementIsPlaceholder":{"message":"Element is {PH1}."},"panels/accessibility/AccessibilityNodeView.ts | elementIsPresentational":{"message":"Element is presentational."},"panels/accessibility/AccessibilityNodeView.ts | elementNotInteresting":{"message":"Element not interesting for accessibility."},"panels/accessibility/AccessibilityNodeView.ts | elementsInheritsPresentational":{"message":"Element inherits presentational role from "},"panels/accessibility/AccessibilityNodeView.ts | invalidSource":{"message":"Invalid source."},"panels/accessibility/AccessibilityNodeView.ts | labelFor":{"message":"Label for "},"panels/accessibility/AccessibilityNodeView.ts | noAccessibilityNode":{"message":"No accessibility node"},"panels/accessibility/AccessibilityNodeView.ts | noNodeWithThisId":{"message":"No node with this ID."},"panels/accessibility/AccessibilityNodeView.ts | noTextContent":{"message":"No text content."},"panels/accessibility/AccessibilityNodeView.ts | notSpecified":{"message":"Not specified"},"panels/accessibility/AccessibilityNodeView.ts | partOfLabelElement":{"message":"Part of label element: "},"panels/accessibility/AccessibilityNodeView.ts | placeholderIsPlaceholderOnAncestor":{"message":"{PH1} is {PH2} on ancestor: "},"panels/accessibility/AccessibilityStrings.ts | activeDescendant":{"message":"Active descendant"},"panels/accessibility/AccessibilityStrings.ts | aHumanreadableVersionOfTheValue":{"message":"A human-readable version of the value of a range widget (where necessary)."},"panels/accessibility/AccessibilityStrings.ts | atomicLiveRegions":{"message":"Atomic (live regions)"},"panels/accessibility/AccessibilityStrings.ts | busyLiveRegions":{"message":"Busy (live regions)"},"panels/accessibility/AccessibilityStrings.ts | canSetValue":{"message":"Can set value"},"panels/accessibility/AccessibilityStrings.ts | checked":{"message":"Checked"},"panels/accessibility/AccessibilityStrings.ts | contents":{"message":"Contents"},"panels/accessibility/AccessibilityStrings.ts | controls":{"message":"Controls"},"panels/accessibility/AccessibilityStrings.ts | describedBy":{"message":"Described by"},"panels/accessibility/AccessibilityStrings.ts | description":{"message":"Description"},"panels/accessibility/AccessibilityStrings.ts | disabled":{"message":"Disabled"},"panels/accessibility/AccessibilityStrings.ts | editable":{"message":"Editable"},"panels/accessibility/AccessibilityStrings.ts | elementOrElementsWhichFormThe":{"message":"Element or elements which form the description of this element."},"panels/accessibility/AccessibilityStrings.ts | elementOrElementsWhichMayFormThe":{"message":"Element or elements which may form the name of this element."},"panels/accessibility/AccessibilityStrings.ts | elementOrElementsWhichShouldBe":{"message":"Element or elements which should be considered descendants of this element, despite not being descendants in the DOM."},"panels/accessibility/AccessibilityStrings.ts | elementOrElementsWhoseContentOr":{"message":"Element or elements whose content or presence is/are controlled by this widget."},"panels/accessibility/AccessibilityStrings.ts | elementToWhichTheUserMayChooseTo":{"message":"Element to which the user may choose to navigate after this one, instead of the next element in the DOM order."},"panels/accessibility/AccessibilityStrings.ts | expanded":{"message":"Expanded"},"panels/accessibility/AccessibilityStrings.ts | focusable":{"message":"Focusable"},"panels/accessibility/AccessibilityStrings.ts | focused":{"message":"Focused"},"panels/accessibility/AccessibilityStrings.ts | forARangeWidgetTheMaximumAllowed":{"message":"For a range widget, the maximum allowed value."},"panels/accessibility/AccessibilityStrings.ts | forARangeWidgetTheMinimumAllowed":{"message":"For a range widget, the minimum allowed value."},"panels/accessibility/AccessibilityStrings.ts | fromAttribute":{"message":"From attribute"},"panels/accessibility/AccessibilityStrings.ts | fromCaption":{"message":"From caption"},"panels/accessibility/AccessibilityStrings.ts | fromDescription":{"message":"From description"},"panels/accessibility/AccessibilityStrings.ts | fromLabel":{"message":"From label"},"panels/accessibility/AccessibilityStrings.ts | fromLabelFor":{"message":"From label (for= attribute)"},"panels/accessibility/AccessibilityStrings.ts | fromLabelWrapped":{"message":"From label (wrapped)"},"panels/accessibility/AccessibilityStrings.ts | fromLegend":{"message":"From legend"},"panels/accessibility/AccessibilityStrings.ts | fromNativeHtml":{"message":"From native HTML"},"panels/accessibility/AccessibilityStrings.ts | fromPlaceholderAttribute":{"message":"From placeholder attribute"},"panels/accessibility/AccessibilityStrings.ts | fromRubyAnnotation":{"message":"From ruby annotation"},"panels/accessibility/AccessibilityStrings.ts | fromStyle":{"message":"From style"},"panels/accessibility/AccessibilityStrings.ts | fromTitle":{"message":"From title"},"panels/accessibility/AccessibilityStrings.ts | hasAutocomplete":{"message":"Has autocomplete"},"panels/accessibility/AccessibilityStrings.ts | hasPopup":{"message":"Has popup"},"panels/accessibility/AccessibilityStrings.ts | help":{"message":"Help"},"panels/accessibility/AccessibilityStrings.ts | ifAndHowThisElementCanBeEdited":{"message":"If and how this element can be edited."},"panels/accessibility/AccessibilityStrings.ts | ifThisElementMayReceiveLive":{"message":"If this element may receive live updates, whether the entire live region should be presented to the user on changes, or only changed nodes."},"panels/accessibility/AccessibilityStrings.ts | ifThisElementMayReceiveLiveUpdates":{"message":"If this element may receive live updates, what type of updates should trigger a notification."},"panels/accessibility/AccessibilityStrings.ts | ifThisElementMayReceiveLiveUpdatesThe":{"message":"If this element may receive live updates, the root element of the containing live region."},"panels/accessibility/AccessibilityStrings.ts | ifTrueThisElementCanReceiveFocus":{"message":"If true, this element can receive focus."},"panels/accessibility/AccessibilityStrings.ts | ifTrueThisElementCurrentlyCannot":{"message":"If true, this element currently cannot be interacted with."},"panels/accessibility/AccessibilityStrings.ts | ifTrueThisElementCurrentlyHas":{"message":"If true, this element currently has focus."},"panels/accessibility/AccessibilityStrings.ts | ifTrueThisElementMayBeInteracted":{"message":"If true, this element may be interacted with, but its value cannot be changed."},"panels/accessibility/AccessibilityStrings.ts | ifTrueThisElementsUserentered":{"message":"If true, this element's user-entered value does not conform to validation requirement."},"panels/accessibility/AccessibilityStrings.ts | implicit":{"message":"Implicit"},"panels/accessibility/AccessibilityStrings.ts | implicitValue":{"message":"Implicit value."},"panels/accessibility/AccessibilityStrings.ts | indicatesThePurposeOfThisElement":{"message":"Indicates the purpose of this element, such as a user interface idiom for a widget, or structural role within a document."},"panels/accessibility/AccessibilityStrings.ts | invalidUserEntry":{"message":"Invalid user entry"},"panels/accessibility/AccessibilityStrings.ts | labeledBy":{"message":"Labeled by"},"panels/accessibility/AccessibilityStrings.ts | level":{"message":"Level"},"panels/accessibility/AccessibilityStrings.ts | liveRegion":{"message":"Live region"},"panels/accessibility/AccessibilityStrings.ts | liveRegionRoot":{"message":"Live region root"},"panels/accessibility/AccessibilityStrings.ts | maximumValue":{"message":"Maximum value"},"panels/accessibility/AccessibilityStrings.ts | minimumValue":{"message":"Minimum value"},"panels/accessibility/AccessibilityStrings.ts | multiline":{"message":"Multi-line"},"panels/accessibility/AccessibilityStrings.ts | multiselectable":{"message":"Multi-selectable"},"panels/accessibility/AccessibilityStrings.ts | orientation":{"message":"Orientation"},"panels/accessibility/AccessibilityStrings.ts | pressed":{"message":"Pressed"},"panels/accessibility/AccessibilityStrings.ts | readonlyString":{"message":"Read-only"},"panels/accessibility/AccessibilityStrings.ts | relatedElement":{"message":"Related element"},"panels/accessibility/AccessibilityStrings.ts | relevantLiveRegions":{"message":"Relevant (live regions)"},"panels/accessibility/AccessibilityStrings.ts | requiredString":{"message":"Required"},"panels/accessibility/AccessibilityStrings.ts | role":{"message":"Role"},"panels/accessibility/AccessibilityStrings.ts | selectedString":{"message":"Selected"},"panels/accessibility/AccessibilityStrings.ts | theAccessibleDescriptionForThis":{"message":"The accessible description for this element."},"panels/accessibility/AccessibilityStrings.ts | theComputedHelpTextForThis":{"message":"The computed help text for this element."},"panels/accessibility/AccessibilityStrings.ts | theComputedNameOfThisElement":{"message":"The computed name of this element."},"panels/accessibility/AccessibilityStrings.ts | theDescendantOfThisElementWhich":{"message":"The descendant of this element which is active; i.e. the element to which focus should be delegated."},"panels/accessibility/AccessibilityStrings.ts | theHierarchicalLevelOfThis":{"message":"The hierarchical level of this element."},"panels/accessibility/AccessibilityStrings.ts | theValueOfThisElementThisMayBe":{"message":"The value of this element; this may be user-provided or developer-provided, depending on the element."},"panels/accessibility/AccessibilityStrings.ts | value":{"message":"Value"},"panels/accessibility/AccessibilityStrings.ts | valueDescription":{"message":"Value description"},"panels/accessibility/AccessibilityStrings.ts | valueFromAttribute":{"message":"Value from attribute."},"panels/accessibility/AccessibilityStrings.ts | valueFromDescriptionElement":{"message":"Value from description element."},"panels/accessibility/AccessibilityStrings.ts | valueFromElementContents":{"message":"Value from element contents."},"panels/accessibility/AccessibilityStrings.ts | valueFromFigcaptionElement":{"message":"Value from figcaption element."},"panels/accessibility/AccessibilityStrings.ts | valueFromLabelElement":{"message":"Value from label element."},"panels/accessibility/AccessibilityStrings.ts | valueFromLabelElementWithFor":{"message":"Value from label element with for= attribute."},"panels/accessibility/AccessibilityStrings.ts | valueFromLabelElementWrapped":{"message":"Value from a wrapping label element."},"panels/accessibility/AccessibilityStrings.ts | valueFromLegendElement":{"message":"Value from legend element."},"panels/accessibility/AccessibilityStrings.ts | valueFromNativeHtmlRuby":{"message":"Value from plain HTML ruby annotation."},"panels/accessibility/AccessibilityStrings.ts | valueFromNativeHtmlUnknownSource":{"message":"Value from native HTML (unknown source)."},"panels/accessibility/AccessibilityStrings.ts | valueFromPlaceholderAttribute":{"message":"Value from placeholder attribute."},"panels/accessibility/AccessibilityStrings.ts | valueFromRelatedElement":{"message":"Value from related element."},"panels/accessibility/AccessibilityStrings.ts | valueFromStyle":{"message":"Value from style."},"panels/accessibility/AccessibilityStrings.ts | valueFromTableCaption":{"message":"Value from table caption."},"panels/accessibility/AccessibilityStrings.ts | valueFromTitleAttribute":{"message":"Value from title attribute."},"panels/accessibility/AccessibilityStrings.ts | whetherAndWhatPriorityOfLive":{"message":"Whether and what priority of live updates may be expected for this element."},"panels/accessibility/AccessibilityStrings.ts | whetherAndWhatTypeOfAutocomplete":{"message":"Whether and what type of autocomplete suggestions are currently provided by this element."},"panels/accessibility/AccessibilityStrings.ts | whetherAUserMaySelectMoreThanOne":{"message":"Whether a user may select more than one option from this widget."},"panels/accessibility/AccessibilityStrings.ts | whetherTheOptionRepresentedBy":{"message":"Whether the option represented by this element is currently selected."},"panels/accessibility/AccessibilityStrings.ts | whetherTheValueOfThisElementCan":{"message":"Whether the value of this element can be set."},"panels/accessibility/AccessibilityStrings.ts | whetherThisCheckboxRadioButtonOr":{"message":"Whether this checkbox, radio button or tree item is checked, unchecked, or mixed (e.g. has both checked and un-checked children)."},"panels/accessibility/AccessibilityStrings.ts | whetherThisElementHasCausedSome":{"message":"Whether this element has caused some kind of pop-up (such as a menu) to appear."},"panels/accessibility/AccessibilityStrings.ts | whetherThisElementIsARequired":{"message":"Whether this element is a required field in a form."},"panels/accessibility/AccessibilityStrings.ts | whetherThisElementOrAnother":{"message":"Whether this element, or another grouping element it controls, is expanded."},"panels/accessibility/AccessibilityStrings.ts | whetherThisElementOrItsSubtree":{"message":"Whether this element or its subtree are currently being updated (and thus may be in an inconsistent state)."},"panels/accessibility/AccessibilityStrings.ts | whetherThisLinearElements":{"message":"Whether this linear element's orientation is horizontal or vertical."},"panels/accessibility/AccessibilityStrings.ts | whetherThisTextBoxMayHaveMore":{"message":"Whether this text box may have more than one line."},"panels/accessibility/AccessibilityStrings.ts | whetherThisToggleButtonIs":{"message":"Whether this toggle button is currently in a pressed state."},"panels/accessibility/ARIAAttributesView.ts | ariaAttributes":{"message":"ARIA Attributes"},"panels/accessibility/ARIAAttributesView.ts | noAriaAttributes":{"message":"No ARIA attributes"},"panels/accessibility/AXBreadcrumbsPane.ts | accessibilityTree":{"message":"Accessibility Tree"},"panels/accessibility/AXBreadcrumbsPane.ts | fullTreeExperimentDescription":{"message":"The accessibility tree moved to the top right corner of the DOM tree."},"panels/accessibility/AXBreadcrumbsPane.ts | fullTreeExperimentName":{"message":"Enable full-page accessibility tree"},"panels/accessibility/AXBreadcrumbsPane.ts | ignored":{"message":"Ignored"},"panels/accessibility/AXBreadcrumbsPane.ts | reloadRequired":{"message":"Reload required before the change takes effect."},"panels/accessibility/AXBreadcrumbsPane.ts | scrollIntoView":{"message":"Scroll into view"},"panels/accessibility/SourceOrderView.ts | noSourceOrderInformation":{"message":"No source order information available"},"panels/accessibility/SourceOrderView.ts | showSourceOrder":{"message":"Show source order"},"panels/accessibility/SourceOrderView.ts | sourceOrderViewer":{"message":"Source Order Viewer"},"panels/accessibility/SourceOrderView.ts | thereMayBeADelayInDisplaying":{"message":"There may be a delay in displaying source order for elements with many children"},"panels/animation/animation-meta.ts | animations":{"message":"Animations"},"panels/animation/animation-meta.ts | showAnimations":{"message":"Show Animations"},"panels/animation/AnimationTimeline.ts | animationPreviews":{"message":"Animation previews"},"panels/animation/AnimationTimeline.ts | animationPreviewS":{"message":"Animation Preview {PH1}"},"panels/animation/AnimationTimeline.ts | clearAll":{"message":"Clear all"},"panels/animation/AnimationTimeline.ts | pause":{"message":"Pause"},"panels/animation/AnimationTimeline.ts | pauseAll":{"message":"Pause all"},"panels/animation/AnimationTimeline.ts | pauseTimeline":{"message":"Pause timeline"},"panels/animation/AnimationTimeline.ts | playbackRatePlaceholder":{"message":"{PH1}%"},"panels/animation/AnimationTimeline.ts | playbackRates":{"message":"Playback rates"},"panels/animation/AnimationTimeline.ts | playTimeline":{"message":"Play timeline"},"panels/animation/AnimationTimeline.ts | replayTimeline":{"message":"Replay timeline"},"panels/animation/AnimationTimeline.ts | resumeAll":{"message":"Resume all"},"panels/animation/AnimationTimeline.ts | selectAnEffectAboveToInspectAnd":{"message":"Select an effect above to inspect and modify."},"panels/animation/AnimationTimeline.ts | setSpeedToS":{"message":"Set speed to {PH1}"},"panels/animation/AnimationTimeline.ts | waitingForAnimations":{"message":"Waiting for animations..."},"panels/animation/AnimationUI.ts | animationEndpointSlider":{"message":"Animation Endpoint slider"},"panels/animation/AnimationUI.ts | animationKeyframeSlider":{"message":"Animation Keyframe slider"},"panels/animation/AnimationUI.ts | sSlider":{"message":"{PH1} slider"},"panels/application/application-meta.ts | application":{"message":"Application"},"panels/application/application-meta.ts | clearSiteData":{"message":"Clear site data"},"panels/application/application-meta.ts | clearSiteDataIncludingThirdparty":{"message":"Clear site data (including third-party cookies)"},"panels/application/application-meta.ts | pwa":{"message":"pwa"},"panels/application/application-meta.ts | showApplication":{"message":"Show Application"},"panels/application/application-meta.ts | startRecordingEvents":{"message":"Start recording events"},"panels/application/application-meta.ts | stopRecordingEvents":{"message":"Stop recording events"},"panels/application/ApplicationPanelSidebar.ts | application":{"message":"Application"},"panels/application/ApplicationPanelSidebar.ts | applicationSidebarPanel":{"message":"Application panel sidebar"},"panels/application/ApplicationPanelSidebar.ts | appManifest":{"message":"App Manifest"},"panels/application/ApplicationPanelSidebar.ts | backgroundServices":{"message":"Background services"},"panels/application/ApplicationPanelSidebar.ts | beforeInvokeAlert":{"message":"{PH1}: Invoke to scroll to this section in manifest"},"panels/application/ApplicationPanelSidebar.ts | clear":{"message":"Clear"},"panels/application/ApplicationPanelSidebar.ts | cookies":{"message":"Cookies"},"panels/application/ApplicationPanelSidebar.ts | cookiesUsedByFramesFromS":{"message":"Cookies used by frames from {PH1}"},"panels/application/ApplicationPanelSidebar.ts | documentNotAvailable":{"message":"Document not available"},"panels/application/ApplicationPanelSidebar.ts | frames":{"message":"Frames"},"panels/application/ApplicationPanelSidebar.ts | indexeddb":{"message":"IndexedDB"},"panels/application/ApplicationPanelSidebar.ts | keyPathS":{"message":"Key path: {PH1}"},"panels/application/ApplicationPanelSidebar.ts | localFiles":{"message":"Local Files"},"panels/application/ApplicationPanelSidebar.ts | localStorage":{"message":"Local storage"},"panels/application/ApplicationPanelSidebar.ts | manifest":{"message":"Manifest"},"panels/application/ApplicationPanelSidebar.ts | noManifestDetected":{"message":"No manifest detected"},"panels/application/ApplicationPanelSidebar.ts | onInvokeAlert":{"message":"Scrolled to {PH1}"},"panels/application/ApplicationPanelSidebar.ts | onInvokeManifestAlert":{"message":"Manifest: Invoke to scroll to the top of manifest"},"panels/application/ApplicationPanelSidebar.ts | openedWindows":{"message":"Opened Windows"},"panels/application/ApplicationPanelSidebar.ts | refreshIndexeddb":{"message":"Refresh IndexedDB"},"panels/application/ApplicationPanelSidebar.ts | sessionStorage":{"message":"Session storage"},"panels/application/ApplicationPanelSidebar.ts | storage":{"message":"Storage"},"panels/application/ApplicationPanelSidebar.ts | theContentOfThisDocumentHasBeen":{"message":"The content of this document has been generated dynamically via 'document.write()'."},"panels/application/ApplicationPanelSidebar.ts | thirdPartyPhaseout":{"message":"Cookies from {PH1} may have been blocked due to third-party cookie phaseout."},"panels/application/ApplicationPanelSidebar.ts | versionS":{"message":"Version: {PH1}"},"panels/application/ApplicationPanelSidebar.ts | versionSEmpty":{"message":"Version: {PH1} (empty)"},"panels/application/ApplicationPanelSidebar.ts | webWorkers":{"message":"Web Workers"},"panels/application/ApplicationPanelSidebar.ts | windowWithoutTitle":{"message":"Window without title"},"panels/application/ApplicationPanelSidebar.ts | worker":{"message":"worker"},"panels/application/AppManifestView.ts | actualHeightSpxOfSSDoesNotMatch":{"message":"Actual height ({PH1}px) of {PH2} {PH3} does not match specified height ({PH4}px)"},"panels/application/AppManifestView.ts | actualSizeSspxOfSSDoesNotMatch":{"message":"Actual size ({PH1}×{PH2})px of {PH3} {PH4} does not match specified size ({PH5}×{PH6}px)"},"panels/application/AppManifestView.ts | actualWidthSpxOfSSDoesNotMatch":{"message":"Actual width ({PH1}px) of {PH2} {PH3} does not match specified width ({PH4}px)"},"panels/application/AppManifestView.ts | appIdExplainer":{"message":"This is used by the browser to know whether the manifest should be updating an existing application, or whether it refers to a new web app that can be installed."},"panels/application/AppManifestView.ts | appIdNote":{"message":"{PH1} {PH2} is not specified in the manifest, {PH3} is used instead. To specify an App ID that matches the current identity, set the {PH4} field to {PH5} {PH6}."},"panels/application/AppManifestView.ts | aUrlInTheManifestContainsA":{"message":"A URL in the manifest contains a username, password, or port"},"panels/application/AppManifestView.ts | avoidPurposeAnyAndMaskable":{"message":"Declaring an icon with 'purpose' of 'any maskable' is discouraged. It is likely to look incorrect on some platforms due to too much or too little padding."},"panels/application/AppManifestView.ts | backgroundColor":{"message":"Background color"},"panels/application/AppManifestView.ts | computedAppId":{"message":"Computed App ID"},"panels/application/AppManifestView.ts | copiedToClipboard":{"message":"Copied suggested ID {PH1} to clipboard"},"panels/application/AppManifestView.ts | copyToClipboard":{"message":"Copy suggested ID to clipboard"},"panels/application/AppManifestView.ts | couldNotCheckServiceWorker":{"message":"Could not check service worker without a 'start_url' field in the manifest"},"panels/application/AppManifestView.ts | couldNotDownloadARequiredIcon":{"message":"Could not download a required icon from the manifest"},"panels/application/AppManifestView.ts | customizePwaTitleBar":{"message":"Customize the window controls overlay of your PWA's title bar"},"panels/application/AppManifestView.ts | description":{"message":"Description"},"panels/application/AppManifestView.ts | descriptionMayBeTruncated":{"message":"Description may be truncated."},"panels/application/AppManifestView.ts | display":{"message":"Display"},"panels/application/AppManifestView.ts | documentationOnMaskableIcons":{"message":"documentation on maskable icons"},"panels/application/AppManifestView.ts | downloadedIconWasEmptyOr":{"message":"Downloaded icon was empty or corrupted"},"panels/application/AppManifestView.ts | errorsAndWarnings":{"message":"Errors and warnings"},"panels/application/AppManifestView.ts | formFactor":{"message":"Form factor"},"panels/application/AppManifestView.ts | icon":{"message":"Icon"},"panels/application/AppManifestView.ts | icons":{"message":"Icons"},"panels/application/AppManifestView.ts | identity":{"message":"Identity"},"panels/application/AppManifestView.ts | imageFromS":{"message":"Image from {PH1}"},"panels/application/AppManifestView.ts | installability":{"message":"Installability"},"panels/application/AppManifestView.ts | label":{"message":"Label"},"panels/application/AppManifestView.ts | learnMore":{"message":"Learn more"},"panels/application/AppManifestView.ts | manifestContainsDisplayoverride":{"message":"Manifest contains 'display_override' field, and the first supported display mode must be one of 'standalone', 'fullscreen', or 'minimal-ui'"},"panels/application/AppManifestView.ts | manifestCouldNotBeFetchedIsEmpty":{"message":"Manifest could not be fetched, is empty, or could not be parsed"},"panels/application/AppManifestView.ts | manifestDisplayPropertyMustBeOne":{"message":"Manifest 'display' property must be one of 'standalone', 'fullscreen', or 'minimal-ui'"},"panels/application/AppManifestView.ts | manifestDoesNotContainANameOr":{"message":"Manifest does not contain a 'name' or 'short_name' field"},"panels/application/AppManifestView.ts | manifestDoesNotContainASuitable":{"message":"Manifest does not contain a suitable icon—PNG, SVG, or WebP format of at least {PH1}px is required, the 'sizes' attribute must be set, and the 'purpose' attribute, if set, must include 'any'."},"panels/application/AppManifestView.ts | manifestSpecifies":{"message":"Manifest specifies 'prefer_related_applications: true'"},"panels/application/AppManifestView.ts | manifestStartUrlIsNotValid":{"message":"Manifest 'start_url' is not valid"},"panels/application/AppManifestView.ts | name":{"message":"Name"},"panels/application/AppManifestView.ts | needHelpReadOurS":{"message":"Need help? Read the {PH1}."},"panels/application/AppManifestView.ts | newNoteUrl":{"message":"New note URL"},"panels/application/AppManifestView.ts | noPlayStoreIdProvided":{"message":"No Play store ID provided"},"panels/application/AppManifestView.ts | noScreenshotsForRicherPWAInstallOnDesktop":{"message":"Richer PWA Install UI won’t be available on desktop. Please add at least one screenshot with the form_factor set to wide."},"panels/application/AppManifestView.ts | noScreenshotsForRicherPWAInstallOnMobile":{"message":"Richer PWA Install UI won’t be available on mobile. Please add at least one screenshot for which form_factor is not set or set to a value other than wide."},"panels/application/AppManifestView.ts | noSuppliedIconIsAtLeastSpxSquare":{"message":"No supplied icon is at least {PH1} pixels square in PNG, SVG, or WebP format, with the purpose attribute unset or set to 'any'."},"panels/application/AppManifestView.ts | note":{"message":"Note:"},"panels/application/AppManifestView.ts | orientation":{"message":"Orientation"},"panels/application/AppManifestView.ts | pageDoesNotWorkOffline":{"message":"Page does not work offline"},"panels/application/AppManifestView.ts | pageDoesNotWorkOfflineThePage":{"message":"Page does not work offline. Starting in Chrome 93, the installability criteria are changing, and this site will not be installable. See {PH1} for more information."},"panels/application/AppManifestView.ts | pageHasNoManifestLinkUrl":{"message":"Page has no manifest URL"},"panels/application/AppManifestView.ts | pageIsLoadedInAnIncognitoWindow":{"message":"Page is loaded in an incognito window"},"panels/application/AppManifestView.ts | pageIsNotLoadedInTheMainFrame":{"message":"Page is not loaded in the main frame"},"panels/application/AppManifestView.ts | pageIsNotServedFromASecureOrigin":{"message":"Page is not served from a secure origin"},"panels/application/AppManifestView.ts | platform":{"message":"Platform"},"panels/application/AppManifestView.ts | preferrelatedapplicationsIsOnly":{"message":"'prefer_related_applications' is only supported on Chrome Beta and Stable channels on Android."},"panels/application/AppManifestView.ts | presentation":{"message":"Presentation"},"panels/application/AppManifestView.ts | protocolHandlers":{"message":"Protocol Handlers"},"panels/application/AppManifestView.ts | screenshot":{"message":"Screenshot"},"panels/application/AppManifestView.ts | screenshotPixelSize":{"message":"Screenshot {url} should specify a pixel size [width]x[height] instead of any as first size."},"panels/application/AppManifestView.ts | screenshotS":{"message":"Screenshot #{PH1}"},"panels/application/AppManifestView.ts | screenshotsMustHaveSameAspectRatio":{"message":"All screenshots with the same form_factor must have the same aspect ratio as the first screenshot with that form_factor. Some screenshots will be ignored."},"panels/application/AppManifestView.ts | selectWindowControlsOverlayEmulationOs":{"message":"Emulate the Window Controls Overlay on"},"panels/application/AppManifestView.ts | shortcutS":{"message":"Shortcut #{PH1}"},"panels/application/AppManifestView.ts | shortcutsMayBeNotAvailable":{"message":"The maximum number of shortcuts is platform dependent. Some shortcuts may be not available."},"panels/application/AppManifestView.ts | shortcutSShouldIncludeAXPixel":{"message":"Shortcut #{PH1} should include a 96×96 pixel icon"},"panels/application/AppManifestView.ts | shortName":{"message":"Short name"},"panels/application/AppManifestView.ts | showOnlyTheMinimumSafeAreaFor":{"message":"Show only the minimum safe area for maskable icons"},"panels/application/AppManifestView.ts | sSDoesNotSpecifyItsSizeInThe":{"message":"{PH1} {PH2} does not specify its size in the manifest"},"panels/application/AppManifestView.ts | sSFailedToLoad":{"message":"{PH1} {PH2} failed to load"},"panels/application/AppManifestView.ts | sSHeightDoesNotComplyWithRatioRequirement":{"message":"{PH1} {PH2} height can't be more than 2.3 times as long as the width"},"panels/application/AppManifestView.ts | sSrcIsNotSet":{"message":"{PH1} 'src' is not set"},"panels/application/AppManifestView.ts | sSShouldHaveSquareIcon":{"message":"Most operating systems require square icons. Please include at least one square icon in the array."},"panels/application/AppManifestView.ts | sSShouldSpecifyItsSizeAs":{"message":"{PH1} {PH2} should specify its size as [width]x[height]"},"panels/application/AppManifestView.ts | sSSizeShouldBeAtLeast320":{"message":"{PH1} {PH2} size should be at least 320×320"},"panels/application/AppManifestView.ts | sSSizeShouldBeAtMost3840":{"message":"{PH1} {PH2} size should be at most 3840×3840"},"panels/application/AppManifestView.ts | sSWidthDoesNotComplyWithRatioRequirement":{"message":"{PH1} {PH2} width can't be more than 2.3 times as long as the height"},"panels/application/AppManifestView.ts | startUrl":{"message":"Start URL"},"panels/application/AppManifestView.ts | sUrlSFailedToParse":{"message":"{PH1} URL ''{PH2}'' failed to parse"},"panels/application/AppManifestView.ts | theAppIsAlreadyInstalled":{"message":"The app is already installed"},"panels/application/AppManifestView.ts | themeColor":{"message":"Theme color"},"panels/application/AppManifestView.ts | thePlayStoreAppUrlAndPlayStoreId":{"message":"The Play Store app URL and Play Store ID do not match"},"panels/application/AppManifestView.ts | theSpecifiedApplicationPlatform":{"message":"The specified application platform is not supported on Android"},"panels/application/AppManifestView.ts | tooManyScreenshotsForDesktop":{"message":"No more than 8 screenshots will be displayed on desktop. The rest will be ignored."},"panels/application/AppManifestView.ts | tooManyScreenshotsForMobile":{"message":"No more than 5 screenshots will be displayed on mobile. The rest will be ignored."},"panels/application/AppManifestView.ts | url":{"message":"URL"},"panels/application/AppManifestView.ts | wcoFound":{"message":"Chrome has successfully found the {PH1} value for the {PH2} field in the {PH3}."},"panels/application/AppManifestView.ts | wcoNeedHelpReadMore":{"message":"Need help? Read {PH1}."},"panels/application/AppManifestView.ts | wcoNotFound":{"message":"Define {PH1} in the manifest to use the Window Controls Overlay API and customize your app's title bar."},"panels/application/AppManifestView.ts | windowControlsOverlay":{"message":"Window Controls Overlay"},"panels/application/BackForwardCacheTreeElement.ts | backForwardCache":{"message":"Back/forward cache"},"panels/application/BackgroundServiceView.ts | backgroundFetch":{"message":"Background fetch"},"panels/application/BackgroundServiceView.ts | backgroundServices":{"message":"Background services"},"panels/application/BackgroundServiceView.ts | backgroundSync":{"message":"Background sync"},"panels/application/BackgroundServiceView.ts | clear":{"message":"Clear"},"panels/application/BackgroundServiceView.ts | clickTheRecordButtonSOrHitSTo":{"message":"Click the record button {PH1} or hit {PH2} to start recording."},"panels/application/BackgroundServiceView.ts | devtoolsWillRecordAllSActivity":{"message":"DevTools will record all {PH1} activity for up to 3 days, even when closed."},"panels/application/BackgroundServiceView.ts | empty":{"message":"empty"},"panels/application/BackgroundServiceView.ts | event":{"message":"Event"},"panels/application/BackgroundServiceView.ts | instanceId":{"message":"Instance ID"},"panels/application/BackgroundServiceView.ts | learnMore":{"message":"Learn more"},"panels/application/BackgroundServiceView.ts | noMetadataForThisEvent":{"message":"No metadata for this event"},"panels/application/BackgroundServiceView.ts | notifications":{"message":"Notifications"},"panels/application/BackgroundServiceView.ts | origin":{"message":"Origin"},"panels/application/BackgroundServiceView.ts | paymentHandler":{"message":"Payment handler"},"panels/application/BackgroundServiceView.ts | periodicBackgroundSync":{"message":"Periodic background sync"},"panels/application/BackgroundServiceView.ts | pushMessaging":{"message":"Push messaging"},"panels/application/BackgroundServiceView.ts | recordingSActivity":{"message":"Recording {PH1} activity..."},"panels/application/BackgroundServiceView.ts | saveEvents":{"message":"Save events"},"panels/application/BackgroundServiceView.ts | selectAnEntryToViewMetadata":{"message":"Select an entry to view metadata"},"panels/application/BackgroundServiceView.ts | showEventsForOtherStorageKeys":{"message":"Show events from other storage partitions"},"panels/application/BackgroundServiceView.ts | showEventsFromOtherDomains":{"message":"Show events from other domains"},"panels/application/BackgroundServiceView.ts | startRecordingEvents":{"message":"Start recording events"},"panels/application/BackgroundServiceView.ts | stopRecordingEvents":{"message":"Stop recording events"},"panels/application/BackgroundServiceView.ts | storageKey":{"message":"Storage Key"},"panels/application/BackgroundServiceView.ts | swScope":{"message":"Service Worker Scope"},"panels/application/BackgroundServiceView.ts | timestamp":{"message":"Timestamp"},"panels/application/BounceTrackingMitigationsTreeElement.ts | bounceTrackingMitigations":{"message":"Bounce tracking mitigations"},"panels/application/components/BackForwardCacheStrings.ts | appBanner":{"message":"Pages that requested an AppBanner are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | backForwardCacheDisabled":{"message":"Back/forward cache is disabled by flags. Visit chrome://flags/#back-forward-cache to enable it locally on this device."},"panels/application/components/BackForwardCacheStrings.ts | backForwardCacheDisabledByCommandLine":{"message":"Back/forward cache is disabled by the command line."},"panels/application/components/BackForwardCacheStrings.ts | backForwardCacheDisabledByLowMemory":{"message":"Back/forward cache is disabled due to insufficient memory."},"panels/application/components/BackForwardCacheStrings.ts | backForwardCacheDisabledForDelegate":{"message":"Back/forward cache is not supported by delegate."},"panels/application/components/BackForwardCacheStrings.ts | backForwardCacheDisabledForPrerender":{"message":"Back/forward cache is disabled for prerenderer."},"panels/application/components/BackForwardCacheStrings.ts | broadcastChannel":{"message":"The page cannot be cached because it has a BroadcastChannel instance with registered listeners."},"panels/application/components/BackForwardCacheStrings.ts | cacheControlNoStore":{"message":"Pages with cache-control:no-store header cannot enter back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | cacheFlushed":{"message":"The cache was intentionally cleared."},"panels/application/components/BackForwardCacheStrings.ts | cacheLimit":{"message":"The page was evicted from the cache to allow another page to be cached."},"panels/application/components/BackForwardCacheStrings.ts | containsPlugins":{"message":"Pages containing plugins are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | contentDiscarded":{"message":"Undefined"},"panels/application/components/BackForwardCacheStrings.ts | contentFileChooser":{"message":"Pages that use FileChooser API are not eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | contentFileSystemAccess":{"message":"Pages that use File System Access API are not eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | contentMediaDevicesDispatcherHost":{"message":"Pages that use Media Device Dispatcher are not eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | contentMediaPlay":{"message":"A media player was playing upon navigating away."},"panels/application/components/BackForwardCacheStrings.ts | contentMediaSession":{"message":"Pages that use MediaSession API and set a playback state are not eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | contentMediaSessionService":{"message":"Pages that use MediaSession API and set action handlers are not eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | contentScreenReader":{"message":"Back/forward cache is disabled due to screen reader."},"panels/application/components/BackForwardCacheStrings.ts | contentSecurityHandler":{"message":"Pages that use SecurityHandler are not eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | contentSerial":{"message":"Pages that use Serial API are not eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | contentWebAuthenticationAPI":{"message":"Pages that use WebAuthetication API are not eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | contentWebBluetooth":{"message":"Pages that use WebBluetooth API are not eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | contentWebUSB":{"message":"Pages that use WebUSB API are not eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | cookieDisabled":{"message":"Back/forward cache is disabled because cookies are disabled on a page that uses Cache-Control: no-store."},"panels/application/components/BackForwardCacheStrings.ts | dedicatedWorkerOrWorklet":{"message":"Pages that use a dedicated worker or worklet are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | documentLoaded":{"message":"The document did not finish loading before navigating away."},"panels/application/components/BackForwardCacheStrings.ts | embedderAppBannerManager":{"message":"App Banner was present upon navigating away."},"panels/application/components/BackForwardCacheStrings.ts | embedderChromePasswordManagerClientBindCredentialManager":{"message":"Chrome Password Manager was present upon navigating away."},"panels/application/components/BackForwardCacheStrings.ts | embedderDomDistillerSelfDeletingRequestDelegate":{"message":"DOM distillation was in progress upon navigating away."},"panels/application/components/BackForwardCacheStrings.ts | embedderDomDistillerViewerSource":{"message":"DOM Distiller Viewer was present upon navigating away."},"panels/application/components/BackForwardCacheStrings.ts | embedderExtensionMessaging":{"message":"Back/forward cache is disabled due to extensions using messaging API."},"panels/application/components/BackForwardCacheStrings.ts | embedderExtensionMessagingForOpenPort":{"message":"Extensions with long-lived connection should close the connection before entering back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | embedderExtensions":{"message":"Back/forward cache is disabled due to extensions."},"panels/application/components/BackForwardCacheStrings.ts | embedderExtensionSentMessageToCachedFrame":{"message":"Extensions with long-lived connection attempted to send messages to frames in back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | embedderModalDialog":{"message":"Modal dialog such as form resubmission or http password dialog was shown for the page upon navigating away."},"panels/application/components/BackForwardCacheStrings.ts | embedderOfflinePage":{"message":"The offline page was shown upon navigating away."},"panels/application/components/BackForwardCacheStrings.ts | embedderOomInterventionTabHelper":{"message":"Out-Of-Memory Intervention bar was present upon navigating away."},"panels/application/components/BackForwardCacheStrings.ts | embedderPermissionRequestManager":{"message":"There were permission requests upon navigating away."},"panels/application/components/BackForwardCacheStrings.ts | embedderPopupBlockerTabHelper":{"message":"Popup blocker was present upon navigating away."},"panels/application/components/BackForwardCacheStrings.ts | embedderSafeBrowsingThreatDetails":{"message":"Safe Browsing details were shown upon navigating away."},"panels/application/components/BackForwardCacheStrings.ts | embedderSafeBrowsingTriggeredPopupBlocker":{"message":"Safe Browsing considered this page to be abusive and blocked popup."},"panels/application/components/BackForwardCacheStrings.ts | enteredBackForwardCacheBeforeServiceWorkerHostAdded":{"message":"A service worker was activated while the page was in back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | errorDocument":{"message":"Back/forward cache is disabled due to a document error."},"panels/application/components/BackForwardCacheStrings.ts | fencedFramesEmbedder":{"message":"Pages using FencedFrames cannot be stored in bfcache."},"panels/application/components/BackForwardCacheStrings.ts | foregroundCacheLimit":{"message":"The page was evicted from the cache to allow another page to be cached."},"panels/application/components/BackForwardCacheStrings.ts | grantedMediaStreamAccess":{"message":"Pages that have granted media stream access are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | haveInnerContents":{"message":"Pages that have certain kinds of embedded content (e.g. PDFs) are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | HTTPMethodNotGET":{"message":"Only pages loaded via a GET request are eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | HTTPStatusNotOK":{"message":"Only pages with a status code of 2XX can be cached."},"panels/application/components/BackForwardCacheStrings.ts | idleManager":{"message":"Pages that use IdleManager are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | indexedDBConnection":{"message":"Pages that have an open IndexedDB connection are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | indexedDBEvent":{"message":"Back/forward cache is disabled due to an IndexedDB event."},"panels/application/components/BackForwardCacheStrings.ts | ineligibleAPI":{"message":"Ineligible APIs were used."},"panels/application/components/BackForwardCacheStrings.ts | injectedJavascript":{"message":"Pages that JavaScript is injected into by extensions are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | injectedStyleSheet":{"message":"Pages that a StyleSheet is injected into by extensions are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | internalError":{"message":"Internal error."},"panels/application/components/BackForwardCacheStrings.ts | JavaScriptExecution":{"message":"Chrome detected an attempt to execute JavaScript while in the cache."},"panels/application/components/BackForwardCacheStrings.ts | jsNetworkRequestReceivedCacheControlNoStoreResource":{"message":"Back/forward cache is disabled because some JavaScript network request received resource with Cache-Control: no-store header."},"panels/application/components/BackForwardCacheStrings.ts | keepaliveRequest":{"message":"Back/forward cache is disabled due to a keepalive request."},"panels/application/components/BackForwardCacheStrings.ts | keyboardLock":{"message":"Pages that use Keyboard lock are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | loading":{"message":"The page did not finish loading before navigating away."},"panels/application/components/BackForwardCacheStrings.ts | mainResourceHasCacheControlNoCache":{"message":"Pages whose main resource has cache-control:no-cache cannot enter back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | mainResourceHasCacheControlNoStore":{"message":"Pages whose main resource has cache-control:no-store cannot enter back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | navigationCancelledWhileRestoring":{"message":"Navigation was cancelled before the page could be restored from back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | networkExceedsBufferLimit":{"message":"The page was evicted from the cache because an active network connection received too much data. Chrome limits the amount of data that a page may receive while cached."},"panels/application/components/BackForwardCacheStrings.ts | networkRequestDatapipeDrainedAsBytesConsumer":{"message":"Pages that have inflight fetch() or XHR are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | networkRequestRedirected":{"message":"The page was evicted from back/forward cache because an active network request involved a redirect."},"panels/application/components/BackForwardCacheStrings.ts | networkRequestTimeout":{"message":"The page was evicted from the cache because a network connection was open too long. Chrome limits the amount of time that a page may receive data while cached."},"panels/application/components/BackForwardCacheStrings.ts | noResponseHead":{"message":"Pages that do not have a valid response head cannot enter back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | notMainFrame":{"message":"Navigation happened in a frame other than the main frame."},"panels/application/components/BackForwardCacheStrings.ts | outstandingIndexedDBTransaction":{"message":"Page with ongoing indexed DB transactions are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | outstandingNetworkRequestDirectSocket":{"message":"Pages with an in-flight network request are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | outstandingNetworkRequestFetch":{"message":"Pages with an in-flight fetch network request are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | outstandingNetworkRequestOthers":{"message":"Pages with an in-flight network request are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | outstandingNetworkRequestXHR":{"message":"Pages with an in-flight XHR network request are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | paymentManager":{"message":"Pages that use PaymentManager are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | pictureInPicture":{"message":"Pages that use Picture-in-Picture are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | printing":{"message":"Pages that show Printing UI are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | relatedActiveContentsExist":{"message":"The page was opened using 'window.open()' and another tab has a reference to it, or the page opened a window."},"panels/application/components/BackForwardCacheStrings.ts | rendererProcessCrashed":{"message":"The renderer process for the page in back/forward cache crashed."},"panels/application/components/BackForwardCacheStrings.ts | rendererProcessKilled":{"message":"The renderer process for the page in back/forward cache was killed."},"panels/application/components/BackForwardCacheStrings.ts | requestedAudioCapturePermission":{"message":"Pages that have requested audio capture permissions are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | requestedBackForwardCacheBlockedSensors":{"message":"Pages that have requested sensor permissions are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | requestedBackgroundWorkPermission":{"message":"Pages that have requested background sync or fetch permissions are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | requestedMIDIPermission":{"message":"Pages that have requested MIDI permissions are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | requestedNotificationsPermission":{"message":"Pages that have requested notifications permissions are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | requestedStorageAccessGrant":{"message":"Pages that have requested storage access are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | requestedVideoCapturePermission":{"message":"Pages that have requested video capture permissions are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | schemeNotHTTPOrHTTPS":{"message":"Only pages whose URL scheme is HTTP / HTTPS can be cached."},"panels/application/components/BackForwardCacheStrings.ts | serviceWorkerClaim":{"message":"The page was claimed by a service worker while it is in back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | serviceWorkerPostMessage":{"message":"A service worker attempted to send the page in back/forward cache a MessageEvent."},"panels/application/components/BackForwardCacheStrings.ts | serviceWorkerUnregistration":{"message":"ServiceWorker was unregistered while a page was in back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | serviceWorkerVersionActivation":{"message":"The page was evicted from back/forward cache due to a service worker activation."},"panels/application/components/BackForwardCacheStrings.ts | sessionRestored":{"message":"Chrome restarted and cleared the back/forward cache entries."},"panels/application/components/BackForwardCacheStrings.ts | sharedWorker":{"message":"Pages that use SharedWorker are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | speechRecognizer":{"message":"Pages that use SpeechRecognizer are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | speechSynthesis":{"message":"Pages that use SpeechSynthesis are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | subframeIsNavigating":{"message":"An iframe on the page started a navigation that did not complete."},"panels/application/components/BackForwardCacheStrings.ts | subresourceHasCacheControlNoCache":{"message":"Pages whose subresource has cache-control:no-cache cannot enter back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | subresourceHasCacheControlNoStore":{"message":"Pages whose subresource has cache-control:no-store cannot enter back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | timeout":{"message":"The page exceeded the maximum time in back/forward cache and was expired."},"panels/application/components/BackForwardCacheStrings.ts | timeoutPuttingInCache":{"message":"The page timed out entering back/forward cache (likely due to long-running pagehide handlers)."},"panels/application/components/BackForwardCacheStrings.ts | unloadHandlerExistsInMainFrame":{"message":"The page has an unload handler in the main frame."},"panels/application/components/BackForwardCacheStrings.ts | unloadHandlerExistsInSubFrame":{"message":"The page has an unload handler in a sub frame."},"panels/application/components/BackForwardCacheStrings.ts | userAgentOverrideDiffers":{"message":"Browser has changed the user agent override header."},"panels/application/components/BackForwardCacheStrings.ts | wasGrantedMediaAccess":{"message":"Pages that have granted access to record video or audio are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | webDatabase":{"message":"Pages that use WebDatabase are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | webHID":{"message":"Pages that use WebHID are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | webLocks":{"message":"Pages that use WebLocks are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | webNfc":{"message":"Pages that use WebNfc are not currently eligible for back/forwad cache."},"panels/application/components/BackForwardCacheStrings.ts | webOTPService":{"message":"Pages that use WebOTPService are not currently eligible for bfcache."},"panels/application/components/BackForwardCacheStrings.ts | webRTC":{"message":"Pages with WebRTC cannot enter back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | webRTCSticky":{"message":"Back/forward cache is disabled because WebRTC has been used."},"panels/application/components/BackForwardCacheStrings.ts | webShare":{"message":"Pages that use WebShare are not currently eligible for back/forwad cache."},"panels/application/components/BackForwardCacheStrings.ts | webSocket":{"message":"Pages with WebSocket cannot enter back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | webSocketSticky":{"message":"Back/forward cache is disabled because WebSocket has been used."},"panels/application/components/BackForwardCacheStrings.ts | webTransport":{"message":"Pages with WebTransport cannot enter back/forward cache."},"panels/application/components/BackForwardCacheStrings.ts | webTransportSticky":{"message":"Back/forward cache is disabled because WebTransport has been used."},"panels/application/components/BackForwardCacheStrings.ts | webXR":{"message":"Pages that use WebXR are not currently eligible for back/forward cache."},"panels/application/components/BackForwardCacheView.ts | backForwardCacheTitle":{"message":"Back/forward cache"},"panels/application/components/BackForwardCacheView.ts | blankURLTitle":{"message":"Blank URL [{PH1}]"},"panels/application/components/BackForwardCacheView.ts | blockingExtensionId":{"message":"Extension id: "},"panels/application/components/BackForwardCacheView.ts | circumstantial":{"message":"Not Actionable"},"panels/application/components/BackForwardCacheView.ts | circumstantialExplanation":{"message":"These reasons are not actionable i.e. caching was prevented by something outside of the direct control of the page."},"panels/application/components/BackForwardCacheView.ts | filesPerIssue":{"message":"{n, plural, =1 {# file} other {# files}}"},"panels/application/components/BackForwardCacheView.ts | framesPerIssue":{"message":"{n, plural, =1 {# frame} other {# frames}}"},"panels/application/components/BackForwardCacheView.ts | framesTitle":{"message":"Frames"},"panels/application/components/BackForwardCacheView.ts | issuesInMultipleFrames":{"message":"{n, plural, =1 {# issue found in {m} frames.} other {# issues found in {m} frames.}}"},"panels/application/components/BackForwardCacheView.ts | issuesInSingleFrame":{"message":"{n, plural, =1 {# issue found in 1 frame.} other {# issues found in 1 frame.}}"},"panels/application/components/BackForwardCacheView.ts | learnMore":{"message":"Learn more: back/forward cache eligibility"},"panels/application/components/BackForwardCacheView.ts | mainFrame":{"message":"Main Frame"},"panels/application/components/BackForwardCacheView.ts | neverUseUnload":{"message":"Learn more: Never use unload handler"},"panels/application/components/BackForwardCacheView.ts | normalNavigation":{"message":"Not served from back/forward cache: to trigger back/forward cache, use Chrome's back/forward buttons, or use the test button below to automatically navigate away and back."},"panels/application/components/BackForwardCacheView.ts | pageSupportNeeded":{"message":"Actionable"},"panels/application/components/BackForwardCacheView.ts | pageSupportNeededExplanation":{"message":"These reasons are actionable i.e. they can be cleaned up to make the page eligible for back/forward cache."},"panels/application/components/BackForwardCacheView.ts | restoredFromBFCache":{"message":"Successfully served from back/forward cache."},"panels/application/components/BackForwardCacheView.ts | runningTest":{"message":"Running test"},"panels/application/components/BackForwardCacheView.ts | runTest":{"message":"Test back/forward cache"},"panels/application/components/BackForwardCacheView.ts | supportPending":{"message":"Pending Support"},"panels/application/components/BackForwardCacheView.ts | supportPendingExplanation":{"message":"Chrome support for these reasons is pending i.e. they will not prevent the page from being eligible for back/forward cache in a future version of Chrome."},"panels/application/components/BackForwardCacheView.ts | unavailable":{"message":"unavailable"},"panels/application/components/BackForwardCacheView.ts | unknown":{"message":"Unknown Status"},"panels/application/components/BackForwardCacheView.ts | url":{"message":"URL:"},"panels/application/components/BounceTrackingMitigationsView.ts | bounceTrackingMitigationsTitle":{"message":"Bounce tracking mitigations"},"panels/application/components/BounceTrackingMitigationsView.ts | checkingPotentialTrackers":{"message":"Checking for potential bounce tracking sites."},"panels/application/components/BounceTrackingMitigationsView.ts | featureDisabled":{"message":"Bounce tracking mitigations are disabled. To enable them, set the flag at {PH1} to \"Enabled With Deletion\"."},"panels/application/components/BounceTrackingMitigationsView.ts | featureFlag":{"message":"Bounce Tracking Mitigations Feature Flag"},"panels/application/components/BounceTrackingMitigationsView.ts | forceRun":{"message":"Force run"},"panels/application/components/BounceTrackingMitigationsView.ts | learnMore":{"message":"Learn more: Bounce Tracking Mitigations"},"panels/application/components/BounceTrackingMitigationsView.ts | noPotentialBounceTrackersIdentified":{"message":"State was not cleared for any potential bounce tracking sites. Either none were identified or third-party cookies are not blocked."},"panels/application/components/BounceTrackingMitigationsView.ts | runningMitigations":{"message":"Running"},"panels/application/components/BounceTrackingMitigationsView.ts | stateDeletedFor":{"message":"State was deleted for the following sites:"},"panels/application/components/EndpointsGrid.ts | noEndpointsToDisplay":{"message":"No endpoints to display"},"panels/application/components/FrameDetailsView.ts | additionalInformation":{"message":"Additional Information"},"panels/application/components/FrameDetailsView.ts | adStatus":{"message":"Ad Status"},"panels/application/components/FrameDetailsView.ts | aFrameAncestorIsAnInsecure":{"message":"A frame ancestor is an insecure context"},"panels/application/components/FrameDetailsView.ts | apiAvailability":{"message":"API availability"},"panels/application/components/FrameDetailsView.ts | availabilityOfCertainApisDepends":{"message":"Availability of certain APIs depends on the document being cross-origin isolated."},"panels/application/components/FrameDetailsView.ts | available":{"message":"available"},"panels/application/components/FrameDetailsView.ts | availableNotTransferable":{"message":"available, not transferable"},"panels/application/components/FrameDetailsView.ts | availableTransferable":{"message":"available, transferable"},"panels/application/components/FrameDetailsView.ts | child":{"message":"child"},"panels/application/components/FrameDetailsView.ts | childDescription":{"message":"This frame has been identified as a child frame of an ad"},"panels/application/components/FrameDetailsView.ts | clickToRevealInElementsPanel":{"message":"Click to reveal in Elements panel"},"panels/application/components/FrameDetailsView.ts | clickToRevealInNetworkPanel":{"message":"Click to reveal in Network panel"},"panels/application/components/FrameDetailsView.ts | clickToRevealInNetworkPanelMight":{"message":"Click to reveal in Network panel (might require page reload)"},"panels/application/components/FrameDetailsView.ts | clickToRevealInSourcesPanel":{"message":"Click to reveal in Sources panel"},"panels/application/components/FrameDetailsView.ts | contentSecurityPolicy":{"message":"Content Security Policy (CSP)"},"panels/application/components/FrameDetailsView.ts | createdByAdScriptExplanation":{"message":"There was an ad script in the (async) stack when this frame was created. Examining the creation stack trace of this frame might provide more insight."},"panels/application/components/FrameDetailsView.ts | creationStackTrace":{"message":"Frame Creation Stack Trace"},"panels/application/components/FrameDetailsView.ts | creationStackTraceExplanation":{"message":"This frame was created programmatically. The stack trace shows where this happened."},"panels/application/components/FrameDetailsView.ts | creatorAdScript":{"message":"Creator Ad Script"},"panels/application/components/FrameDetailsView.ts | crossoriginIsolated":{"message":"Cross-Origin Isolated"},"panels/application/components/FrameDetailsView.ts | document":{"message":"Document"},"panels/application/components/FrameDetailsView.ts | frameId":{"message":"Frame ID"},"panels/application/components/FrameDetailsView.ts | learnMore":{"message":"Learn more"},"panels/application/components/FrameDetailsView.ts | localhostIsAlwaysASecureContext":{"message":"Localhost is always a secure context"},"panels/application/components/FrameDetailsView.ts | matchedBlockingRuleExplanation":{"message":"This frame is considered an ad frame because its current (or previous) main document is an ad resource."},"panels/application/components/FrameDetailsView.ts | measureMemory":{"message":"Measure Memory"},"panels/application/components/FrameDetailsView.ts | no":{"message":"No"},"panels/application/components/FrameDetailsView.ts | none":{"message":"None"},"panels/application/components/FrameDetailsView.ts | origin":{"message":"Origin"},"panels/application/components/FrameDetailsView.ts | originTrialsExplanation":{"message":"Origin trials give you access to a new or experimental feature."},"panels/application/components/FrameDetailsView.ts | ownerElement":{"message":"Owner Element"},"panels/application/components/FrameDetailsView.ts | parentIsAdExplanation":{"message":"This frame is considered an ad frame because its parent frame is an ad frame."},"panels/application/components/FrameDetailsView.ts | reportingTo":{"message":"reporting to"},"panels/application/components/FrameDetailsView.ts | requiresCrossoriginIsolated":{"message":"requires cross-origin isolated context"},"panels/application/components/FrameDetailsView.ts | root":{"message":"root"},"panels/application/components/FrameDetailsView.ts | rootDescription":{"message":"This frame has been identified as the root frame of an ad"},"panels/application/components/FrameDetailsView.ts | secureContext":{"message":"Secure Context"},"panels/application/components/FrameDetailsView.ts | securityIsolation":{"message":"Security & Isolation"},"panels/application/components/FrameDetailsView.ts | sharedarraybufferConstructorIs":{"message":"SharedArrayBuffer constructor is available and SABs can be transferred via postMessage"},"panels/application/components/FrameDetailsView.ts | sharedarraybufferConstructorIsAvailable":{"message":"SharedArrayBuffer constructor is available but SABs cannot be transferred via postMessage"},"panels/application/components/FrameDetailsView.ts | theFramesSchemeIsInsecure":{"message":"The frame's scheme is insecure"},"panels/application/components/FrameDetailsView.ts | thePerformanceAPI":{"message":"The performance.measureUserAgentSpecificMemory() API is available"},"panels/application/components/FrameDetailsView.ts | thePerformancemeasureuseragentspecificmemory":{"message":"The performance.measureUserAgentSpecificMemory() API is not available"},"panels/application/components/FrameDetailsView.ts | thisAdditionalDebugging":{"message":"This additional (debugging) information is shown because the 'Protocol Monitor' experiment is enabled."},"panels/application/components/FrameDetailsView.ts | transferRequiresCrossoriginIsolatedPermission":{"message":"SharedArrayBuffer transfer requires enabling the permission policy:"},"panels/application/components/FrameDetailsView.ts | unavailable":{"message":"unavailable"},"panels/application/components/FrameDetailsView.ts | unreachableUrl":{"message":"Unreachable URL"},"panels/application/components/FrameDetailsView.ts | url":{"message":"URL"},"panels/application/components/FrameDetailsView.ts | willRequireCrossoriginIsolated":{"message":"⚠️ will require cross-origin isolated context in the future"},"panels/application/components/FrameDetailsView.ts | yes":{"message":"Yes"},"panels/application/components/InterestGroupAccessGrid.ts | allInterestGroupStorageEvents":{"message":"All interest group storage events."},"panels/application/components/InterestGroupAccessGrid.ts | eventTime":{"message":"Event Time"},"panels/application/components/InterestGroupAccessGrid.ts | eventType":{"message":"Access Type"},"panels/application/components/InterestGroupAccessGrid.ts | groupName":{"message":"Name"},"panels/application/components/InterestGroupAccessGrid.ts | groupOwner":{"message":"Owner"},"panels/application/components/InterestGroupAccessGrid.ts | noEvents":{"message":"No interest group events recorded."},"panels/application/components/OriginTrialTreeView.ts | expiryTime":{"message":"Expiry Time"},"panels/application/components/OriginTrialTreeView.ts | isThirdParty":{"message":"Third Party"},"panels/application/components/OriginTrialTreeView.ts | matchSubDomains":{"message":"Subdomain Matching"},"panels/application/components/OriginTrialTreeView.ts | noTrialTokens":{"message":"No trial tokens"},"panels/application/components/OriginTrialTreeView.ts | origin":{"message":"Origin"},"panels/application/components/OriginTrialTreeView.ts | rawTokenText":{"message":"Raw Token"},"panels/application/components/OriginTrialTreeView.ts | status":{"message":"Token Status"},"panels/application/components/OriginTrialTreeView.ts | token":{"message":"Token"},"panels/application/components/OriginTrialTreeView.ts | tokens":{"message":"{PH1} tokens"},"panels/application/components/OriginTrialTreeView.ts | trialName":{"message":"Trial Name"},"panels/application/components/OriginTrialTreeView.ts | usageRestriction":{"message":"Usage Restriction"},"panels/application/components/PermissionsPolicySection.ts | allowedFeatures":{"message":"Allowed Features"},"panels/application/components/PermissionsPolicySection.ts | clickToShowHeader":{"message":"Click to reveal the request whose \"Permissions-Policy\" HTTP header disables this feature."},"panels/application/components/PermissionsPolicySection.ts | clickToShowIframe":{"message":"Click to reveal the top-most iframe which does not allow this feature in the elements panel."},"panels/application/components/PermissionsPolicySection.ts | disabledByFencedFrame":{"message":"disabled inside a fencedframe"},"panels/application/components/PermissionsPolicySection.ts | disabledByHeader":{"message":"disabled by \"Permissions-Policy\" header"},"panels/application/components/PermissionsPolicySection.ts | disabledByIframe":{"message":"missing in iframe \"allow\" attribute"},"panels/application/components/PermissionsPolicySection.ts | disabledFeatures":{"message":"Disabled Features"},"panels/application/components/PermissionsPolicySection.ts | hideDetails":{"message":"Hide details"},"panels/application/components/PermissionsPolicySection.ts | showDetails":{"message":"Show details"},"panels/application/components/ProtocolHandlersView.ts | dropdownLabel":{"message":"Select protocol handler"},"panels/application/components/ProtocolHandlersView.ts | manifest":{"message":"manifest"},"panels/application/components/ProtocolHandlersView.ts | needHelpReadOur":{"message":"Need help? Read {PH1}."},"panels/application/components/ProtocolHandlersView.ts | protocolDetected":{"message":"Found valid protocol handler registration in the {PH1}. With the app installed, test the registered protocols."},"panels/application/components/ProtocolHandlersView.ts | protocolHandlerRegistrations":{"message":"URL protocol handler registration for PWAs"},"panels/application/components/ProtocolHandlersView.ts | protocolNotDetected":{"message":"Define protocol handlers in the {PH1} to register your app as a handler for custom protocols when your app is installed."},"panels/application/components/ProtocolHandlersView.ts | testProtocol":{"message":"Test protocol"},"panels/application/components/ProtocolHandlersView.ts | textboxLabel":{"message":"Query parameter or endpoint for protocol handler"},"panels/application/components/ProtocolHandlersView.ts | textboxPlaceholder":{"message":"Enter URL"},"panels/application/components/ReportsGrid.ts | destination":{"message":"Destination"},"panels/application/components/ReportsGrid.ts | generatedAt":{"message":"Generated at"},"panels/application/components/ReportsGrid.ts | noReportsToDisplay":{"message":"No reports to display"},"panels/application/components/ReportsGrid.ts | status":{"message":"Status"},"panels/application/components/SharedStorageAccessGrid.ts | allSharedStorageEvents":{"message":"All shared storage events for this page."},"panels/application/components/SharedStorageAccessGrid.ts | eventParams":{"message":"Optional Event Params"},"panels/application/components/SharedStorageAccessGrid.ts | eventTime":{"message":"Event Time"},"panels/application/components/SharedStorageAccessGrid.ts | eventType":{"message":"Access Type"},"panels/application/components/SharedStorageAccessGrid.ts | mainFrameId":{"message":"Main Frame ID"},"panels/application/components/SharedStorageAccessGrid.ts | noEvents":{"message":"No shared storage events recorded."},"panels/application/components/SharedStorageAccessGrid.ts | ownerOrigin":{"message":"Owner Origin"},"panels/application/components/SharedStorageAccessGrid.ts | sharedStorage":{"message":"Shared storage"},"panels/application/components/SharedStorageMetadataView.ts | budgetExplanation":{"message":"Remaining data leakage allowed within a 24-hour period for this origin in bits of entropy"},"panels/application/components/SharedStorageMetadataView.ts | creation":{"message":"Creation Time"},"panels/application/components/SharedStorageMetadataView.ts | entropyBudget":{"message":"Entropy Budget for Fenced Frames"},"panels/application/components/SharedStorageMetadataView.ts | notYetCreated":{"message":"Not yet created"},"panels/application/components/SharedStorageMetadataView.ts | numBytesUsed":{"message":"Number of Bytes Used"},"panels/application/components/SharedStorageMetadataView.ts | numEntries":{"message":"Number of Entries"},"panels/application/components/SharedStorageMetadataView.ts | resetBudget":{"message":"Reset Budget"},"panels/application/components/SharedStorageMetadataView.ts | sharedStorage":{"message":"Shared storage"},"panels/application/components/StackTrace.ts | cannotRenderStackTrace":{"message":"Cannot render stack trace"},"panels/application/components/StackTrace.ts | creationStackTrace":{"message":"Frame Creation Stack Trace"},"panels/application/components/StackTrace.ts | showLess":{"message":"Show less"},"panels/application/components/StackTrace.ts | showSMoreFrames":{"message":"{n, plural, =1 {Show # more frame} other {Show # more frames}}"},"panels/application/components/StorageMetadataView.ts | bucketName":{"message":"Bucket name"},"panels/application/components/StorageMetadataView.ts | confirmBucketDeletion":{"message":"Delete the \"{PH1}\" bucket?"},"panels/application/components/StorageMetadataView.ts | defaultBucket":{"message":"Default bucket"},"panels/application/components/StorageMetadataView.ts | deleteBucket":{"message":"Delete bucket"},"panels/application/components/StorageMetadataView.ts | durability":{"message":"Durability"},"panels/application/components/StorageMetadataView.ts | expiration":{"message":"Expiration"},"panels/application/components/StorageMetadataView.ts | isOpaque":{"message":"Is opaque"},"panels/application/components/StorageMetadataView.ts | isThirdParty":{"message":"Is third-party"},"panels/application/components/StorageMetadataView.ts | loading":{"message":"Loading…"},"panels/application/components/StorageMetadataView.ts | no":{"message":"No"},"panels/application/components/StorageMetadataView.ts | none":{"message":"None"},"panels/application/components/StorageMetadataView.ts | opaque":{"message":"(opaque)"},"panels/application/components/StorageMetadataView.ts | origin":{"message":"Origin"},"panels/application/components/StorageMetadataView.ts | persistent":{"message":"Is persistent"},"panels/application/components/StorageMetadataView.ts | quota":{"message":"Quota"},"panels/application/components/StorageMetadataView.ts | topLevelSite":{"message":"Top-level site"},"panels/application/components/StorageMetadataView.ts | yes":{"message":"Yes"},"panels/application/components/StorageMetadataView.ts | yesBecauseAncestorChainHasCrossSite":{"message":"Yes, because the ancestry chain contains a third-party origin"},"panels/application/components/StorageMetadataView.ts | yesBecauseKeyIsOpaque":{"message":"Yes, because the storage key is opaque"},"panels/application/components/StorageMetadataView.ts | yesBecauseOriginNotInTopLevelSite":{"message":"Yes, because the origin is outside of the top-level site"},"panels/application/components/StorageMetadataView.ts | yesBecauseTopLevelIsOpaque":{"message":"Yes, because the top-level site is opaque"},"panels/application/components/TrustTokensView.ts | allStoredTrustTokensAvailableIn":{"message":"All stored private state tokens available in this browser instance."},"panels/application/components/TrustTokensView.ts | deleteTrustTokens":{"message":"Delete all stored private state tokens issued by {PH1}."},"panels/application/components/TrustTokensView.ts | issuer":{"message":"Issuer"},"panels/application/components/TrustTokensView.ts | noTrustTokensStored":{"message":"No private state tokens are currently stored."},"panels/application/components/TrustTokensView.ts | storedTokenCount":{"message":"Stored token count"},"panels/application/components/TrustTokensView.ts | trustTokens":{"message":"Private state tokens"},"panels/application/CookieItemsView.ts | clearAllCookies":{"message":"Clear all cookies"},"panels/application/CookieItemsView.ts | clearFilteredCookies":{"message":"Clear filtered cookies"},"panels/application/CookieItemsView.ts | cookies":{"message":"Cookies"},"panels/application/CookieItemsView.ts | numberOfCookiesShownInTableS":{"message":"Number of cookies shown in table: {PH1}"},"panels/application/CookieItemsView.ts | onlyShowCookiesWhichHaveAn":{"message":"Only show cookies that have an associated issue"},"panels/application/CookieItemsView.ts | onlyShowCookiesWithAnIssue":{"message":"Only show cookies with an issue"},"panels/application/CookieItemsView.ts | selectACookieToPreviewItsValue":{"message":"Select a cookie to preview its value"},"panels/application/CookieItemsView.ts | showUrlDecoded":{"message":"Show URL-decoded"},"panels/application/DOMStorageItemsView.ts | domStorage":{"message":"DOM Storage"},"panels/application/DOMStorageItemsView.ts | domStorageItemDeleted":{"message":"The storage item was deleted."},"panels/application/DOMStorageItemsView.ts | domStorageItems":{"message":"DOM Storage Items"},"panels/application/DOMStorageItemsView.ts | domStorageItemsCleared":{"message":"DOM Storage Items cleared"},"panels/application/DOMStorageItemsView.ts | key":{"message":"Key"},"panels/application/DOMStorageItemsView.ts | value":{"message":"Value"},"panels/application/IndexedDBViews.ts | clearObjectStore":{"message":"Clear object store"},"panels/application/IndexedDBViews.ts | collapse":{"message":"Collapse"},"panels/application/IndexedDBViews.ts | dataMayBeStale":{"message":"Data may be stale"},"panels/application/IndexedDBViews.ts | deleteDatabase":{"message":"Delete database"},"panels/application/IndexedDBViews.ts | deleteSelected":{"message":"Delete selected"},"panels/application/IndexedDBViews.ts | expandRecursively":{"message":"Expand Recursively"},"panels/application/IndexedDBViews.ts | filterByKey":{"message":"Filter by key (show keys greater or equal to)"},"panels/application/IndexedDBViews.ts | idb":{"message":"IDB"},"panels/application/IndexedDBViews.ts | indexedDb":{"message":"Indexed DB"},"panels/application/IndexedDBViews.ts | keyGeneratorValueS":{"message":"Key generator value: {PH1}"},"panels/application/IndexedDBViews.ts | keyPath":{"message":"Key path: "},"panels/application/IndexedDBViews.ts | keyString":{"message":"Key"},"panels/application/IndexedDBViews.ts | objectStores":{"message":"Object stores"},"panels/application/IndexedDBViews.ts | pleaseConfirmDeleteOfSDatabase":{"message":"Please confirm delete of \"{PH1}\" database."},"panels/application/IndexedDBViews.ts | primaryKey":{"message":"Primary key"},"panels/application/IndexedDBViews.ts | refresh":{"message":"Refresh"},"panels/application/IndexedDBViews.ts | refreshDatabase":{"message":"Refresh database"},"panels/application/IndexedDBViews.ts | showNextPage":{"message":"Show next page"},"panels/application/IndexedDBViews.ts | showPreviousPage":{"message":"Show previous page"},"panels/application/IndexedDBViews.ts | someEntriesMayHaveBeenModified":{"message":"Some entries may have been modified"},"panels/application/IndexedDBViews.ts | totalEntriesS":{"message":"Total entries: {PH1}"},"panels/application/IndexedDBViews.ts | valueString":{"message":"Value"},"panels/application/IndexedDBViews.ts | version":{"message":"Version"},"panels/application/InterestGroupStorageView.ts | clickToDisplayBody":{"message":"Click on any interest group event to display the group's current state"},"panels/application/InterestGroupStorageView.ts | noDataAvailable":{"message":"No details available for the selected interest group. The browser may have left the group."},"panels/application/InterestGroupTreeElement.ts | interestGroups":{"message":"Interest groups"},"panels/application/OpenedWindowDetailsView.ts | accessToOpener":{"message":"Access to opener"},"panels/application/OpenedWindowDetailsView.ts | clickToRevealInElementsPanel":{"message":"Click to reveal in Elements panel"},"panels/application/OpenedWindowDetailsView.ts | closed":{"message":"closed"},"panels/application/OpenedWindowDetailsView.ts | crossoriginEmbedderPolicy":{"message":"Cross-Origin Embedder Policy"},"panels/application/OpenedWindowDetailsView.ts | document":{"message":"Document"},"panels/application/OpenedWindowDetailsView.ts | no":{"message":"No"},"panels/application/OpenedWindowDetailsView.ts | openerFrame":{"message":"Opener Frame"},"panels/application/OpenedWindowDetailsView.ts | reportingTo":{"message":"reporting to"},"panels/application/OpenedWindowDetailsView.ts | security":{"message":"Security"},"panels/application/OpenedWindowDetailsView.ts | securityIsolation":{"message":"Security & Isolation"},"panels/application/OpenedWindowDetailsView.ts | showsWhetherTheOpenedWindowIs":{"message":"Shows whether the opened window is able to access its opener and vice versa"},"panels/application/OpenedWindowDetailsView.ts | type":{"message":"Type"},"panels/application/OpenedWindowDetailsView.ts | unknown":{"message":"Unknown"},"panels/application/OpenedWindowDetailsView.ts | url":{"message":"URL"},"panels/application/OpenedWindowDetailsView.ts | webWorker":{"message":"Web Worker"},"panels/application/OpenedWindowDetailsView.ts | windowWithoutTitle":{"message":"Window without title"},"panels/application/OpenedWindowDetailsView.ts | worker":{"message":"worker"},"panels/application/OpenedWindowDetailsView.ts | yes":{"message":"Yes"},"panels/application/preloading/components/MismatchedPreloadingGrid.ts | action":{"message":"Action"},"panels/application/preloading/components/MismatchedPreloadingGrid.ts | status":{"message":"Status"},"panels/application/preloading/components/MismatchedPreloadingGrid.ts | statusFailure":{"message":"Failure"},"panels/application/preloading/components/MismatchedPreloadingGrid.ts | statusNotTriggered":{"message":"Not triggered"},"panels/application/preloading/components/MismatchedPreloadingGrid.ts | statusPending":{"message":"Pending"},"panels/application/preloading/components/MismatchedPreloadingGrid.ts | statusReady":{"message":"Ready"},"panels/application/preloading/components/MismatchedPreloadingGrid.ts | statusRunning":{"message":"Running"},"panels/application/preloading/components/MismatchedPreloadingGrid.ts | statusSuccess":{"message":"Success"},"panels/application/preloading/components/MismatchedPreloadingGrid.ts | url":{"message":"URL"},"panels/application/preloading/components/PreloadingDetailsReportView.ts | buttonClickToInspect":{"message":"Click to inspect prerendered page"},"panels/application/preloading/components/PreloadingDetailsReportView.ts | buttonClickToRevealRuleSet":{"message":"Click to reveal rule set"},"panels/application/preloading/components/PreloadingDetailsReportView.ts | buttonInspect":{"message":"Inspect"},"panels/application/preloading/components/PreloadingDetailsReportView.ts | detailedStatusFailure":{"message":"Speculative load failed."},"panels/application/preloading/components/PreloadingDetailsReportView.ts | detailedStatusNotTriggered":{"message":"Speculative load attempt is not yet triggered."},"panels/application/preloading/components/PreloadingDetailsReportView.ts | detailedStatusPending":{"message":"Speculative load attempt is eligible but pending."},"panels/application/preloading/components/PreloadingDetailsReportView.ts | detailedStatusReady":{"message":"Speculative load finished and the result is ready for the next navigation."},"panels/application/preloading/components/PreloadingDetailsReportView.ts | detailedStatusRunning":{"message":"Speculative load is running."},"panels/application/preloading/components/PreloadingDetailsReportView.ts | detailedStatusSuccess":{"message":"Speculative load finished and used for a navigation."},"panels/application/preloading/components/PreloadingDetailsReportView.ts | detailsAction":{"message":"Action"},"panels/application/preloading/components/PreloadingDetailsReportView.ts | detailsDetailedInformation":{"message":"Detailed information"},"panels/application/preloading/components/PreloadingDetailsReportView.ts | detailsFailureReason":{"message":"Failure reason"},"panels/application/preloading/components/PreloadingDetailsReportView.ts | detailsRuleSet":{"message":"Rule set"},"panels/application/preloading/components/PreloadingDetailsReportView.ts | detailsStatus":{"message":"Status"},"panels/application/preloading/components/PreloadingDetailsReportView.ts | selectAnElementForMoreDetails":{"message":"Select an element for more details"},"panels/application/preloading/components/PreloadingDisabledInfobar.ts | descriptionDisabledByBatterySaver":{"message":"Speculative loading is disabled because of the operating system's Battery Saver mode."},"panels/application/preloading/components/PreloadingDisabledInfobar.ts | descriptionDisabledByDataSaver":{"message":"Speculative loading is disabled because of the operating system's Data Saver mode."},"panels/application/preloading/components/PreloadingDisabledInfobar.ts | descriptionDisabledByHoldbackPrefetchSpeculationRules":{"message":"Prefetch is forced-enabled because DevTools is open. When DevTools is closed, prefetch will be disabled because this browser session is part of a holdback group used for performance comparisons."},"panels/application/preloading/components/PreloadingDisabledInfobar.ts | descriptionDisabledByHoldbackPrerenderSpeculationRules":{"message":"Prerendering is forced-enabled because DevTools is open. When DevTools is closed, prerendering will be disabled because this browser session is part of a holdback group used for performance comparisons."},"panels/application/preloading/components/PreloadingDisabledInfobar.ts | descriptionDisabledByPreference":{"message":"Speculative loading is disabled because of user settings or an extension. Go to {PH1} to update your preference. Go to {PH2} to disable any extension that blocks speculative loading."},"panels/application/preloading/components/PreloadingDisabledInfobar.ts | extensionsSettings":{"message":"Extensions settings"},"panels/application/preloading/components/PreloadingDisabledInfobar.ts | footerLearnMore":{"message":"Learn more"},"panels/application/preloading/components/PreloadingDisabledInfobar.ts | headerDisabledByBatterySaver":{"message":"Battery Saver"},"panels/application/preloading/components/PreloadingDisabledInfobar.ts | headerDisabledByDataSaver":{"message":"Data Saver"},"panels/application/preloading/components/PreloadingDisabledInfobar.ts | headerDisabledByHoldbackPrefetchSpeculationRules":{"message":"Prefetch was disabled, but is force-enabled now"},"panels/application/preloading/components/PreloadingDisabledInfobar.ts | headerDisabledByHoldbackPrerenderSpeculationRules":{"message":"Prerendering was disabled, but is force-enabled now"},"panels/application/preloading/components/PreloadingDisabledInfobar.ts | headerDisabledByPreference":{"message":"User settings or extensions"},"panels/application/preloading/components/PreloadingDisabledInfobar.ts | infobarPreloadingIsDisabled":{"message":"Speculative loading is disabled"},"panels/application/preloading/components/PreloadingDisabledInfobar.ts | infobarPreloadingIsForceEnabled":{"message":"Speculative loading is force-enabled"},"panels/application/preloading/components/PreloadingDisabledInfobar.ts | preloadingPagesSettings":{"message":"Preload pages settings"},"panels/application/preloading/components/PreloadingDisabledInfobar.ts | titleReasonsPreventingPreloading":{"message":"Reasons preventing speculative loading"},"panels/application/preloading/components/PreloadingGrid.ts | action":{"message":"Action"},"panels/application/preloading/components/PreloadingGrid.ts | ruleSet":{"message":"Rule set"},"panels/application/preloading/components/PreloadingGrid.ts | status":{"message":"Status"},"panels/application/preloading/components/PreloadingMismatchedHeadersGrid.ts | activationNavigationValue":{"message":"Value in activation navigation"},"panels/application/preloading/components/PreloadingMismatchedHeadersGrid.ts | headerName":{"message":"Header name"},"panels/application/preloading/components/PreloadingMismatchedHeadersGrid.ts | initialNavigationValue":{"message":"Value in initial navigation"},"panels/application/preloading/components/PreloadingMismatchedHeadersGrid.ts | missing":{"message":"(missing)"},"panels/application/preloading/components/PreloadingString.ts | PrefetchEvictedAfterCandidateRemoved":{"message":"The prefetch was discarded because no speculation rule in the initating page triggers a prefetch for this URL anymore."},"panels/application/preloading/components/PreloadingString.ts | PrefetchEvictedForNewerPrefetch":{"message":"The prefetch was discarded because the initiating page has too many prefetches ongoing, and this was one of the oldest."},"panels/application/preloading/components/PreloadingString.ts | PrefetchFailedIneligibleRedirect":{"message":"The prefetch was redirected, but the redirect URL is not eligible for prefetch."},"panels/application/preloading/components/PreloadingString.ts | PrefetchFailedInvalidRedirect":{"message":"The prefetch was redirected, but there was a problem with the redirect."},"panels/application/preloading/components/PreloadingString.ts | PrefetchFailedMIMENotSupported":{"message":"The prefetch failed because the response's Content-Type header was not supported."},"panels/application/preloading/components/PreloadingString.ts | PrefetchFailedNetError":{"message":"The prefetch failed because of a network error."},"panels/application/preloading/components/PreloadingString.ts | PrefetchFailedNon2XX":{"message":"The prefetch failed because of a non-2xx HTTP response status code."},"panels/application/preloading/components/PreloadingString.ts | PrefetchIneligibleRetryAfter":{"message":"A previous prefetch to the origin got a HTTP 503 response with an Retry-After header that has not elapsed yet."},"panels/application/preloading/components/PreloadingString.ts | PrefetchIsPrivacyDecoy":{"message":"The URL was not eligible to be prefetched because there was a registered service worker or cross-site cookies for that origin, but the prefetch was put on the network anyways and not used, to disguise that the user had some kind of previous relationship with the origin."},"panels/application/preloading/components/PreloadingString.ts | PrefetchIsStale":{"message":"Too much time elapsed between the prefetch and usage, so the prefetch was discarded."},"panels/application/preloading/components/PreloadingString.ts | PrefetchNotEligibleBatterySaverEnabled":{"message":"The prefetch was not performed because the Battery Saver setting was enabled."},"panels/application/preloading/components/PreloadingString.ts | PrefetchNotEligibleBrowserContextOffTheRecord":{"message":"The prefetch was not performed because the browser is in Incognito or Guest mode."},"panels/application/preloading/components/PreloadingString.ts | PrefetchNotEligibleDataSaverEnabled":{"message":"The prefetch was not performed because the operating system is in Data Saver mode."},"panels/application/preloading/components/PreloadingString.ts | PrefetchNotEligibleExistingProxy":{"message":"The URL is not eligible to be prefetched, because in the default network context it is configured to use a proxy server."},"panels/application/preloading/components/PreloadingString.ts | PrefetchNotEligibleHostIsNonUnique":{"message":"The URL was not eligible to be prefetched because its host was not unique (e.g., a non publicly routable IP address or a hostname which is not registry-controlled), but the prefetch was required to be proxied."},"panels/application/preloading/components/PreloadingString.ts | PrefetchNotEligibleNonDefaultStoragePartition":{"message":"The URL was not eligible to be prefetched because it uses a non-default storage partition."},"panels/application/preloading/components/PreloadingString.ts | PrefetchNotEligiblePreloadingDisabled":{"message":"The prefetch was not performed because speculative loading was disabled."},"panels/application/preloading/components/PreloadingString.ts | PrefetchNotEligibleSameSiteCrossOriginPrefetchRequiredProxy":{"message":"The URL was not eligible to be prefetched because the default network context cannot be configured to use the prefetch proxy for a same-site cross-origin prefetch request."},"panels/application/preloading/components/PreloadingString.ts | PrefetchNotEligibleSchemeIsNotHttps":{"message":"The URL was not eligible to be prefetched because its scheme was not https:."},"panels/application/preloading/components/PreloadingString.ts | PrefetchNotEligibleUserHasCookies":{"message":"The URL was not eligible to be prefetched because it was cross-site, but the user had cookies for that origin."},"panels/application/preloading/components/PreloadingString.ts | PrefetchNotEligibleUserHasServiceWorker":{"message":"The URL was not eligible to be prefetched because there was a registered service worker for that origin, which is currently not supported."},"panels/application/preloading/components/PreloadingString.ts | PrefetchNotUsedCookiesChanged":{"message":"The prefetch was not used because it was a cross-site prefetch, and cookies were added for that URL while the prefetch was ongoing, so the prefetched response is now out-of-date."},"panels/application/preloading/components/PreloadingString.ts | PrefetchNotUsedProbeFailed":{"message":"The prefetch was blocked by your Internet Service Provider or network administrator."},"panels/application/preloading/components/PreloadingString.ts | PrefetchProxyNotAvailable":{"message":"A network error was encountered when trying to set up a connection to the prefetching proxy."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusActivatedDuringMainFrameNavigation":{"message":"Prerendered page activated during initiating page's main frame navigation."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusActivatedWithAuxiliaryBrowsingContexts":{"message":"The prerender was not used because during activation time, there were other windows with an active opener reference to the initiating page, which is currently not supported."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusActivationFramePolicyNotCompatible":{"message":"The prerender was not used because the sandboxing flags or permissions policy of the initiating page was not compatible with those of the prerendering page."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusActivationNavigationParameterMismatch":{"message":"The prerender was not used because during activation time, different navigation parameters (e.g., HTTP headers) were calculated than during the original prerendering navigation request."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusActivationUrlHasEffectiveUrl":{"message":"The prerender was not used because during activation time, navigation has an effective URL that is different from its normal URL. (For example, the New Tab Page, or hosted apps.)"},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusAllPrerenderingCanceled":{"message":"All prerendered pages were unloaded by the browser for some reason (For example, WebViewCompat.addWebMessageListener() was called during prerendering.)"},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusAudioOutputDeviceRequested":{"message":"The prerendered page requested audio output, which is currently not supported."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusBatterySaverEnabled":{"message":"The prerender was not performed because the user requested that the browser use less battery."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusBlockedByClient":{"message":"Some resource load was blocked."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusClientCertRequested":{"message":"The prerendering navigation required a HTTP client certificate."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusCrossSiteNavigationInInitialNavigation":{"message":"The prerendering navigation failed because it targeted a cross-site URL."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusCrossSiteNavigationInMainFrameNavigation":{"message":"The prerendered page navigated to a cross-site URL."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusCrossSiteRedirectInInitialNavigation":{"message":"The prerendering navigation failed because the prerendered URL redirected to a cross-site URL."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusCrossSiteRedirectInMainFrameNavigation":{"message":"The prerendered page navigated to a URL which redirected to a cross-site URL."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusDataSaverEnabled":{"message":"The prerender was not performed because the user requested that the browser use less data."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusDownload":{"message":"The prerendered page attempted to initiate a download, which is currently not supported."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusHasEffectiveUrl":{"message":"The initiating page cannot perform prerendering, because it has an effective URL that is different from its normal URL. (For example, the New Tab Page, or hosted apps.)"},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusInvalidSchemeNavigation":{"message":"The URL was not eligible to be prerendered because its scheme was not http: or https:."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusInvalidSchemeRedirect":{"message":"The prerendering navigation failed because it redirected to a URL whose scheme was not http: or https:."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusJavaScriptInterfaceAdded":{"message":"The prerendered page was unloaded because a new JavaScript interface has been injected by WebView.addJavascriptInterface()."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusJavaScriptInterfaceRemoved":{"message":"The prerendered page was unloaded because a JavaScript interface has been removed by WebView.removeJavascriptInterface()."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusLoginAuthRequested":{"message":"The prerendering navigation required HTTP authentication, which is currently not supported."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusLowEndDevice":{"message":"The prerender was not performed because this device does not have enough total system memory to support prerendering."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusMainFrameNavigation":{"message":"The prerendered page navigated itself to another URL, which is currently not supported."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusMaxNumOfRunningEagerPrerendersExceeded":{"message":"The prerender whose eagerness is \"eager\" was not performed because the initiating page already has too many prerenders ongoing. Remove other speculation rules with \"eager\" to enable further prerendering."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusMaxNumOfRunningEmbedderPrerendersExceeded":{"message":"The browser-triggered prerender was not performed because the initiating page already has too many prerenders ongoing."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusMaxNumOfRunningNonEagerPrerendersExceeded":{"message":"The old non-eager prerender (with a \"moderate\" or \"conservative\" eagerness and triggered by hovering or clicking links) was automatically canceled due to starting a new non-eager prerender. It can be retriggered by interacting with the link again."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusMemoryLimitExceeded":{"message":"The prerender was not performed because the browser exceeded the prerendering memory limit."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusMemoryPressureAfterTriggered":{"message":"The prerendered page was unloaded because the browser came under critical memory pressure."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusMemoryPressureOnTrigger":{"message":"The prerender was not performed because the browser was under critical memory pressure."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusMixedContent":{"message":"The prerendered page contained mixed content."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusMojoBinderPolicy":{"message":"The prerendered page used a forbidden JavaScript API that is currently not supported. (Internal Mojo interface: {PH1})"},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusNavigationBadHttpStatus":{"message":"The prerendering navigation failed because of a non-2xx HTTP response status code."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusNavigationRequestBlockedByCsp":{"message":"The prerendering navigation was blocked by a Content Security Policy."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusNavigationRequestNetworkError":{"message":"The prerendering navigation encountered a network error."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusPreloadingDisabled":{"message":"The prerender was not performed because the user disabled preloading in their browser settings."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusPrerenderingDisabledByDevTools":{"message":"The prerender was not performed because DevTools has been used to disable prerendering."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusPrerenderingUrlHasEffectiveUrl":{"message":"The prerendering navigation failed because it has an effective URL that is different from its normal URL. (For example, the New Tab Page, or hosted apps.)"},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusPrimaryMainFrameRendererProcessCrashed":{"message":"The initiating page crashed."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusPrimaryMainFrameRendererProcessKilled":{"message":"The initiating page was killed."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusRedirectedPrerenderingUrlHasEffectiveUrl":{"message":"The prerendering navigation failed because it redirected to an effective URL that is different from its normal URL. (For example, the New Tab Page, or hosted apps.)"},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusRendererProcessCrashed":{"message":"The prerendered page crashed."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusRendererProcessKilled":{"message":"The prerendered page was killed."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusSameSiteCrossOriginNavigationNotOptInInInitialNavigation":{"message":"The prerendering navigation failed because it was to a cross-origin same-site URL, but the destination response did not include the appropriate Supports-Loading-Mode header."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusSameSiteCrossOriginNavigationNotOptInInMainFrameNavigation":{"message":"The prerendered page navigated to a cross-origin same-site URL, but the destination response did not include the appropriate Supports-Loading-Mode header."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusSameSiteCrossOriginRedirectNotOptInInInitialNavigation":{"message":"The prerendering navigation failed because the prerendered URL redirected to a cross-origin same-site URL, but the destination response did not include the appropriate Supports-Loading-Mode header."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusSameSiteCrossOriginRedirectNotOptInInMainFrameNavigation":{"message":"The prerendered page navigated to a URL which redirected to a cross-origin same-site URL, but the destination response did not include the appropriate Supports-Loading-Mode header."},"panels/application/preloading/components/PreloadingString.ts | prerenderFinalStatusSpeculationRuleRemoved":{"message":"The prerendered page was unloaded because the initiating page removed the corresponding prerender rule from , the backend will emit two\n // navigationStarted events that are identical except for timestamps, and\n // this caused the trace engine to crash.\n // To ensure that we handle this case, we have this test which makes sure a\n // trace that does have two navigations with the same ID does not cause the\n // MetaHandler to throw an error.\n const events = await TraceLoader.rawEvents(this, 'multiple-navigations-same-id.json.gz');\n assert.doesNotThrow(function() {\n for (const event of events) {\n TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n });\n });\n\n it('marks a generic trace as generic', async function() {\n const events = await TraceLoader.rawEvents(this, 'generic-about-tracing.json.gz');\n for (const event of events) {\n TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.Meta.finalize();\n assert.isTrue(TraceModel.Handlers.ModelHandlers.Meta.data().traceIsGeneric);\n });\n\n it('marks a web trace as being not generic', async function() {\n const events = await TraceLoader.rawEvents(this, 'web-dev-with-commit.json.gz');\n for (const event of events) {\n TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.Meta.finalize();\n assert.isFalse(TraceModel.Handlers.ModelHandlers.Meta.data().traceIsGeneric);\n });\n\n it('sets the main frame URL from the TracingStartedInBrowser event', async function() {\n // This trace has the right URL in TracingStartedInBrowser\n const events = await TraceLoader.rawEvents(this, 'web-dev-with-commit.json.gz');\n for (const event of events) {\n TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.Meta.finalize();\n const data = TraceModel.Handlers.ModelHandlers.Meta.data();\n assert.strictEqual(data.mainFrameURL, 'https://web.dev/');\n });\n\n it('will alter the main frame URL based on the first main frame navigation', async function() {\n // This trace has the wrong URL in TracingStartedInBrowser - but it will be\n // corrected by looking at the first main frame navigation.\n const events = await TraceLoader.rawEvents(this, 'web-dev-initial-url.json.gz');\n for (const event of events) {\n TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.Meta.finalize();\n const data = TraceModel.Handlers.ModelHandlers.Meta.data();\n assert.strictEqual(data.mainFrameURL, 'https://web.dev/articles/inp');\n });\n\n it('returns a list of processes and process_name events', async function() {\n const events = await TraceLoader.rawEvents(this, 'web-dev-initial-url.json.gz');\n for (const event of events) {\n TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.Meta.finalize();\n const data = TraceModel.Handlers.ModelHandlers.Meta.data();\n const pidsToNames = Array.from(data.processNames.entries(), ([pid, event]) => {\n return [pid, event.args.name];\n });\n assert.deepEqual(pidsToNames, [\n [TraceModel.Types.TraceEvents.ProcessID(37605), 'Browser'],\n [TraceModel.Types.TraceEvents.ProcessID(48544), 'Renderer'],\n [TraceModel.Types.TraceEvents.ProcessID(37613), 'GPU Process'],\n [TraceModel.Types.TraceEvents.ProcessID(48531), 'Renderer'],\n ]);\n });\n\n it('does not set a frame as a main frame if it has no URL.', async function() {\n // This test exists because of a bug report from this trace where we\n // incorrectly set the main frame ID, causing DevTools to pick an advert in\n // an iframe as the main thread. This happened because we happily set\n // mainFrameID to a frame that had no URL, which doesn't make sense.\n const events = await TraceLoader.rawEvents(this, 'wrong-main-frame-bug.json.gz');\n for (const event of events) {\n TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.Meta.finalize();\n const data = TraceModel.Handlers.ModelHandlers.Meta.data();\n assert.strictEqual(data.mainFrameId, 'D1731088F5DE299149240DF9E6025291');\n });\n\n it('will use isOutermostMainFrame to determine the main frame from the TracingStartedInBrowser event if it is present',\n async function() {\n const events = await TraceLoader.rawEvents(this, 'web-dev-outermost-frames.json.gz');\n for (const event of events) {\n TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.Meta.finalize();\n const data = TraceModel.Handlers.ModelHandlers.Meta.data();\n assert.strictEqual(data.mainFrameId, '881522AC20B813B0C0E99E27CEBAB951');\n });\n\n it('will use isInPrimaryPage along with isOutermostMainFrame to identify the main frame from TracingStartedInBrowser',\n async function() {\n // See crbug.com/343873756 for context on this bug report and fix.\n const events = await TraceLoader.rawEvents(this, 'primary-page-frame.json.gz');\n for (const event of events) {\n TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.Meta.finalize();\n const data = TraceModel.Handlers.ModelHandlers.Meta.data();\n // If you look at the trace, this is the frame that is both:\n // isInPrimaryPage === true\n // isOutermostMainFrame == true\n //\n // The other frames have isOutermostMainFrame == true (as they are pre-rendered pages)\n // But they are not in the primary page.\n assert.strictEqual(data.mainFrameId, '07B7D55F5BE0ADB8AAD6502F2D3859FF');\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"MetaHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/MetaHandler.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {defaultTraceEvent} from '../../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Trace from '../trace.js';\n\ndescribe('MetaHandler', function() {\n let baseEvents: Trace.Types.Events.Event[];\n beforeEach(async function() {\n let defaultTraceEvents: readonly Trace.Types.Events.Event[];\n try {\n defaultTraceEvents = await TraceLoader.rawEvents(this, 'basic.json.gz');\n } catch (error) {\n assert.fail(error);\n return;\n }\n\n baseEvents = [\n ...defaultTraceEvents,\n {\n ...defaultTraceEvent,\n args: {\n data: {\n isLoadingMainFrame: true,\n isOutermostMainFrame: true,\n documentLoaderURL: 'test1',\n navigationId: 'navigation-1',\n },\n frame: '3E1717BE677B75D0536E292E00D6A34A',\n },\n pid: Trace.Types.Events.ProcessID(23456),\n tid: Trace.Types.Events.ThreadID(775),\n ts: Trace.Types.Timing.MicroSeconds(100),\n name: 'navigationStart',\n } as Trace.Types.Events.NavigationStart,\n {\n ...defaultTraceEvent,\n // Should be ignored based on empty documentLoaderURL\n args: {\n data: {\n isLoadingMainFrame: true,\n isOutermostMainFrame: true,\n documentLoaderURL: '',\n navigationId: 'navigation-2',\n },\n },\n pid: Trace.Types.Events.ProcessID(23456),\n tid: Trace.Types.Events.ThreadID(775),\n ts: Trace.Types.Timing.MicroSeconds(800),\n name: 'navigationStart',\n } as Trace.Types.Events.NavigationStart,\n {\n ...defaultTraceEvent,\n args: {\n data: {\n isLoadingMainFrame: true,\n isOutermostMainFrame: true,\n documentLoaderURL: 'test3',\n navigationId: 'navigation-3',\n },\n },\n pid: Trace.Types.Events.ProcessID(23456),\n tid: Trace.Types.Events.ThreadID(775),\n ts: Trace.Types.Timing.MicroSeconds(1000),\n name: 'navigationStart',\n } as Trace.Types.Events.NavigationStart,\n ];\n\n Trace.Handlers.ModelHandlers.Meta.reset();\n Trace.Handlers.ModelHandlers.Meta.initialize();\n });\n\n describe('error handling', function() {\n it('throws if data is called before finalize', function() {\n for (const event of baseEvents) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n\n assert.throws(() => {\n Trace.Handlers.ModelHandlers.Meta.data();\n }, 'Handler is not finalized');\n });\n\n it('throws if initialize is called without a reset', function() {\n // Due to the beforeEach the handler is already initialized, so calling\n // it a second time should throw an error.\n assert.throws(() => {\n Trace.Handlers.ModelHandlers.Meta.initialize();\n }, 'Handler was not reset');\n });\n });\n\n describe('browser process ID', function() {\n it('obtains the PID if present', async () => {\n for (const event of baseEvents) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n const data = Trace.Handlers.ModelHandlers.Meta.data();\n assert.strictEqual(data.browserProcessId, Trace.Types.Events.ProcessID(8017));\n });\n });\n\n describe('browser thread ID', function() {\n it('obtains the TID if present', async () => {\n for (const event of baseEvents) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n const data = Trace.Handlers.ModelHandlers.Meta.data();\n assert.strictEqual(data.browserThreadId, Trace.Types.Events.ThreadID(775));\n });\n });\n\n describe('renderer process ID', function() {\n it('obtains the PID if present', async () => {\n for (const event of baseEvents) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n const data = Trace.Handlers.ModelHandlers.Meta.data();\n assert.strictEqual(data.topLevelRendererIds.size, 1);\n assert.deepStrictEqual([...data.topLevelRendererIds], [Trace.Types.Events.ProcessID(8051)]);\n });\n });\n\n describe('navigations', function() {\n it('obtains them if present', async () => {\n for (const event of baseEvents) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n const data = Trace.Handlers.ModelHandlers.Meta.data();\n // navigation-2 is discarded because it has no URL.\n // navigation-3 doesn't have a frame id so it is discarded as well.\n assert.strictEqual(data.navigationsByFrameId.size, 1);\n assert.strictEqual(data.navigationsByNavigationId.size, 1);\n\n const firstNavigation = data.navigationsByNavigationId.get('navigation-1');\n if (!firstNavigation?.args.data) {\n assert.fail('Navigation data was expected in trace events');\n return;\n }\n\n assert.strictEqual(firstNavigation.args.data.documentLoaderURL, 'test1');\n });\n\n it('provides a list of main frame only navigations', async function() {\n const events = await TraceLoader.rawEvents(this, 'multiple-navigations-with-iframes.json.gz');\n Trace.Handlers.ModelHandlers.Meta.reset();\n Trace.Handlers.ModelHandlers.Meta.initialize();\n for (const event of events) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n const data = Trace.Handlers.ModelHandlers.Meta.data();\n const allNavigationsCount = data.navigationsByNavigationId.size;\n assert.isTrue(data.mainFrameNavigations.length < allNavigationsCount);\n assert.isTrue(data.mainFrameNavigations.every(event => {\n return event.args.frame === data.mainFrameId;\n }));\n });\n });\n\n describe('frames', function() {\n it('finds the main frame ID', async () => {\n for (const event of baseEvents) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n const data = Trace.Handlers.ModelHandlers.Meta.data();\n assert.strictEqual(data.mainFrameId, '3E1717BE677B75D0536E292E00D6A34A');\n });\n\n it('finds the main frame ID for a trace that started with a page reload', async function() {\n const events = await TraceLoader.rawEvents(this, 'reload-and-trace-page.json.gz');\n Trace.Handlers.ModelHandlers.Meta.reset();\n Trace.Handlers.ModelHandlers.Meta.initialize();\n for (const event of events) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n const data = Trace.Handlers.ModelHandlers.Meta.data();\n assert.strictEqual(data.mainFrameId, '1D148CB660D1F96ED70D78DC6A53267B');\n });\n it('tracks the frames for found processes', async function() {\n const events = await TraceLoader.rawEvents(this, 'reload-and-trace-page.json.gz');\n Trace.Handlers.ModelHandlers.Meta.reset();\n Trace.Handlers.ModelHandlers.Meta.initialize();\n for (const event of events) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n const data = Trace.Handlers.ModelHandlers.Meta.data();\n assert.strictEqual(data.frameByProcessId.size, 1);\n const [[processId, framesInProcess]] = data.frameByProcessId.entries();\n assert.strictEqual(processId, 3581385);\n assert.strictEqual(framesInProcess.size, 1);\n const [{url}] = framesInProcess.values();\n assert.strictEqual(url, 'https://example.com/');\n });\n });\n\n describe('finding GPU thread and main frame', function() {\n it('finds the GPU process and GPU Thread', async function() {\n const events = await TraceLoader.rawEvents(this, 'threejs-gpu.json.gz');\n Trace.Handlers.ModelHandlers.Meta.reset();\n Trace.Handlers.ModelHandlers.Meta.initialize();\n for (const event of events) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n const {gpuProcessId, gpuThreadId} = Trace.Handlers.ModelHandlers.Meta.data();\n assert.strictEqual(gpuProcessId, Trace.Types.Events.ProcessID(3581327));\n assert.strictEqual(gpuThreadId, Trace.Types.Events.ThreadID(3581327));\n });\n\n it('handles traces that do not have a GPU thread and returns undefined for the thread ID', async function() {\n const traceEventsWithNoGPUThread = await TraceLoader.rawEvents(this, 'forced-layouts-and-no-gpu.json.gz');\n for (const event of traceEventsWithNoGPUThread) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n\n assert.doesNotThrow(async () => {\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n });\n\n const data = Trace.Handlers.ModelHandlers.Meta.data();\n assert.isUndefined(data.gpuThreadId);\n });\n });\n\n it('obtains renderer process IDs when there are no navigations', async function() {\n let traceEvents: readonly Trace.Types.Events.Event[];\n try {\n traceEvents = await TraceLoader.rawEvents(this, 'threejs-gpu.json.gz');\n } catch (error) {\n assert.fail(error);\n return;\n }\n\n Trace.Handlers.ModelHandlers.Meta.reset();\n Trace.Handlers.ModelHandlers.Meta.initialize();\n for (const event of traceEvents) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n\n const data = Trace.Handlers.ModelHandlers.Meta.data();\n assert.deepStrictEqual([...data.topLevelRendererIds], [3601132]);\n\n const rendererProcesses = data.rendererProcessesByFrame.get(data.mainFrameId);\n if (!rendererProcesses) {\n assert.fail('No renderer processes found');\n return;\n }\n assert.deepStrictEqual([...rendererProcesses?.keys()], [3601132]);\n const windowMinTime = 1143381875846;\n assert.deepStrictEqual(\n [...rendererProcesses?.values()], [[{\n frame: {\n frame: '1D148CB660D1F96ED70D78DC6A53267B',\n name: '',\n processId: 3601132,\n url: 'https://threejs.org/examples/',\n },\n window: {min: windowMinTime, max: data.traceBounds.max, range: data.traceBounds.max - windowMinTime},\n }]]);\n });\n\n it('handles multiple renderers from navigations', async function() {\n let traceEvents: readonly Trace.Types.Events.Event[];\n try {\n traceEvents = await TraceLoader.rawEvents(this, 'multiple-top-level-renderers.json.gz');\n } catch (error) {\n assert.fail(error);\n return;\n }\n\n Trace.Handlers.ModelHandlers.Meta.reset();\n Trace.Handlers.ModelHandlers.Meta.initialize();\n for (const event of traceEvents) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n\n const data = Trace.Handlers.ModelHandlers.Meta.data();\n assert.deepStrictEqual([...data.topLevelRendererIds], [78450, 78473, 79194]);\n\n const rendererProcesses = data.rendererProcessesByFrame.get(data.mainFrameId);\n if (!rendererProcesses) {\n assert.fail('No renderer processes found');\n return;\n }\n\n const windowMinTime = 3550807444741;\n assert.deepStrictEqual([...rendererProcesses?.keys()], [78450, 78473, 79194]);\n assert.deepStrictEqual([...rendererProcesses?.values()], [\n [{\n frame: {\n frame: 'E70A9327100EBD78F1C03582BBBE8E5F',\n name: '',\n processId: 78450,\n url: 'http://127.0.0.1:8081/',\n },\n window: {min: 3550803491779, max: 3550805534872, range: 2043093},\n }],\n [{\n frame: {\n frame: 'E70A9327100EBD78F1C03582BBBE8E5F',\n name: '',\n processId: 78473,\n url: 'http://localhost:8080/',\n },\n window: {min: 3550805534873, max: 3550807444740, range: 1909867},\n }],\n [{\n frame: {\n frame: 'E70A9327100EBD78F1C03582BBBE8E5F',\n name: '',\n processId: 79194,\n url: 'https://www.google.com/',\n },\n window: {min: windowMinTime, max: data.traceBounds.max, range: data.traceBounds.max - windowMinTime},\n }],\n ]);\n });\n it('handles multiple renderers from navigations where a process handled multiple URLs ', async function() {\n let traceEvents: readonly Trace.Types.Events.Event[];\n try {\n traceEvents = await TraceLoader.rawEvents(this, 'simple-js-program.json.gz');\n } catch (error) {\n assert.fail(error);\n return;\n }\n\n Trace.Handlers.ModelHandlers.Meta.reset();\n Trace.Handlers.ModelHandlers.Meta.initialize();\n for (const event of traceEvents) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n\n const data = Trace.Handlers.ModelHandlers.Meta.data();\n assert.deepStrictEqual([...data.topLevelRendererIds], [2080]);\n\n const rendererProcesses = data.rendererProcessesByFrame.get(data.mainFrameId);\n if (!rendererProcesses) {\n assert.fail('No renderer processes found');\n return;\n }\n\n assert.deepStrictEqual([...rendererProcesses?.keys()], [2080]);\n assert.deepStrictEqual([...rendererProcesses?.values()], [\n [\n {\n frame: {\n frame: '1F729458403A23CF1D8D246095129AC4',\n name: '',\n processId: 2080,\n url: 'about:blank',\n },\n window: {\n min: 251126654355,\n max: 251126663397,\n range: 9042,\n },\n },\n {\n frame: {\n frame: '1F729458403A23CF1D8D246095129AC4',\n name: '',\n processId: 2080,\n url: 'https://www.google.com',\n },\n window: {\n min: 251126663398,\n max: 251128073034,\n range: 1409636,\n },\n },\n ],\n ]);\n });\n\n it('calculates trace bounds correctly', async function() {\n let traceEvents: readonly Trace.Types.Events.Event[];\n try {\n traceEvents = await TraceLoader.rawEvents(this, 'basic.json.gz');\n } catch (error) {\n assert.fail(error);\n return;\n }\n\n Trace.Handlers.ModelHandlers.Meta.reset();\n Trace.Handlers.ModelHandlers.Meta.initialize();\n for (const event of traceEvents) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n\n const data = Trace.Handlers.ModelHandlers.Meta.data();\n const {\n max,\n min,\n range,\n } = data.traceBounds;\n const expectedMin = 50_442_438_975;\n const expectedMax = 50_442_438_976;\n assert.strictEqual(min, expectedMin, 'Min calculated incorrectly');\n assert.strictEqual(max, expectedMax, 'Max calculated incorrectly');\n assert.strictEqual(range, expectedMax - expectedMin, 'Range calculated incorrectly');\n });\n\n it('calculates the min trace bound correctly if no TracingStartedInBrowser event is found', async function() {\n const baseEvents = await TraceLoader.rawEvents(this, 'basic.json.gz');\n // We are about to mutate these events, so copy them to avoid mutating the\n // cached events from the TraceLoader.\n const traceEvents = baseEvents.slice().filter(event => {\n // Delete the tracing started in browser event to force the min bounds to\n // be calculated based on the event with the smallest timestamp.\n return event.name !== 'TracingStartedInBrowser';\n });\n\n Trace.Handlers.ModelHandlers.Meta.reset();\n Trace.Handlers.ModelHandlers.Meta.initialize();\n for (const event of traceEvents) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n\n const data = Trace.Handlers.ModelHandlers.Meta.data();\n const expectedMin = 50_442_438_976;\n assert.strictEqual(data.traceBounds.min, expectedMin, 'Min calculated incorrectly');\n });\n\n it('ignores ::UMA Events', async function() {\n let traceEvents: readonly Trace.Types.Events.Event[];\n try {\n // This file contains UMA events which need to be ignored.\n traceEvents = await TraceLoader.rawEvents(this, 'web-dev.json.gz');\n } catch (error) {\n assert.fail(error);\n return;\n }\n\n Trace.Handlers.ModelHandlers.Meta.reset();\n Trace.Handlers.ModelHandlers.Meta.initialize();\n for (const event of traceEvents) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n\n const data = Trace.Handlers.ModelHandlers.Meta.data();\n const {\n max,\n min,\n range,\n } = data.traceBounds;\n const expectedMin = 1_020_034_823_047;\n const expectedMax = 1_020_036_087_961;\n assert.strictEqual(min, expectedMin, 'Min calculated incorrectly');\n assert.strictEqual(max, expectedMax, 'Max calculated incorrectly');\n assert.strictEqual(range, expectedMax - expectedMin, 'Range calculated incorrectly');\n });\n\n it('collects all thread metadata in all processes', async () => {\n for (const event of baseEvents) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n const data = Trace.Handlers.ModelHandlers.Meta.data();\n const collected = [...data.threadsInProcess.values()].map(threadInProcess => [...threadInProcess.values()]);\n\n expect(collected.map(process => process.map(thread => thread.args.name))).to.deep.equal([\n [\n 'swapper',\n 'VizCompositorThread',\n 'ThreadPoolServiceThread',\n 'ThreadPoolBackgroundWorker',\n 'GpuWatchdog',\n 'ThreadPoolForegroundWorker',\n ],\n [\n 'CrBrowserMain',\n 'Chrome_IOThread',\n 'ThreadPoolServiceThread',\n 'Chrome_DevToolsADBThread',\n 'ThreadPoolForegroundWorker',\n ],\n [\n 'CrRendererMain',\n 'Compositor',\n 'Chrome_ChildIOThread',\n 'ThreadPoolServiceThread',\n 'ThreadPoolForegroundWorker',\n ],\n [\n 'CrRendererMain',\n 'Compositor',\n 'Chrome_ChildIOThread',\n 'ThreadPoolServiceThread',\n 'ThreadPoolForegroundWorker',\n ],\n ]);\n });\n\n it('can handle edge cases where there are multiple navigations with the same ID', async function() {\n // For context to why this test and trace file exist, see crbug.com/1503982\n // If an HTML page contains , the backend will emit two\n // navigationStarted events that are identical except for timestamps, and\n // this caused the trace engine to crash.\n // To ensure that we handle this case, we have this test which makes sure a\n // trace that does have two navigations with the same ID does not cause the\n // MetaHandler to throw an error.\n const events = await TraceLoader.rawEvents(this, 'multiple-navigations-same-id.json.gz');\n assert.doesNotThrow(function() {\n for (const event of events) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n });\n });\n\n it('marks a generic trace as generic', async function() {\n const events = await TraceLoader.rawEvents(this, 'generic-about-tracing.json.gz');\n for (const event of events) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n assert.isTrue(Trace.Handlers.ModelHandlers.Meta.data().traceIsGeneric);\n });\n\n it('marks a web trace as being not generic', async function() {\n const events = await TraceLoader.rawEvents(this, 'web-dev-with-commit.json.gz');\n for (const event of events) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n assert.isFalse(Trace.Handlers.ModelHandlers.Meta.data().traceIsGeneric);\n });\n\n it('sets the main frame URL from the TracingStartedInBrowser event', async function() {\n // This trace has the right URL in TracingStartedInBrowser\n const events = await TraceLoader.rawEvents(this, 'web-dev-with-commit.json.gz');\n for (const event of events) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n const data = Trace.Handlers.ModelHandlers.Meta.data();\n assert.strictEqual(data.mainFrameURL, 'https://web.dev/');\n });\n\n it('will alter the main frame URL based on the first main frame navigation', async function() {\n // This trace has the wrong URL in TracingStartedInBrowser - but it will be\n // corrected by looking at the first main frame navigation.\n const events = await TraceLoader.rawEvents(this, 'web-dev-initial-url.json.gz');\n for (const event of events) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n const data = Trace.Handlers.ModelHandlers.Meta.data();\n assert.strictEqual(data.mainFrameURL, 'https://web.dev/articles/inp');\n });\n\n it('returns a list of processes and process_name events', async function() {\n const events = await TraceLoader.rawEvents(this, 'web-dev-initial-url.json.gz');\n for (const event of events) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n const data = Trace.Handlers.ModelHandlers.Meta.data();\n const pidsToNames = Array.from(data.processNames.entries(), ([pid, event]) => {\n return [pid, event.args.name];\n });\n assert.deepEqual(pidsToNames, [\n [Trace.Types.Events.ProcessID(37605), 'Browser'],\n [Trace.Types.Events.ProcessID(48544), 'Renderer'],\n [Trace.Types.Events.ProcessID(37613), 'GPU Process'],\n [Trace.Types.Events.ProcessID(48531), 'Renderer'],\n ]);\n });\n\n it('does not set a frame as a main frame if it has no URL.', async function() {\n // This test exists because of a bug report from this trace where we\n // incorrectly set the main frame ID, causing DevTools to pick an advert in\n // an iframe as the main thread. This happened because we happily set\n // mainFrameID to a frame that had no URL, which doesn't make sense.\n const events = await TraceLoader.rawEvents(this, 'wrong-main-frame-bug.json.gz');\n for (const event of events) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n const data = Trace.Handlers.ModelHandlers.Meta.data();\n assert.strictEqual(data.mainFrameId, 'D1731088F5DE299149240DF9E6025291');\n });\n\n it('will use isOutermostMainFrame to determine the main frame from the TracingStartedInBrowser event if it is present',\n async function() {\n const events = await TraceLoader.rawEvents(this, 'web-dev-outermost-frames.json.gz');\n for (const event of events) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n const data = Trace.Handlers.ModelHandlers.Meta.data();\n assert.strictEqual(data.mainFrameId, '881522AC20B813B0C0E99E27CEBAB951');\n });\n\n it('will use isInPrimaryPage along with isOutermostMainFrame to identify the main frame from TracingStartedInBrowser',\n async function() {\n // See crbug.com/343873756 for context on this bug report and fix.\n const events = await TraceLoader.rawEvents(this, 'primary-page-frame.json.gz');\n for (const event of events) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n const data = Trace.Handlers.ModelHandlers.Meta.data();\n // If you look at the trace, this is the frame that is both:\n // isInPrimaryPage === true\n // isOutermostMainFrame == true\n //\n // The other frames have isOutermostMainFrame == true (as they are pre-rendered pages)\n // But they are not in the primary page.\n assert.strictEqual(data.mainFrameId, '07B7D55F5BE0ADB8AAD6502F2D3859FF');\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/ModelHandlers.d.ts b/public/models/trace/handlers/ModelHandlers.d.ts index 433e87e25..2fc29ecfc 100644 --- a/public/models/trace/handlers/ModelHandlers.d.ts +++ b/public/models/trace/handlers/ModelHandlers.d.ts @@ -1,6 +1,5 @@ export * as Animations from './AnimationHandler.js'; export * as AuctionWorklets from './AuctionWorkletsHandler.js'; -export * as EnhancedTraces from './EnhancedTracesHandler.js'; export * as ExtensionTraceData from './ExtensionTraceDataHandler.js'; export * as Frames from './FramesHandler.js'; export * as GPU from './GPUHandler.js'; diff --git a/public/models/trace/handlers/ModelHandlers.js b/public/models/trace/handlers/ModelHandlers.js index cdb4ae767..0fc63c79e 100644 --- a/public/models/trace/handlers/ModelHandlers.js +++ b/public/models/trace/handlers/ModelHandlers.js @@ -3,7 +3,6 @@ // found in the LICENSE file. export * as Animations from './AnimationHandler.js'; export * as AuctionWorklets from './AuctionWorkletsHandler.js'; -export * as EnhancedTraces from './EnhancedTracesHandler.js'; export * as ExtensionTraceData from './ExtensionTraceDataHandler.js'; export * as Frames from './FramesHandler.js'; export * as GPU from './GPUHandler.js'; diff --git a/public/models/trace/handlers/ModelHandlers.js.map b/public/models/trace/handlers/ModelHandlers.js.map index ddb552b25..c81e8101c 100644 --- a/public/models/trace/handlers/ModelHandlers.js.map +++ b/public/models/trace/handlers/ModelHandlers.js.map @@ -1 +1 @@ -{"version":3,"file":"ModelHandlers.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/ModelHandlers.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,UAAU,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,eAAe,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,cAAc,MAAM,4BAA4B,CAAC;AAC7D,OAAO,KAAK,kBAAkB,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAC;AAC7C,OAAO,KAAK,GAAG,MAAM,iBAAiB,CAAC;AACvC,OAAO,KAAK,aAAa,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,aAAa,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,iBAAiB,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,gBAAgB,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,YAAY,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAC;AAC7C,OAAO,KAAK,IAAI,MAAM,kBAAkB,CAAC;AACzC,OAAO,KAAK,eAAe,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,eAAe,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAC;AACjD,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAC;AAC/C,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,aAAa,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,aAAa,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,gBAAgB,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAC;AACjD,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAC","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nexport * as Animations from './AnimationHandler.js';\nexport * as AuctionWorklets from './AuctionWorkletsHandler.js';\nexport * as EnhancedTraces from './EnhancedTracesHandler.js';\nexport * as ExtensionTraceData from './ExtensionTraceDataHandler.js';\nexport * as Frames from './FramesHandler.js';\nexport * as GPU from './GPUHandler.js';\nexport * as ImagePainting from './ImagePaintingHandler.js';\nexport * as Initiators from './InitiatorsHandler.js';\nexport * as Invalidations from './InvalidationsHandler.js';\nexport * as LargestImagePaint from './LargestImagePaintHandler.js';\nexport * as LargestTextPaint from './LargestTextPaintHandler.js';\nexport * as LayerTree from './LayerTreeHandler.js';\nexport * as LayoutShifts from './LayoutShiftsHandler.js';\nexport * as Memory from './MemoryHandler.js';\nexport * as Meta from './MetaHandler.js';\nexport * as NetworkRequests from './NetworkRequestsHandler.js';\nexport * as PageFrames from './PageFramesHandler.js';\nexport * as PageLoadMetrics from './PageLoadMetricsHandler.js';\nexport * as Renderer from './RendererHandler.js';\nexport * as Samples from './SamplesHandler.js';\nexport * as Screenshots from './ScreenshotsHandler.js';\nexport * as SelectorStats from './SelectorStatsHandler.js';\nexport * as ServerTimings from './ServerTimingsHandler.js';\nexport * as UserInteractions from './UserInteractionsHandler.js';\nexport * as UserTimings from './UserTimingsHandler.js';\nexport * as Warnings from './WarningsHandler.js';\nexport * as Workers from './WorkersHandler.js';\n"]} \ No newline at end of file +{"version":3,"file":"ModelHandlers.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/ModelHandlers.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,UAAU,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,eAAe,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,kBAAkB,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAC;AAC7C,OAAO,KAAK,GAAG,MAAM,iBAAiB,CAAC;AACvC,OAAO,KAAK,aAAa,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,aAAa,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,iBAAiB,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,gBAAgB,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAC;AACnD,OAAO,KAAK,YAAY,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAC;AAC7C,OAAO,KAAK,IAAI,MAAM,kBAAkB,CAAC;AACzC,OAAO,KAAK,eAAe,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,UAAU,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,eAAe,MAAM,6BAA6B,CAAC;AAC/D,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAC;AACjD,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAC;AAC/C,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,aAAa,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,aAAa,MAAM,2BAA2B,CAAC;AAC3D,OAAO,KAAK,gBAAgB,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC;AACvD,OAAO,KAAK,QAAQ,MAAM,sBAAsB,CAAC;AACjD,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAC","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nexport * as Animations from './AnimationHandler.js';\nexport * as AuctionWorklets from './AuctionWorkletsHandler.js';\nexport * as ExtensionTraceData from './ExtensionTraceDataHandler.js';\nexport * as Frames from './FramesHandler.js';\nexport * as GPU from './GPUHandler.js';\nexport * as ImagePainting from './ImagePaintingHandler.js';\nexport * as Initiators from './InitiatorsHandler.js';\nexport * as Invalidations from './InvalidationsHandler.js';\nexport * as LargestImagePaint from './LargestImagePaintHandler.js';\nexport * as LargestTextPaint from './LargestTextPaintHandler.js';\nexport * as LayerTree from './LayerTreeHandler.js';\nexport * as LayoutShifts from './LayoutShiftsHandler.js';\nexport * as Memory from './MemoryHandler.js';\nexport * as Meta from './MetaHandler.js';\nexport * as NetworkRequests from './NetworkRequestsHandler.js';\nexport * as PageFrames from './PageFramesHandler.js';\nexport * as PageLoadMetrics from './PageLoadMetricsHandler.js';\nexport * as Renderer from './RendererHandler.js';\nexport * as Samples from './SamplesHandler.js';\nexport * as Screenshots from './ScreenshotsHandler.js';\nexport * as SelectorStats from './SelectorStatsHandler.js';\nexport * as ServerTimings from './ServerTimingsHandler.js';\nexport * as UserInteractions from './UserInteractionsHandler.js';\nexport * as UserTimings from './UserTimingsHandler.js';\nexport * as Warnings from './WarningsHandler.js';\nexport * as Workers from './WorkersHandler.js';\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/NetworkRequestsHandler.d.ts b/public/models/trace/handlers/NetworkRequestsHandler.d.ts index d7dcee3ce..71cfd422b 100644 --- a/public/models/trace/handlers/NetworkRequestsHandler.d.ts +++ b/public/models/trace/handlers/NetworkRequestsHandler.d.ts @@ -1,32 +1,33 @@ import * as Types from '../types/types.js'; -import { type TraceEventHandlerName } from './types.js'; +import { type HandlerName } from './types.js'; export interface WebSocketTraceDataForFrame { frame: string; webSocketIdentifier: number; - events: Types.TraceEvents.WebSocketEvent[]; - syntheticConnectionEvent: Types.TraceEvents.SyntheticWebSocketConnectionEvent | null; + events: Types.Events.WebSocketEvent[]; + syntheticConnection: Types.Events.SyntheticWebSocketConnection | null; } export interface WebSocketTraceDataForWorker { workerId: string; webSocketIdentifier: number; - events: Types.TraceEvents.WebSocketEvent[]; - syntheticConnectionEvent: Types.TraceEvents.SyntheticWebSocketConnectionEvent | null; + events: Types.Events.WebSocketEvent[]; + syntheticConnection: Types.Events.SyntheticWebSocketConnection | null; } export type WebSocketTraceData = WebSocketTraceDataForFrame | WebSocketTraceDataForWorker; interface NetworkRequestData { + byId: Map; byOrigin: Map; - byTime: Types.TraceEvents.SyntheticNetworkRequest[]; - eventToInitiator: Map; + byTime: Types.Events.SyntheticNetworkRequest[]; + eventToInitiator: Map; webSocket: WebSocketTraceData[]; } export declare function reset(): void; export declare function initialize(): void; -export declare function handleEvent(event: Types.TraceEvents.TraceEventData): void; +export declare function handleEvent(event: Types.Events.Event): void; export declare function finalize(): Promise; export declare function data(): NetworkRequestData; -export declare function deps(): TraceEventHandlerName[]; +export declare function deps(): HandlerName[]; export {}; diff --git a/public/models/trace/handlers/NetworkRequestsHandler.js b/public/models/trace/handlers/NetworkRequestsHandler.js index 9333fe30b..c6802da31 100644 --- a/public/models/trace/handlers/NetworkRequestsHandler.js +++ b/public/models/trace/handlers/NetworkRequestsHandler.js @@ -9,6 +9,7 @@ const MILLISECONDS_TO_MICROSECONDS = 1000; const SECONDS_TO_MICROSECONDS = 1000000; const webSocketData = new Map(); const requestMap = new Map(); +const requestsById = new Map(); const requestsByOrigin = new Map(); const requestsByTime = []; const networkRequestEventByInitiatorUrl = new Map(); @@ -43,6 +44,7 @@ function firstPositiveValueInList(entries) { } let handlerState = 1 /* HandlerState.UNINITIALIZED */; export function reset() { + requestsById.clear(); requestsByOrigin.clear(); requestMap.clear(); requestsByTime.length = 0; @@ -58,36 +60,36 @@ export function handleEvent(event) { if (handlerState !== 2 /* HandlerState.INITIALIZED */) { throw new Error('Network Request handler is not initialized'); } - if (Types.TraceEvents.isTraceEventResourceChangePriority(event)) { + if (Types.Events.isResourceChangePriority(event)) { storeTraceEventWithRequestId(event.args.data.requestId, 'changePriority', event); return; } - if (Types.TraceEvents.isTraceEventResourceWillSendRequest(event)) { + if (Types.Events.isResourceWillSendRequest(event)) { storeTraceEventWithRequestId(event.args.data.requestId, 'willSendRequests', [event]); return; } - if (Types.TraceEvents.isTraceEventResourceSendRequest(event)) { + if (Types.Events.isResourceSendRequest(event)) { storeTraceEventWithRequestId(event.args.data.requestId, 'sendRequests', [event]); return; } - if (Types.TraceEvents.isTraceEventResourceReceiveResponse(event)) { + if (Types.Events.isResourceReceiveResponse(event)) { storeTraceEventWithRequestId(event.args.data.requestId, 'receiveResponse', event); return; } - if (Types.TraceEvents.isTraceEventResourceReceivedData(event)) { + if (Types.Events.isResourceReceivedData(event)) { storeTraceEventWithRequestId(event.args.data.requestId, 'receivedData', [event]); return; } - if (Types.TraceEvents.isTraceEventResourceFinish(event)) { + if (Types.Events.isResourceFinish(event)) { storeTraceEventWithRequestId(event.args.data.requestId, 'resourceFinish', event); return; } - if (Types.TraceEvents.isTraceEventResourceMarkAsCached(event)) { + if (Types.Events.isResourceMarkAsCached(event)) { storeTraceEventWithRequestId(event.args.data.requestId, 'resourceMarkAsCached', event); return; } - if (Types.TraceEvents.isTraceEventWebSocketCreate(event) || Types.TraceEvents.isTraceEventWebSocketInfo(event) || - Types.TraceEvents.isTraceEventWebSocketTransfer(event)) { + if (Types.Events.isWebSocketCreate(event) || Types.Events.isWebSocketInfo(event) || + Types.Events.isWebSocketTransfer(event)) { const identifier = event.args.data.identifier; if (!webSocketData.has(identifier)) { if (event.args.data.frame) { @@ -95,7 +97,7 @@ export function handleEvent(event) { frame: event.args.data.frame, webSocketIdentifier: identifier, events: [], - syntheticConnectionEvent: null, + syntheticConnection: null, }); } else if (event.args.data.workerId) { @@ -103,7 +105,7 @@ export function handleEvent(event) { workerId: event.args.data.workerId, webSocketIdentifier: identifier, events: [], - syntheticConnectionEvent: null, + syntheticConnection: null, }); } } @@ -292,8 +294,7 @@ export async function finalize() { const isHttps = parsedUrl.protocol === 'https:'; const requestingFrameUrl = Helpers.Trace.activeURLForFrameAtTime(frame, finalSendRequest.ts, rendererProcessesByFrame) || ''; // Construct a synthetic trace event for this network request. - const networkEvent = Helpers.SyntheticEvents.SyntheticEventsManager - .registerSyntheticBasedEvent({ + const networkEvent = Helpers.SyntheticEvents.SyntheticEventsManager.registerSyntheticEvent({ rawSourceEvent: finalSendRequest, args: { data: { @@ -352,7 +353,7 @@ export async function finalize() { }, cat: 'loading', name: 'SyntheticNetworkRequest', - ph: "X" /* Types.TraceEvents.Phase.COMPLETE */, + ph: "X" /* Types.Events.Phase.COMPLETE */, dur: Types.Timing.MicroSeconds(endTime - startTime), tdur: Types.Timing.MicroSeconds(endTime - startTime), ts: Types.Timing.MicroSeconds(startTime), @@ -379,6 +380,7 @@ export async function finalize() { // the captured requests, so here we store all of them together. requests.all.push(networkEvent); requestsByTime.push(networkEvent); + requestsById.set(networkEvent.args.data.requestId, networkEvent); const initiatorUrl = networkEvent.args.data.initiator?.url || Helpers.Trace.getZeroIndexedStackTraceForEvent(networkEvent)?.at(0)?.url; if (initiatorUrl) { @@ -403,6 +405,7 @@ export function data() { throw new Error('Network Request handler is not finalized'); } return { + byId: requestsById, byOrigin: requestsByOrigin, byTime: requestsByTime, eventToInitiator: eventToInitiatorMap, @@ -419,32 +422,32 @@ function finalizeWebSocketData() { // for the end. So each WebSocketTraceData will have // { // events: the list of WebSocket events - // syntheticConnectionEvent: the synthetic event representing the entire WebSocket connection + // syntheticConnection: the synthetic event representing the entire WebSocket connection // } webSocketData.forEach(data => { let startEvent = null; let endEvent = null; for (const event of data.events) { - if (Types.TraceEvents.isTraceEventWebSocketCreate(event)) { + if (Types.Events.isWebSocketCreate(event)) { startEvent = event; } - if (Types.TraceEvents.isTraceEventWebSocketDestroy(event)) { + if (Types.Events.isWebSocketDestroy(event)) { endEvent = event; } } - data.syntheticConnectionEvent = createSyntheticWebSocketConnectionEvent(startEvent, endEvent, data.events[0]); + data.syntheticConnection = createSyntheticWebSocketConnection(startEvent, endEvent, data.events[0]); }); } -function createSyntheticWebSocketConnectionEvent(startEvent, endEvent, firstRecordedEvent) { +function createSyntheticWebSocketConnection(startEvent, endEvent, firstRecordedEvent) { const { traceBounds } = metaHandlerData(); const startTs = startEvent ? startEvent.ts : traceBounds.min; const endTs = endEvent ? endEvent.ts : traceBounds.max; const duration = endTs - startTs; const mainEvent = startEvent || endEvent || firstRecordedEvent; return { - name: 'SyntheticWebSocketConnectionEvent', + name: 'SyntheticWebSocketConnection', cat: mainEvent.cat, - ph: "X" /* Types.TraceEvents.Phase.COMPLETE */, + ph: "X" /* Types.Events.Phase.COMPLETE */, ts: startTs, dur: duration, pid: mainEvent.pid, diff --git a/public/models/trace/handlers/NetworkRequestsHandler.js.map b/public/models/trace/handlers/NetworkRequestsHandler.js.map index 6fd848386..7be5b0caa 100644 --- a/public/models/trace/handlers/NetworkRequestsHandler.js.map +++ b/public/models/trace/handlers/NetworkRequestsHandler.js.map @@ -1 +1 @@ -{"version":3,"file":"NetworkRequestsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/NetworkRequestsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport * as Protocol from '../../../generated/protocol.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {data as metaHandlerData} from './MetaHandler.js';\nimport {HandlerState, type TraceEventHandlerName} from './types.js';\n\nconst MILLISECONDS_TO_MICROSECONDS = 1000;\nconst SECONDS_TO_MICROSECONDS = 1000000;\n\n// Network requests from traces are actually formed of 5 trace records.\n// This handler tracks all trace records based on the request ID, and\n// then creates a new synthetic trace event for those network requests.\n//\n// This interface, then, defines the shape of the object we intend to\n// keep for each request in the trace. In the finalize we will convert\n// these 5 types of trace records to a synthetic complete event that\n// represents a composite of these trace records.\ninterface TraceEventsForNetworkRequest {\n changePriority?: Types.TraceEvents.TraceEventResourceChangePriority;\n willSendRequests?: Types.TraceEvents.TraceEventResourceWillSendRequest[];\n sendRequests?: Types.TraceEvents.TraceEventResourceSendRequest[];\n receiveResponse?: Types.TraceEvents.TraceEventResourceReceiveResponse;\n resourceFinish?: Types.TraceEvents.TraceEventResourceFinish;\n receivedData?: Types.TraceEvents.TraceEventResourceReceivedData[];\n resourceMarkAsCached?: Types.TraceEvents.TraceEventResourceMarkAsCached;\n}\n\nexport interface WebSocketTraceDataForFrame {\n frame: string;\n webSocketIdentifier: number;\n events: Types.TraceEvents.WebSocketEvent[];\n syntheticConnectionEvent: Types.TraceEvents.SyntheticWebSocketConnectionEvent|null;\n}\nexport interface WebSocketTraceDataForWorker {\n workerId: string;\n webSocketIdentifier: number;\n events: Types.TraceEvents.WebSocketEvent[];\n syntheticConnectionEvent: Types.TraceEvents.SyntheticWebSocketConnectionEvent|null;\n}\nexport type WebSocketTraceData = WebSocketTraceDataForFrame|WebSocketTraceDataForWorker;\n\nconst webSocketData: Map = new Map();\ninterface NetworkRequestData {\n byOrigin: Map;\n byTime: Types.TraceEvents.SyntheticNetworkRequest[];\n eventToInitiator: Map;\n webSocket: WebSocketTraceData[];\n}\n\nconst requestMap = new Map();\nconst requestsByOrigin = new Map();\nconst requestsByTime: Types.TraceEvents.SyntheticNetworkRequest[] = [];\n\nconst networkRequestEventByInitiatorUrl = new Map();\nconst eventToInitiatorMap =\n new Map();\n\nfunction storeTraceEventWithRequestId(\n requestId: string, key: K, value: TraceEventsForNetworkRequest[K]): void {\n if (!requestMap.has(requestId)) {\n requestMap.set(requestId, {});\n }\n\n const traceEvents = requestMap.get(requestId);\n if (!traceEvents) {\n throw new Error(`Unable to locate trace events for request ID ${requestId}`);\n }\n\n if (Array.isArray(traceEvents[key])) {\n const target = traceEvents[key] as Types.TraceEvents.TraceEventData[];\n const values = value as Types.TraceEvents.TraceEventData[];\n target.push(...values);\n } else {\n traceEvents[key] = value;\n }\n}\n\nfunction firstPositiveValueInList(entries: number[]): number {\n for (const entry of entries) {\n if (entry > 0) {\n return entry;\n }\n }\n\n // In the event we don't find a positive value, we return 0 so as to\n // be a mathematical noop. It's typically not correct to return – say –\n // a -1 here because it would affect the calculation of stats below.\n return 0;\n}\n\nlet handlerState = HandlerState.UNINITIALIZED;\n\nexport function reset(): void {\n requestsByOrigin.clear();\n requestMap.clear();\n requestsByTime.length = 0;\n networkRequestEventByInitiatorUrl.clear();\n eventToInitiatorMap.clear();\n webSocketData.clear();\n\n handlerState = HandlerState.UNINITIALIZED;\n}\n\nexport function initialize(): void {\n handlerState = HandlerState.INITIALIZED;\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Network Request handler is not initialized');\n }\n\n if (Types.TraceEvents.isTraceEventResourceChangePriority(event)) {\n storeTraceEventWithRequestId(event.args.data.requestId, 'changePriority', event);\n return;\n }\n\n if (Types.TraceEvents.isTraceEventResourceWillSendRequest(event)) {\n storeTraceEventWithRequestId(event.args.data.requestId, 'willSendRequests', [event]);\n return;\n }\n\n if (Types.TraceEvents.isTraceEventResourceSendRequest(event)) {\n storeTraceEventWithRequestId(event.args.data.requestId, 'sendRequests', [event]);\n return;\n }\n\n if (Types.TraceEvents.isTraceEventResourceReceiveResponse(event)) {\n storeTraceEventWithRequestId(event.args.data.requestId, 'receiveResponse', event);\n return;\n }\n\n if (Types.TraceEvents.isTraceEventResourceReceivedData(event)) {\n storeTraceEventWithRequestId(event.args.data.requestId, 'receivedData', [event]);\n return;\n }\n\n if (Types.TraceEvents.isTraceEventResourceFinish(event)) {\n storeTraceEventWithRequestId(event.args.data.requestId, 'resourceFinish', event);\n return;\n }\n\n if (Types.TraceEvents.isTraceEventResourceMarkAsCached(event)) {\n storeTraceEventWithRequestId(event.args.data.requestId, 'resourceMarkAsCached', event);\n return;\n }\n\n if (Types.TraceEvents.isTraceEventWebSocketCreate(event) || Types.TraceEvents.isTraceEventWebSocketInfo(event) ||\n Types.TraceEvents.isTraceEventWebSocketTransfer(event)) {\n const identifier = event.args.data.identifier;\n if (!webSocketData.has(identifier)) {\n if (event.args.data.frame) {\n webSocketData.set(identifier, {\n frame: event.args.data.frame,\n webSocketIdentifier: identifier,\n events: [],\n syntheticConnectionEvent: null,\n });\n } else if (event.args.data.workerId) {\n webSocketData.set(identifier, {\n workerId: event.args.data.workerId,\n webSocketIdentifier: identifier,\n events: [],\n syntheticConnectionEvent: null,\n });\n }\n }\n\n webSocketData.get(identifier)?.events.push(event);\n }\n}\n\nexport async function finalize(): Promise {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Network Request handler is not initialized');\n }\n\n const {rendererProcessesByFrame} = metaHandlerData();\n for (const [requestId, request] of requestMap.entries()) {\n // If we have an incomplete set of events here, we choose to drop the network\n // request rather than attempt to synthesize the missing data.\n if (!request.sendRequests || !request.receiveResponse) {\n continue;\n }\n\n // In the data we may get multiple willSendRequests and sendRequests, which\n // will indicate that there are redirects for a given (sub)resource. In the\n // case of a navigation, e.g., example.com/ we will get willSendRequests,\n // and we should use these to calculate time spent in redirects.\n // In the case of sub-resources, however, e.g., example.com/foo.js we will\n // *only* get sendRequests, and we use these instead of willSendRequests\n // to detect the time in redirects. We always use the sendRequest for the\n // url, priority etc since it contains those values, but we use the\n // willSendRequest (if it exists) to calculate the timestamp and durations\n // of redirects.\n const redirects: Types.TraceEvents.SyntheticNetworkRedirect[] = [];\n for (let i = 0; i < request.sendRequests.length - 1; i++) {\n const sendRequest = request.sendRequests[i];\n const nextSendRequest = request.sendRequests[i + 1];\n\n // Use the willSendRequests as the source for redirects if possible.\n // We default to those of the sendRequests, however, since willSendRequest\n // is not guaranteed to be present in the data for every request.\n let ts = sendRequest.ts;\n let dur = Types.Timing.MicroSeconds(nextSendRequest.ts - sendRequest.ts);\n if (request.willSendRequests && request.willSendRequests[i] && request.willSendRequests[i + 1]) {\n const willSendRequest = request.willSendRequests[i];\n const nextWillSendRequest = request.willSendRequests[i + 1];\n ts = willSendRequest.ts;\n dur = Types.Timing.MicroSeconds(nextWillSendRequest.ts - willSendRequest.ts);\n }\n\n redirects.push({\n url: sendRequest.args.data.url,\n priority: sendRequest.args.data.priority,\n requestMethod: sendRequest.args.data.requestMethod,\n ts,\n dur,\n });\n }\n\n // If a ResourceFinish event with an encoded data length is received,\n // then the resource was not cached; it was fetched before it was\n // requested, e.g. because it was pushed in this navigation.\n const isPushedResource = request.resourceFinish?.args.data.encodedDataLength !== 0;\n // This works around crbug.com/998397, which reports pushed resources, and resources served by a service worker as disk cached.\n const isDiskCached = request.receiveResponse.args.data.fromCache &&\n !request.receiveResponse.args.data.fromServiceWorker && !isPushedResource;\n // If the request contains a resourceMarkAsCached event, it was served from memory cache.\n // The timing data returned is from the original (uncached) request, which\n // means that if we leave the above network record data as-is when the\n // request came from either the disk cache or memory cache, our calculations\n // will be incorrect.\n //\n // So we use this flag so when we calculate the timestamps of the various\n // events, we can overwrite them.\n // These timestamps may not be perfect (indeed they don't always match\n // the Network CDP domain exactly, which is likely an artifact of the way\n // the data is routed on the backend), but they're the closest we have.\n const isMemoryCached = request.resourceMarkAsCached !== undefined;\n // If a request has `resourceMarkAsCached` field, the `timing` field is not correct.\n // So let's discard it and override to 0 (which will be handled in later logic if timing field is undefined).\n const timing = isMemoryCached ? undefined : request.receiveResponse.args.data.timing;\n // If a non-cached request has no |timing| indicates data URLs, we ignore it.\n if (!timing && !isMemoryCached) {\n continue;\n }\n\n const firstSendRequest = request.sendRequests[0];\n const finalSendRequest = request.sendRequests[request.sendRequests.length - 1];\n\n const initialPriority = finalSendRequest.args.data.priority;\n let finalPriority = initialPriority;\n if (request.changePriority) {\n finalPriority = request.changePriority.args.data.priority;\n }\n\n // Start time\n // =======================\n // The time where the request started, which is either the first willSendRequest\n // event if there is one, or, if there is not, the sendRequest.\n const startTime = (request.willSendRequests && request.willSendRequests.length) ?\n Types.Timing.MicroSeconds(request.willSendRequests[0].ts) :\n Types.Timing.MicroSeconds(firstSendRequest.ts);\n\n // End redirect time\n // =======================\n // It's possible that when we start requesting data we will receive redirections.\n // Here we note the time of the *last* willSendRequest / sendRequest event,\n // which is used later on in the calculations for time queueing etc.\n const endRedirectTime = (request.willSendRequests && request.willSendRequests.length) ?\n Types.Timing.MicroSeconds(request.willSendRequests[request.willSendRequests.length - 1].ts) :\n Types.Timing.MicroSeconds(finalSendRequest.ts);\n\n // Finish time and end time\n // =======================\n // The finish time and the end time are subtly different.\n // - Finish time: records the point at which the network stack stopped receiving the data\n // - End time: the timestamp of the finish event itself (if one exists)\n //\n // The end time, then, will be slightly after the finish time.\n const endTime = request.resourceFinish ? request.resourceFinish.ts : endRedirectTime;\n const finishTime = request.resourceFinish?.args.data.finishTime ?\n Types.Timing.MicroSeconds(request.resourceFinish.args.data.finishTime * SECONDS_TO_MICROSECONDS) :\n Types.Timing.MicroSeconds(endTime);\n\n // Network duration\n // =======================\n // Time spent on the network.\n const networkDuration = Types.Timing.MicroSeconds(timing ? (finishTime || endRedirectTime) - endRedirectTime : 0);\n\n // Processing duration\n // =======================\n // Time spent from start to end.\n const processingDuration = Types.Timing.MicroSeconds(endTime - (finishTime || endTime));\n\n // Redirection duration\n // =======================\n // Time between the first willSendRequest / sendRequest and last. This we place in *front* of the\n // queueing, since the queueing time that we know about from the trace data is only the last request,\n // i.e., the one that occurs after all the redirects.\n const redirectionDuration = Types.Timing.MicroSeconds(endRedirectTime - startTime);\n\n // Queueing\n // =======================\n // The amount of time queueing is the time between the request's start time to the requestTime\n // arg recorded in the receiveResponse event. In the cases where the recorded start time is larger\n // that the requestTime we set queueing time to zero.\n const queueingFromTraceData = timing ? timing.requestTime * SECONDS_TO_MICROSECONDS - endRedirectTime : 0;\n const queueing =\n Types.Timing.MicroSeconds(Platform.NumberUtilities.clamp(queueingFromTraceData, 0, Number.MAX_VALUE));\n\n // Stalled\n // =======================\n // If the request is cached, the amount of time stalled is the time between the start time and\n // receiving a response.\n // Otherwise it is whichever positive number comes first from the following timing info:\n // DNS start, Connection start, Send Start, or the time duration between our start time and\n // receiving a response.\n const stalled = timing ? Types.Timing.MicroSeconds(firstPositiveValueInList([\n timing.dnsStart * MILLISECONDS_TO_MICROSECONDS,\n timing.connectStart * MILLISECONDS_TO_MICROSECONDS,\n timing.sendStart * MILLISECONDS_TO_MICROSECONDS,\n (request.receiveResponse.ts - endRedirectTime),\n ])) :\n Types.Timing.MicroSeconds(request.receiveResponse.ts - startTime);\n\n // Sending HTTP request\n // =======================\n // Time when the HTTP request is sent.\n const sendStartTime = timing ?\n Types.Timing.MicroSeconds(\n timing.requestTime * SECONDS_TO_MICROSECONDS + timing.sendStart * MILLISECONDS_TO_MICROSECONDS) :\n startTime;\n\n // Waiting\n // =======================\n // Time from when the send finished going to when the headers were received.\n const waiting = timing ?\n Types.Timing.MicroSeconds((timing.receiveHeadersEnd - timing.sendEnd) * MILLISECONDS_TO_MICROSECONDS) :\n Types.Timing.MicroSeconds(0);\n\n // Download\n // =======================\n // Time from receipt of headers to the finish time.\n const downloadStart = timing ?\n Types.Timing.MicroSeconds(\n timing.requestTime * SECONDS_TO_MICROSECONDS + timing.receiveHeadersEnd * MILLISECONDS_TO_MICROSECONDS) :\n startTime;\n const download = timing ? Types.Timing.MicroSeconds(((finishTime || downloadStart) - downloadStart)) :\n Types.Timing.MicroSeconds(endTime - request.receiveResponse.ts);\n\n const totalTime = Types.Timing.MicroSeconds(networkDuration + processingDuration);\n\n // Collect a few values from the timing info.\n // If the Network request is cached, these fields will be zero, so the minus will zero out them.\n const dnsLookup = timing ?\n Types.Timing.MicroSeconds((timing.dnsEnd - timing.dnsStart) * MILLISECONDS_TO_MICROSECONDS) :\n Types.Timing.MicroSeconds(0);\n const ssl = timing ? Types.Timing.MicroSeconds((timing.sslEnd - timing.sslStart) * MILLISECONDS_TO_MICROSECONDS) :\n Types.Timing.MicroSeconds(0);\n const proxyNegotiation = timing ?\n Types.Timing.MicroSeconds((timing.proxyEnd - timing.proxyStart) * MILLISECONDS_TO_MICROSECONDS) :\n Types.Timing.MicroSeconds(0);\n const requestSent = timing ?\n Types.Timing.MicroSeconds((timing.sendEnd - timing.sendStart) * MILLISECONDS_TO_MICROSECONDS) :\n Types.Timing.MicroSeconds(0);\n const initialConnection = timing ?\n Types.Timing.MicroSeconds((timing.connectEnd - timing.connectStart) * MILLISECONDS_TO_MICROSECONDS) :\n Types.Timing.MicroSeconds(0);\n\n // Finally get some of the general data from the trace events.\n const {frame, url, renderBlocking} = finalSendRequest.args.data;\n const {encodedDataLength, decodedBodyLength} =\n request.resourceFinish ? request.resourceFinish.args.data : {encodedDataLength: 0, decodedBodyLength: 0};\n const parsedUrl = new URL(url);\n const isHttps = parsedUrl.protocol === 'https:';\n const requestingFrameUrl =\n Helpers.Trace.activeURLForFrameAtTime(frame, finalSendRequest.ts, rendererProcessesByFrame) || '';\n // Construct a synthetic trace event for this network request.\n const networkEvent = Helpers.SyntheticEvents.SyntheticEventsManager\n .registerSyntheticBasedEvent({\n rawSourceEvent: finalSendRequest,\n args: {\n data: {\n // All data we create from trace events should be added to |syntheticData|.\n syntheticData: {\n dnsLookup,\n download,\n downloadStart,\n finishTime,\n initialConnection,\n isDiskCached,\n isHttps,\n isMemoryCached,\n isPushedResource,\n networkDuration,\n processingDuration,\n proxyNegotiation,\n queueing,\n redirectionDuration,\n requestSent,\n sendStartTime,\n ssl,\n stalled,\n totalTime,\n waiting,\n },\n // All fields below are from TraceEventsForNetworkRequest.\n decodedBodyLength,\n encodedDataLength,\n frame,\n fromServiceWorker: request.receiveResponse.args.data.fromServiceWorker,\n isLinkPreload: finalSendRequest.args.data.isLinkPreload || false,\n mimeType: request.receiveResponse.args.data.mimeType,\n priority: finalPriority,\n initialPriority,\n protocol: request.receiveResponse.args.data.protocol ?? 'unknown',\n redirects,\n // In the event the property isn't set, assume non-blocking.\n renderBlocking: renderBlocking ?? 'non_blocking',\n requestId,\n requestingFrameUrl,\n requestMethod: finalSendRequest.args.data.requestMethod,\n resourceType: finalSendRequest.args.data.resourceType,\n statusCode: request.receiveResponse.args.data.statusCode,\n responseHeaders: request.receiveResponse.args.data.headers || [],\n fetchPriorityHint: finalSendRequest.args.data.fetchPriorityHint,\n initiator: finalSendRequest.args.data.initiator,\n stackTrace: finalSendRequest.args.data.stackTrace,\n timing,\n url,\n failed: request.resourceFinish?.args.data.didFail ?? false,\n finished: Boolean(request.resourceFinish),\n connectionId: request.receiveResponse.args.data.connectionId,\n connectionReused: request.receiveResponse.args.data.connectionReused,\n },\n },\n cat: 'loading',\n name: 'SyntheticNetworkRequest',\n ph: Types.TraceEvents.Phase.COMPLETE,\n dur: Types.Timing.MicroSeconds(endTime - startTime),\n tdur: Types.Timing.MicroSeconds(endTime - startTime),\n ts: Types.Timing.MicroSeconds(startTime),\n tts: Types.Timing.MicroSeconds(startTime),\n pid: finalSendRequest.pid,\n tid: finalSendRequest.tid,\n });\n\n const requests = Platform.MapUtilities.getWithDefault(requestsByOrigin, parsedUrl.host, () => {\n return {\n renderBlocking: [],\n nonRenderBlocking: [],\n all: [],\n };\n });\n\n // For ease of rendering we sometimes want to differentiate between\n // render-blocking and non-render-blocking, so we divide the data here.\n if (!Helpers.Network.isSyntheticNetworkRequestEventRenderBlocking(networkEvent)) {\n requests.nonRenderBlocking.push(networkEvent);\n } else {\n requests.renderBlocking.push(networkEvent);\n }\n\n // However, there are also times where we just want to loop through all\n // the captured requests, so here we store all of them together.\n requests.all.push(networkEvent);\n requestsByTime.push(networkEvent);\n\n const initiatorUrl = networkEvent.args.data.initiator?.url ||\n Helpers.Trace.getZeroIndexedStackTraceForEvent(networkEvent)?.at(0)?.url;\n if (initiatorUrl) {\n const events = networkRequestEventByInitiatorUrl.get(initiatorUrl) ?? [];\n events.push(networkEvent);\n networkRequestEventByInitiatorUrl.set(initiatorUrl, events);\n }\n }\n\n for (const request of requestsByTime) {\n const initiatedEvents = networkRequestEventByInitiatorUrl.get(request.args.data.url);\n\n if (initiatedEvents) {\n for (const initiatedEvent of initiatedEvents) {\n eventToInitiatorMap.set(initiatedEvent, request);\n }\n }\n }\n finalizeWebSocketData();\n\n handlerState = HandlerState.FINALIZED;\n}\n\nexport function data(): NetworkRequestData {\n if (handlerState !== HandlerState.FINALIZED) {\n throw new Error('Network Request handler is not finalized');\n }\n\n return {\n byOrigin: requestsByOrigin,\n byTime: requestsByTime,\n eventToInitiator: eventToInitiatorMap,\n webSocket: [...webSocketData.values()],\n };\n}\n\nexport function deps(): TraceEventHandlerName[] {\n return ['Meta'];\n}\n\nfunction finalizeWebSocketData(): void {\n // for each WebSocketTraceData in webSocketData map, we create a synthetic event\n // to represent the entire WebSocket connection. This is done by finding the start and end event\n // if they exist, and if they don't, we use the first event in the list for start, and the traceBounds.max\n // for the end. So each WebSocketTraceData will have\n // {\n // events: the list of WebSocket events\n // syntheticConnectionEvent: the synthetic event representing the entire WebSocket connection\n // }\n webSocketData.forEach(data => {\n let startEvent: Types.TraceEvents.WebSocketEvent|null = null;\n let endEvent: Types.TraceEvents.TraceEventWebSocketDestroy|null = null;\n for (const event of data.events) {\n if (Types.TraceEvents.isTraceEventWebSocketCreate(event)) {\n startEvent = event;\n }\n if (Types.TraceEvents.isTraceEventWebSocketDestroy(event)) {\n endEvent = event;\n }\n }\n data.syntheticConnectionEvent = createSyntheticWebSocketConnectionEvent(startEvent, endEvent, data.events[0]);\n });\n}\n\nfunction createSyntheticWebSocketConnectionEvent(\n startEvent: Types.TraceEvents.TraceEventWebSocketCreate|null,\n endEvent: Types.TraceEvents.TraceEventWebSocketDestroy|null,\n firstRecordedEvent: Types.TraceEvents.WebSocketEvent): Types.TraceEvents.SyntheticWebSocketConnectionEvent {\n const {traceBounds} = metaHandlerData();\n const startTs = startEvent ? startEvent.ts : traceBounds.min;\n const endTs = endEvent ? endEvent.ts : traceBounds.max;\n const duration = endTs - startTs;\n const mainEvent = startEvent || endEvent || firstRecordedEvent;\n return {\n name: 'SyntheticWebSocketConnectionEvent',\n cat: mainEvent.cat,\n ph: Types.TraceEvents.Phase.COMPLETE,\n ts: startTs,\n dur: duration as Types.Timing.MicroSeconds,\n pid: mainEvent.pid,\n tid: mainEvent.tid,\n s: mainEvent.s,\n rawSourceEvent: mainEvent,\n _tag: 'SyntheticEntryTag',\n args: {\n data: {\n identifier: mainEvent.args.data.identifier,\n priority: Protocol.Network.ResourcePriority.Low,\n url: mainEvent.args.data.url || '',\n },\n },\n };\n}\n"]} \ No newline at end of file +{"version":3,"file":"NetworkRequestsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/NetworkRequestsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport * as Protocol from '../../../generated/protocol.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {data as metaHandlerData} from './MetaHandler.js';\nimport {type HandlerName, HandlerState} from './types.js';\n\nconst MILLISECONDS_TO_MICROSECONDS = 1000;\nconst SECONDS_TO_MICROSECONDS = 1000000;\n\n// Network requests from traces are actually formed of 5 trace records.\n// This handler tracks all trace records based on the request ID, and\n// then creates a new synthetic trace event for those network requests.\n//\n// This interface, then, defines the shape of the object we intend to\n// keep for each request in the trace. In the finalize we will convert\n// these 5 types of trace records to a synthetic complete event that\n// represents a composite of these trace records.\ninterface TraceEventsForNetworkRequest {\n changePriority?: Types.Events.ResourceChangePriority;\n willSendRequests?: Types.Events.ResourceWillSendRequest[];\n sendRequests?: Types.Events.ResourceSendRequest[];\n receiveResponse?: Types.Events.ResourceReceiveResponse;\n resourceFinish?: Types.Events.ResourceFinish;\n receivedData?: Types.Events.ResourceReceivedData[];\n resourceMarkAsCached?: Types.Events.ResourceMarkAsCached;\n}\n\nexport interface WebSocketTraceDataForFrame {\n frame: string;\n webSocketIdentifier: number;\n events: Types.Events.WebSocketEvent[];\n syntheticConnection: Types.Events.SyntheticWebSocketConnection|null;\n}\nexport interface WebSocketTraceDataForWorker {\n workerId: string;\n webSocketIdentifier: number;\n events: Types.Events.WebSocketEvent[];\n syntheticConnection: Types.Events.SyntheticWebSocketConnection|null;\n}\nexport type WebSocketTraceData = WebSocketTraceDataForFrame|WebSocketTraceDataForWorker;\n\nconst webSocketData: Map = new Map();\ninterface NetworkRequestData {\n byId: Map;\n byOrigin: Map;\n byTime: Types.Events.SyntheticNetworkRequest[];\n eventToInitiator: Map;\n webSocket: WebSocketTraceData[];\n}\n\nconst requestMap = new Map();\nconst requestsById = new Map();\nconst requestsByOrigin = new Map();\nconst requestsByTime: Types.Events.SyntheticNetworkRequest[] = [];\n\nconst networkRequestEventByInitiatorUrl = new Map();\nconst eventToInitiatorMap = new Map();\n\nfunction storeTraceEventWithRequestId(\n requestId: string, key: K, value: TraceEventsForNetworkRequest[K]): void {\n if (!requestMap.has(requestId)) {\n requestMap.set(requestId, {});\n }\n\n const traceEvents = requestMap.get(requestId);\n if (!traceEvents) {\n throw new Error(`Unable to locate trace events for request ID ${requestId}`);\n }\n\n if (Array.isArray(traceEvents[key])) {\n const target = traceEvents[key] as Types.Events.Event[];\n const values = value as Types.Events.Event[];\n target.push(...values);\n } else {\n traceEvents[key] = value;\n }\n}\n\nfunction firstPositiveValueInList(entries: number[]): number {\n for (const entry of entries) {\n if (entry > 0) {\n return entry;\n }\n }\n\n // In the event we don't find a positive value, we return 0 so as to\n // be a mathematical noop. It's typically not correct to return – say –\n // a -1 here because it would affect the calculation of stats below.\n return 0;\n}\n\nlet handlerState = HandlerState.UNINITIALIZED;\n\nexport function reset(): void {\n requestsById.clear();\n requestsByOrigin.clear();\n requestMap.clear();\n requestsByTime.length = 0;\n networkRequestEventByInitiatorUrl.clear();\n eventToInitiatorMap.clear();\n webSocketData.clear();\n\n handlerState = HandlerState.UNINITIALIZED;\n}\n\nexport function initialize(): void {\n handlerState = HandlerState.INITIALIZED;\n}\n\nexport function handleEvent(event: Types.Events.Event): void {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Network Request handler is not initialized');\n }\n\n if (Types.Events.isResourceChangePriority(event)) {\n storeTraceEventWithRequestId(event.args.data.requestId, 'changePriority', event);\n return;\n }\n\n if (Types.Events.isResourceWillSendRequest(event)) {\n storeTraceEventWithRequestId(event.args.data.requestId, 'willSendRequests', [event]);\n return;\n }\n\n if (Types.Events.isResourceSendRequest(event)) {\n storeTraceEventWithRequestId(event.args.data.requestId, 'sendRequests', [event]);\n return;\n }\n\n if (Types.Events.isResourceReceiveResponse(event)) {\n storeTraceEventWithRequestId(event.args.data.requestId, 'receiveResponse', event);\n return;\n }\n\n if (Types.Events.isResourceReceivedData(event)) {\n storeTraceEventWithRequestId(event.args.data.requestId, 'receivedData', [event]);\n return;\n }\n\n if (Types.Events.isResourceFinish(event)) {\n storeTraceEventWithRequestId(event.args.data.requestId, 'resourceFinish', event);\n return;\n }\n\n if (Types.Events.isResourceMarkAsCached(event)) {\n storeTraceEventWithRequestId(event.args.data.requestId, 'resourceMarkAsCached', event);\n return;\n }\n\n if (Types.Events.isWebSocketCreate(event) || Types.Events.isWebSocketInfo(event) ||\n Types.Events.isWebSocketTransfer(event)) {\n const identifier = event.args.data.identifier;\n if (!webSocketData.has(identifier)) {\n if (event.args.data.frame) {\n webSocketData.set(identifier, {\n frame: event.args.data.frame,\n webSocketIdentifier: identifier,\n events: [],\n syntheticConnection: null,\n });\n } else if (event.args.data.workerId) {\n webSocketData.set(identifier, {\n workerId: event.args.data.workerId,\n webSocketIdentifier: identifier,\n events: [],\n syntheticConnection: null,\n });\n }\n }\n\n webSocketData.get(identifier)?.events.push(event);\n }\n}\n\nexport async function finalize(): Promise {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Network Request handler is not initialized');\n }\n\n const {rendererProcessesByFrame} = metaHandlerData();\n for (const [requestId, request] of requestMap.entries()) {\n // If we have an incomplete set of events here, we choose to drop the network\n // request rather than attempt to synthesize the missing data.\n if (!request.sendRequests || !request.receiveResponse) {\n continue;\n }\n\n // In the data we may get multiple willSendRequests and sendRequests, which\n // will indicate that there are redirects for a given (sub)resource. In the\n // case of a navigation, e.g., example.com/ we will get willSendRequests,\n // and we should use these to calculate time spent in redirects.\n // In the case of sub-resources, however, e.g., example.com/foo.js we will\n // *only* get sendRequests, and we use these instead of willSendRequests\n // to detect the time in redirects. We always use the sendRequest for the\n // url, priority etc since it contains those values, but we use the\n // willSendRequest (if it exists) to calculate the timestamp and durations\n // of redirects.\n const redirects: Types.Events.SyntheticNetworkRedirect[] = [];\n for (let i = 0; i < request.sendRequests.length - 1; i++) {\n const sendRequest = request.sendRequests[i];\n const nextSendRequest = request.sendRequests[i + 1];\n\n // Use the willSendRequests as the source for redirects if possible.\n // We default to those of the sendRequests, however, since willSendRequest\n // is not guaranteed to be present in the data for every request.\n let ts = sendRequest.ts;\n let dur = Types.Timing.MicroSeconds(nextSendRequest.ts - sendRequest.ts);\n if (request.willSendRequests && request.willSendRequests[i] && request.willSendRequests[i + 1]) {\n const willSendRequest = request.willSendRequests[i];\n const nextWillSendRequest = request.willSendRequests[i + 1];\n ts = willSendRequest.ts;\n dur = Types.Timing.MicroSeconds(nextWillSendRequest.ts - willSendRequest.ts);\n }\n\n redirects.push({\n url: sendRequest.args.data.url,\n priority: sendRequest.args.data.priority,\n requestMethod: sendRequest.args.data.requestMethod,\n ts,\n dur,\n });\n }\n\n // If a ResourceFinish event with an encoded data length is received,\n // then the resource was not cached; it was fetched before it was\n // requested, e.g. because it was pushed in this navigation.\n const isPushedResource = request.resourceFinish?.args.data.encodedDataLength !== 0;\n // This works around crbug.com/998397, which reports pushed resources, and resources served by a service worker as disk cached.\n const isDiskCached = request.receiveResponse.args.data.fromCache &&\n !request.receiveResponse.args.data.fromServiceWorker && !isPushedResource;\n // If the request contains a resourceMarkAsCached event, it was served from memory cache.\n // The timing data returned is from the original (uncached) request, which\n // means that if we leave the above network record data as-is when the\n // request came from either the disk cache or memory cache, our calculations\n // will be incorrect.\n //\n // So we use this flag so when we calculate the timestamps of the various\n // events, we can overwrite them.\n // These timestamps may not be perfect (indeed they don't always match\n // the Network CDP domain exactly, which is likely an artifact of the way\n // the data is routed on the backend), but they're the closest we have.\n const isMemoryCached = request.resourceMarkAsCached !== undefined;\n // If a request has `resourceMarkAsCached` field, the `timing` field is not correct.\n // So let's discard it and override to 0 (which will be handled in later logic if timing field is undefined).\n const timing = isMemoryCached ? undefined : request.receiveResponse.args.data.timing;\n // If a non-cached request has no |timing| indicates data URLs, we ignore it.\n if (!timing && !isMemoryCached) {\n continue;\n }\n\n const firstSendRequest = request.sendRequests[0];\n const finalSendRequest = request.sendRequests[request.sendRequests.length - 1];\n\n const initialPriority = finalSendRequest.args.data.priority;\n let finalPriority = initialPriority;\n if (request.changePriority) {\n finalPriority = request.changePriority.args.data.priority;\n }\n\n // Start time\n // =======================\n // The time where the request started, which is either the first willSendRequest\n // event if there is one, or, if there is not, the sendRequest.\n const startTime = (request.willSendRequests && request.willSendRequests.length) ?\n Types.Timing.MicroSeconds(request.willSendRequests[0].ts) :\n Types.Timing.MicroSeconds(firstSendRequest.ts);\n\n // End redirect time\n // =======================\n // It's possible that when we start requesting data we will receive redirections.\n // Here we note the time of the *last* willSendRequest / sendRequest event,\n // which is used later on in the calculations for time queueing etc.\n const endRedirectTime = (request.willSendRequests && request.willSendRequests.length) ?\n Types.Timing.MicroSeconds(request.willSendRequests[request.willSendRequests.length - 1].ts) :\n Types.Timing.MicroSeconds(finalSendRequest.ts);\n\n // Finish time and end time\n // =======================\n // The finish time and the end time are subtly different.\n // - Finish time: records the point at which the network stack stopped receiving the data\n // - End time: the timestamp of the finish event itself (if one exists)\n //\n // The end time, then, will be slightly after the finish time.\n const endTime = request.resourceFinish ? request.resourceFinish.ts : endRedirectTime;\n const finishTime = request.resourceFinish?.args.data.finishTime ?\n Types.Timing.MicroSeconds(request.resourceFinish.args.data.finishTime * SECONDS_TO_MICROSECONDS) :\n Types.Timing.MicroSeconds(endTime);\n\n // Network duration\n // =======================\n // Time spent on the network.\n const networkDuration = Types.Timing.MicroSeconds(timing ? (finishTime || endRedirectTime) - endRedirectTime : 0);\n\n // Processing duration\n // =======================\n // Time spent from start to end.\n const processingDuration = Types.Timing.MicroSeconds(endTime - (finishTime || endTime));\n\n // Redirection duration\n // =======================\n // Time between the first willSendRequest / sendRequest and last. This we place in *front* of the\n // queueing, since the queueing time that we know about from the trace data is only the last request,\n // i.e., the one that occurs after all the redirects.\n const redirectionDuration = Types.Timing.MicroSeconds(endRedirectTime - startTime);\n\n // Queueing\n // =======================\n // The amount of time queueing is the time between the request's start time to the requestTime\n // arg recorded in the receiveResponse event. In the cases where the recorded start time is larger\n // that the requestTime we set queueing time to zero.\n const queueingFromTraceData = timing ? timing.requestTime * SECONDS_TO_MICROSECONDS - endRedirectTime : 0;\n const queueing =\n Types.Timing.MicroSeconds(Platform.NumberUtilities.clamp(queueingFromTraceData, 0, Number.MAX_VALUE));\n\n // Stalled\n // =======================\n // If the request is cached, the amount of time stalled is the time between the start time and\n // receiving a response.\n // Otherwise it is whichever positive number comes first from the following timing info:\n // DNS start, Connection start, Send Start, or the time duration between our start time and\n // receiving a response.\n const stalled = timing ? Types.Timing.MicroSeconds(firstPositiveValueInList([\n timing.dnsStart * MILLISECONDS_TO_MICROSECONDS,\n timing.connectStart * MILLISECONDS_TO_MICROSECONDS,\n timing.sendStart * MILLISECONDS_TO_MICROSECONDS,\n (request.receiveResponse.ts - endRedirectTime),\n ])) :\n Types.Timing.MicroSeconds(request.receiveResponse.ts - startTime);\n\n // Sending HTTP request\n // =======================\n // Time when the HTTP request is sent.\n const sendStartTime = timing ?\n Types.Timing.MicroSeconds(\n timing.requestTime * SECONDS_TO_MICROSECONDS + timing.sendStart * MILLISECONDS_TO_MICROSECONDS) :\n startTime;\n\n // Waiting\n // =======================\n // Time from when the send finished going to when the headers were received.\n const waiting = timing ?\n Types.Timing.MicroSeconds((timing.receiveHeadersEnd - timing.sendEnd) * MILLISECONDS_TO_MICROSECONDS) :\n Types.Timing.MicroSeconds(0);\n\n // Download\n // =======================\n // Time from receipt of headers to the finish time.\n const downloadStart = timing ?\n Types.Timing.MicroSeconds(\n timing.requestTime * SECONDS_TO_MICROSECONDS + timing.receiveHeadersEnd * MILLISECONDS_TO_MICROSECONDS) :\n startTime;\n const download = timing ? Types.Timing.MicroSeconds(((finishTime || downloadStart) - downloadStart)) :\n Types.Timing.MicroSeconds(endTime - request.receiveResponse.ts);\n\n const totalTime = Types.Timing.MicroSeconds(networkDuration + processingDuration);\n\n // Collect a few values from the timing info.\n // If the Network request is cached, these fields will be zero, so the minus will zero out them.\n const dnsLookup = timing ?\n Types.Timing.MicroSeconds((timing.dnsEnd - timing.dnsStart) * MILLISECONDS_TO_MICROSECONDS) :\n Types.Timing.MicroSeconds(0);\n const ssl = timing ? Types.Timing.MicroSeconds((timing.sslEnd - timing.sslStart) * MILLISECONDS_TO_MICROSECONDS) :\n Types.Timing.MicroSeconds(0);\n const proxyNegotiation = timing ?\n Types.Timing.MicroSeconds((timing.proxyEnd - timing.proxyStart) * MILLISECONDS_TO_MICROSECONDS) :\n Types.Timing.MicroSeconds(0);\n const requestSent = timing ?\n Types.Timing.MicroSeconds((timing.sendEnd - timing.sendStart) * MILLISECONDS_TO_MICROSECONDS) :\n Types.Timing.MicroSeconds(0);\n const initialConnection = timing ?\n Types.Timing.MicroSeconds((timing.connectEnd - timing.connectStart) * MILLISECONDS_TO_MICROSECONDS) :\n Types.Timing.MicroSeconds(0);\n\n // Finally get some of the general data from the trace events.\n const {frame, url, renderBlocking} = finalSendRequest.args.data;\n const {encodedDataLength, decodedBodyLength} =\n request.resourceFinish ? request.resourceFinish.args.data : {encodedDataLength: 0, decodedBodyLength: 0};\n const parsedUrl = new URL(url);\n const isHttps = parsedUrl.protocol === 'https:';\n const requestingFrameUrl =\n Helpers.Trace.activeURLForFrameAtTime(frame, finalSendRequest.ts, rendererProcessesByFrame) || '';\n // Construct a synthetic trace event for this network request.\n const networkEvent =\n Helpers.SyntheticEvents.SyntheticEventsManager.registerSyntheticEvent({\n rawSourceEvent: finalSendRequest,\n args: {\n data: {\n // All data we create from trace events should be added to |syntheticData|.\n syntheticData: {\n dnsLookup,\n download,\n downloadStart,\n finishTime,\n initialConnection,\n isDiskCached,\n isHttps,\n isMemoryCached,\n isPushedResource,\n networkDuration,\n processingDuration,\n proxyNegotiation,\n queueing,\n redirectionDuration,\n requestSent,\n sendStartTime,\n ssl,\n stalled,\n totalTime,\n waiting,\n },\n // All fields below are from TraceEventsForNetworkRequest.\n decodedBodyLength,\n encodedDataLength,\n frame,\n fromServiceWorker: request.receiveResponse.args.data.fromServiceWorker,\n isLinkPreload: finalSendRequest.args.data.isLinkPreload || false,\n mimeType: request.receiveResponse.args.data.mimeType,\n priority: finalPriority,\n initialPriority,\n protocol: request.receiveResponse.args.data.protocol ?? 'unknown',\n redirects,\n // In the event the property isn't set, assume non-blocking.\n renderBlocking: renderBlocking ?? 'non_blocking',\n requestId,\n requestingFrameUrl,\n requestMethod: finalSendRequest.args.data.requestMethod,\n resourceType: finalSendRequest.args.data.resourceType,\n statusCode: request.receiveResponse.args.data.statusCode,\n responseHeaders: request.receiveResponse.args.data.headers || [],\n fetchPriorityHint: finalSendRequest.args.data.fetchPriorityHint,\n initiator: finalSendRequest.args.data.initiator,\n stackTrace: finalSendRequest.args.data.stackTrace,\n timing,\n url,\n failed: request.resourceFinish?.args.data.didFail ?? false,\n finished: Boolean(request.resourceFinish),\n connectionId: request.receiveResponse.args.data.connectionId,\n connectionReused: request.receiveResponse.args.data.connectionReused,\n },\n },\n cat: 'loading',\n name: 'SyntheticNetworkRequest',\n ph: Types.Events.Phase.COMPLETE,\n dur: Types.Timing.MicroSeconds(endTime - startTime),\n tdur: Types.Timing.MicroSeconds(endTime - startTime),\n ts: Types.Timing.MicroSeconds(startTime),\n tts: Types.Timing.MicroSeconds(startTime),\n pid: finalSendRequest.pid,\n tid: finalSendRequest.tid,\n });\n\n const requests = Platform.MapUtilities.getWithDefault(requestsByOrigin, parsedUrl.host, () => {\n return {\n renderBlocking: [],\n nonRenderBlocking: [],\n all: [],\n };\n });\n\n // For ease of rendering we sometimes want to differentiate between\n // render-blocking and non-render-blocking, so we divide the data here.\n if (!Helpers.Network.isSyntheticNetworkRequestEventRenderBlocking(networkEvent)) {\n requests.nonRenderBlocking.push(networkEvent);\n } else {\n requests.renderBlocking.push(networkEvent);\n }\n\n // However, there are also times where we just want to loop through all\n // the captured requests, so here we store all of them together.\n requests.all.push(networkEvent);\n requestsByTime.push(networkEvent);\n requestsById.set(networkEvent.args.data.requestId, networkEvent);\n\n const initiatorUrl = networkEvent.args.data.initiator?.url ||\n Helpers.Trace.getZeroIndexedStackTraceForEvent(networkEvent)?.at(0)?.url;\n if (initiatorUrl) {\n const events = networkRequestEventByInitiatorUrl.get(initiatorUrl) ?? [];\n events.push(networkEvent);\n networkRequestEventByInitiatorUrl.set(initiatorUrl, events);\n }\n }\n\n for (const request of requestsByTime) {\n const initiatedEvents = networkRequestEventByInitiatorUrl.get(request.args.data.url);\n\n if (initiatedEvents) {\n for (const initiatedEvent of initiatedEvents) {\n eventToInitiatorMap.set(initiatedEvent, request);\n }\n }\n }\n finalizeWebSocketData();\n\n handlerState = HandlerState.FINALIZED;\n}\n\nexport function data(): NetworkRequestData {\n if (handlerState !== HandlerState.FINALIZED) {\n throw new Error('Network Request handler is not finalized');\n }\n\n return {\n byId: requestsById,\n byOrigin: requestsByOrigin,\n byTime: requestsByTime,\n eventToInitiator: eventToInitiatorMap,\n webSocket: [...webSocketData.values()],\n };\n}\n\nexport function deps(): HandlerName[] {\n return ['Meta'];\n}\n\nfunction finalizeWebSocketData(): void {\n // for each WebSocketTraceData in webSocketData map, we create a synthetic event\n // to represent the entire WebSocket connection. This is done by finding the start and end event\n // if they exist, and if they don't, we use the first event in the list for start, and the traceBounds.max\n // for the end. So each WebSocketTraceData will have\n // {\n // events: the list of WebSocket events\n // syntheticConnection: the synthetic event representing the entire WebSocket connection\n // }\n webSocketData.forEach(data => {\n let startEvent: Types.Events.WebSocketEvent|null = null;\n let endEvent: Types.Events.WebSocketDestroy|null = null;\n for (const event of data.events) {\n if (Types.Events.isWebSocketCreate(event)) {\n startEvent = event;\n }\n if (Types.Events.isWebSocketDestroy(event)) {\n endEvent = event;\n }\n }\n data.syntheticConnection = createSyntheticWebSocketConnection(startEvent, endEvent, data.events[0]);\n });\n}\n\nfunction createSyntheticWebSocketConnection(\n startEvent: Types.Events.WebSocketCreate|null, endEvent: Types.Events.WebSocketDestroy|null,\n firstRecordedEvent: Types.Events.WebSocketEvent): Types.Events.SyntheticWebSocketConnection {\n const {traceBounds} = metaHandlerData();\n const startTs = startEvent ? startEvent.ts : traceBounds.min;\n const endTs = endEvent ? endEvent.ts : traceBounds.max;\n const duration = endTs - startTs;\n const mainEvent = startEvent || endEvent || firstRecordedEvent;\n return {\n name: 'SyntheticWebSocketConnection',\n cat: mainEvent.cat,\n ph: Types.Events.Phase.COMPLETE,\n ts: startTs,\n dur: duration as Types.Timing.MicroSeconds,\n pid: mainEvent.pid,\n tid: mainEvent.tid,\n s: mainEvent.s,\n rawSourceEvent: mainEvent,\n _tag: 'SyntheticEntryTag',\n args: {\n data: {\n identifier: mainEvent.args.data.identifier,\n priority: Protocol.Network.ResourcePriority.Low,\n url: mainEvent.args.data.url || '',\n },\n },\n };\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/NetworkRequestsHandler.test.js b/public/models/trace/handlers/NetworkRequestsHandler.test.js index 23adf54c4..9f35927e3 100644 --- a/public/models/trace/handlers/NetworkRequestsHandler.test.js +++ b/public/models/trace/handlers/NetworkRequestsHandler.test.js @@ -2,18 +2,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import { TraceLoader } from '../../../testing/TraceLoader.js'; -import * as TraceModel from '../trace.js'; +import * as Trace from '../trace.js'; describe('NetworkRequestsHandler', function () { describe('error handling', () => { it('throws if handleEvent is called before it is initialized', () => { assert.throws(() => { - TraceModel.Handlers.ModelHandlers.NetworkRequests.handleEvent({}); + Trace.Handlers.ModelHandlers.NetworkRequests.handleEvent({}); }, 'Network Request handler is not initialized'); }); it('throws if finalize is called before initialize', async () => { let thrown = null; try { - await TraceModel.Handlers.ModelHandlers.NetworkRequests.finalize(); + await Trace.Handlers.ModelHandlers.NetworkRequests.finalize(); } catch (e) { thrown = e; @@ -23,46 +23,46 @@ describe('NetworkRequestsHandler', function () { }); describe('network requests calculations', () => { beforeEach(() => { - TraceModel.Handlers.ModelHandlers.Meta.reset(); - TraceModel.Handlers.ModelHandlers.Meta.initialize(); - TraceModel.Handlers.ModelHandlers.NetworkRequests.initialize(); + Trace.Handlers.ModelHandlers.Meta.reset(); + Trace.Handlers.ModelHandlers.Meta.initialize(); + Trace.Handlers.ModelHandlers.NetworkRequests.initialize(); }); it('calculates network requests correctly', async function () { const traceEvents = await TraceLoader.rawEvents(this, 'load-simple.json.gz'); for (const event of traceEvents) { - TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event); - TraceModel.Handlers.ModelHandlers.NetworkRequests.handleEvent(event); + Trace.Handlers.ModelHandlers.Meta.handleEvent(event); + Trace.Handlers.ModelHandlers.NetworkRequests.handleEvent(event); } - await TraceModel.Handlers.ModelHandlers.Meta.finalize(); - await TraceModel.Handlers.ModelHandlers.NetworkRequests.finalize(); - const requestsByOrigin = TraceModel.Handlers.ModelHandlers.NetworkRequests.data().byOrigin; + await Trace.Handlers.ModelHandlers.Meta.finalize(); + await Trace.Handlers.ModelHandlers.NetworkRequests.finalize(); + const requestsByOrigin = Trace.Handlers.ModelHandlers.NetworkRequests.data().byOrigin; assert.strictEqual(requestsByOrigin.size, 3, 'Too many origins detected'); const topLevelRequests = requestsByOrigin.get('localhost:8080') || { all: [] }; assert.strictEqual(topLevelRequests.all.length, 4, 'Incorrect number of requests'); // Page Request. const pageRequestExpected = new Map([ - ['queueing', TraceModel.Types.Timing.MicroSeconds(25085)], - ['stalled', TraceModel.Types.Timing.MicroSeconds(5670)], - ['dnsLookup', TraceModel.Types.Timing.MicroSeconds(105)], - ['initialConnection', TraceModel.Types.Timing.MicroSeconds(498)], - ['ssl', TraceModel.Types.Timing.MicroSeconds(0)], - ['requestSent', TraceModel.Types.Timing.MicroSeconds(363)], - ['waiting', TraceModel.Types.Timing.MicroSeconds(1383)], - ['download', TraceModel.Types.Timing.MicroSeconds(4827)], - ['networkDuration', TraceModel.Types.Timing.MicroSeconds(38503)], + ['queueing', Trace.Types.Timing.MicroSeconds(25085)], + ['stalled', Trace.Types.Timing.MicroSeconds(5670)], + ['dnsLookup', Trace.Types.Timing.MicroSeconds(105)], + ['initialConnection', Trace.Types.Timing.MicroSeconds(498)], + ['ssl', Trace.Types.Timing.MicroSeconds(0)], + ['requestSent', Trace.Types.Timing.MicroSeconds(363)], + ['waiting', Trace.Types.Timing.MicroSeconds(1383)], + ['download', Trace.Types.Timing.MicroSeconds(4827)], + ['networkDuration', Trace.Types.Timing.MicroSeconds(38503)], ]); assertDataArgsProcessedDataStats(topLevelRequests.all, 'http://localhost:8080/', pageRequestExpected); // CSS Request (cached event (with resourceMarkAsCached event)), const cssRequestExpected = new Map([ - ['queueing', TraceModel.Types.Timing.MicroSeconds(0)], - ['stalled', TraceModel.Types.Timing.MicroSeconds(2175)], - ['dnsLookup', TraceModel.Types.Timing.MicroSeconds(0)], - ['initialConnection', TraceModel.Types.Timing.MicroSeconds(0)], - ['ssl', TraceModel.Types.Timing.MicroSeconds(0)], - ['requestSent', TraceModel.Types.Timing.MicroSeconds(0)], - ['waiting', TraceModel.Types.Timing.MicroSeconds(0)], - ['download', TraceModel.Types.Timing.MicroSeconds(1294)], - ['networkDuration', TraceModel.Types.Timing.MicroSeconds(0)], + ['queueing', Trace.Types.Timing.MicroSeconds(0)], + ['stalled', Trace.Types.Timing.MicroSeconds(2175)], + ['dnsLookup', Trace.Types.Timing.MicroSeconds(0)], + ['initialConnection', Trace.Types.Timing.MicroSeconds(0)], + ['ssl', Trace.Types.Timing.MicroSeconds(0)], + ['requestSent', Trace.Types.Timing.MicroSeconds(0)], + ['waiting', Trace.Types.Timing.MicroSeconds(0)], + ['download', Trace.Types.Timing.MicroSeconds(1294)], + ['networkDuration', Trace.Types.Timing.MicroSeconds(0)], ]); const cssRequestBlockingStatusExpected = new Map([ ['renderBlocking', 'blocking'], @@ -71,15 +71,15 @@ describe('NetworkRequestsHandler', function () { assertDataArgsStats(topLevelRequests.all, 'http://localhost:8080/styles.css', cssRequestBlockingStatusExpected); // Blocking JS Request. const blockingJSRequestExpected = new Map([ - ['queueing', TraceModel.Types.Timing.MicroSeconds(0)], - ['stalled', TraceModel.Types.Timing.MicroSeconds(2126)], - ['dnsLookup', TraceModel.Types.Timing.MicroSeconds(0)], - ['initialConnection', TraceModel.Types.Timing.MicroSeconds(0)], - ['ssl', TraceModel.Types.Timing.MicroSeconds(0)], - ['requestSent', TraceModel.Types.Timing.MicroSeconds(0)], - ['waiting', TraceModel.Types.Timing.MicroSeconds(0)], - ['download', TraceModel.Types.Timing.MicroSeconds(1207)], - ['networkDuration', TraceModel.Types.Timing.MicroSeconds(0)], + ['queueing', Trace.Types.Timing.MicroSeconds(0)], + ['stalled', Trace.Types.Timing.MicroSeconds(2126)], + ['dnsLookup', Trace.Types.Timing.MicroSeconds(0)], + ['initialConnection', Trace.Types.Timing.MicroSeconds(0)], + ['ssl', Trace.Types.Timing.MicroSeconds(0)], + ['requestSent', Trace.Types.Timing.MicroSeconds(0)], + ['waiting', Trace.Types.Timing.MicroSeconds(0)], + ['download', Trace.Types.Timing.MicroSeconds(1207)], + ['networkDuration', Trace.Types.Timing.MicroSeconds(0)], ]); const blockingJSBlockingStatusExpected = new Map([ ['renderBlocking', 'in_body_parser_blocking'], @@ -88,15 +88,15 @@ describe('NetworkRequestsHandler', function () { assertDataArgsStats(topLevelRequests.all, 'http://localhost:8080/blocking.js', blockingJSBlockingStatusExpected); // Module JS Request (cached). const moduleRequestExpected = new Map([ - ['queueing', TraceModel.Types.Timing.MicroSeconds(7681)], - ['stalled', TraceModel.Types.Timing.MicroSeconds(1527)], - ['dnsLookup', TraceModel.Types.Timing.MicroSeconds(0)], - ['initialConnection', TraceModel.Types.Timing.MicroSeconds(0)], - ['ssl', TraceModel.Types.Timing.MicroSeconds(0)], - ['requestSent', TraceModel.Types.Timing.MicroSeconds(0)], - ['waiting', TraceModel.Types.Timing.MicroSeconds(20200)], - ['download', TraceModel.Types.Timing.MicroSeconds(19273)], - ['networkDuration', TraceModel.Types.Timing.MicroSeconds(48681)], + ['queueing', Trace.Types.Timing.MicroSeconds(7681)], + ['stalled', Trace.Types.Timing.MicroSeconds(1527)], + ['dnsLookup', Trace.Types.Timing.MicroSeconds(0)], + ['initialConnection', Trace.Types.Timing.MicroSeconds(0)], + ['ssl', Trace.Types.Timing.MicroSeconds(0)], + ['requestSent', Trace.Types.Timing.MicroSeconds(0)], + ['waiting', Trace.Types.Timing.MicroSeconds(20200)], + ['download', Trace.Types.Timing.MicroSeconds(19273)], + ['networkDuration', Trace.Types.Timing.MicroSeconds(48681)], ]); const moduleRequestBlockingStatusExpected = new Map([ ['renderBlocking', 'non_blocking'], @@ -107,15 +107,15 @@ describe('NetworkRequestsHandler', function () { const fontCSSRequests = requestsByOrigin.get('fonts.googleapis.com') || { all: [] }; assert.strictEqual(fontCSSRequests.all.length, 1, 'Incorrect number of requests'); const fontCSSRequestExpected = new Map([ - ['queueing', TraceModel.Types.Timing.MicroSeconds(0)], - ['stalled', TraceModel.Types.Timing.MicroSeconds(3178)], - ['dnsLookup', TraceModel.Types.Timing.MicroSeconds(0)], - ['initialConnection', TraceModel.Types.Timing.MicroSeconds(0)], - ['ssl', TraceModel.Types.Timing.MicroSeconds(0)], - ['requestSent', TraceModel.Types.Timing.MicroSeconds(0)], - ['waiting', TraceModel.Types.Timing.MicroSeconds(0)], - ['download', TraceModel.Types.Timing.MicroSeconds(1203)], - ['networkDuration', TraceModel.Types.Timing.MicroSeconds(0)], + ['queueing', Trace.Types.Timing.MicroSeconds(0)], + ['stalled', Trace.Types.Timing.MicroSeconds(3178)], + ['dnsLookup', Trace.Types.Timing.MicroSeconds(0)], + ['initialConnection', Trace.Types.Timing.MicroSeconds(0)], + ['ssl', Trace.Types.Timing.MicroSeconds(0)], + ['requestSent', Trace.Types.Timing.MicroSeconds(0)], + ['waiting', Trace.Types.Timing.MicroSeconds(0)], + ['download', Trace.Types.Timing.MicroSeconds(1203)], + ['networkDuration', Trace.Types.Timing.MicroSeconds(0)], ]); const fontCSSBlockingStatusExpected = new Map([ ['renderBlocking', 'blocking'], @@ -126,15 +126,15 @@ describe('NetworkRequestsHandler', function () { const fontDataRequests = requestsByOrigin.get('fonts.gstatic.com') || { all: [] }; assert.strictEqual(fontDataRequests.all.length, 1, 'Incorrect number of requests'); const fontDataRequestExpected = new Map([ - ['queueing', TraceModel.Types.Timing.MicroSeconds(0)], - ['stalled', TraceModel.Types.Timing.MicroSeconds(1929)], - ['dnsLookup', TraceModel.Types.Timing.MicroSeconds(0)], - ['initialConnection', TraceModel.Types.Timing.MicroSeconds(0)], - ['ssl', TraceModel.Types.Timing.MicroSeconds(0)], - ['requestSent', TraceModel.Types.Timing.MicroSeconds(0)], - ['waiting', TraceModel.Types.Timing.MicroSeconds(0)], - ['download', TraceModel.Types.Timing.MicroSeconds(962)], - ['networkDuration', TraceModel.Types.Timing.MicroSeconds(0)], + ['queueing', Trace.Types.Timing.MicroSeconds(0)], + ['stalled', Trace.Types.Timing.MicroSeconds(1929)], + ['dnsLookup', Trace.Types.Timing.MicroSeconds(0)], + ['initialConnection', Trace.Types.Timing.MicroSeconds(0)], + ['ssl', Trace.Types.Timing.MicroSeconds(0)], + ['requestSent', Trace.Types.Timing.MicroSeconds(0)], + ['waiting', Trace.Types.Timing.MicroSeconds(0)], + ['download', Trace.Types.Timing.MicroSeconds(962)], + ['networkDuration', Trace.Types.Timing.MicroSeconds(0)], ]); const fontDataRequestBlockingStatusExpected = new Map([ ['renderBlocking', 'non_blocking'], @@ -145,30 +145,30 @@ describe('NetworkRequestsHandler', function () { it('calculates Websocket events correctly', async function () { const traceEvents = await TraceLoader.rawEvents(this, 'network-websocket-messages.json.gz'); for (const event of traceEvents) { - TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event); - TraceModel.Handlers.ModelHandlers.NetworkRequests.handleEvent(event); + Trace.Handlers.ModelHandlers.Meta.handleEvent(event); + Trace.Handlers.ModelHandlers.NetworkRequests.handleEvent(event); } - await TraceModel.Handlers.ModelHandlers.Meta.finalize(); - await TraceModel.Handlers.ModelHandlers.NetworkRequests.finalize(); - const webSocketEvents = TraceModel.Handlers.ModelHandlers.NetworkRequests.data().webSocket; + await Trace.Handlers.ModelHandlers.Meta.finalize(); + await Trace.Handlers.ModelHandlers.NetworkRequests.finalize(); + const webSocketEvents = Trace.Handlers.ModelHandlers.NetworkRequests.data().webSocket; assert.strictEqual(webSocketEvents[0].events.length, 9, 'Incorrect number of events'); }); }); describe('parses the change priority request', () => { beforeEach(() => { - TraceModel.Handlers.ModelHandlers.Meta.reset(); - TraceModel.Handlers.ModelHandlers.Meta.initialize(); - TraceModel.Handlers.ModelHandlers.NetworkRequests.initialize(); + Trace.Handlers.ModelHandlers.Meta.reset(); + Trace.Handlers.ModelHandlers.Meta.initialize(); + Trace.Handlers.ModelHandlers.NetworkRequests.initialize(); }); it('changes priority of the resouce', async function () { const traceEvents = await TraceLoader.rawEvents(this, 'changing-priority.json.gz'); for (const event of traceEvents) { - TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event); - TraceModel.Handlers.ModelHandlers.NetworkRequests.handleEvent(event); + Trace.Handlers.ModelHandlers.Meta.handleEvent(event); + Trace.Handlers.ModelHandlers.NetworkRequests.handleEvent(event); } - await TraceModel.Handlers.ModelHandlers.Meta.finalize(); - await TraceModel.Handlers.ModelHandlers.NetworkRequests.finalize(); - const { byTime } = TraceModel.Handlers.ModelHandlers.NetworkRequests.data(); + await Trace.Handlers.ModelHandlers.Meta.finalize(); + await Trace.Handlers.ModelHandlers.NetworkRequests.finalize(); + const { byTime } = Trace.Handlers.ModelHandlers.NetworkRequests.data(); const imageRequest = byTime.find(request => { return request.args.data.url === 'https://via.placeholder.com/3000.jpg'; }); @@ -181,19 +181,19 @@ describe('NetworkRequestsHandler', function () { }); describe('redirects', () => { beforeEach(() => { - TraceModel.Handlers.ModelHandlers.Meta.reset(); - TraceModel.Handlers.ModelHandlers.Meta.initialize(); - TraceModel.Handlers.ModelHandlers.NetworkRequests.initialize(); + Trace.Handlers.ModelHandlers.Meta.reset(); + Trace.Handlers.ModelHandlers.Meta.initialize(); + Trace.Handlers.ModelHandlers.NetworkRequests.initialize(); }); it('calculates redirects correctly (navigations)', async function () { const traceEvents = await TraceLoader.rawEvents(this, 'redirects.json.gz'); for (const event of traceEvents) { - TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event); - TraceModel.Handlers.ModelHandlers.NetworkRequests.handleEvent(event); + Trace.Handlers.ModelHandlers.Meta.handleEvent(event); + Trace.Handlers.ModelHandlers.NetworkRequests.handleEvent(event); } - await TraceModel.Handlers.ModelHandlers.Meta.finalize(); - await TraceModel.Handlers.ModelHandlers.NetworkRequests.finalize(); - const { byTime } = TraceModel.Handlers.ModelHandlers.NetworkRequests.data(); + await Trace.Handlers.ModelHandlers.Meta.finalize(); + await Trace.Handlers.ModelHandlers.NetworkRequests.finalize(); + const { byTime } = Trace.Handlers.ModelHandlers.NetworkRequests.data(); assert.strictEqual(byTime.length, 2, 'Incorrect number of requests'); assert.strictEqual(byTime[0].args.data.redirects.length, 0, 'Incorrect number of redirects (request 0)'); assert.deepStrictEqual(byTime[1].args.data.redirects, [ @@ -201,27 +201,27 @@ describe('NetworkRequestsHandler', function () { url: 'http://localhost:3000/foo', priority: 'VeryHigh', requestMethod: 'GET', - ts: TraceModel.Types.Timing.MicroSeconds(1311223447642), - dur: TraceModel.Types.Timing.MicroSeconds(7845), + ts: Trace.Types.Timing.MicroSeconds(1311223447642), + dur: Trace.Types.Timing.MicroSeconds(7845), }, { url: 'http://localhost:3000/bar', priority: 'VeryHigh', requestMethod: 'GET', - ts: TraceModel.Types.Timing.MicroSeconds(1311223455487), - dur: TraceModel.Types.Timing.MicroSeconds(3771), + ts: Trace.Types.Timing.MicroSeconds(1311223455487), + dur: Trace.Types.Timing.MicroSeconds(3771), }, ], 'Incorrect number of redirects (request 1)'); }); it('calculates redirects correctly (subresources)', async function () { const traceEvents = await TraceLoader.rawEvents(this, 'redirects-subresource-multiple.json.gz'); for (const event of traceEvents) { - TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event); - TraceModel.Handlers.ModelHandlers.NetworkRequests.handleEvent(event); + Trace.Handlers.ModelHandlers.Meta.handleEvent(event); + Trace.Handlers.ModelHandlers.NetworkRequests.handleEvent(event); } - await TraceModel.Handlers.ModelHandlers.Meta.finalize(); - await TraceModel.Handlers.ModelHandlers.NetworkRequests.finalize(); - const { byTime } = TraceModel.Handlers.ModelHandlers.NetworkRequests.data(); + await Trace.Handlers.ModelHandlers.Meta.finalize(); + await Trace.Handlers.ModelHandlers.NetworkRequests.finalize(); + const { byTime } = Trace.Handlers.ModelHandlers.NetworkRequests.data(); assert.strictEqual(byTime.length, 2, 'Incorrect number of requests'); assert.strictEqual(byTime[0].args.data.redirects.length, 0, 'Incorrect number of redirects (request 0)'); assert.deepStrictEqual(byTime[1].args.data.redirects, [ @@ -229,34 +229,34 @@ describe('NetworkRequestsHandler', function () { url: 'http://localhost:3000/foo.js', priority: 'Low', requestMethod: 'GET', - ts: TraceModel.Types.Timing.MicroSeconds(183611568786), - dur: TraceModel.Types.Timing.MicroSeconds(506233), + ts: Trace.Types.Timing.MicroSeconds(183611568786), + dur: Trace.Types.Timing.MicroSeconds(506233), }, { url: 'http://localhost:3000/bar.js', priority: 'Low', requestMethod: 'GET', - ts: TraceModel.Types.Timing.MicroSeconds(183612075019), - dur: TraceModel.Types.Timing.MicroSeconds(802726), + ts: Trace.Types.Timing.MicroSeconds(183612075019), + dur: Trace.Types.Timing.MicroSeconds(802726), }, ], 'Incorrect number of redirects (request 1)'); }); }); describe('initiators', () => { beforeEach(() => { - TraceModel.Handlers.ModelHandlers.Meta.reset(); - TraceModel.Handlers.ModelHandlers.Meta.initialize(); - TraceModel.Handlers.ModelHandlers.NetworkRequests.initialize(); + Trace.Handlers.ModelHandlers.Meta.reset(); + Trace.Handlers.ModelHandlers.Meta.initialize(); + Trace.Handlers.ModelHandlers.NetworkRequests.initialize(); }); it('calculate the initiator by `initiator` field correctly', async function () { const traceEvents = await TraceLoader.rawEvents(this, 'network-requests-initiators.json.gz'); for (const event of traceEvents) { - TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event); - TraceModel.Handlers.ModelHandlers.NetworkRequests.handleEvent(event); + Trace.Handlers.ModelHandlers.Meta.handleEvent(event); + Trace.Handlers.ModelHandlers.NetworkRequests.handleEvent(event); } - await TraceModel.Handlers.ModelHandlers.Meta.finalize(); - await TraceModel.Handlers.ModelHandlers.NetworkRequests.finalize(); - const { eventToInitiator, byTime } = TraceModel.Handlers.ModelHandlers.NetworkRequests.data(); + await Trace.Handlers.ModelHandlers.Meta.finalize(); + await Trace.Handlers.ModelHandlers.NetworkRequests.finalize(); + const { eventToInitiator, byTime } = Trace.Handlers.ModelHandlers.NetworkRequests.data(); // Find the network request to test, it is initiated by `youtube.com`. const event = byTime.find(event => event.ts === 1491680762420); if (!event) { @@ -273,12 +273,12 @@ describe('NetworkRequestsHandler', function () { it('calculate the initiator by top frame correctly', async function () { const traceEvents = await TraceLoader.rawEvents(this, 'network-requests-initiators.json.gz'); for (const event of traceEvents) { - TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event); - TraceModel.Handlers.ModelHandlers.NetworkRequests.handleEvent(event); + Trace.Handlers.ModelHandlers.Meta.handleEvent(event); + Trace.Handlers.ModelHandlers.NetworkRequests.handleEvent(event); } - await TraceModel.Handlers.ModelHandlers.Meta.finalize(); - await TraceModel.Handlers.ModelHandlers.NetworkRequests.finalize(); - const { eventToInitiator, byTime } = TraceModel.Handlers.ModelHandlers.NetworkRequests.data(); + await Trace.Handlers.ModelHandlers.Meta.finalize(); + await Trace.Handlers.ModelHandlers.NetworkRequests.finalize(); + const { eventToInitiator, byTime } = Trace.Handlers.ModelHandlers.NetworkRequests.data(); // Find the network request to test, it is initiated by ` `. const event = byTime.find(event => event.ts === 1491681999060); if (!event) { diff --git a/public/models/trace/handlers/NetworkRequestsHandler.test.js.map b/public/models/trace/handlers/NetworkRequestsHandler.test.js.map index 8db0e138c..75d3f2c16 100644 --- a/public/models/trace/handlers/NetworkRequestsHandler.test.js.map +++ b/public/models/trace/handlers/NetworkRequestsHandler.test.js.map @@ -1 +1 @@ -{"version":3,"file":"NetworkRequestsHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/NetworkRequestsHandler.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as TraceModel from '../trace.js';\n\ntype DataArgs = TraceModel.Types.TraceEvents.SyntheticNetworkRequest['args']['data'];\ntype DataArgsProcessedData = TraceModel.Types.TraceEvents.SyntheticNetworkRequest['args']['data']['syntheticData'];\ntype DataArgsMap = Map;\ntype DataArgsProcessedDataMap = Map;\n\ndescribe('NetworkRequestsHandler', function() {\n describe('error handling', () => {\n it('throws if handleEvent is called before it is initialized', () => {\n assert.throws(() => {\n TraceModel.Handlers.ModelHandlers.NetworkRequests.handleEvent(\n {} as TraceModel.Types.TraceEvents.TraceEventData);\n }, 'Network Request handler is not initialized');\n });\n\n it('throws if finalize is called before initialize', async () => {\n let thrown: Error|null = null;\n try {\n await TraceModel.Handlers.ModelHandlers.NetworkRequests.finalize();\n } catch (e) {\n thrown = e as Error;\n }\n assert.strictEqual(thrown?.message, 'Network Request handler is not initialized');\n });\n });\n\n describe('network requests calculations', () => {\n beforeEach(() => {\n TraceModel.Handlers.ModelHandlers.Meta.reset();\n TraceModel.Handlers.ModelHandlers.Meta.initialize();\n TraceModel.Handlers.ModelHandlers.NetworkRequests.initialize();\n });\n\n it('calculates network requests correctly', async function() {\n const traceEvents = await TraceLoader.rawEvents(this, 'load-simple.json.gz');\n for (const event of traceEvents) {\n TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event);\n TraceModel.Handlers.ModelHandlers.NetworkRequests.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.Meta.finalize();\n await TraceModel.Handlers.ModelHandlers.NetworkRequests.finalize();\n\n const requestsByOrigin = TraceModel.Handlers.ModelHandlers.NetworkRequests.data().byOrigin;\n assert.strictEqual(requestsByOrigin.size, 3, 'Too many origins detected');\n\n const topLevelRequests = requestsByOrigin.get('localhost:8080') || {all: []};\n assert.strictEqual(topLevelRequests.all.length, 4, 'Incorrect number of requests');\n\n // Page Request.\n const pageRequestExpected: DataArgsProcessedDataMap = new Map([\n ['queueing', TraceModel.Types.Timing.MicroSeconds(25085)],\n ['stalled', TraceModel.Types.Timing.MicroSeconds(5670)],\n ['dnsLookup', TraceModel.Types.Timing.MicroSeconds(105)],\n ['initialConnection', TraceModel.Types.Timing.MicroSeconds(498)],\n ['ssl', TraceModel.Types.Timing.MicroSeconds(0)],\n ['requestSent', TraceModel.Types.Timing.MicroSeconds(363)],\n ['waiting', TraceModel.Types.Timing.MicroSeconds(1383)],\n ['download', TraceModel.Types.Timing.MicroSeconds(4827)],\n ['networkDuration', TraceModel.Types.Timing.MicroSeconds(38503)],\n ]);\n assertDataArgsProcessedDataStats(topLevelRequests.all, 'http://localhost:8080/', pageRequestExpected);\n\n // CSS Request (cached event (with resourceMarkAsCached event)),\n const cssRequestExpected: DataArgsProcessedDataMap = new Map([\n ['queueing', TraceModel.Types.Timing.MicroSeconds(0)],\n ['stalled', TraceModel.Types.Timing.MicroSeconds(2175)],\n ['dnsLookup', TraceModel.Types.Timing.MicroSeconds(0)],\n ['initialConnection', TraceModel.Types.Timing.MicroSeconds(0)],\n ['ssl', TraceModel.Types.Timing.MicroSeconds(0)],\n ['requestSent', TraceModel.Types.Timing.MicroSeconds(0)],\n ['waiting', TraceModel.Types.Timing.MicroSeconds(0)],\n ['download', TraceModel.Types.Timing.MicroSeconds(1294)],\n ['networkDuration', TraceModel.Types.Timing.MicroSeconds(0)],\n ]);\n\n const cssRequestBlockingStatusExpected: DataArgsMap = new Map([\n ['renderBlocking', 'blocking'],\n ]);\n\n assertDataArgsProcessedDataStats(topLevelRequests.all, 'http://localhost:8080/styles.css', cssRequestExpected);\n assertDataArgsStats(topLevelRequests.all, 'http://localhost:8080/styles.css', cssRequestBlockingStatusExpected);\n\n // Blocking JS Request.\n const blockingJSRequestExpected: DataArgsProcessedDataMap = new Map([\n ['queueing', TraceModel.Types.Timing.MicroSeconds(0)],\n ['stalled', TraceModel.Types.Timing.MicroSeconds(2126)],\n ['dnsLookup', TraceModel.Types.Timing.MicroSeconds(0)],\n ['initialConnection', TraceModel.Types.Timing.MicroSeconds(0)],\n ['ssl', TraceModel.Types.Timing.MicroSeconds(0)],\n ['requestSent', TraceModel.Types.Timing.MicroSeconds(0)],\n ['waiting', TraceModel.Types.Timing.MicroSeconds(0)],\n ['download', TraceModel.Types.Timing.MicroSeconds(1207)],\n ['networkDuration', TraceModel.Types.Timing.MicroSeconds(0)],\n ]);\n\n const blockingJSBlockingStatusExpected: DataArgsMap = new Map([\n ['renderBlocking', 'in_body_parser_blocking'],\n ]);\n\n assertDataArgsProcessedDataStats(\n topLevelRequests.all, 'http://localhost:8080/blocking.js', blockingJSRequestExpected);\n assertDataArgsStats(topLevelRequests.all, 'http://localhost:8080/blocking.js', blockingJSBlockingStatusExpected);\n\n // Module JS Request (cached).\n const moduleRequestExpected: DataArgsProcessedDataMap = new Map([\n ['queueing', TraceModel.Types.Timing.MicroSeconds(7681)],\n ['stalled', TraceModel.Types.Timing.MicroSeconds(1527)],\n ['dnsLookup', TraceModel.Types.Timing.MicroSeconds(0)],\n ['initialConnection', TraceModel.Types.Timing.MicroSeconds(0)],\n ['ssl', TraceModel.Types.Timing.MicroSeconds(0)],\n ['requestSent', TraceModel.Types.Timing.MicroSeconds(0)],\n ['waiting', TraceModel.Types.Timing.MicroSeconds(20200)],\n ['download', TraceModel.Types.Timing.MicroSeconds(19273)],\n ['networkDuration', TraceModel.Types.Timing.MicroSeconds(48681)],\n ]);\n\n const moduleRequestBlockingStatusExpected: DataArgsMap = new Map([\n ['renderBlocking', 'non_blocking'],\n ]);\n\n assertDataArgsProcessedDataStats(topLevelRequests.all, 'http://localhost:8080/module.js', moduleRequestExpected);\n assertDataArgsStats(topLevelRequests.all, 'http://localhost:8080/module.js', moduleRequestBlockingStatusExpected);\n\n // Google Fonts CSS Request (cached).\n const fontCSSRequests = requestsByOrigin.get('fonts.googleapis.com') || {all: []};\n assert.strictEqual(fontCSSRequests.all.length, 1, 'Incorrect number of requests');\n\n const fontCSSRequestExpected: DataArgsProcessedDataMap = new Map([\n ['queueing', TraceModel.Types.Timing.MicroSeconds(0)],\n ['stalled', TraceModel.Types.Timing.MicroSeconds(3178)],\n ['dnsLookup', TraceModel.Types.Timing.MicroSeconds(0)],\n ['initialConnection', TraceModel.Types.Timing.MicroSeconds(0)],\n ['ssl', TraceModel.Types.Timing.MicroSeconds(0)],\n ['requestSent', TraceModel.Types.Timing.MicroSeconds(0)],\n ['waiting', TraceModel.Types.Timing.MicroSeconds(0)],\n ['download', TraceModel.Types.Timing.MicroSeconds(1203)],\n ['networkDuration', TraceModel.Types.Timing.MicroSeconds(0)],\n ]);\n\n const fontCSSBlockingStatusExpected: DataArgsMap = new Map([\n ['renderBlocking', 'blocking'],\n ]);\n\n assertDataArgsProcessedDataStats(\n fontCSSRequests.all, 'https://fonts.googleapis.com/css2?family=Orelega+One&display=swap',\n fontCSSRequestExpected);\n assertDataArgsStats(\n fontCSSRequests.all, 'https://fonts.googleapis.com/css2?family=Orelega+One&display=swap',\n fontCSSBlockingStatusExpected);\n\n // Google Fonts Data Request (cached).\n const fontDataRequests = requestsByOrigin.get('fonts.gstatic.com') || {all: []};\n assert.strictEqual(fontDataRequests.all.length, 1, 'Incorrect number of requests');\n\n const fontDataRequestExpected: DataArgsProcessedDataMap = new Map([\n ['queueing', TraceModel.Types.Timing.MicroSeconds(0)],\n ['stalled', TraceModel.Types.Timing.MicroSeconds(1929)],\n ['dnsLookup', TraceModel.Types.Timing.MicroSeconds(0)],\n ['initialConnection', TraceModel.Types.Timing.MicroSeconds(0)],\n ['ssl', TraceModel.Types.Timing.MicroSeconds(0)],\n ['requestSent', TraceModel.Types.Timing.MicroSeconds(0)],\n ['waiting', TraceModel.Types.Timing.MicroSeconds(0)],\n ['download', TraceModel.Types.Timing.MicroSeconds(962)],\n ['networkDuration', TraceModel.Types.Timing.MicroSeconds(0)],\n ]);\n\n const fontDataRequestBlockingStatusExpected: DataArgsMap = new Map([\n ['renderBlocking', 'non_blocking'],\n ]);\n\n assertDataArgsProcessedDataStats(\n fontDataRequests.all, 'https://fonts.gstatic.com/s/orelegaone/v1/3qTpojOggD2XtAdFb-QXZFt93kY.woff2',\n fontDataRequestExpected);\n\n assertDataArgsStats(\n fontDataRequests.all, 'https://fonts.gstatic.com/s/orelegaone/v1/3qTpojOggD2XtAdFb-QXZFt93kY.woff2',\n fontDataRequestBlockingStatusExpected);\n });\n\n it('calculates Websocket events correctly', async function() {\n const traceEvents = await TraceLoader.rawEvents(this, 'network-websocket-messages.json.gz');\n for (const event of traceEvents) {\n TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event);\n TraceModel.Handlers.ModelHandlers.NetworkRequests.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.Meta.finalize();\n await TraceModel.Handlers.ModelHandlers.NetworkRequests.finalize();\n\n const webSocketEvents = TraceModel.Handlers.ModelHandlers.NetworkRequests.data().webSocket;\n\n assert.strictEqual(webSocketEvents[0].events.length, 9, 'Incorrect number of events');\n });\n });\n\n describe('parses the change priority request', () => {\n beforeEach(() => {\n TraceModel.Handlers.ModelHandlers.Meta.reset();\n TraceModel.Handlers.ModelHandlers.Meta.initialize();\n TraceModel.Handlers.ModelHandlers.NetworkRequests.initialize();\n });\n\n it('changes priority of the resouce', async function() {\n const traceEvents = await TraceLoader.rawEvents(this, 'changing-priority.json.gz');\n\n for (const event of traceEvents) {\n TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event);\n TraceModel.Handlers.ModelHandlers.NetworkRequests.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.Meta.finalize();\n await TraceModel.Handlers.ModelHandlers.NetworkRequests.finalize();\n\n const {byTime} = TraceModel.Handlers.ModelHandlers.NetworkRequests.data();\n\n const imageRequest = byTime.find(request => {\n return request.args.data.url === 'https://via.placeholder.com/3000.jpg';\n });\n\n if (!imageRequest) {\n throw new Error('Could not find expected network request.');\n }\n\n assert.strictEqual(imageRequest.args.data.priority, 'High');\n assert.strictEqual(imageRequest.args.data.initialPriority, 'Medium');\n });\n });\n\n describe('redirects', () => {\n beforeEach(() => {\n TraceModel.Handlers.ModelHandlers.Meta.reset();\n TraceModel.Handlers.ModelHandlers.Meta.initialize();\n TraceModel.Handlers.ModelHandlers.NetworkRequests.initialize();\n });\n\n it('calculates redirects correctly (navigations)', async function() {\n const traceEvents = await TraceLoader.rawEvents(this, 'redirects.json.gz');\n for (const event of traceEvents) {\n TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event);\n TraceModel.Handlers.ModelHandlers.NetworkRequests.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.Meta.finalize();\n await TraceModel.Handlers.ModelHandlers.NetworkRequests.finalize();\n\n const {byTime} = TraceModel.Handlers.ModelHandlers.NetworkRequests.data();\n assert.strictEqual(byTime.length, 2, 'Incorrect number of requests');\n assert.strictEqual(byTime[0].args.data.redirects.length, 0, 'Incorrect number of redirects (request 0)');\n assert.deepStrictEqual(\n byTime[1].args.data.redirects,\n [\n {\n url: 'http://localhost:3000/foo',\n priority: 'VeryHigh',\n requestMethod: 'GET',\n ts: TraceModel.Types.Timing.MicroSeconds(1311223447642),\n dur: TraceModel.Types.Timing.MicroSeconds(7845),\n },\n {\n url: 'http://localhost:3000/bar',\n priority: 'VeryHigh',\n requestMethod: 'GET',\n ts: TraceModel.Types.Timing.MicroSeconds(1311223455487),\n dur: TraceModel.Types.Timing.MicroSeconds(3771),\n },\n ],\n 'Incorrect number of redirects (request 1)');\n });\n\n it('calculates redirects correctly (subresources)', async function() {\n const traceEvents = await TraceLoader.rawEvents(this, 'redirects-subresource-multiple.json.gz');\n for (const event of traceEvents) {\n TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event);\n TraceModel.Handlers.ModelHandlers.NetworkRequests.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.Meta.finalize();\n await TraceModel.Handlers.ModelHandlers.NetworkRequests.finalize();\n\n const {byTime} = TraceModel.Handlers.ModelHandlers.NetworkRequests.data();\n assert.strictEqual(byTime.length, 2, 'Incorrect number of requests');\n assert.strictEqual(byTime[0].args.data.redirects.length, 0, 'Incorrect number of redirects (request 0)');\n assert.deepStrictEqual(\n byTime[1].args.data.redirects,\n [\n {\n url: 'http://localhost:3000/foo.js',\n priority: 'Low',\n requestMethod: 'GET',\n ts: TraceModel.Types.Timing.MicroSeconds(183611568786),\n dur: TraceModel.Types.Timing.MicroSeconds(506233),\n },\n {\n url: 'http://localhost:3000/bar.js',\n priority: 'Low',\n requestMethod: 'GET',\n ts: TraceModel.Types.Timing.MicroSeconds(183612075019),\n dur: TraceModel.Types.Timing.MicroSeconds(802726),\n },\n ],\n 'Incorrect number of redirects (request 1)');\n });\n });\n\n describe('initiators', () => {\n beforeEach(() => {\n TraceModel.Handlers.ModelHandlers.Meta.reset();\n TraceModel.Handlers.ModelHandlers.Meta.initialize();\n TraceModel.Handlers.ModelHandlers.NetworkRequests.initialize();\n });\n\n it('calculate the initiator by `initiator` field correctly', async function() {\n const traceEvents = await TraceLoader.rawEvents(this, 'network-requests-initiators.json.gz');\n for (const event of traceEvents) {\n TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event);\n TraceModel.Handlers.ModelHandlers.NetworkRequests.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.Meta.finalize();\n await TraceModel.Handlers.ModelHandlers.NetworkRequests.finalize();\n\n const {eventToInitiator, byTime} = TraceModel.Handlers.ModelHandlers.NetworkRequests.data();\n\n // Find the network request to test, it is initiated by `youtube.com`.\n const event = byTime.find(event => event.ts === 1491680762420);\n if (!event) {\n throw new Error('Could not find the network request.');\n }\n assert.strictEqual(\n event.args.data.url,\n 'https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&family=YouTube+Sans:wght@300..900&display=swap');\n\n const initiator = eventToInitiator.get(event);\n if (!initiator) {\n throw new Error('Did not find expected initiator for the network request');\n }\n assert.strictEqual(initiator.args.data.url, 'https://www.youtube.com/');\n assert.strictEqual(initiator.args.data.url, event.args.data.initiator?.url);\n });\n\n it('calculate the initiator by top frame correctly', async function() {\n const traceEvents = await TraceLoader.rawEvents(this, 'network-requests-initiators.json.gz');\n for (const event of traceEvents) {\n TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event);\n TraceModel.Handlers.ModelHandlers.NetworkRequests.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.Meta.finalize();\n await TraceModel.Handlers.ModelHandlers.NetworkRequests.finalize();\n\n const {eventToInitiator, byTime} = TraceModel.Handlers.ModelHandlers.NetworkRequests.data();\n\n // Find the network request to test, it is initiated by ` `.\n const event = byTime.find(event => event.ts === 1491681999060);\n if (!event) {\n throw new Error('Could not find the network request.');\n }\n assert.strictEqual(\n event.args.data.url, 'https://www.youtube.com/s/player/5b22937f/player_ias.vflset/en_US/base.js');\n\n const initiator = eventToInitiator.get(event);\n if (!initiator) {\n throw new Error('Did not find expected initiator for the network request');\n }\n assert.strictEqual(\n initiator.args.data.url,\n 'https://www.youtube.com/s/desktop/28bb7000/jsbin/desktop_polymer.vflset/desktop_polymer.js');\n assert.isUndefined(event.args.data.initiator?.url);\n assert.strictEqual(initiator.args.data.url, event.args.data.stackTrace?.[0].url);\n });\n });\n});\n\nfunction assertDataArgsStats(\n requests: TraceModel.Types.TraceEvents.SyntheticNetworkRequest[], url: string, stats: Map): void {\n const request = requests.find(request => request.args.data.url === url);\n if (!request) {\n assert.fail(`Unable to find request for URL ${url}`);\n return;\n }\n\n for (const [name, value] of stats.entries()) {\n if (typeof request.args.data[name] === 'number') {\n const expectedValue = value as DataArgs[D];\n const actualValueRounded = Number((request.args.data[name] as number).toPrecision(5)) as DataArgs[D];\n assert.strictEqual(actualValueRounded, expectedValue, url);\n } else {\n assert.strictEqual(request.args.data[name], value, url);\n }\n }\n}\n\nfunction assertDataArgsProcessedDataStats(\n requests: TraceModel.Types.TraceEvents.SyntheticNetworkRequest[], url: string,\n stats: Map): void {\n const request = requests.find(request => request.args.data.url === url);\n if (!request) {\n assert.fail(`Unable to find request for URL ${url}`);\n return;\n }\n\n for (const [name, value] of stats.entries()) {\n if (typeof request.args.data.syntheticData[name] === 'number') {\n const expectedValue = value as DataArgsProcessedData[D];\n const actualValueRounded =\n Number((request.args.data.syntheticData[name] as number).toPrecision(5)) as DataArgsProcessedData[D];\n assert.strictEqual(actualValueRounded, expectedValue, url);\n } else {\n assert.strictEqual(request.args.data.syntheticData[name], value, url);\n }\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"NetworkRequestsHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/NetworkRequestsHandler.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Trace from '../trace.js';\n\ntype DataArgs = Trace.Types.Events.SyntheticNetworkRequest['args']['data'];\ntype DataArgsProcessedData = Trace.Types.Events.SyntheticNetworkRequest['args']['data']['syntheticData'];\ntype DataArgsMap = Map;\ntype DataArgsProcessedDataMap = Map;\n\ndescribe('NetworkRequestsHandler', function() {\n describe('error handling', () => {\n it('throws if handleEvent is called before it is initialized', () => {\n assert.throws(() => {\n Trace.Handlers.ModelHandlers.NetworkRequests.handleEvent({} as Trace.Types.Events.Event);\n }, 'Network Request handler is not initialized');\n });\n\n it('throws if finalize is called before initialize', async () => {\n let thrown: Error|null = null;\n try {\n await Trace.Handlers.ModelHandlers.NetworkRequests.finalize();\n } catch (e) {\n thrown = e as Error;\n }\n assert.strictEqual(thrown?.message, 'Network Request handler is not initialized');\n });\n });\n\n describe('network requests calculations', () => {\n beforeEach(() => {\n Trace.Handlers.ModelHandlers.Meta.reset();\n Trace.Handlers.ModelHandlers.Meta.initialize();\n Trace.Handlers.ModelHandlers.NetworkRequests.initialize();\n });\n\n it('calculates network requests correctly', async function() {\n const traceEvents = await TraceLoader.rawEvents(this, 'load-simple.json.gz');\n for (const event of traceEvents) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n Trace.Handlers.ModelHandlers.NetworkRequests.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n await Trace.Handlers.ModelHandlers.NetworkRequests.finalize();\n\n const requestsByOrigin = Trace.Handlers.ModelHandlers.NetworkRequests.data().byOrigin;\n assert.strictEqual(requestsByOrigin.size, 3, 'Too many origins detected');\n\n const topLevelRequests = requestsByOrigin.get('localhost:8080') || {all: []};\n assert.strictEqual(topLevelRequests.all.length, 4, 'Incorrect number of requests');\n\n // Page Request.\n const pageRequestExpected: DataArgsProcessedDataMap = new Map([\n ['queueing', Trace.Types.Timing.MicroSeconds(25085)],\n ['stalled', Trace.Types.Timing.MicroSeconds(5670)],\n ['dnsLookup', Trace.Types.Timing.MicroSeconds(105)],\n ['initialConnection', Trace.Types.Timing.MicroSeconds(498)],\n ['ssl', Trace.Types.Timing.MicroSeconds(0)],\n ['requestSent', Trace.Types.Timing.MicroSeconds(363)],\n ['waiting', Trace.Types.Timing.MicroSeconds(1383)],\n ['download', Trace.Types.Timing.MicroSeconds(4827)],\n ['networkDuration', Trace.Types.Timing.MicroSeconds(38503)],\n ]);\n assertDataArgsProcessedDataStats(topLevelRequests.all, 'http://localhost:8080/', pageRequestExpected);\n\n // CSS Request (cached event (with resourceMarkAsCached event)),\n const cssRequestExpected: DataArgsProcessedDataMap = new Map([\n ['queueing', Trace.Types.Timing.MicroSeconds(0)],\n ['stalled', Trace.Types.Timing.MicroSeconds(2175)],\n ['dnsLookup', Trace.Types.Timing.MicroSeconds(0)],\n ['initialConnection', Trace.Types.Timing.MicroSeconds(0)],\n ['ssl', Trace.Types.Timing.MicroSeconds(0)],\n ['requestSent', Trace.Types.Timing.MicroSeconds(0)],\n ['waiting', Trace.Types.Timing.MicroSeconds(0)],\n ['download', Trace.Types.Timing.MicroSeconds(1294)],\n ['networkDuration', Trace.Types.Timing.MicroSeconds(0)],\n ]);\n\n const cssRequestBlockingStatusExpected: DataArgsMap = new Map([\n ['renderBlocking', 'blocking'],\n ]);\n\n assertDataArgsProcessedDataStats(topLevelRequests.all, 'http://localhost:8080/styles.css', cssRequestExpected);\n assertDataArgsStats(topLevelRequests.all, 'http://localhost:8080/styles.css', cssRequestBlockingStatusExpected);\n\n // Blocking JS Request.\n const blockingJSRequestExpected: DataArgsProcessedDataMap = new Map([\n ['queueing', Trace.Types.Timing.MicroSeconds(0)],\n ['stalled', Trace.Types.Timing.MicroSeconds(2126)],\n ['dnsLookup', Trace.Types.Timing.MicroSeconds(0)],\n ['initialConnection', Trace.Types.Timing.MicroSeconds(0)],\n ['ssl', Trace.Types.Timing.MicroSeconds(0)],\n ['requestSent', Trace.Types.Timing.MicroSeconds(0)],\n ['waiting', Trace.Types.Timing.MicroSeconds(0)],\n ['download', Trace.Types.Timing.MicroSeconds(1207)],\n ['networkDuration', Trace.Types.Timing.MicroSeconds(0)],\n ]);\n\n const blockingJSBlockingStatusExpected: DataArgsMap = new Map([\n ['renderBlocking', 'in_body_parser_blocking'],\n ]);\n\n assertDataArgsProcessedDataStats(\n topLevelRequests.all, 'http://localhost:8080/blocking.js', blockingJSRequestExpected);\n assertDataArgsStats(topLevelRequests.all, 'http://localhost:8080/blocking.js', blockingJSBlockingStatusExpected);\n\n // Module JS Request (cached).\n const moduleRequestExpected: DataArgsProcessedDataMap = new Map([\n ['queueing', Trace.Types.Timing.MicroSeconds(7681)],\n ['stalled', Trace.Types.Timing.MicroSeconds(1527)],\n ['dnsLookup', Trace.Types.Timing.MicroSeconds(0)],\n ['initialConnection', Trace.Types.Timing.MicroSeconds(0)],\n ['ssl', Trace.Types.Timing.MicroSeconds(0)],\n ['requestSent', Trace.Types.Timing.MicroSeconds(0)],\n ['waiting', Trace.Types.Timing.MicroSeconds(20200)],\n ['download', Trace.Types.Timing.MicroSeconds(19273)],\n ['networkDuration', Trace.Types.Timing.MicroSeconds(48681)],\n ]);\n\n const moduleRequestBlockingStatusExpected: DataArgsMap = new Map([\n ['renderBlocking', 'non_blocking'],\n ]);\n\n assertDataArgsProcessedDataStats(topLevelRequests.all, 'http://localhost:8080/module.js', moduleRequestExpected);\n assertDataArgsStats(topLevelRequests.all, 'http://localhost:8080/module.js', moduleRequestBlockingStatusExpected);\n\n // Google Fonts CSS Request (cached).\n const fontCSSRequests = requestsByOrigin.get('fonts.googleapis.com') || {all: []};\n assert.strictEqual(fontCSSRequests.all.length, 1, 'Incorrect number of requests');\n\n const fontCSSRequestExpected: DataArgsProcessedDataMap = new Map([\n ['queueing', Trace.Types.Timing.MicroSeconds(0)],\n ['stalled', Trace.Types.Timing.MicroSeconds(3178)],\n ['dnsLookup', Trace.Types.Timing.MicroSeconds(0)],\n ['initialConnection', Trace.Types.Timing.MicroSeconds(0)],\n ['ssl', Trace.Types.Timing.MicroSeconds(0)],\n ['requestSent', Trace.Types.Timing.MicroSeconds(0)],\n ['waiting', Trace.Types.Timing.MicroSeconds(0)],\n ['download', Trace.Types.Timing.MicroSeconds(1203)],\n ['networkDuration', Trace.Types.Timing.MicroSeconds(0)],\n ]);\n\n const fontCSSBlockingStatusExpected: DataArgsMap = new Map([\n ['renderBlocking', 'blocking'],\n ]);\n\n assertDataArgsProcessedDataStats(\n fontCSSRequests.all, 'https://fonts.googleapis.com/css2?family=Orelega+One&display=swap',\n fontCSSRequestExpected);\n assertDataArgsStats(\n fontCSSRequests.all, 'https://fonts.googleapis.com/css2?family=Orelega+One&display=swap',\n fontCSSBlockingStatusExpected);\n\n // Google Fonts Data Request (cached).\n const fontDataRequests = requestsByOrigin.get('fonts.gstatic.com') || {all: []};\n assert.strictEqual(fontDataRequests.all.length, 1, 'Incorrect number of requests');\n\n const fontDataRequestExpected: DataArgsProcessedDataMap = new Map([\n ['queueing', Trace.Types.Timing.MicroSeconds(0)],\n ['stalled', Trace.Types.Timing.MicroSeconds(1929)],\n ['dnsLookup', Trace.Types.Timing.MicroSeconds(0)],\n ['initialConnection', Trace.Types.Timing.MicroSeconds(0)],\n ['ssl', Trace.Types.Timing.MicroSeconds(0)],\n ['requestSent', Trace.Types.Timing.MicroSeconds(0)],\n ['waiting', Trace.Types.Timing.MicroSeconds(0)],\n ['download', Trace.Types.Timing.MicroSeconds(962)],\n ['networkDuration', Trace.Types.Timing.MicroSeconds(0)],\n ]);\n\n const fontDataRequestBlockingStatusExpected: DataArgsMap = new Map([\n ['renderBlocking', 'non_blocking'],\n ]);\n\n assertDataArgsProcessedDataStats(\n fontDataRequests.all, 'https://fonts.gstatic.com/s/orelegaone/v1/3qTpojOggD2XtAdFb-QXZFt93kY.woff2',\n fontDataRequestExpected);\n\n assertDataArgsStats(\n fontDataRequests.all, 'https://fonts.gstatic.com/s/orelegaone/v1/3qTpojOggD2XtAdFb-QXZFt93kY.woff2',\n fontDataRequestBlockingStatusExpected);\n });\n\n it('calculates Websocket events correctly', async function() {\n const traceEvents = await TraceLoader.rawEvents(this, 'network-websocket-messages.json.gz');\n for (const event of traceEvents) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n Trace.Handlers.ModelHandlers.NetworkRequests.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n await Trace.Handlers.ModelHandlers.NetworkRequests.finalize();\n\n const webSocketEvents = Trace.Handlers.ModelHandlers.NetworkRequests.data().webSocket;\n\n assert.strictEqual(webSocketEvents[0].events.length, 9, 'Incorrect number of events');\n });\n });\n\n describe('parses the change priority request', () => {\n beforeEach(() => {\n Trace.Handlers.ModelHandlers.Meta.reset();\n Trace.Handlers.ModelHandlers.Meta.initialize();\n Trace.Handlers.ModelHandlers.NetworkRequests.initialize();\n });\n\n it('changes priority of the resouce', async function() {\n const traceEvents = await TraceLoader.rawEvents(this, 'changing-priority.json.gz');\n\n for (const event of traceEvents) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n Trace.Handlers.ModelHandlers.NetworkRequests.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n await Trace.Handlers.ModelHandlers.NetworkRequests.finalize();\n\n const {byTime} = Trace.Handlers.ModelHandlers.NetworkRequests.data();\n\n const imageRequest = byTime.find(request => {\n return request.args.data.url === 'https://via.placeholder.com/3000.jpg';\n });\n\n if (!imageRequest) {\n throw new Error('Could not find expected network request.');\n }\n\n assert.strictEqual(imageRequest.args.data.priority, 'High');\n assert.strictEqual(imageRequest.args.data.initialPriority, 'Medium');\n });\n });\n\n describe('redirects', () => {\n beforeEach(() => {\n Trace.Handlers.ModelHandlers.Meta.reset();\n Trace.Handlers.ModelHandlers.Meta.initialize();\n Trace.Handlers.ModelHandlers.NetworkRequests.initialize();\n });\n\n it('calculates redirects correctly (navigations)', async function() {\n const traceEvents = await TraceLoader.rawEvents(this, 'redirects.json.gz');\n for (const event of traceEvents) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n Trace.Handlers.ModelHandlers.NetworkRequests.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n await Trace.Handlers.ModelHandlers.NetworkRequests.finalize();\n\n const {byTime} = Trace.Handlers.ModelHandlers.NetworkRequests.data();\n assert.strictEqual(byTime.length, 2, 'Incorrect number of requests');\n assert.strictEqual(byTime[0].args.data.redirects.length, 0, 'Incorrect number of redirects (request 0)');\n assert.deepStrictEqual(\n byTime[1].args.data.redirects,\n [\n {\n url: 'http://localhost:3000/foo',\n priority: 'VeryHigh',\n requestMethod: 'GET',\n ts: Trace.Types.Timing.MicroSeconds(1311223447642),\n dur: Trace.Types.Timing.MicroSeconds(7845),\n },\n {\n url: 'http://localhost:3000/bar',\n priority: 'VeryHigh',\n requestMethod: 'GET',\n ts: Trace.Types.Timing.MicroSeconds(1311223455487),\n dur: Trace.Types.Timing.MicroSeconds(3771),\n },\n ],\n 'Incorrect number of redirects (request 1)');\n });\n\n it('calculates redirects correctly (subresources)', async function() {\n const traceEvents = await TraceLoader.rawEvents(this, 'redirects-subresource-multiple.json.gz');\n for (const event of traceEvents) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n Trace.Handlers.ModelHandlers.NetworkRequests.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n await Trace.Handlers.ModelHandlers.NetworkRequests.finalize();\n\n const {byTime} = Trace.Handlers.ModelHandlers.NetworkRequests.data();\n assert.strictEqual(byTime.length, 2, 'Incorrect number of requests');\n assert.strictEqual(byTime[0].args.data.redirects.length, 0, 'Incorrect number of redirects (request 0)');\n assert.deepStrictEqual(\n byTime[1].args.data.redirects,\n [\n {\n url: 'http://localhost:3000/foo.js',\n priority: 'Low',\n requestMethod: 'GET',\n ts: Trace.Types.Timing.MicroSeconds(183611568786),\n dur: Trace.Types.Timing.MicroSeconds(506233),\n },\n {\n url: 'http://localhost:3000/bar.js',\n priority: 'Low',\n requestMethod: 'GET',\n ts: Trace.Types.Timing.MicroSeconds(183612075019),\n dur: Trace.Types.Timing.MicroSeconds(802726),\n },\n ],\n 'Incorrect number of redirects (request 1)');\n });\n });\n\n describe('initiators', () => {\n beforeEach(() => {\n Trace.Handlers.ModelHandlers.Meta.reset();\n Trace.Handlers.ModelHandlers.Meta.initialize();\n Trace.Handlers.ModelHandlers.NetworkRequests.initialize();\n });\n\n it('calculate the initiator by `initiator` field correctly', async function() {\n const traceEvents = await TraceLoader.rawEvents(this, 'network-requests-initiators.json.gz');\n for (const event of traceEvents) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n Trace.Handlers.ModelHandlers.NetworkRequests.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n await Trace.Handlers.ModelHandlers.NetworkRequests.finalize();\n\n const {eventToInitiator, byTime} = Trace.Handlers.ModelHandlers.NetworkRequests.data();\n\n // Find the network request to test, it is initiated by `youtube.com`.\n const event = byTime.find(event => event.ts === 1491680762420);\n if (!event) {\n throw new Error('Could not find the network request.');\n }\n assert.strictEqual(\n event.args.data.url,\n 'https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&family=YouTube+Sans:wght@300..900&display=swap');\n\n const initiator = eventToInitiator.get(event);\n if (!initiator) {\n throw new Error('Did not find expected initiator for the network request');\n }\n assert.strictEqual(initiator.args.data.url, 'https://www.youtube.com/');\n assert.strictEqual(initiator.args.data.url, event.args.data.initiator?.url);\n });\n\n it('calculate the initiator by top frame correctly', async function() {\n const traceEvents = await TraceLoader.rawEvents(this, 'network-requests-initiators.json.gz');\n for (const event of traceEvents) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n Trace.Handlers.ModelHandlers.NetworkRequests.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n await Trace.Handlers.ModelHandlers.NetworkRequests.finalize();\n\n const {eventToInitiator, byTime} = Trace.Handlers.ModelHandlers.NetworkRequests.data();\n\n // Find the network request to test, it is initiated by ` `.\n const event = byTime.find(event => event.ts === 1491681999060);\n if (!event) {\n throw new Error('Could not find the network request.');\n }\n assert.strictEqual(\n event.args.data.url, 'https://www.youtube.com/s/player/5b22937f/player_ias.vflset/en_US/base.js');\n\n const initiator = eventToInitiator.get(event);\n if (!initiator) {\n throw new Error('Did not find expected initiator for the network request');\n }\n assert.strictEqual(\n initiator.args.data.url,\n 'https://www.youtube.com/s/desktop/28bb7000/jsbin/desktop_polymer.vflset/desktop_polymer.js');\n assert.isUndefined(event.args.data.initiator?.url);\n assert.strictEqual(initiator.args.data.url, event.args.data.stackTrace?.[0].url);\n });\n });\n});\n\nfunction assertDataArgsStats(\n requests: Trace.Types.Events.SyntheticNetworkRequest[], url: string, stats: Map): void {\n const request = requests.find(request => request.args.data.url === url);\n if (!request) {\n assert.fail(`Unable to find request for URL ${url}`);\n return;\n }\n\n for (const [name, value] of stats.entries()) {\n if (typeof request.args.data[name] === 'number') {\n const expectedValue = value as DataArgs[D];\n const actualValueRounded = Number((request.args.data[name] as number).toPrecision(5)) as DataArgs[D];\n assert.strictEqual(actualValueRounded, expectedValue, url);\n } else {\n assert.strictEqual(request.args.data[name], value, url);\n }\n }\n}\n\nfunction assertDataArgsProcessedDataStats(\n requests: Trace.Types.Events.SyntheticNetworkRequest[], url: string,\n stats: Map): void {\n const request = requests.find(request => request.args.data.url === url);\n if (!request) {\n assert.fail(`Unable to find request for URL ${url}`);\n return;\n }\n\n for (const [name, value] of stats.entries()) {\n if (typeof request.args.data.syntheticData[name] === 'number') {\n const expectedValue = value as DataArgsProcessedData[D];\n const actualValueRounded =\n Number((request.args.data.syntheticData[name] as number).toPrecision(5)) as DataArgsProcessedData[D];\n assert.strictEqual(actualValueRounded, expectedValue, url);\n } else {\n assert.strictEqual(request.args.data.syntheticData[name], value, url);\n }\n }\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/PageFramesHandler.d.ts b/public/models/trace/handlers/PageFramesHandler.d.ts index e07b7b3bb..32f0f844e 100644 --- a/public/models/trace/handlers/PageFramesHandler.d.ts +++ b/public/models/trace/handlers/PageFramesHandler.d.ts @@ -1,7 +1,7 @@ import * as Types from '../types/types.js'; export declare function reset(): void; -export declare function handleEvent(event: Types.TraceEvents.TraceEventData): void; +export declare function handleEvent(event: Types.Events.Event): void; export interface PageFrameData { - frames: Map; + frames: Map; } export declare function data(): PageFrameData; diff --git a/public/models/trace/handlers/PageFramesHandler.js b/public/models/trace/handlers/PageFramesHandler.js index 694a7029d..0839b0f38 100644 --- a/public/models/trace/handlers/PageFramesHandler.js +++ b/public/models/trace/handlers/PageFramesHandler.js @@ -7,7 +7,7 @@ export function reset() { frames.clear(); } export function handleEvent(event) { - if (Types.TraceEvents.isTraceEventTracingStartedInBrowser(event)) { + if (Types.Events.isTracingStartedInBrowser(event)) { for (const frame of event.args.data?.frames ?? []) { // The ID of a frame is stored under the `frame` key. frames.set(frame.frame, frame); @@ -15,7 +15,7 @@ export function handleEvent(event) { return; } // CommitLoad events can contain an updated URL or Name for a frame. - if (Types.TraceEvents.isTraceEventCommitLoad(event)) { + if (Types.Events.isCommitLoad(event)) { const frameData = event.args.data; if (!frameData) { return; diff --git a/public/models/trace/handlers/PageFramesHandler.js.map b/public/models/trace/handlers/PageFramesHandler.js.map index 1cb3b5e53..14109b9bb 100644 --- a/public/models/trace/handlers/PageFramesHandler.js.map +++ b/public/models/trace/handlers/PageFramesHandler.js.map @@ -1 +1 @@ -{"version":3,"file":"PageFramesHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/PageFramesHandler.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAE3C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAwC,CAAC;AAE/D,MAAM,UAAU,KAAK;IACnB,MAAM,CAAC,KAAK,EAAE,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAuC;IACjE,IAAI,KAAK,CAAC,WAAW,CAAC,mCAAmC,CAAC,KAAK,CAAC,EAAE,CAAC;QACjE,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,EAAE,CAAC;YAClD,qDAAqD;YACrD,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACjC,CAAC;QACD,OAAO;IACT,CAAC;IAED,oEAAoE;IACpE,IAAI,KAAK,CAAC,WAAW,CAAC,sBAAsB,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;QAClC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO;QACT,CAAC;QACD,yDAAyD;QACzD,wDAAwD;QACxD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO;QACT,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE;YAC1B,GAAG,KAAK;YACR,GAAG,EAAE,SAAS,CAAC,GAAG,IAAI,KAAK,CAAC,GAAG;YAC/B,IAAI,EAAE,SAAS,CAAC,IAAI,IAAI,SAAS,CAAC,IAAI;SACvC,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAKD,MAAM,UAAU,IAAI;IAClB,OAAO;QACL,MAAM;KACP,CAAC;AACJ,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Types from '../types/types.js';\n\nconst frames = new Map();\n\nexport function reset(): void {\n frames.clear();\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (Types.TraceEvents.isTraceEventTracingStartedInBrowser(event)) {\n for (const frame of event.args.data?.frames ?? []) {\n // The ID of a frame is stored under the `frame` key.\n frames.set(frame.frame, frame);\n }\n return;\n }\n\n // CommitLoad events can contain an updated URL or Name for a frame.\n if (Types.TraceEvents.isTraceEventCommitLoad(event)) {\n const frameData = event.args.data;\n if (!frameData) {\n return;\n }\n // We don't want to mutate the original object, hence why\n // we set a new object from the new and existing values.\n const frame = frames.get(frameData.frame);\n if (!frame) {\n return;\n }\n frames.set(frameData.frame, {\n ...frame,\n url: frameData.url || frame.url,\n name: frameData.name || frameData.name,\n });\n }\n}\n\nexport interface PageFrameData {\n frames: Map;\n}\nexport function data(): PageFrameData {\n return {\n frames,\n };\n}\n"]} \ No newline at end of file +{"version":3,"file":"PageFramesHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/PageFramesHandler.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAE3C,MAAM,MAAM,GAAG,IAAI,GAAG,EAAmC,CAAC;AAE1D,MAAM,UAAU,KAAK;IACnB,MAAM,CAAC,KAAK,EAAE,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAyB;IACnD,IAAI,KAAK,CAAC,MAAM,CAAC,yBAAyB,CAAC,KAAK,CAAC,EAAE,CAAC;QAClD,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,IAAI,EAAE,EAAE,CAAC;YAClD,qDAAqD;YACrD,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACjC,CAAC;QACD,OAAO;IACT,CAAC;IAED,oEAAoE;IACpE,IAAI,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QACrC,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;QAClC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO;QACT,CAAC;QACD,yDAAyD;QACzD,wDAAwD;QACxD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO;QACT,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE;YAC1B,GAAG,KAAK;YACR,GAAG,EAAE,SAAS,CAAC,GAAG,IAAI,KAAK,CAAC,GAAG;YAC/B,IAAI,EAAE,SAAS,CAAC,IAAI,IAAI,SAAS,CAAC,IAAI;SACvC,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAKD,MAAM,UAAU,IAAI;IAClB,OAAO;QACL,MAAM;KACP,CAAC;AACJ,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Types from '../types/types.js';\n\nconst frames = new Map();\n\nexport function reset(): void {\n frames.clear();\n}\n\nexport function handleEvent(event: Types.Events.Event): void {\n if (Types.Events.isTracingStartedInBrowser(event)) {\n for (const frame of event.args.data?.frames ?? []) {\n // The ID of a frame is stored under the `frame` key.\n frames.set(frame.frame, frame);\n }\n return;\n }\n\n // CommitLoad events can contain an updated URL or Name for a frame.\n if (Types.Events.isCommitLoad(event)) {\n const frameData = event.args.data;\n if (!frameData) {\n return;\n }\n // We don't want to mutate the original object, hence why\n // we set a new object from the new and existing values.\n const frame = frames.get(frameData.frame);\n if (!frame) {\n return;\n }\n frames.set(frameData.frame, {\n ...frame,\n url: frameData.url || frame.url,\n name: frameData.name || frameData.name,\n });\n }\n}\n\nexport interface PageFrameData {\n frames: Map;\n}\nexport function data(): PageFrameData {\n return {\n frames,\n };\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/PageFramesHandler.test.js b/public/models/trace/handlers/PageFramesHandler.test.js index d3bb5312c..8795836a2 100644 --- a/public/models/trace/handlers/PageFramesHandler.test.js +++ b/public/models/trace/handlers/PageFramesHandler.test.js @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import { TraceLoader } from '../../../testing/TraceLoader.js'; -import * as TraceEngine from '../trace.js'; +import * as Trace from '../trace.js'; describe('PageFramesHandler', () => { it('returns frames and their data', async function () { const events = await TraceLoader.rawEvents(this, 'web-dev-with-commit.json.gz'); - TraceEngine.Handlers.ModelHandlers.PageFrames.reset(); + Trace.Handlers.ModelHandlers.PageFrames.reset(); for (const event of events) { - TraceEngine.Handlers.ModelHandlers.PageFrames.handleEvent(event); + Trace.Handlers.ModelHandlers.PageFrames.handleEvent(event); } - const data = TraceEngine.Handlers.ModelHandlers.PageFrames.data(); + const data = Trace.Handlers.ModelHandlers.PageFrames.data(); const frames = Array.from(data.frames.entries()); assert.deepEqual(frames, [ [ @@ -18,7 +18,7 @@ describe('PageFramesHandler', () => { { frame: '25D2F12F1818C70B5BD4325CC9ACD8FF', name: '', - processId: TraceEngine.Types.TraceEvents.ProcessID(90812), + processId: Trace.Types.Events.ProcessID(90812), url: 'https://web.dev/', }, ], @@ -28,7 +28,7 @@ describe('PageFramesHandler', () => { frame: 'DD911DEB03F2AAB573DE9CA330486E80', name: '', parent: '25D2F12F1818C70B5BD4325CC9ACD8FF', - processId: TraceEngine.Types.TraceEvents.ProcessID(90824), + processId: Trace.Types.Events.ProcessID(90824), url: 'https://shared-storage-demo-content-producer.web.app/paa/scripts/private-aggregation-test.html', }, ], diff --git a/public/models/trace/handlers/PageFramesHandler.test.js.map b/public/models/trace/handlers/PageFramesHandler.test.js.map index 46208c1f8..998d460c3 100644 --- a/public/models/trace/handlers/PageFramesHandler.test.js.map +++ b/public/models/trace/handlers/PageFramesHandler.test.js.map @@ -1 +1 @@ -{"version":3,"file":"PageFramesHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/PageFramesHandler.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,EAAC,WAAW,EAAC,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,WAAW,MAAM,aAAa,CAAC;AAE3C,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,+BAA+B,EAAE,KAAK;QACvC,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,IAAI,EAAE,6BAA6B,CAAC,CAAC;QAChF,WAAW,CAAC,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QACtD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,WAAW,CAAC,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACnE,CAAC;QACD,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QAClE,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QACjD,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE;YAEvB;gBACE,kCAAkC;gBAClC;oBACE,KAAK,EAAE,kCAAkC;oBACzC,IAAI,EAAE,EAAE;oBACR,SAAS,EAAE,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC;oBACzD,GAAG,EAAE,kBAAkB;iBACxB;aACF;YACD;gBACE,kCAAkC;gBAClC;oBACE,KAAK,EAAE,kCAAkC;oBACzC,IAAI,EAAE,EAAE;oBACR,MAAM,EAAE,kCAAkC;oBAC1C,SAAS,EAAE,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC;oBACzD,GAAG,EAAE,gGAAgG;iBACtG;aACF;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as TraceEngine from '../trace.js';\n\ndescribe('PageFramesHandler', () => {\n it('returns frames and their data', async function() {\n const events = await TraceLoader.rawEvents(this, 'web-dev-with-commit.json.gz');\n TraceEngine.Handlers.ModelHandlers.PageFrames.reset();\n for (const event of events) {\n TraceEngine.Handlers.ModelHandlers.PageFrames.handleEvent(event);\n }\n const data = TraceEngine.Handlers.ModelHandlers.PageFrames.data();\n const frames = Array.from(data.frames.entries());\n assert.deepEqual(frames, [\n\n [\n '25D2F12F1818C70B5BD4325CC9ACD8FF',\n {\n frame: '25D2F12F1818C70B5BD4325CC9ACD8FF',\n name: '',\n processId: TraceEngine.Types.TraceEvents.ProcessID(90812),\n url: 'https://web.dev/',\n },\n ],\n [\n 'DD911DEB03F2AAB573DE9CA330486E80',\n {\n frame: 'DD911DEB03F2AAB573DE9CA330486E80',\n name: '',\n parent: '25D2F12F1818C70B5BD4325CC9ACD8FF',\n processId: TraceEngine.Types.TraceEvents.ProcessID(90824),\n url: 'https://shared-storage-demo-content-producer.web.app/paa/scripts/private-aggregation-test.html',\n },\n ],\n ]);\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"PageFramesHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/PageFramesHandler.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,EAAC,WAAW,EAAC,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,KAAK,MAAM,aAAa,CAAC;AAErC,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,EAAE,CAAC,+BAA+B,EAAE,KAAK;QACvC,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,IAAI,EAAE,6BAA6B,CAAC,CAAC;QAChF,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QAChD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC7D,CAAC;QACD,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QAC5D,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QACjD,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE;YAEvB;gBACE,kCAAkC;gBAClC;oBACE,KAAK,EAAE,kCAAkC;oBACzC,IAAI,EAAE,EAAE;oBACR,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;oBAC9C,GAAG,EAAE,kBAAkB;iBACxB;aACF;YACD;gBACE,kCAAkC;gBAClC;oBACE,KAAK,EAAE,kCAAkC;oBACzC,IAAI,EAAE,EAAE;oBACR,MAAM,EAAE,kCAAkC;oBAC1C,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;oBAC9C,GAAG,EAAE,gGAAgG;iBACtG;aACF;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Trace from '../trace.js';\n\ndescribe('PageFramesHandler', () => {\n it('returns frames and their data', async function() {\n const events = await TraceLoader.rawEvents(this, 'web-dev-with-commit.json.gz');\n Trace.Handlers.ModelHandlers.PageFrames.reset();\n for (const event of events) {\n Trace.Handlers.ModelHandlers.PageFrames.handleEvent(event);\n }\n const data = Trace.Handlers.ModelHandlers.PageFrames.data();\n const frames = Array.from(data.frames.entries());\n assert.deepEqual(frames, [\n\n [\n '25D2F12F1818C70B5BD4325CC9ACD8FF',\n {\n frame: '25D2F12F1818C70B5BD4325CC9ACD8FF',\n name: '',\n processId: Trace.Types.Events.ProcessID(90812),\n url: 'https://web.dev/',\n },\n ],\n [\n 'DD911DEB03F2AAB573DE9CA330486E80',\n {\n frame: 'DD911DEB03F2AAB573DE9CA330486E80',\n name: '',\n parent: '25D2F12F1818C70B5BD4325CC9ACD8FF',\n processId: Trace.Types.Events.ProcessID(90824),\n url: 'https://shared-storage-demo-content-producer.web.app/paa/scripts/private-aggregation-test.html',\n },\n ],\n ]);\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/PageLoadMetricsHandler.d.ts b/public/models/trace/handlers/PageLoadMetricsHandler.d.ts index 979c6be95..aee3d12e5 100644 --- a/public/models/trace/handlers/PageLoadMetricsHandler.d.ts +++ b/public/models/trace/handlers/PageLoadMetricsHandler.d.ts @@ -1,8 +1,8 @@ import * as Types from '../types/types.js'; -import { type TraceEventHandlerName } from './types.js'; +import { type HandlerName } from './types.js'; export declare function reset(): void; -export declare function handleEvent(event: Types.TraceEvents.TraceEventData): void; -export declare function getFrameIdForPageLoadEvent(event: Types.TraceEvents.PageLoadEvent): string; +export declare function handleEvent(event: Types.Events.Event): void; +export declare function getFrameIdForPageLoadEvent(event: Types.Events.PageLoadEvent): string; /** * Classifications sourced from * https://web.dev/fcp/ @@ -40,10 +40,10 @@ export type PageLoadMetricsData = { * Page load events with no associated duration that happened in the * main frame. */ - allMarkerEvents: Types.TraceEvents.PageLoadEvent[]; + allMarkerEvents: Types.Events.PageLoadEvent[]; }; export declare function data(): PageLoadMetricsData; -export declare function deps(): TraceEventHandlerName[]; +export declare function deps(): HandlerName[]; export declare const enum ScoreClassification { GOOD = "good", OK = "ok", @@ -63,8 +63,8 @@ export declare const enum MetricName { export interface MetricScore { metricName: MetricName; classification: ScoreClassification; - event?: Types.TraceEvents.PageLoadEvent; - navigation?: Types.TraceEvents.TraceEventNavigationStart; + event?: Types.Events.PageLoadEvent; + navigation?: Types.Events.NavigationStart; estimated?: boolean; timing: Types.Timing.MicroSeconds; } diff --git a/public/models/trace/handlers/PageLoadMetricsHandler.js b/public/models/trace/handlers/PageLoadMetricsHandler.js index 82c2320e3..de683ed5a 100644 --- a/public/models/trace/handlers/PageLoadMetricsHandler.js +++ b/public/models/trace/handlers/PageLoadMetricsHandler.js @@ -44,7 +44,7 @@ let pageLoadEventsArray = []; // the candidates that were the actual LCP events. const selectedLCPCandidateEvents = new Set(); export function handleEvent(event) { - if (!Types.TraceEvents.eventIsPageLoadEvent(event)) { + if (!Types.Events.eventIsPageLoadEvent(event)) { return; } pageLoadEventsArray.push(event); @@ -70,24 +70,24 @@ function storePageLoadMetricAgainstNavigationId(navigation, event) { if (!processData) { return; } - if (Types.TraceEvents.isTraceEventNavigationStart(event)) { + if (Types.Events.isNavigationStart(event)) { return; } - if (Types.TraceEvents.isTraceEventFirstContentfulPaint(event)) { + if (Types.Events.isFirstContentfulPaint(event)) { const fcpTime = Types.Timing.MicroSeconds(event.ts - navigation.ts); const classification = scoreClassificationForFirstContentfulPaint(fcpTime); const metricScore = { event, metricName: "FCP" /* MetricName.FCP */, classification, navigation, timing: fcpTime }; storeMetricScore(frameId, navigationId, metricScore); return; } - if (Types.TraceEvents.isTraceEventFirstPaint(event)) { + if (Types.Events.isFirstPaint(event)) { const paintTime = Types.Timing.MicroSeconds(event.ts - navigation.ts); const classification = "unclassified" /* ScoreClassification.UNCLASSIFIED */; const metricScore = { event, metricName: "FP" /* MetricName.FP */, classification, navigation, timing: paintTime }; storeMetricScore(frameId, navigationId, metricScore); return; } - if (Types.TraceEvents.isTraceEventMarkDOMContent(event)) { + if (Types.Events.isMarkDOMContent(event)) { const dclTime = Types.Timing.MicroSeconds(event.ts - navigation.ts); const metricScore = { event, @@ -99,7 +99,7 @@ function storePageLoadMetricAgainstNavigationId(navigation, event) { storeMetricScore(frameId, navigationId, metricScore); return; } - if (Types.TraceEvents.isTraceEventInteractiveTime(event)) { + if (Types.Events.isInteractiveTime(event)) { const ttiValue = Types.Timing.MicroSeconds(event.ts - navigation.ts); const tti = { event, @@ -120,7 +120,7 @@ function storePageLoadMetricAgainstNavigationId(navigation, event) { storeMetricScore(frameId, navigationId, tbt); return; } - if (Types.TraceEvents.isTraceEventMarkLoad(event)) { + if (Types.Events.isMarkLoad(event)) { const loadTime = Types.Timing.MicroSeconds(event.ts - navigation.ts); const metricScore = { event, @@ -132,7 +132,7 @@ function storePageLoadMetricAgainstNavigationId(navigation, event) { storeMetricScore(frameId, navigationId, metricScore); return; } - if (Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate(event)) { + if (Types.Events.isLargestContentfulPaintCandidate(event)) { const candidateIndex = event.args.data?.candidateIndex; if (!candidateIndex) { throw new Error('Largest Contenful Paint unexpectedly had no candidateIndex.'); @@ -154,7 +154,7 @@ function storePageLoadMetricAgainstNavigationId(navigation, event) { return; } const lastLCPCandidateEvent = lastLCPCandidate.event; - if (!Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate(lastLCPCandidateEvent)) { + if (!Types.Events.isLargestContentfulPaintCandidate(lastLCPCandidateEvent)) { return; } const lastCandidateIndex = lastLCPCandidateEvent.args.data?.candidateIndex; @@ -171,7 +171,7 @@ function storePageLoadMetricAgainstNavigationId(navigation, event) { } return; } - if (Types.TraceEvents.isTraceEventLayoutShift(event)) { + if (Types.Events.isLayoutShift(event)) { return; } return Platform.assertNever(event, `Unexpected event type: ${event}`); @@ -186,14 +186,12 @@ function storeMetricScore(frameId, navigationId, metricScore) { metrics.set(metricScore.metricName, metricScore); } export function getFrameIdForPageLoadEvent(event) { - if (Types.TraceEvents.isTraceEventFirstContentfulPaint(event) || - Types.TraceEvents.isTraceEventInteractiveTime(event) || - Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate(event) || - Types.TraceEvents.isTraceEventNavigationStart(event) || Types.TraceEvents.isTraceEventLayoutShift(event) || - Types.TraceEvents.isTraceEventFirstPaint(event)) { + if (Types.Events.isFirstContentfulPaint(event) || Types.Events.isInteractiveTime(event) || + Types.Events.isLargestContentfulPaintCandidate(event) || Types.Events.isNavigationStart(event) || + Types.Events.isLayoutShift(event) || Types.Events.isFirstPaint(event)) { return event.args.frame; } - if (Types.TraceEvents.isTraceEventMarkDOMContent(event) || Types.TraceEvents.isTraceEventMarkLoad(event)) { + if (Types.Events.isMarkDOMContent(event) || Types.Events.isMarkLoad(event)) { const frameId = event.args.data?.frame; if (!frameId) { throw new Error('MarkDOMContent unexpectedly had no frame ID.'); @@ -203,9 +201,8 @@ export function getFrameIdForPageLoadEvent(event) { Platform.assertNever(event, `Unexpected event type: ${event}`); } function getNavigationForPageLoadEvent(event) { - if (Types.TraceEvents.isTraceEventFirstContentfulPaint(event) || - Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate(event) || - Types.TraceEvents.isTraceEventFirstPaint(event)) { + if (Types.Events.isFirstContentfulPaint(event) || Types.Events.isLargestContentfulPaintCandidate(event) || + Types.Events.isFirstPaint(event)) { const navigationId = event.args.data?.navigationId; if (!navigationId) { throw new Error('Trace event unexpectedly had no navigation ID.'); @@ -218,13 +215,13 @@ function getNavigationForPageLoadEvent(event) { } return navigation; } - if (Types.TraceEvents.isTraceEventMarkDOMContent(event) || Types.TraceEvents.isTraceEventInteractiveTime(event) || - Types.TraceEvents.isTraceEventLayoutShift(event) || Types.TraceEvents.isTraceEventMarkLoad(event)) { + if (Types.Events.isMarkDOMContent(event) || Types.Events.isInteractiveTime(event) || + Types.Events.isLayoutShift(event) || Types.Events.isMarkLoad(event)) { const frameId = getFrameIdForPageLoadEvent(event); const { navigationsByFrameId } = metaHandlerData(); return Helpers.Trace.getNavigationForTraceEvent(event, frameId, navigationsByFrameId); } - if (Types.TraceEvents.isTraceEventNavigationStart(event)) { + if (Types.Events.isNavigationStart(event)) { // We don't want to compute metrics of the navigation relative to itself, so we'll avoid avoid all that. return null; } @@ -332,8 +329,8 @@ export async function finalize() { const allFinalLCPEvents = gatherFinalLCPEvents(); const mainFrame = metaHandlerData().mainFrameId; // Filter out LCP candidates to use only definitive LCP values - const allEventsButLCP = pageLoadEventsArray.filter(event => !Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate(event)); - const markerEvents = [...allFinalLCPEvents, ...allEventsButLCP].filter(Types.TraceEvents.isTraceEventMarkerEvent); + const allEventsButLCP = pageLoadEventsArray.filter(event => !Types.Events.isLargestContentfulPaintCandidate(event)); + const markerEvents = [...allFinalLCPEvents, ...allEventsButLCP].filter(Types.Events.isMarkerEvent); // Filter by main frame and sort. allMarkerEvents = markerEvents.filter(event => getFrameIdForPageLoadEvent(event) === mainFrame).sort((a, b) => a.ts - b.ts); diff --git a/public/models/trace/handlers/PageLoadMetricsHandler.js.map b/public/models/trace/handlers/PageLoadMetricsHandler.js.map index c92242854..574ec80ff 100644 --- a/public/models/trace/handlers/PageLoadMetricsHandler.js.map +++ b/public/models/trace/handlers/PageLoadMetricsHandler.js.map @@ -1 +1 @@ -{"version":3,"file":"PageLoadMetricsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/PageLoadMetricsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * This handler stores page load metrics, including web vitals,\n * and exports them in the shape of a map with the following shape:\n * Map(FrameId -> Map(navigationID -> metrics) )\n *\n * It also exports all markers in a trace in an array.\n *\n * Some metrics are taken directly from a page load events (AKA markers) like DCL.\n * Others require processing multiple events to be determined, like CLS and TBT.\n */\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {data as metaHandlerData} from './MetaHandler.js';\nimport {type TraceEventHandlerName} from './types.js';\n\n/**\n * This represents the metric scores for all navigations, for all frames in a trace.\n * Given a frame id, the map points to another map from navigation id to metric scores.\n * The metric scores include the event related to the metric as well as the data regarding\n * the score itself.\n */\nconst metricScoresByFrameId =\n new Map>>();\n\n/**\n * Page load events with no associated duration that happened in the\n * main frame.\n */\nlet allMarkerEvents: Types.TraceEvents.PageLoadEvent[] = [];\n\nexport function reset(): void {\n metricScoresByFrameId.clear();\n pageLoadEventsArray = [];\n allMarkerEvents = [];\n selectedLCPCandidateEvents.clear();\n}\n\nlet pageLoadEventsArray: Types.TraceEvents.PageLoadEvent[] = [];\n\n// Once we've found the LCP events in the trace we want to fetch their DOM Node\n// from the backend. We could do this by parsing through our Map of frame =>\n// navigation => metric, but it's easier to keep a set of LCP events. As we\n// parse the trace, any time we store an LCP candidate as the potential LCP\n// event, we store the event here. If we later find a new candidate in the\n// trace, we store that and delete the prior event. When we've parsed the\n// entire trace this set will contain all the LCP events that were used - e.g.\n// the candidates that were the actual LCP events.\nconst selectedLCPCandidateEvents = new Set();\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (!Types.TraceEvents.eventIsPageLoadEvent(event)) {\n return;\n }\n pageLoadEventsArray.push(event);\n}\n\nfunction storePageLoadMetricAgainstNavigationId(\n navigation: Types.TraceEvents.TraceEventNavigationStart, event: Types.TraceEvents.PageLoadEvent): void {\n const navigationId = navigation.args.data?.navigationId;\n if (!navigationId) {\n throw new Error('Navigation event unexpectedly had no navigation ID.');\n }\n const frameId = getFrameIdForPageLoadEvent(event);\n const {rendererProcessesByFrame} = metaHandlerData();\n\n // If either of these pieces of data do not exist, the most likely\n // explanation is that the page load metric we found is for a frame/process\n // combo that the MetaHandler discarded. This typically happens if we get a\n // navigation event with an empty URL. Therefore, we will silently return and\n // drop this metric. If we didn't care about the navigation, we certainly do\n // not need to care about metrics for that navigation.\n const rendererProcessesInFrame = rendererProcessesByFrame.get(frameId);\n if (!rendererProcessesInFrame) {\n return;\n }\n const processData = rendererProcessesInFrame.get(event.pid);\n if (!processData) {\n return;\n }\n\n if (Types.TraceEvents.isTraceEventNavigationStart(event)) {\n return;\n }\n\n if (Types.TraceEvents.isTraceEventFirstContentfulPaint(event)) {\n const fcpTime = Types.Timing.MicroSeconds(event.ts - navigation.ts);\n const classification = scoreClassificationForFirstContentfulPaint(fcpTime);\n const metricScore = {event, metricName: MetricName.FCP, classification, navigation, timing: fcpTime};\n storeMetricScore(frameId, navigationId, metricScore);\n return;\n }\n\n if (Types.TraceEvents.isTraceEventFirstPaint(event)) {\n const paintTime = Types.Timing.MicroSeconds(event.ts - navigation.ts);\n const classification = ScoreClassification.UNCLASSIFIED;\n const metricScore = {event, metricName: MetricName.FP, classification, navigation, timing: paintTime};\n storeMetricScore(frameId, navigationId, metricScore);\n return;\n }\n\n if (Types.TraceEvents.isTraceEventMarkDOMContent(event)) {\n const dclTime = Types.Timing.MicroSeconds(event.ts - navigation.ts);\n const metricScore = {\n event,\n metricName: MetricName.DCL,\n classification: scoreClassificationForDOMContentLoaded(dclTime),\n navigation,\n timing: dclTime,\n };\n storeMetricScore(frameId, navigationId, metricScore);\n return;\n }\n\n if (Types.TraceEvents.isTraceEventInteractiveTime(event)) {\n const ttiValue = Types.Timing.MicroSeconds(event.ts - navigation.ts);\n const tti = {\n event,\n metricName: MetricName.TTI,\n classification: scoreClassificationForTimeToInteractive(ttiValue),\n navigation,\n timing: ttiValue,\n };\n storeMetricScore(frameId, navigationId, tti);\n\n const tbtValue =\n Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(event.args.args.total_blocking_time_ms));\n const tbt = {\n event,\n metricName: MetricName.TBT,\n classification: scoreClassificationForTotalBlockingTime(tbtValue),\n navigation,\n timing: tbtValue,\n };\n storeMetricScore(frameId, navigationId, tbt);\n return;\n }\n\n if (Types.TraceEvents.isTraceEventMarkLoad(event)) {\n const loadTime = Types.Timing.MicroSeconds(event.ts - navigation.ts);\n const metricScore = {\n event,\n metricName: MetricName.L,\n classification: ScoreClassification.UNCLASSIFIED,\n navigation,\n timing: loadTime,\n };\n storeMetricScore(frameId, navigationId, metricScore);\n return;\n }\n\n if (Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate(event)) {\n const candidateIndex = event.args.data?.candidateIndex;\n if (!candidateIndex) {\n throw new Error('Largest Contenful Paint unexpectedly had no candidateIndex.');\n }\n const lcpTime = Types.Timing.MicroSeconds(event.ts - navigation.ts);\n const lcp = {\n event,\n metricName: MetricName.LCP,\n classification: scoreClassificationForLargestContentfulPaint(lcpTime),\n navigation,\n timing: lcpTime,\n };\n const metricsByNavigation = Platform.MapUtilities.getWithDefault(metricScoresByFrameId, frameId, () => new Map());\n const metrics = Platform.MapUtilities.getWithDefault(metricsByNavigation, navigationId, () => new Map());\n const lastLCPCandidate = metrics.get(MetricName.LCP);\n if (lastLCPCandidate === undefined) {\n selectedLCPCandidateEvents.add(lcp.event);\n storeMetricScore(frameId, navigationId, lcp);\n return;\n }\n const lastLCPCandidateEvent = lastLCPCandidate.event;\n\n if (!Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate(lastLCPCandidateEvent)) {\n return;\n }\n const lastCandidateIndex = lastLCPCandidateEvent.args.data?.candidateIndex;\n if (!lastCandidateIndex) {\n // lastCandidateIndex cannot be undefined because we don't store candidates with\n // with an undefined candidateIndex value. This check is only to make TypeScript\n // treat the field as not undefined below.\n return;\n }\n if (lastCandidateIndex < candidateIndex) {\n selectedLCPCandidateEvents.delete(lastLCPCandidateEvent);\n selectedLCPCandidateEvents.add(lcp.event);\n storeMetricScore(frameId, navigationId, lcp);\n }\n return;\n }\n if (Types.TraceEvents.isTraceEventLayoutShift(event)) {\n return;\n }\n return Platform.assertNever(event, `Unexpected event type: ${event}`);\n}\n\nfunction storeMetricScore(frameId: string, navigationId: string, metricScore: MetricScore): void {\n const metricsByNavigation = Platform.MapUtilities.getWithDefault(metricScoresByFrameId, frameId, () => new Map());\n const metrics = Platform.MapUtilities.getWithDefault(metricsByNavigation, navigationId, () => new Map());\n // If an entry with that metric name is present, delete it so that the new entry that\n // will replace it is added at the end of the map. This way we guarantee the map entries\n // are ordered in ASC manner by timestamp.\n metrics.delete(metricScore.metricName);\n metrics.set(metricScore.metricName, metricScore);\n}\n\nexport function getFrameIdForPageLoadEvent(event: Types.TraceEvents.PageLoadEvent): string {\n if (Types.TraceEvents.isTraceEventFirstContentfulPaint(event) ||\n Types.TraceEvents.isTraceEventInteractiveTime(event) ||\n Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate(event) ||\n Types.TraceEvents.isTraceEventNavigationStart(event) || Types.TraceEvents.isTraceEventLayoutShift(event) ||\n Types.TraceEvents.isTraceEventFirstPaint(event)) {\n return event.args.frame;\n }\n if (Types.TraceEvents.isTraceEventMarkDOMContent(event) || Types.TraceEvents.isTraceEventMarkLoad(event)) {\n const frameId = event.args.data?.frame;\n if (!frameId) {\n throw new Error('MarkDOMContent unexpectedly had no frame ID.');\n }\n return frameId;\n }\n Platform.assertNever(event, `Unexpected event type: ${event}`);\n}\n\nfunction getNavigationForPageLoadEvent(event: Types.TraceEvents.PageLoadEvent):\n Types.TraceEvents.TraceEventNavigationStart|null {\n if (Types.TraceEvents.isTraceEventFirstContentfulPaint(event) ||\n Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate(event) ||\n Types.TraceEvents.isTraceEventFirstPaint(event)) {\n const navigationId = event.args.data?.navigationId;\n if (!navigationId) {\n throw new Error('Trace event unexpectedly had no navigation ID.');\n }\n const {navigationsByNavigationId} = metaHandlerData();\n const navigation = navigationsByNavigationId.get(navigationId);\n\n if (!navigation) {\n // This event's navigation has been filtered out by the meta handler as a noise event.\n return null;\n }\n return navigation;\n }\n\n if (Types.TraceEvents.isTraceEventMarkDOMContent(event) || Types.TraceEvents.isTraceEventInteractiveTime(event) ||\n Types.TraceEvents.isTraceEventLayoutShift(event) || Types.TraceEvents.isTraceEventMarkLoad(event)) {\n const frameId = getFrameIdForPageLoadEvent(event);\n const {navigationsByFrameId} = metaHandlerData();\n return Helpers.Trace.getNavigationForTraceEvent(event, frameId, navigationsByFrameId);\n }\n\n if (Types.TraceEvents.isTraceEventNavigationStart(event)) {\n // We don't want to compute metrics of the navigation relative to itself, so we'll avoid avoid all that.\n return null;\n }\n\n return Platform.assertNever(event, `Unexpected event type: ${event}`);\n}\n\n/**\n * Classifications sourced from\n * https://web.dev/fcp/\n */\nexport function scoreClassificationForFirstContentfulPaint(fcpScoreInMicroseconds: Types.Timing.MicroSeconds):\n ScoreClassification {\n const FCP_GOOD_TIMING = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(1.8));\n const FCP_MEDIUM_TIMING = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(3.0));\n let scoreClassification = ScoreClassification.BAD;\n if (fcpScoreInMicroseconds <= FCP_MEDIUM_TIMING) {\n scoreClassification = ScoreClassification.OK;\n }\n if (fcpScoreInMicroseconds <= FCP_GOOD_TIMING) {\n scoreClassification = ScoreClassification.GOOD;\n }\n return scoreClassification;\n}\n\n/**\n * Classifications sourced from\n * https://web.dev/interactive/#how-lighthouse-determines-your-tti-score\n */\n\nexport function scoreClassificationForTimeToInteractive(ttiTimeInMicroseconds: Types.Timing.MicroSeconds):\n ScoreClassification {\n const TTI_GOOD_TIMING = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(3.8));\n const TTI_MEDIUM_TIMING = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(7.3));\n let scoreClassification = ScoreClassification.BAD;\n if (ttiTimeInMicroseconds <= TTI_MEDIUM_TIMING) {\n scoreClassification = ScoreClassification.OK;\n }\n if (ttiTimeInMicroseconds <= TTI_GOOD_TIMING) {\n scoreClassification = ScoreClassification.GOOD;\n }\n return scoreClassification;\n}\n\n/**\n * Classifications sourced from\n * https://web.dev/lcp/#what-is-lcp\n */\n\nexport function scoreClassificationForLargestContentfulPaint(lcpTimeInMicroseconds: Types.Timing.MicroSeconds):\n ScoreClassification {\n const LCP_GOOD_TIMING = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(2.5));\n const LCP_MEDIUM_TIMING = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(4));\n let scoreClassification = ScoreClassification.BAD;\n if (lcpTimeInMicroseconds <= LCP_MEDIUM_TIMING) {\n scoreClassification = ScoreClassification.OK;\n }\n if (lcpTimeInMicroseconds <= LCP_GOOD_TIMING) {\n scoreClassification = ScoreClassification.GOOD;\n }\n return scoreClassification;\n}\n\n/**\n * DCL does not have a classification.\n */\nexport function scoreClassificationForDOMContentLoaded(_dclTimeInMicroseconds: Types.Timing.MicroSeconds):\n ScoreClassification {\n return ScoreClassification.UNCLASSIFIED;\n}\n\n/**\n * Classifications sourced from\n * https://web.dev/lighthouse-total-blocking-#time/\n */\n\nexport function scoreClassificationForTotalBlockingTime(tbtTimeInMicroseconds: Types.Timing.MicroSeconds):\n ScoreClassification {\n const TBT_GOOD_TIMING = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(200));\n const TBT_MEDIUM_TIMING = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(600));\n let scoreClassification = ScoreClassification.BAD;\n if (tbtTimeInMicroseconds <= TBT_MEDIUM_TIMING) {\n scoreClassification = ScoreClassification.OK;\n }\n if (tbtTimeInMicroseconds <= TBT_GOOD_TIMING) {\n scoreClassification = ScoreClassification.GOOD;\n }\n return scoreClassification;\n}\n\n/**\n * Gets all the Largest Contentful Paint scores of all the frames in the\n * trace.\n */\nfunction gatherFinalLCPEvents(): Types.TraceEvents.PageLoadEvent[] {\n const allFinalLCPEvents: Types.TraceEvents.PageLoadEvent[] = [];\n const dataForAllFrames = [...metricScoresByFrameId.values()];\n const dataForAllNavigations = dataForAllFrames.flatMap(frameData => [...frameData.values()]);\n for (let i = 0; i < dataForAllNavigations.length; i++) {\n const navigationData = dataForAllNavigations[i];\n const lcpInNavigation = navigationData.get(MetricName.LCP);\n if (!lcpInNavigation || !lcpInNavigation.event) {\n continue;\n }\n\n allFinalLCPEvents.push(lcpInNavigation.event);\n }\n return allFinalLCPEvents;\n}\n\nexport async function finalize(): Promise {\n pageLoadEventsArray.sort((a, b) => a.ts - b.ts);\n\n for (const pageLoadEvent of pageLoadEventsArray) {\n const navigation = getNavigationForPageLoadEvent(pageLoadEvent);\n if (navigation) {\n // Event's navigation was not filtered out as noise.\n storePageLoadMetricAgainstNavigationId(navigation, pageLoadEvent);\n }\n }\n // NOTE: if you are looking for the TBT calculation, it has temporarily been\n // removed. See crbug.com/1424335 for details.\n const allFinalLCPEvents = gatherFinalLCPEvents();\n const mainFrame = metaHandlerData().mainFrameId;\n // Filter out LCP candidates to use only definitive LCP values\n const allEventsButLCP =\n pageLoadEventsArray.filter(event => !Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate(event));\n const markerEvents = [...allFinalLCPEvents, ...allEventsButLCP].filter(Types.TraceEvents.isTraceEventMarkerEvent);\n // Filter by main frame and sort.\n allMarkerEvents =\n markerEvents.filter(event => getFrameIdForPageLoadEvent(event) === mainFrame).sort((a, b) => a.ts - b.ts);\n}\n\nexport type PageLoadMetricsData = {\n /**\n * This represents the metric scores for all navigations, for all frames in a trace.\n * Given a frame id, the map points to another map from navigation id to metric scores.\n * The metric scores include the event related to the metric as well as the data regarding\n * the score itself.\n */\n metricScoresByFrameId: Map>>,\n /**\n * Page load events with no associated duration that happened in the\n * main frame.\n */\n allMarkerEvents: Types.TraceEvents.PageLoadEvent[],\n};\n\nexport function data(): PageLoadMetricsData {\n return {\n metricScoresByFrameId,\n allMarkerEvents,\n };\n}\n\nexport function deps(): TraceEventHandlerName[] {\n return ['Meta'];\n}\n\nexport const enum ScoreClassification {\n GOOD = 'good',\n OK = 'ok',\n BAD = 'bad',\n // Some metrics (such as DOMContentLoaded) don't have a Good/OK/Bad classification, hence this additional entry.\n UNCLASSIFIED = 'unclassified',\n}\n\nexport const enum MetricName {\n // First Contentful Paint\n FCP = 'FCP',\n // First Paint\n FP = 'FP',\n // MarkLoad\n L = 'L',\n LCP = 'LCP',\n // Mark DOM Content\n DCL = 'DCL',\n // Time To Interactive\n TTI = 'TTI',\n // Total Blocking Time\n TBT = 'TBT',\n // Cumulative Layout Shift\n CLS = 'CLS',\n // Note: INP is handled in UserInteractionsHandler\n}\n\nexport interface MetricScore {\n metricName: MetricName;\n classification: ScoreClassification;\n event?: Types.TraceEvents.PageLoadEvent;\n // The last navigation that occured before this metric score.\n navigation?: Types.TraceEvents.TraceEventNavigationStart;\n estimated?: boolean;\n timing: Types.Timing.MicroSeconds;\n}\n"]} \ No newline at end of file +{"version":3,"file":"PageLoadMetricsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/PageLoadMetricsHandler.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B;;;;;;;;;GASG;AAEH,OAAO,KAAK,QAAQ,MAAM,oCAAoC,CAAC;AAC/D,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAE3C,OAAO,EAAC,IAAI,IAAI,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAGzD;;;;;GAKG;AACH,MAAM,qBAAqB,GACvB,IAAI,GAAG,EAAwF,CAAC;AAEpG;;;GAGG;AACH,IAAI,eAAe,GAAiC,EAAE,CAAC;AAEvD,MAAM,UAAU,KAAK;IACnB,qBAAqB,CAAC,KAAK,EAAE,CAAC;IAC9B,mBAAmB,GAAG,EAAE,CAAC;IACzB,eAAe,GAAG,EAAE,CAAC;IACrB,0BAA0B,CAAC,KAAK,EAAE,CAAC;AACrC,CAAC;AAED,IAAI,mBAAmB,GAAiC,EAAE,CAAC;AAE3D,+EAA+E;AAC/E,4EAA4E;AAC5E,2EAA2E;AAC3E,2EAA2E;AAC3E,0EAA0E;AAC1E,yEAAyE;AACzE,8EAA8E;AAC9E,kDAAkD;AAClD,MAAM,0BAA0B,GAAG,IAAI,GAAG,EAAgD,CAAC;AAE3F,MAAM,UAAU,WAAW,CAAC,KAAyB;IACnD,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9C,OAAO;IACT,CAAC;IACD,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,sCAAsC,CAC3C,UAAwC,EAAE,KAAiC;IAC7E,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC;IACxD,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzE,CAAC;IACD,MAAM,OAAO,GAAG,0BAA0B,CAAC,KAAK,CAAC,CAAC;IAClD,MAAM,EAAC,wBAAwB,EAAC,GAAG,eAAe,EAAE,CAAC;IAErD,kEAAkE;IAClE,2EAA2E;IAC3E,2EAA2E;IAC3E,6EAA6E;IAC7E,4EAA4E;IAC5E,sDAAsD;IACtD,MAAM,wBAAwB,GAAG,wBAAwB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACvE,IAAI,CAAC,wBAAwB,EAAE,CAAC;QAC9B,OAAO;IACT,CAAC;IACD,MAAM,WAAW,GAAG,wBAAwB,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC5D,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1C,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,sBAAsB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/C,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;QACpE,MAAM,cAAc,GAAG,0CAA0C,CAAC,OAAO,CAAC,CAAC;QAC3E,MAAM,WAAW,GAAG,EAAC,KAAK,EAAE,UAAU,4BAAgB,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAAE,OAAO,EAAC,CAAC;QACrG,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;QACrD,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QACrC,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;QACtE,MAAM,cAAc,wDAAmC,CAAC;QACxD,MAAM,WAAW,GAAG,EAAC,KAAK,EAAE,UAAU,0BAAe,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,EAAE,SAAS,EAAC,CAAC;QACtG,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;QACrD,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;QACpE,MAAM,WAAW,GAAG;YAClB,KAAK;YACL,UAAU,4BAAgB;YAC1B,cAAc,EAAE,sCAAsC,CAAC,OAAO,CAAC;YAC/D,UAAU;YACV,MAAM,EAAE,OAAO;SAChB,CAAC;QACF,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;QACrD,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1C,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;QACrE,MAAM,GAAG,GAAG;YACV,KAAK;YACL,UAAU,4BAAgB;YAC1B,cAAc,EAAE,uCAAuC,CAAC,QAAQ,CAAC;YACjE,UAAU;YACV,MAAM,EAAE,QAAQ;SACjB,CAAC;QACF,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,CAAC,CAAC;QAE7C,MAAM,QAAQ,GACV,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC;QACjH,MAAM,GAAG,GAAG;YACV,KAAK;YACL,UAAU,4BAAgB;YAC1B,cAAc,EAAE,uCAAuC,CAAC,QAAQ,CAAC;YACjE,UAAU;YACV,MAAM,EAAE,QAAQ;SACjB,CAAC;QACF,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,CAAC,CAAC;QAC7C,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;QACrE,MAAM,WAAW,GAAG;YAClB,KAAK;YACL,UAAU,wBAAc;YACxB,cAAc,uDAAkC;YAChD,UAAU;YACV,MAAM,EAAE,QAAQ;SACjB,CAAC;QACF,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;QACrD,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,iCAAiC,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1D,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC;QACvD,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;QACjF,CAAC;QACD,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;QACpE,MAAM,GAAG,GAAG;YACV,KAAK;YACL,UAAU,4BAAgB;YAC1B,cAAc,EAAE,4CAA4C,CAAC,OAAO,CAAC;YACrE,UAAU;YACV,MAAM,EAAE,OAAO;SAChB,CAAC;QACF,MAAM,mBAAmB,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,qBAAqB,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;QAClH,MAAM,OAAO,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,mBAAmB,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;QACzG,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,4BAAgB,CAAC;QACrD,IAAI,gBAAgB,KAAK,SAAS,EAAE,CAAC;YACnC,0BAA0B,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAC1C,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,CAAC,CAAC;YAC7C,OAAO;QACT,CAAC;QACD,MAAM,qBAAqB,GAAG,gBAAgB,CAAC,KAAK,CAAC;QAErD,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,iCAAiC,CAAC,qBAAqB,CAAC,EAAE,CAAC;YAC3E,OAAO;QACT,CAAC;QACD,MAAM,kBAAkB,GAAG,qBAAqB,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC;QAC3E,IAAI,CAAC,kBAAkB,EAAE,CAAC;YACxB,gFAAgF;YAChF,gFAAgF;YAChF,0CAA0C;YAC1C,OAAO;QACT,CAAC;QACD,IAAI,kBAAkB,GAAG,cAAc,EAAE,CAAC;YACxC,0BAA0B,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC;YACzD,0BAA0B,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAC1C,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,CAAC,CAAC;QAC/C,CAAC;QACD,OAAO;IACT,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QACtC,OAAO;IACT,CAAC;IACD,OAAO,QAAQ,CAAC,WAAW,CAAC,KAAK,EAAE,0BAA0B,KAAK,EAAE,CAAC,CAAC;AACxE,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAe,EAAE,YAAoB,EAAE,WAAwB;IACvF,MAAM,mBAAmB,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,qBAAqB,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;IAClH,MAAM,OAAO,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,mBAAmB,EAAE,YAAY,EAAE,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;IACzG,qFAAqF;IACrF,wFAAwF;IACxF,0CAA0C;IAC1C,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,KAAiC;IAC1E,IAAI,KAAK,CAAC,MAAM,CAAC,sBAAsB,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,iBAAiB,CAAC,KAAK,CAAC;QACnF,KAAK,CAAC,MAAM,CAAC,iCAAiC,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,iBAAiB,CAAC,KAAK,CAAC;QAC9F,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1E,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;IAC1B,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3E,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC;QACvC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;QAClE,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IACD,QAAQ,CAAC,WAAW,CAAC,KAAK,EAAE,0BAA0B,KAAK,EAAE,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,6BAA6B,CAAC,KAAiC;IACtE,IAAI,KAAK,CAAC,MAAM,CAAC,sBAAsB,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,iCAAiC,CAAC,KAAK,CAAC;QACnG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QACrC,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC;QACnD,IAAI,CAAC,YAAY,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACpE,CAAC;QACD,MAAM,EAAC,yBAAyB,EAAC,GAAG,eAAe,EAAE,CAAC;QACtD,MAAM,UAAU,GAAG,yBAAyB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QAE/D,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,sFAAsF;YACtF,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,iBAAiB,CAAC,KAAK,CAAC;QAC7E,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACxE,MAAM,OAAO,GAAG,0BAA0B,CAAC,KAAK,CAAC,CAAC;QAClD,MAAM,EAAC,oBAAoB,EAAC,GAAG,eAAe,EAAE,CAAC;QACjD,OAAO,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,KAAK,EAAE,OAAO,EAAE,oBAAoB,CAAC,CAAC;IACxF,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,iBAAiB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1C,wGAAwG;QACxG,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,QAAQ,CAAC,WAAW,CAAC,KAAK,EAAE,0BAA0B,KAAK,EAAE,CAAC,CAAC;AACxE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,0CAA0C,CAAC,sBAAiD;IAE1G,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IACxF,MAAM,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1F,IAAI,mBAAmB,sCAA0B,CAAC;IAClD,IAAI,sBAAsB,IAAI,iBAAiB,EAAE,CAAC;QAChD,mBAAmB,oCAAyB,CAAC;IAC/C,CAAC;IACD,IAAI,sBAAsB,IAAI,eAAe,EAAE,CAAC;QAC9C,mBAAmB,wCAA2B,CAAC;IACjD,CAAC;IACD,OAAO,mBAAmB,CAAC;AAC7B,CAAC;AAED;;;GAGG;AAEH,MAAM,UAAU,uCAAuC,CAAC,qBAAgD;IAEtG,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IACxF,MAAM,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1F,IAAI,mBAAmB,sCAA0B,CAAC;IAClD,IAAI,qBAAqB,IAAI,iBAAiB,EAAE,CAAC;QAC/C,mBAAmB,oCAAyB,CAAC;IAC/C,CAAC;IACD,IAAI,qBAAqB,IAAI,eAAe,EAAE,CAAC;QAC7C,mBAAmB,wCAA2B,CAAC;IACjD,CAAC;IACD,OAAO,mBAAmB,CAAC;AAC7B,CAAC;AAED;;;GAGG;AAEH,MAAM,UAAU,4CAA4C,CAAC,qBAAgD;IAE3G,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;IACxF,MAAM,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACxF,IAAI,mBAAmB,sCAA0B,CAAC;IAClD,IAAI,qBAAqB,IAAI,iBAAiB,EAAE,CAAC;QAC/C,mBAAmB,oCAAyB,CAAC;IAC/C,CAAC;IACD,IAAI,qBAAqB,IAAI,eAAe,EAAE,CAAC;QAC7C,mBAAmB,wCAA2B,CAAC;IACjD,CAAC;IACD,OAAO,mBAAmB,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,sCAAsC,CAAC,sBAAiD;IAEtG,6DAAwC;AAC1C,CAAC;AAED;;;GAGG;AAEH,MAAM,UAAU,uCAAuC,CAAC,qBAAgD;IAEtG,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;IAClG,MAAM,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;IACpG,IAAI,mBAAmB,sCAA0B,CAAC;IAClD,IAAI,qBAAqB,IAAI,iBAAiB,EAAE,CAAC;QAC/C,mBAAmB,oCAAyB,CAAC;IAC/C,CAAC;IACD,IAAI,qBAAqB,IAAI,eAAe,EAAE,CAAC;QAC7C,mBAAmB,wCAA2B,CAAC;IACjD,CAAC;IACD,OAAO,mBAAmB,CAAC;AAC7B,CAAC;AAED;;;GAGG;AACH,SAAS,oBAAoB;IAC3B,MAAM,iBAAiB,GAAiC,EAAE,CAAC;IAC3D,MAAM,gBAAgB,GAAG,CAAC,GAAG,qBAAqB,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7D,MAAM,qBAAqB,GAAG,gBAAgB,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC7F,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,qBAAqB,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtD,MAAM,cAAc,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC;QAChD,MAAM,eAAe,GAAG,cAAc,CAAC,GAAG,4BAAgB,CAAC;QAC3D,IAAI,CAAC,eAAe,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;YAC/C,SAAS;QACX,CAAC;QAED,iBAAiB,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;IAEhD,KAAK,MAAM,aAAa,IAAI,mBAAmB,EAAE,CAAC;QAChD,MAAM,UAAU,GAAG,6BAA6B,CAAC,aAAa,CAAC,CAAC;QAChE,IAAI,UAAU,EAAE,CAAC;YACf,oDAAoD;YACpD,sCAAsC,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IACD,4EAA4E;IAC5E,8CAA8C;IAC9C,MAAM,iBAAiB,GAAG,oBAAoB,EAAE,CAAC;IACjD,MAAM,SAAS,GAAG,eAAe,EAAE,CAAC,WAAW,CAAC;IAChD,8DAA8D;IAC9D,MAAM,eAAe,GAAG,mBAAmB,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,iCAAiC,CAAC,KAAK,CAAC,CAAC,CAAC;IACpH,MAAM,YAAY,GAAG,CAAC,GAAG,iBAAiB,EAAE,GAAG,eAAe,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;IACnG,iCAAiC;IACjC,eAAe;QACX,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,0BAA0B,CAAC,KAAK,CAAC,KAAK,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;AAChH,CAAC;AAiBD,MAAM,UAAU,IAAI;IAClB,OAAO;QACL,qBAAqB;QACrB,eAAe;KAChB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,MAAM,CAAC,CAAC;AAClB,CAAC","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/**\n * This handler stores page load metrics, including web vitals,\n * and exports them in the shape of a map with the following shape:\n * Map(FrameId -> Map(navigationID -> metrics) )\n *\n * It also exports all markers in a trace in an array.\n *\n * Some metrics are taken directly from a page load events (AKA markers) like DCL.\n * Others require processing multiple events to be determined, like CLS and TBT.\n */\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {data as metaHandlerData} from './MetaHandler.js';\nimport {type HandlerName} from './types.js';\n\n/**\n * This represents the metric scores for all navigations, for all frames in a trace.\n * Given a frame id, the map points to another map from navigation id to metric scores.\n * The metric scores include the event related to the metric as well as the data regarding\n * the score itself.\n */\nconst metricScoresByFrameId =\n new Map>>();\n\n/**\n * Page load events with no associated duration that happened in the\n * main frame.\n */\nlet allMarkerEvents: Types.Events.PageLoadEvent[] = [];\n\nexport function reset(): void {\n metricScoresByFrameId.clear();\n pageLoadEventsArray = [];\n allMarkerEvents = [];\n selectedLCPCandidateEvents.clear();\n}\n\nlet pageLoadEventsArray: Types.Events.PageLoadEvent[] = [];\n\n// Once we've found the LCP events in the trace we want to fetch their DOM Node\n// from the backend. We could do this by parsing through our Map of frame =>\n// navigation => metric, but it's easier to keep a set of LCP events. As we\n// parse the trace, any time we store an LCP candidate as the potential LCP\n// event, we store the event here. If we later find a new candidate in the\n// trace, we store that and delete the prior event. When we've parsed the\n// entire trace this set will contain all the LCP events that were used - e.g.\n// the candidates that were the actual LCP events.\nconst selectedLCPCandidateEvents = new Set();\n\nexport function handleEvent(event: Types.Events.Event): void {\n if (!Types.Events.eventIsPageLoadEvent(event)) {\n return;\n }\n pageLoadEventsArray.push(event);\n}\n\nfunction storePageLoadMetricAgainstNavigationId(\n navigation: Types.Events.NavigationStart, event: Types.Events.PageLoadEvent): void {\n const navigationId = navigation.args.data?.navigationId;\n if (!navigationId) {\n throw new Error('Navigation event unexpectedly had no navigation ID.');\n }\n const frameId = getFrameIdForPageLoadEvent(event);\n const {rendererProcessesByFrame} = metaHandlerData();\n\n // If either of these pieces of data do not exist, the most likely\n // explanation is that the page load metric we found is for a frame/process\n // combo that the MetaHandler discarded. This typically happens if we get a\n // navigation event with an empty URL. Therefore, we will silently return and\n // drop this metric. If we didn't care about the navigation, we certainly do\n // not need to care about metrics for that navigation.\n const rendererProcessesInFrame = rendererProcessesByFrame.get(frameId);\n if (!rendererProcessesInFrame) {\n return;\n }\n const processData = rendererProcessesInFrame.get(event.pid);\n if (!processData) {\n return;\n }\n\n if (Types.Events.isNavigationStart(event)) {\n return;\n }\n\n if (Types.Events.isFirstContentfulPaint(event)) {\n const fcpTime = Types.Timing.MicroSeconds(event.ts - navigation.ts);\n const classification = scoreClassificationForFirstContentfulPaint(fcpTime);\n const metricScore = {event, metricName: MetricName.FCP, classification, navigation, timing: fcpTime};\n storeMetricScore(frameId, navigationId, metricScore);\n return;\n }\n\n if (Types.Events.isFirstPaint(event)) {\n const paintTime = Types.Timing.MicroSeconds(event.ts - navigation.ts);\n const classification = ScoreClassification.UNCLASSIFIED;\n const metricScore = {event, metricName: MetricName.FP, classification, navigation, timing: paintTime};\n storeMetricScore(frameId, navigationId, metricScore);\n return;\n }\n\n if (Types.Events.isMarkDOMContent(event)) {\n const dclTime = Types.Timing.MicroSeconds(event.ts - navigation.ts);\n const metricScore = {\n event,\n metricName: MetricName.DCL,\n classification: scoreClassificationForDOMContentLoaded(dclTime),\n navigation,\n timing: dclTime,\n };\n storeMetricScore(frameId, navigationId, metricScore);\n return;\n }\n\n if (Types.Events.isInteractiveTime(event)) {\n const ttiValue = Types.Timing.MicroSeconds(event.ts - navigation.ts);\n const tti = {\n event,\n metricName: MetricName.TTI,\n classification: scoreClassificationForTimeToInteractive(ttiValue),\n navigation,\n timing: ttiValue,\n };\n storeMetricScore(frameId, navigationId, tti);\n\n const tbtValue =\n Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(event.args.args.total_blocking_time_ms));\n const tbt = {\n event,\n metricName: MetricName.TBT,\n classification: scoreClassificationForTotalBlockingTime(tbtValue),\n navigation,\n timing: tbtValue,\n };\n storeMetricScore(frameId, navigationId, tbt);\n return;\n }\n\n if (Types.Events.isMarkLoad(event)) {\n const loadTime = Types.Timing.MicroSeconds(event.ts - navigation.ts);\n const metricScore = {\n event,\n metricName: MetricName.L,\n classification: ScoreClassification.UNCLASSIFIED,\n navigation,\n timing: loadTime,\n };\n storeMetricScore(frameId, navigationId, metricScore);\n return;\n }\n\n if (Types.Events.isLargestContentfulPaintCandidate(event)) {\n const candidateIndex = event.args.data?.candidateIndex;\n if (!candidateIndex) {\n throw new Error('Largest Contenful Paint unexpectedly had no candidateIndex.');\n }\n const lcpTime = Types.Timing.MicroSeconds(event.ts - navigation.ts);\n const lcp = {\n event,\n metricName: MetricName.LCP,\n classification: scoreClassificationForLargestContentfulPaint(lcpTime),\n navigation,\n timing: lcpTime,\n };\n const metricsByNavigation = Platform.MapUtilities.getWithDefault(metricScoresByFrameId, frameId, () => new Map());\n const metrics = Platform.MapUtilities.getWithDefault(metricsByNavigation, navigationId, () => new Map());\n const lastLCPCandidate = metrics.get(MetricName.LCP);\n if (lastLCPCandidate === undefined) {\n selectedLCPCandidateEvents.add(lcp.event);\n storeMetricScore(frameId, navigationId, lcp);\n return;\n }\n const lastLCPCandidateEvent = lastLCPCandidate.event;\n\n if (!Types.Events.isLargestContentfulPaintCandidate(lastLCPCandidateEvent)) {\n return;\n }\n const lastCandidateIndex = lastLCPCandidateEvent.args.data?.candidateIndex;\n if (!lastCandidateIndex) {\n // lastCandidateIndex cannot be undefined because we don't store candidates with\n // with an undefined candidateIndex value. This check is only to make TypeScript\n // treat the field as not undefined below.\n return;\n }\n if (lastCandidateIndex < candidateIndex) {\n selectedLCPCandidateEvents.delete(lastLCPCandidateEvent);\n selectedLCPCandidateEvents.add(lcp.event);\n storeMetricScore(frameId, navigationId, lcp);\n }\n return;\n }\n if (Types.Events.isLayoutShift(event)) {\n return;\n }\n return Platform.assertNever(event, `Unexpected event type: ${event}`);\n}\n\nfunction storeMetricScore(frameId: string, navigationId: string, metricScore: MetricScore): void {\n const metricsByNavigation = Platform.MapUtilities.getWithDefault(metricScoresByFrameId, frameId, () => new Map());\n const metrics = Platform.MapUtilities.getWithDefault(metricsByNavigation, navigationId, () => new Map());\n // If an entry with that metric name is present, delete it so that the new entry that\n // will replace it is added at the end of the map. This way we guarantee the map entries\n // are ordered in ASC manner by timestamp.\n metrics.delete(metricScore.metricName);\n metrics.set(metricScore.metricName, metricScore);\n}\n\nexport function getFrameIdForPageLoadEvent(event: Types.Events.PageLoadEvent): string {\n if (Types.Events.isFirstContentfulPaint(event) || Types.Events.isInteractiveTime(event) ||\n Types.Events.isLargestContentfulPaintCandidate(event) || Types.Events.isNavigationStart(event) ||\n Types.Events.isLayoutShift(event) || Types.Events.isFirstPaint(event)) {\n return event.args.frame;\n }\n if (Types.Events.isMarkDOMContent(event) || Types.Events.isMarkLoad(event)) {\n const frameId = event.args.data?.frame;\n if (!frameId) {\n throw new Error('MarkDOMContent unexpectedly had no frame ID.');\n }\n return frameId;\n }\n Platform.assertNever(event, `Unexpected event type: ${event}`);\n}\n\nfunction getNavigationForPageLoadEvent(event: Types.Events.PageLoadEvent): Types.Events.NavigationStart|null {\n if (Types.Events.isFirstContentfulPaint(event) || Types.Events.isLargestContentfulPaintCandidate(event) ||\n Types.Events.isFirstPaint(event)) {\n const navigationId = event.args.data?.navigationId;\n if (!navigationId) {\n throw new Error('Trace event unexpectedly had no navigation ID.');\n }\n const {navigationsByNavigationId} = metaHandlerData();\n const navigation = navigationsByNavigationId.get(navigationId);\n\n if (!navigation) {\n // This event's navigation has been filtered out by the meta handler as a noise event.\n return null;\n }\n return navigation;\n }\n\n if (Types.Events.isMarkDOMContent(event) || Types.Events.isInteractiveTime(event) ||\n Types.Events.isLayoutShift(event) || Types.Events.isMarkLoad(event)) {\n const frameId = getFrameIdForPageLoadEvent(event);\n const {navigationsByFrameId} = metaHandlerData();\n return Helpers.Trace.getNavigationForTraceEvent(event, frameId, navigationsByFrameId);\n }\n\n if (Types.Events.isNavigationStart(event)) {\n // We don't want to compute metrics of the navigation relative to itself, so we'll avoid avoid all that.\n return null;\n }\n\n return Platform.assertNever(event, `Unexpected event type: ${event}`);\n}\n\n/**\n * Classifications sourced from\n * https://web.dev/fcp/\n */\nexport function scoreClassificationForFirstContentfulPaint(fcpScoreInMicroseconds: Types.Timing.MicroSeconds):\n ScoreClassification {\n const FCP_GOOD_TIMING = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(1.8));\n const FCP_MEDIUM_TIMING = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(3.0));\n let scoreClassification = ScoreClassification.BAD;\n if (fcpScoreInMicroseconds <= FCP_MEDIUM_TIMING) {\n scoreClassification = ScoreClassification.OK;\n }\n if (fcpScoreInMicroseconds <= FCP_GOOD_TIMING) {\n scoreClassification = ScoreClassification.GOOD;\n }\n return scoreClassification;\n}\n\n/**\n * Classifications sourced from\n * https://web.dev/interactive/#how-lighthouse-determines-your-tti-score\n */\n\nexport function scoreClassificationForTimeToInteractive(ttiTimeInMicroseconds: Types.Timing.MicroSeconds):\n ScoreClassification {\n const TTI_GOOD_TIMING = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(3.8));\n const TTI_MEDIUM_TIMING = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(7.3));\n let scoreClassification = ScoreClassification.BAD;\n if (ttiTimeInMicroseconds <= TTI_MEDIUM_TIMING) {\n scoreClassification = ScoreClassification.OK;\n }\n if (ttiTimeInMicroseconds <= TTI_GOOD_TIMING) {\n scoreClassification = ScoreClassification.GOOD;\n }\n return scoreClassification;\n}\n\n/**\n * Classifications sourced from\n * https://web.dev/lcp/#what-is-lcp\n */\n\nexport function scoreClassificationForLargestContentfulPaint(lcpTimeInMicroseconds: Types.Timing.MicroSeconds):\n ScoreClassification {\n const LCP_GOOD_TIMING = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(2.5));\n const LCP_MEDIUM_TIMING = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(4));\n let scoreClassification = ScoreClassification.BAD;\n if (lcpTimeInMicroseconds <= LCP_MEDIUM_TIMING) {\n scoreClassification = ScoreClassification.OK;\n }\n if (lcpTimeInMicroseconds <= LCP_GOOD_TIMING) {\n scoreClassification = ScoreClassification.GOOD;\n }\n return scoreClassification;\n}\n\n/**\n * DCL does not have a classification.\n */\nexport function scoreClassificationForDOMContentLoaded(_dclTimeInMicroseconds: Types.Timing.MicroSeconds):\n ScoreClassification {\n return ScoreClassification.UNCLASSIFIED;\n}\n\n/**\n * Classifications sourced from\n * https://web.dev/lighthouse-total-blocking-#time/\n */\n\nexport function scoreClassificationForTotalBlockingTime(tbtTimeInMicroseconds: Types.Timing.MicroSeconds):\n ScoreClassification {\n const TBT_GOOD_TIMING = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(200));\n const TBT_MEDIUM_TIMING = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(600));\n let scoreClassification = ScoreClassification.BAD;\n if (tbtTimeInMicroseconds <= TBT_MEDIUM_TIMING) {\n scoreClassification = ScoreClassification.OK;\n }\n if (tbtTimeInMicroseconds <= TBT_GOOD_TIMING) {\n scoreClassification = ScoreClassification.GOOD;\n }\n return scoreClassification;\n}\n\n/**\n * Gets all the Largest Contentful Paint scores of all the frames in the\n * trace.\n */\nfunction gatherFinalLCPEvents(): Types.Events.PageLoadEvent[] {\n const allFinalLCPEvents: Types.Events.PageLoadEvent[] = [];\n const dataForAllFrames = [...metricScoresByFrameId.values()];\n const dataForAllNavigations = dataForAllFrames.flatMap(frameData => [...frameData.values()]);\n for (let i = 0; i < dataForAllNavigations.length; i++) {\n const navigationData = dataForAllNavigations[i];\n const lcpInNavigation = navigationData.get(MetricName.LCP);\n if (!lcpInNavigation || !lcpInNavigation.event) {\n continue;\n }\n\n allFinalLCPEvents.push(lcpInNavigation.event);\n }\n return allFinalLCPEvents;\n}\n\nexport async function finalize(): Promise {\n pageLoadEventsArray.sort((a, b) => a.ts - b.ts);\n\n for (const pageLoadEvent of pageLoadEventsArray) {\n const navigation = getNavigationForPageLoadEvent(pageLoadEvent);\n if (navigation) {\n // Event's navigation was not filtered out as noise.\n storePageLoadMetricAgainstNavigationId(navigation, pageLoadEvent);\n }\n }\n // NOTE: if you are looking for the TBT calculation, it has temporarily been\n // removed. See crbug.com/1424335 for details.\n const allFinalLCPEvents = gatherFinalLCPEvents();\n const mainFrame = metaHandlerData().mainFrameId;\n // Filter out LCP candidates to use only definitive LCP values\n const allEventsButLCP = pageLoadEventsArray.filter(event => !Types.Events.isLargestContentfulPaintCandidate(event));\n const markerEvents = [...allFinalLCPEvents, ...allEventsButLCP].filter(Types.Events.isMarkerEvent);\n // Filter by main frame and sort.\n allMarkerEvents =\n markerEvents.filter(event => getFrameIdForPageLoadEvent(event) === mainFrame).sort((a, b) => a.ts - b.ts);\n}\n\nexport type PageLoadMetricsData = {\n /**\n * This represents the metric scores for all navigations, for all frames in a trace.\n * Given a frame id, the map points to another map from navigation id to metric scores.\n * The metric scores include the event related to the metric as well as the data regarding\n * the score itself.\n */\n metricScoresByFrameId: Map>>,\n /**\n * Page load events with no associated duration that happened in the\n * main frame.\n */\n allMarkerEvents: Types.Events.PageLoadEvent[],\n};\n\nexport function data(): PageLoadMetricsData {\n return {\n metricScoresByFrameId,\n allMarkerEvents,\n };\n}\n\nexport function deps(): HandlerName[] {\n return ['Meta'];\n}\n\nexport const enum ScoreClassification {\n GOOD = 'good',\n OK = 'ok',\n BAD = 'bad',\n // Some metrics (such as DOMContentLoaded) don't have a Good/OK/Bad classification, hence this additional entry.\n UNCLASSIFIED = 'unclassified',\n}\n\nexport const enum MetricName {\n // First Contentful Paint\n FCP = 'FCP',\n // First Paint\n FP = 'FP',\n // MarkLoad\n L = 'L',\n LCP = 'LCP',\n // Mark DOM Content\n DCL = 'DCL',\n // Time To Interactive\n TTI = 'TTI',\n // Total Blocking Time\n TBT = 'TBT',\n // Cumulative Layout Shift\n CLS = 'CLS',\n // Note: INP is handled in UserInteractionsHandler\n}\n\nexport interface MetricScore {\n metricName: MetricName;\n classification: ScoreClassification;\n event?: Types.Events.PageLoadEvent;\n // The last navigation that occured before this metric score.\n navigation?: Types.Events.NavigationStart;\n estimated?: boolean;\n timing: Types.Timing.MicroSeconds;\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/PageLoadMetricsHandler.test.js b/public/models/trace/handlers/PageLoadMetricsHandler.test.js index f812551f4..15322f67c 100644 --- a/public/models/trace/handlers/PageLoadMetricsHandler.test.js +++ b/public/models/trace/handlers/PageLoadMetricsHandler.test.js @@ -3,7 +3,7 @@ // found in the LICENSE file. import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; -import * as TraceModel from '../trace.js'; +import * as Trace from '../trace.js'; function countMetricOcurrences(scoresByMetricName, metricName) { return scoresByMetricName.reduce((acc, val) => { if (val.get(metricName)) { @@ -15,8 +15,8 @@ function countMetricOcurrences(scoresByMetricName, metricName) { describeWithEnvironment('PageLoadMetricsHandler', function () { describe('contentful paints', () => { it('obtains all the FCP and LCP events for all frames', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz'); - const { Meta, PageLoadMetrics } = traceData; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz'); + const { Meta, PageLoadMetrics } = parsedTrace; const { mainFrameId } = Meta; const pageLoadMetricsData = PageLoadMetrics.metricScoresByFrameId; assert.strictEqual(pageLoadMetricsData.size, 3); @@ -28,14 +28,14 @@ describeWithEnvironment('PageLoadMetricsHandler', function () { // and one for the second. assert.strictEqual(pageLoadEventsForMainFrame.size, 2); const scoresByMetricName = [...pageLoadEventsForMainFrame.values()]; - const fcpCount = countMetricOcurrences(scoresByMetricName, "FCP" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP */); - const lcpCount = countMetricOcurrences(scoresByMetricName, "LCP" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP */); + const fcpCount = countMetricOcurrences(scoresByMetricName, "FCP" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP */); + const lcpCount = countMetricOcurrences(scoresByMetricName, "LCP" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP */); assert.strictEqual(fcpCount, 2); assert.strictEqual(lcpCount, 2); }); it('finds the right FCP and LCP events for a trace for a page that was refreshed', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'reload-and-trace-page.json.gz'); - const { Meta, PageLoadMetrics } = traceData; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'reload-and-trace-page.json.gz'); + const { Meta, PageLoadMetrics } = parsedTrace; const { mainFrameId } = Meta; const pageLoadMetricsData = PageLoadMetrics.metricScoresByFrameId; // Only one frame to deal with @@ -47,14 +47,14 @@ describeWithEnvironment('PageLoadMetricsHandler', function () { // Single FCP event that occured after the refresh. assert.strictEqual(pageLoadEventsForMainFrame.size, 1); const scoresByMetricName = [...pageLoadEventsForMainFrame.values()]; - const fcpCount = countMetricOcurrences(scoresByMetricName, "FCP" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP */); - const lcpCount = countMetricOcurrences(scoresByMetricName, "LCP" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP */); + const fcpCount = countMetricOcurrences(scoresByMetricName, "FCP" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP */); + const lcpCount = countMetricOcurrences(scoresByMetricName, "LCP" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP */); assert.strictEqual(fcpCount, 1); assert.strictEqual(lcpCount, 1); }); it('stores the navigation event as part of the metric', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'reload-and-trace-page.json.gz'); - const { Meta, PageLoadMetrics } = traceData; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'reload-and-trace-page.json.gz'); + const { Meta, PageLoadMetrics } = parsedTrace; const { mainFrameId, navigationsByFrameId } = Meta; const navigationBeforeMetrics = navigationsByFrameId.get(mainFrameId)?.[0]; const navigationId = navigationBeforeMetrics?.args.data?.navigationId; @@ -79,8 +79,8 @@ describeWithEnvironment('PageLoadMetricsHandler', function () { }); describe('markDOMContent frame', () => { it('obtains them and assigns them to the correct frames', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz'); - const { Meta, PageLoadMetrics } = traceData; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz'); + const { Meta, PageLoadMetrics } = parsedTrace; const { mainFrameId } = Meta; const pageLoadMetricsData = PageLoadMetrics.metricScoresByFrameId; // We expect 3 frames: main frame, and two iframes. @@ -92,7 +92,7 @@ describeWithEnvironment('PageLoadMetricsHandler', function () { // There are 2 MarkDOMContent events on the main frame: one for the first navigation, // and one for the second. assert.strictEqual(pageLoadEventsForMainFrame.size, 2); - const dclCount = countMetricOcurrences([...pageLoadEventsForMainFrame.values()], "DCL" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.DCL */); + const dclCount = countMetricOcurrences([...pageLoadEventsForMainFrame.values()], "DCL" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.DCL */); assert.strictEqual(dclCount, 2); }); }); @@ -107,8 +107,8 @@ describeWithEnvironment('PageLoadMetricsHandler', function () { const firstNavigationId = '05059ACF683224E6FC7E344F544A4050'; const secondNavigationId = '550FC08C662EF691E1535F305CBC0FCA'; beforeEach(async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz'); - const { Meta, PageLoadMetrics } = traceData; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz'); + const { Meta, PageLoadMetrics } = parsedTrace; const pageLoadMetricsData = PageLoadMetrics.metricScoresByFrameId.get(Meta.mainFrameId); if (!pageLoadMetricsData) { assert.fail('Page load events for main frame were unexpectedly undefined.'); @@ -117,53 +117,53 @@ describeWithEnvironment('PageLoadMetricsHandler', function () { allMetricScores = scoresByMetricName.flatMap(metricScores => [...metricScores.values()]); }); it('extracts DOMContentLoaded correctly', () => { - const domContentLoadedMetrics = getMetricsByName("DCL" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.DCL */); + const domContentLoadedMetrics = getMetricsByName("DCL" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.DCL */); assert.strictEqual(domContentLoadedMetrics[0].timing, 34520); - assert.strictEqual(domContentLoadedMetrics[0].classification, "unclassified" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.UNCLASSIFIED */); + assert.strictEqual(domContentLoadedMetrics[0].classification, "unclassified" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.UNCLASSIFIED */); assertMetricNavigationId(domContentLoadedMetrics[0], firstNavigationId); assert.strictEqual(domContentLoadedMetrics[1].timing, 40401); - assert.strictEqual(domContentLoadedMetrics[1].classification, "unclassified" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.UNCLASSIFIED */); + assert.strictEqual(domContentLoadedMetrics[1].classification, "unclassified" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.UNCLASSIFIED */); assertMetricNavigationId(domContentLoadedMetrics[1], secondNavigationId); }); it('extracts First Contentful Paint correctly', () => { - const firstContentfulPaints = getMetricsByName("FCP" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP */); + const firstContentfulPaints = getMetricsByName("FCP" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP */); assert.strictEqual(firstContentfulPaints[0].timing, 37269); - assert.strictEqual(firstContentfulPaints[0].classification, "good" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.GOOD */); + assert.strictEqual(firstContentfulPaints[0].classification, "good" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.GOOD */); assertMetricNavigationId(firstContentfulPaints[0], firstNavigationId); assert.strictEqual(firstContentfulPaints[1].timing, 42390); - assert.strictEqual(firstContentfulPaints[1].classification, "good" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.GOOD */); + assert.strictEqual(firstContentfulPaints[1].classification, "good" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.GOOD */); assertMetricNavigationId(firstContentfulPaints[1], secondNavigationId); }); it('extracts Largest Contentful Paint correctly', () => { - const firstContentfulPaints = getMetricsByName("LCP" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP */); + const firstContentfulPaints = getMetricsByName("LCP" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP */); assert.strictEqual(firstContentfulPaints[0].timing, 37271); - assert.strictEqual(firstContentfulPaints[0].classification, "good" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.GOOD */); + assert.strictEqual(firstContentfulPaints[0].classification, "good" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.GOOD */); assertMetricNavigationId(firstContentfulPaints[0], firstNavigationId); assert.strictEqual(firstContentfulPaints[1].timing, 42391); - assert.strictEqual(firstContentfulPaints[1].classification, "good" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.GOOD */); + assert.strictEqual(firstContentfulPaints[1].classification, "good" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.GOOD */); assertMetricNavigationId(firstContentfulPaints[1], secondNavigationId); }); it('extracts First Paint correctly', () => { - const firstContentfulPaints = getMetricsByName("FP" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FP */); + const firstContentfulPaints = getMetricsByName("FP" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FP */); assert.strictEqual(firstContentfulPaints[0].timing, 37269); - assert.strictEqual(firstContentfulPaints[0].classification, "unclassified" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.UNCLASSIFIED */); + assert.strictEqual(firstContentfulPaints[0].classification, "unclassified" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.UNCLASSIFIED */); assertMetricNavigationId(firstContentfulPaints[0], firstNavigationId); assert.strictEqual(firstContentfulPaints[1].timing, 42389); - assert.strictEqual(firstContentfulPaints[1].classification, "unclassified" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.UNCLASSIFIED */); + assert.strictEqual(firstContentfulPaints[1].classification, "unclassified" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.UNCLASSIFIED */); assertMetricNavigationId(firstContentfulPaints[1], secondNavigationId); }); it('extracts Load correctly', () => { - const firstContentfulPaints = getMetricsByName("L" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.L */); + const firstContentfulPaints = getMetricsByName("L" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.L */); assert.strictEqual(firstContentfulPaints[0].timing, 148980); - assert.strictEqual(firstContentfulPaints[0].classification, "unclassified" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.UNCLASSIFIED */); + assert.strictEqual(firstContentfulPaints[0].classification, "unclassified" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.UNCLASSIFIED */); assertMetricNavigationId(firstContentfulPaints[0], firstNavigationId); assert.strictEqual(firstContentfulPaints[1].timing, 161333); - assert.strictEqual(firstContentfulPaints[1].classification, "unclassified" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.UNCLASSIFIED */); + assert.strictEqual(firstContentfulPaints[1].classification, "unclassified" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.UNCLASSIFIED */); assertMetricNavigationId(firstContentfulPaints[1], secondNavigationId); }); it('provides metric scores sorted in ASC order by their events\' timestamps', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz'); - const { Meta, PageLoadMetrics } = traceData; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz'); + const { Meta, PageLoadMetrics } = parsedTrace; const pageLoadMetricsData = PageLoadMetrics.metricScoresByFrameId.get(Meta.mainFrameId); if (!pageLoadMetricsData) { assert.fail('Page load events for main frame were unexpectedly null.'); @@ -186,8 +186,8 @@ describeWithEnvironment('PageLoadMetricsHandler', function () { }); describe('FLEDGE fenced frames', () => { it('is able to parse a trace containing fenced frames without erroring', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'fenced-frame-fledge.json.gz'); - const { PageLoadMetrics } = traceData; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'fenced-frame-fledge.json.gz'); + const { PageLoadMetrics } = parsedTrace; assert.strictEqual(PageLoadMetrics.metricScoresByFrameId.size, 3); }); }); @@ -195,29 +195,29 @@ describeWithEnvironment('PageLoadMetricsHandler', function () { let mainFrameId; let allMarkerEvents; beforeEach(async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz'); - const { PageLoadMetrics, Meta } = traceData; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz'); + const { PageLoadMetrics, Meta } = parsedTrace; mainFrameId = Meta.mainFrameId; allMarkerEvents = PageLoadMetrics.allMarkerEvents; }); it('extracts all marker events from a trace correctly', () => { - for (const metricName of TraceModel.Types.TraceEvents.MarkerName) { + for (const metricName of Trace.Types.Events.MarkerName) { const markerEventsOfThisType = allMarkerEvents.filter(event => event.name === metricName); // There should be 2 events for each marker and all of them should correspond to the main frame assert.strictEqual(markerEventsOfThisType.length, 2); - assert.isTrue(markerEventsOfThisType.every(marker => TraceModel.Handlers.ModelHandlers.PageLoadMetrics.getFrameIdForPageLoadEvent(marker) === mainFrameId)); + assert.isTrue(markerEventsOfThisType.every(marker => Trace.Handlers.ModelHandlers.PageLoadMetrics.getFrameIdForPageLoadEvent(marker) === mainFrameId)); } }); it('only marker events are exported in allMarkerEvents', () => { for (const marker of allMarkerEvents) { - assert.isTrue(TraceModel.Types.TraceEvents.isTraceEventMarkerEvent(marker)); + assert.isTrue(Trace.Types.Events.isMarkerEvent(marker)); } }); it('only stores the largest contentful paint with the highest candidate index', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'multiple-lcp-main-frame.json.gz'); - const { PageLoadMetrics } = traceData; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'multiple-lcp-main-frame.json.gz'); + const { PageLoadMetrics } = parsedTrace; const pageLoadMarkers = PageLoadMetrics.allMarkerEvents; - const largestContentfulPaints = pageLoadMarkers.filter(TraceModel.Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate); + const largestContentfulPaints = pageLoadMarkers.filter(Trace.Types.Events.isLargestContentfulPaintCandidate); assert.strictEqual(largestContentfulPaints.length, 1); assert.strictEqual(largestContentfulPaints[0].args.data?.candidateIndex, 2); }); diff --git a/public/models/trace/handlers/PageLoadMetricsHandler.test.js.map b/public/models/trace/handlers/PageLoadMetricsHandler.test.js.map index 032a97079..1ac7e4cb5 100644 --- a/public/models/trace/handlers/PageLoadMetricsHandler.test.js.map +++ b/public/models/trace/handlers/PageLoadMetricsHandler.test.js.map @@ -1 +1 @@ -{"version":3,"file":"PageLoadMetricsHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/PageLoadMetricsHandler.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as TraceModel from '../trace.js';\n\nfunction countMetricOcurrences(\n scoresByMetricName:\n Map[],\n metricName: TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName): number {\n return scoresByMetricName.reduce((acc, val) => {\n if (val.get(metricName)) {\n return acc + 1;\n }\n return acc;\n }, 0);\n}\n\ndescribeWithEnvironment('PageLoadMetricsHandler', function() {\n describe('contentful paints', () => {\n it('obtains all the FCP and LCP events for all frames', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz');\n const {Meta, PageLoadMetrics} = traceData;\n const {mainFrameId} = Meta;\n const pageLoadMetricsData = PageLoadMetrics.metricScoresByFrameId;\n assert.strictEqual(pageLoadMetricsData.size, 3);\n\n const pageLoadEventsForMainFrame = pageLoadMetricsData.get(mainFrameId);\n if (!pageLoadEventsForMainFrame) {\n assert.fail('Page load events for main frame were unexpectedly null.');\n }\n\n // There are 2 FCP events and 2 LCP events on the main frame: one for the first navigation,\n // and one for the second.\n assert.strictEqual(pageLoadEventsForMainFrame.size, 2);\n const scoresByMetricName = [...pageLoadEventsForMainFrame.values()];\n\n const fcpCount =\n countMetricOcurrences(scoresByMetricName, TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP);\n\n const lcpCount =\n countMetricOcurrences(scoresByMetricName, TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP);\n\n assert.strictEqual(fcpCount, 2);\n assert.strictEqual(lcpCount, 2);\n });\n\n it('finds the right FCP and LCP events for a trace for a page that was refreshed', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'reload-and-trace-page.json.gz');\n const {Meta, PageLoadMetrics} = traceData;\n const {mainFrameId} = Meta;\n const pageLoadMetricsData = PageLoadMetrics.metricScoresByFrameId;\n // Only one frame to deal with\n assert.strictEqual(pageLoadMetricsData.size, 1);\n\n const pageLoadEventsForMainFrame = pageLoadMetricsData.get(mainFrameId);\n if (!pageLoadEventsForMainFrame) {\n assert.fail('Page load events for main frame were unexpectedly null.');\n }\n // Single FCP event that occured after the refresh.\n assert.strictEqual(pageLoadEventsForMainFrame.size, 1);\n const scoresByMetricName = [...pageLoadEventsForMainFrame.values()];\n const fcpCount =\n countMetricOcurrences(scoresByMetricName, TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP);\n const lcpCount =\n countMetricOcurrences(scoresByMetricName, TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP);\n assert.strictEqual(fcpCount, 1);\n assert.strictEqual(lcpCount, 1);\n });\n\n it('stores the navigation event as part of the metric', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'reload-and-trace-page.json.gz');\n const {Meta, PageLoadMetrics} = traceData;\n const {mainFrameId, navigationsByFrameId} = Meta;\n const navigationBeforeMetrics = navigationsByFrameId.get(mainFrameId)?.[0];\n const navigationId = navigationBeforeMetrics?.args.data?.navigationId;\n if (!navigationBeforeMetrics || !navigationId) {\n assert.fail('Could not find expected navigation event or its navigation ID');\n }\n const pageLoadMetricsData = PageLoadMetrics.metricScoresByFrameId;\n // Only one frame to deal with\n assert.strictEqual(pageLoadMetricsData.size, 1);\n\n const pageLoadEventsForMainFrame = pageLoadMetricsData.get(mainFrameId);\n if (!pageLoadEventsForMainFrame) {\n assert.fail('Page load events for main frame were unexpectedly null.');\n }\n // Single FCP event that occured after the refresh.\n assert.strictEqual(pageLoadEventsForMainFrame.size, 1);\n const events = pageLoadEventsForMainFrame.get(navigationId);\n const allFoundMetricScoresForMainFrame = events ? Array.from(events.values()) : [];\n for (const score of allFoundMetricScoresForMainFrame) {\n assert.strictEqual(score.navigation, navigationBeforeMetrics);\n }\n });\n });\n\n describe('markDOMContent frame', () => {\n it('obtains them and assigns them to the correct frames', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz');\n const {Meta, PageLoadMetrics} = traceData;\n const {mainFrameId} = Meta;\n const pageLoadMetricsData = PageLoadMetrics.metricScoresByFrameId;\n // We expect 3 frames: main frame, and two iframes.\n assert.strictEqual(pageLoadMetricsData.size, 3);\n const pageLoadEventsForMainFrame = pageLoadMetricsData.get(mainFrameId);\n if (!pageLoadEventsForMainFrame) {\n assert.fail('Page load events for main frame were unexpectedly null.');\n }\n // There are 2 MarkDOMContent events on the main frame: one for the first navigation,\n // and one for the second.\n assert.strictEqual(pageLoadEventsForMainFrame.size, 2);\n const dclCount = countMetricOcurrences(\n [...pageLoadEventsForMainFrame.values()], TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.DCL);\n assert.strictEqual(dclCount, 2);\n });\n });\n\n describe('metric scores', () => {\n let allMetricScores: TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricScore[];\n\n function getMetricsByName(name: TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName) {\n return allMetricScores.filter(metric => metric.metricName === name);\n }\n function assertMetricNavigationId(\n metric: TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricScore, navigationId: string) {\n assert.strictEqual(metric.navigation?.args.data?.navigationId, navigationId);\n }\n const firstNavigationId = '05059ACF683224E6FC7E344F544A4050';\n const secondNavigationId = '550FC08C662EF691E1535F305CBC0FCA';\n beforeEach(async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz');\n const {Meta, PageLoadMetrics} = traceData;\n const pageLoadMetricsData = PageLoadMetrics.metricScoresByFrameId.get(Meta.mainFrameId);\n if (!pageLoadMetricsData) {\n assert.fail('Page load events for main frame were unexpectedly undefined.');\n }\n const scoresByMetricName = [...pageLoadMetricsData.values()];\n allMetricScores = scoresByMetricName.flatMap(metricScores => [...metricScores.values()]);\n });\n it('extracts DOMContentLoaded correctly', () => {\n const domContentLoadedMetrics =\n getMetricsByName(TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.DCL);\n assert.strictEqual(domContentLoadedMetrics[0].timing, 34520);\n assert.strictEqual(\n domContentLoadedMetrics[0].classification,\n TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.UNCLASSIFIED);\n assertMetricNavigationId(domContentLoadedMetrics[0], firstNavigationId);\n\n assert.strictEqual(domContentLoadedMetrics[1].timing, 40401);\n assert.strictEqual(\n domContentLoadedMetrics[1].classification,\n TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.UNCLASSIFIED);\n assertMetricNavigationId(domContentLoadedMetrics[1], secondNavigationId);\n });\n\n it('extracts First Contentful Paint correctly', () => {\n const firstContentfulPaints = getMetricsByName(TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP);\n assert.strictEqual(firstContentfulPaints[0].timing, 37269);\n assert.strictEqual(\n firstContentfulPaints[0].classification,\n TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.GOOD);\n assertMetricNavigationId(firstContentfulPaints[0], firstNavigationId);\n\n assert.strictEqual(firstContentfulPaints[1].timing, 42390);\n assert.strictEqual(\n firstContentfulPaints[1].classification,\n TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.GOOD);\n assertMetricNavigationId(firstContentfulPaints[1], secondNavigationId);\n });\n\n it('extracts Largest Contentful Paint correctly', () => {\n const firstContentfulPaints = getMetricsByName(TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP);\n assert.strictEqual(firstContentfulPaints[0].timing, 37271);\n assert.strictEqual(\n firstContentfulPaints[0].classification,\n TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.GOOD);\n assertMetricNavigationId(firstContentfulPaints[0], firstNavigationId);\n\n assert.strictEqual(firstContentfulPaints[1].timing, 42391);\n assert.strictEqual(\n firstContentfulPaints[1].classification,\n TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.GOOD);\n assertMetricNavigationId(firstContentfulPaints[1], secondNavigationId);\n });\n\n it('extracts First Paint correctly', () => {\n const firstContentfulPaints = getMetricsByName(TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FP);\n assert.strictEqual(firstContentfulPaints[0].timing, 37269);\n assert.strictEqual(\n firstContentfulPaints[0].classification,\n TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.UNCLASSIFIED);\n assertMetricNavigationId(firstContentfulPaints[0], firstNavigationId);\n\n assert.strictEqual(firstContentfulPaints[1].timing, 42389);\n assert.strictEqual(\n firstContentfulPaints[1].classification,\n TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.UNCLASSIFIED);\n assertMetricNavigationId(firstContentfulPaints[1], secondNavigationId);\n });\n\n it('extracts Load correctly', () => {\n const firstContentfulPaints = getMetricsByName(TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.L);\n assert.strictEqual(firstContentfulPaints[0].timing, 148980);\n assert.strictEqual(\n firstContentfulPaints[0].classification,\n TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.UNCLASSIFIED);\n assertMetricNavigationId(firstContentfulPaints[0], firstNavigationId);\n\n assert.strictEqual(firstContentfulPaints[1].timing, 161333);\n assert.strictEqual(\n firstContentfulPaints[1].classification,\n TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.UNCLASSIFIED);\n assertMetricNavigationId(firstContentfulPaints[1], secondNavigationId);\n });\n\n it('provides metric scores sorted in ASC order by their events\\' timestamps', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz');\n const {Meta, PageLoadMetrics} = traceData;\n\n const pageLoadMetricsData = PageLoadMetrics.metricScoresByFrameId.get(Meta.mainFrameId);\n if (!pageLoadMetricsData) {\n assert.fail('Page load events for main frame were unexpectedly null.');\n }\n\n const scoresByMetricName = [...pageLoadMetricsData.values()];\n const flatResults = scoresByMetricName.map(metricScores => [...metricScores.values()])\n .reduce((acc, metricScore) => acc.concat(metricScore), []);\n const timestamps = [];\n for (const metricScore of flatResults) {\n if (metricScore.event) {\n timestamps.push(metricScore.event.ts);\n }\n }\n let previousTimestamp = timestamps[0];\n for (let i = 1; i < timestamps.length; i++) {\n assert.isAtLeast(timestamps[i], previousTimestamp);\n previousTimestamp = timestamps[i];\n }\n });\n });\n\n describe('FLEDGE fenced frames', () => {\n it('is able to parse a trace containing fenced frames without erroring', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'fenced-frame-fledge.json.gz');\n const {PageLoadMetrics} = traceData;\n assert.strictEqual(PageLoadMetrics.metricScoresByFrameId.size, 3);\n });\n });\n\n describe('Marker events', () => {\n let mainFrameId: string;\n let allMarkerEvents: TraceModel.Types.TraceEvents.PageLoadEvent[];\n beforeEach(async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz');\n const {PageLoadMetrics, Meta} = traceData;\n mainFrameId = Meta.mainFrameId;\n allMarkerEvents = PageLoadMetrics.allMarkerEvents;\n });\n it('extracts all marker events from a trace correctly', () => {\n for (const metricName of TraceModel.Types.TraceEvents.MarkerName) {\n const markerEventsOfThisType = allMarkerEvents.filter(event => event.name === metricName);\n // There should be 2 events for each marker and all of them should correspond to the main frame\n assert.strictEqual(markerEventsOfThisType.length, 2);\n assert.isTrue(markerEventsOfThisType.every(\n marker =>\n TraceModel.Handlers.ModelHandlers.PageLoadMetrics.getFrameIdForPageLoadEvent(marker) === mainFrameId));\n }\n });\n it('only marker events are exported in allMarkerEvents', () => {\n for (const marker of allMarkerEvents) {\n assert.isTrue(TraceModel.Types.TraceEvents.isTraceEventMarkerEvent(marker));\n }\n });\n\n it('only stores the largest contentful paint with the highest candidate index', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'multiple-lcp-main-frame.json.gz');\n const {PageLoadMetrics} = traceData;\n const pageLoadMarkers = PageLoadMetrics.allMarkerEvents;\n const largestContentfulPaints =\n pageLoadMarkers.filter(TraceModel.Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate);\n assert.strictEqual(largestContentfulPaints.length, 1);\n assert.strictEqual(largestContentfulPaints[0].args.data?.candidateIndex, 2);\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"PageLoadMetricsHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/PageLoadMetricsHandler.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Trace from '../trace.js';\n\nfunction countMetricOcurrences(\n scoresByMetricName:\n Map[],\n metricName: Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName): number {\n return scoresByMetricName.reduce((acc, val) => {\n if (val.get(metricName)) {\n return acc + 1;\n }\n return acc;\n }, 0);\n}\n\ndescribeWithEnvironment('PageLoadMetricsHandler', function() {\n describe('contentful paints', () => {\n it('obtains all the FCP and LCP events for all frames', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz');\n const {Meta, PageLoadMetrics} = parsedTrace;\n const {mainFrameId} = Meta;\n const pageLoadMetricsData = PageLoadMetrics.metricScoresByFrameId;\n assert.strictEqual(pageLoadMetricsData.size, 3);\n\n const pageLoadEventsForMainFrame = pageLoadMetricsData.get(mainFrameId);\n if (!pageLoadEventsForMainFrame) {\n assert.fail('Page load events for main frame were unexpectedly null.');\n }\n\n // There are 2 FCP events and 2 LCP events on the main frame: one for the first navigation,\n // and one for the second.\n assert.strictEqual(pageLoadEventsForMainFrame.size, 2);\n const scoresByMetricName = [...pageLoadEventsForMainFrame.values()];\n\n const fcpCount =\n countMetricOcurrences(scoresByMetricName, Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP);\n\n const lcpCount =\n countMetricOcurrences(scoresByMetricName, Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP);\n\n assert.strictEqual(fcpCount, 2);\n assert.strictEqual(lcpCount, 2);\n });\n\n it('finds the right FCP and LCP events for a trace for a page that was refreshed', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'reload-and-trace-page.json.gz');\n const {Meta, PageLoadMetrics} = parsedTrace;\n const {mainFrameId} = Meta;\n const pageLoadMetricsData = PageLoadMetrics.metricScoresByFrameId;\n // Only one frame to deal with\n assert.strictEqual(pageLoadMetricsData.size, 1);\n\n const pageLoadEventsForMainFrame = pageLoadMetricsData.get(mainFrameId);\n if (!pageLoadEventsForMainFrame) {\n assert.fail('Page load events for main frame were unexpectedly null.');\n }\n // Single FCP event that occured after the refresh.\n assert.strictEqual(pageLoadEventsForMainFrame.size, 1);\n const scoresByMetricName = [...pageLoadEventsForMainFrame.values()];\n const fcpCount =\n countMetricOcurrences(scoresByMetricName, Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP);\n const lcpCount =\n countMetricOcurrences(scoresByMetricName, Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP);\n assert.strictEqual(fcpCount, 1);\n assert.strictEqual(lcpCount, 1);\n });\n\n it('stores the navigation event as part of the metric', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'reload-and-trace-page.json.gz');\n const {Meta, PageLoadMetrics} = parsedTrace;\n const {mainFrameId, navigationsByFrameId} = Meta;\n const navigationBeforeMetrics = navigationsByFrameId.get(mainFrameId)?.[0];\n const navigationId = navigationBeforeMetrics?.args.data?.navigationId;\n if (!navigationBeforeMetrics || !navigationId) {\n assert.fail('Could not find expected navigation event or its navigation ID');\n }\n const pageLoadMetricsData = PageLoadMetrics.metricScoresByFrameId;\n // Only one frame to deal with\n assert.strictEqual(pageLoadMetricsData.size, 1);\n\n const pageLoadEventsForMainFrame = pageLoadMetricsData.get(mainFrameId);\n if (!pageLoadEventsForMainFrame) {\n assert.fail('Page load events for main frame were unexpectedly null.');\n }\n // Single FCP event that occured after the refresh.\n assert.strictEqual(pageLoadEventsForMainFrame.size, 1);\n const events = pageLoadEventsForMainFrame.get(navigationId);\n const allFoundMetricScoresForMainFrame = events ? Array.from(events.values()) : [];\n for (const score of allFoundMetricScoresForMainFrame) {\n assert.strictEqual(score.navigation, navigationBeforeMetrics);\n }\n });\n });\n\n describe('markDOMContent frame', () => {\n it('obtains them and assigns them to the correct frames', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz');\n const {Meta, PageLoadMetrics} = parsedTrace;\n const {mainFrameId} = Meta;\n const pageLoadMetricsData = PageLoadMetrics.metricScoresByFrameId;\n // We expect 3 frames: main frame, and two iframes.\n assert.strictEqual(pageLoadMetricsData.size, 3);\n const pageLoadEventsForMainFrame = pageLoadMetricsData.get(mainFrameId);\n if (!pageLoadEventsForMainFrame) {\n assert.fail('Page load events for main frame were unexpectedly null.');\n }\n // There are 2 MarkDOMContent events on the main frame: one for the first navigation,\n // and one for the second.\n assert.strictEqual(pageLoadEventsForMainFrame.size, 2);\n const dclCount = countMetricOcurrences(\n [...pageLoadEventsForMainFrame.values()], Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.DCL);\n assert.strictEqual(dclCount, 2);\n });\n });\n\n describe('metric scores', () => {\n let allMetricScores: Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricScore[];\n\n function getMetricsByName(name: Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName) {\n return allMetricScores.filter(metric => metric.metricName === name);\n }\n function assertMetricNavigationId(\n metric: Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricScore, navigationId: string) {\n assert.strictEqual(metric.navigation?.args.data?.navigationId, navigationId);\n }\n const firstNavigationId = '05059ACF683224E6FC7E344F544A4050';\n const secondNavigationId = '550FC08C662EF691E1535F305CBC0FCA';\n beforeEach(async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz');\n const {Meta, PageLoadMetrics} = parsedTrace;\n const pageLoadMetricsData = PageLoadMetrics.metricScoresByFrameId.get(Meta.mainFrameId);\n if (!pageLoadMetricsData) {\n assert.fail('Page load events for main frame were unexpectedly undefined.');\n }\n const scoresByMetricName = [...pageLoadMetricsData.values()];\n allMetricScores = scoresByMetricName.flatMap(metricScores => [...metricScores.values()]);\n });\n it('extracts DOMContentLoaded correctly', () => {\n const domContentLoadedMetrics = getMetricsByName(Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.DCL);\n assert.strictEqual(domContentLoadedMetrics[0].timing, 34520);\n assert.strictEqual(\n domContentLoadedMetrics[0].classification,\n Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.UNCLASSIFIED);\n assertMetricNavigationId(domContentLoadedMetrics[0], firstNavigationId);\n\n assert.strictEqual(domContentLoadedMetrics[1].timing, 40401);\n assert.strictEqual(\n domContentLoadedMetrics[1].classification,\n Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.UNCLASSIFIED);\n assertMetricNavigationId(domContentLoadedMetrics[1], secondNavigationId);\n });\n\n it('extracts First Contentful Paint correctly', () => {\n const firstContentfulPaints = getMetricsByName(Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP);\n assert.strictEqual(firstContentfulPaints[0].timing, 37269);\n assert.strictEqual(\n firstContentfulPaints[0].classification,\n Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.GOOD);\n assertMetricNavigationId(firstContentfulPaints[0], firstNavigationId);\n\n assert.strictEqual(firstContentfulPaints[1].timing, 42390);\n assert.strictEqual(\n firstContentfulPaints[1].classification,\n Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.GOOD);\n assertMetricNavigationId(firstContentfulPaints[1], secondNavigationId);\n });\n\n it('extracts Largest Contentful Paint correctly', () => {\n const firstContentfulPaints = getMetricsByName(Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP);\n assert.strictEqual(firstContentfulPaints[0].timing, 37271);\n assert.strictEqual(\n firstContentfulPaints[0].classification,\n Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.GOOD);\n assertMetricNavigationId(firstContentfulPaints[0], firstNavigationId);\n\n assert.strictEqual(firstContentfulPaints[1].timing, 42391);\n assert.strictEqual(\n firstContentfulPaints[1].classification,\n Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.GOOD);\n assertMetricNavigationId(firstContentfulPaints[1], secondNavigationId);\n });\n\n it('extracts First Paint correctly', () => {\n const firstContentfulPaints = getMetricsByName(Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FP);\n assert.strictEqual(firstContentfulPaints[0].timing, 37269);\n assert.strictEqual(\n firstContentfulPaints[0].classification,\n Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.UNCLASSIFIED);\n assertMetricNavigationId(firstContentfulPaints[0], firstNavigationId);\n\n assert.strictEqual(firstContentfulPaints[1].timing, 42389);\n assert.strictEqual(\n firstContentfulPaints[1].classification,\n Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.UNCLASSIFIED);\n assertMetricNavigationId(firstContentfulPaints[1], secondNavigationId);\n });\n\n it('extracts Load correctly', () => {\n const firstContentfulPaints = getMetricsByName(Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.L);\n assert.strictEqual(firstContentfulPaints[0].timing, 148980);\n assert.strictEqual(\n firstContentfulPaints[0].classification,\n Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.UNCLASSIFIED);\n assertMetricNavigationId(firstContentfulPaints[0], firstNavigationId);\n\n assert.strictEqual(firstContentfulPaints[1].timing, 161333);\n assert.strictEqual(\n firstContentfulPaints[1].classification,\n Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.UNCLASSIFIED);\n assertMetricNavigationId(firstContentfulPaints[1], secondNavigationId);\n });\n\n it('provides metric scores sorted in ASC order by their events\\' timestamps', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz');\n const {Meta, PageLoadMetrics} = parsedTrace;\n\n const pageLoadMetricsData = PageLoadMetrics.metricScoresByFrameId.get(Meta.mainFrameId);\n if (!pageLoadMetricsData) {\n assert.fail('Page load events for main frame were unexpectedly null.');\n }\n\n const scoresByMetricName = [...pageLoadMetricsData.values()];\n const flatResults = scoresByMetricName.map(metricScores => [...metricScores.values()])\n .reduce((acc, metricScore) => acc.concat(metricScore), []);\n const timestamps = [];\n for (const metricScore of flatResults) {\n if (metricScore.event) {\n timestamps.push(metricScore.event.ts);\n }\n }\n let previousTimestamp = timestamps[0];\n for (let i = 1; i < timestamps.length; i++) {\n assert.isAtLeast(timestamps[i], previousTimestamp);\n previousTimestamp = timestamps[i];\n }\n });\n });\n\n describe('FLEDGE fenced frames', () => {\n it('is able to parse a trace containing fenced frames without erroring', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'fenced-frame-fledge.json.gz');\n const {PageLoadMetrics} = parsedTrace;\n assert.strictEqual(PageLoadMetrics.metricScoresByFrameId.size, 3);\n });\n });\n\n describe('Marker events', () => {\n let mainFrameId: string;\n let allMarkerEvents: Trace.Types.Events.PageLoadEvent[];\n beforeEach(async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz');\n const {PageLoadMetrics, Meta} = parsedTrace;\n mainFrameId = Meta.mainFrameId;\n allMarkerEvents = PageLoadMetrics.allMarkerEvents;\n });\n it('extracts all marker events from a trace correctly', () => {\n for (const metricName of Trace.Types.Events.MarkerName) {\n const markerEventsOfThisType = allMarkerEvents.filter(event => event.name === metricName);\n // There should be 2 events for each marker and all of them should correspond to the main frame\n assert.strictEqual(markerEventsOfThisType.length, 2);\n assert.isTrue(markerEventsOfThisType.every(\n marker => Trace.Handlers.ModelHandlers.PageLoadMetrics.getFrameIdForPageLoadEvent(marker) === mainFrameId));\n }\n });\n it('only marker events are exported in allMarkerEvents', () => {\n for (const marker of allMarkerEvents) {\n assert.isTrue(Trace.Types.Events.isMarkerEvent(marker));\n }\n });\n\n it('only stores the largest contentful paint with the highest candidate index', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'multiple-lcp-main-frame.json.gz');\n const {PageLoadMetrics} = parsedTrace;\n const pageLoadMarkers = PageLoadMetrics.allMarkerEvents;\n const largestContentfulPaints = pageLoadMarkers.filter(Trace.Types.Events.isLargestContentfulPaintCandidate);\n assert.strictEqual(largestContentfulPaints.length, 1);\n assert.strictEqual(largestContentfulPaints[0].args.data?.candidateIndex, 2);\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/RendererHandler.d.ts b/public/models/trace/handlers/RendererHandler.d.ts index fdf30dc13..338b7d719 100644 --- a/public/models/trace/handlers/RendererHandler.d.ts +++ b/public/models/trace/handlers/RendererHandler.d.ts @@ -1,11 +1,11 @@ import * as Helpers from '../helpers/helpers.js'; import * as Types from '../types/types.js'; import { type FrameProcessData } from './MetaHandler.js'; -import { type TraceEventHandlerName } from './types.js'; +import { type HandlerName } from './types.js'; export declare function handleUserConfig(userConfig: Types.Configuration.Configuration): void; export declare function reset(): void; export declare function initialize(): void; -export declare function handleEvent(event: Types.TraceEvents.TraceEventData): void; +export declare function handleEvent(event: Types.Events.Event): void; export declare function finalize(): Promise; export declare function data(): RendererHandlerData; /** @@ -14,34 +14,34 @@ export declare function data(): RendererHandlerData; * collecting each one of their threads' name. This meta handler's data is * assigned to the renderer handler's data. */ -export declare function assignMeta(processes: Map, mainFrameId: string, rendererProcessesByFrame: FrameProcessData, threadsInProcess: Map>): void; +export declare function assignMeta(processes: Map, mainFrameId: string, rendererProcessesByFrame: FrameProcessData, threadsInProcess: Map>): void; /** * Assigns origins to all threads in all processes. * @see assignMeta */ -export declare function assignOrigin(processes: Map, rendererProcessesByFrame: FrameProcessData): void; +export declare function assignOrigin(processes: Map, rendererProcessesByFrame: FrameProcessData): void; /** * Assigns whether or not a thread is the main frame to all threads in all processes. * @see assignMeta */ -export declare function assignIsMainFrame(processes: Map, mainFrameId: string, rendererProcessesByFrame: FrameProcessData): void; +export declare function assignIsMainFrame(processes: Map, mainFrameId: string, rendererProcessesByFrame: FrameProcessData): void; /** * Assigns the thread name to all threads in all processes. * @see assignMeta */ -export declare function assignThreadName(processes: Map, rendererProcessesByFrame: FrameProcessData, threadsInProcess: Map>): void; +export declare function assignThreadName(processes: Map, rendererProcessesByFrame: FrameProcessData, threadsInProcess: Map>): void; /** * Removes unneeded trace data opportunistically stored while handling events. * This currently does the following: * - Deletes processes with an unkonwn origin. */ -export declare function sanitizeProcesses(processes: Map): void; +export declare function sanitizeProcesses(processes: Map): void; /** * Removes unneeded trace data opportunistically stored while handling events. * This currently does the following: * - Deletes threads with no roots. */ -export declare function sanitizeThreads(processes: Map): void; +export declare function sanitizeThreads(processes: Map): void; /** * Creates a hierarchical structure from the trace events. Each thread in each * process will contribute to their own individual hierarchy. @@ -64,31 +64,31 @@ export declare function sanitizeThreads(processes: Map, options?: { +export declare function buildHierarchy(processes: Map, options?: { filter: { - has: (name: Types.TraceEvents.KnownEventName) => boolean; + has: (name: Types.Events.Name) => boolean; }; }): void; -export declare function makeCompleteEvent(event: Types.TraceEvents.TraceEventBegin | Types.TraceEvents.TraceEventEnd): Types.TraceEvents.SyntheticCompleteEvent | null; -export declare function deps(): TraceEventHandlerName[]; +export declare function makeCompleteEvent(event: Types.Events.Begin | Types.Events.End): Types.Events.SyntheticComplete | null; +export declare function deps(): HandlerName[]; export interface RendererHandlerData { - processes: Map; + processes: Map; /** * A map of all compositor workers (which we show in the UI as Rasterizers) * by the process ID. */ - compositorTileWorkers: Map; - entryToNode: Map; + compositorTileWorkers: Map; + entryToNode: Map; /** * All trace events and synthetic profile calls made from * samples. */ - allTraceEntries: Types.TraceEvents.TraceEventData[]; + allTraceEntries: Types.Events.Event[]; } export interface RendererProcess { url: string | null; isOnMainFrame: boolean; - threads: Map; + threads: Map; } export interface RendererThread { name: string | null; @@ -96,7 +96,7 @@ export interface RendererThread { * Contains trace events and synthetic profile calls made from * samples. */ - entries: Types.TraceEvents.TraceEventData[]; - profileCalls: Types.TraceEvents.SyntheticProfileCall[]; + entries: Types.Events.Event[]; + profileCalls: Types.Events.SyntheticProfileCall[]; tree?: Helpers.TreeHelpers.TraceEntryTree; } diff --git a/public/models/trace/handlers/RendererHandler.js b/public/models/trace/handlers/RendererHandler.js index 65e9e07c1..7afe049bd 100644 --- a/public/models/trace/handlers/RendererHandler.js +++ b/public/models/trace/handlers/RendererHandler.js @@ -65,13 +65,13 @@ export function handleEvent(event) { if (handlerState !== 2 /* HandlerState.INITIALIZED */) { throw new Error('Renderer Handler is not initialized'); } - if (Types.TraceEvents.isThreadName(event) && event.args.name?.startsWith('CompositorTileWorker')) { + if (Types.Events.isThreadName(event) && event.args.name?.startsWith('CompositorTileWorker')) { compositorTileWorkers.push({ pid: event.pid, tid: event.tid, }); } - if (Types.TraceEvents.isTraceEventBegin(event) || Types.TraceEvents.isTraceEventEnd(event)) { + if (Types.Events.isBegin(event) || Types.Events.isEnd(event)) { const process = getOrCreateRendererProcess(processes, event.pid); const thread = getOrCreateRendererThread(process, event.tid); const completeEvent = makeCompleteEvent(event); @@ -82,7 +82,7 @@ export function handleEvent(event) { allTraceEntries.push(completeEvent); return; } - if (Types.TraceEvents.isTraceEventInstant(event) || Types.TraceEvents.isTraceEventComplete(event)) { + if (Types.Events.isInstant(event) || Types.Events.isComplete(event)) { const process = getOrCreateRendererProcess(processes, event.pid); const thread = getOrCreateRendererThread(process, event.tid); thread.entries.push(event); @@ -305,7 +305,7 @@ export function buildHierarchy(processes, options) { } } export function makeCompleteEvent(event) { - if (Types.TraceEvents.isTraceEventEnd(event)) { + if (Types.Events.isEnd(event)) { // Quietly ignore unbalanced close events, they're legit (we could // have missed start one). const beginEvent = completeEventStack.pop(); @@ -326,7 +326,7 @@ export function makeCompleteEvent(event) { // matching end event later we will update its duration. const syntheticComplete = { ...event, - ph: "X" /* Types.TraceEvents.Phase.COMPLETE */, + ph: "X" /* Types.Events.Phase.COMPLETE */, dur: Types.Timing.MicroSeconds(0), }; completeEventStack.push(syntheticComplete); diff --git a/public/models/trace/handlers/RendererHandler.js.map b/public/models/trace/handlers/RendererHandler.js.map index 2bbbfd236..cfadca62b 100644 --- a/public/models/trace/handlers/RendererHandler.js.map +++ b/public/models/trace/handlers/RendererHandler.js.map @@ -1 +1 @@ -{"version":3,"file":"RendererHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/RendererHandler.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,QAAQ,MAAM,oCAAoC,CAAC;AAC/D,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAE3C,OAAO,EAAC,IAAI,IAAI,mBAAmB,EAAC,MAAM,6BAA6B,CAAC;AACxE,OAAO,EAAC,IAAI,IAAI,eAAe,EAAwB,MAAM,kBAAkB,CAAC;AAChF,OAAO,EAAC,IAAI,IAAI,kBAAkB,EAAC,MAAM,qBAAqB,CAAC;AAG/D;;;;;;;;;;GAUG;AAEH,MAAM,SAAS,GAAG,IAAI,GAAG,EAAgD,CAAC;AAE1E,+EAA+E;AAC/E,8EAA8E;AAC9E,yEAAyE;AACzE,MAAM,qBAAqB,GAAG,KAAK,EAG/B,CAAC;AACL,MAAM,WAAW,GAA8E,IAAI,GAAG,EAAE,CAAC;AACzG,IAAI,eAAe,GAAuC,EAAE,CAAC;AAE7D,MAAM,kBAAkB,GAAiD,EAAE,CAAC;AAE5E,IAAI,YAAY,qCAA6B,CAAC;AAC9C,IAAI,MAAM,GAAsC,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC;AAE/E,MAAM,mBAAmB,GAAG,GAAoB,EAAE,CAAC,CAAC;IAClD,GAAG,EAAE,IAAI;IACT,aAAa,EAAE,KAAK;IACpB,OAAO,EAAE,IAAI,GAAG,EAAE;CACnB,CAAC,CAAC;AAEH,MAAM,kBAAkB,GAAG,GAAmB,EAAE,CAAC,CAAC;IAChD,IAAI,EAAE,IAAI;IACV,OAAO,EAAE,EAAE;IACX,YAAY,EAAE,EAAE;CACjB,CAAC,CAAC;AAEH,MAAM,0BAA0B,GAC5B,CAAC,SAA4D,EAAE,GAAgC,EAC3E,EAAE;IAChB,OAAO,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,SAAS,EAAE,GAAG,EAAE,mBAAmB,CAAC,CAAC;AACnF,CAAC,CAAC;AAEV,MAAM,yBAAyB,GAAG,CAAC,OAAwB,EAAE,GAA+B,EAAkB,EAAE;IAC9G,OAAO,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,kBAAkB,CAAC,CAAC;AACxF,CAAC,CAAC;AAEF,MAAM,UAAU,gBAAgB,CAAC,UAA6C;IAC5E,MAAM,GAAG,UAAU,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,KAAK;IACnB,SAAS,CAAC,KAAK,EAAE,CAAC;IAClB,WAAW,CAAC,KAAK,EAAE,CAAC;IACpB,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC;IAC3B,kBAAkB,CAAC,MAAM,GAAG,CAAC,CAAC;IAC9B,qBAAqB,CAAC,MAAM,GAAG,CAAC,CAAC;IACjC,YAAY,qCAA6B,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,IAAI,YAAY,uCAA+B,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpD,CAAC;IAED,YAAY,mCAA2B,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAuC;IACjE,IAAI,YAAY,qCAA6B,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IAED,IAAI,KAAK,CAAC,WAAW,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,CAAC,sBAAsB,CAAC,EAAE,CAAC;QACjG,qBAAqB,CAAC,IAAI,CAAC;YACzB,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,GAAG,EAAE,KAAK,CAAC,GAAG;SACf,CAAC,CAAC;IACL,CAAC;IAED,IAAI,KAAK,CAAC,WAAW,CAAC,iBAAiB,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,WAAW,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3F,MAAM,OAAO,GAAG,0BAA0B,CAAC,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QACjE,MAAM,MAAM,GAAG,yBAAyB,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAC7D,MAAM,aAAa,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAC/C,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,OAAO;QACT,CAAC;QACD,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACnC,eAAe,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACpC,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,WAAW,CAAC,mBAAmB,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,WAAW,CAAC,oBAAoB,CAAC,KAAK,CAAC,EAAE,CAAC;QAClG,MAAM,OAAO,GAAG,0BAA0B,CAAC,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QACjE,MAAM,MAAM,GAAG,yBAAyB,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;QAC7D,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3B,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,IAAI,YAAY,qCAA6B,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IACzD,CAAC;IAED,MAAM,EAAC,WAAW,EAAE,wBAAwB,EAAE,gBAAgB,EAAC,GAAG,eAAe,EAAE,CAAC;IACpF,UAAU,CAAC,SAAS,EAAE,WAAW,EAAE,wBAAwB,EAAE,gBAAgB,CAAC,CAAC;IAC/E,iBAAiB,CAAC,SAAS,CAAC,CAAC;IAC7B,cAAc,CAAC,SAAS,CAAC,CAAC;IAC1B,eAAe,CAAC,SAAS,CAAC,CAAC;IAC3B,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,eAAe,CAAC,CAAC;IACtD,YAAY,iCAAyB,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,IAAI;IAClB,IAAI,YAAY,mCAA2B,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvD,CAAC;IAED,OAAO;QACL,SAAS,EAAE,IAAI,GAAG,CAAC,SAAS,CAAC;QAC7B,qBAAqB,EAAE,IAAI,GAAG,CAAC,uBAAuB,EAAE,CAAC;QACzD,WAAW,EAAE,IAAI,GAAG,CAAC,WAAW,CAAC;QACjC,eAAe,EAAE,CAAC,GAAG,eAAe,CAAC;KACtC,CAAC;AACJ,CAAC;AAED,SAAS,uBAAuB;IAC9B,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAA6D,CAAC;IAC9F,KAAK,MAAM,MAAM,IAAI,qBAAqB,EAAE,CAAC;QAC3C,MAAM,SAAS,GAAG,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;QACzD,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC3B,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CACtB,SAA4D,EAAE,WAAmB,EACjF,wBAA0C,EAC1C,gBAC6G;IAE/G,YAAY,CAAC,SAAS,EAAE,wBAAwB,CAAC,CAAC;IAClD,iBAAiB,CAAC,SAAS,EAAE,WAAW,EAAE,wBAAwB,CAAC,CAAC;IACpE,gBAAgB,CAAC,SAAS,EAAE,wBAAwB,EAAE,gBAAgB,CAAC,CAAC;AAC1E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CACxB,SAA4D,EAAE,wBAA0C;IAC1G,KAAK,MAAM,oBAAoB,IAAI,wBAAwB,CAAC,MAAM,EAAE,EAAE,CAAC;QACrE,KAAK,MAAM,CAAC,GAAG,EAAE,cAAc,CAAC,IAAI,oBAAoB,EAAE,CAAC;YACzD,KAAK,MAAM,WAAW,IAAI,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC;gBAChD,MAAM,OAAO,GAAG,0BAA0B,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;gBAC3D,oEAAoE;gBACpE,uEAAuE;gBACvE,wEAAwE;gBACxE,wEAAwE;gBACxE,qEAAqE;gBACrE,uCAAuC;gBACvC,IAAI,OAAO,CAAC,GAAG,KAAK,IAAI,IAAI,OAAO,CAAC,GAAG,KAAK,aAAa,EAAE,CAAC;oBAC1D,2FAA2F;oBAC3F,4FAA4F;oBAC5F,uDAAuD;oBACvD,IAAI,CAAC;wBACH,IAAI,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;wBAC/B,OAAO,CAAC,GAAG,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC;oBACtC,CAAC;oBAAC,OAAO,CAAC,EAAE,CAAC;wBACX,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC;oBACrB,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAC7B,SAA4D,EAAE,WAAmB,EACjF,wBAA0C;IAC5C,KAAK,MAAM,CAAC,OAAO,EAAE,oBAAoB,CAAC,IAAI,wBAAwB,EAAE,CAAC;QACvE,KAAK,MAAM,CAAC,GAAG,CAAC,IAAI,oBAAoB,EAAE,CAAC;YACzC,MAAM,OAAO,GAAG,0BAA0B,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;YAC3D,wEAAwE;YACxE,yEAAyE;YACzE,yEAAyE;YACzE,6DAA6D;YAC7D,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;gBAC5B,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC5B,SAA4D,EAAE,wBAA0C,EACxG,gBAC6G;IAE/G,KAAK,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,SAAS,EAAE,CAAC;QACvC,KAAK,MAAM,CAAC,GAAG,EAAE,UAAU,CAAC,IAAI,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC;YAChE,MAAM,MAAM,GAAG,yBAAyB,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;YACvD,MAAM,CAAC,IAAI,GAAG,UAAU,EAAE,IAAI,CAAC,IAAI,IAAI,GAAG,GAAG,EAAE,CAAC;QAClD,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAA4D;IAC5F,MAAM,eAAe,GAAG,mBAAmB,EAAE,CAAC,QAAQ,CAAC;IACvD,MAAM,QAAQ,GAAG,eAAe,EAAE,CAAC;IACnC,IAAI,QAAQ,CAAC,cAAc,EAAE,CAAC;QAC5B,OAAO;IACT,CAAC;IACD,KAAK,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,SAAS,EAAE,CAAC;QACvC,4EAA4E;QAC5E,oEAAoE;QACpE,yEAAyE;QACzE,0EAA0E;QAC1E,EAAE;QACF,mEAAmE;QACnE,wEAAwE;QACxE,yEAAyE;QACzE,0EAA0E;QAC1E,qBAAqB;QACrB,IAAI,OAAO,CAAC,GAAG,KAAK,IAAI,EAAE,CAAC;YACzB,MAAM,YAAY,GAAG,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC9C,IAAI,YAAY,EAAE,CAAC;gBACjB,OAAO,CAAC,GAAG,GAAG,YAAY,CAAC,IAAI,CAAC;YAClC,CAAC;iBAAM,CAAC;gBACN,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACxB,CAAC;YACD,SAAS;QACX,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,SAA4D;IAC1F,KAAK,MAAM,CAAC,EAAE,OAAO,CAAC,IAAI,SAAS,EAAE,CAAC;QACpC,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YAC5C,qEAAqE;YACrE,wEAAwE;YACxE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;gBAC7B,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,cAAc,CAC1B,SAA4D,EAC5D,OAA8E;IAChF,MAAM,WAAW,GAAG,kBAAkB,EAAE,CAAC;IACzC,KAAK,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,SAAS,EAAE,CAAC;QACvC,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YAC5C,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;gBAC3B,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,uBAAuB,EAAE,CAAC;gBAC5D,SAAS;YACX,CAAC;YACD,4BAA4B;YAC5B,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACrD,4CAA4C;YAC5C,MAAM,oBAAoB,GAAG,WAAW,CAAC,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;YAC9E,IAAI,oBAAoB,EAAE,CAAC;gBACzB,MAAM,UAAU,GAAG,oBAAoB,CAAC,aAAa,CAAC;gBACtD,MAAM,iBAAiB,GAAG,UAAU;oBAChC,IAAI,OAAO,CAAC,iBAAiB,CAAC,iBAAiB,CAC3C,UAAU,EAAE,oBAAoB,CAAC,SAAS,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;gBACtE,MAAM,YAAY,GAAG,iBAAiB,EAAE,iBAAiB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBAC1E,IAAI,iBAAiB,IAAI,YAAY,EAAE,CAAC;oBACtC,eAAe,GAAG,CAAC,GAAG,eAAe,EAAE,GAAG,YAAY,CAAC,CAAC;oBACxD,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,MAAM,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;oBAChF,MAAM,CAAC,YAAY,GAAG,YAAY,CAAC;oBACnC,qEAAqE;oBACrE,MAAM,SAAS,GAAG,iBAAiB,CAAC,cAAc,CAAC;oBACnD,IAAI,SAAS,EAAE,CAAC;wBACd,eAAe,GAAG,CAAC,GAAG,eAAe,EAAE,GAAG,SAAS,CAAC,CAAC;wBACrD,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,kBAAkB,CAAC,MAAM,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;oBAC/E,CAAC;gBACH,CAAC;YACH,CAAC;YACD,0BAA0B;YAC1B,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACrE,MAAM,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;YAC5B,+DAA+D;YAC/D,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;gBACjD,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YAC/B,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAC+B;IAC/D,IAAI,KAAK,CAAC,WAAW,CAAC,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7C,kEAAkE;QAClE,0BAA0B;QAC1B,MAAM,UAAU,GAAG,kBAAkB,CAAC,GAAG,EAAE,CAAC;QAC5C,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,UAAU,CAAC,IAAI,KAAK,KAAK,CAAC,IAAI,IAAI,UAAU,CAAC,GAAG,KAAK,KAAK,CAAC,GAAG,EAAE,CAAC;YACnE,OAAO,CAAC,KAAK,CACT,+BAA+B,GAAG,UAAU,CAAC,EAAE,GAAG,IAAI,GAAG,UAAU,CAAC,IAAI,GAAG,QAAQ,GAAG,KAAK,CAAC,EAAE,GAAG,IAAI;gBACrG,KAAK,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC;YACtB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,mEAAmE;QACnE,SAAS;QACT,UAAU,CAAC,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;QACrE,OAAO,IAAI,CAAC;IACd,CAAC;IAED,mEAAmE;IACnE,wDAAwD;IACxD,MAAM,iBAAiB,GAA6C;QAClE,GAAG,KAAK;QACR,EAAE,4CAAkC;QACpC,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;KAClC,CAAC;IAEF,kBAAkB,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IAC3C,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,MAAM,EAAE,SAAS,EAAE,iBAAiB,CAAC,CAAC;AAChD,CAAC","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {data as auctionWorkletsData} from './AuctionWorkletsHandler.js';\nimport {data as metaHandlerData, type FrameProcessData} from './MetaHandler.js';\nimport {data as samplesHandlerData} from './SamplesHandler.js';\nimport {HandlerState, type TraceEventHandlerName} from './types.js';\n\n/**\n * This handler builds the hierarchy of trace events and profile calls\n * on each thread on each process.\n *\n * Throughout the code, trace events and profile calls are referred to\n * as \"entries\", but note they are different types of data. Trace events\n * come directly from the backend and it's the type the engine commonly\n * refers to. Profile calls on the other hand are built in the frontend,\n * and, for compatibility purposes, typed as an extension to the trace\n * event type.\n */\n\nconst processes = new Map();\n\n// We track the compositor tile worker thread name events so that at the end we\n// can return these keyed by the process ID. These are used in the frontend to\n// show the user the rasterization thread(s) on the main frame as tracks.\nconst compositorTileWorkers = Array<{\n pid: Types.TraceEvents.ProcessID,\n tid: Types.TraceEvents.ThreadID,\n}>();\nconst entryToNode: Map = new Map();\nlet allTraceEntries: Types.TraceEvents.TraceEventData[] = [];\n\nconst completeEventStack: (Types.TraceEvents.SyntheticCompleteEvent)[] = [];\n\nlet handlerState = HandlerState.UNINITIALIZED;\nlet config: Types.Configuration.Configuration = Types.Configuration.defaults();\n\nconst makeRendererProcess = (): RendererProcess => ({\n url: null,\n isOnMainFrame: false,\n threads: new Map(),\n});\n\nconst makeRendererThread = (): RendererThread => ({\n name: null,\n entries: [],\n profileCalls: [],\n});\n\nconst getOrCreateRendererProcess =\n (processes: Map, pid: Types.TraceEvents.ProcessID):\n RendererProcess => {\n return Platform.MapUtilities.getWithDefault(processes, pid, makeRendererProcess);\n };\n\nconst getOrCreateRendererThread = (process: RendererProcess, tid: Types.TraceEvents.ThreadID): RendererThread => {\n return Platform.MapUtilities.getWithDefault(process.threads, tid, makeRendererThread);\n};\n\nexport function handleUserConfig(userConfig: Types.Configuration.Configuration): void {\n config = userConfig;\n}\n\nexport function reset(): void {\n processes.clear();\n entryToNode.clear();\n allTraceEntries.length = 0;\n completeEventStack.length = 0;\n compositorTileWorkers.length = 0;\n handlerState = HandlerState.UNINITIALIZED;\n}\n\nexport function initialize(): void {\n if (handlerState !== HandlerState.UNINITIALIZED) {\n throw new Error('Renderer Handler was not reset');\n }\n\n handlerState = HandlerState.INITIALIZED;\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Renderer Handler is not initialized');\n }\n\n if (Types.TraceEvents.isThreadName(event) && event.args.name?.startsWith('CompositorTileWorker')) {\n compositorTileWorkers.push({\n pid: event.pid,\n tid: event.tid,\n });\n }\n\n if (Types.TraceEvents.isTraceEventBegin(event) || Types.TraceEvents.isTraceEventEnd(event)) {\n const process = getOrCreateRendererProcess(processes, event.pid);\n const thread = getOrCreateRendererThread(process, event.tid);\n const completeEvent = makeCompleteEvent(event);\n if (!completeEvent) {\n return;\n }\n thread.entries.push(completeEvent);\n allTraceEntries.push(completeEvent);\n return;\n }\n\n if (Types.TraceEvents.isTraceEventInstant(event) || Types.TraceEvents.isTraceEventComplete(event)) {\n const process = getOrCreateRendererProcess(processes, event.pid);\n const thread = getOrCreateRendererThread(process, event.tid);\n thread.entries.push(event);\n allTraceEntries.push(event);\n }\n}\n\nexport async function finalize(): Promise {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Renderer Handler is not initialized');\n }\n\n const {mainFrameId, rendererProcessesByFrame, threadsInProcess} = metaHandlerData();\n assignMeta(processes, mainFrameId, rendererProcessesByFrame, threadsInProcess);\n sanitizeProcesses(processes);\n buildHierarchy(processes);\n sanitizeThreads(processes);\n Helpers.Trace.sortTraceEventsInPlace(allTraceEntries);\n handlerState = HandlerState.FINALIZED;\n}\n\nexport function data(): RendererHandlerData {\n if (handlerState !== HandlerState.FINALIZED) {\n throw new Error('Renderer Handler is not finalized');\n }\n\n return {\n processes: new Map(processes),\n compositorTileWorkers: new Map(gatherCompositorThreads()),\n entryToNode: new Map(entryToNode),\n allTraceEntries: [...allTraceEntries],\n };\n}\n\nfunction gatherCompositorThreads(): Map {\n const threadsByProcess = new Map();\n for (const worker of compositorTileWorkers) {\n const byProcess = threadsByProcess.get(worker.pid) || [];\n byProcess.push(worker.tid);\n threadsByProcess.set(worker.pid, byProcess);\n }\n return threadsByProcess;\n}\n\n/**\n * Steps through all the renderer processes we've located so far in the meta\n * handler, obtaining their URL, checking whether they are the main frame, and\n * collecting each one of their threads' name. This meta handler's data is\n * assigned to the renderer handler's data.\n */\nexport function assignMeta(\n processes: Map, mainFrameId: string,\n rendererProcessesByFrame: FrameProcessData,\n threadsInProcess:\n Map>):\n void {\n assignOrigin(processes, rendererProcessesByFrame);\n assignIsMainFrame(processes, mainFrameId, rendererProcessesByFrame);\n assignThreadName(processes, rendererProcessesByFrame, threadsInProcess);\n}\n\n/**\n * Assigns origins to all threads in all processes.\n * @see assignMeta\n */\nexport function assignOrigin(\n processes: Map, rendererProcessesByFrame: FrameProcessData): void {\n for (const renderProcessesByPid of rendererProcessesByFrame.values()) {\n for (const [pid, processWindows] of renderProcessesByPid) {\n for (const processInfo of processWindows.flat()) {\n const process = getOrCreateRendererProcess(processes, pid);\n // Sometimes a single process is responsible with rendering multiple\n // frames at the same time. For example, see https://crbug.com/1334563.\n // When this happens, we'd still like to assign a single url per process\n // so: 1) use the first frame rendered by this process as the url source\n // and 2) if the last url is \"about:blank\", use the next frame's url,\n // data from about:blank is irrelevant.\n if (process.url === null || process.url === 'about:blank') {\n // If we are here, it's because we care about this process and the URL. But before we store\n // it, we check if it is a valid URL by trying to create a URL object. If it isn't, we won't\n // set it, and this process will be filtered out later.\n try {\n new URL(processInfo.frame.url);\n process.url = processInfo.frame.url;\n } catch (e) {\n process.url = null;\n }\n }\n }\n }\n }\n}\n\n/**\n * Assigns whether or not a thread is the main frame to all threads in all processes.\n * @see assignMeta\n */\nexport function assignIsMainFrame(\n processes: Map, mainFrameId: string,\n rendererProcessesByFrame: FrameProcessData): void {\n for (const [frameId, renderProcessesByPid] of rendererProcessesByFrame) {\n for (const [pid] of renderProcessesByPid) {\n const process = getOrCreateRendererProcess(processes, pid);\n // We have this go in one direction; once a renderer has been flagged as\n // being on the main frame, we don't unset it to false if were to show up\n // in a subframe. Equally, if we already saw this renderer in a subframe,\n // but it becomes the main frame, the flag would get updated.\n if (frameId === mainFrameId) {\n process.isOnMainFrame = true;\n }\n }\n }\n}\n\n/**\n * Assigns the thread name to all threads in all processes.\n * @see assignMeta\n */\nexport function assignThreadName(\n processes: Map, rendererProcessesByFrame: FrameProcessData,\n threadsInProcess:\n Map>):\n void {\n for (const [pid, process] of processes) {\n for (const [tid, threadInfo] of threadsInProcess.get(pid) ?? []) {\n const thread = getOrCreateRendererThread(process, tid);\n thread.name = threadInfo?.args.name ?? `${tid}`;\n }\n }\n}\n\n/**\n * Removes unneeded trace data opportunistically stored while handling events.\n * This currently does the following:\n * - Deletes processes with an unkonwn origin.\n */\nexport function sanitizeProcesses(processes: Map): void {\n const auctionWorklets = auctionWorkletsData().worklets;\n const metaData = metaHandlerData();\n if (metaData.traceIsGeneric) {\n return;\n }\n for (const [pid, process] of processes) {\n // If the process had no url, or if it had a malformed url that could not be\n // parsed for some reason, or if it's an \"about:\" origin, delete it.\n // This is done because we don't really care about processes for which we\n // can't provide actionable insights to the user (e.g. about:blank pages).\n //\n // There is one exception; AuctionWorklet processes get parsed in a\n // separate handler, so at this point we check to see if the process has\n // been found by the AuctionWorkletsHandler, and if so we update the URL.\n // This ensures that we keep this process around and do not drop it due to\n // the lack of a URL.\n if (process.url === null) {\n const maybeWorklet = auctionWorklets.get(pid);\n if (maybeWorklet) {\n process.url = maybeWorklet.host;\n } else {\n processes.delete(pid);\n }\n continue;\n }\n }\n}\n\n/**\n * Removes unneeded trace data opportunistically stored while handling events.\n * This currently does the following:\n * - Deletes threads with no roots.\n */\nexport function sanitizeThreads(processes: Map): void {\n for (const [, process] of processes) {\n for (const [tid, thread] of process.threads) {\n // If the thread has no roots, delete it. Otherwise, there's going to\n // be space taken, even though nothing is rendered in the track manager.\n if (!thread.tree?.roots.size) {\n process.threads.delete(tid);\n }\n }\n }\n}\n\n/**\n * Creates a hierarchical structure from the trace events. Each thread in each\n * process will contribute to their own individual hierarchy.\n *\n * The trace data comes in as a contiguous array of events, against which we\n * make a couple of assumptions:\n *\n * 1. Events are temporally-ordered in terms of start time (though they're\n * not necessarily ordered as such in the data stream).\n * 2. If event B's start and end times are within event A's time boundaries\n * we assume that A is the parent of B.\n *\n * Therefore we expect to reformulate something like:\n *\n * [ Task A ][ Task B ][ Task C ][ Task D ][ Task E ]\n *\n * Into something hierarchically-arranged like below:\n *\n * |------------- Task A -------------||-- Task E --|\n * |-- Task B --||-- Task D --|\n * |- Task C -|\n */\nexport function buildHierarchy(\n processes: Map,\n options?: {filter: {has: (name: Types.TraceEvents.KnownEventName) => boolean}}): void {\n const samplesData = samplesHandlerData();\n for (const [pid, process] of processes) {\n for (const [tid, thread] of process.threads) {\n if (!thread.entries.length) {\n thread.tree = Helpers.TreeHelpers.makeEmptyTraceEntryTree();\n continue;\n }\n // Step 1. Massage the data.\n Helpers.Trace.sortTraceEventsInPlace(thread.entries);\n // Step 2. Inject profile calls from samples\n const samplesDataForThread = samplesData.profilesInProcess.get(pid)?.get(tid);\n if (samplesDataForThread) {\n const cpuProfile = samplesDataForThread.parsedProfile;\n const samplesIntegrator = cpuProfile &&\n new Helpers.SamplesIntegrator.SamplesIntegrator(\n cpuProfile, samplesDataForThread.profileId, pid, tid, config);\n const profileCalls = samplesIntegrator?.buildProfileCalls(thread.entries);\n if (samplesIntegrator && profileCalls) {\n allTraceEntries = [...allTraceEntries, ...profileCalls];\n thread.entries = Helpers.Trace.mergeEventsInOrder(thread.entries, profileCalls);\n thread.profileCalls = profileCalls;\n // We'll also inject the instant JSSample events (in debug mode only)\n const jsSamples = samplesIntegrator.jsSampleEvents;\n if (jsSamples) {\n allTraceEntries = [...allTraceEntries, ...jsSamples];\n thread.entries = Helpers.Trace.mergeEventsInOrder(thread.entries, jsSamples);\n }\n }\n }\n // Step 3. Build the tree.\n const treeData = Helpers.TreeHelpers.treify(thread.entries, options);\n thread.tree = treeData.tree;\n // Update the entryToNode map with the entries from this thread\n for (const [entry, node] of treeData.entryToNode) {\n entryToNode.set(entry, node);\n }\n }\n }\n}\n\nexport function makeCompleteEvent(event: Types.TraceEvents.TraceEventBegin|\n Types.TraceEvents.TraceEventEnd): Types.TraceEvents.SyntheticCompleteEvent|null {\n if (Types.TraceEvents.isTraceEventEnd(event)) {\n // Quietly ignore unbalanced close events, they're legit (we could\n // have missed start one).\n const beginEvent = completeEventStack.pop();\n if (!beginEvent) {\n return null;\n }\n if (beginEvent.name !== event.name || beginEvent.cat !== event.cat) {\n console.error(\n 'Begin/End events mismatch at ' + beginEvent.ts + ' (' + beginEvent.name + ') vs. ' + event.ts + ' (' +\n event.name + ')');\n return null;\n }\n // Update the begin event's duration using the timestamp of the end\n // event.\n beginEvent.dur = Types.Timing.MicroSeconds(event.ts - beginEvent.ts);\n return null;\n }\n\n // Create a synthetic event using the begin event, when we find the\n // matching end event later we will update its duration.\n const syntheticComplete: Types.TraceEvents.SyntheticCompleteEvent = {\n ...event,\n ph: Types.TraceEvents.Phase.COMPLETE,\n dur: Types.Timing.MicroSeconds(0),\n };\n\n completeEventStack.push(syntheticComplete);\n return syntheticComplete;\n}\n\nexport function deps(): TraceEventHandlerName[] {\n return ['Meta', 'Samples', 'AuctionWorklets'];\n}\n\nexport interface RendererHandlerData {\n processes: Map;\n /**\n * A map of all compositor workers (which we show in the UI as Rasterizers)\n * by the process ID.\n */\n compositorTileWorkers: Map;\n entryToNode: Map;\n /**\n * All trace events and synthetic profile calls made from\n * samples.\n */\n allTraceEntries: Types.TraceEvents.TraceEventData[];\n}\n\nexport interface RendererProcess {\n // In an ideal world this would be modelled as a URL, but URLs cannot be sent\n // between the main thread and workers, so we have to store it as a string.\n url: string|null;\n isOnMainFrame: boolean;\n threads: Map;\n}\n\nexport interface RendererThread {\n name: string|null;\n /**\n * Contains trace events and synthetic profile calls made from\n * samples.\n */\n entries: Types.TraceEvents.TraceEventData[];\n profileCalls: Types.TraceEvents.SyntheticProfileCall[];\n tree?: Helpers.TreeHelpers.TraceEntryTree;\n}\n"]} \ No newline at end of file +{"version":3,"file":"RendererHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/RendererHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {data as auctionWorkletsData} from './AuctionWorkletsHandler.js';\nimport {data as metaHandlerData, type FrameProcessData} from './MetaHandler.js';\nimport {data as samplesHandlerData} from './SamplesHandler.js';\nimport {type HandlerName, HandlerState} from './types.js';\n\n/**\n * This handler builds the hierarchy of trace events and profile calls\n * on each thread on each process.\n *\n * Throughout the code, trace events and profile calls are referred to\n * as \"entries\", but note they are different types of data. Trace events\n * come directly from the backend and it's the type the engine commonly\n * refers to. Profile calls on the other hand are built in the frontend,\n * and, for compatibility purposes, typed as an extension to the trace\n * event type.\n */\n\nconst processes = new Map();\n\n// We track the compositor tile worker thread name events so that at the end we\n// can return these keyed by the process ID. These are used in the frontend to\n// show the user the rasterization thread(s) on the main frame as tracks.\nconst compositorTileWorkers = Array<{\n pid: Types.Events.ProcessID,\n tid: Types.Events.ThreadID,\n}>();\nconst entryToNode: Map = new Map();\nlet allTraceEntries: Types.Events.Event[] = [];\n\nconst completeEventStack: (Types.Events.SyntheticComplete)[] = [];\n\nlet handlerState = HandlerState.UNINITIALIZED;\nlet config: Types.Configuration.Configuration = Types.Configuration.defaults();\n\nconst makeRendererProcess = (): RendererProcess => ({\n url: null,\n isOnMainFrame: false,\n threads: new Map(),\n});\n\nconst makeRendererThread = (): RendererThread => ({\n name: null,\n entries: [],\n profileCalls: [],\n});\n\nconst getOrCreateRendererProcess =\n (processes: Map, pid: Types.Events.ProcessID): RendererProcess => {\n return Platform.MapUtilities.getWithDefault(processes, pid, makeRendererProcess);\n };\n\nconst getOrCreateRendererThread = (process: RendererProcess, tid: Types.Events.ThreadID): RendererThread => {\n return Platform.MapUtilities.getWithDefault(process.threads, tid, makeRendererThread);\n};\n\nexport function handleUserConfig(userConfig: Types.Configuration.Configuration): void {\n config = userConfig;\n}\n\nexport function reset(): void {\n processes.clear();\n entryToNode.clear();\n allTraceEntries.length = 0;\n completeEventStack.length = 0;\n compositorTileWorkers.length = 0;\n handlerState = HandlerState.UNINITIALIZED;\n}\n\nexport function initialize(): void {\n if (handlerState !== HandlerState.UNINITIALIZED) {\n throw new Error('Renderer Handler was not reset');\n }\n\n handlerState = HandlerState.INITIALIZED;\n}\n\nexport function handleEvent(event: Types.Events.Event): void {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Renderer Handler is not initialized');\n }\n\n if (Types.Events.isThreadName(event) && event.args.name?.startsWith('CompositorTileWorker')) {\n compositorTileWorkers.push({\n pid: event.pid,\n tid: event.tid,\n });\n }\n\n if (Types.Events.isBegin(event) || Types.Events.isEnd(event)) {\n const process = getOrCreateRendererProcess(processes, event.pid);\n const thread = getOrCreateRendererThread(process, event.tid);\n const completeEvent = makeCompleteEvent(event);\n if (!completeEvent) {\n return;\n }\n thread.entries.push(completeEvent);\n allTraceEntries.push(completeEvent);\n return;\n }\n\n if (Types.Events.isInstant(event) || Types.Events.isComplete(event)) {\n const process = getOrCreateRendererProcess(processes, event.pid);\n const thread = getOrCreateRendererThread(process, event.tid);\n thread.entries.push(event);\n allTraceEntries.push(event);\n }\n}\n\nexport async function finalize(): Promise {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Renderer Handler is not initialized');\n }\n\n const {mainFrameId, rendererProcessesByFrame, threadsInProcess} = metaHandlerData();\n assignMeta(processes, mainFrameId, rendererProcessesByFrame, threadsInProcess);\n sanitizeProcesses(processes);\n buildHierarchy(processes);\n sanitizeThreads(processes);\n Helpers.Trace.sortTraceEventsInPlace(allTraceEntries);\n handlerState = HandlerState.FINALIZED;\n}\n\nexport function data(): RendererHandlerData {\n if (handlerState !== HandlerState.FINALIZED) {\n throw new Error('Renderer Handler is not finalized');\n }\n\n return {\n processes: new Map(processes),\n compositorTileWorkers: new Map(gatherCompositorThreads()),\n entryToNode: new Map(entryToNode),\n allTraceEntries: [...allTraceEntries],\n };\n}\n\nfunction gatherCompositorThreads(): Map {\n const threadsByProcess = new Map();\n for (const worker of compositorTileWorkers) {\n const byProcess = threadsByProcess.get(worker.pid) || [];\n byProcess.push(worker.tid);\n threadsByProcess.set(worker.pid, byProcess);\n }\n return threadsByProcess;\n}\n\n/**\n * Steps through all the renderer processes we've located so far in the meta\n * handler, obtaining their URL, checking whether they are the main frame, and\n * collecting each one of their threads' name. This meta handler's data is\n * assigned to the renderer handler's data.\n */\nexport function assignMeta(\n processes: Map, mainFrameId: string,\n rendererProcessesByFrame: FrameProcessData,\n threadsInProcess: Map>): void {\n assignOrigin(processes, rendererProcessesByFrame);\n assignIsMainFrame(processes, mainFrameId, rendererProcessesByFrame);\n assignThreadName(processes, rendererProcessesByFrame, threadsInProcess);\n}\n\n/**\n * Assigns origins to all threads in all processes.\n * @see assignMeta\n */\nexport function assignOrigin(\n processes: Map, rendererProcessesByFrame: FrameProcessData): void {\n for (const renderProcessesByPid of rendererProcessesByFrame.values()) {\n for (const [pid, processWindows] of renderProcessesByPid) {\n for (const processInfo of processWindows.flat()) {\n const process = getOrCreateRendererProcess(processes, pid);\n // Sometimes a single process is responsible with rendering multiple\n // frames at the same time. For example, see https://crbug.com/1334563.\n // When this happens, we'd still like to assign a single url per process\n // so: 1) use the first frame rendered by this process as the url source\n // and 2) if the last url is \"about:blank\", use the next frame's url,\n // data from about:blank is irrelevant.\n if (process.url === null || process.url === 'about:blank') {\n // If we are here, it's because we care about this process and the URL. But before we store\n // it, we check if it is a valid URL by trying to create a URL object. If it isn't, we won't\n // set it, and this process will be filtered out later.\n try {\n new URL(processInfo.frame.url);\n process.url = processInfo.frame.url;\n } catch (e) {\n process.url = null;\n }\n }\n }\n }\n }\n}\n\n/**\n * Assigns whether or not a thread is the main frame to all threads in all processes.\n * @see assignMeta\n */\nexport function assignIsMainFrame(\n processes: Map, mainFrameId: string,\n rendererProcessesByFrame: FrameProcessData): void {\n for (const [frameId, renderProcessesByPid] of rendererProcessesByFrame) {\n for (const [pid] of renderProcessesByPid) {\n const process = getOrCreateRendererProcess(processes, pid);\n // We have this go in one direction; once a renderer has been flagged as\n // being on the main frame, we don't unset it to false if were to show up\n // in a subframe. Equally, if we already saw this renderer in a subframe,\n // but it becomes the main frame, the flag would get updated.\n if (frameId === mainFrameId) {\n process.isOnMainFrame = true;\n }\n }\n }\n}\n\n/**\n * Assigns the thread name to all threads in all processes.\n * @see assignMeta\n */\nexport function assignThreadName(\n processes: Map, rendererProcessesByFrame: FrameProcessData,\n threadsInProcess: Map>): void {\n for (const [pid, process] of processes) {\n for (const [tid, threadInfo] of threadsInProcess.get(pid) ?? []) {\n const thread = getOrCreateRendererThread(process, tid);\n thread.name = threadInfo?.args.name ?? `${tid}`;\n }\n }\n}\n\n/**\n * Removes unneeded trace data opportunistically stored while handling events.\n * This currently does the following:\n * - Deletes processes with an unkonwn origin.\n */\nexport function sanitizeProcesses(processes: Map): void {\n const auctionWorklets = auctionWorkletsData().worklets;\n const metaData = metaHandlerData();\n if (metaData.traceIsGeneric) {\n return;\n }\n for (const [pid, process] of processes) {\n // If the process had no url, or if it had a malformed url that could not be\n // parsed for some reason, or if it's an \"about:\" origin, delete it.\n // This is done because we don't really care about processes for which we\n // can't provide actionable insights to the user (e.g. about:blank pages).\n //\n // There is one exception; AuctionWorklet processes get parsed in a\n // separate handler, so at this point we check to see if the process has\n // been found by the AuctionWorkletsHandler, and if so we update the URL.\n // This ensures that we keep this process around and do not drop it due to\n // the lack of a URL.\n if (process.url === null) {\n const maybeWorklet = auctionWorklets.get(pid);\n if (maybeWorklet) {\n process.url = maybeWorklet.host;\n } else {\n processes.delete(pid);\n }\n continue;\n }\n }\n}\n\n/**\n * Removes unneeded trace data opportunistically stored while handling events.\n * This currently does the following:\n * - Deletes threads with no roots.\n */\nexport function sanitizeThreads(processes: Map): void {\n for (const [, process] of processes) {\n for (const [tid, thread] of process.threads) {\n // If the thread has no roots, delete it. Otherwise, there's going to\n // be space taken, even though nothing is rendered in the track manager.\n if (!thread.tree?.roots.size) {\n process.threads.delete(tid);\n }\n }\n }\n}\n\n/**\n * Creates a hierarchical structure from the trace events. Each thread in each\n * process will contribute to their own individual hierarchy.\n *\n * The trace data comes in as a contiguous array of events, against which we\n * make a couple of assumptions:\n *\n * 1. Events are temporally-ordered in terms of start time (though they're\n * not necessarily ordered as such in the data stream).\n * 2. If event B's start and end times are within event A's time boundaries\n * we assume that A is the parent of B.\n *\n * Therefore we expect to reformulate something like:\n *\n * [ Task A ][ Task B ][ Task C ][ Task D ][ Task E ]\n *\n * Into something hierarchically-arranged like below:\n *\n * |------------- Task A -------------||-- Task E --|\n * |-- Task B --||-- Task D --|\n * |- Task C -|\n */\nexport function buildHierarchy(\n processes: Map,\n options?: {filter: {has: (name: Types.Events.Name) => boolean}}): void {\n const samplesData = samplesHandlerData();\n for (const [pid, process] of processes) {\n for (const [tid, thread] of process.threads) {\n if (!thread.entries.length) {\n thread.tree = Helpers.TreeHelpers.makeEmptyTraceEntryTree();\n continue;\n }\n // Step 1. Massage the data.\n Helpers.Trace.sortTraceEventsInPlace(thread.entries);\n // Step 2. Inject profile calls from samples\n const samplesDataForThread = samplesData.profilesInProcess.get(pid)?.get(tid);\n if (samplesDataForThread) {\n const cpuProfile = samplesDataForThread.parsedProfile;\n const samplesIntegrator = cpuProfile &&\n new Helpers.SamplesIntegrator.SamplesIntegrator(\n cpuProfile, samplesDataForThread.profileId, pid, tid, config);\n const profileCalls = samplesIntegrator?.buildProfileCalls(thread.entries);\n if (samplesIntegrator && profileCalls) {\n allTraceEntries = [...allTraceEntries, ...profileCalls];\n thread.entries = Helpers.Trace.mergeEventsInOrder(thread.entries, profileCalls);\n thread.profileCalls = profileCalls;\n // We'll also inject the instant JSSample events (in debug mode only)\n const jsSamples = samplesIntegrator.jsSampleEvents;\n if (jsSamples) {\n allTraceEntries = [...allTraceEntries, ...jsSamples];\n thread.entries = Helpers.Trace.mergeEventsInOrder(thread.entries, jsSamples);\n }\n }\n }\n // Step 3. Build the tree.\n const treeData = Helpers.TreeHelpers.treify(thread.entries, options);\n thread.tree = treeData.tree;\n // Update the entryToNode map with the entries from this thread\n for (const [entry, node] of treeData.entryToNode) {\n entryToNode.set(entry, node);\n }\n }\n }\n}\n\nexport function makeCompleteEvent(event: Types.Events.Begin|Types.Events.End): Types.Events.SyntheticComplete|null {\n if (Types.Events.isEnd(event)) {\n // Quietly ignore unbalanced close events, they're legit (we could\n // have missed start one).\n const beginEvent = completeEventStack.pop();\n if (!beginEvent) {\n return null;\n }\n if (beginEvent.name !== event.name || beginEvent.cat !== event.cat) {\n console.error(\n 'Begin/End events mismatch at ' + beginEvent.ts + ' (' + beginEvent.name + ') vs. ' + event.ts + ' (' +\n event.name + ')');\n return null;\n }\n // Update the begin event's duration using the timestamp of the end\n // event.\n beginEvent.dur = Types.Timing.MicroSeconds(event.ts - beginEvent.ts);\n return null;\n }\n\n // Create a synthetic event using the begin event, when we find the\n // matching end event later we will update its duration.\n const syntheticComplete: Types.Events.SyntheticComplete = {\n ...event,\n ph: Types.Events.Phase.COMPLETE,\n dur: Types.Timing.MicroSeconds(0),\n };\n\n completeEventStack.push(syntheticComplete);\n return syntheticComplete;\n}\n\nexport function deps(): HandlerName[] {\n return ['Meta', 'Samples', 'AuctionWorklets'];\n}\n\nexport interface RendererHandlerData {\n processes: Map;\n /**\n * A map of all compositor workers (which we show in the UI as Rasterizers)\n * by the process ID.\n */\n compositorTileWorkers: Map;\n entryToNode: Map;\n /**\n * All trace events and synthetic profile calls made from\n * samples.\n */\n allTraceEntries: Types.Events.Event[];\n}\n\nexport interface RendererProcess {\n // In an ideal world this would be modelled as a URL, but URLs cannot be sent\n // between the main thread and workers, so we have to store it as a string.\n url: string|null;\n isOnMainFrame: boolean;\n threads: Map;\n}\n\nexport interface RendererThread {\n name: string|null;\n /**\n * Contains trace events and synthetic profile calls made from\n * samples.\n */\n entries: Types.Events.Event[];\n profileCalls: Types.Events.SyntheticProfileCall[];\n tree?: Helpers.TreeHelpers.TraceEntryTree;\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/RendererHandler.test.js b/public/models/trace/handlers/RendererHandler.test.js index da6722e65..6d0c59a59 100644 --- a/public/models/trace/handlers/RendererHandler.test.js +++ b/public/models/trace/handlers/RendererHandler.test.js @@ -5,14 +5,14 @@ import * as Components from '../../../panels/timeline/components/components.js'; import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; import { getAllNodes, getEventsIn, getRootAt, makeBeginEvent, makeCompleteEvent, makeEndEvent, makeInstantEvent, prettyPrint, } from '../../../testing/TraceHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; -import * as TraceModel from '../trace.js'; +import * as Trace from '../trace.js'; const MAIN_FRAME_PID = 2154214; const SUB_FRAME_PID = 2236065; const SUB_FRAME_PID_2 = 2236084; const SUB_FRAME_PID_3 = 2236123; async function handleEventsFromTraceFile(context, file) { - const { traceData } = await TraceLoader.traceEngine(context, file); - return traceData; + const { parsedTrace } = await TraceLoader.traceEngine(context, file); + return parsedTrace; } describeWithEnvironment('RendererHandler', function () { it('finds all the renderers in a real world profile', async () => { @@ -46,7 +46,7 @@ describeWithEnvironment('RendererHandler', function () { }); it('finds all the main frame threads in a real world profile', async () => { const { Renderer: renderers } = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz'); - const frame = renderers.processes.get(TraceModel.Types.TraceEvents.ProcessID(MAIN_FRAME_PID)); + const frame = renderers.processes.get(Trace.Types.Events.ProcessID(MAIN_FRAME_PID)); const names = [...frame.threads].map(([, thread]) => thread.name).sort(); assert.deepEqual(names, [ 'Chrome_ChildIOThread', @@ -69,7 +69,7 @@ describeWithEnvironment('RendererHandler', function () { }); it('finds all the sub frame threads in a real world profile', async () => { const { Renderer: renderers } = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz'); - const frame = renderers.processes.get(TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID)); + const frame = renderers.processes.get(Trace.Types.Events.ProcessID(SUB_FRAME_PID)); const names = [...frame.threads].map(([, thread]) => thread.name).sort(); assert.deepEqual(names, [ 'Chrome_ChildIOThread', @@ -80,7 +80,7 @@ describeWithEnvironment('RendererHandler', function () { }); it('finds all the roots on the main frame\'s main thread in a real world profile', async () => { const { Renderer: renderers } = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz'); - const frame = renderers.processes.get(TraceModel.Types.TraceEvents.ProcessID(MAIN_FRAME_PID)); + const frame = renderers.processes.get(Trace.Types.Events.ProcessID(MAIN_FRAME_PID)); const thread = [...frame.threads.values()].find(thread => thread.name === 'CrRendererMain'); if (!thread) { assert(false, 'Main thread was not found'); @@ -118,7 +118,7 @@ describeWithEnvironment('RendererHandler', function () { }); it('finds all the roots on the sub frame\'s main thread in a real world profile', async () => { const { Renderer: renderers } = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz'); - const frame = renderers.processes.get(TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID)); + const frame = renderers.processes.get(Trace.Types.Events.ProcessID(SUB_FRAME_PID)); const thread = [...frame.threads.values()].find(thread => thread.name === 'CrRendererMain'); if (!thread) { assert(false, 'Main thread was not found'); @@ -131,7 +131,7 @@ describeWithEnvironment('RendererHandler', function () { }); it('builds a hierarchy for the main frame\'s main thread in a real world profile', async () => { const { Renderer: renderers } = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz'); - const frame = renderers.processes.get(TraceModel.Types.TraceEvents.ProcessID(MAIN_FRAME_PID)); + const frame = renderers.processes.get(Trace.Types.Events.ProcessID(MAIN_FRAME_PID)); const thread = [...frame.threads.values()].find(thread => thread.name === 'CrRendererMain'); if (!thread) { assert(false, 'Main thread was not found'); @@ -141,8 +141,8 @@ describeWithEnvironment('RendererHandler', function () { assert(false, 'Main thread has no tree of events'); } const isRoot = (node) => node.depth === 0; - const isInstant = (event) => TraceModel.Types.TraceEvents.isTraceEventInstant(event); - const isLong = (event) => TraceModel.Types.TraceEvents.isTraceEventComplete(event) && event.dur > 1000; + const isInstant = (event) => Trace.Types.Events.isInstant(event); + const isLong = (event) => Trace.Types.Events.isComplete(event) && event.dur > 1000; const isIncluded = (node, event) => (!isRoot(node) || isInstant(event) || isLong(event)) && Boolean(Components.EntryStyles.getEventStyle(event.name)); assert.strictEqual(prettyPrint(tree, isIncluded), ` @@ -330,7 +330,7 @@ describeWithEnvironment('RendererHandler', function () { }); it('builds a hierarchy for the sub frame\'s main thread in a real world profile', async () => { const { Renderer: renderers } = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz'); - const frame = renderers.processes.get(TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID)); + const frame = renderers.processes.get(Trace.Types.Events.ProcessID(SUB_FRAME_PID)); const thread = [...frame.threads.values()].find(thread => thread.name === 'CrRendererMain'); if (!thread) { assert(false, 'Main thread was not found'); @@ -365,7 +365,7 @@ describeWithEnvironment('RendererHandler', function () { }); it('has some correct known roots for the main frame\'s main thread in a real world profile', async () => { const { Renderer: renderers } = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz'); - const frame = renderers.processes.get(TraceModel.Types.TraceEvents.ProcessID(MAIN_FRAME_PID)); + const frame = renderers.processes.get(Trace.Types.Events.ProcessID(MAIN_FRAME_PID)); const thread = [...frame.threads.values()].find(thread => thread.name === 'CrRendererMain'); if (!thread) { assert(false, 'Main thread was not found'); @@ -419,7 +419,7 @@ describeWithEnvironment('RendererHandler', function () { }); it('has some correct known roots for the sub frame\'s main thread in a real world profile', async () => { const { Renderer: renderers } = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz'); - const frame = renderers.processes.get(TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID)); + const frame = renderers.processes.get(Trace.Types.Events.ProcessID(SUB_FRAME_PID)); const thread = [...frame.threads.values()].find(thread => thread.name === 'CrRendererMain'); if (!thread) { assert(false, 'Main thread was not found'); @@ -483,7 +483,7 @@ describeWithEnvironment('RendererHandler', function () { makeCompleteEvent('b1', 1, 0.01), makeCompleteEvent('a3', 0.5, 0.25), ]; - TraceModel.Helpers.Trace.sortTraceEventsInPlace(data); + Trace.Helpers.Trace.sortTraceEventsInPlace(data); assert.deepEqual(data.map(e => ({ name: e.name, ts: e.ts, dur: e.dur })), [ { name: 'a0', ts: 0, dur: 1 }, { name: 'a1', ts: 0, dur: 0.5 }, @@ -517,7 +517,7 @@ describeWithEnvironment('RendererHandler', function () { makeCompleteEvent('a3', 0.5, 0.25), makeInstantEvent('i8', 2.01), ]; - TraceModel.Helpers.Trace.sortTraceEventsInPlace(data); + Trace.Helpers.Trace.sortTraceEventsInPlace(data); assert.deepEqual(data.map(e => ({ name: e.name, ts: e.ts, dur: e.dur })), [ { name: 'a0', ts: 0, dur: 1 }, { name: 'a1', ts: 0, dur: 0.5 }, @@ -566,31 +566,31 @@ describeWithEnvironment('RendererHandler', function () { ]; const processes = new Map([ [ - TraceModel.Types.TraceEvents.ProcessID(0), + Trace.Types.Events.ProcessID(0), { url: ('http://a.com'), isOnMainFrame: true, threads: new Map([[ - TraceModel.Types.TraceEvents.ThreadID(1), + Trace.Types.Events.ThreadID(1), { name: 'Foo', entries: data1 }, ]]), }, ], [ - TraceModel.Types.TraceEvents.ProcessID(2), + Trace.Types.Events.ProcessID(2), { url: ('http://b.com'), isOnMainFrame: false, threads: new Map([[ - TraceModel.Types.TraceEvents.ThreadID(3), + Trace.Types.Events.ThreadID(3), { name: 'Bar', entries: data2 }, ]]), }, ], ]); - TraceModel.Handlers.ModelHandlers.Samples.initialize(); - await TraceModel.Handlers.ModelHandlers.Samples.finalize(); - TraceModel.Handlers.ModelHandlers.Renderer.buildHierarchy(processes, { filter: { has: () => true } }); + Trace.Handlers.ModelHandlers.Samples.initialize(); + await Trace.Handlers.ModelHandlers.Samples.finalize(); + Trace.Handlers.ModelHandlers.Renderer.buildHierarchy(processes, { filter: { has: () => true } }); const firstThread = [...[...processes.values()][0].threads.values()][0]; const secondThread = [...[...processes.values()][1].threads.values()][0]; if (!firstThread.tree || !secondThread.tree) { @@ -612,80 +612,80 @@ describeWithEnvironment('RendererHandler', function () { it('can assign origins to processes', async () => { const { Meta: metadata } = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz'); const processes = new Map(); - TraceModel.Handlers.ModelHandlers.Renderer.assignOrigin(processes, metadata.rendererProcessesByFrame); + Trace.Handlers.ModelHandlers.Renderer.assignOrigin(processes, metadata.rendererProcessesByFrame); assert.deepEqual([...processes].map(([pid, p]) => [pid, p.url ? new URL(p.url).origin : null]), [ - [TraceModel.Types.TraceEvents.ProcessID(MAIN_FRAME_PID), 'http://localhost:5000'], - [TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID), 'https://www.example.com'], - [TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID_2), 'https://www.example.com'], - [TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID_3), 'https://www.example.com'], + [Trace.Types.Events.ProcessID(MAIN_FRAME_PID), 'http://localhost:5000'], + [Trace.Types.Events.ProcessID(SUB_FRAME_PID), 'https://www.example.com'], + [Trace.Types.Events.ProcessID(SUB_FRAME_PID_2), 'https://www.example.com'], + [Trace.Types.Events.ProcessID(SUB_FRAME_PID_3), 'https://www.example.com'], ]); }); it('can assign main frame flags to processes', async () => { const { Meta: metadata } = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz'); const processes = new Map(); - TraceModel.Handlers.ModelHandlers.Renderer.assignIsMainFrame(processes, metadata.mainFrameId, metadata.rendererProcessesByFrame); + Trace.Handlers.ModelHandlers.Renderer.assignIsMainFrame(processes, metadata.mainFrameId, metadata.rendererProcessesByFrame); assert.deepEqual([...processes].map(([pid, p]) => [pid, p.isOnMainFrame]), [ - [TraceModel.Types.TraceEvents.ProcessID(MAIN_FRAME_PID), true], - [TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID), false], - [TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID_2), false], - [TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID_3), false], + [Trace.Types.Events.ProcessID(MAIN_FRAME_PID), true], + [Trace.Types.Events.ProcessID(SUB_FRAME_PID), false], + [Trace.Types.Events.ProcessID(SUB_FRAME_PID_2), false], + [Trace.Types.Events.ProcessID(SUB_FRAME_PID_3), false], ]); }); it('can assign thread names to threads in processes', async () => { const { Meta: metadata } = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz'); const { mainFrameId, rendererProcessesByFrame, threadsInProcess } = metadata; const processes = new Map(); - TraceModel.Handlers.ModelHandlers.Renderer.assignMeta(processes, mainFrameId, rendererProcessesByFrame, threadsInProcess); + Trace.Handlers.ModelHandlers.Renderer.assignMeta(processes, mainFrameId, rendererProcessesByFrame, threadsInProcess); assert.deepEqual([...processes].map(([pid, p]) => [pid, [...p.threads].map(([tid, t]) => [tid, t.name])]), [ [ - TraceModel.Types.TraceEvents.ProcessID(MAIN_FRAME_PID), + Trace.Types.Events.ProcessID(MAIN_FRAME_PID), [ - [TraceModel.Types.TraceEvents.ThreadID(1), 'CrRendererMain'], - [TraceModel.Types.TraceEvents.ThreadID(7), 'Compositor'], - [TraceModel.Types.TraceEvents.ThreadID(2), 'ThreadPoolServiceThread'], - [TraceModel.Types.TraceEvents.ThreadID(4), 'Chrome_ChildIOThread'], - [TraceModel.Types.TraceEvents.ThreadID(24), 'ThreadPoolForegroundWorker'], - [TraceModel.Types.TraceEvents.ThreadID(27), 'ThreadPoolForegroundWorker'], - [TraceModel.Types.TraceEvents.ThreadID(17), 'ThreadPoolForegroundWorker'], - [TraceModel.Types.TraceEvents.ThreadID(29), 'ThreadPoolForegroundWorker'], - [TraceModel.Types.TraceEvents.ThreadID(25), 'ThreadPoolForegroundWorker'], - [TraceModel.Types.TraceEvents.ThreadID(28), 'ThreadPoolForegroundWorker'], - [TraceModel.Types.TraceEvents.ThreadID(30), 'ThreadPoolForegroundWorker'], - [TraceModel.Types.TraceEvents.ThreadID(26), 'ThreadPoolForegroundWorker'], - [TraceModel.Types.TraceEvents.ThreadID(11), 'CompositorTileWorker3'], - [TraceModel.Types.TraceEvents.ThreadID(12), 'CompositorTileWorker4'], - [TraceModel.Types.TraceEvents.ThreadID(10), 'CompositorTileWorker2'], - [TraceModel.Types.TraceEvents.ThreadID(9), 'CompositorTileWorker1'], + [Trace.Types.Events.ThreadID(1), 'CrRendererMain'], + [Trace.Types.Events.ThreadID(7), 'Compositor'], + [Trace.Types.Events.ThreadID(2), 'ThreadPoolServiceThread'], + [Trace.Types.Events.ThreadID(4), 'Chrome_ChildIOThread'], + [Trace.Types.Events.ThreadID(24), 'ThreadPoolForegroundWorker'], + [Trace.Types.Events.ThreadID(27), 'ThreadPoolForegroundWorker'], + [Trace.Types.Events.ThreadID(17), 'ThreadPoolForegroundWorker'], + [Trace.Types.Events.ThreadID(29), 'ThreadPoolForegroundWorker'], + [Trace.Types.Events.ThreadID(25), 'ThreadPoolForegroundWorker'], + [Trace.Types.Events.ThreadID(28), 'ThreadPoolForegroundWorker'], + [Trace.Types.Events.ThreadID(30), 'ThreadPoolForegroundWorker'], + [Trace.Types.Events.ThreadID(26), 'ThreadPoolForegroundWorker'], + [Trace.Types.Events.ThreadID(11), 'CompositorTileWorker3'], + [Trace.Types.Events.ThreadID(12), 'CompositorTileWorker4'], + [Trace.Types.Events.ThreadID(10), 'CompositorTileWorker2'], + [Trace.Types.Events.ThreadID(9), 'CompositorTileWorker1'], ], ], [ - TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID), + Trace.Types.Events.ProcessID(SUB_FRAME_PID), [ - [TraceModel.Types.TraceEvents.ThreadID(2), 'ThreadPoolServiceThread'], - [TraceModel.Types.TraceEvents.ThreadID(1), 'CrRendererMain'], - [TraceModel.Types.TraceEvents.ThreadID(7), 'Compositor'], - [TraceModel.Types.TraceEvents.ThreadID(4), 'Chrome_ChildIOThread'], + [Trace.Types.Events.ThreadID(2), 'ThreadPoolServiceThread'], + [Trace.Types.Events.ThreadID(1), 'CrRendererMain'], + [Trace.Types.Events.ThreadID(7), 'Compositor'], + [Trace.Types.Events.ThreadID(4), 'Chrome_ChildIOThread'], ], ], [ - TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID_2), + Trace.Types.Events.ProcessID(SUB_FRAME_PID_2), [ - [TraceModel.Types.TraceEvents.ThreadID(1), 'CrRendererMain'], - [TraceModel.Types.TraceEvents.ThreadID(4), 'Chrome_ChildIOThread'], - [TraceModel.Types.TraceEvents.ThreadID(8), 'Compositor'], - [TraceModel.Types.TraceEvents.ThreadID(2), 'ThreadPoolServiceThread'], - [TraceModel.Types.TraceEvents.ThreadID(10), 'CompositorTileWorker1'], + [Trace.Types.Events.ThreadID(1), 'CrRendererMain'], + [Trace.Types.Events.ThreadID(4), 'Chrome_ChildIOThread'], + [Trace.Types.Events.ThreadID(8), 'Compositor'], + [Trace.Types.Events.ThreadID(2), 'ThreadPoolServiceThread'], + [Trace.Types.Events.ThreadID(10), 'CompositorTileWorker1'], ], ], [ - TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID_3), + Trace.Types.Events.ProcessID(SUB_FRAME_PID_3), [ - [TraceModel.Types.TraceEvents.ThreadID(1), 'CrRendererMain'], - [TraceModel.Types.TraceEvents.ThreadID(2), 'ThreadPoolServiceThread'], - [TraceModel.Types.TraceEvents.ThreadID(4), 'Chrome_ChildIOThread'], - [TraceModel.Types.TraceEvents.ThreadID(7), 'Compositor'], - [TraceModel.Types.TraceEvents.ThreadID(10), 'CompositorTileWorker2'], - [TraceModel.Types.TraceEvents.ThreadID(3), 'ThreadPoolForegroundWorker'], + [Trace.Types.Events.ThreadID(1), 'CrRendererMain'], + [Trace.Types.Events.ThreadID(2), 'ThreadPoolServiceThread'], + [Trace.Types.Events.ThreadID(4), 'Chrome_ChildIOThread'], + [Trace.Types.Events.ThreadID(7), 'Compositor'], + [Trace.Types.Events.ThreadID(10), 'CompositorTileWorker2'], + [Trace.Types.Events.ThreadID(3), 'ThreadPoolForegroundWorker'], ], ], ]); @@ -696,31 +696,31 @@ describeWithEnvironment('RendererHandler', function () { }); describe('Synthetic complete events', () => { async function handleEvents(traceEvents) { - TraceModel.Handlers.ModelHandlers.Renderer.reset(); - TraceModel.Handlers.ModelHandlers.Meta.reset(); - TraceModel.Handlers.ModelHandlers.Samples.reset(); - TraceModel.Handlers.ModelHandlers.Meta.initialize(); - TraceModel.Handlers.ModelHandlers.Samples.initialize(); - TraceModel.Handlers.ModelHandlers.Renderer.initialize(); + Trace.Handlers.ModelHandlers.Renderer.reset(); + Trace.Handlers.ModelHandlers.Meta.reset(); + Trace.Handlers.ModelHandlers.Samples.reset(); + Trace.Handlers.ModelHandlers.Meta.initialize(); + Trace.Handlers.ModelHandlers.Samples.initialize(); + Trace.Handlers.ModelHandlers.Renderer.initialize(); for (const event of traceEvents) { - TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event); - TraceModel.Handlers.ModelHandlers.Renderer.handleEvent(event); + Trace.Handlers.ModelHandlers.Meta.handleEvent(event); + Trace.Handlers.ModelHandlers.Renderer.handleEvent(event); } - await TraceModel.Handlers.ModelHandlers.Meta.finalize(); - await TraceModel.Handlers.ModelHandlers.Samples.finalize(); - await TraceModel.Handlers.ModelHandlers.Renderer.finalize(); - return TraceModel.Handlers.ModelHandlers.Renderer.data(); + await Trace.Handlers.ModelHandlers.Meta.finalize(); + await Trace.Handlers.ModelHandlers.Samples.finalize(); + await Trace.Handlers.ModelHandlers.Renderer.finalize(); + return Trace.Handlers.ModelHandlers.Renderer.data(); } let defaultTraceEvents; - const pid = TraceModel.Types.TraceEvents.ProcessID(28274); - const tid = TraceModel.Types.TraceEvents.ThreadID(775); + const pid = Trace.Types.Events.ProcessID(28274); + const tid = Trace.Types.Events.ThreadID(775); beforeEach(async function () { defaultTraceEvents = await TraceLoader.rawEvents(this, 'basic.json.gz'); }); afterEach(() => { - TraceModel.Handlers.ModelHandlers.Renderer.reset(); - TraceModel.Handlers.ModelHandlers.Meta.reset(); - TraceModel.Handlers.ModelHandlers.Samples.reset(); + Trace.Handlers.ModelHandlers.Renderer.reset(); + Trace.Handlers.ModelHandlers.Meta.reset(); + Trace.Handlers.ModelHandlers.Samples.reset(); }); it('builds a hierarchy using begin and end trace events', async () => { // |------------- RunTask -------------||-- RunTask --| @@ -816,8 +816,8 @@ describeWithEnvironment('RendererHandler', function () { describe('building hierarchies trace events and profile calls', () => { it('build a hierarchy using data from real world trace file', async () => { const { Renderer } = await handleEventsFromTraceFile(this, 'recursive-counting-js.json.gz'); - const threadId = TraceModel.Types.TraceEvents.ThreadID(259); - const firstProcessId = TraceModel.Types.TraceEvents.ProcessID(23239); + const threadId = Trace.Types.Events.ThreadID(259); + const firstProcessId = Trace.Types.Events.ProcessID(23239); const thread = Renderer.processes.get(firstProcessId)?.threads.get(threadId); if (!thread || !thread.tree) { throw new Error('Tree not found'); @@ -863,19 +863,19 @@ describeWithEnvironment('RendererHandler', function () { const { Renderer } = await handleEventsFromTraceFile(this, 'web-dev.json.gz'); assert.deepEqual(Array.from(Renderer.compositorTileWorkers.entries()), [ [ - TraceModel.Types.TraceEvents.ProcessID(68481), + Trace.Types.Events.ProcessID(68481), [ - TraceModel.Types.TraceEvents.ThreadID(81675), + Trace.Types.Events.ThreadID(81675), ], ], [ - TraceModel.Types.TraceEvents.ProcessID(73704), + Trace.Types.Events.ProcessID(73704), [ - TraceModel.Types.TraceEvents.ThreadID(23299), - TraceModel.Types.TraceEvents.ThreadID(22275), - TraceModel.Types.TraceEvents.ThreadID(41475), - TraceModel.Types.TraceEvents.ThreadID(40451), - TraceModel.Types.TraceEvents.ThreadID(22531), + Trace.Types.Events.ThreadID(23299), + Trace.Types.Events.ThreadID(22275), + Trace.Types.Events.ThreadID(41475), + Trace.Types.Events.ThreadID(40451), + Trace.Types.Events.ThreadID(22531), ], ], ]); diff --git a/public/models/trace/handlers/RendererHandler.test.js.map b/public/models/trace/handlers/RendererHandler.test.js.map index a83c3ae72..dab881c2a 100644 --- a/public/models/trace/handlers/RendererHandler.test.js.map +++ b/public/models/trace/handlers/RendererHandler.test.js.map @@ -1 +1 @@ -{"version":3,"file":"RendererHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/RendererHandler.test.ts"],"names":[],"mappings":"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AG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG;YAC/G,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG;YAC/G,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG;YAC/G,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG;YAC/G,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG;YAC/G,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG;YAC/G,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG;YAC/G,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG;YAC/G,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG;YAC/G,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG;YAC/G,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG;YAC/G,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;YAChH,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;YAChH,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;YAChH,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;YAChH,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;YAChH,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;YAChH,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;YAChH,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;SACzC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;QAC3F,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAC,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,2CAA2C,CAAC,CAAC;QACjH,MAAM,KAAK,GAAG,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,aAAa,CAAC,CAC7B,CAAC;QAC/D,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC;QAC5F,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,CAAC,KAAK,EAAE,2BAA2B,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,CAAC,KAAK,EAAE,mCAAmC,CAAC,CAAC;QACrD,CAAC;QACD,MAAM,CAAC,SAAS,CACZ,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IACpH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8EAA8E,EAAE,KAAK,IAAI,EAAE;QAC5F,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAC,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,2CAA2C,CAAC,CAAC;QACjH,MAAM,KAAK,GAAG,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,cAAc,CAAC,CAC9B,CAAC;QAC/D,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC;QAC5F,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,CAAC,KAAK,EAAE,2BAA2B,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,CAAC,KAAK,EAAE,mCAAmC,CAAC,CAAC;QACrD,CAAC;QAED,MAAM,MAAM,GAAG,CAAC,IAAmD,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC;QACzF,MAAM,SAAS,GAAG,CAAC,KAAkD,EAAE,EAAE,CACrE,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;QAC5D,MAAM,MAAM,GAAG,CAAC,KAAkD,EAAE,EAAE,CAClE,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,oBAAoB,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC;QACjF,MAAM,UAAU,GACZ,CAAC,IAAmD,EAAE,KAAkD,EAAE,EAAE,CACxG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;YACxD,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,CAAC,IAAmD,CAAC,CAAC,CAAC;QAC7G,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uHAqLiE,CAAC,CAAC;IACvH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;QAC3F,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAC,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,2CAA2C,CAAC,CAAC;QACjH,MAAM,KAAK,GAAG,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,aAAa,CAAC,CAC7B,CAAC;QAC/D,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC;QAC5F,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,CAAC,KAAK,EAAE,2BAA2B,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,CAAC,KAAK,EAAE,mCAAmC,CAAC,CAAC;QACrD,CAAC;QACD,MAAM,UAAU,GACZ,CAAC,KAAoD,EAAE,KAAkD,EAAE,EAAE,CACzG,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,CAAC,IAAmD,CAAC,CAAC,CAAC;QACjH,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;EAqBpD,CAAC,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wFAAwF,EAAE,KAAK,IAAI,EAAE;QACtG,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAC,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,2CAA2C,CAAC,CAAC;QACjH,MAAM,KAAK,GAAG,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,cAAc,CAAC,CAC9B,CAAC;QAC/D,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC;QAC5F,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,CAAC,KAAK,EAAE,2BAA2B,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,CAAC,KAAK,EAAE,mCAAmC,CAAC,CAAC;QACrD,CAAC;QAED,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;QAC1C,MAAM,CAAC,SAAS,CAAC,MAAiB,EAAE;YAClC,IAAI,EAAE,EAAE;YACR,GAAG,EAAE,uCAAuC;YAC5C,GAAG,EAAE,GAAG;YACR,IAAI,EAAE,SAAS;YACf,EAAE,EAAE,GAAG;YACP,GAAG,EAAE,OAAO;YACZ,IAAI,EAAE,GAAG;YACT,GAAG,EAAE,CAAC;YACN,EAAE,EAAE,YAAY;YAChB,GAAG,EAAE,MAAM;SACZ,CAAC,CAAC;QACH,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;QAErE,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;QAC1C,MAAM,CAAC,SAAS,CAAC,MAAiB,EAAE;YAClC,IAAI,EAAE,EAAE;YACR,GAAG,EAAE,uCAAuC;YAC5C,GAAG,EAAE,CAAC;YACN,IAAI,EAAE,SAAS;YACf,EAAE,EAAE,GAAG;YACP,GAAG,EAAE,OAAO;YACZ,IAAI,EAAE,CAAC;YACP,GAAG,EAAE,CAAC;YACN,EAAE,EAAE,YAAY;YAChB,GAAG,EAAE,MAAM;SACZ,CAAC,CAAC;QACH,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;QAEnE,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;QAC/D,MAAM,CAAC,SAAS,CAAC,SAAoB,EAAE;YACrC,IAAI,EAAE,EAAE;YACR,GAAG,EAAE,uCAAuC;YAC5C,GAAG,EAAE,EAAE;YACP,IAAI,EAAE,SAAS;YACf,EAAE,EAAE,GAAG;YACP,GAAG,EAAE,OAAO;YACZ,IAAI,EAAE,EAAE;YACR,GAAG,EAAE,CAAC;YACN,EAAE,EAAE,YAAY;YAChB,GAAG,EAAE,MAAM;SACZ,CAAC,CAAC;QACH,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uFAAuF,EAAE,KAAK,IAAI,EAAE;QACrG,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAC,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,2CAA2C,CAAC,CAAC;QACjH,MAAM,KAAK,GAAG,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,aAAa,CAAC,CAC7B,CAAC;QAC/D,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC;QAC5F,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,CAAC,KAAK,EAAE,2BAA2B,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,CAAC,KAAK,EAAE,mCAAmC,CAAC,CAAC;QACrD,CAAC;QAED,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;QAC1C,MAAM,CAAC,SAAS,CAAC,MAAiB,EAAE;YAClC,IAAI,EAAE,EAAE;YACR,GAAG,EAAE,uCAAuC;YAC5C,GAAG,EAAE,GAAG;YACR,IAAI,EAAE,SAAS;YACf,EAAE,EAAE,GAAG;YACP,GAAG,EAAE,OAAO;YACZ,IAAI,EAAE,GAAG;YACT,GAAG,EAAE,CAAC;YACN,EAAE,EAAE,YAAY;YAChB,GAAG,EAAE,KAAK;SACX,CAAC,CAAC;QACH,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;QAErE,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;QAC1C,MAAM,CAAC,SAAS,CAAC,MAAiB,EAAE;YAClC,IAAI,EAAE,EAAE;YACR,GAAG,EAAE,uCAAuC;YAC5C,GAAG,EAAE,CAAC;YACN,IAAI,EAAE,SAAS;YACf,EAAE,EAAE,GAAG;YACP,GAAG,EAAE,OAAO;YACZ,IAAI,EAAE,CAAC;YACP,GAAG,EAAE,CAAC;YACN,EAAE,EAAE,YAAY;YAChB,GAAG,EAAE,KAAK;SACX,CAAC,CAAC;QACH,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;QAEnE,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;QAE1C,MAAM,CAAC,SAAS,CAAC,MAAiB,EAAE;YAClC,IAAI,EAAE,EAAE;YACR,GAAG,EAAE,uCAAuC;YAC5C,GAAG,EAAE,CAAC;YACN,IAAI,EAAE,SAAS;YACf,EAAE,EAAE,GAAG;YACP,GAAG,EAAE,OAAO;YACZ,IAAI,EAAE,CAAC;YACP,GAAG,EAAE,CAAC;YACN,EAAE,EAAE,YAAY;YAChB,GAAG,EAAE,KAAK;SACX,CAAC,CAAC;QACH,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,IAAI,GAAG;YACX,iBAAiB,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;YAC7B,iBAAiB,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;YAC7B,iBAAiB,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;YAC7B,iBAAiB,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC;YAC/B,iBAAiB,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC;YACjC,iBAAiB,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC;YACjC,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;YACnC,iBAAiB,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC;YAChC,iBAAiB,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC;SACnC,CAAC;QAEF,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;QAEtD,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAC,CAAC,CAAY,EAAE;YACjF,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAC;YAC3B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAC;YAC7B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAC;YAC/B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAC;YAChC,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAC;YACjC,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAC;YAC3B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,EAAC;YAC9B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAC;YAC/B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAC;SAC5B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sFAAsF,EAAE,KAAK,IAAI,EAAE;QACpG,MAAM,IAAI,GAAG;YACX,iBAAiB,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;YAC7B,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC;YACzB,iBAAiB,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;YAC7B,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC;YAC5B,iBAAiB,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;YAC7B,gBAAgB,CAAC,IAAI,EAAE,GAAG,CAAC;YAC3B,iBAAiB,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC;YAC/B,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC;YAC5B,iBAAiB,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC;YACjC,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC;YACzB,iBAAiB,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC;YACjC,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC;YAC5B,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;YACnC,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC;YAC5B,iBAAiB,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC;YAChC,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC;YACzB,iBAAiB,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC;YAClC,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC;SAC7B,CAAC;QAEF,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;QAEtD,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAC,CAAC,CAAY,EAAE;YACjF,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAC;YAC3B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAC;YAC7B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,SAAS,EAAC;YACnC,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAC;YACtC,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAC;YAC/B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAC;YAChC,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,SAAS,EAAC;YACrC,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAC;YACjC,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAC;YACtC,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAC;YAC3B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,EAAC;YAC9B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,SAAS,EAAC;YACnC,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAC;YAC/B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAC;YACtC,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAC;YACtC,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAC;YAC3B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,SAAS,EAAC;YACnC,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAC;SACvC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC9C;;;;WAIG;QACH,MAAM,KAAK,GAAG;YACZ,iBAAiB,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,EAAG,QAAQ;YACxC,iBAAiB,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,EAAI,OAAO;YACvC,iBAAiB,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,EAAI,OAAO;YACvC,iBAAiB,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,EAAI,OAAO;YACvC,iBAAiB,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC,EAAG,SAAS;SAC1C,CAAC;QAEF;;;;WAIG;QACH,MAAM,KAAK,GAAG;YACZ,iBAAiB,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,EAAI,OAAO;YACvC,iBAAiB,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,EAAG,iCAAiC;YACjE,iBAAiB,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,EAAI,+BAA+B;YAC/D,iBAAiB,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,EAAI,gCAAgC;YAChE,iBAAiB,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,EAAI,kCAAkC;SACnE,CAAC;QAEF,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC;YACxB;gBACE,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC;gBACzC;oBACE,GAAG,EAAE,CAAC,cAAc,CAAC;oBACrB,aAAa,EAAE,IAAI;oBACnB,OAAO,EAAE,IAAI,GAAG,CAAC,CAAC;4BAChB,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;4BACxC,EAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAC;yBAC9B,CAAC,CAAC;iBAC0D;aAChE;YACD;gBACE,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC;gBACzC;oBACE,GAAG,EAAE,CAAC,cAAc,CAAC;oBACrB,aAAa,EAAE,KAAK;oBACpB,OAAO,EAAE,IAAI,GAAG,CAAC,CAAC;4BAChB,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;4BACxC,EAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAC;yBAC9B,CAAC,CAAC;iBAC0D;aAChE;SACF,CAAC,CAAC;QAEH,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QACvD,MAAM,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QAC3D,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,cAAc,CAAC,SAAS,EAAE,EAAC,MAAM,EAAE,EAAC,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,EAAC,EAAC,CAAC,CAAC;QAElG,MAAM,WAAW,GAAG,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACxE,MAAM,YAAY,GAAG,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAEzE,IAAI,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;YAC5C,MAAM,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC;QACnC,CAAC;QAED,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,qDAAqD,CAAC,CAAC;QACxG,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,sDAAsD,CAAC,CAAC;QAE1G,MAAM,UAAU,GAAG,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QAChE,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAC,CAAC,CAAC,CAAC,IAAI,CAAc,EAAE;YAClG,EAAC,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAC;YAC3B,EAAC,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAC;SAC5B,CAAC,CAAC;QAEH,MAAM,WAAW,GAAG,WAAW,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QAClE,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAC,CAAC,CAAC,CAAC,IAAI,CAAc,EAAE;YACnG,EAAC,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAC;YAC1B,EAAC,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAC;SAC5B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QAC/C,MAAM,EAAC,IAAI,EAAE,QAAQ,EAAC,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,2CAA2C,CAAC,CAAC;QAC5G,MAAM,SAAS,GAEP,IAAI,GAAG,EAAE,CAAC;QAElB,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,YAAY,CAAC,SAAS,EAAE,QAAQ,CAAC,wBAAwB,CAAC,CAAC;QAEtG,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE;YAC9F,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,uBAAuB,CAAC;YACjF,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,yBAAyB,CAAC;YAClF,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,yBAAyB,CAAC;YACpF,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,yBAAyB,CAAC;SACrF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,EAAC,IAAI,EAAE,QAAQ,EAAC,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,2CAA2C,CAAC,CAAC;QAC5G,MAAM,SAAS,GAEP,IAAI,GAAG,EAAE,CAAC;QAElB,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,iBAAiB,CACxD,SAAS,EAAE,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,wBAAwB,CAAC,CAAC;QAExE,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,EAAE;YACzE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,IAAI,CAAC;YAC9D,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,KAAK,CAAC;YAC9D,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,KAAK,CAAC;YAChE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,KAAK,CAAC;SACjE,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,EAAC,IAAI,EAAE,QAAQ,EAAC,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,2CAA2C,CAAC,CAAC;QAC5G,MAAM,EAAC,WAAW,EAAE,wBAAwB,EAAE,gBAAgB,EAAC,GAAG,QAAQ,CAAC;QAC3E,MAAM,SAAS,GAEP,IAAI,GAAG,EAAE,CAAC;QAElB,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,UAAU,CACjD,SAAS,EAAE,WAAW,EAAE,wBAAwB,EAAE,gBAAgB,CAAC,CAAC;QAExE,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE;YACzG;gBACE,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,cAAc,CAAC;gBACtD;oBACE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,gBAAgB,CAAC;oBAC5D,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC;oBACxD,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,yBAAyB,CAAC;oBACrE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,sBAAsB,CAAC;oBAClE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,4BAA4B,CAAC;oBACzE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,4BAA4B,CAAC;oBACzE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,4BAA4B,CAAC;oBACzE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,4BAA4B,CAAC;oBACzE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,4BAA4B,CAAC;oBACzE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,4BAA4B,CAAC;oBACzE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,4BAA4B,CAAC;oBACzE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,4BAA4B,CAAC;oBACzE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,uBAAuB,CAAC;oBACpE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,uBAAuB,CAAC;oBACpE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,uBAAuB,CAAC;oBACpE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,uBAAuB,CAAC;iBACpE;aACF;YACD;gBACE,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,aAAa,CAAC;gBACrD;oBACE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,yBAAyB,CAAC;oBACrE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,gBAAgB,CAAC;oBAC5D,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC;oBACxD,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,sBAAsB,CAAC;iBACnE;aACF;YACD;gBACE,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,eAAe,CAAC;gBACvD;oBACE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,gBAAgB,CAAC;oBAC5D,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,sBAAsB,CAAC;oBAClE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC;oBACxD,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,yBAAyB,CAAC;oBACrE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,uBAAuB,CAAC;iBACrE;aACF;YACD;gBACE,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,eAAe,CAAC;gBACvD;oBACE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,gBAAgB,CAAC;oBAC5D,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,yBAAyB,CAAC;oBACrE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,sBAAsB,CAAC;oBAClE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC;oBACxD,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,uBAAuB,CAAC;oBACpE,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,4BAA4B,CAAC;iBACzE;aACF;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAC,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,2CAA2C,CAAC,CAAC;QACjH,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACzC,KAAK,UAAU,YAAY,CAAC,WAA0D;YAEpF,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;YACnD,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAC/C,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAClD,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACpD,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;YACvD,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;YAExD,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;gBAChC,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;gBAC1D,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YAChE,CAAC;YAED,MAAM,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACxD,MAAM,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YAC3D,MAAM,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;YAC5D,OAAO,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC3D,CAAC;QACD,IAAI,kBAA0E,CAAC;QAC/E,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC1D,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACvD,UAAU,CAAC,KAAK;YACd,kBAAkB,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;QAC1E,CAAC,CAAC,CAAC;QAEH,SAAS,CAAC,GAAG,EAAE;YACb,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;YACnD,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAC/C,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACpD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;YACnE,uDAAuD;YACvD,uCAAuC;YACvC,uBAAuB;YACvB,MAAM,WAAW,GAAG;gBAClB,GAAG,kBAAkB,EAAE,cAAc,CAAC,SAAS,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAG,QAAQ;gBAC7E,cAAc,CAAC,eAAe,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAoB,OAAO;gBAC5E,cAAc,CAAC,cAAc,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAqB,OAAO;gBAC5E,YAAY,CAAC,cAAc,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAuB,OAAO;gBAC5E,YAAY,CAAC,eAAe,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAsB,OAAO;gBAC5E,cAAc,CAAC,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAA2B,OAAO;gBAC5E,YAAY,CAAC,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAA6B,OAAO;gBAC5E,YAAY,CAAC,SAAS,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAA2B,QAAQ;gBAC7E,cAAc,CAAC,SAAS,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAyB,SAAS;gBAC9E,YAAY,CAAC,SAAS,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAA2B,SAAS;aAC/E,CAAC;YAEF,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC;YAE7C,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACnD,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC3C,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;YAC1C,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC5C,MAAM,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YAC1C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC/C,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;gBACxB,iGAAiG;gBACjG,OAAO;YACT,CAAC;YACD,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACjD,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACvC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;gBACjB,OAAO;YACT,CAAC;YACD,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;;;;;mBAKhC,CAAC,CAAC;QACjB,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;YAC7E,wCAAwC;YACxC,uCAAuC;YACvC,uBAAuB;YAEvB,MAAM,WAAW,GAAG;gBAClB,GAAG,kBAAkB,EAAE,cAAc,CAAC,SAAS,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAG,QAAQ;gBAC7E,cAAc,CAAC,eAAe,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAoB,OAAO;gBAC5E,iBAAiB,CAAC,cAAc,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAe,OAAO;gBAC5E,YAAY,CAAC,eAAe,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAsB,OAAO;gBAC5E,cAAc,CAAC,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAA2B,OAAO;gBAC5E,YAAY,CAAC,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAA6B,OAAO;gBAC5E,YAAY,CAAC,SAAS,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAA2B,QAAQ;aAC9E,CAAC;YAEF,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC;YAE7C,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACnD,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC3C,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;YAC1C,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC5C,MAAM,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YAC1C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC/C,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;gBACxB,iGAAiG;gBACjG,OAAO;YACT,CAAC;YACD,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACjD,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACvC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;gBACjB,OAAO;YACT,CAAC;YACD,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;;;;oBAI/B,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;YACnE,MAAM,WAAW,GAAG;gBAClB,GAAG,kBAAkB,EAAE,cAAc,CAAC,eAAe,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAG,OAAO;gBAClF,cAAc,CAAC,cAAc,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAA2B,OAAO;aACnF,CAAC;YAEF,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC;YAC7C,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC3C,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;YAC1C,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC5C,MAAM,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YAC1C,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;YAC/C,CAAC;YACD,oFAAoF;YACpF,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,eAAe,EAAE,cAAc,CAAC,CAAC,CAAC;QACvF,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,qDAAqD,EAAE,GAAG,EAAE;QACnE,EAAE,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;YACvE,MAAM,EAAC,QAAQ,EAAC,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,+BAA+B,CAAC,CAAC;YAC1F,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;YAC5D,MAAM,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YACrE,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC7E,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;YACpC,CAAC;YACD,MAAM,sBAAsB,GACxB,CAAC,KAAoD,EAAE,KAAkD,EAAE,EAAE,CACzG,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC;gBAC1C,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,CAAC,IAAmD,CAAC,CAAC,CAAC;YAC7G,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,sBAAsB,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;SAgClE,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,EAAC,QAAQ,EAAC,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;QAC5E,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,qBAAqB,CAAC,OAAO,EAAE,CAAC,EAAE;YACrE;gBACE,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC;gBAC7C;oBACE,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC;iBAC7C;aACF;YACD;gBACE,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC;gBAC7C;oBACE,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC;oBAC5C,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC;oBAC5C,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC;oBAC5C,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC;oBAC5C,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC;iBAC7C;aACF;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2EAA2E,EAAE,KAAK,IAAI,EAAE;QACzF,MAAM,EAAC,QAAQ,EAAE,eAAe,EAAC,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,6BAA6B,CAAC,CAAC;QACzG,MAAM,CAAC,WAAW,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACrD,KAAK,MAAM,CAAC,GAAG,CAAC,IAAI,eAAe,CAAC,QAAQ,EAAE,CAAC;YAC7C,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC5C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACvB,oFAAoF;YACpF,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,uBAAuB,CAAC,CAAC,CAAC;QACjE,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Components from '../../../panels/timeline/components/components.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {\n getAllNodes,\n getEventsIn,\n getRootAt,\n makeBeginEvent,\n makeCompleteEvent,\n makeEndEvent,\n makeInstantEvent,\n prettyPrint,\n} from '../../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as TraceModel from '../trace.js';\n\nconst MAIN_FRAME_PID = 2154214;\nconst SUB_FRAME_PID = 2236065;\nconst SUB_FRAME_PID_2 = 2236084;\nconst SUB_FRAME_PID_3 = 2236123;\n\nasync function handleEventsFromTraceFile(\n context: Mocha.Suite|Mocha.Context|null, file: string): Promise {\n const {traceData} = await TraceLoader.traceEngine(context, file);\n return traceData;\n}\n\ndescribeWithEnvironment('RendererHandler', function() {\n it('finds all the renderers in a real world profile', async () => {\n const {Renderer: renderers} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n assert.strictEqual(renderers.processes.size, 4);\n\n const pids = [...renderers.processes].map(([pid]) => pid);\n assert.deepStrictEqual(\n pids,\n [\n MAIN_FRAME_PID, // Main frame process: localhost:5000\n SUB_FRAME_PID, // Sub frame process (trace start): example.com\n SUB_FRAME_PID_2, // Sub frame process (after first navigation): example.com\n SUB_FRAME_PID_3, // Sub frame process (after second navigation): example.com\n ],\n 'Process IDs do not match expectations');\n\n const origins = [...renderers.processes].map(([, process]) => {\n return process.url ? new URL(process.url).origin : null;\n });\n assert.deepEqual(\n origins,\n [\n 'http://localhost:5000', // Main frame process: localhost:5000\n 'https://www.example.com', // Sub frame process (trace start): example.com\n 'https://www.example.com', // Sub frame process (after first navigation): example.com\n 'https://www.example.com', // Sub frame process (after second navigation): example.com\n ],\n 'Process origins do not meet expectations');\n\n // Assert on whether it has correctly detected a given process to be on the\n // main frame or in a subframe.\n const isOnMainFrame = [...renderers.processes].map(([, process]) => process.isOnMainFrame);\n assert.deepStrictEqual(\n isOnMainFrame,\n [\n true, // Main frame process: localhost:5000\n false, // Sub frame process (trace start): example.com\n false, // Sub frame process (after first navigation): example.com\n false, // Sub frame process (after second navigation): example.com\n ],\n 'Processes are incorrectly assigned as being on the main frame');\n });\n\n it('finds all the main frame threads in a real world profile', async () => {\n const {Renderer: renderers} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n const frame = renderers.processes.get(TraceModel.Types.TraceEvents.ProcessID(MAIN_FRAME_PID)) as\n TraceModel.Handlers.ModelHandlers.Renderer.RendererProcess;\n const names = [...frame.threads].map(([, thread]) => thread.name).sort();\n assert.deepEqual(\n names,\n [\n 'Chrome_ChildIOThread',\n 'Compositor',\n 'CompositorTileWorker1',\n 'CompositorTileWorker2',\n 'CompositorTileWorker3',\n 'CompositorTileWorker4',\n 'CrRendererMain',\n 'ThreadPoolForegroundWorker',\n 'ThreadPoolForegroundWorker',\n 'ThreadPoolForegroundWorker',\n 'ThreadPoolForegroundWorker',\n 'ThreadPoolForegroundWorker',\n 'ThreadPoolForegroundWorker',\n 'ThreadPoolForegroundWorker',\n 'ThreadPoolForegroundWorker',\n 'ThreadPoolServiceThread',\n ],\n 'Main frame thread names do not meet expectations before navigation');\n });\n\n it('finds all the sub frame threads in a real world profile', async () => {\n const {Renderer: renderers} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n const frame = renderers.processes.get(TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID)) as\n TraceModel.Handlers.ModelHandlers.Renderer.RendererProcess;\n const names = [...frame.threads].map(([, thread]) => thread.name).sort();\n assert.deepEqual(\n names,\n [\n 'Chrome_ChildIOThread',\n 'Compositor',\n 'CrRendererMain',\n 'ThreadPoolServiceThread',\n ],\n 'Main frame thread names do not meet expectations after navigation');\n });\n\n it('finds all the roots on the main frame\\'s main thread in a real world profile', async () => {\n const {Renderer: renderers} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n const frame = renderers.processes.get(TraceModel.Types.TraceEvents.ProcessID(MAIN_FRAME_PID)) as\n TraceModel.Handlers.ModelHandlers.Renderer.RendererProcess;\n const thread = [...frame.threads.values()].find(thread => thread.name === 'CrRendererMain');\n if (!thread) {\n assert(false, 'Main thread was not found');\n }\n\n const tree = thread.tree;\n if (!tree) {\n assert(false, 'Main thread has no tree of events');\n }\n assert.deepEqual([...tree.roots].map(root => root.id), [\n 0, 1, 2, 3, 4, 5, 16, 18, 29, 38, 49, 58, 77, 183, 184, 185, 186, 188, 189,\n 190, 199, 200, 201, 202, 211, 212, 213, 214, 229, 230, 232, 237, 239, 240, 242, 251, 252, 261,\n 264, 265, 266, 267, 268, 279, 282, 284, 285, 286, 287, 288, 289, 290, 293, 294, 295, 296, 297,\n 298, 299, 300, 301, 302, 303, 304, 305, 306, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337,\n 338, 339, 340, 341, 342, 343, 344, 345, 354, 355, 356, 359, 389, 408, 409, 410, 411, 412, 413,\n 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432,\n 433, 441, 442, 443, 444, 445, 446, 447, 448, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464,\n 465, 466, 467, 468, 469, 479, 480, 481, 482, 483, 484, 485, 492, 493, 494, 495, 496, 498, 506,\n 507, 508, 509, 510, 511, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 538, 540, 541,\n 552, 555, 556, 565, 566, 575, 576, 585, 586, 595, 596, 605, 606, 615, 616, 625, 626, 635, 636,\n 645, 646, 657, 660, 661, 662, 663, 674, 677, 678, 679, 680, 689, 690, 691, 692, 701, 702, 711,\n 712, 721, 722, 733, 734, 737, 738, 739, 740, 749, 750, 751, 760, 761, 762, 771, 772, 773, 782,\n 783, 784, 793, 794, 795, 796, 797, 808, 809, 810, 811, 835, 843, 844, 845, 846, 848, 861, 869,\n 870, 871, 872, 873, 874, 875, 876, 877, 878, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890,\n 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922,\n 931, 932, 933, 936, 966, 967, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995,\n 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1020, 1021,\n 1022, 1023, 1024, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055,\n 1056, 1057, 1064, 1065, 1066, 1068, 1069, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088,\n 1089, 1090, 1091, 1092, 1102, 1104, 1105, 1106, 1107, 1116, 1117, 1118, 1127, 1128, 1129, 1138, 1139, 1140, 1141,\n 1150, 1151, 1152, 1153, 1154, 1165, 1166, 1167, 1176, 1177, 1178, 1189, 1192, 1193, 1194, 1203, 1204, 1205, 1206,\n 1215, 1216, 1225, 1226, 1235, 1236, 1237, 1246, 1247, 1256, 1257, 1266, 1267, 1276, 1277, 1286, 1287, 1298, 1301,\n 1302, 1303, 1304, 1313, 1314, 1315, 1324, 1325, 1326, 1335, 1336, 1337, 1348, 1351, 1352, 1353, 1362, 1364, 1365,\n 1366, 1367, 1368, 1369, 1370, 1371, 1378,\n ]);\n });\n\n it('finds all the roots on the sub frame\\'s main thread in a real world profile', async () => {\n const {Renderer: renderers} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n const frame = renderers.processes.get(TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID)) as\n TraceModel.Handlers.ModelHandlers.Renderer.RendererProcess;\n const thread = [...frame.threads.values()].find(thread => thread.name === 'CrRendererMain');\n if (!thread) {\n assert(false, 'Main thread was not found');\n }\n\n const tree = thread.tree;\n if (!tree) {\n assert(false, 'Main thread has no tree of events');\n }\n assert.deepEqual(\n [...tree.roots].map(root => root.id), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20]);\n });\n\n it('builds a hierarchy for the main frame\\'s main thread in a real world profile', async () => {\n const {Renderer: renderers} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n const frame = renderers.processes.get(TraceModel.Types.TraceEvents.ProcessID(MAIN_FRAME_PID)) as\n TraceModel.Handlers.ModelHandlers.Renderer.RendererProcess;\n const thread = [...frame.threads.values()].find(thread => thread.name === 'CrRendererMain');\n if (!thread) {\n assert(false, 'Main thread was not found');\n }\n\n const tree = thread.tree;\n if (!tree) {\n assert(false, 'Main thread has no tree of events');\n }\n\n const isRoot = (node: TraceModel.Helpers.TreeHelpers.TraceEntryNode) => node.depth === 0;\n const isInstant = (event: TraceModel.Types.TraceEvents.TraceEventData) =>\n TraceModel.Types.TraceEvents.isTraceEventInstant(event);\n const isLong = (event: TraceModel.Types.TraceEvents.TraceEventData) =>\n TraceModel.Types.TraceEvents.isTraceEventComplete(event) && event.dur > 1000;\n const isIncluded =\n (node: TraceModel.Helpers.TreeHelpers.TraceEntryNode, event: TraceModel.Types.TraceEvents.TraceEventData) =>\n (!isRoot(node) || isInstant(event) || isLong(event)) &&\n Boolean(Components.EntryStyles.getEventStyle(event.name as TraceModel.Types.TraceEvents.KnownEventName));\n assert.strictEqual(prettyPrint(tree, isIncluded), `\n............\n-RunTask [2.21ms]\n.\n -MajorGC [2.148ms]\n...........................................................\n-RunTask [15.436ms]\n -FrameStartedLoading [0ms]\n -EventDispatch (pagehide) [0.018ms]\n -EventDispatch (visibilitychange) [0.01ms]\n -EventDispatch (webkitvisibilitychange) [0.006ms]\n.\n -EventDispatch (unload) [0.006ms]\n.\n -ResourceSendRequest [0ms]\n -ResourceReceiveResponse [0ms]\n...\n -ProfileCall (anonymous) [0.205ms]\n -ProfileCall (anonymous) [0.205ms]\n.......................\n-RunTask [3.402ms]\n -ParseHTML [2.593ms]\n....\n -ParseHTML [0.064ms]\n...\n -EventDispatch (readystatechange) [0.008ms]\n.\n -EventDispatch (DOMContentLoaded) [0.004ms]\n.\n -MarkDOMContent [0ms]\n.\n -EventDispatch (readystatechange) [0.01ms]\n -EventDispatch (beforeunload) [0.013ms]\n -FrameStartedLoading [0ms]\n.\n -ParseHTML [0.01ms]\n..\n -EventDispatch (readystatechange) [0.008ms]\n.\n -EventDispatch (DOMContentLoaded) [0.035ms]\n.\n -UpdateLayoutTree [0.373ms]\n -InvalidateLayout [0ms]\n -MarkDOMContent [0ms]\n-RunTask [2.675ms]\n -BeginMainThreadFrame [0ms]\n -Layout [0.854ms]\n -InvalidateLayout [0ms]\n -Layout [0.302ms]\n -UpdateLayoutTree [0.149ms]\n.\n -UpdateLayerTree [0.338ms]\n -Paint [0.203ms]\n..\n -firstPaint [0ms]\n -firstContentfulPaint [0ms]\n.....\n -largestContentfulPaint::Candidate [0ms]\n.................................\n-RunTask [1.605ms]\n -EventDispatch (pagehide) [0.014ms]\n -EventDispatch (visibilitychange) [0.038ms]\n -EventDispatch (webkitvisibilitychange) [0.009ms]\n -EventDispatch (unload) [0.004ms]\n.\n -ScheduleStyleRecalculation [0ms]\n..............\n-RunTask [1.231ms]\n -BeginMainThreadFrame [0ms]\n -UpdateLayoutTree [0.093ms]\n.\n -UpdateLayerTree [0.186ms]\n -Paint [0.063ms]\n -Paint [0.084ms]\n -UpdateLayer [0.022ms]\n -UpdateLayer [0.006ms]\n -CompositeLayers [0.311ms]\n............\n-RunTask [1.663ms]\n.\n -EventDispatch (readystatechange) [0.009ms]\n.\n -EventDispatch (load) [0.014ms]\n.\n -MarkLoad [0ms]\n -EventDispatch (pageshow) [0.007ms]\n.......................................................................................\n-RunTask [1.42ms]\n.\n -UpdateLayerTree [0.023ms]\n -HitTest [0.057ms]\n -EventDispatch (mousemove) [0.018ms]\n.\n -UpdateLayerTree [0.028ms]\n -HitTest [0.022ms]\n.\n -UpdateLayerTree [0.01ms]\n -HitTest [0.002ms]\n -ScheduleStyleRecalculation [0ms]\n -EventDispatch (mousedown) [0.018ms]\n -UpdateLayoutTree [0.146ms]\n.\n -UpdateLayerTree [0.031ms]\n -HitTest [0.016ms]\n -ScheduleStyleRecalculation [0ms]\n -UpdateLayoutTree [0.031ms]\n -EventDispatch (focus) [0.014ms]\n -EventDispatch (focusin) [0.005ms]\n -EventDispatch (DOMFocusIn) [0.005ms]\n.\n -UpdateLayerTree [0.029ms]\n.....\n-RunTask [1.034ms]\n.\n -UpdateLayerTree [0.021ms]\n -HitTest [0.038ms]\n -ScheduleStyleRecalculation [0ms]\n -EventDispatch (mouseup) [0.016ms]\n -EventDispatch (click) [0.44ms]\n -EventDispatch (beforeunload) [0.009ms]\n -FrameStartedLoading [0ms]\n.\n -UpdateLayoutTree [0.137ms]\n.\n -UpdateLayerTree [0.03ms]\n....................\n-RunTask [8.203ms]\n -EventDispatch (pagehide) [0.016ms]\n -EventDispatch (visibilitychange) [0.006ms]\n -EventDispatch (webkitvisibilitychange) [0.004ms]\n -EventDispatch (unload) [0.008ms]\n..\n -ResourceSendRequest [0ms]\n -ResourceSendRequest [0ms]\n -ResourceReceiveResponse [0ms]\n..........................\n-RunTask [2.996ms]\n -ParseHTML [2.368ms]\n....\n -ParseHTML [0.074ms]\n...\n -EventDispatch (readystatechange) [0.01ms]\n.\n -EventDispatch (DOMContentLoaded) [0.005ms]\n.\n -MarkDOMContent [0ms]\n.\n -EventDispatch (readystatechange) [0.008ms]\n -EventDispatch (beforeunload) [0.009ms]\n -FrameStartedLoading [0ms]\n.\n -ParseHTML [0.009ms]\n..\n -EventDispatch (readystatechange) [0.007ms]\n.\n -EventDispatch (DOMContentLoaded) [0.005ms]\n.\n -UpdateLayoutTree [0.301ms]\n -InvalidateLayout [0ms]\n -MarkDOMContent [0ms]\n.\n-RunTask [1.897ms]\n -BeginMainThreadFrame [0ms]\n -Layout [0.44ms]\n -InvalidateLayout [0ms]\n.\n -UpdateLayerTree [0.247ms]\n -Paint [0.289ms]\n..\n -firstPaint [0ms]\n -firstContentfulPaint [0ms]\n..\n -largestContentfulPaint::Candidate [0ms]\n....................................\n-RunTask [1.304ms]\n -EventDispatch (pagehide) [0.016ms]\n -EventDispatch (visibilitychange) [0.009ms]\n -EventDispatch (webkitvisibilitychange) [0.004ms]\n -EventDispatch (unload) [0.015ms]\n.\n -ScheduleStyleRecalculation [0ms]\n......................................................................................................................`);\n });\n\n it('builds a hierarchy for the sub frame\\'s main thread in a real world profile', async () => {\n const {Renderer: renderers} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n const frame = renderers.processes.get(TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID)) as\n TraceModel.Handlers.ModelHandlers.Renderer.RendererProcess;\n const thread = [...frame.threads.values()].find(thread => thread.name === 'CrRendererMain');\n if (!thread) {\n assert(false, 'Main thread was not found');\n }\n\n const tree = thread.tree;\n if (!tree) {\n assert(false, 'Main thread has no tree of events');\n }\n const isIncluded =\n (_node: TraceModel.Helpers.TreeHelpers.TraceEntryNode, event: TraceModel.Types.TraceEvents.TraceEventData) =>\n Boolean(Components.EntryStyles.getEventStyle(event.name as TraceModel.Types.TraceEvents.KnownEventName));\n assert.strictEqual(prettyPrint(tree, isIncluded), `\n-RunTask [0.13ms]\n-RunTask [0.005ms]\n-RunTask [0.009ms]\n-RunTask [0.065ms]\n-RunTask [0.084ms]\n-RunTask [0.041ms]\n-RunTask [0.057ms]\n-RunTask [0.021ms]\n-RunTask [0.009ms]\n-RunTask [0.065ms]\n-RunTask [0.078ms]\n-RunTask [0.043ms]\n-RunTask [0.077ms]\n -ScheduleStyleRecalculation [0ms]\n-RunTask [0.415ms]\n-RunTask [0ms]\n-EventDispatch (pagehide) [0.012ms]\n-EventDispatch (visibilitychange) [0.007ms]\n-EventDispatch (webkitvisibilitychange) [0.016ms]\n-EventDispatch (unload) [0.007ms]\n.`);\n });\n\n it('has some correct known roots for the main frame\\'s main thread in a real world profile', async () => {\n const {Renderer: renderers} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n const frame = renderers.processes.get(TraceModel.Types.TraceEvents.ProcessID(MAIN_FRAME_PID)) as\n TraceModel.Handlers.ModelHandlers.Renderer.RendererProcess;\n const thread = [...frame.threads.values()].find(thread => thread.name === 'CrRendererMain');\n if (!thread) {\n assert(false, 'Main thread was not found');\n }\n\n const tree = thread.tree;\n if (!tree) {\n assert(false, 'Main thread has no tree of events');\n }\n\n const event0 = getRootAt(thread, 1).entry;\n assert.deepEqual(event0 as unknown, {\n args: {},\n cat: 'disabled-by-default-devtools.timeline',\n dur: 132,\n name: 'RunTask',\n ph: 'X',\n pid: 2154214,\n tdur: 131,\n tid: 1,\n ts: 643492822363,\n tts: 291450,\n });\n assert.strictEqual(renderers.entryToNode.get(event0)?.selfTime, 132);\n\n const event1 = getRootAt(thread, 2).entry;\n assert.deepEqual(event1 as unknown, {\n args: {},\n cat: 'disabled-by-default-devtools.timeline',\n dur: 4,\n name: 'RunTask',\n ph: 'X',\n pid: 2154214,\n tdur: 4,\n tid: 1,\n ts: 643492822500,\n tts: 291586,\n });\n assert.strictEqual(renderers.entryToNode.get(event1)?.selfTime, 4);\n\n const eventLast = getRootAt(thread, tree.roots.size - 1).entry;\n assert.deepEqual(eventLast as unknown, {\n args: {},\n cat: 'disabled-by-default-devtools.timeline',\n dur: 67,\n name: 'RunTask',\n ph: 'X',\n pid: 2154214,\n tdur: 67,\n tid: 1,\n ts: 643499551460,\n tts: 949032,\n });\n assert.strictEqual(renderers.entryToNode.get(eventLast)?.selfTime, 35);\n });\n\n it('has some correct known roots for the sub frame\\'s main thread in a real world profile', async () => {\n const {Renderer: renderers} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n const frame = renderers.processes.get(TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID)) as\n TraceModel.Handlers.ModelHandlers.Renderer.RendererProcess;\n const thread = [...frame.threads.values()].find(thread => thread.name === 'CrRendererMain');\n if (!thread) {\n assert(false, 'Main thread was not found');\n }\n\n const tree = thread.tree;\n if (!tree) {\n assert(false, 'Main thread has no tree of events');\n }\n\n const event0 = getRootAt(thread, 0).entry;\n assert.deepEqual(event0 as unknown, {\n args: {},\n cat: 'disabled-by-default-devtools.timeline',\n dur: 130,\n name: 'RunTask',\n ph: 'X',\n pid: 2236065,\n tdur: 129,\n tid: 1,\n ts: 643492822099,\n tts: 62157,\n });\n assert.strictEqual(renderers.entryToNode.get(event0)?.selfTime, 130);\n\n const event1 = getRootAt(thread, 1).entry;\n assert.deepEqual(event1 as unknown, {\n args: {},\n cat: 'disabled-by-default-devtools.timeline',\n dur: 5,\n name: 'RunTask',\n ph: 'X',\n pid: 2236065,\n tdur: 5,\n tid: 1,\n ts: 643492822234,\n tts: 62291,\n });\n assert.strictEqual(renderers.entryToNode.get(event1)?.selfTime, 5);\n\n const event2 = getRootAt(thread, 2).entry;\n\n assert.deepEqual(event2 as unknown, {\n args: {},\n cat: 'disabled-by-default-devtools.timeline',\n dur: 9,\n name: 'RunTask',\n ph: 'X',\n pid: 2236065,\n tdur: 9,\n tid: 1,\n ts: 643492822242,\n tts: 62299,\n });\n assert.strictEqual(renderers.entryToNode.get(event2)?.selfTime, 9);\n });\n\n it('can correctly sort a simple list of complete events', async () => {\n const data = [\n makeCompleteEvent('d0', 2, 1),\n makeCompleteEvent('b0', 1, 1),\n makeCompleteEvent('a0', 0, 1),\n makeCompleteEvent('a1', 0, 0.5),\n makeCompleteEvent('a2', 0.5, 0.5),\n makeCompleteEvent('c0', 1.5, 0.5),\n makeCompleteEvent('a4', 0.99, 0.01),\n makeCompleteEvent('b1', 1, 0.01),\n makeCompleteEvent('a3', 0.5, 0.25),\n ];\n\n TraceModel.Helpers.Trace.sortTraceEventsInPlace(data);\n\n assert.deepEqual(data.map(e => ({name: e.name, ts: e.ts, dur: e.dur})) as unknown, [\n {name: 'a0', ts: 0, dur: 1},\n {name: 'a1', ts: 0, dur: 0.5},\n {name: 'a2', ts: 0.5, dur: 0.5},\n {name: 'a3', ts: 0.5, dur: 0.25},\n {name: 'a4', ts: 0.99, dur: 0.01},\n {name: 'b0', ts: 1, dur: 1},\n {name: 'b1', ts: 1, dur: 0.01},\n {name: 'c0', ts: 1.5, dur: 0.5},\n {name: 'd0', ts: 2, dur: 1},\n ]);\n });\n\n it('can correctly sort a simple list of complete events interspersed with instant events', async () => {\n const data = [\n makeCompleteEvent('d0', 2, 1),\n makeInstantEvent('i0', 0),\n makeCompleteEvent('b0', 1, 1),\n makeInstantEvent('i1', 0.01),\n makeCompleteEvent('a0', 0, 1),\n makeInstantEvent('i2', 0.5),\n makeCompleteEvent('a1', 0, 0.5),\n makeInstantEvent('i3', 0.99),\n makeCompleteEvent('a2', 0.5, 0.5),\n makeInstantEvent('i4', 1),\n makeCompleteEvent('c0', 1.5, 0.5),\n makeInstantEvent('i5', 1.75),\n makeCompleteEvent('a4', 0.99, 0.01),\n makeInstantEvent('i6', 1.99),\n makeCompleteEvent('b1', 1, 0.01),\n makeInstantEvent('i7', 2),\n makeCompleteEvent('a3', 0.5, 0.25),\n makeInstantEvent('i8', 2.01),\n ];\n\n TraceModel.Helpers.Trace.sortTraceEventsInPlace(data);\n\n assert.deepEqual(data.map(e => ({name: e.name, ts: e.ts, dur: e.dur})) as unknown, [\n {name: 'a0', ts: 0, dur: 1},\n {name: 'a1', ts: 0, dur: 0.5},\n {name: 'i0', ts: 0, dur: undefined},\n {name: 'i1', ts: 0.01, dur: undefined},\n {name: 'a2', ts: 0.5, dur: 0.5},\n {name: 'a3', ts: 0.5, dur: 0.25},\n {name: 'i2', ts: 0.5, dur: undefined},\n {name: 'a4', ts: 0.99, dur: 0.01},\n {name: 'i3', ts: 0.99, dur: undefined},\n {name: 'b0', ts: 1, dur: 1},\n {name: 'b1', ts: 1, dur: 0.01},\n {name: 'i4', ts: 1, dur: undefined},\n {name: 'c0', ts: 1.5, dur: 0.5},\n {name: 'i5', ts: 1.75, dur: undefined},\n {name: 'i6', ts: 1.99, dur: undefined},\n {name: 'd0', ts: 2, dur: 1},\n {name: 'i7', ts: 2, dur: undefined},\n {name: 'i8', ts: 2.01, dur: undefined},\n ]);\n });\n\n it('can process multiple processes', async () => {\n /**\n * |------------- Task A -------------||-- Task E --|\n * |-- Task B --||-- Task D --|\n * |- Task C -|\n */\n const data1 = [\n makeCompleteEvent('A', 0, 10), // 0..10\n makeCompleteEvent('B', 1, 3), // 1..4\n makeCompleteEvent('D', 5, 3), // 5..8\n makeCompleteEvent('C', 2, 1), // 2..3\n makeCompleteEvent('E', 11, 3), // 11..14\n ];\n\n /**\n * |-- Task F --||------------- Task G -------------|\n * |-- Task H --||-- Task J --|\n * |- Task I -|\n */\n const data2 = [\n makeCompleteEvent('F', 0, 3), // 0..3\n makeCompleteEvent('G', 3, 10), // 3..13 (starts when F finishes)\n makeCompleteEvent('H', 3, 3), // 3..6 (starts same time as G)\n makeCompleteEvent('J', 6, 3), // 6..9 (starts when H finishes)\n makeCompleteEvent('I', 5, 1), // 5..6 (finishes when H finishes)\n ];\n\n const processes = new Map([\n [\n TraceModel.Types.TraceEvents.ProcessID(0),\n {\n url: ('http://a.com'),\n isOnMainFrame: true,\n threads: new Map([[\n TraceModel.Types.TraceEvents.ThreadID(1),\n {name: 'Foo', entries: data1},\n ]]),\n } as TraceModel.Handlers.ModelHandlers.Renderer.RendererProcess,\n ],\n [\n TraceModel.Types.TraceEvents.ProcessID(2),\n {\n url: ('http://b.com'),\n isOnMainFrame: false,\n threads: new Map([[\n TraceModel.Types.TraceEvents.ThreadID(3),\n {name: 'Bar', entries: data2},\n ]]),\n } as TraceModel.Handlers.ModelHandlers.Renderer.RendererProcess,\n ],\n ]);\n\n TraceModel.Handlers.ModelHandlers.Samples.initialize();\n await TraceModel.Handlers.ModelHandlers.Samples.finalize();\n TraceModel.Handlers.ModelHandlers.Renderer.buildHierarchy(processes, {filter: {has: () => true}});\n\n const firstThread = [...[...processes.values()][0].threads.values()][0];\n const secondThread = [...[...processes.values()][1].threads.values()][0];\n\n if (!firstThread.tree || !secondThread.tree) {\n assert(false, 'Trees not found');\n }\n\n assert.strictEqual(firstThread.tree.maxDepth, 3, 'Got the correct tree max depth for the first thread');\n assert.strictEqual(secondThread.tree.maxDepth, 3, 'Got the correct tree max depth for the second thread');\n\n const firstRoots = getEventsIn(firstThread.tree.roots.values());\n assert.deepEqual(firstRoots.map(e => e ? {name: e.name, ts: e.ts, dur: e.dur} : null) as unknown[], [\n {name: 'A', ts: 0, dur: 10},\n {name: 'E', ts: 11, dur: 3},\n ]);\n\n const secondRoots = getEventsIn(secondThread.tree.roots.values());\n assert.deepEqual(secondRoots.map(e => e ? {name: e.name, ts: e.ts, dur: e.dur} : null) as unknown[], [\n {name: 'F', ts: 0, dur: 3},\n {name: 'G', ts: 3, dur: 10},\n ]);\n });\n\n it('can assign origins to processes', async () => {\n const {Meta: metadata} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n const processes:\n Map =\n new Map();\n\n TraceModel.Handlers.ModelHandlers.Renderer.assignOrigin(processes, metadata.rendererProcessesByFrame);\n\n assert.deepEqual([...processes].map(([pid, p]) => [pid, p.url ? new URL(p.url).origin : null]), [\n [TraceModel.Types.TraceEvents.ProcessID(MAIN_FRAME_PID), 'http://localhost:5000'],\n [TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID), 'https://www.example.com'],\n [TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID_2), 'https://www.example.com'],\n [TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID_3), 'https://www.example.com'],\n ]);\n });\n\n it('can assign main frame flags to processes', async () => {\n const {Meta: metadata} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n const processes:\n Map =\n new Map();\n\n TraceModel.Handlers.ModelHandlers.Renderer.assignIsMainFrame(\n processes, metadata.mainFrameId, metadata.rendererProcessesByFrame);\n\n assert.deepEqual([...processes].map(([pid, p]) => [pid, p.isOnMainFrame]), [\n [TraceModel.Types.TraceEvents.ProcessID(MAIN_FRAME_PID), true],\n [TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID), false],\n [TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID_2), false],\n [TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID_3), false],\n ]);\n });\n\n it('can assign thread names to threads in processes', async () => {\n const {Meta: metadata} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n const {mainFrameId, rendererProcessesByFrame, threadsInProcess} = metadata;\n const processes:\n Map =\n new Map();\n\n TraceModel.Handlers.ModelHandlers.Renderer.assignMeta(\n processes, mainFrameId, rendererProcessesByFrame, threadsInProcess);\n\n assert.deepEqual([...processes].map(([pid, p]) => [pid, [...p.threads].map(([tid, t]) => [tid, t.name])]), [\n [\n TraceModel.Types.TraceEvents.ProcessID(MAIN_FRAME_PID),\n [\n [TraceModel.Types.TraceEvents.ThreadID(1), 'CrRendererMain'],\n [TraceModel.Types.TraceEvents.ThreadID(7), 'Compositor'],\n [TraceModel.Types.TraceEvents.ThreadID(2), 'ThreadPoolServiceThread'],\n [TraceModel.Types.TraceEvents.ThreadID(4), 'Chrome_ChildIOThread'],\n [TraceModel.Types.TraceEvents.ThreadID(24), 'ThreadPoolForegroundWorker'],\n [TraceModel.Types.TraceEvents.ThreadID(27), 'ThreadPoolForegroundWorker'],\n [TraceModel.Types.TraceEvents.ThreadID(17), 'ThreadPoolForegroundWorker'],\n [TraceModel.Types.TraceEvents.ThreadID(29), 'ThreadPoolForegroundWorker'],\n [TraceModel.Types.TraceEvents.ThreadID(25), 'ThreadPoolForegroundWorker'],\n [TraceModel.Types.TraceEvents.ThreadID(28), 'ThreadPoolForegroundWorker'],\n [TraceModel.Types.TraceEvents.ThreadID(30), 'ThreadPoolForegroundWorker'],\n [TraceModel.Types.TraceEvents.ThreadID(26), 'ThreadPoolForegroundWorker'],\n [TraceModel.Types.TraceEvents.ThreadID(11), 'CompositorTileWorker3'],\n [TraceModel.Types.TraceEvents.ThreadID(12), 'CompositorTileWorker4'],\n [TraceModel.Types.TraceEvents.ThreadID(10), 'CompositorTileWorker2'],\n [TraceModel.Types.TraceEvents.ThreadID(9), 'CompositorTileWorker1'],\n ],\n ],\n [\n TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID),\n [\n [TraceModel.Types.TraceEvents.ThreadID(2), 'ThreadPoolServiceThread'],\n [TraceModel.Types.TraceEvents.ThreadID(1), 'CrRendererMain'],\n [TraceModel.Types.TraceEvents.ThreadID(7), 'Compositor'],\n [TraceModel.Types.TraceEvents.ThreadID(4), 'Chrome_ChildIOThread'],\n ],\n ],\n [\n TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID_2),\n [\n [TraceModel.Types.TraceEvents.ThreadID(1), 'CrRendererMain'],\n [TraceModel.Types.TraceEvents.ThreadID(4), 'Chrome_ChildIOThread'],\n [TraceModel.Types.TraceEvents.ThreadID(8), 'Compositor'],\n [TraceModel.Types.TraceEvents.ThreadID(2), 'ThreadPoolServiceThread'],\n [TraceModel.Types.TraceEvents.ThreadID(10), 'CompositorTileWorker1'],\n ],\n ],\n [\n TraceModel.Types.TraceEvents.ProcessID(SUB_FRAME_PID_3),\n [\n [TraceModel.Types.TraceEvents.ThreadID(1), 'CrRendererMain'],\n [TraceModel.Types.TraceEvents.ThreadID(2), 'ThreadPoolServiceThread'],\n [TraceModel.Types.TraceEvents.ThreadID(4), 'Chrome_ChildIOThread'],\n [TraceModel.Types.TraceEvents.ThreadID(7), 'Compositor'],\n [TraceModel.Types.TraceEvents.ThreadID(10), 'CompositorTileWorker2'],\n [TraceModel.Types.TraceEvents.ThreadID(3), 'ThreadPoolForegroundWorker'],\n ],\n ],\n ]);\n });\n\n it('populates the map of trace events to tree nodes', async () => {\n const {Renderer: renderers} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n assert.strictEqual(renderers.entryToNode.size, 3591);\n });\n\n describe('Synthetic complete events', () => {\n async function handleEvents(traceEvents: TraceModel.Types.TraceEvents.TraceEventData[]):\n Promise {\n TraceModel.Handlers.ModelHandlers.Renderer.reset();\n TraceModel.Handlers.ModelHandlers.Meta.reset();\n TraceModel.Handlers.ModelHandlers.Samples.reset();\n TraceModel.Handlers.ModelHandlers.Meta.initialize();\n TraceModel.Handlers.ModelHandlers.Samples.initialize();\n TraceModel.Handlers.ModelHandlers.Renderer.initialize();\n\n for (const event of traceEvents) {\n TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event);\n TraceModel.Handlers.ModelHandlers.Renderer.handleEvent(event);\n }\n\n await TraceModel.Handlers.ModelHandlers.Meta.finalize();\n await TraceModel.Handlers.ModelHandlers.Samples.finalize();\n await TraceModel.Handlers.ModelHandlers.Renderer.finalize();\n return TraceModel.Handlers.ModelHandlers.Renderer.data();\n }\n let defaultTraceEvents: readonly TraceModel.Types.TraceEvents.TraceEventData[];\n const pid = TraceModel.Types.TraceEvents.ProcessID(28274);\n const tid = TraceModel.Types.TraceEvents.ThreadID(775);\n beforeEach(async function() {\n defaultTraceEvents = await TraceLoader.rawEvents(this, 'basic.json.gz');\n });\n\n afterEach(() => {\n TraceModel.Handlers.ModelHandlers.Renderer.reset();\n TraceModel.Handlers.ModelHandlers.Meta.reset();\n TraceModel.Handlers.ModelHandlers.Samples.reset();\n });\n\n it('builds a hierarchy using begin and end trace events', async () => {\n // |------------- RunTask -------------||-- RunTask --|\n // |-- RunMicrotasks --||-- Layout --|\n // |- FunctionCall -|\n const traceEvents = [\n ...defaultTraceEvents, makeBeginEvent('RunTask', 0, '*', pid, tid), // 0..10\n makeBeginEvent('RunMicrotasks', 1, '*', pid, tid), // 1..4\n makeBeginEvent('FunctionCall', 2, '*', pid, tid), // 2..3\n makeEndEvent('FunctionCall', 3, '*', pid, tid), // 2..3\n makeEndEvent('RunMicrotasks', 4, '*', pid, tid), // 1..4\n makeBeginEvent('Layout', 5, '*', pid, tid), // 5..8\n makeEndEvent('Layout', 8, '*', pid, tid), // 5..8\n makeEndEvent('RunTask', 10, '*', pid, tid), // 0..10\n makeBeginEvent('RunTask', 11, '*', pid, tid), // 11..14\n makeEndEvent('RunTask', 14, '*', pid, tid), // 11..14\n ];\n\n const data = await handleEvents(traceEvents);\n\n assert.strictEqual(data.allTraceEntries.length, 7);\n assert.strictEqual(data.processes.size, 1);\n const [process] = data.processes.values();\n assert.strictEqual(process.threads.size, 1);\n const [thread] = process.threads.values();\n assert.strictEqual(thread.tree?.roots.size, 2);\n if (!thread.tree?.roots) {\n // This shouldn't happen, since the tree.roots.size is 2, but add this if check to pass ts check.\n return;\n }\n const allNodes = getAllNodes(thread.tree?.roots);\n assert.strictEqual(allNodes.length, 5);\n if (!thread.tree) {\n return;\n }\n assert.strictEqual(prettyPrint(thread.tree), `\n-RunTask [0.01ms]\n -RunMicrotasks [0.003ms]\n -FunctionCall [0.001ms]\n -Layout [0.003ms]\n-RunTask [0.003ms]`);\n });\n it('builds a hierarchy using complete, begin and end trace events', async () => {\n // |------------- RunTask -------------|\n // |-- RunMicrotasks --||-- Layout --|\n // |- FunctionCall -|\n\n const traceEvents = [\n ...defaultTraceEvents, makeBeginEvent('RunTask', 0, '*', pid, tid), // 0..10\n makeBeginEvent('RunMicrotasks', 1, '*', pid, tid), // 1..4\n makeCompleteEvent('FunctionCall', 2, 1, '*', pid, tid), // 2..3\n makeEndEvent('RunMicrotasks', 4, '*', pid, tid), // 1..4\n makeBeginEvent('Layout', 5, '*', pid, tid), // 5..8\n makeEndEvent('Layout', 8, '*', pid, tid), // 5..8\n makeEndEvent('RunTask', 10, '*', pid, tid), // 0..10\n ];\n\n const data = await handleEvents(traceEvents);\n\n assert.strictEqual(data.allTraceEntries.length, 6);\n assert.strictEqual(data.processes.size, 1);\n const [process] = data.processes.values();\n assert.strictEqual(process.threads.size, 1);\n const [thread] = process.threads.values();\n assert.strictEqual(thread.tree?.roots.size, 1);\n if (!thread.tree?.roots) {\n // This shouldn't happen, since the tree.roots.size is 1, but add this if check to pass ts check.\n return;\n }\n const allNodes = getAllNodes(thread.tree?.roots);\n assert.strictEqual(allNodes.length, 4);\n if (!thread.tree) {\n return;\n }\n assert.strictEqual(prettyPrint(thread.tree), `\n-RunTask [0.01ms]\n -RunMicrotasks [0.003ms]\n -FunctionCall [0.001ms]\n -Layout [0.003ms]`);\n });\n\n it('keeps a FunctionCall that has the end event missing', async () => {\n const traceEvents = [\n ...defaultTraceEvents, makeBeginEvent('RunMicrotasks', 1, '*', pid, tid), // 1..4\n makeBeginEvent('FunctionCall', 2, '*', pid, tid), // 2..3\n ];\n\n const data = await handleEvents(traceEvents);\n assert.strictEqual(data.processes.size, 1);\n const [process] = data.processes.values();\n assert.strictEqual(process.threads.size, 1);\n const [thread] = process.threads.values();\n if (!thread.tree) {\n throw new Error('thread should have a tree');\n }\n // Ensure that the FunctionCall event has been kept despite not having an END event.\n assert.deepEqual(thread.entries.map(e => e.name), ['RunMicrotasks', 'FunctionCall']);\n });\n });\n\n describe('building hierarchies trace events and profile calls', () => {\n it('build a hierarchy using data from real world trace file', async () => {\n const {Renderer} = await handleEventsFromTraceFile(this, 'recursive-counting-js.json.gz');\n const threadId = TraceModel.Types.TraceEvents.ThreadID(259);\n const firstProcessId = TraceModel.Types.TraceEvents.ProcessID(23239);\n const thread = Renderer.processes.get(firstProcessId)?.threads.get(threadId);\n if (!thread || !thread.tree) {\n throw new Error('Tree not found');\n }\n const onlyLongTasksPredicate =\n (_node: TraceModel.Helpers.TreeHelpers.TraceEntryNode, event: TraceModel.Types.TraceEvents.TraceEventData) =>\n Boolean(event.dur && event.dur > 1000) &&\n Boolean(Components.EntryStyles.getEventStyle(event.name as TraceModel.Types.TraceEvents.KnownEventName));\n assert.strictEqual(prettyPrint(thread.tree, onlyLongTasksPredicate), `\n.............\n-RunTask [17.269ms]\n.............................\n-RunTask [1065.663ms]\n -ParseHTML [1065.609ms]\n.........\n-RunTask [1.12ms]\n -ParseHTML [1.082ms]\n.........................................................\n-RunTask [1058.811ms]\n -TimerFire [1058.77ms]\n -FunctionCall [1058.693ms]\n.\n -ProfileCall (anonymous) [1058.589ms]\n -ProfileCall (foo) [1058.589ms]\n -ProfileCall (foo) [1058.589ms]\n -ProfileCall (foo) [1058.589ms]\n -ProfileCall (foo) [1058.589ms]\n..\n -ProfileCall (count) [1058.453ms]\n........\n-RunTask [1057.455ms]\n -TimerFire [1057.391ms]\n -FunctionCall [1057.27ms]\n.\n -ProfileCall (anonymous) [1056.579ms]\n -ProfileCall (foo) [1056.579ms]\n -ProfileCall (foo) [1056.579ms]\n -ProfileCall (foo) [1056.579ms]\n -ProfileCall (foo) [1056.579ms]\n -ProfileCall (count) [1056.538ms]\n........`);\n });\n });\n\n it('identifies and returns rasterizer threads', async () => {\n const {Renderer} = await handleEventsFromTraceFile(this, 'web-dev.json.gz');\n assert.deepEqual(Array.from(Renderer.compositorTileWorkers.entries()), [\n [\n TraceModel.Types.TraceEvents.ProcessID(68481),\n [\n TraceModel.Types.TraceEvents.ThreadID(81675),\n ],\n ],\n [\n TraceModel.Types.TraceEvents.ProcessID(73704),\n [\n TraceModel.Types.TraceEvents.ThreadID(23299),\n TraceModel.Types.TraceEvents.ThreadID(22275),\n TraceModel.Types.TraceEvents.ThreadID(41475),\n TraceModel.Types.TraceEvents.ThreadID(40451),\n TraceModel.Types.TraceEvents.ThreadID(22531),\n ],\n ],\n ]);\n });\n\n it('keeps the processes associated with AuctionWorklets and assigns them URLs', async () => {\n const {Renderer, AuctionWorklets} = await handleEventsFromTraceFile(this, 'fenced-frame-fledge.json.gz');\n assert.strictEqual(AuctionWorklets.worklets.size, 3);\n for (const [pid] of AuctionWorklets.worklets) {\n const process = Renderer.processes.get(pid);\n assert.exists(process);\n // Ensure that the URL was set properly based on the AuctionWorklets metadata event.\n assert.isTrue(process?.url?.includes('fledge-demo.glitch.me'));\n }\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"RendererHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/RendererHandler.test.ts"],"names":[],"mappings":"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AG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG;YAC/G,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG;YAC/G,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG;YAC/G,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG;YAC/G,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG;YAC/G,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG;YAC/G,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG;YAC/G,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG;YAC/G,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG;YAC/G,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG;YAC/G,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG;YAC/G,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,GAAG,EAAG,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;YAChH,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;YAChH,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;YAChH,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;YAChH,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;YAChH,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;YAChH,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;YAChH,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI;SACzC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;QAC3F,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAC,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,2CAA2C,CAAC,CAAC;QACjH,MAAM,KAAK,GAAG,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,CACxB,CAAC;QAC1D,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC;QAC5F,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,CAAC,KAAK,EAAE,2BAA2B,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,CAAC,KAAK,EAAE,mCAAmC,CAAC,CAAC;QACrD,CAAC;QACD,MAAM,CAAC,SAAS,CACZ,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;IACpH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8EAA8E,EAAE,KAAK,IAAI,EAAE;QAC5F,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAC,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,2CAA2C,CAAC,CAAC;QACjH,MAAM,KAAK,GAAG,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,CACzB,CAAC;QAC1D,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC;QAC5F,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,CAAC,KAAK,EAAE,2BAA2B,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,CAAC,KAAK,EAAE,mCAAmC,CAAC,CAAC;QACrD,CAAC;QAED,MAAM,MAAM,GAAG,CAAC,IAA8C,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,CAAC,CAAC;QACpF,MAAM,SAAS,GAAG,CAAC,KAA+B,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAC3F,MAAM,MAAM,GAAG,CAAC,KAA+B,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC;QAC7G,MAAM,UAAU,GAAG,CAAC,IAA8C,EAAE,KAA+B,EAAE,EAAE,CACnG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;YACpD,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,CAAC,IAA+B,CAAC,CAAC,CAAC;QACzF,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uHAqLiE,CAAC,CAAC;IACvH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;QAC3F,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAC,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,2CAA2C,CAAC,CAAC;QACjH,MAAM,KAAK,GAAG,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,CACxB,CAAC;QAC1D,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC;QAC5F,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,CAAC,KAAK,EAAE,2BAA2B,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,CAAC,KAAK,EAAE,mCAAmC,CAAC,CAAC;QACrD,CAAC;QACD,MAAM,UAAU,GAAG,CAAC,KAA+C,EAAE,KAA+B,EAAE,EAAE,CACpG,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,CAAC,IAA+B,CAAC,CAAC,CAAC;QACzF,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;EAqBpD,CAAC,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wFAAwF,EAAE,KAAK,IAAI,EAAE;QACtG,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAC,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,2CAA2C,CAAC,CAAC;QACjH,MAAM,KAAK,GAAG,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,CACzB,CAAC;QAC1D,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC;QAC5F,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,CAAC,KAAK,EAAE,2BAA2B,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,CAAC,KAAK,EAAE,mCAAmC,CAAC,CAAC;QACrD,CAAC;QAED,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;QAC1C,MAAM,CAAC,SAAS,CAAC,MAAiB,EAAE;YAClC,IAAI,EAAE,EAAE;YACR,GAAG,EAAE,uCAAuC;YAC5C,GAAG,EAAE,GAAG;YACR,IAAI,EAAE,SAAS;YACf,EAAE,EAAE,GAAG;YACP,GAAG,EAAE,OAAO;YACZ,IAAI,EAAE,GAAG;YACT,GAAG,EAAE,CAAC;YACN,EAAE,EAAE,YAAY;YAChB,GAAG,EAAE,MAAM;SACZ,CAAC,CAAC;QACH,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;QAErE,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;QAC1C,MAAM,CAAC,SAAS,CAAC,MAAiB,EAAE;YAClC,IAAI,EAAE,EAAE;YACR,GAAG,EAAE,uCAAuC;YAC5C,GAAG,EAAE,CAAC;YACN,IAAI,EAAE,SAAS;YACf,EAAE,EAAE,GAAG;YACP,GAAG,EAAE,OAAO;YACZ,IAAI,EAAE,CAAC;YACP,GAAG,EAAE,CAAC;YACN,EAAE,EAAE,YAAY;YAChB,GAAG,EAAE,MAAM;SACZ,CAAC,CAAC;QACH,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;QAEnE,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;QAC/D,MAAM,CAAC,SAAS,CAAC,SAAoB,EAAE;YACrC,IAAI,EAAE,EAAE;YACR,GAAG,EAAE,uCAAuC;YAC5C,GAAG,EAAE,EAAE;YACP,IAAI,EAAE,SAAS;YACf,EAAE,EAAE,GAAG;YACP,GAAG,EAAE,OAAO;YACZ,IAAI,EAAE,EAAE;YACR,GAAG,EAAE,CAAC;YACN,EAAE,EAAE,YAAY;YAChB,GAAG,EAAE,MAAM;SACZ,CAAC,CAAC;QACH,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uFAAuF,EAAE,KAAK,IAAI,EAAE;QACrG,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAC,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,2CAA2C,CAAC,CAAC;QACjH,MAAM,KAAK,GAAG,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,CACxB,CAAC;QAC1D,MAAM,MAAM,GAAG,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC;QAC5F,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,CAAC,KAAK,EAAE,2BAA2B,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACzB,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,CAAC,KAAK,EAAE,mCAAmC,CAAC,CAAC;QACrD,CAAC;QAED,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;QAC1C,MAAM,CAAC,SAAS,CAAC,MAAiB,EAAE;YAClC,IAAI,EAAE,EAAE;YACR,GAAG,EAAE,uCAAuC;YAC5C,GAAG,EAAE,GAAG;YACR,IAAI,EAAE,SAAS;YACf,EAAE,EAAE,GAAG;YACP,GAAG,EAAE,OAAO;YACZ,IAAI,EAAE,GAAG;YACT,GAAG,EAAE,CAAC;YACN,EAAE,EAAE,YAAY;YAChB,GAAG,EAAE,KAAK;SACX,CAAC,CAAC;QACH,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;QAErE,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;QAC1C,MAAM,CAAC,SAAS,CAAC,MAAiB,EAAE;YAClC,IAAI,EAAE,EAAE;YACR,GAAG,EAAE,uCAAuC;YAC5C,GAAG,EAAE,CAAC;YACN,IAAI,EAAE,SAAS;YACf,EAAE,EAAE,GAAG;YACP,GAAG,EAAE,OAAO;YACZ,IAAI,EAAE,CAAC;YACP,GAAG,EAAE,CAAC;YACN,EAAE,EAAE,YAAY;YAChB,GAAG,EAAE,KAAK;SACX,CAAC,CAAC;QACH,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;QAEnE,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;QAE1C,MAAM,CAAC,SAAS,CAAC,MAAiB,EAAE;YAClC,IAAI,EAAE,EAAE;YACR,GAAG,EAAE,uCAAuC;YAC5C,GAAG,EAAE,CAAC;YACN,IAAI,EAAE,SAAS;YACf,EAAE,EAAE,GAAG;YACP,GAAG,EAAE,OAAO;YACZ,IAAI,EAAE,CAAC;YACP,GAAG,EAAE,CAAC;YACN,EAAE,EAAE,YAAY;YAChB,GAAG,EAAE,KAAK;SACX,CAAC,CAAC;QACH,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;QACnE,MAAM,IAAI,GAAG;YACX,iBAAiB,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;YAC7B,iBAAiB,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;YAC7B,iBAAiB,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;YAC7B,iBAAiB,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC;YAC/B,iBAAiB,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC;YACjC,iBAAiB,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC;YACjC,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;YACnC,iBAAiB,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC;YAChC,iBAAiB,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC;SACnC,CAAC;QAEF,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;QAEjD,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAC,CAAC,CAAY,EAAE;YACjF,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAC;YAC3B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAC;YAC7B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAC;YAC/B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAC;YAChC,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAC;YACjC,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAC;YAC3B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,EAAC;YAC9B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAC;YAC/B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAC;SAC5B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,sFAAsF,EAAE,KAAK,IAAI,EAAE;QACpG,MAAM,IAAI,GAAG;YACX,iBAAiB,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;YAC7B,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC;YACzB,iBAAiB,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;YAC7B,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC;YAC5B,iBAAiB,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;YAC7B,gBAAgB,CAAC,IAAI,EAAE,GAAG,CAAC;YAC3B,iBAAiB,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC;YAC/B,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC;YAC5B,iBAAiB,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC;YACjC,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC;YACzB,iBAAiB,CAAC,IAAI,EAAE,GAAG,EAAE,GAAG,CAAC;YACjC,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC;YAC5B,iBAAiB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;YACnC,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC;YAC5B,iBAAiB,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC;YAChC,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC;YACzB,iBAAiB,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,CAAC;YAClC,gBAAgB,CAAC,IAAI,EAAE,IAAI,CAAC;SAC7B,CAAC;QAEF,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC;QAEjD,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAC,CAAC,CAAY,EAAE;YACjF,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAC;YAC3B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAC;YAC7B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,SAAS,EAAC;YACnC,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAC;YACtC,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAC;YAC/B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,EAAC;YAChC,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,SAAS,EAAC;YACrC,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAC;YACjC,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAC;YACtC,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAC;YAC3B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,IAAI,EAAC;YAC9B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,SAAS,EAAC;YACnC,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAC;YAC/B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAC;YACtC,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAC;YACtC,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAC;YAC3B,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,SAAS,EAAC;YACnC,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,SAAS,EAAC;SACvC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC9C;;;;WAIG;QACH,MAAM,KAAK,GAAG;YACZ,iBAAiB,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,EAAG,QAAQ;YACxC,iBAAiB,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,EAAI,OAAO;YACvC,iBAAiB,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,EAAI,OAAO;YACvC,iBAAiB,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,EAAI,OAAO;YACvC,iBAAiB,CAAC,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC,EAAG,SAAS;SAC1C,CAAC;QAEF;;;;WAIG;QACH,MAAM,KAAK,GAAG;YACZ,iBAAiB,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,EAAI,OAAO;YACvC,iBAAiB,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,EAAG,iCAAiC;YACjE,iBAAiB,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,EAAI,+BAA+B;YAC/D,iBAAiB,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,EAAI,gCAAgC;YAChE,iBAAiB,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,EAAI,kCAAkC;SACnE,CAAC;QAEF,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC;YACxB;gBACE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;gBAC/B;oBACE,GAAG,EAAE,CAAC,cAAc,CAAC;oBACrB,aAAa,EAAE,IAAI;oBACnB,OAAO,EAAE,IAAI,GAAG,CAAC,CAAC;4BAChB,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;4BAC9B,EAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAC;yBAC9B,CAAC,CAAC;iBACqD;aAC3D;YACD;gBACE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;gBAC/B;oBACE,GAAG,EAAE,CAAC,cAAc,CAAC;oBACrB,aAAa,EAAE,KAAK;oBACpB,OAAO,EAAE,IAAI,GAAG,CAAC,CAAC;4BAChB,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC;4BAC9B,EAAC,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAC;yBAC9B,CAAC,CAAC;iBACqD;aAC3D;SACF,CAAC,CAAC;QAEH,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QAClD,MAAM,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACtD,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,cAAc,CAAC,SAAS,EAAE,EAAC,MAAM,EAAE,EAAC,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,EAAC,EAAC,CAAC,CAAC;QAE7F,MAAM,WAAW,GAAG,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACxE,MAAM,YAAY,GAAG,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAEzE,IAAI,CAAC,WAAW,CAAC,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;YAC5C,MAAM,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC;QACnC,CAAC;QAED,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,qDAAqD,CAAC,CAAC;QACxG,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE,sDAAsD,CAAC,CAAC;QAE1G,MAAM,UAAU,GAAG,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QAChE,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAC,CAAC,CAAC,CAAC,IAAI,CAAc,EAAE;YAClG,EAAC,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAC;YAC3B,EAAC,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,EAAC;SAC5B,CAAC,CAAC;QAEH,MAAM,WAAW,GAAG,WAAW,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QAClE,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAC,CAAC,CAAC,CAAC,IAAI,CAAc,EAAE;YACnG,EAAC,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAC;YAC1B,EAAC,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAC;SAC5B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QAC/C,MAAM,EAAC,IAAI,EAAE,QAAQ,EAAC,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,2CAA2C,CAAC,CAAC;QAC5G,MAAM,SAAS,GACX,IAAI,GAAG,EAAE,CAAC;QAEd,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,YAAY,CAAC,SAAS,EAAE,QAAQ,CAAC,wBAAwB,CAAC,CAAC;QAEjG,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE;YAC9F,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,uBAAuB,CAAC;YACvE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,yBAAyB,CAAC;YACxE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,yBAAyB,CAAC;YAC1E,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,yBAAyB,CAAC;SAC3E,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK,IAAI,EAAE;QACxD,MAAM,EAAC,IAAI,EAAE,QAAQ,EAAC,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,2CAA2C,CAAC,CAAC;QAC5G,MAAM,SAAS,GACX,IAAI,GAAG,EAAE,CAAC;QAEd,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,iBAAiB,CACnD,SAAS,EAAE,QAAQ,CAAC,WAAW,EAAE,QAAQ,CAAC,wBAAwB,CAAC,CAAC;QAExE,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,EAAE;YACzE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,IAAI,CAAC;YACpD,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,KAAK,CAAC;YACpD,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,KAAK,CAAC;YACtD,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC,EAAE,KAAK,CAAC;SACvD,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,EAAC,IAAI,EAAE,QAAQ,EAAC,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,2CAA2C,CAAC,CAAC;QAC5G,MAAM,EAAC,WAAW,EAAE,wBAAwB,EAAE,gBAAgB,EAAC,GAAG,QAAQ,CAAC;QAC3E,MAAM,SAAS,GACX,IAAI,GAAG,EAAE,CAAC;QAEd,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,UAAU,CAC5C,SAAS,EAAE,WAAW,EAAE,wBAAwB,EAAE,gBAAgB,CAAC,CAAC;QAExE,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE;YACzG;gBACE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC;gBAC5C;oBACE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,gBAAgB,CAAC;oBAClD,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC;oBAC9C,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,yBAAyB,CAAC;oBAC3D,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,sBAAsB,CAAC;oBACxD,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,4BAA4B,CAAC;oBAC/D,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,4BAA4B,CAAC;oBAC/D,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,4BAA4B,CAAC;oBAC/D,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,4BAA4B,CAAC;oBAC/D,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,4BAA4B,CAAC;oBAC/D,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,4BAA4B,CAAC;oBAC/D,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,4BAA4B,CAAC;oBAC/D,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,4BAA4B,CAAC;oBAC/D,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,uBAAuB,CAAC;oBAC1D,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,uBAAuB,CAAC;oBAC1D,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,uBAAuB,CAAC;oBAC1D,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,uBAAuB,CAAC;iBAC1D;aACF;YACD;gBACE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC;gBAC3C;oBACE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,yBAAyB,CAAC;oBAC3D,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,gBAAgB,CAAC;oBAClD,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC;oBAC9C,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,sBAAsB,CAAC;iBACzD;aACF;YACD;gBACE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC;gBAC7C;oBACE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,gBAAgB,CAAC;oBAClD,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,sBAAsB,CAAC;oBACxD,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC;oBAC9C,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,yBAAyB,CAAC;oBAC3D,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,uBAAuB,CAAC;iBAC3D;aACF;YACD;gBACE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC;gBAC7C;oBACE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,gBAAgB,CAAC;oBAClD,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,yBAAyB,CAAC;oBAC3D,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,sBAAsB,CAAC;oBACxD,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC;oBAC9C,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,uBAAuB,CAAC;oBAC1D,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,4BAA4B,CAAC;iBAC/D;aACF;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK,IAAI,EAAE;QAC/D,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAC,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,2CAA2C,CAAC,CAAC;QACjH,MAAM,CAAC,WAAW,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACzC,KAAK,UAAU,YAAY,CAAC,WAAuC;YAEjE,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;YAC9C,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAC1C,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAC7C,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YAC/C,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;YAClD,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;YAEnD,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;gBAChC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;gBACrD,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YAC3D,CAAC;YAED,MAAM,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnD,MAAM,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YACtD,MAAM,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACvD,OAAO,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACtD,CAAC;QACD,IAAI,kBAAuD,CAAC;QAC5D,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAChD,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAC7C,UAAU,CAAC,KAAK;YACd,kBAAkB,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;QAC1E,CAAC,CAAC,CAAC;QAEH,SAAS,CAAC,GAAG,EAAE;YACb,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;YAC9C,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAC1C,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;YACnE,uDAAuD;YACvD,uCAAuC;YACvC,uBAAuB;YACvB,MAAM,WAAW,GAAG;gBAClB,GAAG,kBAAkB,EAAE,cAAc,CAAC,SAAS,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAG,QAAQ;gBAC7E,cAAc,CAAC,eAAe,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAoB,OAAO;gBAC5E,cAAc,CAAC,cAAc,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAqB,OAAO;gBAC5E,YAAY,CAAC,cAAc,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAuB,OAAO;gBAC5E,YAAY,CAAC,eAAe,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAsB,OAAO;gBAC5E,cAAc,CAAC,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAA2B,OAAO;gBAC5E,YAAY,CAAC,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAA6B,OAAO;gBAC5E,YAAY,CAAC,SAAS,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAA2B,QAAQ;gBAC7E,cAAc,CAAC,SAAS,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAyB,SAAS;gBAC9E,YAAY,CAAC,SAAS,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAA2B,SAAS;aAC/E,CAAC;YAEF,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC;YAE7C,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACnD,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC3C,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;YAC1C,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC5C,MAAM,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YAC1C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC/C,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;gBACxB,iGAAiG;gBACjG,OAAO;YACT,CAAC;YACD,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACjD,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACvC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;gBACjB,OAAO;YACT,CAAC;YACD,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;;;;;mBAKhC,CAAC,CAAC;QACjB,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;YAC7E,wCAAwC;YACxC,uCAAuC;YACvC,uBAAuB;YAEvB,MAAM,WAAW,GAAG;gBAClB,GAAG,kBAAkB,EAAE,cAAc,CAAC,SAAS,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAG,QAAQ;gBAC7E,cAAc,CAAC,eAAe,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAoB,OAAO;gBAC5E,iBAAiB,CAAC,cAAc,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAe,OAAO;gBAC5E,YAAY,CAAC,eAAe,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAsB,OAAO;gBAC5E,cAAc,CAAC,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAA2B,OAAO;gBAC5E,YAAY,CAAC,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAA6B,OAAO;gBAC5E,YAAY,CAAC,SAAS,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAA2B,QAAQ;aAC9E,CAAC;YAEF,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC;YAE7C,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACnD,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC3C,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;YAC1C,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC5C,MAAM,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YAC1C,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC/C,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;gBACxB,iGAAiG;gBACjG,OAAO;YACT,CAAC;YACD,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YACjD,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACvC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;gBACjB,OAAO;YACT,CAAC;YACD,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;;;;oBAI/B,CAAC,CAAC;QAClB,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qDAAqD,EAAE,KAAK,IAAI,EAAE;YACnE,MAAM,WAAW,GAAG;gBAClB,GAAG,kBAAkB,EAAE,cAAc,CAAC,eAAe,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAG,OAAO;gBAClF,cAAc,CAAC,cAAc,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAA2B,OAAO;aACnF,CAAC;YAEF,MAAM,IAAI,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC;YAC7C,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC3C,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;YAC1C,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC5C,MAAM,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;YAC1C,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;YAC/C,CAAC;YACD,oFAAoF;YACpF,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,eAAe,EAAE,cAAc,CAAC,CAAC,CAAC;QACvF,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,qDAAqD,EAAE,GAAG,EAAE;QACnE,EAAE,CAAC,yDAAyD,EAAE,KAAK,IAAI,EAAE;YACvE,MAAM,EAAC,QAAQ,EAAC,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,+BAA+B,CAAC,CAAC;YAC1F,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;YAClD,MAAM,cAAc,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAC3D,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC7E,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;YACpC,CAAC;YACD,MAAM,sBAAsB,GACxB,CAAC,KAA+C,EAAE,KAA+B,EAAE,EAAE,CACjF,OAAO,CAAC,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC,GAAG,GAAG,IAAI,CAAC;gBAC1C,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,CAAC,IAA+B,CAAC,CAAC,CAAC;YACzF,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,sBAAsB,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;SAgClE,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,MAAM,EAAC,QAAQ,EAAC,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;QAC5E,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,qBAAqB,CAAC,OAAO,EAAE,CAAC,EAAE;YACrE;gBACE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;gBACnC;oBACE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;iBACnC;aACF;YACD;gBACE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;gBACnC;oBACE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;oBAClC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;oBAClC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;oBAClC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;oBAClC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;iBACnC;aACF;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2EAA2E,EAAE,KAAK,IAAI,EAAE;QACzF,MAAM,EAAC,QAAQ,EAAE,eAAe,EAAC,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,6BAA6B,CAAC,CAAC;QACzG,MAAM,CAAC,WAAW,CAAC,eAAe,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACrD,KAAK,MAAM,CAAC,GAAG,CAAC,IAAI,eAAe,CAAC,QAAQ,EAAE,CAAC;YAC7C,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC5C,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YACvB,oFAAoF;YACpF,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,EAAE,QAAQ,CAAC,uBAAuB,CAAC,CAAC,CAAC;QACjE,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Components from '../../../panels/timeline/components/components.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {\n getAllNodes,\n getEventsIn,\n getRootAt,\n makeBeginEvent,\n makeCompleteEvent,\n makeEndEvent,\n makeInstantEvent,\n prettyPrint,\n} from '../../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Trace from '../trace.js';\n\nconst MAIN_FRAME_PID = 2154214;\nconst SUB_FRAME_PID = 2236065;\nconst SUB_FRAME_PID_2 = 2236084;\nconst SUB_FRAME_PID_3 = 2236123;\n\nasync function handleEventsFromTraceFile(\n context: Mocha.Suite|Mocha.Context|null, file: string): Promise {\n const {parsedTrace} = await TraceLoader.traceEngine(context, file);\n return parsedTrace;\n}\n\ndescribeWithEnvironment('RendererHandler', function() {\n it('finds all the renderers in a real world profile', async () => {\n const {Renderer: renderers} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n assert.strictEqual(renderers.processes.size, 4);\n\n const pids = [...renderers.processes].map(([pid]) => pid);\n assert.deepStrictEqual(\n pids,\n [\n MAIN_FRAME_PID, // Main frame process: localhost:5000\n SUB_FRAME_PID, // Sub frame process (trace start): example.com\n SUB_FRAME_PID_2, // Sub frame process (after first navigation): example.com\n SUB_FRAME_PID_3, // Sub frame process (after second navigation): example.com\n ],\n 'Process IDs do not match expectations');\n\n const origins = [...renderers.processes].map(([, process]) => {\n return process.url ? new URL(process.url).origin : null;\n });\n assert.deepEqual(\n origins,\n [\n 'http://localhost:5000', // Main frame process: localhost:5000\n 'https://www.example.com', // Sub frame process (trace start): example.com\n 'https://www.example.com', // Sub frame process (after first navigation): example.com\n 'https://www.example.com', // Sub frame process (after second navigation): example.com\n ],\n 'Process origins do not meet expectations');\n\n // Assert on whether it has correctly detected a given process to be on the\n // main frame or in a subframe.\n const isOnMainFrame = [...renderers.processes].map(([, process]) => process.isOnMainFrame);\n assert.deepStrictEqual(\n isOnMainFrame,\n [\n true, // Main frame process: localhost:5000\n false, // Sub frame process (trace start): example.com\n false, // Sub frame process (after first navigation): example.com\n false, // Sub frame process (after second navigation): example.com\n ],\n 'Processes are incorrectly assigned as being on the main frame');\n });\n\n it('finds all the main frame threads in a real world profile', async () => {\n const {Renderer: renderers} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n const frame = renderers.processes.get(Trace.Types.Events.ProcessID(MAIN_FRAME_PID)) as\n Trace.Handlers.ModelHandlers.Renderer.RendererProcess;\n const names = [...frame.threads].map(([, thread]) => thread.name).sort();\n assert.deepEqual(\n names,\n [\n 'Chrome_ChildIOThread',\n 'Compositor',\n 'CompositorTileWorker1',\n 'CompositorTileWorker2',\n 'CompositorTileWorker3',\n 'CompositorTileWorker4',\n 'CrRendererMain',\n 'ThreadPoolForegroundWorker',\n 'ThreadPoolForegroundWorker',\n 'ThreadPoolForegroundWorker',\n 'ThreadPoolForegroundWorker',\n 'ThreadPoolForegroundWorker',\n 'ThreadPoolForegroundWorker',\n 'ThreadPoolForegroundWorker',\n 'ThreadPoolForegroundWorker',\n 'ThreadPoolServiceThread',\n ],\n 'Main frame thread names do not meet expectations before navigation');\n });\n\n it('finds all the sub frame threads in a real world profile', async () => {\n const {Renderer: renderers} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n const frame = renderers.processes.get(Trace.Types.Events.ProcessID(SUB_FRAME_PID)) as\n Trace.Handlers.ModelHandlers.Renderer.RendererProcess;\n const names = [...frame.threads].map(([, thread]) => thread.name).sort();\n assert.deepEqual(\n names,\n [\n 'Chrome_ChildIOThread',\n 'Compositor',\n 'CrRendererMain',\n 'ThreadPoolServiceThread',\n ],\n 'Main frame thread names do not meet expectations after navigation');\n });\n\n it('finds all the roots on the main frame\\'s main thread in a real world profile', async () => {\n const {Renderer: renderers} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n const frame = renderers.processes.get(Trace.Types.Events.ProcessID(MAIN_FRAME_PID)) as\n Trace.Handlers.ModelHandlers.Renderer.RendererProcess;\n const thread = [...frame.threads.values()].find(thread => thread.name === 'CrRendererMain');\n if (!thread) {\n assert(false, 'Main thread was not found');\n }\n\n const tree = thread.tree;\n if (!tree) {\n assert(false, 'Main thread has no tree of events');\n }\n assert.deepEqual([...tree.roots].map(root => root.id), [\n 0, 1, 2, 3, 4, 5, 16, 18, 29, 38, 49, 58, 77, 183, 184, 185, 186, 188, 189,\n 190, 199, 200, 201, 202, 211, 212, 213, 214, 229, 230, 232, 237, 239, 240, 242, 251, 252, 261,\n 264, 265, 266, 267, 268, 279, 282, 284, 285, 286, 287, 288, 289, 290, 293, 294, 295, 296, 297,\n 298, 299, 300, 301, 302, 303, 304, 305, 306, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337,\n 338, 339, 340, 341, 342, 343, 344, 345, 354, 355, 356, 359, 389, 408, 409, 410, 411, 412, 413,\n 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432,\n 433, 441, 442, 443, 444, 445, 446, 447, 448, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464,\n 465, 466, 467, 468, 469, 479, 480, 481, 482, 483, 484, 485, 492, 493, 494, 495, 496, 498, 506,\n 507, 508, 509, 510, 511, 516, 517, 518, 519, 520, 521, 522, 523, 524, 525, 526, 538, 540, 541,\n 552, 555, 556, 565, 566, 575, 576, 585, 586, 595, 596, 605, 606, 615, 616, 625, 626, 635, 636,\n 645, 646, 657, 660, 661, 662, 663, 674, 677, 678, 679, 680, 689, 690, 691, 692, 701, 702, 711,\n 712, 721, 722, 733, 734, 737, 738, 739, 740, 749, 750, 751, 760, 761, 762, 771, 772, 773, 782,\n 783, 784, 793, 794, 795, 796, 797, 808, 809, 810, 811, 835, 843, 844, 845, 846, 848, 861, 869,\n 870, 871, 872, 873, 874, 875, 876, 877, 878, 881, 882, 883, 884, 885, 886, 887, 888, 889, 890,\n 904, 905, 906, 907, 908, 909, 910, 911, 912, 913, 914, 915, 916, 917, 918, 919, 920, 921, 922,\n 931, 932, 933, 936, 966, 967, 983, 984, 985, 986, 987, 988, 989, 990, 991, 992, 993, 994, 995,\n 996, 997, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1020, 1021,\n 1022, 1023, 1024, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1048, 1049, 1050, 1051, 1052, 1053, 1054, 1055,\n 1056, 1057, 1064, 1065, 1066, 1068, 1069, 1077, 1078, 1079, 1080, 1081, 1082, 1083, 1084, 1085, 1086, 1087, 1088,\n 1089, 1090, 1091, 1092, 1102, 1104, 1105, 1106, 1107, 1116, 1117, 1118, 1127, 1128, 1129, 1138, 1139, 1140, 1141,\n 1150, 1151, 1152, 1153, 1154, 1165, 1166, 1167, 1176, 1177, 1178, 1189, 1192, 1193, 1194, 1203, 1204, 1205, 1206,\n 1215, 1216, 1225, 1226, 1235, 1236, 1237, 1246, 1247, 1256, 1257, 1266, 1267, 1276, 1277, 1286, 1287, 1298, 1301,\n 1302, 1303, 1304, 1313, 1314, 1315, 1324, 1325, 1326, 1335, 1336, 1337, 1348, 1351, 1352, 1353, 1362, 1364, 1365,\n 1366, 1367, 1368, 1369, 1370, 1371, 1378,\n ]);\n });\n\n it('finds all the roots on the sub frame\\'s main thread in a real world profile', async () => {\n const {Renderer: renderers} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n const frame = renderers.processes.get(Trace.Types.Events.ProcessID(SUB_FRAME_PID)) as\n Trace.Handlers.ModelHandlers.Renderer.RendererProcess;\n const thread = [...frame.threads.values()].find(thread => thread.name === 'CrRendererMain');\n if (!thread) {\n assert(false, 'Main thread was not found');\n }\n\n const tree = thread.tree;\n if (!tree) {\n assert(false, 'Main thread has no tree of events');\n }\n assert.deepEqual(\n [...tree.roots].map(root => root.id), [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20]);\n });\n\n it('builds a hierarchy for the main frame\\'s main thread in a real world profile', async () => {\n const {Renderer: renderers} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n const frame = renderers.processes.get(Trace.Types.Events.ProcessID(MAIN_FRAME_PID)) as\n Trace.Handlers.ModelHandlers.Renderer.RendererProcess;\n const thread = [...frame.threads.values()].find(thread => thread.name === 'CrRendererMain');\n if (!thread) {\n assert(false, 'Main thread was not found');\n }\n\n const tree = thread.tree;\n if (!tree) {\n assert(false, 'Main thread has no tree of events');\n }\n\n const isRoot = (node: Trace.Helpers.TreeHelpers.TraceEntryNode) => node.depth === 0;\n const isInstant = (event: Trace.Types.Events.Event) => Trace.Types.Events.isInstant(event);\n const isLong = (event: Trace.Types.Events.Event) => Trace.Types.Events.isComplete(event) && event.dur > 1000;\n const isIncluded = (node: Trace.Helpers.TreeHelpers.TraceEntryNode, event: Trace.Types.Events.Event) =>\n (!isRoot(node) || isInstant(event) || isLong(event)) &&\n Boolean(Components.EntryStyles.getEventStyle(event.name as Trace.Types.Events.Name));\n assert.strictEqual(prettyPrint(tree, isIncluded), `\n............\n-RunTask [2.21ms]\n.\n -MajorGC [2.148ms]\n...........................................................\n-RunTask [15.436ms]\n -FrameStartedLoading [0ms]\n -EventDispatch (pagehide) [0.018ms]\n -EventDispatch (visibilitychange) [0.01ms]\n -EventDispatch (webkitvisibilitychange) [0.006ms]\n.\n -EventDispatch (unload) [0.006ms]\n.\n -ResourceSendRequest [0ms]\n -ResourceReceiveResponse [0ms]\n...\n -ProfileCall (anonymous) [0.205ms]\n -ProfileCall (anonymous) [0.205ms]\n.......................\n-RunTask [3.402ms]\n -ParseHTML [2.593ms]\n....\n -ParseHTML [0.064ms]\n...\n -EventDispatch (readystatechange) [0.008ms]\n.\n -EventDispatch (DOMContentLoaded) [0.004ms]\n.\n -MarkDOMContent [0ms]\n.\n -EventDispatch (readystatechange) [0.01ms]\n -EventDispatch (beforeunload) [0.013ms]\n -FrameStartedLoading [0ms]\n.\n -ParseHTML [0.01ms]\n..\n -EventDispatch (readystatechange) [0.008ms]\n.\n -EventDispatch (DOMContentLoaded) [0.035ms]\n.\n -UpdateLayoutTree [0.373ms]\n -InvalidateLayout [0ms]\n -MarkDOMContent [0ms]\n-RunTask [2.675ms]\n -BeginMainThreadFrame [0ms]\n -Layout [0.854ms]\n -InvalidateLayout [0ms]\n -Layout [0.302ms]\n -UpdateLayoutTree [0.149ms]\n.\n -UpdateLayerTree [0.338ms]\n -Paint [0.203ms]\n..\n -firstPaint [0ms]\n -firstContentfulPaint [0ms]\n.....\n -largestContentfulPaint::Candidate [0ms]\n.................................\n-RunTask [1.605ms]\n -EventDispatch (pagehide) [0.014ms]\n -EventDispatch (visibilitychange) [0.038ms]\n -EventDispatch (webkitvisibilitychange) [0.009ms]\n -EventDispatch (unload) [0.004ms]\n.\n -ScheduleStyleRecalculation [0ms]\n..............\n-RunTask [1.231ms]\n -BeginMainThreadFrame [0ms]\n -UpdateLayoutTree [0.093ms]\n.\n -UpdateLayerTree [0.186ms]\n -Paint [0.063ms]\n -Paint [0.084ms]\n -UpdateLayer [0.022ms]\n -UpdateLayer [0.006ms]\n -CompositeLayers [0.311ms]\n............\n-RunTask [1.663ms]\n.\n -EventDispatch (readystatechange) [0.009ms]\n.\n -EventDispatch (load) [0.014ms]\n.\n -MarkLoad [0ms]\n -EventDispatch (pageshow) [0.007ms]\n.......................................................................................\n-RunTask [1.42ms]\n.\n -UpdateLayerTree [0.023ms]\n -HitTest [0.057ms]\n -EventDispatch (mousemove) [0.018ms]\n.\n -UpdateLayerTree [0.028ms]\n -HitTest [0.022ms]\n.\n -UpdateLayerTree [0.01ms]\n -HitTest [0.002ms]\n -ScheduleStyleRecalculation [0ms]\n -EventDispatch (mousedown) [0.018ms]\n -UpdateLayoutTree [0.146ms]\n.\n -UpdateLayerTree [0.031ms]\n -HitTest [0.016ms]\n -ScheduleStyleRecalculation [0ms]\n -UpdateLayoutTree [0.031ms]\n -EventDispatch (focus) [0.014ms]\n -EventDispatch (focusin) [0.005ms]\n -EventDispatch (DOMFocusIn) [0.005ms]\n.\n -UpdateLayerTree [0.029ms]\n.....\n-RunTask [1.034ms]\n.\n -UpdateLayerTree [0.021ms]\n -HitTest [0.038ms]\n -ScheduleStyleRecalculation [0ms]\n -EventDispatch (mouseup) [0.016ms]\n -EventDispatch (click) [0.44ms]\n -EventDispatch (beforeunload) [0.009ms]\n -FrameStartedLoading [0ms]\n.\n -UpdateLayoutTree [0.137ms]\n.\n -UpdateLayerTree [0.03ms]\n....................\n-RunTask [8.203ms]\n -EventDispatch (pagehide) [0.016ms]\n -EventDispatch (visibilitychange) [0.006ms]\n -EventDispatch (webkitvisibilitychange) [0.004ms]\n -EventDispatch (unload) [0.008ms]\n..\n -ResourceSendRequest [0ms]\n -ResourceSendRequest [0ms]\n -ResourceReceiveResponse [0ms]\n..........................\n-RunTask [2.996ms]\n -ParseHTML [2.368ms]\n....\n -ParseHTML [0.074ms]\n...\n -EventDispatch (readystatechange) [0.01ms]\n.\n -EventDispatch (DOMContentLoaded) [0.005ms]\n.\n -MarkDOMContent [0ms]\n.\n -EventDispatch (readystatechange) [0.008ms]\n -EventDispatch (beforeunload) [0.009ms]\n -FrameStartedLoading [0ms]\n.\n -ParseHTML [0.009ms]\n..\n -EventDispatch (readystatechange) [0.007ms]\n.\n -EventDispatch (DOMContentLoaded) [0.005ms]\n.\n -UpdateLayoutTree [0.301ms]\n -InvalidateLayout [0ms]\n -MarkDOMContent [0ms]\n.\n-RunTask [1.897ms]\n -BeginMainThreadFrame [0ms]\n -Layout [0.44ms]\n -InvalidateLayout [0ms]\n.\n -UpdateLayerTree [0.247ms]\n -Paint [0.289ms]\n..\n -firstPaint [0ms]\n -firstContentfulPaint [0ms]\n..\n -largestContentfulPaint::Candidate [0ms]\n....................................\n-RunTask [1.304ms]\n -EventDispatch (pagehide) [0.016ms]\n -EventDispatch (visibilitychange) [0.009ms]\n -EventDispatch (webkitvisibilitychange) [0.004ms]\n -EventDispatch (unload) [0.015ms]\n.\n -ScheduleStyleRecalculation [0ms]\n......................................................................................................................`);\n });\n\n it('builds a hierarchy for the sub frame\\'s main thread in a real world profile', async () => {\n const {Renderer: renderers} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n const frame = renderers.processes.get(Trace.Types.Events.ProcessID(SUB_FRAME_PID)) as\n Trace.Handlers.ModelHandlers.Renderer.RendererProcess;\n const thread = [...frame.threads.values()].find(thread => thread.name === 'CrRendererMain');\n if (!thread) {\n assert(false, 'Main thread was not found');\n }\n\n const tree = thread.tree;\n if (!tree) {\n assert(false, 'Main thread has no tree of events');\n }\n const isIncluded = (_node: Trace.Helpers.TreeHelpers.TraceEntryNode, event: Trace.Types.Events.Event) =>\n Boolean(Components.EntryStyles.getEventStyle(event.name as Trace.Types.Events.Name));\n assert.strictEqual(prettyPrint(tree, isIncluded), `\n-RunTask [0.13ms]\n-RunTask [0.005ms]\n-RunTask [0.009ms]\n-RunTask [0.065ms]\n-RunTask [0.084ms]\n-RunTask [0.041ms]\n-RunTask [0.057ms]\n-RunTask [0.021ms]\n-RunTask [0.009ms]\n-RunTask [0.065ms]\n-RunTask [0.078ms]\n-RunTask [0.043ms]\n-RunTask [0.077ms]\n -ScheduleStyleRecalculation [0ms]\n-RunTask [0.415ms]\n-RunTask [0ms]\n-EventDispatch (pagehide) [0.012ms]\n-EventDispatch (visibilitychange) [0.007ms]\n-EventDispatch (webkitvisibilitychange) [0.016ms]\n-EventDispatch (unload) [0.007ms]\n.`);\n });\n\n it('has some correct known roots for the main frame\\'s main thread in a real world profile', async () => {\n const {Renderer: renderers} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n const frame = renderers.processes.get(Trace.Types.Events.ProcessID(MAIN_FRAME_PID)) as\n Trace.Handlers.ModelHandlers.Renderer.RendererProcess;\n const thread = [...frame.threads.values()].find(thread => thread.name === 'CrRendererMain');\n if (!thread) {\n assert(false, 'Main thread was not found');\n }\n\n const tree = thread.tree;\n if (!tree) {\n assert(false, 'Main thread has no tree of events');\n }\n\n const event0 = getRootAt(thread, 1).entry;\n assert.deepEqual(event0 as unknown, {\n args: {},\n cat: 'disabled-by-default-devtools.timeline',\n dur: 132,\n name: 'RunTask',\n ph: 'X',\n pid: 2154214,\n tdur: 131,\n tid: 1,\n ts: 643492822363,\n tts: 291450,\n });\n assert.strictEqual(renderers.entryToNode.get(event0)?.selfTime, 132);\n\n const event1 = getRootAt(thread, 2).entry;\n assert.deepEqual(event1 as unknown, {\n args: {},\n cat: 'disabled-by-default-devtools.timeline',\n dur: 4,\n name: 'RunTask',\n ph: 'X',\n pid: 2154214,\n tdur: 4,\n tid: 1,\n ts: 643492822500,\n tts: 291586,\n });\n assert.strictEqual(renderers.entryToNode.get(event1)?.selfTime, 4);\n\n const eventLast = getRootAt(thread, tree.roots.size - 1).entry;\n assert.deepEqual(eventLast as unknown, {\n args: {},\n cat: 'disabled-by-default-devtools.timeline',\n dur: 67,\n name: 'RunTask',\n ph: 'X',\n pid: 2154214,\n tdur: 67,\n tid: 1,\n ts: 643499551460,\n tts: 949032,\n });\n assert.strictEqual(renderers.entryToNode.get(eventLast)?.selfTime, 35);\n });\n\n it('has some correct known roots for the sub frame\\'s main thread in a real world profile', async () => {\n const {Renderer: renderers} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n const frame = renderers.processes.get(Trace.Types.Events.ProcessID(SUB_FRAME_PID)) as\n Trace.Handlers.ModelHandlers.Renderer.RendererProcess;\n const thread = [...frame.threads.values()].find(thread => thread.name === 'CrRendererMain');\n if (!thread) {\n assert(false, 'Main thread was not found');\n }\n\n const tree = thread.tree;\n if (!tree) {\n assert(false, 'Main thread has no tree of events');\n }\n\n const event0 = getRootAt(thread, 0).entry;\n assert.deepEqual(event0 as unknown, {\n args: {},\n cat: 'disabled-by-default-devtools.timeline',\n dur: 130,\n name: 'RunTask',\n ph: 'X',\n pid: 2236065,\n tdur: 129,\n tid: 1,\n ts: 643492822099,\n tts: 62157,\n });\n assert.strictEqual(renderers.entryToNode.get(event0)?.selfTime, 130);\n\n const event1 = getRootAt(thread, 1).entry;\n assert.deepEqual(event1 as unknown, {\n args: {},\n cat: 'disabled-by-default-devtools.timeline',\n dur: 5,\n name: 'RunTask',\n ph: 'X',\n pid: 2236065,\n tdur: 5,\n tid: 1,\n ts: 643492822234,\n tts: 62291,\n });\n assert.strictEqual(renderers.entryToNode.get(event1)?.selfTime, 5);\n\n const event2 = getRootAt(thread, 2).entry;\n\n assert.deepEqual(event2 as unknown, {\n args: {},\n cat: 'disabled-by-default-devtools.timeline',\n dur: 9,\n name: 'RunTask',\n ph: 'X',\n pid: 2236065,\n tdur: 9,\n tid: 1,\n ts: 643492822242,\n tts: 62299,\n });\n assert.strictEqual(renderers.entryToNode.get(event2)?.selfTime, 9);\n });\n\n it('can correctly sort a simple list of complete events', async () => {\n const data = [\n makeCompleteEvent('d0', 2, 1),\n makeCompleteEvent('b0', 1, 1),\n makeCompleteEvent('a0', 0, 1),\n makeCompleteEvent('a1', 0, 0.5),\n makeCompleteEvent('a2', 0.5, 0.5),\n makeCompleteEvent('c0', 1.5, 0.5),\n makeCompleteEvent('a4', 0.99, 0.01),\n makeCompleteEvent('b1', 1, 0.01),\n makeCompleteEvent('a3', 0.5, 0.25),\n ];\n\n Trace.Helpers.Trace.sortTraceEventsInPlace(data);\n\n assert.deepEqual(data.map(e => ({name: e.name, ts: e.ts, dur: e.dur})) as unknown, [\n {name: 'a0', ts: 0, dur: 1},\n {name: 'a1', ts: 0, dur: 0.5},\n {name: 'a2', ts: 0.5, dur: 0.5},\n {name: 'a3', ts: 0.5, dur: 0.25},\n {name: 'a4', ts: 0.99, dur: 0.01},\n {name: 'b0', ts: 1, dur: 1},\n {name: 'b1', ts: 1, dur: 0.01},\n {name: 'c0', ts: 1.5, dur: 0.5},\n {name: 'd0', ts: 2, dur: 1},\n ]);\n });\n\n it('can correctly sort a simple list of complete events interspersed with instant events', async () => {\n const data = [\n makeCompleteEvent('d0', 2, 1),\n makeInstantEvent('i0', 0),\n makeCompleteEvent('b0', 1, 1),\n makeInstantEvent('i1', 0.01),\n makeCompleteEvent('a0', 0, 1),\n makeInstantEvent('i2', 0.5),\n makeCompleteEvent('a1', 0, 0.5),\n makeInstantEvent('i3', 0.99),\n makeCompleteEvent('a2', 0.5, 0.5),\n makeInstantEvent('i4', 1),\n makeCompleteEvent('c0', 1.5, 0.5),\n makeInstantEvent('i5', 1.75),\n makeCompleteEvent('a4', 0.99, 0.01),\n makeInstantEvent('i6', 1.99),\n makeCompleteEvent('b1', 1, 0.01),\n makeInstantEvent('i7', 2),\n makeCompleteEvent('a3', 0.5, 0.25),\n makeInstantEvent('i8', 2.01),\n ];\n\n Trace.Helpers.Trace.sortTraceEventsInPlace(data);\n\n assert.deepEqual(data.map(e => ({name: e.name, ts: e.ts, dur: e.dur})) as unknown, [\n {name: 'a0', ts: 0, dur: 1},\n {name: 'a1', ts: 0, dur: 0.5},\n {name: 'i0', ts: 0, dur: undefined},\n {name: 'i1', ts: 0.01, dur: undefined},\n {name: 'a2', ts: 0.5, dur: 0.5},\n {name: 'a3', ts: 0.5, dur: 0.25},\n {name: 'i2', ts: 0.5, dur: undefined},\n {name: 'a4', ts: 0.99, dur: 0.01},\n {name: 'i3', ts: 0.99, dur: undefined},\n {name: 'b0', ts: 1, dur: 1},\n {name: 'b1', ts: 1, dur: 0.01},\n {name: 'i4', ts: 1, dur: undefined},\n {name: 'c0', ts: 1.5, dur: 0.5},\n {name: 'i5', ts: 1.75, dur: undefined},\n {name: 'i6', ts: 1.99, dur: undefined},\n {name: 'd0', ts: 2, dur: 1},\n {name: 'i7', ts: 2, dur: undefined},\n {name: 'i8', ts: 2.01, dur: undefined},\n ]);\n });\n\n it('can process multiple processes', async () => {\n /**\n * |------------- Task A -------------||-- Task E --|\n * |-- Task B --||-- Task D --|\n * |- Task C -|\n */\n const data1 = [\n makeCompleteEvent('A', 0, 10), // 0..10\n makeCompleteEvent('B', 1, 3), // 1..4\n makeCompleteEvent('D', 5, 3), // 5..8\n makeCompleteEvent('C', 2, 1), // 2..3\n makeCompleteEvent('E', 11, 3), // 11..14\n ];\n\n /**\n * |-- Task F --||------------- Task G -------------|\n * |-- Task H --||-- Task J --|\n * |- Task I -|\n */\n const data2 = [\n makeCompleteEvent('F', 0, 3), // 0..3\n makeCompleteEvent('G', 3, 10), // 3..13 (starts when F finishes)\n makeCompleteEvent('H', 3, 3), // 3..6 (starts same time as G)\n makeCompleteEvent('J', 6, 3), // 6..9 (starts when H finishes)\n makeCompleteEvent('I', 5, 1), // 5..6 (finishes when H finishes)\n ];\n\n const processes = new Map([\n [\n Trace.Types.Events.ProcessID(0),\n {\n url: ('http://a.com'),\n isOnMainFrame: true,\n threads: new Map([[\n Trace.Types.Events.ThreadID(1),\n {name: 'Foo', entries: data1},\n ]]),\n } as Trace.Handlers.ModelHandlers.Renderer.RendererProcess,\n ],\n [\n Trace.Types.Events.ProcessID(2),\n {\n url: ('http://b.com'),\n isOnMainFrame: false,\n threads: new Map([[\n Trace.Types.Events.ThreadID(3),\n {name: 'Bar', entries: data2},\n ]]),\n } as Trace.Handlers.ModelHandlers.Renderer.RendererProcess,\n ],\n ]);\n\n Trace.Handlers.ModelHandlers.Samples.initialize();\n await Trace.Handlers.ModelHandlers.Samples.finalize();\n Trace.Handlers.ModelHandlers.Renderer.buildHierarchy(processes, {filter: {has: () => true}});\n\n const firstThread = [...[...processes.values()][0].threads.values()][0];\n const secondThread = [...[...processes.values()][1].threads.values()][0];\n\n if (!firstThread.tree || !secondThread.tree) {\n assert(false, 'Trees not found');\n }\n\n assert.strictEqual(firstThread.tree.maxDepth, 3, 'Got the correct tree max depth for the first thread');\n assert.strictEqual(secondThread.tree.maxDepth, 3, 'Got the correct tree max depth for the second thread');\n\n const firstRoots = getEventsIn(firstThread.tree.roots.values());\n assert.deepEqual(firstRoots.map(e => e ? {name: e.name, ts: e.ts, dur: e.dur} : null) as unknown[], [\n {name: 'A', ts: 0, dur: 10},\n {name: 'E', ts: 11, dur: 3},\n ]);\n\n const secondRoots = getEventsIn(secondThread.tree.roots.values());\n assert.deepEqual(secondRoots.map(e => e ? {name: e.name, ts: e.ts, dur: e.dur} : null) as unknown[], [\n {name: 'F', ts: 0, dur: 3},\n {name: 'G', ts: 3, dur: 10},\n ]);\n });\n\n it('can assign origins to processes', async () => {\n const {Meta: metadata} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n const processes: Map =\n new Map();\n\n Trace.Handlers.ModelHandlers.Renderer.assignOrigin(processes, metadata.rendererProcessesByFrame);\n\n assert.deepEqual([...processes].map(([pid, p]) => [pid, p.url ? new URL(p.url).origin : null]), [\n [Trace.Types.Events.ProcessID(MAIN_FRAME_PID), 'http://localhost:5000'],\n [Trace.Types.Events.ProcessID(SUB_FRAME_PID), 'https://www.example.com'],\n [Trace.Types.Events.ProcessID(SUB_FRAME_PID_2), 'https://www.example.com'],\n [Trace.Types.Events.ProcessID(SUB_FRAME_PID_3), 'https://www.example.com'],\n ]);\n });\n\n it('can assign main frame flags to processes', async () => {\n const {Meta: metadata} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n const processes: Map =\n new Map();\n\n Trace.Handlers.ModelHandlers.Renderer.assignIsMainFrame(\n processes, metadata.mainFrameId, metadata.rendererProcessesByFrame);\n\n assert.deepEqual([...processes].map(([pid, p]) => [pid, p.isOnMainFrame]), [\n [Trace.Types.Events.ProcessID(MAIN_FRAME_PID), true],\n [Trace.Types.Events.ProcessID(SUB_FRAME_PID), false],\n [Trace.Types.Events.ProcessID(SUB_FRAME_PID_2), false],\n [Trace.Types.Events.ProcessID(SUB_FRAME_PID_3), false],\n ]);\n });\n\n it('can assign thread names to threads in processes', async () => {\n const {Meta: metadata} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n const {mainFrameId, rendererProcessesByFrame, threadsInProcess} = metadata;\n const processes: Map =\n new Map();\n\n Trace.Handlers.ModelHandlers.Renderer.assignMeta(\n processes, mainFrameId, rendererProcessesByFrame, threadsInProcess);\n\n assert.deepEqual([...processes].map(([pid, p]) => [pid, [...p.threads].map(([tid, t]) => [tid, t.name])]), [\n [\n Trace.Types.Events.ProcessID(MAIN_FRAME_PID),\n [\n [Trace.Types.Events.ThreadID(1), 'CrRendererMain'],\n [Trace.Types.Events.ThreadID(7), 'Compositor'],\n [Trace.Types.Events.ThreadID(2), 'ThreadPoolServiceThread'],\n [Trace.Types.Events.ThreadID(4), 'Chrome_ChildIOThread'],\n [Trace.Types.Events.ThreadID(24), 'ThreadPoolForegroundWorker'],\n [Trace.Types.Events.ThreadID(27), 'ThreadPoolForegroundWorker'],\n [Trace.Types.Events.ThreadID(17), 'ThreadPoolForegroundWorker'],\n [Trace.Types.Events.ThreadID(29), 'ThreadPoolForegroundWorker'],\n [Trace.Types.Events.ThreadID(25), 'ThreadPoolForegroundWorker'],\n [Trace.Types.Events.ThreadID(28), 'ThreadPoolForegroundWorker'],\n [Trace.Types.Events.ThreadID(30), 'ThreadPoolForegroundWorker'],\n [Trace.Types.Events.ThreadID(26), 'ThreadPoolForegroundWorker'],\n [Trace.Types.Events.ThreadID(11), 'CompositorTileWorker3'],\n [Trace.Types.Events.ThreadID(12), 'CompositorTileWorker4'],\n [Trace.Types.Events.ThreadID(10), 'CompositorTileWorker2'],\n [Trace.Types.Events.ThreadID(9), 'CompositorTileWorker1'],\n ],\n ],\n [\n Trace.Types.Events.ProcessID(SUB_FRAME_PID),\n [\n [Trace.Types.Events.ThreadID(2), 'ThreadPoolServiceThread'],\n [Trace.Types.Events.ThreadID(1), 'CrRendererMain'],\n [Trace.Types.Events.ThreadID(7), 'Compositor'],\n [Trace.Types.Events.ThreadID(4), 'Chrome_ChildIOThread'],\n ],\n ],\n [\n Trace.Types.Events.ProcessID(SUB_FRAME_PID_2),\n [\n [Trace.Types.Events.ThreadID(1), 'CrRendererMain'],\n [Trace.Types.Events.ThreadID(4), 'Chrome_ChildIOThread'],\n [Trace.Types.Events.ThreadID(8), 'Compositor'],\n [Trace.Types.Events.ThreadID(2), 'ThreadPoolServiceThread'],\n [Trace.Types.Events.ThreadID(10), 'CompositorTileWorker1'],\n ],\n ],\n [\n Trace.Types.Events.ProcessID(SUB_FRAME_PID_3),\n [\n [Trace.Types.Events.ThreadID(1), 'CrRendererMain'],\n [Trace.Types.Events.ThreadID(2), 'ThreadPoolServiceThread'],\n [Trace.Types.Events.ThreadID(4), 'Chrome_ChildIOThread'],\n [Trace.Types.Events.ThreadID(7), 'Compositor'],\n [Trace.Types.Events.ThreadID(10), 'CompositorTileWorker2'],\n [Trace.Types.Events.ThreadID(3), 'ThreadPoolForegroundWorker'],\n ],\n ],\n ]);\n });\n\n it('populates the map of trace events to tree nodes', async () => {\n const {Renderer: renderers} = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n assert.strictEqual(renderers.entryToNode.size, 3591);\n });\n\n describe('Synthetic complete events', () => {\n async function handleEvents(traceEvents: Trace.Types.Events.Event[]):\n Promise {\n Trace.Handlers.ModelHandlers.Renderer.reset();\n Trace.Handlers.ModelHandlers.Meta.reset();\n Trace.Handlers.ModelHandlers.Samples.reset();\n Trace.Handlers.ModelHandlers.Meta.initialize();\n Trace.Handlers.ModelHandlers.Samples.initialize();\n Trace.Handlers.ModelHandlers.Renderer.initialize();\n\n for (const event of traceEvents) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n Trace.Handlers.ModelHandlers.Renderer.handleEvent(event);\n }\n\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n await Trace.Handlers.ModelHandlers.Samples.finalize();\n await Trace.Handlers.ModelHandlers.Renderer.finalize();\n return Trace.Handlers.ModelHandlers.Renderer.data();\n }\n let defaultTraceEvents: readonly Trace.Types.Events.Event[];\n const pid = Trace.Types.Events.ProcessID(28274);\n const tid = Trace.Types.Events.ThreadID(775);\n beforeEach(async function() {\n defaultTraceEvents = await TraceLoader.rawEvents(this, 'basic.json.gz');\n });\n\n afterEach(() => {\n Trace.Handlers.ModelHandlers.Renderer.reset();\n Trace.Handlers.ModelHandlers.Meta.reset();\n Trace.Handlers.ModelHandlers.Samples.reset();\n });\n\n it('builds a hierarchy using begin and end trace events', async () => {\n // |------------- RunTask -------------||-- RunTask --|\n // |-- RunMicrotasks --||-- Layout --|\n // |- FunctionCall -|\n const traceEvents = [\n ...defaultTraceEvents, makeBeginEvent('RunTask', 0, '*', pid, tid), // 0..10\n makeBeginEvent('RunMicrotasks', 1, '*', pid, tid), // 1..4\n makeBeginEvent('FunctionCall', 2, '*', pid, tid), // 2..3\n makeEndEvent('FunctionCall', 3, '*', pid, tid), // 2..3\n makeEndEvent('RunMicrotasks', 4, '*', pid, tid), // 1..4\n makeBeginEvent('Layout', 5, '*', pid, tid), // 5..8\n makeEndEvent('Layout', 8, '*', pid, tid), // 5..8\n makeEndEvent('RunTask', 10, '*', pid, tid), // 0..10\n makeBeginEvent('RunTask', 11, '*', pid, tid), // 11..14\n makeEndEvent('RunTask', 14, '*', pid, tid), // 11..14\n ];\n\n const data = await handleEvents(traceEvents);\n\n assert.strictEqual(data.allTraceEntries.length, 7);\n assert.strictEqual(data.processes.size, 1);\n const [process] = data.processes.values();\n assert.strictEqual(process.threads.size, 1);\n const [thread] = process.threads.values();\n assert.strictEqual(thread.tree?.roots.size, 2);\n if (!thread.tree?.roots) {\n // This shouldn't happen, since the tree.roots.size is 2, but add this if check to pass ts check.\n return;\n }\n const allNodes = getAllNodes(thread.tree?.roots);\n assert.strictEqual(allNodes.length, 5);\n if (!thread.tree) {\n return;\n }\n assert.strictEqual(prettyPrint(thread.tree), `\n-RunTask [0.01ms]\n -RunMicrotasks [0.003ms]\n -FunctionCall [0.001ms]\n -Layout [0.003ms]\n-RunTask [0.003ms]`);\n });\n it('builds a hierarchy using complete, begin and end trace events', async () => {\n // |------------- RunTask -------------|\n // |-- RunMicrotasks --||-- Layout --|\n // |- FunctionCall -|\n\n const traceEvents = [\n ...defaultTraceEvents, makeBeginEvent('RunTask', 0, '*', pid, tid), // 0..10\n makeBeginEvent('RunMicrotasks', 1, '*', pid, tid), // 1..4\n makeCompleteEvent('FunctionCall', 2, 1, '*', pid, tid), // 2..3\n makeEndEvent('RunMicrotasks', 4, '*', pid, tid), // 1..4\n makeBeginEvent('Layout', 5, '*', pid, tid), // 5..8\n makeEndEvent('Layout', 8, '*', pid, tid), // 5..8\n makeEndEvent('RunTask', 10, '*', pid, tid), // 0..10\n ];\n\n const data = await handleEvents(traceEvents);\n\n assert.strictEqual(data.allTraceEntries.length, 6);\n assert.strictEqual(data.processes.size, 1);\n const [process] = data.processes.values();\n assert.strictEqual(process.threads.size, 1);\n const [thread] = process.threads.values();\n assert.strictEqual(thread.tree?.roots.size, 1);\n if (!thread.tree?.roots) {\n // This shouldn't happen, since the tree.roots.size is 1, but add this if check to pass ts check.\n return;\n }\n const allNodes = getAllNodes(thread.tree?.roots);\n assert.strictEqual(allNodes.length, 4);\n if (!thread.tree) {\n return;\n }\n assert.strictEqual(prettyPrint(thread.tree), `\n-RunTask [0.01ms]\n -RunMicrotasks [0.003ms]\n -FunctionCall [0.001ms]\n -Layout [0.003ms]`);\n });\n\n it('keeps a FunctionCall that has the end event missing', async () => {\n const traceEvents = [\n ...defaultTraceEvents, makeBeginEvent('RunMicrotasks', 1, '*', pid, tid), // 1..4\n makeBeginEvent('FunctionCall', 2, '*', pid, tid), // 2..3\n ];\n\n const data = await handleEvents(traceEvents);\n assert.strictEqual(data.processes.size, 1);\n const [process] = data.processes.values();\n assert.strictEqual(process.threads.size, 1);\n const [thread] = process.threads.values();\n if (!thread.tree) {\n throw new Error('thread should have a tree');\n }\n // Ensure that the FunctionCall event has been kept despite not having an END event.\n assert.deepEqual(thread.entries.map(e => e.name), ['RunMicrotasks', 'FunctionCall']);\n });\n });\n\n describe('building hierarchies trace events and profile calls', () => {\n it('build a hierarchy using data from real world trace file', async () => {\n const {Renderer} = await handleEventsFromTraceFile(this, 'recursive-counting-js.json.gz');\n const threadId = Trace.Types.Events.ThreadID(259);\n const firstProcessId = Trace.Types.Events.ProcessID(23239);\n const thread = Renderer.processes.get(firstProcessId)?.threads.get(threadId);\n if (!thread || !thread.tree) {\n throw new Error('Tree not found');\n }\n const onlyLongTasksPredicate =\n (_node: Trace.Helpers.TreeHelpers.TraceEntryNode, event: Trace.Types.Events.Event) =>\n Boolean(event.dur && event.dur > 1000) &&\n Boolean(Components.EntryStyles.getEventStyle(event.name as Trace.Types.Events.Name));\n assert.strictEqual(prettyPrint(thread.tree, onlyLongTasksPredicate), `\n.............\n-RunTask [17.269ms]\n.............................\n-RunTask [1065.663ms]\n -ParseHTML [1065.609ms]\n.........\n-RunTask [1.12ms]\n -ParseHTML [1.082ms]\n.........................................................\n-RunTask [1058.811ms]\n -TimerFire [1058.77ms]\n -FunctionCall [1058.693ms]\n.\n -ProfileCall (anonymous) [1058.589ms]\n -ProfileCall (foo) [1058.589ms]\n -ProfileCall (foo) [1058.589ms]\n -ProfileCall (foo) [1058.589ms]\n -ProfileCall (foo) [1058.589ms]\n..\n -ProfileCall (count) [1058.453ms]\n........\n-RunTask [1057.455ms]\n -TimerFire [1057.391ms]\n -FunctionCall [1057.27ms]\n.\n -ProfileCall (anonymous) [1056.579ms]\n -ProfileCall (foo) [1056.579ms]\n -ProfileCall (foo) [1056.579ms]\n -ProfileCall (foo) [1056.579ms]\n -ProfileCall (foo) [1056.579ms]\n -ProfileCall (count) [1056.538ms]\n........`);\n });\n });\n\n it('identifies and returns rasterizer threads', async () => {\n const {Renderer} = await handleEventsFromTraceFile(this, 'web-dev.json.gz');\n assert.deepEqual(Array.from(Renderer.compositorTileWorkers.entries()), [\n [\n Trace.Types.Events.ProcessID(68481),\n [\n Trace.Types.Events.ThreadID(81675),\n ],\n ],\n [\n Trace.Types.Events.ProcessID(73704),\n [\n Trace.Types.Events.ThreadID(23299),\n Trace.Types.Events.ThreadID(22275),\n Trace.Types.Events.ThreadID(41475),\n Trace.Types.Events.ThreadID(40451),\n Trace.Types.Events.ThreadID(22531),\n ],\n ],\n ]);\n });\n\n it('keeps the processes associated with AuctionWorklets and assigns them URLs', async () => {\n const {Renderer, AuctionWorklets} = await handleEventsFromTraceFile(this, 'fenced-frame-fledge.json.gz');\n assert.strictEqual(AuctionWorklets.worklets.size, 3);\n for (const [pid] of AuctionWorklets.worklets) {\n const process = Renderer.processes.get(pid);\n assert.exists(process);\n // Ensure that the URL was set properly based on the AuctionWorklets metadata event.\n assert.isTrue(process?.url?.includes('fledge-demo.glitch.me'));\n }\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/SamplesHandler.d.ts b/public/models/trace/handlers/SamplesHandler.d.ts index 28fe5a2e2..c887a89c2 100644 --- a/public/models/trace/handlers/SamplesHandler.d.ts +++ b/public/models/trace/handlers/SamplesHandler.d.ts @@ -1,11 +1,11 @@ import * as CPUProfile from '../../cpu_profile/cpu_profile.js'; import * as Helpers from '../helpers/helpers.js'; import * as Types from '../types/types.js'; -declare const profilesInProcess: Map>; -declare const entryToNode: Map; +declare const profilesInProcess: Map>; +declare const entryToNode: Map; export declare function reset(): void; export declare function initialize(): void; -export declare function handleEvent(event: Types.TraceEvents.TraceEventData): void; +export declare function handleEvent(event: Types.Events.Event): void; export declare function finalize(): Promise; export declare function data(): SamplesHandlerData; export interface SamplesHandlerData { @@ -13,7 +13,7 @@ export interface SamplesHandlerData { entryToNode: typeof entryToNode; } export type ProfileData = { - profileId: Types.TraceEvents.ProfileID; + profileId: Types.Events.ProfileID; rawProfile: CPUProfile.CPUProfileDataModel.ExtendedProfile; parsedProfile: CPUProfile.CPUProfileDataModel.CPUProfileDataModel; /** @@ -26,7 +26,7 @@ export type ProfileData = { * If you need the profile calls from a CPU profile obtained from a * web trace, use the data exported by the RendererHandler instead. */ - profileCalls: Types.TraceEvents.SyntheticProfileCall[]; + profileCalls: Types.Events.SyntheticProfileCall[]; /** * Contains the call tree built from the CPU profile samples. * Similar to the profileCalls field, this tree does not contain nor @@ -43,5 +43,5 @@ export type ProfileData = { * we fall back to the function name that was in the callframe that we got * when parsing the profile's trace data. */ -export declare function getProfileCallFunctionName(data: SamplesHandlerData, entry: Types.TraceEvents.SyntheticProfileCall): string; +export declare function getProfileCallFunctionName(data: SamplesHandlerData, entry: Types.Events.SyntheticProfileCall): string; export {}; diff --git a/public/models/trace/handlers/SamplesHandler.js b/public/models/trace/handlers/SamplesHandler.js index 14c3f033e..008257811 100644 --- a/public/models/trace/handlers/SamplesHandler.js +++ b/public/models/trace/handlers/SamplesHandler.js @@ -106,7 +106,7 @@ export function handleEvent(event) { * A fake trace event created to support CDP.Profiler.Profiles in the * trace engine. */ - if (Types.TraceEvents.isSyntheticCpuProfile(event)) { + if (Types.Events.isSyntheticCpuProfile(event)) { // At the moment we are attaching to a single node target so we // should only get a single CPU profile. The values of the process // id and thread id are not really important, so we use the data @@ -121,7 +121,7 @@ export function handleEvent(event) { profileData.threadId = tid; return; } - if (Types.TraceEvents.isTraceEventProfile(event)) { + if (Types.Events.isProfile(event)) { // Do not use event.args.data.startTime as it is in CLOCK_MONOTONIC domain, // but use profileEvent.ts which has been translated to Perfetto's clock // domain. Also convert from ms to us. @@ -132,7 +132,7 @@ export function handleEvent(event) { profileData.threadId = event.tid; return; } - if (Types.TraceEvents.isTraceEventProfileChunk(event)) { + if (Types.Events.isProfileChunk(event)) { const profileData = getOrCreatePreProcessedData(event.pid, event.id); const cdpProfile = profileData.rawProfile; const nodesAndSamples = event.args?.data?.cpuProfile || { samples: [] }; diff --git a/public/models/trace/handlers/SamplesHandler.js.map b/public/models/trace/handlers/SamplesHandler.js.map index e5a0f09c0..eee561147 100644 --- a/public/models/trace/handlers/SamplesHandler.js.map +++ b/public/models/trace/handlers/SamplesHandler.js.map @@ -1 +1 @@ -{"version":3,"file":"SamplesHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/SamplesHandler.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,QAAQ,MAAM,oCAAoC,CAAC;AAE/D,OAAO,KAAK,UAAU,MAAM,kCAAkC,CAAC;AAC/D,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAI3C,MAAM,MAAM,GACR,IAAI,GAAG,EAAwG,CAAC;AAEpH,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAA6E,CAAC;AAC/G,MAAM,WAAW,GAAG,IAAI,GAAG,EAAwE,CAAC;AAEpG,2DAA2D;AAC3D,6DAA6D;AAC7D,sEAAsE;AACtE,uEAAuE;AACvE,sEAAsE;AACtE,mDAAmD;AACnD,uEAAuE;AACvE,uEAAuE;AACvE,+BAA+B;AAC/B,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAmF,CAAC;AAEpH,IAAI,YAAY,qCAA6B,CAAC;AAE9C,SAAS,iBAAiB;IACxB,KAAK,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,gBAAgB,EAAE,CAAC;QACrD,KAAK,MAAM,CAAC,SAAS,EAAE,gBAAgB,CAAC,IAAI,QAAQ,EAAE,CAAC;YACrD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,CAAC;YAC3C,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBACxE,SAAS;YACX,CAAC;YACD,MAAM,UAAU,GAAa,EAAE,CAAC;YAEhC,MAAM,YAAY,GAAG,IAAI,UAAU,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;YACzG,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,uBAAuB,EAAE,CAAC;YAClE,WAAW,CAAC,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC;YAE7C,MAAM,aAAa,GAAgB;gBACjC,UAAU,EAAE,gBAAgB,CAAC,UAAU;gBACvC,aAAa,EAAE,YAAY;gBAC3B,YAAY,EAAE,EAAE;gBAChB,WAAW;gBACX,SAAS;aACV,CAAC;YAEF,MAAM,YAAY,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,iBAAiB,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;YACzG,YAAY,CAAC,YAAY,CAAC,iBAAiB,EAAE,kBAAkB,CAAC,CAAC;YACjE,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;YAE1C,SAAS,iBAAiB,CACtB,KAAa,EAAE,IAA6C,EAAE,WAAmB,EACjF,qBAA6B;gBAC/B,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;oBAC3B,OAAO;gBACT,CAAC;gBACD,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,qBAAqB,CAAC,CAAC,CAAC;gBACvG,MAAM,MAAM,GAAG,IAAI,CAAC,EAA0C,CAAC;gBAE/D,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;gBACzG,aAAa,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;gBAC7C,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBACvD,MAAM,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,uBAAuB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;gBACxF,WAAW,CAAC,GAAG,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;gBAC7C,cAAc,CAAC,KAAK,GAAG,KAAK,CAAC;gBAC7B,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC5B,0CAA0C;oBAC1C,aAAa,CAAC,WAAW,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;gBACvD,CAAC;YACH,CAAC;YACD,SAAS,kBAAkB,CACvB,MAAc,EAAE,KAA8C,EAAE,YAAoB,EACpF,gBAAwB,EAAE,KAAa,EAAE,UAAkB;gBAC7D,MAAM,gBAAgB,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC;gBAC1C,MAAM,WAAW,GAAG,gBAAgB,KAAK,SAAS,IAAI,aAAa,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;gBACnG,IAAI,CAAC,WAAW,EAAE,CAAC;oBACjB,OAAO;gBACT,CAAC;gBACD,MAAM,EAAC,SAAS,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAC,GAAG,WAAW,CAAC;gBAC9C,MAAM,cAAc,GAAG,WAAW,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;gBACpD,IAAI,SAAS,KAAK,SAAS,IAAI,EAAE,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS,IAAI,SAAS,KAAK,SAAS;oBAC3F,GAAG,KAAK,SAAS,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;oBACtD,OAAO;gBACT,CAAC;gBACD,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;gBACxF,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC;gBAClG,WAAW,CAAC,GAAG,GAAG,GAAG,CAAC;gBACtB,cAAc,CAAC,QAAQ,GAAG,QAAQ,CAAC;gBAEnC,MAAM,WAAW,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;gBACtC,MAAM,MAAM,GAAG,WAAW,KAAK,SAAS,IAAI,aAAa,CAAC,YAAY,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC;gBACvF,MAAM,UAAU,GAAG,MAAM,IAAI,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACrD,IAAI,CAAC,UAAU,EAAE,CAAC;oBAChB,OAAO;gBACT,CAAC;gBACD,cAAc,CAAC,MAAM,GAAG,UAAU,CAAC;gBACnC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,KAAK;IACnB,MAAM,CAAC,KAAK,EAAE,CAAC;IACf,gBAAgB,CAAC,KAAK,EAAE,CAAC;IACzB,iBAAiB,CAAC,KAAK,EAAE,CAAC;IAC1B,WAAW,CAAC,KAAK,EAAE,CAAC;IACpB,YAAY,qCAA6B,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,IAAI,YAAY,uCAA+B,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IAED,YAAY,mCAA2B,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAuC;IACjE,IAAI,YAAY,qCAA6B,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IAED;;;OAGG;IACH,IAAI,KAAK,CAAC,WAAW,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE,CAAC;QACnD,+DAA+D;QAC/D,kEAAkE;QAClE,gEAAgE;QAChE,oEAAoE;QACpE,8DAA8D;QAC9D,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;QACtB,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;QACtB,kCAAkC;QAClC,MAAM,SAAS,GAAG,KAAoC,CAAC;QACvD,MAAM,WAAW,GAAG,2BAA2B,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAChE,WAAW,CAAC,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;QACpD,WAAW,CAAC,QAAQ,GAAG,GAAG,CAAC;QAC3B,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,WAAW,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC;QACjD,2EAA2E;QAC3E,wEAAwE;QACxE,sCAAsC;QACtC,wEAAwE;QACxE,mEAAmE;QACnE,MAAM,WAAW,GAAG,2BAA2B,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;QACrE,WAAW,CAAC,UAAU,CAAC,SAAS,GAAG,KAAK,CAAC,EAAE,CAAC;QAC5C,WAAW,CAAC,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC;QACjC,OAAO;IACT,CAAC;IACD,IAAI,KAAK,CAAC,WAAW,CAAC,wBAAwB,CAAC,KAAK,CAAC,EAAE,CAAC;QACtD,MAAM,WAAW,GAAG,2BAA2B,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;QACrE,MAAM,UAAU,GAAG,WAAW,CAAC,UAAU,CAAC;QAC1C,MAAM,eAAe,GACjB,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,IAAI,EAAC,OAAO,EAAE,EAAE,EAAC,CAAC;QAClD,MAAM,OAAO,GAAG,eAAe,EAAE,OAAO,IAAI,EAAE,CAAC;QAC/C,MAAM,KAAK,GAAyD,EAAE,CAAC;QACvE,KAAK,MAAM,CAAC,IAAI,eAAe,EAAE,KAAK,IAAI,EAAE,EAAE,CAAC;YAC7C,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,SAAS,CAAC,UAAU,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC;YAC/F,MAAM,YAAY,GAAG,OAAO,CAAC,CAAC,SAAS,CAAC,YAAY,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC;YAErG,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAA8B,CAAC;YAC3E,MAAM,GAAG,GAAG,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,CAAC;YAClC,MAAM,IAAI,GAAG;gBACX,GAAG,CAAC;gBACJ,SAAS,EAAE;oBACT,GAAG,CAAC,CAAC,SAAS;oBACd,GAAG;oBACH,UAAU;oBACV,YAAY;oBACZ,QAAQ;iBACT;aACF,CAAC;YACF,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;QAED,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,IAAI,EAAE,CAAC;QACrD,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtE,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;QAChC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC;QACrC,UAAU,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,UAAU,CAAC,CAAC;QAC3C,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;QACjC,IAAI,UAAU,CAAC,OAAO,IAAI,UAAU,CAAC,UAAU,IAAI,UAAU,CAAC,OAAO,CAAC,MAAM,KAAK,UAAU,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;YAC9G,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;YAC9C,OAAO;QACT,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,OAAO,IAAI,UAAU,CAAC,UAAU,EAAE,CAAC;YACjD,MAAM,UAAU,GAAa,UAAU,CAAC,UAAU,CAAC;YACnD,UAAU,CAAC,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;QAChF,CAAC;QACD,OAAO;IACT,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,IAAI,YAAY,qCAA6B,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IACD,iBAAiB,EAAE,CAAC;IAEpB,YAAY,iCAAyB,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,IAAI;IAClB,IAAI,YAAY,mCAA2B,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACtD,CAAC;IAED,OAAO;QACL,iBAAiB;QACjB,WAAW;KACZ,CAAC;AACJ,CAAC;AAED,SAAS,2BAA2B,CAChC,SAAsC,EAAE,SAAsC;IAChF,MAAM,WAAW,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,gBAAgB,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;IACvG,OAAO,QAAQ,CAAC,YAAY,CAAC,cAAc,CACvC,WAAW,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;QACL,UAAU,EAAE;YACV,SAAS,EAAE,CAAC;YACZ,OAAO,EAAE,CAAC;YACV,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,EAAE;YACX,UAAU,EAAE,EAAE;YACd,KAAK,EAAE,EAAE;SACV;QACD,SAAS;KACV,CAAC,CAAC,CAAC;AAClC,CAAC;AAqCD;;;;;;;GAOG;AACH,MAAM,UAAU,0BAA0B,CACtC,IAAwB,EAAE,KAA6C;IACzE,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACtE,MAAM,IAAI,GAAG,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3D,IAAI,IAAI,EAAE,YAAY,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IACD,OAAO,KAAK,CAAC,SAAS,CAAC,YAAY,CAAC;AACtC,CAAC","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport type * as Protocol from '../../../generated/protocol.js';\nimport * as CPUProfile from '../../cpu_profile/cpu_profile.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {HandlerState} from './types.js';\n\nconst events =\n new Map>();\n\nconst profilesInProcess = new Map>();\nconst entryToNode = new Map();\n\n// The profile head, containing its metadata like its start\n// time, comes in a \"Profile\" event. The sample data comes in\n// \"ProfileChunk\" events. We match these ProfileChunks with their head\n// using process and profile ids. However, in order to integrate sample\n// data with trace data, we need the thread id that owns each profile.\n// This thread id is extracted from the head event.\n// For this reason, we have a preprocessed data structure, where events\n// are matched by profile id, which we then finish processing to export\n// events matched by thread id.\nconst preprocessedData = new Map>();\n\nlet handlerState = HandlerState.UNINITIALIZED;\n\nfunction buildProfileCalls(): void {\n for (const [processId, profiles] of preprocessedData) {\n for (const [profileId, preProcessedData] of profiles) {\n const threadId = preProcessedData.threadId;\n if (!preProcessedData.rawProfile.nodes.length || threadId === undefined) {\n continue;\n }\n const indexStack: number[] = [];\n\n const profileModel = new CPUProfile.CPUProfileDataModel.CPUProfileDataModel(preProcessedData.rawProfile);\n const profileTree = Helpers.TreeHelpers.makeEmptyTraceEntryTree();\n profileTree.maxDepth = profileModel.maxDepth;\n\n const finalizedData: ProfileData = {\n rawProfile: preProcessedData.rawProfile,\n parsedProfile: profileModel,\n profileCalls: [],\n profileTree,\n profileId,\n };\n\n const dataByThread = Platform.MapUtilities.getWithDefault(profilesInProcess, processId, () => new Map());\n profileModel.forEachFrame(openFrameCallback, closeFrameCallback);\n dataByThread.set(threadId, finalizedData);\n\n function openFrameCallback(\n depth: number, node: CPUProfile.ProfileTreeModel.ProfileNode, sampleIndex: number,\n timeStampMilliseconds: number): void {\n if (threadId === undefined) {\n return;\n }\n const ts = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(timeStampMilliseconds));\n const nodeId = node.id as Helpers.TreeHelpers.TraceEntryNodeId;\n\n const profileCall = Helpers.Trace.makeProfileCall(node, profileId, sampleIndex, ts, processId, threadId);\n finalizedData.profileCalls.push(profileCall);\n indexStack.push(finalizedData.profileCalls.length - 1);\n const traceEntryNode = Helpers.TreeHelpers.makeEmptyTraceEntryNode(profileCall, nodeId);\n entryToNode.set(profileCall, traceEntryNode);\n traceEntryNode.depth = depth;\n if (indexStack.length === 1) {\n // First call in the stack is a root call.\n finalizedData.profileTree?.roots.add(traceEntryNode);\n }\n }\n function closeFrameCallback(\n _depth: number, _node: CPUProfile.ProfileTreeModel.ProfileNode, _sampleIndex: number,\n _timeStampMillis: number, durMs: number, selfTimeMs: number): void {\n const profileCallIndex = indexStack.pop();\n const profileCall = profileCallIndex !== undefined && finalizedData.profileCalls[profileCallIndex];\n if (!profileCall) {\n return;\n }\n const {callFrame, ts, pid, tid} = profileCall;\n const traceEntryNode = entryToNode.get(profileCall);\n if (callFrame === undefined || ts === undefined || pid === undefined || profileId === undefined ||\n tid === undefined || traceEntryNode === undefined) {\n return;\n }\n const dur = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(durMs));\n const selfTime = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(selfTimeMs));\n profileCall.dur = dur;\n traceEntryNode.selfTime = selfTime;\n\n const parentIndex = indexStack.at(-1);\n const parent = parentIndex !== undefined && finalizedData.profileCalls.at(parentIndex);\n const parentNode = parent && entryToNode.get(parent);\n if (!parentNode) {\n return;\n }\n traceEntryNode.parent = parentNode;\n parentNode.children.push(traceEntryNode);\n }\n }\n }\n}\n\nexport function reset(): void {\n events.clear();\n preprocessedData.clear();\n profilesInProcess.clear();\n entryToNode.clear();\n handlerState = HandlerState.UNINITIALIZED;\n}\n\nexport function initialize(): void {\n if (handlerState !== HandlerState.UNINITIALIZED) {\n throw new Error('Samples Handler was not reset');\n }\n\n handlerState = HandlerState.INITIALIZED;\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Samples Handler is not initialized');\n }\n\n /**\n * A fake trace event created to support CDP.Profiler.Profiles in the\n * trace engine.\n */\n if (Types.TraceEvents.isSyntheticCpuProfile(event)) {\n // At the moment we are attaching to a single node target so we\n // should only get a single CPU profile. The values of the process\n // id and thread id are not really important, so we use the data\n // in the fake event. Should multi-thread CPU profiling be supported\n // we could use these fields in the event to pass thread info.\n const pid = event.pid;\n const tid = event.tid;\n // Create an arbitrary profile id.\n const profileId = '0x1' as Types.TraceEvents.ProfileID;\n const profileData = getOrCreatePreProcessedData(pid, profileId);\n profileData.rawProfile = event.args.data.cpuProfile;\n profileData.threadId = tid;\n return;\n }\n\n if (Types.TraceEvents.isTraceEventProfile(event)) {\n // Do not use event.args.data.startTime as it is in CLOCK_MONOTONIC domain,\n // but use profileEvent.ts which has been translated to Perfetto's clock\n // domain. Also convert from ms to us.\n // Note: events are collected on a different thread than what's sampled.\n // The correct process and thread ids are specified by the profile.\n const profileData = getOrCreatePreProcessedData(event.pid, event.id);\n profileData.rawProfile.startTime = event.ts;\n profileData.threadId = event.tid;\n return;\n }\n if (Types.TraceEvents.isTraceEventProfileChunk(event)) {\n const profileData = getOrCreatePreProcessedData(event.pid, event.id);\n const cdpProfile = profileData.rawProfile;\n const nodesAndSamples: Types.TraceEvents.TraceEventPartialProfile|undefined =\n event.args?.data?.cpuProfile || {samples: []};\n const samples = nodesAndSamples?.samples || [];\n const nodes: CPUProfile.CPUProfileDataModel.ExtendedProfileNode[] = [];\n for (const n of nodesAndSamples?.nodes || []) {\n const lineNumber = typeof n.callFrame.lineNumber === 'undefined' ? -1 : n.callFrame.lineNumber;\n const columnNumber = typeof n.callFrame.columnNumber === 'undefined' ? -1 : n.callFrame.columnNumber;\n\n const scriptId = String(n.callFrame.scriptId) as Protocol.Runtime.ScriptId;\n const url = n.callFrame.url || '';\n const node = {\n ...n,\n callFrame: {\n ...n.callFrame,\n url,\n lineNumber,\n columnNumber,\n scriptId,\n },\n };\n nodes.push(node);\n }\n\n const timeDeltas = event.args.data?.timeDeltas || [];\n const lines = event.args.data?.lines || Array(samples.length).fill(0);\n cdpProfile.nodes.push(...nodes);\n cdpProfile.samples?.push(...samples);\n cdpProfile.timeDeltas?.push(...timeDeltas);\n cdpProfile.lines?.push(...lines);\n if (cdpProfile.samples && cdpProfile.timeDeltas && cdpProfile.samples.length !== cdpProfile.timeDeltas.length) {\n console.error('Failed to parse CPU profile.');\n return;\n }\n if (!cdpProfile.endTime && cdpProfile.timeDeltas) {\n const timeDeltas: number[] = cdpProfile.timeDeltas;\n cdpProfile.endTime = timeDeltas.reduce((x, y) => x + y, cdpProfile.startTime);\n }\n return;\n }\n}\n\nexport async function finalize(): Promise {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Samples Handler is not initialized');\n }\n buildProfileCalls();\n\n handlerState = HandlerState.FINALIZED;\n}\n\nexport function data(): SamplesHandlerData {\n if (handlerState !== HandlerState.FINALIZED) {\n throw new Error('Samples Handler is not finalized');\n }\n\n return {\n profilesInProcess,\n entryToNode,\n };\n}\n\nfunction getOrCreatePreProcessedData(\n processId: Types.TraceEvents.ProcessID, profileId: Types.TraceEvents.ProfileID): PreprocessedData {\n const profileById = Platform.MapUtilities.getWithDefault(preprocessedData, processId, () => new Map());\n return Platform.MapUtilities.getWithDefault(\n profileById, profileId, () => ({\n rawProfile: {\n startTime: 0,\n endTime: 0,\n nodes: [],\n samples: [],\n timeDeltas: [],\n lines: [],\n },\n profileId,\n }));\n}\n\nexport interface SamplesHandlerData {\n profilesInProcess: typeof profilesInProcess;\n entryToNode: typeof entryToNode;\n}\n\nexport type ProfileData = {\n profileId: Types.TraceEvents.ProfileID,\n rawProfile: CPUProfile.CPUProfileDataModel.ExtendedProfile,\n parsedProfile: CPUProfile.CPUProfileDataModel.CPUProfileDataModel,\n /**\n * Contains the calls built from the CPU profile samples.\n * Note: This doesn't contain real trace events coming from the\n * browser, only calls synthetically typed as trace events for\n * compatibility, as such it only makes sense to use them in pure CPU\n * profiles.\n *\n * If you need the profile calls from a CPU profile obtained from a\n * web trace, use the data exported by the RendererHandler instead.\n */\n profileCalls: Types.TraceEvents.SyntheticProfileCall[],\n /**\n * Contains the call tree built from the CPU profile samples.\n * Similar to the profileCalls field, this tree does not contain nor\n * take into account trace events, as such it only makes sense to use\n * them in pure CPU profiles.\n */\n profileTree?: Helpers.TreeHelpers.TraceEntryTree,\n};\n\ntype PreprocessedData = {\n rawProfile: CPUProfile.CPUProfileDataModel.ExtendedProfile,\n profileId: Types.TraceEvents.ProfileID,\n threadId?: Types.TraceEvents.ThreadID,\n};\n\n/**\n * Returns the name of a function for a given synthetic profile call.\n * We first look to find the ProfileNode representing this call, and use its\n * function name. This is preferred (and should always exist) because if we\n * resolve sourcemaps, we will update this name. If that name is not present,\n * we fall back to the function name that was in the callframe that we got\n * when parsing the profile's trace data.\n */\nexport function getProfileCallFunctionName(\n data: SamplesHandlerData, entry: Types.TraceEvents.SyntheticProfileCall): string {\n const profile = data.profilesInProcess.get(entry.pid)?.get(entry.tid);\n const node = profile?.parsedProfile.nodeById(entry.nodeId);\n if (node?.functionName) {\n return node.functionName;\n }\n return entry.callFrame.functionName;\n}\n"]} \ No newline at end of file +{"version":3,"file":"SamplesHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/SamplesHandler.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,QAAQ,MAAM,oCAAoC,CAAC;AAE/D,OAAO,KAAK,UAAU,MAAM,kCAAkC,CAAC;AAC/D,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAI3C,MAAM,MAAM,GAAG,IAAI,GAAG,EAA+E,CAAC;AAEtG,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAmE,CAAC;AACrG,MAAM,WAAW,GAAG,IAAI,GAAG,EAA0D,CAAC;AAEtF,2DAA2D;AAC3D,6DAA6D;AAC7D,sEAAsE;AACtE,uEAAuE;AACvE,sEAAsE;AACtE,mDAAmD;AACnD,uEAAuE;AACvE,uEAAuE;AACvE,+BAA+B;AAC/B,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAyE,CAAC;AAE1G,IAAI,YAAY,qCAA6B,CAAC;AAE9C,SAAS,iBAAiB;IACxB,KAAK,MAAM,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,gBAAgB,EAAE,CAAC;QACrD,KAAK,MAAM,CAAC,SAAS,EAAE,gBAAgB,CAAC,IAAI,QAAQ,EAAE,CAAC;YACrD,MAAM,QAAQ,GAAG,gBAAgB,CAAC,QAAQ,CAAC;YAC3C,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBACxE,SAAS;YACX,CAAC;YACD,MAAM,UAAU,GAAa,EAAE,CAAC;YAEhC,MAAM,YAAY,GAAG,IAAI,UAAU,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;YACzG,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC,uBAAuB,EAAE,CAAC;YAClE,WAAW,CAAC,QAAQ,GAAG,YAAY,CAAC,QAAQ,CAAC;YAE7C,MAAM,aAAa,GAAgB;gBACjC,UAAU,EAAE,gBAAgB,CAAC,UAAU;gBACvC,aAAa,EAAE,YAAY;gBAC3B,YAAY,EAAE,EAAE;gBAChB,WAAW;gBACX,SAAS;aACV,CAAC;YAEF,MAAM,YAAY,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,iBAAiB,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;YACzG,YAAY,CAAC,YAAY,CAAC,iBAAiB,EAAE,kBAAkB,CAAC,CAAC;YACjE,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;YAE1C,SAAS,iBAAiB,CACtB,KAAa,EAAE,IAA6C,EAAE,WAAmB,EACjF,qBAA6B;gBAC/B,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;oBAC3B,OAAO;gBACT,CAAC;gBACD,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,qBAAqB,CAAC,CAAC,CAAC;gBACvG,MAAM,MAAM,GAAG,IAAI,CAAC,EAA0C,CAAC;gBAE/D,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;gBACzG,aAAa,CAAC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;gBAC7C,UAAU,CAAC,IAAI,CAAC,aAAa,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBACvD,MAAM,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,uBAAuB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;gBACxF,WAAW,CAAC,GAAG,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;gBAC7C,cAAc,CAAC,KAAK,GAAG,KAAK,CAAC;gBAC7B,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC5B,0CAA0C;oBAC1C,aAAa,CAAC,WAAW,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;gBACvD,CAAC;YACH,CAAC;YACD,SAAS,kBAAkB,CACvB,MAAc,EAAE,KAA8C,EAAE,YAAoB,EACpF,gBAAwB,EAAE,KAAa,EAAE,UAAkB;gBAC7D,MAAM,gBAAgB,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC;gBAC1C,MAAM,WAAW,GAAG,gBAAgB,KAAK,SAAS,IAAI,aAAa,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;gBACnG,IAAI,CAAC,WAAW,EAAE,CAAC;oBACjB,OAAO;gBACT,CAAC;gBACD,MAAM,EAAC,SAAS,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAC,GAAG,WAAW,CAAC;gBAC9C,MAAM,cAAc,GAAG,WAAW,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;gBACpD,IAAI,SAAS,KAAK,SAAS,IAAI,EAAE,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS,IAAI,SAAS,KAAK,SAAS;oBAC3F,GAAG,KAAK,SAAS,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;oBACtD,OAAO;gBACT,CAAC;gBACD,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;gBACxF,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC;gBAClG,WAAW,CAAC,GAAG,GAAG,GAAG,CAAC;gBACtB,cAAc,CAAC,QAAQ,GAAG,QAAQ,CAAC;gBAEnC,MAAM,WAAW,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;gBACtC,MAAM,MAAM,GAAG,WAAW,KAAK,SAAS,IAAI,aAAa,CAAC,YAAY,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC;gBACvF,MAAM,UAAU,GAAG,MAAM,IAAI,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBACrD,IAAI,CAAC,UAAU,EAAE,CAAC;oBAChB,OAAO;gBACT,CAAC;gBACD,cAAc,CAAC,MAAM,GAAG,UAAU,CAAC;gBACnC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,KAAK;IACnB,MAAM,CAAC,KAAK,EAAE,CAAC;IACf,gBAAgB,CAAC,KAAK,EAAE,CAAC;IACzB,iBAAiB,CAAC,KAAK,EAAE,CAAC;IAC1B,WAAW,CAAC,KAAK,EAAE,CAAC;IACpB,YAAY,qCAA6B,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,IAAI,YAAY,uCAA+B,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IAED,YAAY,mCAA2B,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAyB;IACnD,IAAI,YAAY,qCAA6B,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IAED;;;OAGG;IACH,IAAI,KAAK,CAAC,MAAM,CAAC,qBAAqB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9C,+DAA+D;QAC/D,kEAAkE;QAClE,gEAAgE;QAChE,oEAAoE;QACpE,8DAA8D;QAC9D,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;QACtB,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;QACtB,kCAAkC;QAClC,MAAM,SAAS,GAAG,KAA+B,CAAC;QAClD,MAAM,WAAW,GAAG,2BAA2B,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAChE,WAAW,CAAC,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;QACpD,WAAW,CAAC,QAAQ,GAAG,GAAG,CAAC;QAC3B,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;QAClC,2EAA2E;QAC3E,wEAAwE;QACxE,sCAAsC;QACtC,wEAAwE;QACxE,mEAAmE;QACnE,MAAM,WAAW,GAAG,2BAA2B,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;QACrE,WAAW,CAAC,UAAU,CAAC,SAAS,GAAG,KAAK,CAAC,EAAE,CAAC;QAC5C,WAAW,CAAC,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC;QACjC,OAAO;IACT,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;QACvC,MAAM,WAAW,GAAG,2BAA2B,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC;QACrE,MAAM,UAAU,GAAG,WAAW,CAAC,UAAU,CAAC;QAC1C,MAAM,eAAe,GAA0C,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,IAAI,EAAC,OAAO,EAAE,EAAE,EAAC,CAAC;QAC7G,MAAM,OAAO,GAAG,eAAe,EAAE,OAAO,IAAI,EAAE,CAAC;QAC/C,MAAM,KAAK,GAAyD,EAAE,CAAC;QACvE,KAAK,MAAM,CAAC,IAAI,eAAe,EAAE,KAAK,IAAI,EAAE,EAAE,CAAC;YAC7C,MAAM,UAAU,GAAG,OAAO,CAAC,CAAC,SAAS,CAAC,UAAU,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC;YAC/F,MAAM,YAAY,GAAG,OAAO,CAAC,CAAC,SAAS,CAAC,YAAY,KAAK,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC;YAErG,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,QAAQ,CAA8B,CAAC;YAC3E,MAAM,GAAG,GAAG,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,CAAC;YAClC,MAAM,IAAI,GAAG;gBACX,GAAG,CAAC;gBACJ,SAAS,EAAE;oBACT,GAAG,CAAC,CAAC,SAAS;oBACd,GAAG;oBACH,UAAU;oBACV,YAAY;oBACZ,QAAQ;iBACT;aACF,CAAC;YACF,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACnB,CAAC;QAED,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,IAAI,EAAE,CAAC;QACrD,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtE,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;QAChC,UAAU,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC;QACrC,UAAU,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,UAAU,CAAC,CAAC;QAC3C,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;QACjC,IAAI,UAAU,CAAC,OAAO,IAAI,UAAU,CAAC,UAAU,IAAI,UAAU,CAAC,OAAO,CAAC,MAAM,KAAK,UAAU,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;YAC9G,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAC;YAC9C,OAAO;QACT,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,OAAO,IAAI,UAAU,CAAC,UAAU,EAAE,CAAC;YACjD,MAAM,UAAU,GAAa,UAAU,CAAC,UAAU,CAAC;YACnD,UAAU,CAAC,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC;QAChF,CAAC;QACD,OAAO;IACT,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,IAAI,YAAY,qCAA6B,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IACD,iBAAiB,EAAE,CAAC;IAEpB,YAAY,iCAAyB,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,IAAI;IAClB,IAAI,YAAY,mCAA2B,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACtD,CAAC;IAED,OAAO;QACL,iBAAiB;QACjB,WAAW;KACZ,CAAC;AACJ,CAAC;AAED,SAAS,2BAA2B,CAChC,SAAiC,EAAE,SAAiC;IACtE,MAAM,WAAW,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,gBAAgB,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;IACvG,OAAO,QAAQ,CAAC,YAAY,CAAC,cAAc,CACvC,WAAW,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC;QACL,UAAU,EAAE;YACV,SAAS,EAAE,CAAC;YACZ,OAAO,EAAE,CAAC;YACV,KAAK,EAAE,EAAE;YACT,OAAO,EAAE,EAAE;YACX,UAAU,EAAE,EAAE;YACd,KAAK,EAAE,EAAE;SACV;QACD,SAAS;KACV,CAAC,CAAC,CAAC;AAClC,CAAC;AAqCD;;;;;;;GAOG;AACH,MAAM,UAAU,0BAA0B,CAAC,IAAwB,EAAE,KAAwC;IAC3G,MAAM,OAAO,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACtE,MAAM,IAAI,GAAG,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC3D,IAAI,IAAI,EAAE,YAAY,EAAE,CAAC;QACvB,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IACD,OAAO,KAAK,CAAC,SAAS,CAAC,YAAY,CAAC;AACtC,CAAC","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport type * as Protocol from '../../../generated/protocol.js';\nimport * as CPUProfile from '../../cpu_profile/cpu_profile.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {HandlerState} from './types.js';\n\nconst events = new Map>();\n\nconst profilesInProcess = new Map>();\nconst entryToNode = new Map();\n\n// The profile head, containing its metadata like its start\n// time, comes in a \"Profile\" event. The sample data comes in\n// \"ProfileChunk\" events. We match these ProfileChunks with their head\n// using process and profile ids. However, in order to integrate sample\n// data with trace data, we need the thread id that owns each profile.\n// This thread id is extracted from the head event.\n// For this reason, we have a preprocessed data structure, where events\n// are matched by profile id, which we then finish processing to export\n// events matched by thread id.\nconst preprocessedData = new Map>();\n\nlet handlerState = HandlerState.UNINITIALIZED;\n\nfunction buildProfileCalls(): void {\n for (const [processId, profiles] of preprocessedData) {\n for (const [profileId, preProcessedData] of profiles) {\n const threadId = preProcessedData.threadId;\n if (!preProcessedData.rawProfile.nodes.length || threadId === undefined) {\n continue;\n }\n const indexStack: number[] = [];\n\n const profileModel = new CPUProfile.CPUProfileDataModel.CPUProfileDataModel(preProcessedData.rawProfile);\n const profileTree = Helpers.TreeHelpers.makeEmptyTraceEntryTree();\n profileTree.maxDepth = profileModel.maxDepth;\n\n const finalizedData: ProfileData = {\n rawProfile: preProcessedData.rawProfile,\n parsedProfile: profileModel,\n profileCalls: [],\n profileTree,\n profileId,\n };\n\n const dataByThread = Platform.MapUtilities.getWithDefault(profilesInProcess, processId, () => new Map());\n profileModel.forEachFrame(openFrameCallback, closeFrameCallback);\n dataByThread.set(threadId, finalizedData);\n\n function openFrameCallback(\n depth: number, node: CPUProfile.ProfileTreeModel.ProfileNode, sampleIndex: number,\n timeStampMilliseconds: number): void {\n if (threadId === undefined) {\n return;\n }\n const ts = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(timeStampMilliseconds));\n const nodeId = node.id as Helpers.TreeHelpers.TraceEntryNodeId;\n\n const profileCall = Helpers.Trace.makeProfileCall(node, profileId, sampleIndex, ts, processId, threadId);\n finalizedData.profileCalls.push(profileCall);\n indexStack.push(finalizedData.profileCalls.length - 1);\n const traceEntryNode = Helpers.TreeHelpers.makeEmptyTraceEntryNode(profileCall, nodeId);\n entryToNode.set(profileCall, traceEntryNode);\n traceEntryNode.depth = depth;\n if (indexStack.length === 1) {\n // First call in the stack is a root call.\n finalizedData.profileTree?.roots.add(traceEntryNode);\n }\n }\n function closeFrameCallback(\n _depth: number, _node: CPUProfile.ProfileTreeModel.ProfileNode, _sampleIndex: number,\n _timeStampMillis: number, durMs: number, selfTimeMs: number): void {\n const profileCallIndex = indexStack.pop();\n const profileCall = profileCallIndex !== undefined && finalizedData.profileCalls[profileCallIndex];\n if (!profileCall) {\n return;\n }\n const {callFrame, ts, pid, tid} = profileCall;\n const traceEntryNode = entryToNode.get(profileCall);\n if (callFrame === undefined || ts === undefined || pid === undefined || profileId === undefined ||\n tid === undefined || traceEntryNode === undefined) {\n return;\n }\n const dur = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(durMs));\n const selfTime = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(selfTimeMs));\n profileCall.dur = dur;\n traceEntryNode.selfTime = selfTime;\n\n const parentIndex = indexStack.at(-1);\n const parent = parentIndex !== undefined && finalizedData.profileCalls.at(parentIndex);\n const parentNode = parent && entryToNode.get(parent);\n if (!parentNode) {\n return;\n }\n traceEntryNode.parent = parentNode;\n parentNode.children.push(traceEntryNode);\n }\n }\n }\n}\n\nexport function reset(): void {\n events.clear();\n preprocessedData.clear();\n profilesInProcess.clear();\n entryToNode.clear();\n handlerState = HandlerState.UNINITIALIZED;\n}\n\nexport function initialize(): void {\n if (handlerState !== HandlerState.UNINITIALIZED) {\n throw new Error('Samples Handler was not reset');\n }\n\n handlerState = HandlerState.INITIALIZED;\n}\n\nexport function handleEvent(event: Types.Events.Event): void {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Samples Handler is not initialized');\n }\n\n /**\n * A fake trace event created to support CDP.Profiler.Profiles in the\n * trace engine.\n */\n if (Types.Events.isSyntheticCpuProfile(event)) {\n // At the moment we are attaching to a single node target so we\n // should only get a single CPU profile. The values of the process\n // id and thread id are not really important, so we use the data\n // in the fake event. Should multi-thread CPU profiling be supported\n // we could use these fields in the event to pass thread info.\n const pid = event.pid;\n const tid = event.tid;\n // Create an arbitrary profile id.\n const profileId = '0x1' as Types.Events.ProfileID;\n const profileData = getOrCreatePreProcessedData(pid, profileId);\n profileData.rawProfile = event.args.data.cpuProfile;\n profileData.threadId = tid;\n return;\n }\n\n if (Types.Events.isProfile(event)) {\n // Do not use event.args.data.startTime as it is in CLOCK_MONOTONIC domain,\n // but use profileEvent.ts which has been translated to Perfetto's clock\n // domain. Also convert from ms to us.\n // Note: events are collected on a different thread than what's sampled.\n // The correct process and thread ids are specified by the profile.\n const profileData = getOrCreatePreProcessedData(event.pid, event.id);\n profileData.rawProfile.startTime = event.ts;\n profileData.threadId = event.tid;\n return;\n }\n if (Types.Events.isProfileChunk(event)) {\n const profileData = getOrCreatePreProcessedData(event.pid, event.id);\n const cdpProfile = profileData.rawProfile;\n const nodesAndSamples: Types.Events.PartialProfile|undefined = event.args?.data?.cpuProfile || {samples: []};\n const samples = nodesAndSamples?.samples || [];\n const nodes: CPUProfile.CPUProfileDataModel.ExtendedProfileNode[] = [];\n for (const n of nodesAndSamples?.nodes || []) {\n const lineNumber = typeof n.callFrame.lineNumber === 'undefined' ? -1 : n.callFrame.lineNumber;\n const columnNumber = typeof n.callFrame.columnNumber === 'undefined' ? -1 : n.callFrame.columnNumber;\n\n const scriptId = String(n.callFrame.scriptId) as Protocol.Runtime.ScriptId;\n const url = n.callFrame.url || '';\n const node = {\n ...n,\n callFrame: {\n ...n.callFrame,\n url,\n lineNumber,\n columnNumber,\n scriptId,\n },\n };\n nodes.push(node);\n }\n\n const timeDeltas = event.args.data?.timeDeltas || [];\n const lines = event.args.data?.lines || Array(samples.length).fill(0);\n cdpProfile.nodes.push(...nodes);\n cdpProfile.samples?.push(...samples);\n cdpProfile.timeDeltas?.push(...timeDeltas);\n cdpProfile.lines?.push(...lines);\n if (cdpProfile.samples && cdpProfile.timeDeltas && cdpProfile.samples.length !== cdpProfile.timeDeltas.length) {\n console.error('Failed to parse CPU profile.');\n return;\n }\n if (!cdpProfile.endTime && cdpProfile.timeDeltas) {\n const timeDeltas: number[] = cdpProfile.timeDeltas;\n cdpProfile.endTime = timeDeltas.reduce((x, y) => x + y, cdpProfile.startTime);\n }\n return;\n }\n}\n\nexport async function finalize(): Promise {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Samples Handler is not initialized');\n }\n buildProfileCalls();\n\n handlerState = HandlerState.FINALIZED;\n}\n\nexport function data(): SamplesHandlerData {\n if (handlerState !== HandlerState.FINALIZED) {\n throw new Error('Samples Handler is not finalized');\n }\n\n return {\n profilesInProcess,\n entryToNode,\n };\n}\n\nfunction getOrCreatePreProcessedData(\n processId: Types.Events.ProcessID, profileId: Types.Events.ProfileID): PreprocessedData {\n const profileById = Platform.MapUtilities.getWithDefault(preprocessedData, processId, () => new Map());\n return Platform.MapUtilities.getWithDefault(\n profileById, profileId, () => ({\n rawProfile: {\n startTime: 0,\n endTime: 0,\n nodes: [],\n samples: [],\n timeDeltas: [],\n lines: [],\n },\n profileId,\n }));\n}\n\nexport interface SamplesHandlerData {\n profilesInProcess: typeof profilesInProcess;\n entryToNode: typeof entryToNode;\n}\n\nexport type ProfileData = {\n profileId: Types.Events.ProfileID,\n rawProfile: CPUProfile.CPUProfileDataModel.ExtendedProfile,\n parsedProfile: CPUProfile.CPUProfileDataModel.CPUProfileDataModel,\n /**\n * Contains the calls built from the CPU profile samples.\n * Note: This doesn't contain real trace events coming from the\n * browser, only calls synthetically typed as trace events for\n * compatibility, as such it only makes sense to use them in pure CPU\n * profiles.\n *\n * If you need the profile calls from a CPU profile obtained from a\n * web trace, use the data exported by the RendererHandler instead.\n */\n profileCalls: Types.Events.SyntheticProfileCall[],\n /**\n * Contains the call tree built from the CPU profile samples.\n * Similar to the profileCalls field, this tree does not contain nor\n * take into account trace events, as such it only makes sense to use\n * them in pure CPU profiles.\n */\n profileTree?: Helpers.TreeHelpers.TraceEntryTree,\n};\n\ntype PreprocessedData = {\n rawProfile: CPUProfile.CPUProfileDataModel.ExtendedProfile,\n profileId: Types.Events.ProfileID,\n threadId?: Types.Events.ThreadID,\n};\n\n/**\n * Returns the name of a function for a given synthetic profile call.\n * We first look to find the ProfileNode representing this call, and use its\n * function name. This is preferred (and should always exist) because if we\n * resolve sourcemaps, we will update this name. If that name is not present,\n * we fall back to the function name that was in the callframe that we got\n * when parsing the profile's trace data.\n */\nexport function getProfileCallFunctionName(data: SamplesHandlerData, entry: Types.Events.SyntheticProfileCall): string {\n const profile = data.profilesInProcess.get(entry.pid)?.get(entry.tid);\n const node = profile?.parsedProfile.nodeById(entry.nodeId);\n if (node?.functionName) {\n return node.functionName;\n }\n return entry.callFrame.functionName;\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/SamplesHandler.test.js b/public/models/trace/handlers/SamplesHandler.test.js index 9ee196e5d..c5b5fa2d2 100644 --- a/public/models/trace/handlers/SamplesHandler.test.js +++ b/public/models/trace/handlers/SamplesHandler.test.js @@ -4,30 +4,30 @@ import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; import { getAllNodes, getMainThread } from '../../../testing/TraceHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; -import * as TraceModel from '../trace.js'; +import * as Trace from '../trace.js'; async function handleEventsFromTraceFile(context, name) { const traceEvents = await TraceLoader.rawEvents(context, name); - TraceModel.Handlers.ModelHandlers.Meta.reset(); - TraceModel.Handlers.ModelHandlers.Samples.reset(); - TraceModel.Handlers.ModelHandlers.Meta.initialize(); - TraceModel.Handlers.ModelHandlers.Samples.initialize(); + Trace.Handlers.ModelHandlers.Meta.reset(); + Trace.Handlers.ModelHandlers.Samples.reset(); + Trace.Handlers.ModelHandlers.Meta.initialize(); + Trace.Handlers.ModelHandlers.Samples.initialize(); for (const event of traceEvents) { - TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event); - TraceModel.Handlers.ModelHandlers.Samples.handleEvent(event); + Trace.Handlers.ModelHandlers.Meta.handleEvent(event); + Trace.Handlers.ModelHandlers.Samples.handleEvent(event); } - await TraceModel.Handlers.ModelHandlers.Meta.finalize(); - await TraceModel.Handlers.ModelHandlers.Samples.finalize(); - return TraceModel.Handlers.ModelHandlers.Samples.data(); + await Trace.Handlers.ModelHandlers.Meta.finalize(); + await Trace.Handlers.ModelHandlers.Samples.finalize(); + return Trace.Handlers.ModelHandlers.Samples.data(); } describeWithEnvironment('SamplesHandler', function () { it('finds all the profiles in a real world recording', async () => { const data = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz'); // The same thread id is shared across profiles in the profiled // processes. - const threadId = TraceModel.Types.TraceEvents.ThreadID(1); - const firstProcessId = TraceModel.Types.TraceEvents.ProcessID(2236123); - const secondProcessId = TraceModel.Types.TraceEvents.ProcessID(2154214); - const thirdProcessId = TraceModel.Types.TraceEvents.ProcessID(2236084); + const threadId = Trace.Types.Events.ThreadID(1); + const firstProcessId = Trace.Types.Events.ProcessID(2236123); + const secondProcessId = Trace.Types.Events.ProcessID(2154214); + const thirdProcessId = Trace.Types.Events.ProcessID(2236084); assert.strictEqual(data.profilesInProcess.size, 3); const profilesFirstProcess = data.profilesInProcess.get(firstProcessId); assert.strictEqual(profilesFirstProcess?.size, 1); @@ -40,29 +40,29 @@ describeWithEnvironment('SamplesHandler', function () { assert.exists(profilesThirdProcess?.get(threadId)); }); describe('profile calls building', () => { - const pid = TraceModel.Types.TraceEvents.ProcessID(0); - const id = TraceModel.Types.TraceEvents.ProfileID('0'); - const tid = TraceModel.Types.TraceEvents.ThreadID(1); + const pid = Trace.Types.Events.ProcessID(0); + const id = Trace.Types.Events.ProfileID('0'); + const tid = Trace.Types.Events.ThreadID(1); function makeProfileChunkEvent(nodes, samples, timeDeltas, ts) { return { cat: '', name: 'ProfileChunk', - ph: "P" /* TraceModel.Types.TraceEvents.Phase.SAMPLE */, + ph: "P" /* Trace.Types.Events.Phase.SAMPLE */, pid, - tid: TraceModel.Types.TraceEvents.ThreadID(0), - ts: TraceModel.Types.Timing.MicroSeconds(ts), + tid: Trace.Types.Events.ThreadID(0), + ts: Trace.Types.Timing.MicroSeconds(ts), id, args: { data: { cpuProfile: { - samples: samples.map(TraceModel.Types.TraceEvents.CallFrameID), + samples: samples.map(Trace.Types.Events.CallFrameID), nodes: nodes.map(node => ({ ...node, callFrame: { functionName: '', scriptId: 0, columnNumber: 0, lineNumber: 0, url: '' }, - id: TraceModel.Types.TraceEvents.CallFrameID(node.id), + id: Trace.Types.Events.CallFrameID(node.id), })), }, - timeDeltas: timeDeltas.map(TraceModel.Types.Timing.MicroSeconds), + timeDeltas: timeDeltas.map(Trace.Types.Timing.MicroSeconds), }, }, }; @@ -77,12 +77,12 @@ describeWithEnvironment('SamplesHandler', function () { const mockProfileEvent = { name: 'Profile', id, - args: { data: { startTime: TraceModel.Types.Timing.MicroSeconds(0) } }, + args: { data: { startTime: Trace.Types.Timing.MicroSeconds(0) } }, cat: '', pid, tid, - ts: TraceModel.Types.Timing.MicroSeconds(0), - ph: "P" /* TraceModel.Types.TraceEvents.Phase.SAMPLE */, + ts: Trace.Types.Timing.MicroSeconds(0), + ph: "P" /* Trace.Types.Events.Phase.SAMPLE */, }; /** * +------------> (sample at time) @@ -109,13 +109,13 @@ describeWithEnvironment('SamplesHandler', function () { makeProfileChunkEvent([{ id: D, children: [] }], [], [], 0), makeProfileChunkEvent([{ id: E, children: [] }], [], [], 0), ]; - TraceModel.Handlers.ModelHandlers.Samples.reset(); - TraceModel.Handlers.ModelHandlers.Samples.initialize(); + Trace.Handlers.ModelHandlers.Samples.reset(); + Trace.Handlers.ModelHandlers.Samples.initialize(); for (const event of [mockProfileEvent, ...mockChunks]) { - TraceModel.Handlers.ModelHandlers.Samples.handleEvent(event); + Trace.Handlers.ModelHandlers.Samples.handleEvent(event); } - await TraceModel.Handlers.ModelHandlers.Samples.finalize(); - const data = TraceModel.Handlers.ModelHandlers.Samples.data(); + await Trace.Handlers.ModelHandlers.Samples.finalize(); + const data = Trace.Handlers.ModelHandlers.Samples.data(); const calls = data.profilesInProcess.get(pid)?.get(tid)?.profileCalls.map(call => { const selfTime = data.entryToNode.get(call)?.selfTime; return { ...call, selfTime }; @@ -149,8 +149,8 @@ describeWithEnvironment('SamplesHandler', function () { }); it('can build profile calls from a CPU profile coming from a real world trace', async () => { const data = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz'); - const threadId = TraceModel.Types.TraceEvents.ThreadID(1); - const firstProcessId = TraceModel.Types.TraceEvents.ProcessID(2236123); + const threadId = Trace.Types.Events.ThreadID(1); + const firstProcessId = Trace.Types.Events.ProcessID(2236123); const profilesFirstProcess = data.profilesInProcess.get(firstProcessId); const calls = profilesFirstProcess?.get(threadId)?.profileCalls.slice(0, 5).map(call => { const selfTime = data.entryToNode.get(call)?.selfTime; @@ -226,14 +226,13 @@ describeWithEnvironment('SamplesHandler', function () { describe('getProfileCallFunctionName', () => { // Find an event from the trace that represents some work. The use of // this specific call frame event is not for any real reason. - function getProfileEventAndNode(traceData) { - const mainThread = getMainThread(traceData.Renderer); + function getProfileEventAndNode(parsedTrace) { + const mainThread = getMainThread(parsedTrace.Renderer); let foundNode = null; let foundEntry = null; for (const entry of mainThread.entries) { - if (TraceModel.Types.TraceEvents.isProfileCall(entry) && - entry.callFrame.functionName === 'performConcurrentWorkOnRoot') { - const profile = traceData.Samples.profilesInProcess.get(entry.pid)?.get(entry.tid); + if (Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'performConcurrentWorkOnRoot') { + const profile = parsedTrace.Samples.profilesInProcess.get(entry.pid)?.get(entry.tid); const node = profile?.parsedProfile.nodeById(entry.nodeId); if (node) { foundNode = node; @@ -254,26 +253,26 @@ describeWithEnvironment('SamplesHandler', function () { }; } it('falls back to the call frame name if the ProfileNode name is empty', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'react-hello-world.json.gz'); - const { entry, profileNode } = getProfileEventAndNode(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'react-hello-world.json.gz'); + const { entry, profileNode } = getProfileEventAndNode(parsedTrace); // Store and then reset this: we are doing this to test the fallback to // the entry callFrame.functionName property. After the assertion we // reset this to avoid impacting other tests. const originalProfileNodeName = profileNode.functionName; profileNode.setFunctionName(''); - assert.strictEqual(TraceModel.Handlers.ModelHandlers.Samples.getProfileCallFunctionName(traceData.Samples, entry), 'performConcurrentWorkOnRoot'); + assert.strictEqual(Trace.Handlers.ModelHandlers.Samples.getProfileCallFunctionName(parsedTrace.Samples, entry), 'performConcurrentWorkOnRoot'); // St profileNode.setFunctionName(originalProfileNodeName); }); it('uses the profile name if it has been set', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'react-hello-world.json.gz'); - const { entry, profileNode } = getProfileEventAndNode(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'react-hello-world.json.gz'); + const { entry, profileNode } = getProfileEventAndNode(parsedTrace); // Store and then reset this: we are doing this to test the fallback to // the entry callFrame.functionName property. After the assertion we // reset this to avoid impacting other tests. const originalProfileNodeName = profileNode.functionName; profileNode.setFunctionName('testing-profile-name'); - assert.strictEqual(TraceModel.Handlers.ModelHandlers.Samples.getProfileCallFunctionName(traceData.Samples, entry), 'testing-profile-name'); + assert.strictEqual(Trace.Handlers.ModelHandlers.Samples.getProfileCallFunctionName(parsedTrace.Samples, entry), 'testing-profile-name'); profileNode.setFunctionName(originalProfileNodeName); }); }); diff --git a/public/models/trace/handlers/SamplesHandler.test.js.map b/public/models/trace/handlers/SamplesHandler.test.js.map index 1cc66f966..d635ba7e0 100644 --- a/public/models/trace/handlers/SamplesHandler.test.js.map +++ b/public/models/trace/handlers/SamplesHandler.test.js.map @@ -1 +1 @@ -{"version":3,"file":"SamplesHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/SamplesHandler.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAG7B,OAAO,EAAC,uBAAuB,EAAC,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EAAC,WAAW,EAAE,aAAa,EAAC,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAC,WAAW,EAAC,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,UAAU,MAAM,aAAa,CAAC;AAE1C,KAAK,UAAU,yBAAyB,CAAC,OAAuC,EAAE,IAAY;IAE5F,MAAM,WAAW,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;IAC/D,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IAC/C,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IAElD,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;IACpD,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;IAEvD,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;QAChC,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1D,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;IACxD,MAAM,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;IAE3D,OAAO,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;AAC1D,CAAC;AAED,uBAAuB,CAAC,gBAAgB,EAAE;IACxC,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QAChE,MAAM,IAAI,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,2CAA2C,CAAC,CAAC;QAChG,+DAA+D;QAC/D,aAAa;QACb,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC1D,MAAM,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACvE,MAAM,eAAe,GAAG,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACxE,MAAM,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAEvE,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QAEnD,MAAM,oBAAoB,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QACxE,MAAM,CAAC,WAAW,CAAC,oBAAoB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAClD,MAAM,CAAC,MAAM,CAAC,oBAAoB,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;QAEnD,MAAM,qBAAqB,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAC1E,MAAM,CAAC,WAAW,CAAC,qBAAqB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACnD,MAAM,CAAC,MAAM,CAAC,qBAAqB,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;QAEpD,MAAM,oBAAoB,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QACxE,MAAM,CAAC,WAAW,CAAC,oBAAoB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAClD,MAAM,CAAC,MAAM,CAAC,oBAAoB,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IACH,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;QACtC,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;QACtD,MAAM,EAAE,GAAG,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACvD,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;QAErD,SAAS,qBAAqB,CAC1B,KAOG,EACH,OAAiB,EACjB,UAAoB,EACpB,EAAU;YAEZ,OAAO;gBACL,GAAG,EAAE,EAAE;gBACP,IAAI,EAAE,cAAc;gBACpB,EAAE,qDAA2C;gBAC7C,GAAG;gBACH,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAC7C,EAAE,EAAE,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC;gBAC5C,EAAE;gBACF,IAAI,EAAE;oBACJ,IAAI,EAAE;wBACJ,UAAU,EAAE;4BACV,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,WAAW,CAAC;4BAC9D,KAAK,EAAE,KAAK,CAAC,GAAG,CACZ,IAAI,CAAC,EAAE,CAAC,CAAC;gCACP,GAAG,IAAI;gCACP,SAAS,EAAE,EAAC,YAAY,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAC;gCACnF,EAAE,EAAE,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;6BACtD,CAAC,CACD;yBACN;wBACD,UAAU,EAAE,UAAU,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC;qBACjE;iBACF;aACF,CAAC;QACJ,CAAC;QACD,EAAE,CAAC,gEAAgE,EAAE,KAAK,IAAI,EAAE;YAC9E,MAAM,CAAC,GAAG,CAAC,CAAC;YACZ,MAAM,CAAC,GAAG,CAAC,CAAC;YACZ,MAAM,CAAC,GAAG,CAAC,CAAC;YACZ,MAAM,CAAC,GAAG,CAAC,CAAC;YACZ,MAAM,CAAC,GAAG,CAAC,CAAC;YACZ,MAAM,IAAI,GAAG,CAAC,CAAC;YACf,MAAM,gBAAgB,GAAmD;gBACvE,IAAI,EAAE,SAAS;gBACf,EAAE;gBACF,IAAI,EAAE,EAAC,IAAI,EAAE,EAAC,SAAS,EAAE,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,EAAC,EAAC;gBAClE,GAAG,EAAE,EAAE;gBACP,GAAG;gBACH,GAAG;gBACH,EAAE,EAAE,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;gBAC3C,EAAE,qDAA2C;aAC9C,CAAC;YACF;;;;;;;eAOG;YACH,MAAM,cAAc,GAAG;gBACrB,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE;aACjF,CAAC;YAEF,MAAM,WAAW,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1F;;;;;;eAMG;YACH,MAAM,UAAU,GAAG;gBACjB,qBAAqB,CAAC,CAAC,EAAC,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;gBAChE,qBAAqB,CACjB,CAAC,EAAC,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAC,EAAE,EAAC,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAC,EAAE,EAAC,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAC,CAAC,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC,CAAC;gBAC/G,qBAAqB,CAAC,CAAC,EAAC,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;gBACzD,qBAAqB,CAAC,CAAC,EAAC,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;aAC1D,CAAC;YACF,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;YAElD,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;YAEvD,KAAK,MAAM,KAAK,IAAI,CAAC,gBAAgB,EAAE,GAAG,UAAU,CAAC,EAAE,CAAC;gBACtD,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YAC/D,CAAC;YACD,MAAM,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;YAC3D,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;YAC9D,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;gBAC/E,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC;gBACtD,OAAO,EAAC,GAAG,IAAI,EAAE,QAAQ,EAAC,CAAC;YAC7B,CAAC,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,EAAE,WAAW,CAAC;YACpE,MAAM,cAAc,GAAG;gBACrB,EAAC,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAC;gBACxD,EAAC,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAC;gBACnD,EAAC,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAC;gBACnD,EAAC,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAC;gBACpD,EAAC,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAC;aACxD,CAAC;YACF,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC3B,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;gBACjB,iEAAiE;gBACjE,OAAO;YACT,CAAC;YACD,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC1C,MAAM,aAAa,GAAG,KAAK,EAAE,GAAG,CAC5B,CAAC,CAAC,EAAE;gBACF,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC;gBACzD,MAAM,QAAQ,GAAG,IAAI,EAAE,QAAQ,IAAI,EAAE,CAAC;gBACtC,OAAO,CAAC;oBACN,EAAE,EAAE,CAAC,CAAC,MAAM;oBACZ,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;oBAC3B,EAAE,EAAE,CAAC,CAAC,EAAE;oBACR,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC;oBACrC,QAAQ,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE;iBACrD,CAAC,CAAC;YACL,CAAC,CACJ,CAAC;YAEF,MAAM,CAAC,SAAS,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,2EAA2E,EAAE,KAAK,IAAI,EAAE;YACzF,MAAM,IAAI,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,2CAA2C,CAAC,CAAC;YAEhG,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC1D,MAAM,cAAc,GAAG,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACvE,MAAM,oBAAoB,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;YACxE,MAAM,KAAK,GAAG,oBAAoB,EAAE,GAAG,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;gBACrF,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC;gBACtD,OAAO,EAAC,GAAG,IAAI,EAAE,QAAQ,EAAC,CAAC;YAC7B,CAAC,CAAC,CAAC;YACH,MAAM,IAAI,GAAG,oBAAoB,EAAE,GAAG,CAAC,QAAQ,CAAC,EAAE,WAAW,CAAC;YAC9D,MAAM,cAAc,GAAG;gBACrB,EAAC,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAC;gBAChE,EAAC,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAC;gBAC/D,EAAC,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAC;gBACjE,EAAC,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAC;gBACpE,EAAC,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,EAAE,EAAC;aACjE,CAAC;YACF,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC3B,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC;gBACjB,iEAAiE;gBACjE,OAAO;YACT,CAAC;YACD,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC1C,MAAM,aAAa,GAAG,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE;gBACnC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC;gBACzD,MAAM,QAAQ,GAAG,IAAI,EAAE,QAAQ,IAAI,EAAE,CAAC;gBACtC,OAAO;oBACL,EAAE,EAAE,CAAC,CAAC,MAAM;oBACZ,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;oBAC3B,EAAE,EAAE,CAAC,CAAC,EAAE;oBACR,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,CAAC;oBACrC,QAAQ,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE;iBACrD,CAAC;YACJ,CAAC,CAAC,CAAC;YACH,MAAM,CAAC,SAAS,CAAC,aAAa,EAAE,cAAc,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;QACpC,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;YACzD,MAAM,IAAI,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,+BAA+B,CAAC,CAAC;YACpF,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YACnD,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;YACjE,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YACxC,MAAM,cAAc,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAA8D,CAAC;YAClH,MAAM,UAAU,GAAG,cAAc,CAAC,UAAU,CAAC;YAC7C,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;YAC/G,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YACjD,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;YACvD,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;YACrD,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;YACtD,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;YAC9E,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC3E,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;QACnC,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;YAChE,MAAM,IAAI,GAAG,MAAM,yBAAyB,CAAC,IAAI,EAAE,+BAA+B,CAAC,CAAC;YACpF,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YACnD,MAAM,WAAW,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;YACjE,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YACxC,MAAM,cAAc,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,KAA8D,CAAC;YAClH,MAAM,aAAa,GAAG,cAAc,CAAC,aAAa,CAAC;YACnD,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;YAEvD,kHAAkH;YAClH,MAAM,uBAAuB,GAAG,aAAa,CAAC,KAAK,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;YACnG,MAAM,CAAC,QAAQ,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC;YAC7C,MAAM,yBAAyB,GAAG,aAAa,CAAC,KAAK,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,YAAY,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;YACvG,MAAM,CAAC,QAAQ,CAAC,yBAAyB,EAAE,EAAE,CAAC,CAAC;YAC/C,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;YACjD,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;YACrD,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;YAClE,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,cAAc,EAAE,iBAAiB,CAAC,CAAC;YACpE,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAC/C,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;QAC1C,qEAAqE;QACrE,6DAA6D;QAC7D,SAAS,sBAAsB,CAAC,SAAmD;YAIjF,MAAM,UAAU,GAAG,aAAa,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YACrD,IAAI,SAAS,GAAiD,IAAI,CAAC;YACnE,IAAI,UAAU,GAA2D,IAAI,CAAC;YAE9E,KAAK,MAAM,KAAK,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;gBACvC,IAAI,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,CAAC;oBACjD,KAAK,CAAC,SAAS,CAAC,YAAY,KAAK,6BAA6B,EAAE,CAAC;oBACnE,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;oBACnF,MAAM,IAAI,GAAG,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;oBAC3D,IAAI,IAAI,EAAE,CAAC;wBACT,SAAS,GAAG,IAAI,CAAC;oBACnB,CAAC;oBACD,UAAU,GAAG,KAAK,CAAC;oBACnB,MAAM;gBACR,CAAC;YACH,CAAC;YACD,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;YACtD,CAAC;YACD,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;YACpD,CAAC;YAED,OAAO;gBACL,KAAK,EAAE,UAAU;gBACjB,WAAW,EAAE,SAAS;aACvB,CAAC;QACJ,CAAC;QAED,EAAE,CAAC,oEAAoE,EAAE,KAAK;YAC5E,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,2BAA2B,CAAC,CAAC;YACrF,MAAM,EAAC,KAAK,EAAE,WAAW,EAAC,GAAG,sBAAsB,CAAC,SAAS,CAAC,CAAC;YAC/D,uEAAuE;YACvE,oEAAoE;YACpE,6CAA6C;YAC7C,MAAM,uBAAuB,GAAG,WAAW,CAAC,YAAY,CAAC;YACzD,WAAW,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;YAChC,MAAM,CAAC,WAAW,CACd,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,0BAA0B,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,EAC9F,6BAA6B,CAAC,CAAC;YACnC,KAAK;YACL,WAAW,CAAC,eAAe,CAAC,uBAAuB,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0CAA0C,EAAE,KAAK;YAClD,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,2BAA2B,CAAC,CAAC;YACrF,MAAM,EAAC,KAAK,EAAE,WAAW,EAAC,GAAG,sBAAsB,CAAC,SAAS,CAAC,CAAC;YAC/D,uEAAuE;YACvE,oEAAoE;YACpE,6CAA6C;YAC7C,MAAM,uBAAuB,GAAG,WAAW,CAAC,YAAY,CAAC;YACzD,WAAW,CAAC,eAAe,CAAC,sBAAsB,CAAC,CAAC;YACpD,MAAM,CAAC,WAAW,CACd,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,0BAA0B,CAAC,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,EAC9F,sBAAsB,CAAC,CAAC;YAC5B,WAAW,CAAC,eAAe,CAAC,uBAAuB,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as CPUProfile from '../../../models/cpu_profile/cpu_profile.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {getAllNodes, getMainThread} from '../../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as TraceModel from '../trace.js';\n\nasync function handleEventsFromTraceFile(context: Mocha.Context|Mocha.Suite|null, name: string):\n Promise {\n const traceEvents = await TraceLoader.rawEvents(context, name);\n TraceModel.Handlers.ModelHandlers.Meta.reset();\n TraceModel.Handlers.ModelHandlers.Samples.reset();\n\n TraceModel.Handlers.ModelHandlers.Meta.initialize();\n TraceModel.Handlers.ModelHandlers.Samples.initialize();\n\n for (const event of traceEvents) {\n TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event);\n TraceModel.Handlers.ModelHandlers.Samples.handleEvent(event);\n }\n\n await TraceModel.Handlers.ModelHandlers.Meta.finalize();\n await TraceModel.Handlers.ModelHandlers.Samples.finalize();\n\n return TraceModel.Handlers.ModelHandlers.Samples.data();\n}\n\ndescribeWithEnvironment('SamplesHandler', function() {\n it('finds all the profiles in a real world recording', async () => {\n const data = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n // The same thread id is shared across profiles in the profiled\n // processes.\n const threadId = TraceModel.Types.TraceEvents.ThreadID(1);\n const firstProcessId = TraceModel.Types.TraceEvents.ProcessID(2236123);\n const secondProcessId = TraceModel.Types.TraceEvents.ProcessID(2154214);\n const thirdProcessId = TraceModel.Types.TraceEvents.ProcessID(2236084);\n\n assert.strictEqual(data.profilesInProcess.size, 3);\n\n const profilesFirstProcess = data.profilesInProcess.get(firstProcessId);\n assert.strictEqual(profilesFirstProcess?.size, 1);\n assert.exists(profilesFirstProcess?.get(threadId));\n\n const profilesSecondProcess = data.profilesInProcess.get(secondProcessId);\n assert.strictEqual(profilesSecondProcess?.size, 1);\n assert.exists(profilesSecondProcess?.get(threadId));\n\n const profilesThirdProcess = data.profilesInProcess.get(thirdProcessId);\n assert.strictEqual(profilesThirdProcess?.size, 1);\n assert.exists(profilesThirdProcess?.get(threadId));\n });\n describe('profile calls building', () => {\n const pid = TraceModel.Types.TraceEvents.ProcessID(0);\n const id = TraceModel.Types.TraceEvents.ProfileID('0');\n const tid = TraceModel.Types.TraceEvents.ThreadID(1);\n\n function makeProfileChunkEvent(\n nodes: {\n id: number,\n children: number[],\n codeType?: string,\n url?: string,\n functionName?: string,\n scriptId?: number,\n }[],\n samples: number[],\n timeDeltas: number[],\n ts: number,\n ): TraceModel.Types.TraceEvents.TraceEventProfileChunk {\n return {\n cat: '',\n name: 'ProfileChunk',\n ph: TraceModel.Types.TraceEvents.Phase.SAMPLE,\n pid,\n tid: TraceModel.Types.TraceEvents.ThreadID(0),\n ts: TraceModel.Types.Timing.MicroSeconds(ts),\n id,\n args: {\n data: {\n cpuProfile: {\n samples: samples.map(TraceModel.Types.TraceEvents.CallFrameID),\n nodes: nodes.map(\n node => ({\n ...node,\n callFrame: {functionName: '', scriptId: 0, columnNumber: 0, lineNumber: 0, url: ''},\n id: TraceModel.Types.TraceEvents.CallFrameID(node.id),\n }),\n ),\n },\n timeDeltas: timeDeltas.map(TraceModel.Types.Timing.MicroSeconds),\n },\n },\n };\n }\n it('can build profile calls from a CPU profile coming from tracing', async () => {\n const A = 0;\n const B = 1;\n const C = 2;\n const D = 3;\n const E = 4;\n const root = 9;\n const mockProfileEvent: TraceModel.Types.TraceEvents.TraceEventProfile = {\n name: 'Profile',\n id,\n args: {data: {startTime: TraceModel.Types.Timing.MicroSeconds(0)}},\n cat: '',\n pid,\n tid,\n ts: TraceModel.Types.Timing.MicroSeconds(0),\n ph: TraceModel.Types.TraceEvents.Phase.SAMPLE,\n };\n /**\n * +------------> (sample at time)\n * |A|A|A|A|A|A|A|A|A|A|A|A|A|A|A|A|A| |E|E|E|E|E|E|\n * | |B|B|B|B|B|B| |D|D|D|D|D|D| | | | | | | | | | |\n * | | |C|C|C|C| | | | | | | | | | | | | | | | | | |\n * |\n * V (stack trace depth)\n */\n const mockTimeDeltas = [\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 21, 22, 23,\n ];\n\n const mockSamples = [A, B, C, C, C, C, B, A, D, D, D, D, D, D, A, A, A, E, E, E, E, E, E];\n /*\n * A E\n * / \\\n * B D\n * |\n * C\n */\n const mockChunks = [\n makeProfileChunkEvent([{id: root, children: [A, E]}], [], [], 0),\n makeProfileChunkEvent(\n [{id: A, children: [B, D]}, {id: B, children: [C]}, {id: C, children: []}], mockSamples, mockTimeDeltas, 0),\n makeProfileChunkEvent([{id: D, children: []}], [], [], 0),\n makeProfileChunkEvent([{id: E, children: []}], [], [], 0),\n ];\n TraceModel.Handlers.ModelHandlers.Samples.reset();\n\n TraceModel.Handlers.ModelHandlers.Samples.initialize();\n\n for (const event of [mockProfileEvent, ...mockChunks]) {\n TraceModel.Handlers.ModelHandlers.Samples.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.Samples.finalize();\n const data = TraceModel.Handlers.ModelHandlers.Samples.data();\n const calls = data.profilesInProcess.get(pid)?.get(tid)?.profileCalls.map(call => {\n const selfTime = data.entryToNode.get(call)?.selfTime;\n return {...call, selfTime};\n });\n const tree = data.profilesInProcess.get(pid)?.get(tid)?.profileTree;\n const expectedResult = [\n {id: A, ts: 0, dur: 154, selfTime: 58, children: [B, D]},\n {id: B, ts: 1, dur: 27, selfTime: 9, children: [C]},\n {id: C, ts: 3, dur: 18, selfTime: 18, children: []},\n {id: D, ts: 36, dur: 69, selfTime: 69, children: []},\n {id: E, ts: 154, dur: 117, selfTime: 117, children: []},\n ];\n assert.exists(tree?.roots);\n if (!tree?.roots) {\n // This shouldn't happen, but add this if check to pass ts check.\n return;\n }\n const allNodes = getAllNodes(tree?.roots);\n const callsTestData = calls?.map(\n c => {\n const node = allNodes.find(node => node.id === c.nodeId);\n const children = node?.children || [];\n return ({\n id: c.nodeId,\n dur: Math.round(c.dur || 0),\n ts: c.ts,\n selfTime: Math.round(c.selfTime || 0),\n children: [...children].map(child => child.id) || [],\n });\n },\n );\n\n assert.deepEqual(callsTestData, expectedResult);\n });\n it('can build profile calls from a CPU profile coming from a real world trace', async () => {\n const data = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n\n const threadId = TraceModel.Types.TraceEvents.ThreadID(1);\n const firstProcessId = TraceModel.Types.TraceEvents.ProcessID(2236123);\n const profilesFirstProcess = data.profilesInProcess.get(firstProcessId);\n const calls = profilesFirstProcess?.get(threadId)?.profileCalls.slice(0, 5).map(call => {\n const selfTime = data.entryToNode.get(call)?.selfTime;\n return {...call, selfTime};\n });\n const tree = profilesFirstProcess?.get(threadId)?.profileTree;\n const expectedResult = [\n {id: 2, dur: 392, ts: 643496962681, selfTime: 392, children: []},\n {id: 3, dur: 682, ts: 643496963073, selfTime: 0, children: [4]},\n {id: 4, dur: 682, ts: 643496963073, selfTime: 160, children: [5]},\n {id: 5, dur: 522, ts: 643496963233, selfTime: 178, children: [6, 7]},\n {id: 6, dur: 175, ts: 643496963411, selfTime: 175, children: []},\n ];\n assert.exists(tree?.roots);\n if (!tree?.roots) {\n // This shouldn't happen, but add this if check to pass ts check.\n return;\n }\n const allNodes = getAllNodes(tree?.roots);\n const callsTestData = calls?.map(c => {\n const node = allNodes.find(node => node.id === c.nodeId);\n const children = node?.children || [];\n return {\n id: c.nodeId,\n dur: Math.round(c.dur || 0),\n ts: c.ts,\n selfTime: Math.round(c.selfTime || 0),\n children: [...children].map(child => child.id) || [],\n };\n });\n assert.deepEqual(callsTestData, expectedResult);\n });\n });\n describe('CPU Profile building', () => {\n it('generates a CPU profile from a trace file', async () => {\n const data = await handleEventsFromTraceFile(this, 'recursive-blocking-js.json.gz');\n assert.strictEqual(data.profilesInProcess.size, 1);\n const profileById = data.profilesInProcess.values().next().value;\n assert.strictEqual(profileById.size, 1);\n const cpuProfileData = profileById.values().next().value as TraceModel.Handlers.ModelHandlers.Samples.ProfileData;\n const cpuProfile = cpuProfileData.rawProfile;\n assert.deepEqual(Object.keys(cpuProfile), ['startTime', 'endTime', 'nodes', 'samples', 'timeDeltas', 'lines']);\n assert.strictEqual(cpuProfile.nodes.length, 153);\n assert.strictEqual(cpuProfile.startTime, 287510826176);\n assert.strictEqual(cpuProfile.endTime, 287510847633);\n assert.strictEqual(cpuProfile.samples?.length, 39471);\n assert.strictEqual(cpuProfile.samples?.length, cpuProfile.timeDeltas?.length);\n assert.strictEqual(cpuProfile.samples?.length, cpuProfile.lines?.length);\n });\n });\n describe('CPU Profile parsing', () => {\n it('generates a parsed CPU profile from a trace file', async () => {\n const data = await handleEventsFromTraceFile(this, 'recursive-blocking-js.json.gz');\n assert.strictEqual(data.profilesInProcess.size, 1);\n const profileById = data.profilesInProcess.values().next().value;\n assert.strictEqual(profileById.size, 1);\n const cpuProfileData = profileById.values().next().value as TraceModel.Handlers.ModelHandlers.Samples.ProfileData;\n const parsedProfile = cpuProfileData.parsedProfile;\n assert.strictEqual(parsedProfile.nodes()?.length, 153);\n\n // Ensure that we correctly maintain a lineNumber/columnNumber of 0 and don't fall back to -1 because 0 is falsey.\n const nodesWithZeroLineNumber = parsedProfile.nodes()?.filter(node => node.lineNumber === 0) || [];\n assert.lengthOf(nodesWithZeroLineNumber, 15);\n const nodesWithZeroColumnNumber = parsedProfile.nodes()?.filter(node => node.columnNumber === 0) || [];\n assert.lengthOf(nodesWithZeroColumnNumber, 12);\n assert.strictEqual(parsedProfile.gcNode?.id, 36);\n assert.strictEqual(parsedProfile.programNode?.id, 2);\n assert.strictEqual(parsedProfile.profileStartTime, 287510835.138);\n assert.strictEqual(parsedProfile.profileEndTime, 287515908.9025441);\n assert.strictEqual(parsedProfile.maxDepth, 14);\n assert.strictEqual(parsedProfile.samples?.length, 39471);\n });\n });\n\n describe('getProfileCallFunctionName', () => {\n // Find an event from the trace that represents some work. The use of\n // this specific call frame event is not for any real reason.\n function getProfileEventAndNode(traceData: TraceModel.Handlers.Types.TraceParseData): {\n entry: TraceModel.Types.TraceEvents.SyntheticProfileCall,\n profileNode: CPUProfile.ProfileTreeModel.ProfileNode,\n } {\n const mainThread = getMainThread(traceData.Renderer);\n let foundNode: CPUProfile.ProfileTreeModel.ProfileNode|null = null;\n let foundEntry: TraceModel.Types.TraceEvents.SyntheticProfileCall|null = null;\n\n for (const entry of mainThread.entries) {\n if (TraceModel.Types.TraceEvents.isProfileCall(entry) &&\n entry.callFrame.functionName === 'performConcurrentWorkOnRoot') {\n const profile = traceData.Samples.profilesInProcess.get(entry.pid)?.get(entry.tid);\n const node = profile?.parsedProfile.nodeById(entry.nodeId);\n if (node) {\n foundNode = node;\n }\n foundEntry = entry;\n break;\n }\n }\n if (!foundNode) {\n throw new Error('Could not find CPU Profile node.');\n }\n if (!foundEntry) {\n throw new Error('Could not find expected entry.');\n }\n\n return {\n entry: foundEntry,\n profileNode: foundNode,\n };\n }\n\n it('falls back to the call frame name if the ProfileNode name is empty', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'react-hello-world.json.gz');\n const {entry, profileNode} = getProfileEventAndNode(traceData);\n // Store and then reset this: we are doing this to test the fallback to\n // the entry callFrame.functionName property. After the assertion we\n // reset this to avoid impacting other tests.\n const originalProfileNodeName = profileNode.functionName;\n profileNode.setFunctionName('');\n assert.strictEqual(\n TraceModel.Handlers.ModelHandlers.Samples.getProfileCallFunctionName(traceData.Samples, entry),\n 'performConcurrentWorkOnRoot');\n // St\n profileNode.setFunctionName(originalProfileNodeName);\n });\n\n it('uses the profile name if it has been set', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'react-hello-world.json.gz');\n const {entry, profileNode} = getProfileEventAndNode(traceData);\n // Store and then reset this: we are doing this to test the fallback to\n // the entry callFrame.functionName property. After the assertion we\n // reset this to avoid impacting other tests.\n const originalProfileNodeName = profileNode.functionName;\n profileNode.setFunctionName('testing-profile-name');\n assert.strictEqual(\n TraceModel.Handlers.ModelHandlers.Samples.getProfileCallFunctionName(traceData.Samples, entry),\n 'testing-profile-name');\n profileNode.setFunctionName(originalProfileNodeName);\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"SamplesHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/SamplesHandler.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as CPUProfile from '../../../models/cpu_profile/cpu_profile.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {getAllNodes, getMainThread} from '../../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Trace from '../trace.js';\n\nasync function handleEventsFromTraceFile(context: Mocha.Context|Mocha.Suite|null, name: string):\n Promise {\n const traceEvents = await TraceLoader.rawEvents(context, name);\n Trace.Handlers.ModelHandlers.Meta.reset();\n Trace.Handlers.ModelHandlers.Samples.reset();\n\n Trace.Handlers.ModelHandlers.Meta.initialize();\n Trace.Handlers.ModelHandlers.Samples.initialize();\n\n for (const event of traceEvents) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n Trace.Handlers.ModelHandlers.Samples.handleEvent(event);\n }\n\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n await Trace.Handlers.ModelHandlers.Samples.finalize();\n\n return Trace.Handlers.ModelHandlers.Samples.data();\n}\n\ndescribeWithEnvironment('SamplesHandler', function() {\n it('finds all the profiles in a real world recording', async () => {\n const data = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n // The same thread id is shared across profiles in the profiled\n // processes.\n const threadId = Trace.Types.Events.ThreadID(1);\n const firstProcessId = Trace.Types.Events.ProcessID(2236123);\n const secondProcessId = Trace.Types.Events.ProcessID(2154214);\n const thirdProcessId = Trace.Types.Events.ProcessID(2236084);\n\n assert.strictEqual(data.profilesInProcess.size, 3);\n\n const profilesFirstProcess = data.profilesInProcess.get(firstProcessId);\n assert.strictEqual(profilesFirstProcess?.size, 1);\n assert.exists(profilesFirstProcess?.get(threadId));\n\n const profilesSecondProcess = data.profilesInProcess.get(secondProcessId);\n assert.strictEqual(profilesSecondProcess?.size, 1);\n assert.exists(profilesSecondProcess?.get(threadId));\n\n const profilesThirdProcess = data.profilesInProcess.get(thirdProcessId);\n assert.strictEqual(profilesThirdProcess?.size, 1);\n assert.exists(profilesThirdProcess?.get(threadId));\n });\n describe('profile calls building', () => {\n const pid = Trace.Types.Events.ProcessID(0);\n const id = Trace.Types.Events.ProfileID('0');\n const tid = Trace.Types.Events.ThreadID(1);\n\n function makeProfileChunkEvent(\n nodes: {\n id: number,\n children: number[],\n codeType?: string,\n url?: string,\n functionName?: string,\n scriptId?: number,\n }[],\n samples: number[],\n timeDeltas: number[],\n ts: number,\n ): Trace.Types.Events.ProfileChunk {\n return {\n cat: '',\n name: 'ProfileChunk',\n ph: Trace.Types.Events.Phase.SAMPLE,\n pid,\n tid: Trace.Types.Events.ThreadID(0),\n ts: Trace.Types.Timing.MicroSeconds(ts),\n id,\n args: {\n data: {\n cpuProfile: {\n samples: samples.map(Trace.Types.Events.CallFrameID),\n nodes: nodes.map(\n node => ({\n ...node,\n callFrame: {functionName: '', scriptId: 0, columnNumber: 0, lineNumber: 0, url: ''},\n id: Trace.Types.Events.CallFrameID(node.id),\n }),\n ),\n },\n timeDeltas: timeDeltas.map(Trace.Types.Timing.MicroSeconds),\n },\n },\n };\n }\n it('can build profile calls from a CPU profile coming from tracing', async () => {\n const A = 0;\n const B = 1;\n const C = 2;\n const D = 3;\n const E = 4;\n const root = 9;\n const mockProfileEvent: Trace.Types.Events.Profile = {\n name: 'Profile',\n id,\n args: {data: {startTime: Trace.Types.Timing.MicroSeconds(0)}},\n cat: '',\n pid,\n tid,\n ts: Trace.Types.Timing.MicroSeconds(0),\n ph: Trace.Types.Events.Phase.SAMPLE,\n };\n /**\n * +------------> (sample at time)\n * |A|A|A|A|A|A|A|A|A|A|A|A|A|A|A|A|A| |E|E|E|E|E|E|\n * | |B|B|B|B|B|B| |D|D|D|D|D|D| | | | | | | | | | |\n * | | |C|C|C|C| | | | | | | | | | | | | | | | | | |\n * |\n * V (stack trace depth)\n */\n const mockTimeDeltas = [\n 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 21, 22, 23,\n ];\n\n const mockSamples = [A, B, C, C, C, C, B, A, D, D, D, D, D, D, A, A, A, E, E, E, E, E, E];\n /*\n * A E\n * / \\\n * B D\n * |\n * C\n */\n const mockChunks = [\n makeProfileChunkEvent([{id: root, children: [A, E]}], [], [], 0),\n makeProfileChunkEvent(\n [{id: A, children: [B, D]}, {id: B, children: [C]}, {id: C, children: []}], mockSamples, mockTimeDeltas, 0),\n makeProfileChunkEvent([{id: D, children: []}], [], [], 0),\n makeProfileChunkEvent([{id: E, children: []}], [], [], 0),\n ];\n Trace.Handlers.ModelHandlers.Samples.reset();\n\n Trace.Handlers.ModelHandlers.Samples.initialize();\n\n for (const event of [mockProfileEvent, ...mockChunks]) {\n Trace.Handlers.ModelHandlers.Samples.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Samples.finalize();\n const data = Trace.Handlers.ModelHandlers.Samples.data();\n const calls = data.profilesInProcess.get(pid)?.get(tid)?.profileCalls.map(call => {\n const selfTime = data.entryToNode.get(call)?.selfTime;\n return {...call, selfTime};\n });\n const tree = data.profilesInProcess.get(pid)?.get(tid)?.profileTree;\n const expectedResult = [\n {id: A, ts: 0, dur: 154, selfTime: 58, children: [B, D]},\n {id: B, ts: 1, dur: 27, selfTime: 9, children: [C]},\n {id: C, ts: 3, dur: 18, selfTime: 18, children: []},\n {id: D, ts: 36, dur: 69, selfTime: 69, children: []},\n {id: E, ts: 154, dur: 117, selfTime: 117, children: []},\n ];\n assert.exists(tree?.roots);\n if (!tree?.roots) {\n // This shouldn't happen, but add this if check to pass ts check.\n return;\n }\n const allNodes = getAllNodes(tree?.roots);\n const callsTestData = calls?.map(\n c => {\n const node = allNodes.find(node => node.id === c.nodeId);\n const children = node?.children || [];\n return ({\n id: c.nodeId,\n dur: Math.round(c.dur || 0),\n ts: c.ts,\n selfTime: Math.round(c.selfTime || 0),\n children: [...children].map(child => child.id) || [],\n });\n },\n );\n\n assert.deepEqual(callsTestData, expectedResult);\n });\n it('can build profile calls from a CPU profile coming from a real world trace', async () => {\n const data = await handleEventsFromTraceFile(this, 'multiple-navigations-with-iframes.json.gz');\n\n const threadId = Trace.Types.Events.ThreadID(1);\n const firstProcessId = Trace.Types.Events.ProcessID(2236123);\n const profilesFirstProcess = data.profilesInProcess.get(firstProcessId);\n const calls = profilesFirstProcess?.get(threadId)?.profileCalls.slice(0, 5).map(call => {\n const selfTime = data.entryToNode.get(call)?.selfTime;\n return {...call, selfTime};\n });\n const tree = profilesFirstProcess?.get(threadId)?.profileTree;\n const expectedResult = [\n {id: 2, dur: 392, ts: 643496962681, selfTime: 392, children: []},\n {id: 3, dur: 682, ts: 643496963073, selfTime: 0, children: [4]},\n {id: 4, dur: 682, ts: 643496963073, selfTime: 160, children: [5]},\n {id: 5, dur: 522, ts: 643496963233, selfTime: 178, children: [6, 7]},\n {id: 6, dur: 175, ts: 643496963411, selfTime: 175, children: []},\n ];\n assert.exists(tree?.roots);\n if (!tree?.roots) {\n // This shouldn't happen, but add this if check to pass ts check.\n return;\n }\n const allNodes = getAllNodes(tree?.roots);\n const callsTestData = calls?.map(c => {\n const node = allNodes.find(node => node.id === c.nodeId);\n const children = node?.children || [];\n return {\n id: c.nodeId,\n dur: Math.round(c.dur || 0),\n ts: c.ts,\n selfTime: Math.round(c.selfTime || 0),\n children: [...children].map(child => child.id) || [],\n };\n });\n assert.deepEqual(callsTestData, expectedResult);\n });\n });\n describe('CPU Profile building', () => {\n it('generates a CPU profile from a trace file', async () => {\n const data = await handleEventsFromTraceFile(this, 'recursive-blocking-js.json.gz');\n assert.strictEqual(data.profilesInProcess.size, 1);\n const profileById = data.profilesInProcess.values().next().value;\n assert.strictEqual(profileById.size, 1);\n const cpuProfileData = profileById.values().next().value as Trace.Handlers.ModelHandlers.Samples.ProfileData;\n const cpuProfile = cpuProfileData.rawProfile;\n assert.deepEqual(Object.keys(cpuProfile), ['startTime', 'endTime', 'nodes', 'samples', 'timeDeltas', 'lines']);\n assert.strictEqual(cpuProfile.nodes.length, 153);\n assert.strictEqual(cpuProfile.startTime, 287510826176);\n assert.strictEqual(cpuProfile.endTime, 287510847633);\n assert.strictEqual(cpuProfile.samples?.length, 39471);\n assert.strictEqual(cpuProfile.samples?.length, cpuProfile.timeDeltas?.length);\n assert.strictEqual(cpuProfile.samples?.length, cpuProfile.lines?.length);\n });\n });\n describe('CPU Profile parsing', () => {\n it('generates a parsed CPU profile from a trace file', async () => {\n const data = await handleEventsFromTraceFile(this, 'recursive-blocking-js.json.gz');\n assert.strictEqual(data.profilesInProcess.size, 1);\n const profileById = data.profilesInProcess.values().next().value;\n assert.strictEqual(profileById.size, 1);\n const cpuProfileData = profileById.values().next().value as Trace.Handlers.ModelHandlers.Samples.ProfileData;\n const parsedProfile = cpuProfileData.parsedProfile;\n assert.strictEqual(parsedProfile.nodes()?.length, 153);\n\n // Ensure that we correctly maintain a lineNumber/columnNumber of 0 and don't fall back to -1 because 0 is falsey.\n const nodesWithZeroLineNumber = parsedProfile.nodes()?.filter(node => node.lineNumber === 0) || [];\n assert.lengthOf(nodesWithZeroLineNumber, 15);\n const nodesWithZeroColumnNumber = parsedProfile.nodes()?.filter(node => node.columnNumber === 0) || [];\n assert.lengthOf(nodesWithZeroColumnNumber, 12);\n assert.strictEqual(parsedProfile.gcNode?.id, 36);\n assert.strictEqual(parsedProfile.programNode?.id, 2);\n assert.strictEqual(parsedProfile.profileStartTime, 287510835.138);\n assert.strictEqual(parsedProfile.profileEndTime, 287515908.9025441);\n assert.strictEqual(parsedProfile.maxDepth, 14);\n assert.strictEqual(parsedProfile.samples?.length, 39471);\n });\n });\n\n describe('getProfileCallFunctionName', () => {\n // Find an event from the trace that represents some work. The use of\n // this specific call frame event is not for any real reason.\n function getProfileEventAndNode(parsedTrace: Trace.Handlers.Types.ParsedTrace): {\n entry: Trace.Types.Events.SyntheticProfileCall,\n profileNode: CPUProfile.ProfileTreeModel.ProfileNode,\n } {\n const mainThread = getMainThread(parsedTrace.Renderer);\n let foundNode: CPUProfile.ProfileTreeModel.ProfileNode|null = null;\n let foundEntry: Trace.Types.Events.SyntheticProfileCall|null = null;\n\n for (const entry of mainThread.entries) {\n if (Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'performConcurrentWorkOnRoot') {\n const profile = parsedTrace.Samples.profilesInProcess.get(entry.pid)?.get(entry.tid);\n const node = profile?.parsedProfile.nodeById(entry.nodeId);\n if (node) {\n foundNode = node;\n }\n foundEntry = entry;\n break;\n }\n }\n if (!foundNode) {\n throw new Error('Could not find CPU Profile node.');\n }\n if (!foundEntry) {\n throw new Error('Could not find expected entry.');\n }\n\n return {\n entry: foundEntry,\n profileNode: foundNode,\n };\n }\n\n it('falls back to the call frame name if the ProfileNode name is empty', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'react-hello-world.json.gz');\n const {entry, profileNode} = getProfileEventAndNode(parsedTrace);\n // Store and then reset this: we are doing this to test the fallback to\n // the entry callFrame.functionName property. After the assertion we\n // reset this to avoid impacting other tests.\n const originalProfileNodeName = profileNode.functionName;\n profileNode.setFunctionName('');\n assert.strictEqual(\n Trace.Handlers.ModelHandlers.Samples.getProfileCallFunctionName(parsedTrace.Samples, entry),\n 'performConcurrentWorkOnRoot');\n // St\n profileNode.setFunctionName(originalProfileNodeName);\n });\n\n it('uses the profile name if it has been set', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'react-hello-world.json.gz');\n const {entry, profileNode} = getProfileEventAndNode(parsedTrace);\n // Store and then reset this: we are doing this to test the fallback to\n // the entry callFrame.functionName property. After the assertion we\n // reset this to avoid impacting other tests.\n const originalProfileNodeName = profileNode.functionName;\n profileNode.setFunctionName('testing-profile-name');\n assert.strictEqual(\n Trace.Handlers.ModelHandlers.Samples.getProfileCallFunctionName(parsedTrace.Samples, entry),\n 'testing-profile-name');\n profileNode.setFunctionName(originalProfileNodeName);\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/ScreenshotsHandler.d.ts b/public/models/trace/handlers/ScreenshotsHandler.d.ts index 5a14f39ff..188d28949 100644 --- a/public/models/trace/handlers/ScreenshotsHandler.d.ts +++ b/public/models/trace/handlers/ScreenshotsHandler.d.ts @@ -1,7 +1,7 @@ import * as Types from '../types/types.js'; -import { type TraceEventHandlerName } from './types.js'; +import { type HandlerName } from './types.js'; export declare function reset(): void; -export declare function handleEvent(event: Types.TraceEvents.TraceEventData): void; +export declare function handleEvent(event: Types.Events.Event): void; export declare function finalize(): Promise; -export declare function data(): Types.TraceEvents.SyntheticScreenshot[]; -export declare function deps(): TraceEventHandlerName[]; +export declare function data(): Types.Events.SyntheticScreenshot[]; +export declare function deps(): HandlerName[]; diff --git a/public/models/trace/handlers/ScreenshotsHandler.js b/public/models/trace/handlers/ScreenshotsHandler.js index bf9e748e4..40e7b5fbf 100644 --- a/public/models/trace/handlers/ScreenshotsHandler.js +++ b/public/models/trace/handlers/ScreenshotsHandler.js @@ -7,19 +7,19 @@ import * as Types from '../types/types.js'; // used to store the event in the correct process thread entry below. const unpairedAsyncEvents = []; const snapshotEvents = []; -const syntheticScreenshotEvents = []; +const syntheticScreenshots = []; let frameSequenceToTs = {}; export function reset() { unpairedAsyncEvents.length = 0; snapshotEvents.length = 0; - syntheticScreenshotEvents.length = 0; + syntheticScreenshots.length = 0; frameSequenceToTs = {}; } export function handleEvent(event) { - if (Types.TraceEvents.isTraceEventScreenshot(event)) { + if (Types.Events.isScreenshot(event)) { snapshotEvents.push(event); } - else if (Types.TraceEvents.isTraceEventPipelineReporter(event)) { + else if (Types.Events.isPipelineReporter(event)) { unpairedAsyncEvents.push(event); } } @@ -32,7 +32,7 @@ export async function finalize() { })); for (const snapshotEvent of snapshotEvents) { const { cat, name, ph, pid, tid } = snapshotEvent; - const syntheticEvent = Helpers.SyntheticEvents.SyntheticEventsManager.registerSyntheticBasedEvent({ + const syntheticEvent = Helpers.SyntheticEvents.SyntheticEventsManager.registerSyntheticEvent({ rawSourceEvent: snapshotEvent, cat, name, @@ -45,7 +45,7 @@ export async function finalize() { dataUri: `data:image/jpg;base64,${snapshotEvent.args.snapshot}`, }, }); - syntheticScreenshotEvents.push(syntheticEvent); + syntheticScreenshots.push(syntheticEvent); } } /** @@ -73,7 +73,7 @@ function getPresentationTimestamp(screenshotEvent) { } // TODO(crbug/41484172): should be readonly export function data() { - return syntheticScreenshotEvents; + return syntheticScreenshots; } export function deps() { return ['Meta']; diff --git a/public/models/trace/handlers/ScreenshotsHandler.js.map b/public/models/trace/handlers/ScreenshotsHandler.js.map index d33783726..3d3034e79 100644 --- a/public/models/trace/handlers/ScreenshotsHandler.js.map +++ b/public/models/trace/handlers/ScreenshotsHandler.js.map @@ -1 +1 @@ -{"version":3,"file":"ScreenshotsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/ScreenshotsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {type TraceEventHandlerName} from './types.js';\n\n// Each thread contains events. Events indicate the thread and process IDs, which are\n// used to store the event in the correct process thread entry below.\nconst unpairedAsyncEvents: Types.TraceEvents.TraceEventPipelineReporter[] = [];\n\nconst snapshotEvents: Types.TraceEvents.TraceEventScreenshot[] = [];\nconst syntheticScreenshotEvents: Types.TraceEvents.SyntheticScreenshot[] = [];\nlet frameSequenceToTs: Record = {};\n\nexport function reset(): void {\n unpairedAsyncEvents.length = 0;\n snapshotEvents.length = 0;\n syntheticScreenshotEvents.length = 0;\n frameSequenceToTs = {};\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (Types.TraceEvents.isTraceEventScreenshot(event)) {\n snapshotEvents.push(event);\n } else if (Types.TraceEvents.isTraceEventPipelineReporter(event)) {\n unpairedAsyncEvents.push(event);\n }\n}\n\nexport async function finalize(): Promise {\n const pipelineReporterEvents = Helpers.Trace.createMatchedSortedSyntheticEvents(unpairedAsyncEvents);\n\n frameSequenceToTs = Object.fromEntries(pipelineReporterEvents.map(evt => {\n const frameSequenceId = evt.args.data.beginEvent.args.chrome_frame_reporter.frame_sequence;\n const presentationTs = Types.Timing.MicroSeconds(evt.ts + evt.dur);\n return [frameSequenceId, presentationTs];\n }));\n\n for (const snapshotEvent of snapshotEvents) {\n const {cat, name, ph, pid, tid} = snapshotEvent;\n const syntheticEvent = Helpers.SyntheticEvents.SyntheticEventsManager.registerSyntheticBasedEvent<\n Types.TraceEvents.SyntheticScreenshot>({\n rawSourceEvent: snapshotEvent,\n cat,\n name,\n ph,\n pid,\n tid,\n // `getPresentationTimestamp(snapshotEvent) - snapshotEvent.ts` is how many microsec the screenshot was adjusted to the right/later\n ts: getPresentationTimestamp(snapshotEvent),\n args: {\n dataUri: `data:image/jpg;base64,${snapshotEvent.args.snapshot}`,\n },\n });\n syntheticScreenshotEvents.push(syntheticEvent);\n }\n}\n\n/**\n * Correct the screenshot timestamps\n * The screenshot 'snapshot object' trace event has the \"frame sequence number\" attached as an ID.\n * We match that up with the \"PipelineReporter\" trace events as they terminate at presentation.\n * Presentation == when the pixels hit the screen. AKA Swap on the GPU\n */\nfunction getPresentationTimestamp(screenshotEvent: Types.TraceEvents.TraceEventScreenshot): Types.Timing.MicroSeconds {\n const frameSequence = parseInt(screenshotEvent.id, 16);\n // If it's 1, then it's an old trace (before https://crrev.com/c/4957973) and cannot be corrected.\n if (frameSequence === 1) {\n return screenshotEvent.ts;\n }\n // The screenshot trace event's `ts` reflects the \"expected display time\" which is ESTIMATE.\n // It is set by the compositor frame sink from the `expected_display_time`, which is based on a previously known\n // frame start PLUS the vsync interval (eg 16.6ms)\n const updatedTs = frameSequenceToTs[frameSequence];\n // Do we always find a match? No...\n // We generally don't match the very first screenshot and, sometimes, the last\n // The very first screenshot is requested immediately (even if nothing is painting). As a result there's no compositor\n // instrumentation running alongside.\n // The last one is sometimes missing as because the trace terminates right before the associated PipelineReporter is emitted.\n return updatedTs ?? screenshotEvent.ts;\n}\n\n// TODO(crbug/41484172): should be readonly\nexport function data(): Types.TraceEvents.SyntheticScreenshot[] {\n return syntheticScreenshotEvents;\n}\n\nexport function deps(): TraceEventHandlerName[] {\n return ['Meta'];\n}\n"]} \ No newline at end of file +{"version":3,"file":"ScreenshotsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/ScreenshotsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {type HandlerName} from './types.js';\n\n// Each thread contains events. Events indicate the thread and process IDs, which are\n// used to store the event in the correct process thread entry below.\nconst unpairedAsyncEvents: Types.Events.PipelineReporter[] = [];\n\nconst snapshotEvents: Types.Events.Screenshot[] = [];\nconst syntheticScreenshots: Types.Events.SyntheticScreenshot[] = [];\nlet frameSequenceToTs: Record = {};\n\nexport function reset(): void {\n unpairedAsyncEvents.length = 0;\n snapshotEvents.length = 0;\n syntheticScreenshots.length = 0;\n frameSequenceToTs = {};\n}\n\nexport function handleEvent(event: Types.Events.Event): void {\n if (Types.Events.isScreenshot(event)) {\n snapshotEvents.push(event);\n } else if (Types.Events.isPipelineReporter(event)) {\n unpairedAsyncEvents.push(event);\n }\n}\n\nexport async function finalize(): Promise {\n const pipelineReporterEvents = Helpers.Trace.createMatchedSortedSyntheticEvents(unpairedAsyncEvents);\n\n frameSequenceToTs = Object.fromEntries(pipelineReporterEvents.map(evt => {\n const frameSequenceId = evt.args.data.beginEvent.args.chrome_frame_reporter.frame_sequence;\n const presentationTs = Types.Timing.MicroSeconds(evt.ts + evt.dur);\n return [frameSequenceId, presentationTs];\n }));\n\n for (const snapshotEvent of snapshotEvents) {\n const {cat, name, ph, pid, tid} = snapshotEvent;\n const syntheticEvent = Helpers.SyntheticEvents.SyntheticEventsManager.registerSyntheticEvent<\n Types.Events.SyntheticScreenshot>({\n rawSourceEvent: snapshotEvent,\n cat,\n name,\n ph,\n pid,\n tid,\n // `getPresentationTimestamp(snapshotEvent) - snapshotEvent.ts` is how many microsec the screenshot was adjusted to the right/later\n ts: getPresentationTimestamp(snapshotEvent),\n args: {\n dataUri: `data:image/jpg;base64,${snapshotEvent.args.snapshot}`,\n },\n });\n syntheticScreenshots.push(syntheticEvent);\n }\n}\n\n/**\n * Correct the screenshot timestamps\n * The screenshot 'snapshot object' trace event has the \"frame sequence number\" attached as an ID.\n * We match that up with the \"PipelineReporter\" trace events as they terminate at presentation.\n * Presentation == when the pixels hit the screen. AKA Swap on the GPU\n */\nfunction getPresentationTimestamp(screenshotEvent: Types.Events.Screenshot): Types.Timing.MicroSeconds {\n const frameSequence = parseInt(screenshotEvent.id, 16);\n // If it's 1, then it's an old trace (before https://crrev.com/c/4957973) and cannot be corrected.\n if (frameSequence === 1) {\n return screenshotEvent.ts;\n }\n // The screenshot trace event's `ts` reflects the \"expected display time\" which is ESTIMATE.\n // It is set by the compositor frame sink from the `expected_display_time`, which is based on a previously known\n // frame start PLUS the vsync interval (eg 16.6ms)\n const updatedTs = frameSequenceToTs[frameSequence];\n // Do we always find a match? No...\n // We generally don't match the very first screenshot and, sometimes, the last\n // The very first screenshot is requested immediately (even if nothing is painting). As a result there's no compositor\n // instrumentation running alongside.\n // The last one is sometimes missing as because the trace terminates right before the associated PipelineReporter is emitted.\n return updatedTs ?? screenshotEvent.ts;\n}\n\n// TODO(crbug/41484172): should be readonly\nexport function data(): Types.Events.SyntheticScreenshot[] {\n return syntheticScreenshots;\n}\n\nexport function deps(): HandlerName[] {\n return ['Meta'];\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/ScreenshotsHandler.test.js b/public/models/trace/handlers/ScreenshotsHandler.test.js index 7c8cd6ab0..093f1b302 100644 --- a/public/models/trace/handlers/ScreenshotsHandler.test.js +++ b/public/models/trace/handlers/ScreenshotsHandler.test.js @@ -3,19 +3,19 @@ // found in the LICENSE file. import { defaultTraceEvent } from '../../../testing/TraceHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; -import * as TraceModel from '../trace.js'; +import * as Trace from '../trace.js'; describe('ScreenshotsHandler', function () { const baseEvent = { ...defaultTraceEvent, name: 'Screenshot', // Ensure that the screenshots are held against the pid & tid values // that match the Browser process and CrBrowserMain in defaultTraceEvents. - pid: TraceModel.Types.TraceEvents.ProcessID(8017), - tid: TraceModel.Types.TraceEvents.ThreadID(775), - ts: TraceModel.Types.Timing.MicroSeconds(0), + pid: Trace.Types.Events.ProcessID(8017), + tid: Trace.Types.Events.ThreadID(775), + ts: Trace.Types.Timing.MicroSeconds(0), args: {}, cat: 'test', - ph: "O" /* TraceModel.Types.TraceEvents.Phase.OBJECT_SNAPSHOT */, + ph: "O" /* Trace.Types.Events.Phase.OBJECT_SNAPSHOT */, }; let baseEvents; beforeEach(async function () { @@ -23,32 +23,32 @@ describe('ScreenshotsHandler', function () { // to know the browser process and thread IDs. Here, then, we reset // and later we will pass events to the meta handler, otherwise the // screenshots handler will fail. - TraceModel.Handlers.ModelHandlers.Meta.reset(); - TraceModel.Handlers.ModelHandlers.Meta.initialize(); - TraceModel.Handlers.ModelHandlers.Screenshots.reset(); + Trace.Handlers.ModelHandlers.Meta.reset(); + Trace.Handlers.ModelHandlers.Meta.initialize(); + Trace.Handlers.ModelHandlers.Screenshots.reset(); }); describe('frames', () => { it('obtains them if present', async function () { const defaultTraceEvents = await TraceLoader.rawEvents(this, 'basic.json.gz'); baseEvents = [ ...defaultTraceEvents, - { ...baseEvent, ts: TraceModel.Types.Timing.MicroSeconds(100) }, - { ...baseEvent, ts: TraceModel.Types.Timing.MicroSeconds(200) }, + { ...baseEvent, ts: Trace.Types.Timing.MicroSeconds(100) }, + { ...baseEvent, ts: Trace.Types.Timing.MicroSeconds(200) }, ]; - TraceModel.Helpers.SyntheticEvents.SyntheticEventsManager.createAndActivate(baseEvents); + Trace.Helpers.SyntheticEvents.SyntheticEventsManager.createAndActivate(baseEvents); for (const event of baseEvents) { - TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event); - TraceModel.Handlers.ModelHandlers.Screenshots.handleEvent(event); + Trace.Handlers.ModelHandlers.Meta.handleEvent(event); + Trace.Handlers.ModelHandlers.Screenshots.handleEvent(event); } - await TraceModel.Handlers.ModelHandlers.Meta.finalize(); - await TraceModel.Handlers.ModelHandlers.Screenshots.finalize(); - const data = TraceModel.Handlers.ModelHandlers.Screenshots.data(); + await Trace.Handlers.ModelHandlers.Meta.finalize(); + await Trace.Handlers.ModelHandlers.Screenshots.finalize(); + const data = Trace.Handlers.ModelHandlers.Screenshots.data(); assert.strictEqual(data.length, 2); }); }); describe('presentation timestamps', () => { - function getMsDifferences(syntheticScreenshotEvents, originalScreenshotEvents) { - return syntheticScreenshotEvents.map((synEvent, i) => { + function getMsDifferences(syntheticScreenshots, originalScreenshotEvents) { + return syntheticScreenshots.map((synEvent, i) => { const origEvent = originalScreenshotEvents.at(i); const msDifference = (synEvent.ts - origEvent.ts) / 1000; return msDifference; @@ -58,18 +58,18 @@ describe('ScreenshotsHandler', function () { // This trace was collected after https://crrev.com/c/4957973 landed. const events = await TraceLoader.rawEvents(this, 'about-blank-first.json.gz'); for (const event of events) { - TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event); - TraceModel.Handlers.ModelHandlers.Screenshots.handleEvent(event); + Trace.Handlers.ModelHandlers.Meta.handleEvent(event); + Trace.Handlers.ModelHandlers.Screenshots.handleEvent(event); } - await TraceModel.Handlers.ModelHandlers.Meta.finalize(); - await TraceModel.Handlers.ModelHandlers.Screenshots.finalize(); - const syntheticScreenshotEvents = TraceModel.Handlers.ModelHandlers.Screenshots.data(); - const originalScreenshotEvents = events.filter(TraceModel.Types.TraceEvents.isTraceEventScreenshot); - assert.strictEqual(syntheticScreenshotEvents.length, originalScreenshotEvents.length); + await Trace.Handlers.ModelHandlers.Meta.finalize(); + await Trace.Handlers.ModelHandlers.Screenshots.finalize(); + const syntheticScreenshots = Trace.Handlers.ModelHandlers.Screenshots.data(); + const originalScreenshotEvents = events.filter(Trace.Types.Events.isScreenshot); + assert.strictEqual(syntheticScreenshots.length, originalScreenshotEvents.length); for (const oEvent of originalScreenshotEvents) { assert.notStrictEqual(oEvent.id, '0x1'); // The id (frame sequence) shouldn't be the old default of 1. } - const msDifferences = getMsDifferences(syntheticScreenshotEvents, originalScreenshotEvents); + const msDifferences = getMsDifferences(syntheticScreenshots, originalScreenshotEvents); // These values indicate all the screenshots true timings are a tad more to the left. assert.deepStrictEqual(msDifferences, [ -13.079, -16.381, -12.503, -5.405, -14.108, -14.661, -11.944, -14.322, -3.532, -15.821, 0.254, @@ -80,18 +80,18 @@ describe('ScreenshotsHandler', function () { // Any trace captured before 121.0.6156.3 doesn't have the extra data to correct the timestamps. const events = await TraceLoader.rawEvents(this, 'web-dev.json.gz'); for (const event of events) { - TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event); - TraceModel.Handlers.ModelHandlers.Screenshots.handleEvent(event); + Trace.Handlers.ModelHandlers.Meta.handleEvent(event); + Trace.Handlers.ModelHandlers.Screenshots.handleEvent(event); } - await TraceModel.Handlers.ModelHandlers.Meta.finalize(); - await TraceModel.Handlers.ModelHandlers.Screenshots.finalize(); - const syntheticScreenshotEvents = TraceModel.Handlers.ModelHandlers.Screenshots.data(); - const originalScreenshotEvents = events.filter(TraceModel.Types.TraceEvents.isTraceEventScreenshot); - assert.strictEqual(syntheticScreenshotEvents.length, originalScreenshotEvents.length); + await Trace.Handlers.ModelHandlers.Meta.finalize(); + await Trace.Handlers.ModelHandlers.Screenshots.finalize(); + const syntheticScreenshots = Trace.Handlers.ModelHandlers.Screenshots.data(); + const originalScreenshotEvents = events.filter(Trace.Types.Events.isScreenshot); + assert.strictEqual(syntheticScreenshots.length, originalScreenshotEvents.length); for (const oEvent of originalScreenshotEvents) { assert.strictEqual(oEvent.id, '0x1'); // The ids here aren't the new frame sequence, but the hardcoded 1. } - const msDifferences = getMsDifferences(syntheticScreenshotEvents, originalScreenshotEvents); + const msDifferences = getMsDifferences(syntheticScreenshots, originalScreenshotEvents); // No adjustment made. assert.deepStrictEqual(msDifferences, [ 0, diff --git a/public/models/trace/handlers/ScreenshotsHandler.test.js.map b/public/models/trace/handlers/ScreenshotsHandler.test.js.map index 7239d98fa..f70658041 100644 --- a/public/models/trace/handlers/ScreenshotsHandler.test.js.map +++ b/public/models/trace/handlers/ScreenshotsHandler.test.js.map @@ -1 +1 @@ -{"version":3,"file":"ScreenshotsHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/ScreenshotsHandler.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {defaultTraceEvent} from '../../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as TraceModel from '../trace.js';\n\ndescribe('ScreenshotsHandler', function() {\n const baseEvent = {\n ...defaultTraceEvent,\n name: 'Screenshot',\n // Ensure that the screenshots are held against the pid & tid values\n // that match the Browser process and CrBrowserMain in defaultTraceEvents.\n pid: TraceModel.Types.TraceEvents.ProcessID(8017),\n tid: TraceModel.Types.TraceEvents.ThreadID(775),\n ts: TraceModel.Types.Timing.MicroSeconds(0),\n args: {},\n cat: 'test',\n ph: TraceModel.Types.TraceEvents.Phase.OBJECT_SNAPSHOT,\n };\n\n let baseEvents: readonly TraceModel.Types.TraceEvents.TraceEventData[];\n\n beforeEach(async function() {\n // The screenshot handler requires the meta handler because it needs\n // to know the browser process and thread IDs. Here, then, we reset\n // and later we will pass events to the meta handler, otherwise the\n // screenshots handler will fail.\n TraceModel.Handlers.ModelHandlers.Meta.reset();\n TraceModel.Handlers.ModelHandlers.Meta.initialize();\n\n TraceModel.Handlers.ModelHandlers.Screenshots.reset();\n });\n\n describe('frames', () => {\n it('obtains them if present', async function() {\n const defaultTraceEvents = await TraceLoader.rawEvents(this, 'basic.json.gz');\n\n baseEvents = [\n ...defaultTraceEvents,\n {...baseEvent, ts: TraceModel.Types.Timing.MicroSeconds(100)},\n {...baseEvent, ts: TraceModel.Types.Timing.MicroSeconds(200)},\n ];\n TraceModel.Helpers.SyntheticEvents.SyntheticEventsManager.createAndActivate(baseEvents);\n\n for (const event of baseEvents) {\n TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event);\n TraceModel.Handlers.ModelHandlers.Screenshots.handleEvent(event);\n }\n\n await TraceModel.Handlers.ModelHandlers.Meta.finalize();\n await TraceModel.Handlers.ModelHandlers.Screenshots.finalize();\n\n const data = TraceModel.Handlers.ModelHandlers.Screenshots.data();\n assert.strictEqual(data.length, 2);\n });\n });\n\n describe('presentation timestamps', () => {\n function getMsDifferences(\n syntheticScreenshotEvents: TraceModel.Types.TraceEvents.SyntheticScreenshot[],\n originalScreenshotEvents: TraceModel.Types.TraceEvents.TraceEventScreenshot[]): number[] {\n return syntheticScreenshotEvents.map((synEvent, i) => {\n const origEvent = originalScreenshotEvents.at(i) as TraceModel.Types.TraceEvents.TraceEventScreenshot;\n const msDifference = (synEvent.ts - origEvent.ts) / 1000;\n return msDifference;\n });\n }\n it('are corrected if frame sequence number is present', async function() {\n // This trace was collected after https://crrev.com/c/4957973 landed.\n const events = await TraceLoader.rawEvents(this, 'about-blank-first.json.gz');\n for (const event of events) {\n TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event);\n TraceModel.Handlers.ModelHandlers.Screenshots.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.Meta.finalize();\n await TraceModel.Handlers.ModelHandlers.Screenshots.finalize();\n\n const syntheticScreenshotEvents = TraceModel.Handlers.ModelHandlers.Screenshots.data();\n const originalScreenshotEvents = events.filter(TraceModel.Types.TraceEvents.isTraceEventScreenshot);\n assert.strictEqual(syntheticScreenshotEvents.length, originalScreenshotEvents.length);\n\n for (const oEvent of originalScreenshotEvents) {\n assert.notStrictEqual(oEvent.id, '0x1'); // The id (frame sequence) shouldn't be the old default of 1.\n }\n\n const msDifferences = getMsDifferences(syntheticScreenshotEvents, originalScreenshotEvents);\n // These values indicate all the screenshots true timings are a tad more to the left.\n assert.deepStrictEqual(msDifferences, [\n -13.079, -16.381, -12.503, -5.405, -14.108, -14.661, -11.944, -14.322, -3.532, -15.821, 0.254,\n -32.22, -15.156, -13.219, -14.464, -16.135, -16.501, -33.165, -15.71, -32.39, -32.445, -30.512,\n ]);\n });\n\n it('remain the same with older traces', async function() {\n // Any trace captured before 121.0.6156.3 doesn't have the extra data to correct the timestamps.\n const events = await TraceLoader.rawEvents(this, 'web-dev.json.gz');\n for (const event of events) {\n TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event);\n TraceModel.Handlers.ModelHandlers.Screenshots.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.Meta.finalize();\n await TraceModel.Handlers.ModelHandlers.Screenshots.finalize();\n\n const syntheticScreenshotEvents = TraceModel.Handlers.ModelHandlers.Screenshots.data();\n const originalScreenshotEvents = events.filter(TraceModel.Types.TraceEvents.isTraceEventScreenshot);\n assert.strictEqual(syntheticScreenshotEvents.length, originalScreenshotEvents.length);\n\n for (const oEvent of originalScreenshotEvents) {\n assert.strictEqual(oEvent.id, '0x1'); // The ids here aren't the new frame sequence, but the hardcoded 1.\n }\n\n const msDifferences = getMsDifferences(syntheticScreenshotEvents, originalScreenshotEvents);\n // No adjustment made.\n assert.deepStrictEqual(msDifferences, [\n 0,\n 0,\n 0,\n 0,\n 0,\n ]);\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"ScreenshotsHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/ScreenshotsHandler.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {defaultTraceEvent} from '../../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Trace from '../trace.js';\n\ndescribe('ScreenshotsHandler', function() {\n const baseEvent = {\n ...defaultTraceEvent,\n name: 'Screenshot',\n // Ensure that the screenshots are held against the pid & tid values\n // that match the Browser process and CrBrowserMain in defaultTraceEvents.\n pid: Trace.Types.Events.ProcessID(8017),\n tid: Trace.Types.Events.ThreadID(775),\n ts: Trace.Types.Timing.MicroSeconds(0),\n args: {},\n cat: 'test',\n ph: Trace.Types.Events.Phase.OBJECT_SNAPSHOT,\n };\n\n let baseEvents: readonly Trace.Types.Events.Event[];\n\n beforeEach(async function() {\n // The screenshot handler requires the meta handler because it needs\n // to know the browser process and thread IDs. Here, then, we reset\n // and later we will pass events to the meta handler, otherwise the\n // screenshots handler will fail.\n Trace.Handlers.ModelHandlers.Meta.reset();\n Trace.Handlers.ModelHandlers.Meta.initialize();\n\n Trace.Handlers.ModelHandlers.Screenshots.reset();\n });\n\n describe('frames', () => {\n it('obtains them if present', async function() {\n const defaultTraceEvents = await TraceLoader.rawEvents(this, 'basic.json.gz');\n\n baseEvents = [\n ...defaultTraceEvents,\n {...baseEvent, ts: Trace.Types.Timing.MicroSeconds(100)},\n {...baseEvent, ts: Trace.Types.Timing.MicroSeconds(200)},\n ];\n Trace.Helpers.SyntheticEvents.SyntheticEventsManager.createAndActivate(baseEvents);\n\n for (const event of baseEvents) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n Trace.Handlers.ModelHandlers.Screenshots.handleEvent(event);\n }\n\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n await Trace.Handlers.ModelHandlers.Screenshots.finalize();\n\n const data = Trace.Handlers.ModelHandlers.Screenshots.data();\n assert.strictEqual(data.length, 2);\n });\n });\n\n describe('presentation timestamps', () => {\n function getMsDifferences(\n syntheticScreenshots: Trace.Types.Events.SyntheticScreenshot[],\n originalScreenshotEvents: Trace.Types.Events.Screenshot[]): number[] {\n return syntheticScreenshots.map((synEvent, i) => {\n const origEvent = originalScreenshotEvents.at(i) as Trace.Types.Events.Screenshot;\n const msDifference = (synEvent.ts - origEvent.ts) / 1000;\n return msDifference;\n });\n }\n it('are corrected if frame sequence number is present', async function() {\n // This trace was collected after https://crrev.com/c/4957973 landed.\n const events = await TraceLoader.rawEvents(this, 'about-blank-first.json.gz');\n for (const event of events) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n Trace.Handlers.ModelHandlers.Screenshots.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n await Trace.Handlers.ModelHandlers.Screenshots.finalize();\n\n const syntheticScreenshots = Trace.Handlers.ModelHandlers.Screenshots.data();\n const originalScreenshotEvents = events.filter(Trace.Types.Events.isScreenshot);\n assert.strictEqual(syntheticScreenshots.length, originalScreenshotEvents.length);\n\n for (const oEvent of originalScreenshotEvents) {\n assert.notStrictEqual(oEvent.id, '0x1'); // The id (frame sequence) shouldn't be the old default of 1.\n }\n\n const msDifferences = getMsDifferences(syntheticScreenshots, originalScreenshotEvents);\n // These values indicate all the screenshots true timings are a tad more to the left.\n assert.deepStrictEqual(msDifferences, [\n -13.079, -16.381, -12.503, -5.405, -14.108, -14.661, -11.944, -14.322, -3.532, -15.821, 0.254,\n -32.22, -15.156, -13.219, -14.464, -16.135, -16.501, -33.165, -15.71, -32.39, -32.445, -30.512,\n ]);\n });\n\n it('remain the same with older traces', async function() {\n // Any trace captured before 121.0.6156.3 doesn't have the extra data to correct the timestamps.\n const events = await TraceLoader.rawEvents(this, 'web-dev.json.gz');\n for (const event of events) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n Trace.Handlers.ModelHandlers.Screenshots.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n await Trace.Handlers.ModelHandlers.Screenshots.finalize();\n\n const syntheticScreenshots = Trace.Handlers.ModelHandlers.Screenshots.data();\n const originalScreenshotEvents = events.filter(Trace.Types.Events.isScreenshot);\n assert.strictEqual(syntheticScreenshots.length, originalScreenshotEvents.length);\n\n for (const oEvent of originalScreenshotEvents) {\n assert.strictEqual(oEvent.id, '0x1'); // The ids here aren't the new frame sequence, but the hardcoded 1.\n }\n\n const msDifferences = getMsDifferences(syntheticScreenshots, originalScreenshotEvents);\n // No adjustment made.\n assert.deepStrictEqual(msDifferences, [\n 0,\n 0,\n 0,\n 0,\n 0,\n ]);\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/SelectorStatsHandler.d.ts b/public/models/trace/handlers/SelectorStatsHandler.d.ts index 271e46562..777c650c2 100644 --- a/public/models/trace/handlers/SelectorStatsHandler.d.ts +++ b/public/models/trace/handlers/SelectorStatsHandler.d.ts @@ -1,9 +1,9 @@ import * as Types from '../types/types.js'; export declare function reset(): void; -export declare function handleEvent(event: Types.TraceEvents.TraceEventData): void; +export declare function handleEvent(event: Types.Events.Event): void; export interface SelectorStatsData { - dataForUpdateLayoutEvent: Map; } export declare function data(): SelectorStatsData; diff --git a/public/models/trace/handlers/SelectorStatsHandler.js b/public/models/trace/handlers/SelectorStatsHandler.js index 09d6e06e8..cb729326f 100644 --- a/public/models/trace/handlers/SelectorStatsHandler.js +++ b/public/models/trace/handlers/SelectorStatsHandler.js @@ -9,13 +9,13 @@ export function reset() { selectorDataForUpdateLayoutTree.clear(); } export function handleEvent(event) { - if (Types.TraceEvents.isTraceEventSelectorStats(event) && lastUpdateLayoutTreeEvent && event.args.selector_stats) { + if (Types.Events.isSelectorStats(event) && lastUpdateLayoutTreeEvent && event.args.selector_stats) { selectorDataForUpdateLayoutTree.set(lastUpdateLayoutTreeEvent, { timings: event.args.selector_stats.selector_timings, }); return; } - if (Types.TraceEvents.isTraceEventUpdateLayoutTree(event)) { + if (Types.Events.isUpdateLayoutTree(event)) { lastUpdateLayoutTreeEvent = event; return; } diff --git a/public/models/trace/handlers/SelectorStatsHandler.js.map b/public/models/trace/handlers/SelectorStatsHandler.js.map index 7c4bed644..4cb8e7b64 100644 --- a/public/models/trace/handlers/SelectorStatsHandler.js.map +++ b/public/models/trace/handlers/SelectorStatsHandler.js.map @@ -1 +1 @@ -{"version":3,"file":"SelectorStatsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/SelectorStatsHandler.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAE3C,IAAI,yBAAyB,GAAsD,IAAI,CAAC;AAExF,MAAM,+BAA+B,GAAG,IAAI,GAAG,EAE3C,CAAC;AAEL,MAAM,UAAU,KAAK;IACnB,yBAAyB,GAAG,IAAI,CAAC;IACjC,+BAA+B,CAAC,KAAK,EAAE,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAuC;IACjE,IAAI,KAAK,CAAC,WAAW,CAAC,yBAAyB,CAAC,KAAK,CAAC,IAAI,yBAAyB,IAAI,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;QACjH,+BAA+B,CAAC,GAAG,CAAC,yBAAyB,EAAE;YAC7D,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,gBAAgB;SACpD,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,WAAW,CAAC,4BAA4B,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1D,yBAAyB,GAAG,KAAK,CAAC;QAClC,OAAO;IACT,CAAC;AACH,CAAC;AAQD,MAAM,UAAU,IAAI;IAClB,OAAO;QACL,wBAAwB,EAAE,+BAA+B;KAC1D,CAAC;AACJ,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Types from '../types/types.js';\n\nlet lastUpdateLayoutTreeEvent: Types.TraceEvents.TraceEventUpdateLayoutTree|null = null;\n\nconst selectorDataForUpdateLayoutTree = new Map();\n\nexport function reset(): void {\n lastUpdateLayoutTreeEvent = null;\n selectorDataForUpdateLayoutTree.clear();\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (Types.TraceEvents.isTraceEventSelectorStats(event) && lastUpdateLayoutTreeEvent && event.args.selector_stats) {\n selectorDataForUpdateLayoutTree.set(lastUpdateLayoutTreeEvent, {\n timings: event.args.selector_stats.selector_timings,\n });\n return;\n }\n\n if (Types.TraceEvents.isTraceEventUpdateLayoutTree(event)) {\n lastUpdateLayoutTreeEvent = event;\n return;\n }\n}\n\nexport interface SelectorStatsData {\n dataForUpdateLayoutEvent: Map;\n}\n\nexport function data(): SelectorStatsData {\n return {\n dataForUpdateLayoutEvent: selectorDataForUpdateLayoutTree,\n };\n}\n"]} \ No newline at end of file +{"version":3,"file":"SelectorStatsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/SelectorStatsHandler.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAE3C,IAAI,yBAAyB,GAAuC,IAAI,CAAC;AAEzE,MAAM,+BAA+B,GAAG,IAAI,GAAG,EAE3C,CAAC;AAEL,MAAM,UAAU,KAAK;IACnB,yBAAyB,GAAG,IAAI,CAAC;IACjC,+BAA+B,CAAC,KAAK,EAAE,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAyB;IACnD,IAAI,KAAK,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,yBAAyB,IAAI,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;QAClG,+BAA+B,CAAC,GAAG,CAAC,yBAAyB,EAAE;YAC7D,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,gBAAgB;SACpD,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC3C,yBAAyB,GAAG,KAAK,CAAC;QAClC,OAAO;IACT,CAAC;AACH,CAAC;AAQD,MAAM,UAAU,IAAI;IAClB,OAAO;QACL,wBAAwB,EAAE,+BAA+B;KAC1D,CAAC;AACJ,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Types from '../types/types.js';\n\nlet lastUpdateLayoutTreeEvent: Types.Events.UpdateLayoutTree|null = null;\n\nconst selectorDataForUpdateLayoutTree = new Map();\n\nexport function reset(): void {\n lastUpdateLayoutTreeEvent = null;\n selectorDataForUpdateLayoutTree.clear();\n}\n\nexport function handleEvent(event: Types.Events.Event): void {\n if (Types.Events.isSelectorStats(event) && lastUpdateLayoutTreeEvent && event.args.selector_stats) {\n selectorDataForUpdateLayoutTree.set(lastUpdateLayoutTreeEvent, {\n timings: event.args.selector_stats.selector_timings,\n });\n return;\n }\n\n if (Types.Events.isUpdateLayoutTree(event)) {\n lastUpdateLayoutTreeEvent = event;\n return;\n }\n}\n\nexport interface SelectorStatsData {\n dataForUpdateLayoutEvent: Map;\n}\n\nexport function data(): SelectorStatsData {\n return {\n dataForUpdateLayoutEvent: selectorDataForUpdateLayoutTree,\n };\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/SelectorStatsHandler.test.js b/public/models/trace/handlers/SelectorStatsHandler.test.js index c2e9c190c..9fddb44a0 100644 --- a/public/models/trace/handlers/SelectorStatsHandler.test.js +++ b/public/models/trace/handlers/SelectorStatsHandler.test.js @@ -2,15 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import { TraceLoader } from '../../../testing/TraceLoader.js'; -import * as TraceEngine from '../trace.js'; +import * as Trace from '../trace.js'; describe('SelectorStatsHandler', () => { it('associates timings and stats with each UpdateLayoutEvent', async function () { - TraceEngine.Handlers.ModelHandlers.SelectorStats.reset(); + Trace.Handlers.ModelHandlers.SelectorStats.reset(); const events = await TraceLoader.rawEvents(this, 'selector-stats.json.gz'); for (const event of events) { - TraceEngine.Handlers.ModelHandlers.SelectorStats.handleEvent(event); + Trace.Handlers.ModelHandlers.SelectorStats.handleEvent(event); } - const data = TraceEngine.Handlers.ModelHandlers.SelectorStats.data(); + const data = Trace.Handlers.ModelHandlers.SelectorStats.data(); // There are 10 UpdateLayoutTree events that we expect to find // SelectorStats for. assert.strictEqual(data.dataForUpdateLayoutEvent.size, 10); @@ -20,10 +20,10 @@ describe('SelectorStatsHandler', () => { // previous UpdateLayoutTreeEvent const targetTimeStamp = 400015719531; const updateLayoutEvent = events.find(event => { - return TraceEngine.Types.TraceEvents.isTraceEventUpdateLayoutTree(event) && event.ts === targetTimeStamp; + return Trace.Types.Events.isUpdateLayoutTree(event) && event.ts === targetTimeStamp; }); assert.isOk(updateLayoutEvent); - if (!TraceEngine.Types.TraceEvents.isTraceEventUpdateLayoutTree(updateLayoutEvent)) { + if (!Trace.Types.Events.isUpdateLayoutTree(updateLayoutEvent)) { assert.fail('Event was of the wrong type.'); } const selectorInfo = data.dataForUpdateLayoutEvent.get(updateLayoutEvent); diff --git a/public/models/trace/handlers/SelectorStatsHandler.test.js.map b/public/models/trace/handlers/SelectorStatsHandler.test.js.map index bd97fc570..8b2f6747b 100644 --- a/public/models/trace/handlers/SelectorStatsHandler.test.js.map +++ b/public/models/trace/handlers/SelectorStatsHandler.test.js.map @@ -1 +1 @@ -{"version":3,"file":"SelectorStatsHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/SelectorStatsHandler.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,EAAC,WAAW,EAAC,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,WAAW,MAAM,aAAa,CAAC;AAE3C,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,0DAA0D,EAAE,KAAK;QAClE,WAAW,CAAC,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QAEzD,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,IAAI,EAAE,wBAAwB,CAAC,CAAC;QAC3E,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,WAAW,CAAC,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACtE,CAAC;QACD,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;QAErE,8DAA8D;QAC9D,qBAAqB;QACrB,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,wBAAwB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAE3D,+DAA+D;QAC/D,2EAA2E;QAC3E,sEAAsE;QACtE,iCAAiC;QACjC,MAAM,eAAe,GAAG,YAAY,CAAC;QACrC,MAAM,iBAAiB,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;YAC5C,OAAO,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC,4BAA4B,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,EAAE,KAAK,eAAe,CAAC;QAC3G,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAE/B,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC,4BAA4B,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACnF,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAC9C,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QAC1E,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC1B,mDAAmD;QACnD,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as TraceEngine from '../trace.js';\n\ndescribe('SelectorStatsHandler', () => {\n it('associates timings and stats with each UpdateLayoutEvent', async function() {\n TraceEngine.Handlers.ModelHandlers.SelectorStats.reset();\n\n const events = await TraceLoader.rawEvents(this, 'selector-stats.json.gz');\n for (const event of events) {\n TraceEngine.Handlers.ModelHandlers.SelectorStats.handleEvent(event);\n }\n const data = TraceEngine.Handlers.ModelHandlers.SelectorStats.data();\n\n // There are 10 UpdateLayoutTree events that we expect to find\n // SelectorStats for.\n assert.strictEqual(data.dataForUpdateLayoutEvent.size, 10);\n\n // We need the first updateLayoutEvent that happened before the\n // SelectorStats. This timestamp was found by looking through the trace and\n // finding the first SelectorStats event, and then finding the closest\n // previous UpdateLayoutTreeEvent\n const targetTimeStamp = 400015719531;\n const updateLayoutEvent = events.find(event => {\n return TraceEngine.Types.TraceEvents.isTraceEventUpdateLayoutTree(event) && event.ts === targetTimeStamp;\n });\n assert.isOk(updateLayoutEvent);\n\n if (!TraceEngine.Types.TraceEvents.isTraceEventUpdateLayoutTree(updateLayoutEvent)) {\n assert.fail('Event was of the wrong type.');\n }\n\n const selectorInfo = data.dataForUpdateLayoutEvent.get(updateLayoutEvent);\n assert.isOk(selectorInfo);\n // Ensure that we dumped the timings into the event\n assert.lengthOf(selectorInfo.timings, 325);\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"SelectorStatsHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/SelectorStatsHandler.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,EAAC,WAAW,EAAC,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,KAAK,MAAM,aAAa,CAAC;AAErC,QAAQ,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACpC,EAAE,CAAC,0DAA0D,EAAE,KAAK;QAClE,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QAEnD,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,IAAI,EAAE,wBAAwB,CAAC,CAAC;QAC3E,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAChE,CAAC;QACD,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;QAE/D,8DAA8D;QAC9D,qBAAqB;QACrB,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,wBAAwB,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAE3D,+DAA+D;QAC/D,2EAA2E;QAC3E,sEAAsE;QACtE,iCAAiC;QACjC,MAAM,eAAe,GAAG,YAAY,CAAC;QACrC,MAAM,iBAAiB,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;YAC5C,OAAO,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,EAAE,KAAK,eAAe,CAAC;QACtF,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAE/B,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,iBAAiB,CAAC,EAAE,CAAC;YAC9D,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAC9C,CAAC;QAED,MAAM,YAAY,GAAG,IAAI,CAAC,wBAAwB,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QAC1E,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC1B,mDAAmD;QACnD,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Trace from '../trace.js';\n\ndescribe('SelectorStatsHandler', () => {\n it('associates timings and stats with each UpdateLayoutEvent', async function() {\n Trace.Handlers.ModelHandlers.SelectorStats.reset();\n\n const events = await TraceLoader.rawEvents(this, 'selector-stats.json.gz');\n for (const event of events) {\n Trace.Handlers.ModelHandlers.SelectorStats.handleEvent(event);\n }\n const data = Trace.Handlers.ModelHandlers.SelectorStats.data();\n\n // There are 10 UpdateLayoutTree events that we expect to find\n // SelectorStats for.\n assert.strictEqual(data.dataForUpdateLayoutEvent.size, 10);\n\n // We need the first updateLayoutEvent that happened before the\n // SelectorStats. This timestamp was found by looking through the trace and\n // finding the first SelectorStats event, and then finding the closest\n // previous UpdateLayoutTreeEvent\n const targetTimeStamp = 400015719531;\n const updateLayoutEvent = events.find(event => {\n return Trace.Types.Events.isUpdateLayoutTree(event) && event.ts === targetTimeStamp;\n });\n assert.isOk(updateLayoutEvent);\n\n if (!Trace.Types.Events.isUpdateLayoutTree(updateLayoutEvent)) {\n assert.fail('Event was of the wrong type.');\n }\n\n const selectorInfo = data.dataForUpdateLayoutEvent.get(updateLayoutEvent);\n assert.isOk(selectorInfo);\n // Ensure that we dumped the timings into the event\n assert.lengthOf(selectorInfo.timings, 325);\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/ServerTimingsHandler.d.ts b/public/models/trace/handlers/ServerTimingsHandler.d.ts index 581a2d1cd..39ba559ee 100644 --- a/public/models/trace/handlers/ServerTimingsHandler.d.ts +++ b/public/models/trace/handlers/ServerTimingsHandler.d.ts @@ -1,10 +1,10 @@ import * as Types from '../types/types.js'; -import { type TraceEventHandlerName } from './types.js'; +import { type HandlerName } from './types.js'; export declare function reset(): void; export declare function initialize(): void; -export declare function handleEvent(_event: Types.TraceEvents.TraceEventData): void; +export declare function handleEvent(_event: Types.Events.Event): void; export declare function finalize(): Promise; export declare function data(): { - serverTimings: Types.TraceEvents.SyntheticServerTiming[]; + serverTimings: Types.Events.SyntheticServerTiming[]; }; -export declare function deps(): TraceEventHandlerName[]; +export declare function deps(): HandlerName[]; diff --git a/public/models/trace/handlers/ServerTimingsHandler.js b/public/models/trace/handlers/ServerTimingsHandler.js index 991df6bf5..973efb6c3 100644 --- a/public/models/trace/handlers/ServerTimingsHandler.js +++ b/public/models/trace/handlers/ServerTimingsHandler.js @@ -88,9 +88,9 @@ function createSyntheticServerTiming(request, serverStart, serverEnd, timingsInR const serverTiming = Helpers.SyntheticEvents.SyntheticEventsManager.registerServerTiming({ rawSourceEvent: request.rawSourceEvent, name: timing.metric, - ph: "X" /* Types.TraceEvents.Phase.COMPLETE */, - pid: Types.TraceEvents.ProcessID(0), - tid: Types.TraceEvents.ThreadID(0), + ph: "X" /* Types.Events.Phase.COMPLETE */, + pid: Types.Events.ProcessID(0), + tid: Types.Events.ThreadID(0), ts: Types.Timing.MicroSeconds(convertedTimestamp), dur: Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(timing.value)), cat: 'devtools.server-timing', diff --git a/public/models/trace/handlers/ServerTimingsHandler.js.map b/public/models/trace/handlers/ServerTimingsHandler.js.map index 9ab887427..ab8d8db88 100644 --- a/public/models/trace/handlers/ServerTimingsHandler.js.map +++ b/public/models/trace/handlers/ServerTimingsHandler.js.map @@ -1 +1 @@ -{"version":3,"file":"ServerTimingsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/ServerTimingsHandler.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,QAAQ,MAAM,oCAAoC,CAAC;AAC/D,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAE3C,OAAO,EAAC,IAAI,IAAI,WAAW,EAAC,MAAM,6BAA6B,CAAC;AAGhE,MAAM,aAAa,GAA8C,EAAE,CAAC;AAEpE,IAAI,YAAY,qCAA6B,CAAC;AAE9C,MAAM,UAAU,KAAK;IACnB,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC;IACzB,YAAY,qCAA6B,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,YAAY,mCAA2B,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAwC;IAClE,gFAAgF;AAClF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,IAAI,YAAY,qCAA6B,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IACD,oBAAoB,EAAE,CAAC;IACvB,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,aAAa,CAAC,CAAC;IACpD,YAAY,iCAAyB,CAAC;AACxC,CAAC;AAED,MAAM,0BAA0B,GAAG,gBAAgB,CAAC;AACpD,MAAM,wBAAwB,GAAG,cAAc,CAAC;AAEhD;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAS,oBAAoB;IAC3B,KAAK,MAAM,YAAY,IAAI,WAAW,EAAE,CAAC,MAAM,EAAE,CAAC;QAChD,IAAI,gBAAgB,GAA8C,IAAI,CAAC;QACvE,KAAK,MAAM,MAAM,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;YAC5D,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACnD,kEAAkE;YAClE,8DAA8D;YAC9D,6DAA6D;YAC7D,+DAA+D;YAC/D,IAAI,UAAU,KAAK,eAAe,IAAI,UAAU,KAAK,oBAAoB,EAAE,CAAC;gBAC1E,MAAM,CAAC,IAAI,GAAG,eAAe,CAAC;gBAC9B,gBAAgB,GAAG,QAAQ,CAAC,YAAY,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;gBAC7E,SAAS;YACX,CAAC;QACH,CAAC;QACD,MAAM,WAAW,GAAG,gBAAgB,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,0BAA0B,CAAC,EAAE,KAAK,CAAC;QAC1G,MAAM,SAAS,GAAG,gBAAgB,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,KAAK,wBAAwB,CAAC,EAAE,KAAK,CAAC;QACtG,IAAI,CAAC,WAAW,IAAI,CAAC,SAAS,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACpD,SAAS;QACX,CAAC;QAED,MAAM,kBAAkB,GAAG,WAAW,GAAG,KAAK,CAAC;QAC/C,MAAM,gBAAgB,GAAG,SAAS,GAAG,KAAK,CAAC;QAC3C,aAAa,CAAC,IAAI,CACd,GAAG,2BAA2B,CAAC,YAAY,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,gBAAgB,CAAC,CAAC,CAAC;IAC5G,CAAC;AACH,CAAC;AACD,SAAS,2BAA2B,CAChC,OAAkD,EAAE,WAAmB,EAAE,SAAiB,EAC1F,gBAAsD;IACxD,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC;IAClE,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;IAC9G,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,WAAW,GAAG,WAAW,GAAG,SAAS,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;IACtG,MAAM,sBAAsB,GAA8C,EAAE,CAAC;IAC7E,KAAK,MAAM,MAAM,IAAI,gBAAgB,EAAE,CAAC;QACtC,IAAI,MAAM,CAAC,MAAM,KAAK,0BAA0B,IAAI,MAAM,CAAC,MAAM,KAAK,wBAAwB,EAAE,CAAC;YAC/F,SAAS;QACX,CAAC;QACD,IAAI,MAAM,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YAC1B,SAAS;QACX,CAAC;QACD,MAAM,kBAAkB,GACpB,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,GAAG,MAAM,CAAC;QAChG,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC;QAEhC,MAAM,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC,sBAAsB,CAAC,oBAAoB,CAAC;YACvF,cAAc,EAAE,OAAO,CAAC,cAAc;YACtC,IAAI,EAAE,MAAM,CAAC,MAAM;YACnB,EAAE,4CAAkC;YACpC,GAAG,EAAE,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC;YACnC,GAAG,EAAE,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;YAClC,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,kBAAkB,CAAC;YACjD,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvF,GAAG,EAAE,wBAAwB;YAC7B,IAAI,EAAE,EAAC,IAAI,EAAE,EAAC,IAAI,EAAE,MAAM,CAAC,WAAW,IAAI,SAAS,EAAE,MAAM,EAAC,EAAC;SAC9D,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,sBAAsB,EAAE,CAAC;YAC9C,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,sBAAsB,GAAG,EAAE,CAAC;QAChD,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC5D,sBAAsB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,sBAAsB,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,IAAI;IAClB,IAAI,YAAY,mCAA2B,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC,CAAC;IAC5D,CAAC;IAED,OAAO;QACL,aAAa;KACd,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAC7B,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {data as networkData} from './NetworkRequestsHandler.js';\nimport {HandlerState, type TraceEventHandlerName} from './types.js';\n\nconst serverTimings: Types.TraceEvents.SyntheticServerTiming[] = [];\n\nlet handlerState = HandlerState.UNINITIALIZED;\n\nexport function reset(): void {\n serverTimings.length = 0;\n handlerState = HandlerState.UNINITIALIZED;\n}\n\nexport function initialize(): void {\n handlerState = HandlerState.INITIALIZED;\n}\n\nexport function handleEvent(_event: Types.TraceEvents.TraceEventData): void {\n // Implementation not needed because data is sourced from NetworkRequestsHandler\n}\n\nexport async function finalize(): Promise {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Server Timings handler is not initialized');\n }\n extractServerTimings();\n Helpers.Trace.sortTraceEventsInPlace(serverTimings);\n handlerState = HandlerState.FINALIZED;\n}\n\nconst RESPONSE_START_METRIC_NAME = 'response-start';\nconst RESPONSE_END_METRIC_NAME = 'response-end';\n\n/**\n * Creates synthetic trace events based on server timings in the\n * `Server-Timing` response header. A non-standard `start` param is\n * expected on each metric that contains the start time of the timing\n * based on the server clock.\n *\n * In order to estimate the offset between the server and client clocks,\n * we look for the non-standard `response-start` and `response-end`\n * metrics in the response header, which contain the start and end\n * timestamps of the network request processing in the server. We\n * compare these with the times the request was sent and received in the\n * client to estimate the offset between the client and the server\n * clocks.\n *\n * With this offset estimation at hand, we can map timestamps from the\n * server clock to the tracing clock and locate the timings in the\n * performance timeline.\n */\nfunction extractServerTimings(): void {\n for (const networkEvent of networkData().byTime) {\n let timingsInRequest: Platform.ServerTiming.ServerTiming[]|null = null;\n for (const header of networkEvent.args.data.responseHeaders) {\n const headerName = header.name.toLocaleLowerCase();\n // Some popular hosting providers like vercel or render get rid of\n // Server-Timing headers added by users, so as a workaround we\n // also support server timing headers with the `-test` suffix\n // while this feature is experimental, to enable easier trials.\n if (headerName === 'server-timing' || headerName === 'server-timing-test') {\n header.name = 'server-timing';\n timingsInRequest = Platform.ServerTiming.ServerTiming.parseHeaders([header]);\n continue;\n }\n }\n const serverStart = timingsInRequest?.find(timing => timing.metric === RESPONSE_START_METRIC_NAME)?.start;\n const serverEnd = timingsInRequest?.find(timing => timing.metric === RESPONSE_END_METRIC_NAME)?.start;\n if (!serverStart || !serverEnd || !timingsInRequest) {\n continue;\n }\n\n const serverStartInMicro = serverStart * 1_000;\n const serverEndInMicro = serverEnd * 1_000;\n serverTimings.push(\n ...createSyntheticServerTiming(networkEvent, serverStartInMicro, serverEndInMicro, timingsInRequest));\n }\n}\nfunction createSyntheticServerTiming(\n request: Types.TraceEvents.SyntheticNetworkRequest, serverStart: number, serverEnd: number,\n timingsInRequest: Platform.ServerTiming.ServerTiming[]): Types.TraceEvents.SyntheticServerTiming[] {\n const clientStart = request.args.data.syntheticData.sendStartTime;\n const clientEndTime = request.args.data.syntheticData.sendStartTime + request.args.data.syntheticData.waiting;\n const offset = Types.Timing.MicroSeconds((serverStart - clientStart + serverEnd - clientEndTime) / 2);\n const convertedServerTimings: Types.TraceEvents.SyntheticServerTiming[] = [];\n for (const timing of timingsInRequest) {\n if (timing.metric === RESPONSE_START_METRIC_NAME || timing.metric === RESPONSE_END_METRIC_NAME) {\n continue;\n }\n if (timing.start === null) {\n continue;\n }\n const convertedTimestamp =\n Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(timing.start)) - offset;\n const parsedUrl = new URL(request.args.data.url);\n const origin = parsedUrl.origin;\n\n const serverTiming = Helpers.SyntheticEvents.SyntheticEventsManager.registerServerTiming({\n rawSourceEvent: request.rawSourceEvent,\n name: timing.metric,\n ph: Types.TraceEvents.Phase.COMPLETE,\n pid: Types.TraceEvents.ProcessID(0),\n tid: Types.TraceEvents.ThreadID(0),\n ts: Types.Timing.MicroSeconds(convertedTimestamp),\n dur: Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(timing.value)),\n cat: 'devtools.server-timing',\n args: {data: {desc: timing.description || undefined, origin}},\n });\n\n if (!request.args.data.syntheticServerTimings) {\n request.args.data.syntheticServerTimings = [];\n }\n request.args.data.syntheticServerTimings.push(serverTiming);\n convertedServerTimings.push(serverTiming);\n }\n return convertedServerTimings;\n}\n\nexport function data(): {serverTimings: Types.TraceEvents.SyntheticServerTiming[]} {\n if (handlerState !== HandlerState.FINALIZED) {\n throw new Error('Server Timing handler is not finalized');\n }\n\n return {\n serverTimings,\n };\n}\n\nexport function deps(): TraceEventHandlerName[] {\n return ['NetworkRequests'];\n}\n"]} \ No newline at end of file +{"version":3,"file":"ServerTimingsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/ServerTimingsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {data as networkData} from './NetworkRequestsHandler.js';\nimport {type HandlerName, HandlerState} from './types.js';\n\nconst serverTimings: Types.Events.SyntheticServerTiming[] = [];\n\nlet handlerState = HandlerState.UNINITIALIZED;\n\nexport function reset(): void {\n serverTimings.length = 0;\n handlerState = HandlerState.UNINITIALIZED;\n}\n\nexport function initialize(): void {\n handlerState = HandlerState.INITIALIZED;\n}\n\nexport function handleEvent(_event: Types.Events.Event): void {\n // Implementation not needed because data is sourced from NetworkRequestsHandler\n}\n\nexport async function finalize(): Promise {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Server Timings handler is not initialized');\n }\n extractServerTimings();\n Helpers.Trace.sortTraceEventsInPlace(serverTimings);\n handlerState = HandlerState.FINALIZED;\n}\n\nconst RESPONSE_START_METRIC_NAME = 'response-start';\nconst RESPONSE_END_METRIC_NAME = 'response-end';\n\n/**\n * Creates synthetic trace events based on server timings in the\n * `Server-Timing` response header. A non-standard `start` param is\n * expected on each metric that contains the start time of the timing\n * based on the server clock.\n *\n * In order to estimate the offset between the server and client clocks,\n * we look for the non-standard `response-start` and `response-end`\n * metrics in the response header, which contain the start and end\n * timestamps of the network request processing in the server. We\n * compare these with the times the request was sent and received in the\n * client to estimate the offset between the client and the server\n * clocks.\n *\n * With this offset estimation at hand, we can map timestamps from the\n * server clock to the tracing clock and locate the timings in the\n * performance timeline.\n */\nfunction extractServerTimings(): void {\n for (const networkEvent of networkData().byTime) {\n let timingsInRequest: Platform.ServerTiming.ServerTiming[]|null = null;\n for (const header of networkEvent.args.data.responseHeaders) {\n const headerName = header.name.toLocaleLowerCase();\n // Some popular hosting providers like vercel or render get rid of\n // Server-Timing headers added by users, so as a workaround we\n // also support server timing headers with the `-test` suffix\n // while this feature is experimental, to enable easier trials.\n if (headerName === 'server-timing' || headerName === 'server-timing-test') {\n header.name = 'server-timing';\n timingsInRequest = Platform.ServerTiming.ServerTiming.parseHeaders([header]);\n continue;\n }\n }\n const serverStart = timingsInRequest?.find(timing => timing.metric === RESPONSE_START_METRIC_NAME)?.start;\n const serverEnd = timingsInRequest?.find(timing => timing.metric === RESPONSE_END_METRIC_NAME)?.start;\n if (!serverStart || !serverEnd || !timingsInRequest) {\n continue;\n }\n\n const serverStartInMicro = serverStart * 1_000;\n const serverEndInMicro = serverEnd * 1_000;\n serverTimings.push(\n ...createSyntheticServerTiming(networkEvent, serverStartInMicro, serverEndInMicro, timingsInRequest));\n }\n}\nfunction createSyntheticServerTiming(\n request: Types.Events.SyntheticNetworkRequest, serverStart: number, serverEnd: number,\n timingsInRequest: Platform.ServerTiming.ServerTiming[]): Types.Events.SyntheticServerTiming[] {\n const clientStart = request.args.data.syntheticData.sendStartTime;\n const clientEndTime = request.args.data.syntheticData.sendStartTime + request.args.data.syntheticData.waiting;\n const offset = Types.Timing.MicroSeconds((serverStart - clientStart + serverEnd - clientEndTime) / 2);\n const convertedServerTimings: Types.Events.SyntheticServerTiming[] = [];\n for (const timing of timingsInRequest) {\n if (timing.metric === RESPONSE_START_METRIC_NAME || timing.metric === RESPONSE_END_METRIC_NAME) {\n continue;\n }\n if (timing.start === null) {\n continue;\n }\n const convertedTimestamp =\n Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(timing.start)) - offset;\n const parsedUrl = new URL(request.args.data.url);\n const origin = parsedUrl.origin;\n\n const serverTiming = Helpers.SyntheticEvents.SyntheticEventsManager.registerServerTiming({\n rawSourceEvent: request.rawSourceEvent,\n name: timing.metric,\n ph: Types.Events.Phase.COMPLETE,\n pid: Types.Events.ProcessID(0),\n tid: Types.Events.ThreadID(0),\n ts: Types.Timing.MicroSeconds(convertedTimestamp),\n dur: Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(timing.value)),\n cat: 'devtools.server-timing',\n args: {data: {desc: timing.description || undefined, origin}},\n });\n\n if (!request.args.data.syntheticServerTimings) {\n request.args.data.syntheticServerTimings = [];\n }\n request.args.data.syntheticServerTimings.push(serverTiming);\n convertedServerTimings.push(serverTiming);\n }\n return convertedServerTimings;\n}\n\nexport function data(): {serverTimings: Types.Events.SyntheticServerTiming[]} {\n if (handlerState !== HandlerState.FINALIZED) {\n throw new Error('Server Timing handler is not finalized');\n }\n\n return {\n serverTimings,\n };\n}\n\nexport function deps(): HandlerName[] {\n return ['NetworkRequests'];\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/ServerTimingsHandler.test.js b/public/models/trace/handlers/ServerTimingsHandler.test.js index bb39b176d..e86010b94 100644 --- a/public/models/trace/handlers/ServerTimingsHandler.test.js +++ b/public/models/trace/handlers/ServerTimingsHandler.test.js @@ -3,31 +3,31 @@ // found in the LICENSE file. import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; -import * as TraceEngine from '../trace.js'; +import * as Trace from '../trace.js'; describeWithEnvironment('ServerTimingsHandler', () => { it('extracts server timings from network request trace events', async function () { - const traceEngineData = await TraceLoader.traceEngine(this, 'server-timings.json.gz'); - const events = traceEngineData.traceData.ServerTimings.serverTimings; + const parsedTrace = await TraceLoader.traceEngine(this, 'server-timings.json.gz'); + const events = parsedTrace.parsedTrace.ServerTimings.serverTimings; const timingData = events.map(({ name, dur, ts, args }) => ({ name, dur, ts, desc: args.data.desc, origin: args.data.origin })); assert.deepEqual(timingData, [ { - dur: TraceEngine.Types.Timing.MicroSeconds(1004293.2819999987), + dur: Trace.Types.Timing.MicroSeconds(1004293.2819999987), name: 'Topleveltask1', - ts: TraceEngine.Types.Timing.MicroSeconds(80542636965.7475), + ts: Trace.Types.Timing.MicroSeconds(80542636965.7475), desc: 'Description of top level task 1', origin: 'https://node-server-tan.vercel.app', }, { - dur: TraceEngine.Types.Timing.MicroSeconds(904293.2819999987), + dur: Trace.Types.Timing.MicroSeconds(904293.2819999987), name: 'Secondleveltask1', - ts: TraceEngine.Types.Timing.MicroSeconds(80542686965.7475), + ts: Trace.Types.Timing.MicroSeconds(80542686965.7475), desc: 'Description of second level task 1', origin: 'https://node-server-tan.vercel.app', }, { - dur: TraceEngine.Types.Timing.MicroSeconds(1000092.5859999988), + dur: Trace.Types.Timing.MicroSeconds(1000092.5859999988), name: 'Topleveltask2', - ts: TraceEngine.Types.Timing.MicroSeconds(80543641261.0185), + ts: Trace.Types.Timing.MicroSeconds(80543641261.0185), desc: undefined, origin: 'https://node-server-tan.vercel.app', }, diff --git a/public/models/trace/handlers/ServerTimingsHandler.test.js.map b/public/models/trace/handlers/ServerTimingsHandler.test.js.map index f1abdec89..57ed01a1a 100644 --- a/public/models/trace/handlers/ServerTimingsHandler.test.js.map +++ b/public/models/trace/handlers/ServerTimingsHandler.test.js.map @@ -1 +1 @@ -{"version":3,"file":"ServerTimingsHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/ServerTimingsHandler.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,EAAC,uBAAuB,EAAC,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EAAC,WAAW,EAAC,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,WAAW,MAAM,aAAa,CAAC;AAE3C,uBAAuB,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACnD,EAAE,CAAC,2DAA2D,EAAE,KAAK;QACnE,MAAM,eAAe,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,wBAAwB,CAAC,CAAC;QACtF,MAAM,MAAM,GAAG,eAAe,CAAC,SAAS,CAAC,aAAa,CAAC,aAAa,CAAC;QACrE,MAAM,UAAU,GACZ,MAAM,CAAC,GAAG,CAAC,CAAC,EAAC,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,EAAC,EAAE,EAAE,CAAC,CAAC,EAAC,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAC,CAAC,CAAC,CAAC;QAC7G,MAAM,CAAC,SAAS,CAAC,UAAU,EAAE;YAC3B;gBACE,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,kBAAkB,CAAC;gBAC9D,IAAI,EAAE,eAAe;gBACrB,EAAE,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,gBAAgB,CAAC;gBAC3D,IAAI,EAAE,iCAAiC;gBACvC,MAAM,EAAE,oCAAoC;aAC7C;YACD;gBACE,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,iBAAiB,CAAC;gBAC7D,IAAI,EAAE,kBAAkB;gBACxB,EAAE,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,gBAAgB,CAAC;gBAC3D,IAAI,EAAE,oCAAoC;gBAC1C,MAAM,EAAE,oCAAoC;aAC7C;YACD;gBACE,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,kBAAkB,CAAC;gBAC9D,IAAI,EAAE,eAAe;gBACrB,EAAE,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,gBAAgB,CAAC;gBAC3D,IAAI,EAAE,SAAS;gBACf,MAAM,EAAE,oCAAoC;aAC7C;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as TraceEngine from '../trace.js';\n\ndescribeWithEnvironment('ServerTimingsHandler', () => {\n it('extracts server timings from network request trace events', async function() {\n const traceEngineData = await TraceLoader.traceEngine(this, 'server-timings.json.gz');\n const events = traceEngineData.traceData.ServerTimings.serverTimings;\n const timingData =\n events.map(({name, dur, ts, args}) => ({name, dur, ts, desc: args.data.desc, origin: args.data.origin}));\n assert.deepEqual(timingData, [\n {\n dur: TraceEngine.Types.Timing.MicroSeconds(1004293.2819999987),\n name: 'Topleveltask1',\n ts: TraceEngine.Types.Timing.MicroSeconds(80542636965.7475),\n desc: 'Description of top level task 1',\n origin: 'https://node-server-tan.vercel.app',\n },\n {\n dur: TraceEngine.Types.Timing.MicroSeconds(904293.2819999987),\n name: 'Secondleveltask1',\n ts: TraceEngine.Types.Timing.MicroSeconds(80542686965.7475),\n desc: 'Description of second level task 1',\n origin: 'https://node-server-tan.vercel.app',\n },\n {\n dur: TraceEngine.Types.Timing.MicroSeconds(1000092.5859999988),\n name: 'Topleveltask2',\n ts: TraceEngine.Types.Timing.MicroSeconds(80543641261.0185),\n desc: undefined,\n origin: 'https://node-server-tan.vercel.app',\n },\n ]);\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"ServerTimingsHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/ServerTimingsHandler.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,EAAC,uBAAuB,EAAC,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EAAC,WAAW,EAAC,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,KAAK,MAAM,aAAa,CAAC;AAErC,uBAAuB,CAAC,sBAAsB,EAAE,GAAG,EAAE;IACnD,EAAE,CAAC,2DAA2D,EAAE,KAAK;QACnE,MAAM,WAAW,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,wBAAwB,CAAC,CAAC;QAClF,MAAM,MAAM,GAAG,WAAW,CAAC,WAAW,CAAC,aAAa,CAAC,aAAa,CAAC;QACnE,MAAM,UAAU,GACZ,MAAM,CAAC,GAAG,CAAC,CAAC,EAAC,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,EAAC,EAAE,EAAE,CAAC,CAAC,EAAC,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAC,CAAC,CAAC,CAAC;QAC7G,MAAM,CAAC,SAAS,CAAC,UAAU,EAAE;YAC3B;gBACE,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,kBAAkB,CAAC;gBACxD,IAAI,EAAE,eAAe;gBACrB,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,gBAAgB,CAAC;gBACrD,IAAI,EAAE,iCAAiC;gBACvC,MAAM,EAAE,oCAAoC;aAC7C;YACD;gBACE,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,iBAAiB,CAAC;gBACvD,IAAI,EAAE,kBAAkB;gBACxB,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,gBAAgB,CAAC;gBACrD,IAAI,EAAE,oCAAoC;gBAC1C,MAAM,EAAE,oCAAoC;aAC7C;YACD;gBACE,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,kBAAkB,CAAC;gBACxD,IAAI,EAAE,eAAe;gBACrB,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,gBAAgB,CAAC;gBACrD,IAAI,EAAE,SAAS;gBACf,MAAM,EAAE,oCAAoC;aAC7C;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Trace from '../trace.js';\n\ndescribeWithEnvironment('ServerTimingsHandler', () => {\n it('extracts server timings from network request trace events', async function() {\n const parsedTrace = await TraceLoader.traceEngine(this, 'server-timings.json.gz');\n const events = parsedTrace.parsedTrace.ServerTimings.serverTimings;\n const timingData =\n events.map(({name, dur, ts, args}) => ({name, dur, ts, desc: args.data.desc, origin: args.data.origin}));\n assert.deepEqual(timingData, [\n {\n dur: Trace.Types.Timing.MicroSeconds(1004293.2819999987),\n name: 'Topleveltask1',\n ts: Trace.Types.Timing.MicroSeconds(80542636965.7475),\n desc: 'Description of top level task 1',\n origin: 'https://node-server-tan.vercel.app',\n },\n {\n dur: Trace.Types.Timing.MicroSeconds(904293.2819999987),\n name: 'Secondleveltask1',\n ts: Trace.Types.Timing.MicroSeconds(80542686965.7475),\n desc: 'Description of second level task 1',\n origin: 'https://node-server-tan.vercel.app',\n },\n {\n dur: Trace.Types.Timing.MicroSeconds(1000092.5859999988),\n name: 'Topleveltask2',\n ts: Trace.Types.Timing.MicroSeconds(80543641261.0185),\n desc: undefined,\n origin: 'https://node-server-tan.vercel.app',\n },\n ]);\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/Threads.d.ts b/public/models/trace/handlers/Threads.d.ts index 268ac1829..b040ea2be 100644 --- a/public/models/trace/handlers/Threads.d.ts +++ b/public/models/trace/handlers/Threads.d.ts @@ -2,16 +2,16 @@ import type * as Helpers from '../helpers/helpers.js'; import type * as Types from '../types/types.js'; import { type AuctionWorkletsData } from './AuctionWorkletsHandler.js'; import type * as Renderer from './RendererHandler.js'; -import { type TraceParseData } from './types.js'; +import { type ParsedTrace } from './types.js'; export interface ThreadData { - pid: Types.TraceEvents.ProcessID; - tid: Types.TraceEvents.ThreadID; - entries: readonly Types.TraceEvents.TraceEventData[]; + pid: Types.Events.ProcessID; + tid: Types.Events.ThreadID; + entries: readonly Types.Events.Event[]; processIsOnMainFrame: boolean; tree: Helpers.TreeHelpers.TraceEntryTree; type: ThreadType; name: string | null; - entryToNode: Map; + entryToNode: Map; } export declare const enum ThreadType { MAIN_THREAD = "MAIN_THREAD", @@ -30,4 +30,4 @@ export declare function threadsInRenderer(rendererData: Renderer.RendererHandler * can use this helper to iterate over threads in confidence that it will work * for both trace types. */ -export declare function threadsInTrace(traceParseData: TraceParseData): readonly ThreadData[]; +export declare function threadsInTrace(parsedTrace: ParsedTrace): readonly ThreadData[]; diff --git a/public/models/trace/handlers/Threads.js b/public/models/trace/handlers/Threads.js index b5ae726d8..a96ed2015 100644 --- a/public/models/trace/handlers/Threads.js +++ b/public/models/trace/handlers/Threads.js @@ -56,18 +56,18 @@ export function threadsInRenderer(rendererData, auctionWorkletsData) { * can use this helper to iterate over threads in confidence that it will work * for both trace types. */ -export function threadsInTrace(traceParseData) { +export function threadsInTrace(parsedTrace) { // If we have Renderer threads, we prefer to use those. In the event that a // trace is a CPU Profile trace, we will never have Renderer threads, so we // know if there are no Renderer threads that we can fallback to using the // data from the SamplesHandler. - const threadsFromRenderer = threadsInRenderer(traceParseData.Renderer, traceParseData.AuctionWorklets); + const threadsFromRenderer = threadsInRenderer(parsedTrace.Renderer, parsedTrace.AuctionWorklets); if (threadsFromRenderer.length) { return threadsFromRenderer; } const foundThreads = []; - if (traceParseData.Samples.profilesInProcess.size) { - for (const [pid, process] of traceParseData.Samples.profilesInProcess) { + if (parsedTrace.Samples.profilesInProcess.size) { + for (const [pid, process] of parsedTrace.Samples.profilesInProcess) { for (const [tid, thread] of process) { if (!thread.profileTree) { // Drop threads where we could not create the tree; this indicates @@ -85,7 +85,7 @@ export function threadsInTrace(traceParseData) { processIsOnMainFrame: false, tree: thread.profileTree, type: "CPU_PROFILE" /* ThreadType.CPU_PROFILE */, - entryToNode: traceParseData.Samples.entryToNode, + entryToNode: parsedTrace.Samples.entryToNode, }); } } diff --git a/public/models/trace/handlers/Threads.js.map b/public/models/trace/handlers/Threads.js.map index 0639f3791..e0c0fb302 100644 --- a/public/models/trace/handlers/Threads.js.map +++ b/public/models/trace/handlers/Threads.js.map @@ -1 +1 @@ -{"version":3,"file":"Threads.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/Threads.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n//\nimport type * as Helpers from '../helpers/helpers.js';\nimport type * as Types from '../types/types.js';\n\nimport {type AuctionWorkletsData} from './AuctionWorkletsHandler.js';\nimport type * as Renderer from './RendererHandler.js';\nimport {type TraceParseData} from './types.js';\n\nexport interface ThreadData {\n pid: Types.TraceEvents.ProcessID;\n tid: Types.TraceEvents.ThreadID;\n entries: readonly Types.TraceEvents.TraceEventData[];\n processIsOnMainFrame: boolean;\n tree: Helpers.TreeHelpers.TraceEntryTree;\n type: ThreadType;\n name: string|null;\n entryToNode: Map;\n}\n\nexport const enum ThreadType {\n MAIN_THREAD = 'MAIN_THREAD',\n WORKER = 'WORKER',\n RASTERIZER = 'RASTERIZER',\n AUCTION_WORKLET = 'AUCTION_WORKLET',\n OTHER = 'OTHER',\n CPU_PROFILE = 'CPU_PROFILE',\n THREAD_POOL = 'THREAD_POOL',\n}\n\nfunction getThreadTypeForRendererThread(\n pid: Types.TraceEvents.ProcessID, thread: Renderer.RendererThread,\n auctionWorkletsData: AuctionWorkletsData): ThreadType {\n let threadType = ThreadType.OTHER;\n if (thread.name === 'CrRendererMain') {\n threadType = ThreadType.MAIN_THREAD;\n } else if (thread.name === 'DedicatedWorker thread') {\n threadType = ThreadType.WORKER;\n } else if (thread.name?.startsWith('CompositorTileWorker')) {\n threadType = ThreadType.RASTERIZER;\n } else if (auctionWorkletsData.worklets.has(pid)) {\n threadType = ThreadType.AUCTION_WORKLET;\n } else if (thread.name?.startsWith('ThreadPool')) {\n // TODO(paulirish): perhaps exclude ThreadPoolServiceThread entirely\n threadType = ThreadType.THREAD_POOL;\n }\n return threadType;\n}\n\nexport function threadsInRenderer(\n rendererData: Renderer.RendererHandlerData, auctionWorkletsData: AuctionWorkletsData): readonly ThreadData[] {\n const foundThreads: ThreadData[] = [];\n // If we have Renderer threads, we prefer to use those. In the event that a\n // trace is a CPU Profile trace, we will never have Renderer threads, so we\n // know if there are no Renderer threads that we can fallback to using the\n // data from the SamplesHandler.\n if (rendererData.processes.size) {\n for (const [pid, process] of rendererData.processes) {\n for (const [tid, thread] of process.threads) {\n if (!thread.tree) {\n // Drop threads where we could not create the tree; this indicates\n // unexpected data and we won't be able to support all the UI\n // filtering we need.\n continue;\n }\n const threadType = getThreadTypeForRendererThread(pid, thread, auctionWorkletsData);\n foundThreads.push({\n name: thread.name,\n pid,\n tid,\n processIsOnMainFrame: process.isOnMainFrame,\n entries: thread.entries,\n tree: thread.tree,\n type: threadType,\n entryToNode: rendererData.entryToNode,\n });\n }\n }\n }\n return foundThreads;\n}\n\n/**\n * Given trace parsed data, this helper will return a high level array of\n * ThreadData. This is useful because it allows you to get a list of threads\n * regardless of if the trace is a CPU Profile or a Tracing profile. Thus you\n * can use this helper to iterate over threads in confidence that it will work\n * for both trace types.\n */\nexport function threadsInTrace(traceParseData: TraceParseData): readonly ThreadData[] {\n // If we have Renderer threads, we prefer to use those. In the event that a\n // trace is a CPU Profile trace, we will never have Renderer threads, so we\n // know if there are no Renderer threads that we can fallback to using the\n // data from the SamplesHandler.\n const threadsFromRenderer = threadsInRenderer(traceParseData.Renderer, traceParseData.AuctionWorklets);\n if (threadsFromRenderer.length) {\n return threadsFromRenderer;\n }\n\n const foundThreads: ThreadData[] = [];\n if (traceParseData.Samples.profilesInProcess.size) {\n for (const [pid, process] of traceParseData.Samples.profilesInProcess) {\n for (const [tid, thread] of process) {\n if (!thread.profileTree) {\n // Drop threads where we could not create the tree; this indicates\n // unexpected data and we won't be able to support all the UI\n // filtering we need.\n continue;\n }\n\n foundThreads.push({\n pid,\n tid,\n // CPU Profile threads do not have a name.\n name: null,\n entries: thread.profileCalls,\n // There is no concept of a \"Main Frame\" in a CPU profile.\n processIsOnMainFrame: false,\n tree: thread.profileTree,\n type: ThreadType.CPU_PROFILE,\n entryToNode: traceParseData.Samples.entryToNode,\n });\n }\n }\n }\n\n return foundThreads;\n}\n"]} \ No newline at end of file +{"version":3,"file":"Threads.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/Threads.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n//\nimport type * as Helpers from '../helpers/helpers.js';\nimport type * as Types from '../types/types.js';\n\nimport {type AuctionWorkletsData} from './AuctionWorkletsHandler.js';\nimport type * as Renderer from './RendererHandler.js';\nimport {type ParsedTrace} from './types.js';\n\nexport interface ThreadData {\n pid: Types.Events.ProcessID;\n tid: Types.Events.ThreadID;\n entries: readonly Types.Events.Event[];\n processIsOnMainFrame: boolean;\n tree: Helpers.TreeHelpers.TraceEntryTree;\n type: ThreadType;\n name: string|null;\n entryToNode: Map;\n}\n\nexport const enum ThreadType {\n MAIN_THREAD = 'MAIN_THREAD',\n WORKER = 'WORKER',\n RASTERIZER = 'RASTERIZER',\n AUCTION_WORKLET = 'AUCTION_WORKLET',\n OTHER = 'OTHER',\n CPU_PROFILE = 'CPU_PROFILE',\n THREAD_POOL = 'THREAD_POOL',\n}\n\nfunction getThreadTypeForRendererThread(\n pid: Types.Events.ProcessID, thread: Renderer.RendererThread,\n auctionWorkletsData: AuctionWorkletsData): ThreadType {\n let threadType = ThreadType.OTHER;\n if (thread.name === 'CrRendererMain') {\n threadType = ThreadType.MAIN_THREAD;\n } else if (thread.name === 'DedicatedWorker thread') {\n threadType = ThreadType.WORKER;\n } else if (thread.name?.startsWith('CompositorTileWorker')) {\n threadType = ThreadType.RASTERIZER;\n } else if (auctionWorkletsData.worklets.has(pid)) {\n threadType = ThreadType.AUCTION_WORKLET;\n } else if (thread.name?.startsWith('ThreadPool')) {\n // TODO(paulirish): perhaps exclude ThreadPoolServiceThread entirely\n threadType = ThreadType.THREAD_POOL;\n }\n return threadType;\n}\n\nexport function threadsInRenderer(\n rendererData: Renderer.RendererHandlerData, auctionWorkletsData: AuctionWorkletsData): readonly ThreadData[] {\n const foundThreads: ThreadData[] = [];\n // If we have Renderer threads, we prefer to use those. In the event that a\n // trace is a CPU Profile trace, we will never have Renderer threads, so we\n // know if there are no Renderer threads that we can fallback to using the\n // data from the SamplesHandler.\n if (rendererData.processes.size) {\n for (const [pid, process] of rendererData.processes) {\n for (const [tid, thread] of process.threads) {\n if (!thread.tree) {\n // Drop threads where we could not create the tree; this indicates\n // unexpected data and we won't be able to support all the UI\n // filtering we need.\n continue;\n }\n const threadType = getThreadTypeForRendererThread(pid, thread, auctionWorkletsData);\n foundThreads.push({\n name: thread.name,\n pid,\n tid,\n processIsOnMainFrame: process.isOnMainFrame,\n entries: thread.entries,\n tree: thread.tree,\n type: threadType,\n entryToNode: rendererData.entryToNode,\n });\n }\n }\n }\n return foundThreads;\n}\n\n/**\n * Given trace parsed data, this helper will return a high level array of\n * ThreadData. This is useful because it allows you to get a list of threads\n * regardless of if the trace is a CPU Profile or a Tracing profile. Thus you\n * can use this helper to iterate over threads in confidence that it will work\n * for both trace types.\n */\nexport function threadsInTrace(parsedTrace: ParsedTrace): readonly ThreadData[] {\n // If we have Renderer threads, we prefer to use those. In the event that a\n // trace is a CPU Profile trace, we will never have Renderer threads, so we\n // know if there are no Renderer threads that we can fallback to using the\n // data from the SamplesHandler.\n const threadsFromRenderer = threadsInRenderer(parsedTrace.Renderer, parsedTrace.AuctionWorklets);\n if (threadsFromRenderer.length) {\n return threadsFromRenderer;\n }\n\n const foundThreads: ThreadData[] = [];\n if (parsedTrace.Samples.profilesInProcess.size) {\n for (const [pid, process] of parsedTrace.Samples.profilesInProcess) {\n for (const [tid, thread] of process) {\n if (!thread.profileTree) {\n // Drop threads where we could not create the tree; this indicates\n // unexpected data and we won't be able to support all the UI\n // filtering we need.\n continue;\n }\n\n foundThreads.push({\n pid,\n tid,\n // CPU Profile threads do not have a name.\n name: null,\n entries: thread.profileCalls,\n // There is no concept of a \"Main Frame\" in a CPU profile.\n processIsOnMainFrame: false,\n tree: thread.profileTree,\n type: ThreadType.CPU_PROFILE,\n entryToNode: parsedTrace.Samples.entryToNode,\n });\n }\n }\n }\n\n return foundThreads;\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/Threads.test.js b/public/models/trace/handlers/Threads.test.js index 3a6106b65..31be32dca 100644 --- a/public/models/trace/handlers/Threads.test.js +++ b/public/models/trace/handlers/Threads.test.js @@ -4,28 +4,28 @@ import * as TimelineModel from '../../../models/timeline_model/timeline_model.js'; import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; -import * as TraceEngine from '../trace.js'; +import * as Trace from '../trace.js'; describeWithEnvironment('Handler Threads helper', function () { it('returns all the threads for a trace that used tracing', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const allThreads = Array.from(traceData.Renderer.processes.values()).flatMap(process => { + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const allThreads = Array.from(parsedTrace.Renderer.processes.values()).flatMap(process => { return Array.from(process.threads.values()); }); const expectedThreadNamesAndTypes = [ - { name: 'CrRendererMain', type: "MAIN_THREAD" /* TraceEngine.Handlers.Threads.ThreadType.MAIN_THREAD */ }, - { name: 'Chrome_ChildIOThread', type: "OTHER" /* TraceEngine.Handlers.Threads.ThreadType.OTHER */ }, - { name: 'Compositor', type: "OTHER" /* TraceEngine.Handlers.Threads.ThreadType.OTHER */ }, - { name: 'ThreadPoolServiceThread', type: "THREAD_POOL" /* TraceEngine.Handlers.Threads.ThreadType.THREAD_POOL */ }, - { name: 'Media', type: "OTHER" /* TraceEngine.Handlers.Threads.ThreadType.OTHER */ }, - { name: 'ThreadPoolForegroundWorker', type: "THREAD_POOL" /* TraceEngine.Handlers.Threads.ThreadType.THREAD_POOL */ }, - { name: 'CompositorTileWorker4', type: "RASTERIZER" /* TraceEngine.Handlers.Threads.ThreadType.RASTERIZER */ }, - { name: 'CompositorTileWorker2', type: "RASTERIZER" /* TraceEngine.Handlers.Threads.ThreadType.RASTERIZER */ }, - { name: 'CompositorTileWorker1', type: "RASTERIZER" /* TraceEngine.Handlers.Threads.ThreadType.RASTERIZER */ }, - { name: 'CompositorTileWorkerBackground', type: "RASTERIZER" /* TraceEngine.Handlers.Threads.ThreadType.RASTERIZER */ }, - { name: 'ThreadPoolForegroundWorker', type: "THREAD_POOL" /* TraceEngine.Handlers.Threads.ThreadType.THREAD_POOL */ }, - { name: 'CompositorTileWorker3', type: "RASTERIZER" /* TraceEngine.Handlers.Threads.ThreadType.RASTERIZER */ }, + { name: 'CrRendererMain', type: "MAIN_THREAD" /* Trace.Handlers.Threads.ThreadType.MAIN_THREAD */ }, + { name: 'Chrome_ChildIOThread', type: "OTHER" /* Trace.Handlers.Threads.ThreadType.OTHER */ }, + { name: 'Compositor', type: "OTHER" /* Trace.Handlers.Threads.ThreadType.OTHER */ }, + { name: 'ThreadPoolServiceThread', type: "THREAD_POOL" /* Trace.Handlers.Threads.ThreadType.THREAD_POOL */ }, + { name: 'Media', type: "OTHER" /* Trace.Handlers.Threads.ThreadType.OTHER */ }, + { name: 'ThreadPoolForegroundWorker', type: "THREAD_POOL" /* Trace.Handlers.Threads.ThreadType.THREAD_POOL */ }, + { name: 'CompositorTileWorker4', type: "RASTERIZER" /* Trace.Handlers.Threads.ThreadType.RASTERIZER */ }, + { name: 'CompositorTileWorker2', type: "RASTERIZER" /* Trace.Handlers.Threads.ThreadType.RASTERIZER */ }, + { name: 'CompositorTileWorker1', type: "RASTERIZER" /* Trace.Handlers.Threads.ThreadType.RASTERIZER */ }, + { name: 'CompositorTileWorkerBackground', type: "RASTERIZER" /* Trace.Handlers.Threads.ThreadType.RASTERIZER */ }, + { name: 'ThreadPoolForegroundWorker', type: "THREAD_POOL" /* Trace.Handlers.Threads.ThreadType.THREAD_POOL */ }, + { name: 'CompositorTileWorker3', type: "RASTERIZER" /* Trace.Handlers.Threads.ThreadType.RASTERIZER */ }, ]; - const threads = TraceEngine.Handlers.Threads.threadsInTrace(traceData); + const threads = Trace.Handlers.Threads.threadsInTrace(parsedTrace); assert.strictEqual(threads.length, allThreads.length); assert.deepEqual(threads.map(thread => ({ name: thread.name, type: thread.type })), expectedThreadNamesAndTypes); }); @@ -34,14 +34,14 @@ describeWithEnvironment('Handler Threads helper', function () { // it takes the CDP Profile and wraps it in fake trace events, before then // passing that through to the new engine. const rawEvents = await TraceLoader.rawCPUProfile(this, 'node-fibonacci-website.cpuprofile.gz'); - const events = TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.createFakeTraceFromCpuProfile(rawEvents, TraceEngine.Types.TraceEvents.ThreadID(1)); - const { traceData } = await TraceLoader.executeTraceEngineOnFileContents(events); + const events = TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.createFakeTraceFromCpuProfile(rawEvents, Trace.Types.Events.ThreadID(1)); + const { parsedTrace } = await TraceLoader.executeTraceEngineOnFileContents(events); // Check that we did indeed parse this properly as a CPU Profile. - assert.strictEqual(traceData.Renderer.processes.size, 0); - assert.strictEqual(traceData.Samples.profilesInProcess.size, 1); - const threads = TraceEngine.Handlers.Threads.threadsInTrace(traceData); + assert.strictEqual(parsedTrace.Renderer.processes.size, 0); + assert.strictEqual(parsedTrace.Samples.profilesInProcess.size, 1); + const threads = Trace.Handlers.Threads.threadsInTrace(parsedTrace); assert.strictEqual(threads.length, 1); - assert.strictEqual(threads.at(0)?.type, "CPU_PROFILE" /* TraceEngine.Handlers.Threads.ThreadType.CPU_PROFILE */); + assert.strictEqual(threads.at(0)?.type, "CPU_PROFILE" /* Trace.Handlers.Threads.ThreadType.CPU_PROFILE */); assert.strictEqual(threads.at(0)?.entries.length, 875); }); }); diff --git a/public/models/trace/handlers/Threads.test.js.map b/public/models/trace/handlers/Threads.test.js.map index c5371fb7f..dbc9de354 100644 --- a/public/models/trace/handlers/Threads.test.js.map +++ b/public/models/trace/handlers/Threads.test.js.map @@ -1 +1 @@ -{"version":3,"file":"Threads.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/Threads.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TimelineModel from '../../../models/timeline_model/timeline_model.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as TraceEngine from '../trace.js';\n\ndescribeWithEnvironment('Handler Threads helper', function() {\n it('returns all the threads for a trace that used tracing', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n\n const allThreads = Array.from(traceData.Renderer.processes.values()).flatMap(process => {\n return Array.from(process.threads.values());\n });\n\n const expectedThreadNamesAndTypes = [\n {name: 'CrRendererMain', type: TraceEngine.Handlers.Threads.ThreadType.MAIN_THREAD},\n {name: 'Chrome_ChildIOThread', type: TraceEngine.Handlers.Threads.ThreadType.OTHER},\n {name: 'Compositor', type: TraceEngine.Handlers.Threads.ThreadType.OTHER},\n {name: 'ThreadPoolServiceThread', type: TraceEngine.Handlers.Threads.ThreadType.THREAD_POOL},\n {name: 'Media', type: TraceEngine.Handlers.Threads.ThreadType.OTHER},\n {name: 'ThreadPoolForegroundWorker', type: TraceEngine.Handlers.Threads.ThreadType.THREAD_POOL},\n {name: 'CompositorTileWorker4', type: TraceEngine.Handlers.Threads.ThreadType.RASTERIZER},\n {name: 'CompositorTileWorker2', type: TraceEngine.Handlers.Threads.ThreadType.RASTERIZER},\n {name: 'CompositorTileWorker1', type: TraceEngine.Handlers.Threads.ThreadType.RASTERIZER},\n {name: 'CompositorTileWorkerBackground', type: TraceEngine.Handlers.Threads.ThreadType.RASTERIZER},\n {name: 'ThreadPoolForegroundWorker', type: TraceEngine.Handlers.Threads.ThreadType.THREAD_POOL},\n {name: 'CompositorTileWorker3', type: TraceEngine.Handlers.Threads.ThreadType.RASTERIZER},\n ];\n\n const threads = TraceEngine.Handlers.Threads.threadsInTrace(traceData);\n assert.strictEqual(threads.length, allThreads.length);\n assert.deepEqual(threads.map(thread => ({name: thread.name, type: thread.type})), expectedThreadNamesAndTypes);\n });\n\n it('returns all the threads for a trace that used CPU profiling', async function() {\n // Bit of extra setup required: we need to mimic what the panel does where\n // it takes the CDP Profile and wraps it in fake trace events, before then\n // passing that through to the new engine.\n const rawEvents = await TraceLoader.rawCPUProfile(this, 'node-fibonacci-website.cpuprofile.gz');\n const events = TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.createFakeTraceFromCpuProfile(\n rawEvents,\n TraceEngine.Types.TraceEvents.ThreadID(1),\n );\n const {traceData} = await TraceLoader.executeTraceEngineOnFileContents(\n events as unknown as TraceEngine.Types.TraceEvents.TraceEventData[]);\n\n // Check that we did indeed parse this properly as a CPU Profile.\n assert.strictEqual(traceData.Renderer.processes.size, 0);\n assert.strictEqual(traceData.Samples.profilesInProcess.size, 1);\n\n const threads = TraceEngine.Handlers.Threads.threadsInTrace(traceData);\n assert.strictEqual(threads.length, 1);\n\n assert.strictEqual(threads.at(0)?.type, TraceEngine.Handlers.Threads.ThreadType.CPU_PROFILE);\n assert.strictEqual(threads.at(0)?.entries.length, 875);\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"Threads.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/Threads.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TimelineModel from '../../../models/timeline_model/timeline_model.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Trace from '../trace.js';\n\ndescribeWithEnvironment('Handler Threads helper', function() {\n it('returns all the threads for a trace that used tracing', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n\n const allThreads = Array.from(parsedTrace.Renderer.processes.values()).flatMap(process => {\n return Array.from(process.threads.values());\n });\n\n const expectedThreadNamesAndTypes = [\n {name: 'CrRendererMain', type: Trace.Handlers.Threads.ThreadType.MAIN_THREAD},\n {name: 'Chrome_ChildIOThread', type: Trace.Handlers.Threads.ThreadType.OTHER},\n {name: 'Compositor', type: Trace.Handlers.Threads.ThreadType.OTHER},\n {name: 'ThreadPoolServiceThread', type: Trace.Handlers.Threads.ThreadType.THREAD_POOL},\n {name: 'Media', type: Trace.Handlers.Threads.ThreadType.OTHER},\n {name: 'ThreadPoolForegroundWorker', type: Trace.Handlers.Threads.ThreadType.THREAD_POOL},\n {name: 'CompositorTileWorker4', type: Trace.Handlers.Threads.ThreadType.RASTERIZER},\n {name: 'CompositorTileWorker2', type: Trace.Handlers.Threads.ThreadType.RASTERIZER},\n {name: 'CompositorTileWorker1', type: Trace.Handlers.Threads.ThreadType.RASTERIZER},\n {name: 'CompositorTileWorkerBackground', type: Trace.Handlers.Threads.ThreadType.RASTERIZER},\n {name: 'ThreadPoolForegroundWorker', type: Trace.Handlers.Threads.ThreadType.THREAD_POOL},\n {name: 'CompositorTileWorker3', type: Trace.Handlers.Threads.ThreadType.RASTERIZER},\n ];\n\n const threads = Trace.Handlers.Threads.threadsInTrace(parsedTrace);\n assert.strictEqual(threads.length, allThreads.length);\n assert.deepEqual(threads.map(thread => ({name: thread.name, type: thread.type})), expectedThreadNamesAndTypes);\n });\n\n it('returns all the threads for a trace that used CPU profiling', async function() {\n // Bit of extra setup required: we need to mimic what the panel does where\n // it takes the CDP Profile and wraps it in fake trace events, before then\n // passing that through to the new engine.\n const rawEvents = await TraceLoader.rawCPUProfile(this, 'node-fibonacci-website.cpuprofile.gz');\n const events = TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.createFakeTraceFromCpuProfile(\n rawEvents,\n Trace.Types.Events.ThreadID(1),\n );\n const {parsedTrace} =\n await TraceLoader.executeTraceEngineOnFileContents(events as unknown as Trace.Types.Events.Event[]);\n\n // Check that we did indeed parse this properly as a CPU Profile.\n assert.strictEqual(parsedTrace.Renderer.processes.size, 0);\n assert.strictEqual(parsedTrace.Samples.profilesInProcess.size, 1);\n\n const threads = Trace.Handlers.Threads.threadsInTrace(parsedTrace);\n assert.strictEqual(threads.length, 1);\n\n assert.strictEqual(threads.at(0)?.type, Trace.Handlers.Threads.ThreadType.CPU_PROFILE);\n assert.strictEqual(threads.at(0)?.entries.length, 875);\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/UserInteractionsHandler.d.ts b/public/models/trace/handlers/UserInteractionsHandler.d.ts index a96f5146a..dc1a392eb 100644 --- a/public/models/trace/handlers/UserInteractionsHandler.d.ts +++ b/public/models/trace/handlers/UserInteractionsHandler.d.ts @@ -1,18 +1,18 @@ import * as Types from '../types/types.js'; import { ScoreClassification } from './PageLoadMetricsHandler.js'; -import { type TraceEventHandlerName } from './types.js'; +import { type HandlerName } from './types.js'; export declare const LONG_INTERACTION_THRESHOLD: Types.Timing.MicroSeconds; export interface UserInteractionsData { /** All the user events we found in the trace */ - allEvents: readonly Types.TraceEvents.TraceEventEventTiming[]; + allEvents: readonly Types.Events.EventTiming[]; /** All the BeginCommitCompositorFrame events we found in the trace */ - beginCommitCompositorFrameEvents: readonly Types.TraceEvents.TraceEventBeginCommitCompositorFrame[]; + beginCommitCompositorFrameEvents: readonly Types.Events.BeginCommitCompositorFrame[]; /** All the ParseMetaViewport events we found in the trace */ - parseMetaViewportEvents: readonly Types.TraceEvents.TraceEventParseMetaViewport[]; + parseMetaViewportEvents: readonly Types.Events.ParseMetaViewport[]; /** All the interaction events we found in the trace that had an * interactionId and a duration > 0 **/ - interactionEvents: readonly Types.TraceEvents.SyntheticInteractionPair[]; + interactionEvents: readonly Types.Events.SyntheticInteractionPair[]; /** If the user rapidly generates interaction events (think typing into a * text box), in the UI we only really want to show the user the longest * interaction in that set. @@ -27,14 +27,14 @@ export interface UserInteractionsData { * all the interaction events filtered down, removing any nested interactions * entirely. **/ - interactionEventsWithNoNesting: readonly Types.TraceEvents.SyntheticInteractionPair[]; - longestInteractionEvent: Readonly | null; - interactionsOverThreshold: Readonly>; + interactionEventsWithNoNesting: readonly Types.Events.SyntheticInteractionPair[]; + longestInteractionEvent: Readonly | null; + interactionsOverThreshold: Readonly>; } export declare function reset(): void; -export declare function handleEvent(event: Types.TraceEvents.TraceEventData): void; +export declare function handleEvent(event: Types.Events.Event): void; export type InteractionCategory = 'KEYBOARD' | 'POINTER' | 'OTHER'; -export declare function categoryOfInteraction(interaction: Types.TraceEvents.SyntheticInteractionPair): InteractionCategory; +export declare function categoryOfInteraction(interaction: Types.Events.SyntheticInteractionPair): InteractionCategory; /** * We define a set of interactions as nested where: * 1. Their end times align. @@ -58,10 +58,10 @@ export declare function categoryOfInteraction(interaction: Types.TraceEvents.Syn * ====C=[pointerdown]= * =D=[pointerup]= **/ -export declare function removeNestedInteractions(interactions: readonly Types.TraceEvents.SyntheticInteractionPair[]): readonly Types.TraceEvents.SyntheticInteractionPair[]; +export declare function removeNestedInteractions(interactions: readonly Types.Events.SyntheticInteractionPair[]): readonly Types.Events.SyntheticInteractionPair[]; export declare function finalize(): Promise; export declare function data(): UserInteractionsData; -export declare function deps(): TraceEventHandlerName[]; +export declare function deps(): HandlerName[]; /** * Classifications sourced from * https://web.dev/articles/inp#good-score diff --git a/public/models/trace/handlers/UserInteractionsHandler.js b/public/models/trace/handlers/UserInteractionsHandler.js index d85b386bc..a8dd7b38c 100644 --- a/public/models/trace/handlers/UserInteractionsHandler.js +++ b/public/models/trace/handlers/UserInteractionsHandler.js @@ -37,18 +37,18 @@ export function handleEvent(event) { if (handlerState !== 2 /* HandlerState.INITIALIZED */) { throw new Error('Handler is not initialized'); } - if (Types.TraceEvents.isTraceEventBeginCommitCompositorFrame(event)) { + if (Types.Events.isBeginCommitCompositorFrame(event)) { beginCommitCompositorFrameEvents.push(event); return; } - if (Types.TraceEvents.isTraceEventParseMetaViewport(event)) { + if (Types.Events.isParseMetaViewport(event)) { parseMetaViewportEvents.push(event); return; } - if (!Types.TraceEvents.isTraceEventEventTiming(event)) { + if (!Types.Events.isEventTiming(event)) { return; } - if (Types.TraceEvents.isTraceEventEventTimingEnd(event)) { + if (Types.Events.isEventTimingEnd(event)) { // Store the end event; for each start event that is an interaction, we need the matching end event to calculate the duration correctly. eventTimingEndEventsById.set(event.id, event); } @@ -56,7 +56,7 @@ export function handleEvent(event) { // From this point on we want to find events that represent interactions. // These events are always start events - those are the ones that contain all // the metadata about the interaction. - if (!event.args.data || !Types.TraceEvents.isTraceEventEventTimingStart(event)) { + if (!event.args.data || !Types.Events.isEventTimingStart(event)) { return; } const { duration, interactionId } = event.args.data; @@ -235,8 +235,7 @@ export async function finalize() { const frameId = interactionStartEvent.args.frame ?? interactionStartEvent.args.data.frame; const navigation = Helpers.Trace.getNavigationForTraceEvent(interactionStartEvent, frameId, navigationsByFrameId); const navigationId = navigation?.args.data?.navigationId; - const interactionEvent = Helpers.SyntheticEvents.SyntheticEventsManager - .registerSyntheticBasedEvent({ + const interactionEvent = Helpers.SyntheticEvents.SyntheticEventsManager.registerSyntheticEvent({ // Use the start event to define the common fields. rawSourceEvent: interactionStartEvent, cat: interactionStartEvent.cat, diff --git a/public/models/trace/handlers/UserInteractionsHandler.js.map b/public/models/trace/handlers/UserInteractionsHandler.js.map index f6c067d48..60badea16 100644 --- a/public/models/trace/handlers/UserInteractionsHandler.js.map +++ b/public/models/trace/handlers/UserInteractionsHandler.js.map @@ -1 +1 @@ -{"version":3,"file":"UserInteractionsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/UserInteractionsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {data as metaHandlerData} from './MetaHandler.js';\nimport {ScoreClassification} from './PageLoadMetricsHandler.js';\nimport {HandlerState, type TraceEventHandlerName} from './types.js';\n\n// This handler serves two purposes. It generates a list of events that are\n// used to show user clicks in the timeline. It is also used to gather\n// EventTimings into Interactions, which we use to show interactions and\n// highlight long interactions to the user, along with INP.\n\n// We don't need to know which process / thread these events occurred in,\n// because they are effectively global, so we just track all that we find.\nconst allEvents: Types.TraceEvents.TraceEventEventTiming[] = [];\n\nconst beginCommitCompositorFrameEvents: Types.TraceEvents.TraceEventBeginCommitCompositorFrame[] = [];\nconst parseMetaViewportEvents: Types.TraceEvents.TraceEventParseMetaViewport[] = [];\n\nexport const LONG_INTERACTION_THRESHOLD = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(200));\n\nconst INP_GOOD_TIMING = LONG_INTERACTION_THRESHOLD;\nconst INP_MEDIUM_TIMING = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(500));\n\nexport interface UserInteractionsData {\n /** All the user events we found in the trace */\n allEvents: readonly Types.TraceEvents.TraceEventEventTiming[];\n /** All the BeginCommitCompositorFrame events we found in the trace */\n beginCommitCompositorFrameEvents: readonly Types.TraceEvents.TraceEventBeginCommitCompositorFrame[];\n /** All the ParseMetaViewport events we found in the trace */\n parseMetaViewportEvents: readonly Types.TraceEvents.TraceEventParseMetaViewport[];\n /** All the interaction events we found in the trace that had an\n * interactionId and a duration > 0\n **/\n interactionEvents: readonly Types.TraceEvents.SyntheticInteractionPair[];\n /** If the user rapidly generates interaction events (think typing into a\n * text box), in the UI we only really want to show the user the longest\n * interaction in that set.\n * For example picture interactions like this:\n * ===[interaction A]==========\n * =[interaction B]======\n * =[interaction C]=\n *\n * These events all end at the same time, and so in this instance we only want\n * to show the first interaction A on the timeline, as that is the longest one\n * and the one the developer should be focusing on. So this array of events is\n * all the interaction events filtered down, removing any nested interactions\n * entirely.\n **/\n interactionEventsWithNoNesting: readonly Types.TraceEvents.SyntheticInteractionPair[];\n // The longest duration interaction event. Can be null if the trace has no interaction events.\n longestInteractionEvent: Readonly|null;\n // All interactions that went over the interaction threshold (200ms, see https://web.dev/inp/)\n interactionsOverThreshold: Readonly>;\n}\n\nlet longestInteractionEvent: Types.TraceEvents.SyntheticInteractionPair|null = null;\n\nconst interactionEvents: Types.TraceEvents.SyntheticInteractionPair[] = [];\nconst interactionEventsWithNoNesting: Types.TraceEvents.SyntheticInteractionPair[] = [];\nconst eventTimingEndEventsById = new Map();\nconst eventTimingStartEventsForInteractions: Types.TraceEvents.TraceEventEventTimingBegin[] = [];\nlet handlerState = HandlerState.UNINITIALIZED;\n\nexport function reset(): void {\n allEvents.length = 0;\n beginCommitCompositorFrameEvents.length = 0;\n parseMetaViewportEvents.length = 0;\n interactionEvents.length = 0;\n eventTimingStartEventsForInteractions.length = 0;\n eventTimingEndEventsById.clear();\n interactionEventsWithNoNesting.length = 0;\n longestInteractionEvent = null;\n handlerState = HandlerState.INITIALIZED;\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Handler is not initialized');\n }\n\n if (Types.TraceEvents.isTraceEventBeginCommitCompositorFrame(event)) {\n beginCommitCompositorFrameEvents.push(event);\n return;\n }\n\n if (Types.TraceEvents.isTraceEventParseMetaViewport(event)) {\n parseMetaViewportEvents.push(event);\n return;\n }\n\n if (!Types.TraceEvents.isTraceEventEventTiming(event)) {\n return;\n }\n\n if (Types.TraceEvents.isTraceEventEventTimingEnd(event)) {\n // Store the end event; for each start event that is an interaction, we need the matching end event to calculate the duration correctly.\n eventTimingEndEventsById.set(event.id, event);\n }\n\n allEvents.push(event);\n\n // From this point on we want to find events that represent interactions.\n // These events are always start events - those are the ones that contain all\n // the metadata about the interaction.\n if (!event.args.data || !Types.TraceEvents.isTraceEventEventTimingStart(event)) {\n return;\n }\n const {duration, interactionId} = event.args.data;\n // We exclude events for the sake of interactions if:\n // 1. They have no duration.\n // 2. They have no interactionId\n // 3. They have an interactionId of 0: this indicates that it's not an\n // interaction that we care about because it hasn't had its own interactionId\n // set (0 is the default on the backend).\n // See: https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/timing/responsiveness_metrics.cc;l=133;drc=40c209a9c365ebb9f16fb99dfe78c7fe768b9594\n\n if (duration < 1 || interactionId === undefined || interactionId === 0) {\n return;\n }\n\n // Store the start event. In the finalize() function we will pair this with\n // its end event and create the synthetic interaction event.\n eventTimingStartEventsForInteractions.push(event);\n}\n\n/**\n * See https://web.dev/better-responsiveness-metric/#interaction-types for the\n * table that defines these sets.\n **/\nconst pointerEventTypes = new Set([\n 'pointerdown',\n 'touchstart',\n 'pointerup',\n 'touchend',\n 'mousedown',\n 'mouseup',\n 'click',\n]);\n\nconst keyboardEventTypes = new Set([\n 'keydown',\n 'keypress',\n 'keyup',\n]);\n\nexport type InteractionCategory = 'KEYBOARD'|'POINTER'|'OTHER';\nexport function categoryOfInteraction(interaction: Types.TraceEvents.SyntheticInteractionPair): InteractionCategory {\n if (pointerEventTypes.has(interaction.type)) {\n return 'POINTER';\n }\n if (keyboardEventTypes.has(interaction.type)) {\n return 'KEYBOARD';\n }\n\n return 'OTHER';\n}\n\n/**\n * We define a set of interactions as nested where:\n * 1. Their end times align.\n * 2. The longest interaction's start time is earlier than all other\n * interactions with the same end time.\n * 3. The interactions are of the same category [each interaction is either\n * categorised as keyboard, or pointer.]\n *\n * =============A=[pointerup]=\n * ====B=[pointerdown]=\n * ===C=[pointerdown]==\n * ===D=[pointerup]===\n *\n * In this example, B, C and D are all nested and therefore should not be\n * returned from this function.\n *\n * However, in this example we would only consider B nested (under A) and D\n * nested (under C). A and C both stay because they are of different types.\n * ========A=[keydown]====\n * =======B=[keyup]=====\n * ====C=[pointerdown]=\n * =D=[pointerup]=\n **/\nexport function removeNestedInteractions(interactions: readonly Types.TraceEvents.SyntheticInteractionPair[]):\n readonly Types.TraceEvents.SyntheticInteractionPair[] {\n /**\n * Because we nest events only that are in the same category, we store the\n * longest event for a given end time by category.\n **/\n const earliestEventForEndTimePerCategory:\n Record> = {\n POINTER: new Map(),\n KEYBOARD: new Map(),\n OTHER: new Map(),\n };\n\n function storeEventIfEarliestForCategoryAndEndTime(interaction: Types.TraceEvents.SyntheticInteractionPair): void {\n const category = categoryOfInteraction(interaction);\n const earliestEventForEndTime = earliestEventForEndTimePerCategory[category];\n const endTime = Types.Timing.MicroSeconds(interaction.ts + interaction.dur);\n\n const earliestCurrentEvent = earliestEventForEndTime.get(endTime);\n if (!earliestCurrentEvent) {\n earliestEventForEndTime.set(endTime, interaction);\n return;\n }\n if (interaction.ts < earliestCurrentEvent.ts) {\n earliestEventForEndTime.set(endTime, interaction);\n } else if (\n interaction.ts === earliestCurrentEvent.ts &&\n interaction.interactionId === earliestCurrentEvent.interactionId) {\n // We have seen in traces that the same interaction can have multiple\n // events (e.g. a 'click' and a 'pointerdown'). Often only one of these\n // events will have an event handler bound to it which caused delay on\n // the main thread, and the others will not. This leads to a situation\n // where if we pick one of the events that had no event handler, its\n // processing duration (processingEnd - processingStart) will be 0, but if we\n // had picked the event that had the slow event handler, we would show\n // correctly the main thread delay due to the event handler.\n // So, if we find events with the same interactionId and the same\n // begin/end times, we pick the one with the largest (processingEnd -\n // processingStart) time in order to make sure we find the event with the\n // worst main thread delay, as that is the one the user should care\n // about.\n const currentProcessingDuration = earliestCurrentEvent.processingEnd - earliestCurrentEvent.processingStart;\n const newProcessingDuration = interaction.processingEnd - interaction.processingStart;\n\n // Use the new interaction if it has a longer processing duration than the existing one.\n if (newProcessingDuration > currentProcessingDuration) {\n earliestEventForEndTime.set(endTime, interaction);\n }\n }\n\n // Maximize the processing duration based on the \"children\" interactions.\n // We pick the earliest start processing duration, and the latest end\n // processing duration to avoid under-reporting.\n if (interaction.processingStart < earliestCurrentEvent.processingStart) {\n earliestCurrentEvent.processingStart = interaction.processingStart;\n writeSyntheticTimespans(earliestCurrentEvent);\n }\n if (interaction.processingEnd > earliestCurrentEvent.processingEnd) {\n earliestCurrentEvent.processingEnd = interaction.processingEnd;\n writeSyntheticTimespans(earliestCurrentEvent);\n }\n }\n\n for (const interaction of interactions) {\n storeEventIfEarliestForCategoryAndEndTime(interaction);\n }\n\n // Combine all the events that we have kept from all the per-category event\n // maps back into an array and sort them by timestamp.\n const keptEvents = Object.values(earliestEventForEndTimePerCategory)\n .flatMap(eventsByEndTime => Array.from(eventsByEndTime.values()));\n keptEvents.sort((eventA, eventB) => {\n return eventA.ts - eventB.ts;\n });\n return keptEvents;\n}\n\nfunction writeSyntheticTimespans(event: Types.TraceEvents.SyntheticInteractionPair): void {\n const startEvent = event.args.data.beginEvent;\n const endEvent = event.args.data.endEvent;\n\n event.inputDelay = Types.Timing.MicroSeconds(event.processingStart - startEvent.ts);\n event.mainThreadHandling = Types.Timing.MicroSeconds(event.processingEnd - event.processingStart);\n event.presentationDelay = Types.Timing.MicroSeconds(endEvent.ts - event.processingEnd);\n}\n\nexport async function finalize(): Promise {\n const {navigationsByFrameId} = metaHandlerData();\n\n // For each interaction start event, find the async end event by the ID, and then create the Synthetic Interaction event.\n for (const interactionStartEvent of eventTimingStartEventsForInteractions) {\n const endEvent = eventTimingEndEventsById.get(interactionStartEvent.id);\n if (!endEvent) {\n // If we cannot find an end event, bail and drop this event.\n continue;\n }\n if (!interactionStartEvent.args.data?.type || !interactionStartEvent.args.data?.interactionId) {\n // A valid interaction event that we care about has to have a type (e.g.\n // pointerdown, keyup).\n //\n // We also need to ensure it has an interactionId. We already checked\n // this in the handleEvent() function, but we do it here also to satisfy\n // TypeScript.\n continue;\n }\n\n // In the future we will add microsecond timestamps to the trace events,\n // but until then we can use the millisecond precision values that are in\n // the trace event. To adjust them to be relative to the event.ts and the\n // trace timestamps, for both processingStart and processingEnd we subtract\n // the event timestamp (NOT event.ts, but the timeStamp millisecond value\n // emitted in args.data), and then add that value to the event.ts. This\n // will give us a processingStart and processingEnd time in microseconds\n // that is relative to event.ts, and can be used when drawing boxes.\n // There is some inaccuracy here as we are converting milliseconds to microseconds, but it is good enough until the backend emits more accurate numbers.\n const processingStartRelativeToTraceTime = Types.Timing.MicroSeconds(\n Helpers.Timing.millisecondsToMicroseconds(interactionStartEvent.args.data.processingStart) -\n Helpers.Timing.millisecondsToMicroseconds(interactionStartEvent.args.data.timeStamp) +\n interactionStartEvent.ts,\n );\n\n const processingEndRelativeToTraceTime = Types.Timing.MicroSeconds(\n (Helpers.Timing.millisecondsToMicroseconds(interactionStartEvent.args.data.processingEnd) -\n Helpers.Timing.millisecondsToMicroseconds(interactionStartEvent.args.data.timeStamp)) +\n interactionStartEvent.ts);\n\n const frameId = interactionStartEvent.args.frame ?? interactionStartEvent.args.data.frame;\n const navigation = Helpers.Trace.getNavigationForTraceEvent(interactionStartEvent, frameId, navigationsByFrameId);\n const navigationId = navigation?.args.data?.navigationId;\n const interactionEvent = Helpers.SyntheticEvents.SyntheticEventsManager\n .registerSyntheticBasedEvent({\n // Use the start event to define the common fields.\n rawSourceEvent: interactionStartEvent,\n cat: interactionStartEvent.cat,\n name: interactionStartEvent.name,\n pid: interactionStartEvent.pid,\n tid: interactionStartEvent.tid,\n ph: interactionStartEvent.ph,\n processingStart: processingStartRelativeToTraceTime,\n processingEnd: processingEndRelativeToTraceTime,\n // These will be set in writeSyntheticTimespans()\n inputDelay: Types.Timing.MicroSeconds(-1),\n mainThreadHandling: Types.Timing.MicroSeconds(-1),\n presentationDelay: Types.Timing.MicroSeconds(-1),\n args: {\n data: {\n beginEvent: interactionStartEvent,\n endEvent,\n frame: frameId,\n navigationId,\n },\n },\n ts: interactionStartEvent.ts,\n dur: Types.Timing.MicroSeconds(endEvent.ts - interactionStartEvent.ts),\n type: interactionStartEvent.args.data.type,\n interactionId: interactionStartEvent.args.data.interactionId,\n });\n writeSyntheticTimespans(interactionEvent);\n\n interactionEvents.push(interactionEvent);\n }\n\n handlerState = HandlerState.FINALIZED;\n interactionEventsWithNoNesting.push(...removeNestedInteractions(interactionEvents));\n\n // Pick the longest interactions from the set that were not nested, as we\n // know those are the set of the largest interactions.\n for (const interactionEvent of interactionEventsWithNoNesting) {\n if (!longestInteractionEvent || longestInteractionEvent.dur < interactionEvent.dur) {\n longestInteractionEvent = interactionEvent;\n }\n }\n}\n\nexport function data(): UserInteractionsData {\n return {\n allEvents,\n beginCommitCompositorFrameEvents,\n parseMetaViewportEvents,\n interactionEvents,\n interactionEventsWithNoNesting,\n longestInteractionEvent,\n interactionsOverThreshold: new Set(interactionEvents.filter(event => {\n return event.dur > LONG_INTERACTION_THRESHOLD;\n })),\n };\n}\n\nexport function deps(): TraceEventHandlerName[] {\n return ['Meta'];\n}\n\n/**\n * Classifications sourced from\n * https://web.dev/articles/inp#good-score\n */\nexport function scoreClassificationForInteractionToNextPaint(timing: Types.Timing.MicroSeconds): ScoreClassification {\n if (timing <= INP_GOOD_TIMING) {\n return ScoreClassification.GOOD;\n }\n\n if (timing <= INP_MEDIUM_TIMING) {\n return ScoreClassification.OK;\n }\n\n return ScoreClassification.BAD;\n}\n"]} \ No newline at end of file +{"version":3,"file":"UserInteractionsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/UserInteractionsHandler.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAE3C,OAAO,EAAC,IAAI,IAAI,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAIzD,2EAA2E;AAC3E,sEAAsE;AACtE,wEAAwE;AACxE,2DAA2D;AAE3D,yEAAyE;AACzE,0EAA0E;AAC1E,MAAM,SAAS,GAA+B,EAAE,CAAC;AAEjD,MAAM,gCAAgC,GAA8C,EAAE,CAAC;AACvF,MAAM,uBAAuB,GAAqC,EAAE,CAAC;AAErE,MAAM,CAAC,MAAM,0BAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;AAEpH,MAAM,eAAe,GAAG,0BAA0B,CAAC;AACnD,MAAM,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;AAkCpG,IAAI,uBAAuB,GAA+C,IAAI,CAAC;AAE/E,MAAM,iBAAiB,GAA4C,EAAE,CAAC;AACtE,MAAM,8BAA8B,GAA4C,EAAE,CAAC;AACnF,MAAM,wBAAwB,GAAG,IAAI,GAAG,EAAuC,CAAC;AAChF,MAAM,qCAAqC,GAAoC,EAAE,CAAC;AAClF,IAAI,YAAY,qCAA6B,CAAC;AAE9C,MAAM,UAAU,KAAK;IACnB,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;IACrB,gCAAgC,CAAC,MAAM,GAAG,CAAC,CAAC;IAC5C,uBAAuB,CAAC,MAAM,GAAG,CAAC,CAAC;IACnC,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC;IAC7B,qCAAqC,CAAC,MAAM,GAAG,CAAC,CAAC;IACjD,wBAAwB,CAAC,KAAK,EAAE,CAAC;IACjC,8BAA8B,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1C,uBAAuB,GAAG,IAAI,CAAC;IAC/B,YAAY,mCAA2B,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAyB;IACnD,IAAI,YAAY,qCAA6B,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAChD,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,4BAA4B,CAAC,KAAK,CAAC,EAAE,CAAC;QACrD,gCAAgC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7C,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5C,uBAAuB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpC,OAAO;IACT,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QACvC,OAAO;IACT,CAAC;IAED,IAAI,KAAK,CAAC,MAAM,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,CAAC;QACzC,wIAAwI;QACxI,wBAAwB,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAChD,CAAC;IAED,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAEtB,yEAAyE;IACzE,6EAA6E;IAC7E,sCAAsC;IACtC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;QAChE,OAAO;IACT,CAAC;IACD,MAAM,EAAC,QAAQ,EAAE,aAAa,EAAC,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC;IAClD,qDAAqD;IACrD,4BAA4B;IAC5B,gCAAgC;IAChC,sEAAsE;IACtE,gFAAgF;IAChF,4CAA4C;IAC5C,oLAAoL;IAEpL,IAAI,QAAQ,GAAG,CAAC,IAAI,aAAa,KAAK,SAAS,IAAI,aAAa,KAAK,CAAC,EAAE,CAAC;QACvE,OAAO;IACT,CAAC;IAED,2EAA2E;IAC3E,4DAA4D;IAC5D,qCAAqC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACpD,CAAC;AAED;;;IAGI;AACJ,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC;IAChC,aAAa;IACb,YAAY;IACZ,WAAW;IACX,UAAU;IACV,WAAW;IACX,SAAS;IACT,OAAO;CACR,CAAC,CAAC;AAEH,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC;IACjC,SAAS;IACT,UAAU;IACV,OAAO;CACR,CAAC,CAAC;AAGH,MAAM,UAAU,qBAAqB,CAAC,WAAkD;IACtF,IAAI,iBAAiB,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QAC5C,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,kBAAkB,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7C,OAAO,UAAU,CAAC;IACpB,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;IAsBI;AACJ,MAAM,UAAU,wBAAwB,CAAC,YAA8D;IAErG;;;QAGI;IACJ,MAAM,kCAAkC,GACiE;QACnG,OAAO,EAAE,IAAI,GAAG,EAAE;QAClB,QAAQ,EAAE,IAAI,GAAG,EAAE;QACnB,KAAK,EAAE,IAAI,GAAG,EAAE;KACjB,CAAC;IAEN,SAAS,yCAAyC,CAAC,WAAkD;QACnG,MAAM,QAAQ,GAAG,qBAAqB,CAAC,WAAW,CAAC,CAAC;QACpD,MAAM,uBAAuB,GAAG,kCAAkC,CAAC,QAAQ,CAAC,CAAC;QAC7E,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,WAAW,CAAC,EAAE,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;QAE5E,MAAM,oBAAoB,GAAG,uBAAuB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAClE,IAAI,CAAC,oBAAoB,EAAE,CAAC;YAC1B,uBAAuB,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;YAClD,OAAO;QACT,CAAC;QACD,IAAI,WAAW,CAAC,EAAE,GAAG,oBAAoB,CAAC,EAAE,EAAE,CAAC;YAC7C,uBAAuB,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;QACpD,CAAC;aAAM,IACH,WAAW,CAAC,EAAE,KAAK,oBAAoB,CAAC,EAAE;YAC1C,WAAW,CAAC,aAAa,KAAK,oBAAoB,CAAC,aAAa,EAAE,CAAC;YACrE,qEAAqE;YACrE,uEAAuE;YACvE,sEAAsE;YACtE,sEAAsE;YACtE,oEAAoE;YACpE,6EAA6E;YAC7E,sEAAsE;YACtE,4DAA4D;YAC5D,iEAAiE;YACjE,qEAAqE;YACrE,yEAAyE;YACzE,mEAAmE;YACnE,SAAS;YACT,MAAM,yBAAyB,GAAG,oBAAoB,CAAC,aAAa,GAAG,oBAAoB,CAAC,eAAe,CAAC;YAC5G,MAAM,qBAAqB,GAAG,WAAW,CAAC,aAAa,GAAG,WAAW,CAAC,eAAe,CAAC;YAEtF,wFAAwF;YACxF,IAAI,qBAAqB,GAAG,yBAAyB,EAAE,CAAC;gBACtD,uBAAuB,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;QAED,yEAAyE;QACzE,qEAAqE;QACrE,gDAAgD;QAChD,IAAI,WAAW,CAAC,eAAe,GAAG,oBAAoB,CAAC,eAAe,EAAE,CAAC;YACvE,oBAAoB,CAAC,eAAe,GAAG,WAAW,CAAC,eAAe,CAAC;YACnE,uBAAuB,CAAC,oBAAoB,CAAC,CAAC;QAChD,CAAC;QACD,IAAI,WAAW,CAAC,aAAa,GAAG,oBAAoB,CAAC,aAAa,EAAE,CAAC;YACnE,oBAAoB,CAAC,aAAa,GAAG,WAAW,CAAC,aAAa,CAAC;YAC/D,uBAAuB,CAAC,oBAAoB,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IAED,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;QACvC,yCAAyC,CAAC,WAAW,CAAC,CAAC;IACzD,CAAC;IAED,2EAA2E;IAC3E,sDAAsD;IACtD,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,kCAAkC,CAAC;SAC5C,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACzF,UAAU,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE;QACjC,OAAO,MAAM,CAAC,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC;IAC/B,CAAC,CAAC,CAAC;IACH,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAS,uBAAuB,CAAC,KAA4C;IAC3E,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;IAC9C,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;IAE1C,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,eAAe,GAAG,UAAU,CAAC,EAAE,CAAC,CAAC;IACpF,KAAK,CAAC,kBAAkB,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,aAAa,GAAG,KAAK,CAAC,eAAe,CAAC,CAAC;IAClG,KAAK,CAAC,iBAAiB,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,GAAG,KAAK,CAAC,aAAa,CAAC,CAAC;AACzF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,MAAM,EAAC,oBAAoB,EAAC,GAAG,eAAe,EAAE,CAAC;IAEjD,yHAAyH;IACzH,KAAK,MAAM,qBAAqB,IAAI,qCAAqC,EAAE,CAAC;QAC1E,MAAM,QAAQ,GAAG,wBAAwB,CAAC,GAAG,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC;QACxE,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,4DAA4D;YAC5D,SAAS;QACX,CAAC;QACD,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,EAAE,aAAa,EAAE,CAAC;YAC9F,wEAAwE;YACxE,uBAAuB;YACvB,EAAE;YACF,qEAAqE;YACrE,wEAAwE;YACxE,cAAc;YACd,SAAS;QACX,CAAC;QAED,wEAAwE;QACxE,yEAAyE;QACzE,yEAAyE;QACzE,2EAA2E;QAC3E,yEAAyE;QACzE,uEAAuE;QACvE,wEAAwE;QACxE,oEAAoE;QACpE,wJAAwJ;QACxJ,MAAM,kCAAkC,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAChE,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC;YACtF,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;YACpF,qBAAqB,CAAC,EAAE,CAC/B,CAAC;QAEF,MAAM,gCAAgC,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAC9D,CAAC,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;YACxF,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YACtF,qBAAqB,CAAC,EAAE,CAAC,CAAC;QAE9B,MAAM,OAAO,GAAG,qBAAqB,CAAC,IAAI,CAAC,KAAK,IAAI,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QAC1F,MAAM,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,qBAAqB,EAAE,OAAO,EAAE,oBAAoB,CAAC,CAAC;QAClH,MAAM,YAAY,GAAG,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC;QACzD,MAAM,gBAAgB,GAClB,OAAO,CAAC,eAAe,CAAC,sBAAsB,CAAC,sBAAsB,CAAwC;YAC3G,mDAAmD;YACnD,cAAc,EAAE,qBAAqB;YACrC,GAAG,EAAE,qBAAqB,CAAC,GAAG;YAC9B,IAAI,EAAE,qBAAqB,CAAC,IAAI;YAChC,GAAG,EAAE,qBAAqB,CAAC,GAAG;YAC9B,GAAG,EAAE,qBAAqB,CAAC,GAAG;YAC9B,EAAE,EAAE,qBAAqB,CAAC,EAAE;YAC5B,eAAe,EAAE,kCAAkC;YACnD,aAAa,EAAE,gCAAgC;YAC/C,iDAAiD;YACjD,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YACzC,kBAAkB,EAAE,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YACjD,iBAAiB,EAAE,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAChD,IAAI,EAAE;gBACJ,IAAI,EAAE;oBACJ,UAAU,EAAE,qBAAqB;oBACjC,QAAQ;oBACR,KAAK,EAAE,OAAO;oBACd,YAAY;iBACb;aACF;YACD,EAAE,EAAE,qBAAqB,CAAC,EAAE;YAC5B,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,GAAG,qBAAqB,CAAC,EAAE,CAAC;YACtE,IAAI,EAAE,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;YAC1C,aAAa,EAAE,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa;SAC7D,CAAC,CAAC;QACP,uBAAuB,CAAC,gBAAgB,CAAC,CAAC;QAE1C,iBAAiB,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC3C,CAAC;IAED,YAAY,iCAAyB,CAAC;IACtC,8BAA8B,CAAC,IAAI,CAAC,GAAG,wBAAwB,CAAC,iBAAiB,CAAC,CAAC,CAAC;IAEpF,yEAAyE;IACzE,sDAAsD;IACtD,KAAK,MAAM,gBAAgB,IAAI,8BAA8B,EAAE,CAAC;QAC9D,IAAI,CAAC,uBAAuB,IAAI,uBAAuB,CAAC,GAAG,GAAG,gBAAgB,CAAC,GAAG,EAAE,CAAC;YACnF,uBAAuB,GAAG,gBAAgB,CAAC;QAC7C,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,UAAU,IAAI;IAClB,OAAO;QACL,SAAS;QACT,gCAAgC;QAChC,uBAAuB;QACvB,iBAAiB;QACjB,8BAA8B;QAC9B,uBAAuB;QACvB,yBAAyB,EAAE,IAAI,GAAG,CAAC,iBAAiB,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;YAClE,OAAO,KAAK,CAAC,GAAG,GAAG,0BAA0B,CAAC;QAChD,CAAC,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,MAAM,CAAC,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,4CAA4C,CAAC,MAAiC;IAC5F,IAAI,MAAM,IAAI,eAAe,EAAE,CAAC;QAC9B,6CAAgC;IAClC,CAAC;IAED,IAAI,MAAM,IAAI,iBAAiB,EAAE,CAAC;QAChC,yCAA8B;IAChC,CAAC;IAED,2CAA+B;AACjC,CAAC","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {data as metaHandlerData} from './MetaHandler.js';\nimport {ScoreClassification} from './PageLoadMetricsHandler.js';\nimport {type HandlerName, HandlerState} from './types.js';\n\n// This handler serves two purposes. It generates a list of events that are\n// used to show user clicks in the timeline. It is also used to gather\n// EventTimings into Interactions, which we use to show interactions and\n// highlight long interactions to the user, along with INP.\n\n// We don't need to know which process / thread these events occurred in,\n// because they are effectively global, so we just track all that we find.\nconst allEvents: Types.Events.EventTiming[] = [];\n\nconst beginCommitCompositorFrameEvents: Types.Events.BeginCommitCompositorFrame[] = [];\nconst parseMetaViewportEvents: Types.Events.ParseMetaViewport[] = [];\n\nexport const LONG_INTERACTION_THRESHOLD = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(200));\n\nconst INP_GOOD_TIMING = LONG_INTERACTION_THRESHOLD;\nconst INP_MEDIUM_TIMING = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(500));\n\nexport interface UserInteractionsData {\n /** All the user events we found in the trace */\n allEvents: readonly Types.Events.EventTiming[];\n /** All the BeginCommitCompositorFrame events we found in the trace */\n beginCommitCompositorFrameEvents: readonly Types.Events.BeginCommitCompositorFrame[];\n /** All the ParseMetaViewport events we found in the trace */\n parseMetaViewportEvents: readonly Types.Events.ParseMetaViewport[];\n /** All the interaction events we found in the trace that had an\n * interactionId and a duration > 0\n **/\n interactionEvents: readonly Types.Events.SyntheticInteractionPair[];\n /** If the user rapidly generates interaction events (think typing into a\n * text box), in the UI we only really want to show the user the longest\n * interaction in that set.\n * For example picture interactions like this:\n * ===[interaction A]==========\n * =[interaction B]======\n * =[interaction C]=\n *\n * These events all end at the same time, and so in this instance we only want\n * to show the first interaction A on the timeline, as that is the longest one\n * and the one the developer should be focusing on. So this array of events is\n * all the interaction events filtered down, removing any nested interactions\n * entirely.\n **/\n interactionEventsWithNoNesting: readonly Types.Events.SyntheticInteractionPair[];\n // The longest duration interaction event. Can be null if the trace has no interaction events.\n longestInteractionEvent: Readonly|null;\n // All interactions that went over the interaction threshold (200ms, see https://web.dev/inp/)\n interactionsOverThreshold: Readonly>;\n}\n\nlet longestInteractionEvent: Types.Events.SyntheticInteractionPair|null = null;\n\nconst interactionEvents: Types.Events.SyntheticInteractionPair[] = [];\nconst interactionEventsWithNoNesting: Types.Events.SyntheticInteractionPair[] = [];\nconst eventTimingEndEventsById = new Map();\nconst eventTimingStartEventsForInteractions: Types.Events.EventTimingBegin[] = [];\nlet handlerState = HandlerState.UNINITIALIZED;\n\nexport function reset(): void {\n allEvents.length = 0;\n beginCommitCompositorFrameEvents.length = 0;\n parseMetaViewportEvents.length = 0;\n interactionEvents.length = 0;\n eventTimingStartEventsForInteractions.length = 0;\n eventTimingEndEventsById.clear();\n interactionEventsWithNoNesting.length = 0;\n longestInteractionEvent = null;\n handlerState = HandlerState.INITIALIZED;\n}\n\nexport function handleEvent(event: Types.Events.Event): void {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Handler is not initialized');\n }\n\n if (Types.Events.isBeginCommitCompositorFrame(event)) {\n beginCommitCompositorFrameEvents.push(event);\n return;\n }\n\n if (Types.Events.isParseMetaViewport(event)) {\n parseMetaViewportEvents.push(event);\n return;\n }\n\n if (!Types.Events.isEventTiming(event)) {\n return;\n }\n\n if (Types.Events.isEventTimingEnd(event)) {\n // Store the end event; for each start event that is an interaction, we need the matching end event to calculate the duration correctly.\n eventTimingEndEventsById.set(event.id, event);\n }\n\n allEvents.push(event);\n\n // From this point on we want to find events that represent interactions.\n // These events are always start events - those are the ones that contain all\n // the metadata about the interaction.\n if (!event.args.data || !Types.Events.isEventTimingStart(event)) {\n return;\n }\n const {duration, interactionId} = event.args.data;\n // We exclude events for the sake of interactions if:\n // 1. They have no duration.\n // 2. They have no interactionId\n // 3. They have an interactionId of 0: this indicates that it's not an\n // interaction that we care about because it hasn't had its own interactionId\n // set (0 is the default on the backend).\n // See: https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/timing/responsiveness_metrics.cc;l=133;drc=40c209a9c365ebb9f16fb99dfe78c7fe768b9594\n\n if (duration < 1 || interactionId === undefined || interactionId === 0) {\n return;\n }\n\n // Store the start event. In the finalize() function we will pair this with\n // its end event and create the synthetic interaction event.\n eventTimingStartEventsForInteractions.push(event);\n}\n\n/**\n * See https://web.dev/better-responsiveness-metric/#interaction-types for the\n * table that defines these sets.\n **/\nconst pointerEventTypes = new Set([\n 'pointerdown',\n 'touchstart',\n 'pointerup',\n 'touchend',\n 'mousedown',\n 'mouseup',\n 'click',\n]);\n\nconst keyboardEventTypes = new Set([\n 'keydown',\n 'keypress',\n 'keyup',\n]);\n\nexport type InteractionCategory = 'KEYBOARD'|'POINTER'|'OTHER';\nexport function categoryOfInteraction(interaction: Types.Events.SyntheticInteractionPair): InteractionCategory {\n if (pointerEventTypes.has(interaction.type)) {\n return 'POINTER';\n }\n if (keyboardEventTypes.has(interaction.type)) {\n return 'KEYBOARD';\n }\n\n return 'OTHER';\n}\n\n/**\n * We define a set of interactions as nested where:\n * 1. Their end times align.\n * 2. The longest interaction's start time is earlier than all other\n * interactions with the same end time.\n * 3. The interactions are of the same category [each interaction is either\n * categorised as keyboard, or pointer.]\n *\n * =============A=[pointerup]=\n * ====B=[pointerdown]=\n * ===C=[pointerdown]==\n * ===D=[pointerup]===\n *\n * In this example, B, C and D are all nested and therefore should not be\n * returned from this function.\n *\n * However, in this example we would only consider B nested (under A) and D\n * nested (under C). A and C both stay because they are of different types.\n * ========A=[keydown]====\n * =======B=[keyup]=====\n * ====C=[pointerdown]=\n * =D=[pointerup]=\n **/\nexport function removeNestedInteractions(interactions: readonly Types.Events.SyntheticInteractionPair[]):\n readonly Types.Events.SyntheticInteractionPair[] {\n /**\n * Because we nest events only that are in the same category, we store the\n * longest event for a given end time by category.\n **/\n const earliestEventForEndTimePerCategory:\n Record> = {\n POINTER: new Map(),\n KEYBOARD: new Map(),\n OTHER: new Map(),\n };\n\n function storeEventIfEarliestForCategoryAndEndTime(interaction: Types.Events.SyntheticInteractionPair): void {\n const category = categoryOfInteraction(interaction);\n const earliestEventForEndTime = earliestEventForEndTimePerCategory[category];\n const endTime = Types.Timing.MicroSeconds(interaction.ts + interaction.dur);\n\n const earliestCurrentEvent = earliestEventForEndTime.get(endTime);\n if (!earliestCurrentEvent) {\n earliestEventForEndTime.set(endTime, interaction);\n return;\n }\n if (interaction.ts < earliestCurrentEvent.ts) {\n earliestEventForEndTime.set(endTime, interaction);\n } else if (\n interaction.ts === earliestCurrentEvent.ts &&\n interaction.interactionId === earliestCurrentEvent.interactionId) {\n // We have seen in traces that the same interaction can have multiple\n // events (e.g. a 'click' and a 'pointerdown'). Often only one of these\n // events will have an event handler bound to it which caused delay on\n // the main thread, and the others will not. This leads to a situation\n // where if we pick one of the events that had no event handler, its\n // processing duration (processingEnd - processingStart) will be 0, but if we\n // had picked the event that had the slow event handler, we would show\n // correctly the main thread delay due to the event handler.\n // So, if we find events with the same interactionId and the same\n // begin/end times, we pick the one with the largest (processingEnd -\n // processingStart) time in order to make sure we find the event with the\n // worst main thread delay, as that is the one the user should care\n // about.\n const currentProcessingDuration = earliestCurrentEvent.processingEnd - earliestCurrentEvent.processingStart;\n const newProcessingDuration = interaction.processingEnd - interaction.processingStart;\n\n // Use the new interaction if it has a longer processing duration than the existing one.\n if (newProcessingDuration > currentProcessingDuration) {\n earliestEventForEndTime.set(endTime, interaction);\n }\n }\n\n // Maximize the processing duration based on the \"children\" interactions.\n // We pick the earliest start processing duration, and the latest end\n // processing duration to avoid under-reporting.\n if (interaction.processingStart < earliestCurrentEvent.processingStart) {\n earliestCurrentEvent.processingStart = interaction.processingStart;\n writeSyntheticTimespans(earliestCurrentEvent);\n }\n if (interaction.processingEnd > earliestCurrentEvent.processingEnd) {\n earliestCurrentEvent.processingEnd = interaction.processingEnd;\n writeSyntheticTimespans(earliestCurrentEvent);\n }\n }\n\n for (const interaction of interactions) {\n storeEventIfEarliestForCategoryAndEndTime(interaction);\n }\n\n // Combine all the events that we have kept from all the per-category event\n // maps back into an array and sort them by timestamp.\n const keptEvents = Object.values(earliestEventForEndTimePerCategory)\n .flatMap(eventsByEndTime => Array.from(eventsByEndTime.values()));\n keptEvents.sort((eventA, eventB) => {\n return eventA.ts - eventB.ts;\n });\n return keptEvents;\n}\n\nfunction writeSyntheticTimespans(event: Types.Events.SyntheticInteractionPair): void {\n const startEvent = event.args.data.beginEvent;\n const endEvent = event.args.data.endEvent;\n\n event.inputDelay = Types.Timing.MicroSeconds(event.processingStart - startEvent.ts);\n event.mainThreadHandling = Types.Timing.MicroSeconds(event.processingEnd - event.processingStart);\n event.presentationDelay = Types.Timing.MicroSeconds(endEvent.ts - event.processingEnd);\n}\n\nexport async function finalize(): Promise {\n const {navigationsByFrameId} = metaHandlerData();\n\n // For each interaction start event, find the async end event by the ID, and then create the Synthetic Interaction event.\n for (const interactionStartEvent of eventTimingStartEventsForInteractions) {\n const endEvent = eventTimingEndEventsById.get(interactionStartEvent.id);\n if (!endEvent) {\n // If we cannot find an end event, bail and drop this event.\n continue;\n }\n if (!interactionStartEvent.args.data?.type || !interactionStartEvent.args.data?.interactionId) {\n // A valid interaction event that we care about has to have a type (e.g.\n // pointerdown, keyup).\n //\n // We also need to ensure it has an interactionId. We already checked\n // this in the handleEvent() function, but we do it here also to satisfy\n // TypeScript.\n continue;\n }\n\n // In the future we will add microsecond timestamps to the trace events,\n // but until then we can use the millisecond precision values that are in\n // the trace event. To adjust them to be relative to the event.ts and the\n // trace timestamps, for both processingStart and processingEnd we subtract\n // the event timestamp (NOT event.ts, but the timeStamp millisecond value\n // emitted in args.data), and then add that value to the event.ts. This\n // will give us a processingStart and processingEnd time in microseconds\n // that is relative to event.ts, and can be used when drawing boxes.\n // There is some inaccuracy here as we are converting milliseconds to microseconds, but it is good enough until the backend emits more accurate numbers.\n const processingStartRelativeToTraceTime = Types.Timing.MicroSeconds(\n Helpers.Timing.millisecondsToMicroseconds(interactionStartEvent.args.data.processingStart) -\n Helpers.Timing.millisecondsToMicroseconds(interactionStartEvent.args.data.timeStamp) +\n interactionStartEvent.ts,\n );\n\n const processingEndRelativeToTraceTime = Types.Timing.MicroSeconds(\n (Helpers.Timing.millisecondsToMicroseconds(interactionStartEvent.args.data.processingEnd) -\n Helpers.Timing.millisecondsToMicroseconds(interactionStartEvent.args.data.timeStamp)) +\n interactionStartEvent.ts);\n\n const frameId = interactionStartEvent.args.frame ?? interactionStartEvent.args.data.frame;\n const navigation = Helpers.Trace.getNavigationForTraceEvent(interactionStartEvent, frameId, navigationsByFrameId);\n const navigationId = navigation?.args.data?.navigationId;\n const interactionEvent =\n Helpers.SyntheticEvents.SyntheticEventsManager.registerSyntheticEvent({\n // Use the start event to define the common fields.\n rawSourceEvent: interactionStartEvent,\n cat: interactionStartEvent.cat,\n name: interactionStartEvent.name,\n pid: interactionStartEvent.pid,\n tid: interactionStartEvent.tid,\n ph: interactionStartEvent.ph,\n processingStart: processingStartRelativeToTraceTime,\n processingEnd: processingEndRelativeToTraceTime,\n // These will be set in writeSyntheticTimespans()\n inputDelay: Types.Timing.MicroSeconds(-1),\n mainThreadHandling: Types.Timing.MicroSeconds(-1),\n presentationDelay: Types.Timing.MicroSeconds(-1),\n args: {\n data: {\n beginEvent: interactionStartEvent,\n endEvent,\n frame: frameId,\n navigationId,\n },\n },\n ts: interactionStartEvent.ts,\n dur: Types.Timing.MicroSeconds(endEvent.ts - interactionStartEvent.ts),\n type: interactionStartEvent.args.data.type,\n interactionId: interactionStartEvent.args.data.interactionId,\n });\n writeSyntheticTimespans(interactionEvent);\n\n interactionEvents.push(interactionEvent);\n }\n\n handlerState = HandlerState.FINALIZED;\n interactionEventsWithNoNesting.push(...removeNestedInteractions(interactionEvents));\n\n // Pick the longest interactions from the set that were not nested, as we\n // know those are the set of the largest interactions.\n for (const interactionEvent of interactionEventsWithNoNesting) {\n if (!longestInteractionEvent || longestInteractionEvent.dur < interactionEvent.dur) {\n longestInteractionEvent = interactionEvent;\n }\n }\n}\n\nexport function data(): UserInteractionsData {\n return {\n allEvents,\n beginCommitCompositorFrameEvents,\n parseMetaViewportEvents,\n interactionEvents,\n interactionEventsWithNoNesting,\n longestInteractionEvent,\n interactionsOverThreshold: new Set(interactionEvents.filter(event => {\n return event.dur > LONG_INTERACTION_THRESHOLD;\n })),\n };\n}\n\nexport function deps(): HandlerName[] {\n return ['Meta'];\n}\n\n/**\n * Classifications sourced from\n * https://web.dev/articles/inp#good-score\n */\nexport function scoreClassificationForInteractionToNextPaint(timing: Types.Timing.MicroSeconds): ScoreClassification {\n if (timing <= INP_GOOD_TIMING) {\n return ScoreClassification.GOOD;\n }\n\n if (timing <= INP_MEDIUM_TIMING) {\n return ScoreClassification.OK;\n }\n\n return ScoreClassification.BAD;\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/UserInteractionsHandler.test.js b/public/models/trace/handlers/UserInteractionsHandler.test.js index 3396c45de..2b7674244 100644 --- a/public/models/trace/handlers/UserInteractionsHandler.test.js +++ b/public/models/trace/handlers/UserInteractionsHandler.test.js @@ -2,55 +2,55 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import { TraceLoader } from '../../../testing/TraceLoader.js'; -import * as TraceModel from '../trace.js'; +import * as Trace from '../trace.js'; async function processTrace(context, path) { const traceEvents = await TraceLoader.rawEvents(context, path); - TraceModel.Handlers.ModelHandlers.Meta.reset(); - TraceModel.Handlers.ModelHandlers.Meta.initialize(); + Trace.Handlers.ModelHandlers.Meta.reset(); + Trace.Handlers.ModelHandlers.Meta.initialize(); for (const event of traceEvents) { - TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event); - TraceModel.Handlers.ModelHandlers.UserInteractions.handleEvent(event); + Trace.Handlers.ModelHandlers.Meta.handleEvent(event); + Trace.Handlers.ModelHandlers.UserInteractions.handleEvent(event); } - await TraceModel.Handlers.ModelHandlers.Meta.finalize(); - await TraceModel.Handlers.ModelHandlers.UserInteractions.finalize(); + await Trace.Handlers.ModelHandlers.Meta.finalize(); + await Trace.Handlers.ModelHandlers.UserInteractions.finalize(); } beforeEach(() => { - TraceModel.Handlers.ModelHandlers.Meta.reset(); - TraceModel.Handlers.ModelHandlers.Meta.initialize(); + Trace.Handlers.ModelHandlers.Meta.reset(); + Trace.Handlers.ModelHandlers.Meta.initialize(); }); describe('UserInteractionsHandler', function () { function makeFakeInteraction(type, options) { const event = { name: 'EventTiming', type, - ts: TraceModel.Types.Timing.MicroSeconds(options.startTime), - dur: TraceModel.Types.Timing.MicroSeconds(options.endTime - options.startTime), - processingStart: TraceModel.Types.Timing.MicroSeconds(options.processingStart || 0), - processingEnd: TraceModel.Types.Timing.MicroSeconds(options.processingEnd || 0), + ts: Trace.Types.Timing.MicroSeconds(options.startTime), + dur: Trace.Types.Timing.MicroSeconds(options.endTime - options.startTime), + processingStart: Trace.Types.Timing.MicroSeconds(options.processingStart || 0), + processingEnd: Trace.Types.Timing.MicroSeconds(options.processingEnd || 0), interactionId: options.interactionId, }; return event; } describe('error handling', () => { it('throws if not initialized', async () => { - TraceModel.Handlers.ModelHandlers.Meta.reset(); - TraceModel.Handlers.ModelHandlers.Meta.initialize(); + Trace.Handlers.ModelHandlers.Meta.reset(); + Trace.Handlers.ModelHandlers.Meta.initialize(); // Finalize the handler by calling data and then finalize on it. - TraceModel.Handlers.ModelHandlers.UserInteractions.data(); - await TraceModel.Handlers.ModelHandlers.Meta.finalize(); - await TraceModel.Handlers.ModelHandlers.UserInteractions.finalize(); + Trace.Handlers.ModelHandlers.UserInteractions.data(); + await Trace.Handlers.ModelHandlers.Meta.finalize(); + await Trace.Handlers.ModelHandlers.UserInteractions.finalize(); assert.throws(() => { const fakeEvent = {}; - TraceModel.Handlers.ModelHandlers.UserInteractions.handleEvent(fakeEvent); + Trace.Handlers.ModelHandlers.UserInteractions.handleEvent(fakeEvent); }, 'Handler is not initialized'); }); }); it('returns all user interactions', async function () { const traceEvents = await TraceLoader.rawEvents(this, 'slow-interaction-button-click.json.gz'); for (const event of traceEvents) { - TraceModel.Handlers.ModelHandlers.UserInteractions.handleEvent(event); + Trace.Handlers.ModelHandlers.UserInteractions.handleEvent(event); } - const data = TraceModel.Handlers.ModelHandlers.UserInteractions.data(); + const data = Trace.Handlers.ModelHandlers.UserInteractions.data(); const clicks = data.allEvents.filter(event => { if (!event.args.data) { return false; @@ -62,7 +62,7 @@ describe('UserInteractionsHandler', function () { }); it('returns all interaction events', async () => { await processTrace(this, 'slow-interaction-button-click.json.gz'); - const data = TraceModel.Handlers.ModelHandlers.UserInteractions.data(); + const data = Trace.Handlers.ModelHandlers.UserInteractions.data(); // There are three inct interactions: // pointerdown on the button (start of the click) // pointerup & click on the button (end of the click) @@ -70,7 +70,7 @@ describe('UserInteractionsHandler', function () { }); it('adds microsecond processingStart and processingEnd times to the synthetic event', async function () { await processTrace(this, 'one-second-interaction.json.gz'); - const data = TraceModel.Handlers.ModelHandlers.UserInteractions.data(); + const data = Trace.Handlers.ModelHandlers.UserInteractions.data(); const oneSecondInteraction = Array.from(data.interactionEvents).find(entry => { return entry.dur === 979974 && entry.type === 'click'; }); @@ -82,7 +82,7 @@ describe('UserInteractionsHandler', function () { }); it('adds the INP phases to the interaction', async function () { await processTrace(this, 'one-second-interaction.json.gz'); - const data = TraceModel.Handlers.ModelHandlers.UserInteractions.data(); + const data = Trace.Handlers.ModelHandlers.UserInteractions.data(); const oneSecondInteraction = Array.from(data.interactionEvents).find(entry => { return entry.dur === 979974 && entry.type === 'click'; }); @@ -97,7 +97,7 @@ describe('UserInteractionsHandler', function () { }); it('identifies the longest interaction', async () => { await processTrace(this, 'slow-interaction-keydown.json.gz'); - const data = TraceModel.Handlers.ModelHandlers.UserInteractions.data(); + const data = Trace.Handlers.ModelHandlers.UserInteractions.data(); assert.lengthOf(data.interactionEvents, 5); const expectedLongestEvent = data.interactionEvents.find(event => { return event.type === 'keydown' && event.interactionId === 7378; @@ -106,26 +106,26 @@ describe('UserInteractionsHandler', function () { }); it('returns a set of all interactions that exceed the threshold', async () => { await processTrace(this, 'one-second-interaction.json.gz'); - const data = TraceModel.Handlers.ModelHandlers.UserInteractions.data(); + const data = Trace.Handlers.ModelHandlers.UserInteractions.data(); // There are two long interactions: the pointerup, and the click. assert.strictEqual(data.interactionsOverThreshold.size, 2); }); it('does not include interactions below the threshold', async () => { await processTrace(this, 'slow-interaction-keydown.json.gz'); - const data = TraceModel.Handlers.ModelHandlers.UserInteractions.data(); + const data = Trace.Handlers.ModelHandlers.UserInteractions.data(); // All the interactions in this trace are < 200ms assert.strictEqual(data.interactionsOverThreshold.size, 0); }); it('sets the `dur` key on each event by finding the begin and end events and subtracting the ts', async () => { await processTrace(this, 'slow-interaction-button-click.json.gz'); - const data = TraceModel.Handlers.ModelHandlers.UserInteractions.data(); + const data = Trace.Handlers.ModelHandlers.UserInteractions.data(); for (const syntheticEvent of data.interactionEvents) { assert.strictEqual(syntheticEvent.dur, syntheticEvent.args.data.endEvent.ts - syntheticEvent.args.data.beginEvent.ts); } }); it('gets the right interaction IDs for each interaction', async () => { await processTrace(this, 'slow-interaction-button-click.json.gz'); - const data = TraceModel.Handlers.ModelHandlers.UserInteractions.data(); + const data = Trace.Handlers.ModelHandlers.UserInteractions.data(); assert.deepEqual(data.interactionEvents.map(i => i.interactionId), [ // pointerdown, pointerup and click are all from the same interaction 1540, @@ -135,7 +135,7 @@ describe('UserInteractionsHandler', function () { }); it('gets the right interaction IDs for a keypress interaction', async () => { await processTrace(this, 'slow-interaction-keydown.json.gz'); - const data = TraceModel.Handlers.ModelHandlers.UserInteractions.data(); + const data = Trace.Handlers.ModelHandlers.UserInteractions.data(); assert.deepEqual(data.interactionEvents.map(i => i.interactionId), [ // pointerdown from clicking on the input 7371, @@ -151,7 +151,7 @@ describe('UserInteractionsHandler', function () { }); it('detects correct events for a click and keydown interaction', async () => { await processTrace(this, 'slow-interaction-keydown.json.gz'); - const data = TraceModel.Handlers.ModelHandlers.UserInteractions.data(); + const data = Trace.Handlers.ModelHandlers.UserInteractions.data(); const foundInteractions = data.allEvents.filter(e => e.args.data && e.args.data.duration > 1 && e.args.data.interactionId); // We expect there to be 3 interactions: // User clicks on input: @@ -173,7 +173,7 @@ describe('UserInteractionsHandler', function () { const events = [ { cat: 'devtools.timeline', - ph: "b" /* TraceModel.Types.TraceEvents.Phase.ASYNC_NESTABLE_START */, + ph: "b" /* Trace.Types.Events.Phase.ASYNC_NESTABLE_START */, pid: 1537729, // the Renderer Thread tid: 1, // CrRendererMain id: '1234', @@ -196,7 +196,7 @@ describe('UserInteractionsHandler', function () { // Has an interactionId of 0, so should NOT be included. { cat: 'devtools.timeline', - ph: "b" /* TraceModel.Types.TraceEvents.Phase.ASYNC_NESTABLE_START */, + ph: "b" /* Trace.Types.Events.Phase.ASYNC_NESTABLE_START */, pid: 1537729, // the Renderer Thread tid: 1, // CrRendererMain id: '1234', @@ -219,7 +219,7 @@ describe('UserInteractionsHandler', function () { // Has an duration of 0, so should NOT be included. { cat: 'devtools.timeline', - ph: "b" /* TraceModel.Types.TraceEvents.Phase.ASYNC_NESTABLE_START */, + ph: "b" /* Trace.Types.Events.Phase.ASYNC_NESTABLE_START */, pid: 1537729, // the Renderer Thread tid: 1, // CrRendererMain id: '1234', @@ -240,17 +240,17 @@ describe('UserInteractionsHandler', function () { }, }, ]; - TraceModel.Handlers.ModelHandlers.UserInteractions.reset(); + Trace.Handlers.ModelHandlers.UserInteractions.reset(); for (const event of events) { - TraceModel.Handlers.ModelHandlers.UserInteractions.handleEvent(event); + Trace.Handlers.ModelHandlers.UserInteractions.handleEvent(event); } - await TraceModel.Handlers.ModelHandlers.Meta.finalize(); - await TraceModel.Handlers.ModelHandlers.UserInteractions.finalize(); - const timings = TraceModel.Handlers.ModelHandlers.UserInteractions.data().allEvents; + await Trace.Handlers.ModelHandlers.Meta.finalize(); + await Trace.Handlers.ModelHandlers.UserInteractions.finalize(); + const timings = Trace.Handlers.ModelHandlers.UserInteractions.data().allEvents; assert.lengthOf(timings, 3); }); describe('collapsing nested interactions', () => { - const { removeNestedInteractions } = TraceModel.Handlers.ModelHandlers.UserInteractions; + const { removeNestedInteractions } = Trace.Handlers.ModelHandlers.UserInteractions; it('removes interactions that have the same end time but are not the first event in that block', () => { /** * ========A============= @@ -351,7 +351,7 @@ describe('UserInteractionsHandler', function () { }); it('can remove nested interactions in a real trace', async () => { await processTrace(this, 'nested-interactions.json.gz'); - const data = TraceModel.Handlers.ModelHandlers.UserInteractions.data(); + const data = Trace.Handlers.ModelHandlers.UserInteractions.data(); const visibleEventInteractionIds = data.interactionEventsWithNoNesting.map(event => { return `${event.type}:${event.interactionId}`; }); @@ -391,11 +391,11 @@ describe('UserInteractionsHandler', function () { }); it('gets the correct score classification for Interaction to Next Paint event', () => { const eventA = makeFakeInteraction('pointerdown', { startTime: 0, endTime: 10_000, interactionId: 1 }); - assert.strictEqual(TraceModel.Handlers.ModelHandlers.UserInteractions.scoreClassificationForInteractionToNextPaint(eventA.dur), "good" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.GOOD */); + assert.strictEqual(Trace.Handlers.ModelHandlers.UserInteractions.scoreClassificationForInteractionToNextPaint(eventA.dur), "good" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.GOOD */); const eventB = makeFakeInteraction('pointerdown', { startTime: 0, endTime: 250_000, interactionId: 1 }); - assert.strictEqual(TraceModel.Handlers.ModelHandlers.UserInteractions.scoreClassificationForInteractionToNextPaint(eventB.dur), "ok" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.OK */); + assert.strictEqual(Trace.Handlers.ModelHandlers.UserInteractions.scoreClassificationForInteractionToNextPaint(eventB.dur), "ok" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.OK */); const eventC = makeFakeInteraction('pointerdown', { startTime: 0, endTime: 1_000_000, interactionId: 1 }); - assert.strictEqual(TraceModel.Handlers.ModelHandlers.UserInteractions.scoreClassificationForInteractionToNextPaint(eventC.dur), "bad" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.BAD */); + assert.strictEqual(Trace.Handlers.ModelHandlers.UserInteractions.scoreClassificationForInteractionToNextPaint(eventC.dur), "bad" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.BAD */); }); }); //# sourceMappingURL=UserInteractionsHandler.test.js.map \ No newline at end of file diff --git a/public/models/trace/handlers/UserInteractionsHandler.test.js.map b/public/models/trace/handlers/UserInteractionsHandler.test.js.map index 5f509c5a8..fbc6798d7 100644 --- a/public/models/trace/handlers/UserInteractionsHandler.test.js.map +++ b/public/models/trace/handlers/UserInteractionsHandler.test.js.map @@ -1 +1 @@ -{"version":3,"file":"UserInteractionsHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/UserInteractionsHandler.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as TraceModel from '../trace.js';\n\nasync function processTrace(context: Mocha.Suite|Mocha.Context|null, path: string): Promise {\n const traceEvents = await TraceLoader.rawEvents(context, path);\n TraceModel.Handlers.ModelHandlers.Meta.reset();\n TraceModel.Handlers.ModelHandlers.Meta.initialize();\n for (const event of traceEvents) {\n TraceModel.Handlers.ModelHandlers.Meta.handleEvent(event);\n TraceModel.Handlers.ModelHandlers.UserInteractions.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.Meta.finalize();\n await TraceModel.Handlers.ModelHandlers.UserInteractions.finalize();\n}\n\nbeforeEach(() => {\n TraceModel.Handlers.ModelHandlers.Meta.reset();\n TraceModel.Handlers.ModelHandlers.Meta.initialize();\n});\n\ndescribe('UserInteractionsHandler', function() {\n function makeFakeInteraction(type: string, options: {\n startTime: number,\n endTime: number,\n interactionId: number,\n processingStart?: number,\n processingEnd?: number,\n }): TraceModel.Types.TraceEvents.SyntheticInteractionPair {\n const event = {\n name: 'EventTiming',\n type,\n ts: TraceModel.Types.Timing.MicroSeconds(options.startTime),\n dur: TraceModel.Types.Timing.MicroSeconds(options.endTime - options.startTime),\n processingStart: TraceModel.Types.Timing.MicroSeconds(options.processingStart || 0),\n processingEnd: TraceModel.Types.Timing.MicroSeconds(options.processingEnd || 0),\n interactionId: options.interactionId,\n };\n\n return event as unknown as TraceModel.Types.TraceEvents.SyntheticInteractionPair;\n }\n\n describe('error handling', () => {\n it('throws if not initialized', async () => {\n TraceModel.Handlers.ModelHandlers.Meta.reset();\n TraceModel.Handlers.ModelHandlers.Meta.initialize();\n\n // Finalize the handler by calling data and then finalize on it.\n TraceModel.Handlers.ModelHandlers.UserInteractions.data();\n await TraceModel.Handlers.ModelHandlers.Meta.finalize();\n await TraceModel.Handlers.ModelHandlers.UserInteractions.finalize();\n\n assert.throws(() => {\n const fakeEvent = {} as TraceModel.Types.TraceEvents.TraceEventData;\n TraceModel.Handlers.ModelHandlers.UserInteractions.handleEvent(fakeEvent);\n }, 'Handler is not initialized');\n });\n });\n\n it('returns all user interactions', async function() {\n const traceEvents = await TraceLoader.rawEvents(this, 'slow-interaction-button-click.json.gz');\n for (const event of traceEvents) {\n TraceModel.Handlers.ModelHandlers.UserInteractions.handleEvent(event);\n }\n\n const data = TraceModel.Handlers.ModelHandlers.UserInteractions.data();\n const clicks = data.allEvents.filter(event => {\n if (!event.args.data) {\n return false;\n }\n\n return event.args.data.type === 'click';\n });\n\n assert.strictEqual(data.allEvents.length, 58);\n assert.strictEqual(clicks.length, 1);\n });\n\n it('returns all interaction events', async () => {\n await processTrace(this, 'slow-interaction-button-click.json.gz');\n const data = TraceModel.Handlers.ModelHandlers.UserInteractions.data();\n // There are three inct interactions:\n // pointerdown on the button (start of the click)\n // pointerup & click on the button (end of the click)\n assert.strictEqual(data.interactionEvents.length, 3);\n });\n\n it('adds microsecond processingStart and processingEnd times to the synthetic event', async function() {\n await processTrace(this, 'one-second-interaction.json.gz');\n const data = TraceModel.Handlers.ModelHandlers.UserInteractions.data();\n const oneSecondInteraction = Array.from(data.interactionEvents).find(entry => {\n return entry.dur === 979974 && entry.type === 'click';\n });\n if (!oneSecondInteraction) {\n throw new Error('Could not find interaction');\n }\n\n assert.strictEqual(oneSecondInteraction.processingStart, 141251950944);\n assert.strictEqual(oneSecondInteraction.processingEnd, 141252927944);\n });\n\n it('adds the INP phases to the interaction', async function() {\n await processTrace(this, 'one-second-interaction.json.gz');\n const data = TraceModel.Handlers.ModelHandlers.UserInteractions.data();\n const oneSecondInteraction = Array.from(data.interactionEvents).find(entry => {\n return entry.dur === 979974 && entry.type === 'click';\n });\n if (!oneSecondInteraction) {\n throw new Error('Could not find interaction');\n }\n\n // These numbers do seem suspciously round: that is because they are from\n // converted millisecond values and this is expected.\n assert.strictEqual(oneSecondInteraction.inputDelay, 1_000);\n assert.strictEqual(oneSecondInteraction.mainThreadHandling, 977_000);\n assert.strictEqual(oneSecondInteraction.presentationDelay, 1974);\n });\n\n it('identifies the longest interaction', async () => {\n await processTrace(this, 'slow-interaction-keydown.json.gz');\n const data = TraceModel.Handlers.ModelHandlers.UserInteractions.data();\n assert.lengthOf(data.interactionEvents, 5);\n\n const expectedLongestEvent = data.interactionEvents.find(event => {\n return event.type === 'keydown' && event.interactionId === 7378;\n });\n assert.strictEqual(data.longestInteractionEvent, expectedLongestEvent);\n });\n\n it('returns a set of all interactions that exceed the threshold', async () => {\n await processTrace(this, 'one-second-interaction.json.gz');\n const data = TraceModel.Handlers.ModelHandlers.UserInteractions.data();\n // There are two long interactions: the pointerup, and the click.\n assert.strictEqual(data.interactionsOverThreshold.size, 2);\n });\n\n it('does not include interactions below the threshold', async () => {\n await processTrace(this, 'slow-interaction-keydown.json.gz');\n const data = TraceModel.Handlers.ModelHandlers.UserInteractions.data();\n // All the interactions in this trace are < 200ms\n assert.strictEqual(data.interactionsOverThreshold.size, 0);\n });\n\n it('sets the `dur` key on each event by finding the begin and end events and subtracting the ts', async () => {\n await processTrace(this, 'slow-interaction-button-click.json.gz');\n const data = TraceModel.Handlers.ModelHandlers.UserInteractions.data();\n for (const syntheticEvent of data.interactionEvents) {\n assert.strictEqual(\n syntheticEvent.dur, syntheticEvent.args.data.endEvent.ts - syntheticEvent.args.data.beginEvent.ts);\n }\n });\n\n it('gets the right interaction IDs for each interaction', async () => {\n await processTrace(this, 'slow-interaction-button-click.json.gz');\n const data = TraceModel.Handlers.ModelHandlers.UserInteractions.data();\n assert.deepEqual(data.interactionEvents.map(i => i.interactionId), [\n // pointerdown, pointerup and click are all from the same interaction\n 1540,\n 1540,\n 1540,\n ]);\n });\n\n it('gets the right interaction IDs for a keypress interaction', async () => {\n await processTrace(this, 'slow-interaction-keydown.json.gz');\n const data = TraceModel.Handlers.ModelHandlers.UserInteractions.data();\n assert.deepEqual(data.interactionEvents.map(i => i.interactionId), [\n // pointerdown from clicking on the input\n 7371,\n // pointerup from clicking on the input\n 7371,\n // click from clicking on the input\n 7371,\n // keydown from typing character\n 7378,\n // keyup from typing character\n 7378,\n ]);\n });\n\n it('detects correct events for a click and keydown interaction', async () => {\n await processTrace(this, 'slow-interaction-keydown.json.gz');\n const data = TraceModel.Handlers.ModelHandlers.UserInteractions.data();\n const foundInteractions =\n data.allEvents.filter(e => e.args.data && e.args.data.duration > 1 && e.args.data.interactionId);\n // We expect there to be 3 interactions:\n // User clicks on input:\n // 1.pointerdown, 2. pointerup, 3. click\n // User types into input:\n // 4. keydown, 5. keyup\n assert.deepEqual(\n foundInteractions.map(event => event.args.data?.type),\n ['pointerdown', 'pointerup', 'click', 'keydown', 'keyup']);\n\n assert.deepEqual(foundInteractions.map(e => e.args.data?.interactionId), [\n // The first three events relate to the click, so they have the same InteractionID\n 7371,\n 7371,\n 7371,\n // The final two relate to the keypress, so they have the same InteractionID\n 7378,\n 7378,\n ]);\n });\n\n it('finds all interaction events with a duration and interactionId', async () => {\n const events = [\n {\n cat: 'devtools.timeline',\n ph: TraceModel.Types.TraceEvents.Phase.ASYNC_NESTABLE_START,\n pid: 1537729, // the Renderer Thread\n tid: 1, // CrRendererMain\n id: '1234',\n ts: 10,\n dur: 500,\n scope: 'scope',\n name: 'EventTiming',\n args: {\n data: {\n duration: 16,\n interactionId: 9700,\n nodeId: 0,\n processingEnd: 993,\n processingStart: 993,\n timeStamp: 985,\n type: 'pointerdown',\n },\n },\n },\n // Has an interactionId of 0, so should NOT be included.\n {\n cat: 'devtools.timeline',\n ph: TraceModel.Types.TraceEvents.Phase.ASYNC_NESTABLE_START,\n pid: 1537729, // the Renderer Thread\n tid: 1, // CrRendererMain\n id: '1234',\n ts: 10,\n dur: 500,\n scope: 'scope',\n name: 'EventTiming',\n args: {\n data: {\n duration: 16,\n interactionId: 0,\n nodeId: 0,\n processingEnd: 993,\n processingStart: 993,\n timeStamp: 985,\n type: 'pointerdown',\n },\n },\n },\n // Has an duration of 0, so should NOT be included.\n {\n cat: 'devtools.timeline',\n ph: TraceModel.Types.TraceEvents.Phase.ASYNC_NESTABLE_START,\n pid: 1537729, // the Renderer Thread\n tid: 1, // CrRendererMain\n id: '1234',\n ts: 10,\n dur: 500,\n scope: 'scope',\n name: 'EventTiming',\n args: {\n data: {\n duration: 0,\n interactionId: 0,\n nodeId: 0,\n processingEnd: 993,\n processingStart: 993,\n timeStamp: 985,\n type: 'pointerdown',\n },\n },\n },\n ] as unknown as TraceModel.Types.TraceEvents.TraceEventEventTiming[];\n TraceModel.Handlers.ModelHandlers.UserInteractions.reset();\n for (const event of events) {\n TraceModel.Handlers.ModelHandlers.UserInteractions.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.Meta.finalize();\n await TraceModel.Handlers.ModelHandlers.UserInteractions.finalize();\n const timings = TraceModel.Handlers.ModelHandlers.UserInteractions.data().allEvents;\n assert.lengthOf(timings, 3);\n });\n\n describe('collapsing nested interactions', () => {\n const {removeNestedInteractions} = TraceModel.Handlers.ModelHandlers.UserInteractions;\n\n it('removes interactions that have the same end time but are not the first event in that block', () => {\n /**\n * ========A=============\n * ===========B========\n * ===========C========\n * =====D========\n */\n const eventA = makeFakeInteraction('pointerdown', {startTime: 0, endTime: 10, interactionId: 1});\n const eventB = makeFakeInteraction('pointerdown', {startTime: 2, endTime: 10, interactionId: 2});\n const eventC = makeFakeInteraction('pointerdown', {startTime: 4, endTime: 10, interactionId: 3});\n const eventD = makeFakeInteraction('pointerdown', {startTime: 6, endTime: 10, interactionId: 4});\n const result = removeNestedInteractions([eventA, eventB, eventC, eventD]);\n assert.deepEqual(result, [eventA]);\n });\n\n it('prefers the event with the longer processing start/end if the events have the same ts and dur', () => {\n // Here we would expect eventA to be used; these events both have the\n // same interactionId, the same start/end, but different processing\n // start/end. In this situation we want to use the one with the largest\n // processing range, as that is more likely accurate to the situation. We\n // see in traces that other events will have processingStart and\n // processingEnd set to the same value, which does not provide much\n // insight compared to picking the event that does have more information\n // and accurate processing numbers.\n const eventA = makeFakeInteraction(\n 'pointerdown', {startTime: 0, endTime: 10, interactionId: 1, processingStart: 1, processingEnd: 8});\n const eventB = makeFakeInteraction(\n 'pointerdown', {startTime: 0, endTime: 10, interactionId: 1, processingStart: 6, processingEnd: 6});\n const result = removeNestedInteractions([eventA, eventB]);\n assert.deepEqual(result, [eventA]);\n });\n\n it('only collapses events of the same type', () => {\n /**\n * Here we should collapse B, because A is bigger and of the same type.\n * Similarly, we should collapse D, because C is bigger and of the same type.\n * But C should remain visible, because it is a pointer event, not a key event,\n * and therefore does not get collapsed into A.\n * ========A=[keydown]====\n * =======B=[keyup]=====\n * ====C=[pointerdown]=\n * =D=[pointerup]=\n */\n const eventA = makeFakeInteraction('keydown', {startTime: 0, endTime: 10, interactionId: 1});\n const eventB = makeFakeInteraction('keyup', {startTime: 2, endTime: 10, interactionId: 2});\n const eventC = makeFakeInteraction('pointerdown', {startTime: 4, endTime: 10, interactionId: 3});\n const eventD = makeFakeInteraction('pointerup', {startTime: 6, endTime: 10, interactionId: 4});\n const result = removeNestedInteractions([eventA, eventB, eventC, eventD]);\n assert.deepEqual(result, [eventA, eventC]);\n });\n\n it('does not remove interactions that overlap but have a different end time', () => {\n /**\n * ========A=============\n * ===========B========\n * ===========C========\n * =====D================\n */\n const eventA = makeFakeInteraction('pointerdown', {startTime: 0, endTime: 10, interactionId: 1});\n const eventB = makeFakeInteraction('pointerdown', {startTime: 2, endTime: 10, interactionId: 2});\n const eventC = makeFakeInteraction('pointerdown', {startTime: 4, endTime: 10, interactionId: 3});\n const eventD = makeFakeInteraction('pointerdown', {startTime: 6, endTime: 20, interactionId: 4});\n const result = removeNestedInteractions([eventA, eventB, eventC, eventD]);\n assert.deepEqual(result, [eventA, eventD]);\n });\n\n it('does not remove interactions with an unexpected type', () => {\n /**\n * =====A=[pointerdown]=====\n * ===========B=[unknown]=\n */\n const eventA = makeFakeInteraction('pointerdown', {startTime: 0, endTime: 10, interactionId: 1});\n const eventB = makeFakeInteraction('unknown', {startTime: 2, endTime: 10, interactionId: 2});\n const result = removeNestedInteractions([eventA, eventB]);\n assert.deepEqual(result, [eventA, eventB]);\n });\n\n it('correctly identifies nested events when their parent overlaps with multiple events', () => {\n /**\n * Here although it does not look like it on first glance, C is nested\n * within B and should therefore be hidden. Similarly, D is nested within A and\n * so should be hidden.\n *\n * ========A====== ======C====\n * ===========B=============\n * ======D======\n */\n const eventA = makeFakeInteraction('pointerdown', {startTime: 0, endTime: 5, interactionId: 1});\n const eventB = makeFakeInteraction('pointerdown', {startTime: 2, endTime: 20, interactionId: 2});\n const eventC = makeFakeInteraction('pointerdown', {startTime: 10, endTime: 20, interactionId: 3});\n const eventD = makeFakeInteraction('pointerdown', {startTime: 2, endTime: 5, interactionId: 3});\n const result = removeNestedInteractions([eventA, eventB, eventC, eventD]);\n assert.deepEqual(result, [eventA, eventB]);\n });\n\n it('returns the events in timestamp order', () => {\n /**\n * None of the events below overlap at all, this test makes sure that the order of events does not change.\n */\n const eventA = makeFakeInteraction('pointerdown', {startTime: 0, endTime: 5, interactionId: 1});\n const eventB = makeFakeInteraction('pointerdown', {startTime: 10, endTime: 20, interactionId: 2});\n const eventC = makeFakeInteraction('pointerdown', {startTime: 30, endTime: 40, interactionId: 3});\n const eventD = makeFakeInteraction('pointerdown', {startTime: 50, endTime: 60, interactionId: 4});\n const result = removeNestedInteractions([eventA, eventB, eventC, eventD]);\n assert.deepEqual(result, [eventA, eventB, eventC, eventD]);\n });\n\n it('can remove nested interactions in a real trace', async () => {\n await processTrace(this, 'nested-interactions.json.gz');\n const data = TraceModel.Handlers.ModelHandlers.UserInteractions.data();\n\n const visibleEventInteractionIds = data.interactionEventsWithNoNesting.map(event => {\n return `${event.type}:${event.interactionId}`;\n });\n\n // Note: it is very hard to explain in comments all these assertions, so\n // it is highly recommended that you load the trace file above into\n // DevTools to look at the timeline whilst working on this test.\n\n /**\n * This is a block of events with identical end times, so only the\n * first should be kept:\n * =====[keydown 3579]====\n * ==[keydown 3558]====\n * =[keyup 3558]====\n **/\n assert.isTrue(visibleEventInteractionIds.includes('keydown:3579'));\n assert.isFalse(visibleEventInteractionIds.includes('keydown:3558'));\n assert.isFalse(visibleEventInteractionIds.includes('keyup:3558'));\n\n /** This is a slightly offset block of events:\n * ====[keydown 3572]=====\n * =[keydown 3565]=====\n * ====[keydown 3586]========\n * In this test we want to make sure that 3565 is collapsed, but the\n * others are not.\n **/\n assert.isTrue(visibleEventInteractionIds.includes('keydown:3572'));\n assert.isTrue(visibleEventInteractionIds.includes('keydown:3586'));\n assert.isFalse(visibleEventInteractionIds.includes('keydown:3565'));\n\n /** This is a block of events that have offset overlaps:\n * ====[keydown 3614]===== =====[keydown 3621]======\n * =====[keydown 3628]=========================\n * In this test we want to make sure that 3621 is collapsed as it fits\n * iwthin 3628, but 3614 is not collapsed.\n **/\n assert.isTrue(visibleEventInteractionIds.includes('keydown:3614'));\n assert.isTrue(visibleEventInteractionIds.includes('keydown:3628'));\n assert.isFalse(visibleEventInteractionIds.includes('keydown:3621'));\n });\n });\n\n it('gets the correct score classification for Interaction to Next Paint event', () => {\n const eventA = makeFakeInteraction('pointerdown', {startTime: 0, endTime: 10_000, interactionId: 1});\n assert.strictEqual(\n TraceModel.Handlers.ModelHandlers.UserInteractions.scoreClassificationForInteractionToNextPaint(eventA.dur),\n TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.GOOD);\n const eventB = makeFakeInteraction('pointerdown', {startTime: 0, endTime: 250_000, interactionId: 1});\n assert.strictEqual(\n TraceModel.Handlers.ModelHandlers.UserInteractions.scoreClassificationForInteractionToNextPaint(eventB.dur),\n TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.OK);\n const eventC = makeFakeInteraction('pointerdown', {startTime: 0, endTime: 1_000_000, interactionId: 1});\n assert.strictEqual(\n TraceModel.Handlers.ModelHandlers.UserInteractions.scoreClassificationForInteractionToNextPaint(eventC.dur),\n TraceModel.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.BAD);\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"UserInteractionsHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/UserInteractionsHandler.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Trace from '../trace.js';\n\nasync function processTrace(context: Mocha.Suite|Mocha.Context|null, path: string): Promise {\n const traceEvents = await TraceLoader.rawEvents(context, path);\n Trace.Handlers.ModelHandlers.Meta.reset();\n Trace.Handlers.ModelHandlers.Meta.initialize();\n for (const event of traceEvents) {\n Trace.Handlers.ModelHandlers.Meta.handleEvent(event);\n Trace.Handlers.ModelHandlers.UserInteractions.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n await Trace.Handlers.ModelHandlers.UserInteractions.finalize();\n}\n\nbeforeEach(() => {\n Trace.Handlers.ModelHandlers.Meta.reset();\n Trace.Handlers.ModelHandlers.Meta.initialize();\n});\n\ndescribe('UserInteractionsHandler', function() {\n function makeFakeInteraction(type: string, options: {\n startTime: number,\n endTime: number,\n interactionId: number,\n processingStart?: number,\n processingEnd?: number,\n }): Trace.Types.Events.SyntheticInteractionPair {\n const event = {\n name: 'EventTiming',\n type,\n ts: Trace.Types.Timing.MicroSeconds(options.startTime),\n dur: Trace.Types.Timing.MicroSeconds(options.endTime - options.startTime),\n processingStart: Trace.Types.Timing.MicroSeconds(options.processingStart || 0),\n processingEnd: Trace.Types.Timing.MicroSeconds(options.processingEnd || 0),\n interactionId: options.interactionId,\n };\n\n return event as unknown as Trace.Types.Events.SyntheticInteractionPair;\n }\n\n describe('error handling', () => {\n it('throws if not initialized', async () => {\n Trace.Handlers.ModelHandlers.Meta.reset();\n Trace.Handlers.ModelHandlers.Meta.initialize();\n\n // Finalize the handler by calling data and then finalize on it.\n Trace.Handlers.ModelHandlers.UserInteractions.data();\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n await Trace.Handlers.ModelHandlers.UserInteractions.finalize();\n\n assert.throws(() => {\n const fakeEvent = {} as Trace.Types.Events.Event;\n Trace.Handlers.ModelHandlers.UserInteractions.handleEvent(fakeEvent);\n }, 'Handler is not initialized');\n });\n });\n\n it('returns all user interactions', async function() {\n const traceEvents = await TraceLoader.rawEvents(this, 'slow-interaction-button-click.json.gz');\n for (const event of traceEvents) {\n Trace.Handlers.ModelHandlers.UserInteractions.handleEvent(event);\n }\n\n const data = Trace.Handlers.ModelHandlers.UserInteractions.data();\n const clicks = data.allEvents.filter(event => {\n if (!event.args.data) {\n return false;\n }\n\n return event.args.data.type === 'click';\n });\n\n assert.strictEqual(data.allEvents.length, 58);\n assert.strictEqual(clicks.length, 1);\n });\n\n it('returns all interaction events', async () => {\n await processTrace(this, 'slow-interaction-button-click.json.gz');\n const data = Trace.Handlers.ModelHandlers.UserInteractions.data();\n // There are three inct interactions:\n // pointerdown on the button (start of the click)\n // pointerup & click on the button (end of the click)\n assert.strictEqual(data.interactionEvents.length, 3);\n });\n\n it('adds microsecond processingStart and processingEnd times to the synthetic event', async function() {\n await processTrace(this, 'one-second-interaction.json.gz');\n const data = Trace.Handlers.ModelHandlers.UserInteractions.data();\n const oneSecondInteraction = Array.from(data.interactionEvents).find(entry => {\n return entry.dur === 979974 && entry.type === 'click';\n });\n if (!oneSecondInteraction) {\n throw new Error('Could not find interaction');\n }\n\n assert.strictEqual(oneSecondInteraction.processingStart, 141251950944);\n assert.strictEqual(oneSecondInteraction.processingEnd, 141252927944);\n });\n\n it('adds the INP phases to the interaction', async function() {\n await processTrace(this, 'one-second-interaction.json.gz');\n const data = Trace.Handlers.ModelHandlers.UserInteractions.data();\n const oneSecondInteraction = Array.from(data.interactionEvents).find(entry => {\n return entry.dur === 979974 && entry.type === 'click';\n });\n if (!oneSecondInteraction) {\n throw new Error('Could not find interaction');\n }\n\n // These numbers do seem suspciously round: that is because they are from\n // converted millisecond values and this is expected.\n assert.strictEqual(oneSecondInteraction.inputDelay, 1_000);\n assert.strictEqual(oneSecondInteraction.mainThreadHandling, 977_000);\n assert.strictEqual(oneSecondInteraction.presentationDelay, 1974);\n });\n\n it('identifies the longest interaction', async () => {\n await processTrace(this, 'slow-interaction-keydown.json.gz');\n const data = Trace.Handlers.ModelHandlers.UserInteractions.data();\n assert.lengthOf(data.interactionEvents, 5);\n\n const expectedLongestEvent = data.interactionEvents.find(event => {\n return event.type === 'keydown' && event.interactionId === 7378;\n });\n assert.strictEqual(data.longestInteractionEvent, expectedLongestEvent);\n });\n\n it('returns a set of all interactions that exceed the threshold', async () => {\n await processTrace(this, 'one-second-interaction.json.gz');\n const data = Trace.Handlers.ModelHandlers.UserInteractions.data();\n // There are two long interactions: the pointerup, and the click.\n assert.strictEqual(data.interactionsOverThreshold.size, 2);\n });\n\n it('does not include interactions below the threshold', async () => {\n await processTrace(this, 'slow-interaction-keydown.json.gz');\n const data = Trace.Handlers.ModelHandlers.UserInteractions.data();\n // All the interactions in this trace are < 200ms\n assert.strictEqual(data.interactionsOverThreshold.size, 0);\n });\n\n it('sets the `dur` key on each event by finding the begin and end events and subtracting the ts', async () => {\n await processTrace(this, 'slow-interaction-button-click.json.gz');\n const data = Trace.Handlers.ModelHandlers.UserInteractions.data();\n for (const syntheticEvent of data.interactionEvents) {\n assert.strictEqual(\n syntheticEvent.dur, syntheticEvent.args.data.endEvent.ts - syntheticEvent.args.data.beginEvent.ts);\n }\n });\n\n it('gets the right interaction IDs for each interaction', async () => {\n await processTrace(this, 'slow-interaction-button-click.json.gz');\n const data = Trace.Handlers.ModelHandlers.UserInteractions.data();\n assert.deepEqual(data.interactionEvents.map(i => i.interactionId), [\n // pointerdown, pointerup and click are all from the same interaction\n 1540,\n 1540,\n 1540,\n ]);\n });\n\n it('gets the right interaction IDs for a keypress interaction', async () => {\n await processTrace(this, 'slow-interaction-keydown.json.gz');\n const data = Trace.Handlers.ModelHandlers.UserInteractions.data();\n assert.deepEqual(data.interactionEvents.map(i => i.interactionId), [\n // pointerdown from clicking on the input\n 7371,\n // pointerup from clicking on the input\n 7371,\n // click from clicking on the input\n 7371,\n // keydown from typing character\n 7378,\n // keyup from typing character\n 7378,\n ]);\n });\n\n it('detects correct events for a click and keydown interaction', async () => {\n await processTrace(this, 'slow-interaction-keydown.json.gz');\n const data = Trace.Handlers.ModelHandlers.UserInteractions.data();\n const foundInteractions =\n data.allEvents.filter(e => e.args.data && e.args.data.duration > 1 && e.args.data.interactionId);\n // We expect there to be 3 interactions:\n // User clicks on input:\n // 1.pointerdown, 2. pointerup, 3. click\n // User types into input:\n // 4. keydown, 5. keyup\n assert.deepEqual(\n foundInteractions.map(event => event.args.data?.type),\n ['pointerdown', 'pointerup', 'click', 'keydown', 'keyup']);\n\n assert.deepEqual(foundInteractions.map(e => e.args.data?.interactionId), [\n // The first three events relate to the click, so they have the same InteractionID\n 7371,\n 7371,\n 7371,\n // The final two relate to the keypress, so they have the same InteractionID\n 7378,\n 7378,\n ]);\n });\n\n it('finds all interaction events with a duration and interactionId', async () => {\n const events = [\n {\n cat: 'devtools.timeline',\n ph: Trace.Types.Events.Phase.ASYNC_NESTABLE_START,\n pid: 1537729, // the Renderer Thread\n tid: 1, // CrRendererMain\n id: '1234',\n ts: 10,\n dur: 500,\n scope: 'scope',\n name: 'EventTiming',\n args: {\n data: {\n duration: 16,\n interactionId: 9700,\n nodeId: 0,\n processingEnd: 993,\n processingStart: 993,\n timeStamp: 985,\n type: 'pointerdown',\n },\n },\n },\n // Has an interactionId of 0, so should NOT be included.\n {\n cat: 'devtools.timeline',\n ph: Trace.Types.Events.Phase.ASYNC_NESTABLE_START,\n pid: 1537729, // the Renderer Thread\n tid: 1, // CrRendererMain\n id: '1234',\n ts: 10,\n dur: 500,\n scope: 'scope',\n name: 'EventTiming',\n args: {\n data: {\n duration: 16,\n interactionId: 0,\n nodeId: 0,\n processingEnd: 993,\n processingStart: 993,\n timeStamp: 985,\n type: 'pointerdown',\n },\n },\n },\n // Has an duration of 0, so should NOT be included.\n {\n cat: 'devtools.timeline',\n ph: Trace.Types.Events.Phase.ASYNC_NESTABLE_START,\n pid: 1537729, // the Renderer Thread\n tid: 1, // CrRendererMain\n id: '1234',\n ts: 10,\n dur: 500,\n scope: 'scope',\n name: 'EventTiming',\n args: {\n data: {\n duration: 0,\n interactionId: 0,\n nodeId: 0,\n processingEnd: 993,\n processingStart: 993,\n timeStamp: 985,\n type: 'pointerdown',\n },\n },\n },\n ] as unknown as Trace.Types.Events.EventTiming[];\n Trace.Handlers.ModelHandlers.UserInteractions.reset();\n for (const event of events) {\n Trace.Handlers.ModelHandlers.UserInteractions.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Meta.finalize();\n await Trace.Handlers.ModelHandlers.UserInteractions.finalize();\n const timings = Trace.Handlers.ModelHandlers.UserInteractions.data().allEvents;\n assert.lengthOf(timings, 3);\n });\n\n describe('collapsing nested interactions', () => {\n const {removeNestedInteractions} = Trace.Handlers.ModelHandlers.UserInteractions;\n\n it('removes interactions that have the same end time but are not the first event in that block', () => {\n /**\n * ========A=============\n * ===========B========\n * ===========C========\n * =====D========\n */\n const eventA = makeFakeInteraction('pointerdown', {startTime: 0, endTime: 10, interactionId: 1});\n const eventB = makeFakeInteraction('pointerdown', {startTime: 2, endTime: 10, interactionId: 2});\n const eventC = makeFakeInteraction('pointerdown', {startTime: 4, endTime: 10, interactionId: 3});\n const eventD = makeFakeInteraction('pointerdown', {startTime: 6, endTime: 10, interactionId: 4});\n const result = removeNestedInteractions([eventA, eventB, eventC, eventD]);\n assert.deepEqual(result, [eventA]);\n });\n\n it('prefers the event with the longer processing start/end if the events have the same ts and dur', () => {\n // Here we would expect eventA to be used; these events both have the\n // same interactionId, the same start/end, but different processing\n // start/end. In this situation we want to use the one with the largest\n // processing range, as that is more likely accurate to the situation. We\n // see in traces that other events will have processingStart and\n // processingEnd set to the same value, which does not provide much\n // insight compared to picking the event that does have more information\n // and accurate processing numbers.\n const eventA = makeFakeInteraction(\n 'pointerdown', {startTime: 0, endTime: 10, interactionId: 1, processingStart: 1, processingEnd: 8});\n const eventB = makeFakeInteraction(\n 'pointerdown', {startTime: 0, endTime: 10, interactionId: 1, processingStart: 6, processingEnd: 6});\n const result = removeNestedInteractions([eventA, eventB]);\n assert.deepEqual(result, [eventA]);\n });\n\n it('only collapses events of the same type', () => {\n /**\n * Here we should collapse B, because A is bigger and of the same type.\n * Similarly, we should collapse D, because C is bigger and of the same type.\n * But C should remain visible, because it is a pointer event, not a key event,\n * and therefore does not get collapsed into A.\n * ========A=[keydown]====\n * =======B=[keyup]=====\n * ====C=[pointerdown]=\n * =D=[pointerup]=\n */\n const eventA = makeFakeInteraction('keydown', {startTime: 0, endTime: 10, interactionId: 1});\n const eventB = makeFakeInteraction('keyup', {startTime: 2, endTime: 10, interactionId: 2});\n const eventC = makeFakeInteraction('pointerdown', {startTime: 4, endTime: 10, interactionId: 3});\n const eventD = makeFakeInteraction('pointerup', {startTime: 6, endTime: 10, interactionId: 4});\n const result = removeNestedInteractions([eventA, eventB, eventC, eventD]);\n assert.deepEqual(result, [eventA, eventC]);\n });\n\n it('does not remove interactions that overlap but have a different end time', () => {\n /**\n * ========A=============\n * ===========B========\n * ===========C========\n * =====D================\n */\n const eventA = makeFakeInteraction('pointerdown', {startTime: 0, endTime: 10, interactionId: 1});\n const eventB = makeFakeInteraction('pointerdown', {startTime: 2, endTime: 10, interactionId: 2});\n const eventC = makeFakeInteraction('pointerdown', {startTime: 4, endTime: 10, interactionId: 3});\n const eventD = makeFakeInteraction('pointerdown', {startTime: 6, endTime: 20, interactionId: 4});\n const result = removeNestedInteractions([eventA, eventB, eventC, eventD]);\n assert.deepEqual(result, [eventA, eventD]);\n });\n\n it('does not remove interactions with an unexpected type', () => {\n /**\n * =====A=[pointerdown]=====\n * ===========B=[unknown]=\n */\n const eventA = makeFakeInteraction('pointerdown', {startTime: 0, endTime: 10, interactionId: 1});\n const eventB = makeFakeInteraction('unknown', {startTime: 2, endTime: 10, interactionId: 2});\n const result = removeNestedInteractions([eventA, eventB]);\n assert.deepEqual(result, [eventA, eventB]);\n });\n\n it('correctly identifies nested events when their parent overlaps with multiple events', () => {\n /**\n * Here although it does not look like it on first glance, C is nested\n * within B and should therefore be hidden. Similarly, D is nested within A and\n * so should be hidden.\n *\n * ========A====== ======C====\n * ===========B=============\n * ======D======\n */\n const eventA = makeFakeInteraction('pointerdown', {startTime: 0, endTime: 5, interactionId: 1});\n const eventB = makeFakeInteraction('pointerdown', {startTime: 2, endTime: 20, interactionId: 2});\n const eventC = makeFakeInteraction('pointerdown', {startTime: 10, endTime: 20, interactionId: 3});\n const eventD = makeFakeInteraction('pointerdown', {startTime: 2, endTime: 5, interactionId: 3});\n const result = removeNestedInteractions([eventA, eventB, eventC, eventD]);\n assert.deepEqual(result, [eventA, eventB]);\n });\n\n it('returns the events in timestamp order', () => {\n /**\n * None of the events below overlap at all, this test makes sure that the order of events does not change.\n */\n const eventA = makeFakeInteraction('pointerdown', {startTime: 0, endTime: 5, interactionId: 1});\n const eventB = makeFakeInteraction('pointerdown', {startTime: 10, endTime: 20, interactionId: 2});\n const eventC = makeFakeInteraction('pointerdown', {startTime: 30, endTime: 40, interactionId: 3});\n const eventD = makeFakeInteraction('pointerdown', {startTime: 50, endTime: 60, interactionId: 4});\n const result = removeNestedInteractions([eventA, eventB, eventC, eventD]);\n assert.deepEqual(result, [eventA, eventB, eventC, eventD]);\n });\n\n it('can remove nested interactions in a real trace', async () => {\n await processTrace(this, 'nested-interactions.json.gz');\n const data = Trace.Handlers.ModelHandlers.UserInteractions.data();\n\n const visibleEventInteractionIds = data.interactionEventsWithNoNesting.map(event => {\n return `${event.type}:${event.interactionId}`;\n });\n\n // Note: it is very hard to explain in comments all these assertions, so\n // it is highly recommended that you load the trace file above into\n // DevTools to look at the timeline whilst working on this test.\n\n /**\n * This is a block of events with identical end times, so only the\n * first should be kept:\n * =====[keydown 3579]====\n * ==[keydown 3558]====\n * =[keyup 3558]====\n **/\n assert.isTrue(visibleEventInteractionIds.includes('keydown:3579'));\n assert.isFalse(visibleEventInteractionIds.includes('keydown:3558'));\n assert.isFalse(visibleEventInteractionIds.includes('keyup:3558'));\n\n /** This is a slightly offset block of events:\n * ====[keydown 3572]=====\n * =[keydown 3565]=====\n * ====[keydown 3586]========\n * In this test we want to make sure that 3565 is collapsed, but the\n * others are not.\n **/\n assert.isTrue(visibleEventInteractionIds.includes('keydown:3572'));\n assert.isTrue(visibleEventInteractionIds.includes('keydown:3586'));\n assert.isFalse(visibleEventInteractionIds.includes('keydown:3565'));\n\n /** This is a block of events that have offset overlaps:\n * ====[keydown 3614]===== =====[keydown 3621]======\n * =====[keydown 3628]=========================\n * In this test we want to make sure that 3621 is collapsed as it fits\n * iwthin 3628, but 3614 is not collapsed.\n **/\n assert.isTrue(visibleEventInteractionIds.includes('keydown:3614'));\n assert.isTrue(visibleEventInteractionIds.includes('keydown:3628'));\n assert.isFalse(visibleEventInteractionIds.includes('keydown:3621'));\n });\n });\n\n it('gets the correct score classification for Interaction to Next Paint event', () => {\n const eventA = makeFakeInteraction('pointerdown', {startTime: 0, endTime: 10_000, interactionId: 1});\n assert.strictEqual(\n Trace.Handlers.ModelHandlers.UserInteractions.scoreClassificationForInteractionToNextPaint(eventA.dur),\n Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.GOOD);\n const eventB = makeFakeInteraction('pointerdown', {startTime: 0, endTime: 250_000, interactionId: 1});\n assert.strictEqual(\n Trace.Handlers.ModelHandlers.UserInteractions.scoreClassificationForInteractionToNextPaint(eventB.dur),\n Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.OK);\n const eventC = makeFakeInteraction('pointerdown', {startTime: 0, endTime: 1_000_000, interactionId: 1});\n assert.strictEqual(\n Trace.Handlers.ModelHandlers.UserInteractions.scoreClassificationForInteractionToNextPaint(eventC.dur),\n Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification.BAD);\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/UserTimingsHandler.d.ts b/public/models/trace/handlers/UserTimingsHandler.d.ts index c27572a2f..f23b1a290 100644 --- a/public/models/trace/handlers/UserTimingsHandler.d.ts +++ b/public/models/trace/handlers/UserTimingsHandler.d.ts @@ -4,25 +4,25 @@ export interface UserTimingsData { * Events triggered with the performance.measure() API. * https://developer.mozilla.org/en-US/docs/Web/API/Performance/measure */ - performanceMeasures: readonly Types.TraceEvents.SyntheticUserTimingPair[]; + performanceMeasures: readonly Types.Events.SyntheticUserTimingPair[]; /** * Events triggered with the performance.mark() API. * https://developer.mozilla.org/en-US/docs/Web/API/Performance/mark */ - performanceMarks: readonly Types.TraceEvents.TraceEventPerformanceMark[]; + performanceMarks: readonly Types.Events.PerformanceMark[]; /** * Events triggered with the console.time(), console.timeEnd() and * console.timeLog() API. * https://developer.mozilla.org/en-US/docs/Web/API/console/time */ - consoleTimings: readonly Types.TraceEvents.SyntheticConsoleTimingPair[]; + consoleTimings: readonly Types.Events.SyntheticConsoleTimingPair[]; /** * Events triggered with the console.timeStamp() API * https://developer.mozilla.org/en-US/docs/Web/API/console/timeStamp */ - timestampEvents: readonly Types.TraceEvents.TraceEventTimeStamp[]; + timestampEvents: readonly Types.Events.TimeStamp[]; } export declare function reset(): void; -export declare function handleEvent(event: Types.TraceEvents.TraceEventData): void; +export declare function handleEvent(event: Types.Events.Event): void; export declare function finalize(): Promise; export declare function data(): UserTimingsData; diff --git a/public/models/trace/handlers/UserTimingsHandler.js b/public/models/trace/handlers/UserTimingsHandler.js index 29d888a69..d528d1296 100644 --- a/public/models/trace/handlers/UserTimingsHandler.js +++ b/public/models/trace/handlers/UserTimingsHandler.js @@ -72,17 +72,17 @@ export function handleEvent(event) { if (ignoredNames.includes(event.name)) { return; } - if (Types.TraceEvents.isTraceEventPerformanceMeasure(event)) { + if (Types.Events.isPerformanceMeasure(event)) { performanceMeasureEvents.push(event); return; } - if (Types.TraceEvents.isTraceEventPerformanceMark(event)) { + if (Types.Events.isPerformanceMark(event)) { performanceMarkEvents.push(event); } - if (Types.TraceEvents.isTraceEventConsoleTime(event)) { + if (Types.Events.isConsoleTime(event)) { consoleTimings.push(event); } - if (Types.TraceEvents.isTraceEventTimeStamp(event)) { + if (Types.Events.isTimeStamp(event)) { timestampEvents.push(event); } } diff --git a/public/models/trace/handlers/UserTimingsHandler.js.map b/public/models/trace/handlers/UserTimingsHandler.js.map index 5dbf4d468..73e2c10d3 100644 --- a/public/models/trace/handlers/UserTimingsHandler.js.map +++ b/public/models/trace/handlers/UserTimingsHandler.js.map @@ -1 +1 @@ -{"version":3,"file":"UserTimingsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/UserTimingsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {HandlerState} from './types.js';\n\n/**\n * IMPORTANT!\n * See UserTimings.md in this directory for some handy documentation on\n * UserTimings and the trace events we parse currently.\n **/\nlet syntheticEvents: Types.TraceEvents.SyntheticEventPair[] = [];\nconst performanceMeasureEvents: Types.TraceEvents.TraceEventPerformanceMeasure[] = [];\nconst performanceMarkEvents: Types.TraceEvents.TraceEventPerformanceMark[] = [];\n\nconst consoleTimings: (Types.TraceEvents.TraceEventConsoleTimeBegin|Types.TraceEvents.TraceEventConsoleTimeEnd)[] = [];\n\nconst timestampEvents: Types.TraceEvents.TraceEventTimeStamp[] = [];\n\nexport interface UserTimingsData {\n /**\n * Events triggered with the performance.measure() API.\n * https://developer.mozilla.org/en-US/docs/Web/API/Performance/measure\n */\n performanceMeasures: readonly Types.TraceEvents.SyntheticUserTimingPair[];\n /**\n * Events triggered with the performance.mark() API.\n * https://developer.mozilla.org/en-US/docs/Web/API/Performance/mark\n */\n performanceMarks: readonly Types.TraceEvents.TraceEventPerformanceMark[];\n /**\n * Events triggered with the console.time(), console.timeEnd() and\n * console.timeLog() API.\n * https://developer.mozilla.org/en-US/docs/Web/API/console/time\n */\n consoleTimings: readonly Types.TraceEvents.SyntheticConsoleTimingPair[];\n /**\n * Events triggered with the console.timeStamp() API\n * https://developer.mozilla.org/en-US/docs/Web/API/console/timeStamp\n */\n timestampEvents: readonly Types.TraceEvents.TraceEventTimeStamp[];\n}\nlet handlerState = HandlerState.UNINITIALIZED;\n\nexport function reset(): void {\n syntheticEvents.length = 0;\n performanceMeasureEvents.length = 0;\n performanceMarkEvents.length = 0;\n consoleTimings.length = 0;\n timestampEvents.length = 0;\n handlerState = HandlerState.INITIALIZED;\n}\n\nconst resourceTimingNames = [\n 'workerStart',\n 'redirectStart',\n 'redirectEnd',\n 'fetchStart',\n 'domainLookupStart',\n 'domainLookupEnd',\n 'connectStart',\n 'connectEnd',\n 'secureConnectionStart',\n 'requestStart',\n 'responseStart',\n 'responseEnd',\n];\nconst navTimingNames = [\n 'navigationStart',\n 'unloadEventStart',\n 'unloadEventEnd',\n 'redirectStart',\n 'redirectEnd',\n 'fetchStart',\n 'commitNavigationEnd',\n 'domainLookupStart',\n 'domainLookupEnd',\n 'connectStart',\n 'connectEnd',\n 'secureConnectionStart',\n 'requestStart',\n 'responseStart',\n 'responseEnd',\n 'domLoading',\n 'domInteractive',\n 'domContentLoadedEventStart',\n 'domContentLoadedEventEnd',\n 'domComplete',\n 'loadEventStart',\n 'loadEventEnd',\n];\n// These are events dispatched under the blink.user_timing category\n// but that the user didn't add. Filter them out so that they do not\n// Appear in the timings track (they still appear in the main thread\n// flame chart).\nconst ignoredNames = [...resourceTimingNames, ...navTimingNames];\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('UserTimings handler is not initialized');\n }\n\n if (ignoredNames.includes(event.name)) {\n return;\n }\n\n if (Types.TraceEvents.isTraceEventPerformanceMeasure(event)) {\n performanceMeasureEvents.push(event);\n return;\n }\n if (Types.TraceEvents.isTraceEventPerformanceMark(event)) {\n performanceMarkEvents.push(event);\n }\n if (Types.TraceEvents.isTraceEventConsoleTime(event)) {\n consoleTimings.push(event);\n }\n if (Types.TraceEvents.isTraceEventTimeStamp(event)) {\n timestampEvents.push(event);\n }\n}\n\nexport async function finalize(): Promise {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('UserTimings handler is not initialized');\n }\n\n const asyncEvents = [...performanceMeasureEvents, ...consoleTimings];\n syntheticEvents = Helpers.Trace.createMatchedSortedSyntheticEvents(asyncEvents);\n handlerState = HandlerState.FINALIZED;\n}\n\nexport function data(): UserTimingsData {\n if (handlerState !== HandlerState.FINALIZED) {\n throw new Error('UserTimings handler is not finalized');\n }\n\n return {\n performanceMeasures: syntheticEvents.filter(e => e.cat === 'blink.user_timing') as\n Types.TraceEvents.SyntheticUserTimingPair[],\n consoleTimings: syntheticEvents.filter(e => e.cat === 'blink.console') as\n Types.TraceEvents.SyntheticConsoleTimingPair[],\n // TODO(crbug/41484172): UserTimingsHandler.test.ts fails if this is not copied.\n performanceMarks: [...performanceMarkEvents],\n timestampEvents: [...timestampEvents],\n };\n}\n"]} \ No newline at end of file +{"version":3,"file":"UserTimingsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/UserTimingsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {HandlerState} from './types.js';\n\n/**\n * IMPORTANT!\n * See UserTimings.md in this directory for some handy documentation on\n * UserTimings and the trace events we parse currently.\n **/\nlet syntheticEvents: Types.Events.SyntheticEventPair[] = [];\nconst performanceMeasureEvents: Types.Events.PerformanceMeasure[] = [];\nconst performanceMarkEvents: Types.Events.PerformanceMark[] = [];\n\nconst consoleTimings: (Types.Events.ConsoleTimeBegin|Types.Events.ConsoleTimeEnd)[] = [];\n\nconst timestampEvents: Types.Events.TimeStamp[] = [];\n\nexport interface UserTimingsData {\n /**\n * Events triggered with the performance.measure() API.\n * https://developer.mozilla.org/en-US/docs/Web/API/Performance/measure\n */\n performanceMeasures: readonly Types.Events.SyntheticUserTimingPair[];\n /**\n * Events triggered with the performance.mark() API.\n * https://developer.mozilla.org/en-US/docs/Web/API/Performance/mark\n */\n performanceMarks: readonly Types.Events.PerformanceMark[];\n /**\n * Events triggered with the console.time(), console.timeEnd() and\n * console.timeLog() API.\n * https://developer.mozilla.org/en-US/docs/Web/API/console/time\n */\n consoleTimings: readonly Types.Events.SyntheticConsoleTimingPair[];\n /**\n * Events triggered with the console.timeStamp() API\n * https://developer.mozilla.org/en-US/docs/Web/API/console/timeStamp\n */\n timestampEvents: readonly Types.Events.TimeStamp[];\n}\nlet handlerState = HandlerState.UNINITIALIZED;\n\nexport function reset(): void {\n syntheticEvents.length = 0;\n performanceMeasureEvents.length = 0;\n performanceMarkEvents.length = 0;\n consoleTimings.length = 0;\n timestampEvents.length = 0;\n handlerState = HandlerState.INITIALIZED;\n}\n\nconst resourceTimingNames = [\n 'workerStart',\n 'redirectStart',\n 'redirectEnd',\n 'fetchStart',\n 'domainLookupStart',\n 'domainLookupEnd',\n 'connectStart',\n 'connectEnd',\n 'secureConnectionStart',\n 'requestStart',\n 'responseStart',\n 'responseEnd',\n];\nconst navTimingNames = [\n 'navigationStart',\n 'unloadEventStart',\n 'unloadEventEnd',\n 'redirectStart',\n 'redirectEnd',\n 'fetchStart',\n 'commitNavigationEnd',\n 'domainLookupStart',\n 'domainLookupEnd',\n 'connectStart',\n 'connectEnd',\n 'secureConnectionStart',\n 'requestStart',\n 'responseStart',\n 'responseEnd',\n 'domLoading',\n 'domInteractive',\n 'domContentLoadedEventStart',\n 'domContentLoadedEventEnd',\n 'domComplete',\n 'loadEventStart',\n 'loadEventEnd',\n];\n// These are events dispatched under the blink.user_timing category\n// but that the user didn't add. Filter them out so that they do not\n// Appear in the timings track (they still appear in the main thread\n// flame chart).\nconst ignoredNames = [...resourceTimingNames, ...navTimingNames];\n\nexport function handleEvent(event: Types.Events.Event): void {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('UserTimings handler is not initialized');\n }\n\n if (ignoredNames.includes(event.name)) {\n return;\n }\n\n if (Types.Events.isPerformanceMeasure(event)) {\n performanceMeasureEvents.push(event);\n return;\n }\n if (Types.Events.isPerformanceMark(event)) {\n performanceMarkEvents.push(event);\n }\n if (Types.Events.isConsoleTime(event)) {\n consoleTimings.push(event);\n }\n if (Types.Events.isTimeStamp(event)) {\n timestampEvents.push(event);\n }\n}\n\nexport async function finalize(): Promise {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('UserTimings handler is not initialized');\n }\n\n const asyncEvents = [...performanceMeasureEvents, ...consoleTimings];\n syntheticEvents = Helpers.Trace.createMatchedSortedSyntheticEvents(asyncEvents);\n handlerState = HandlerState.FINALIZED;\n}\n\nexport function data(): UserTimingsData {\n if (handlerState !== HandlerState.FINALIZED) {\n throw new Error('UserTimings handler is not finalized');\n }\n\n return {\n performanceMeasures: syntheticEvents.filter(e => e.cat === 'blink.user_timing') as\n Types.Events.SyntheticUserTimingPair[],\n consoleTimings: syntheticEvents.filter(e => e.cat === 'blink.console') as Types.Events.SyntheticConsoleTimingPair[],\n // TODO(crbug/41484172): UserTimingsHandler.test.ts fails if this is not copied.\n performanceMarks: [...performanceMarkEvents],\n timestampEvents: [...timestampEvents],\n };\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/UserTimingsHandler.test.js b/public/models/trace/handlers/UserTimingsHandler.test.js index 20f007c85..1efe15e53 100644 --- a/public/models/trace/handlers/UserTimingsHandler.test.js +++ b/public/models/trace/handlers/UserTimingsHandler.test.js @@ -2,17 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import { TraceLoader } from '../../../testing/TraceLoader.js'; -import * as TraceModel from '../trace.js'; +import * as Trace from '../trace.js'; describe('UserTimingsHandler', function () { let timingsData; describe('performance timings', function () { async function getTimingsDataFromEvents(events) { - TraceModel.Handlers.ModelHandlers.UserTimings.reset(); + Trace.Handlers.ModelHandlers.UserTimings.reset(); for (const event of events) { - TraceModel.Handlers.ModelHandlers.UserTimings.handleEvent(event); + Trace.Handlers.ModelHandlers.UserTimings.handleEvent(event); } - await TraceModel.Handlers.ModelHandlers.UserTimings.finalize(); - return TraceModel.Handlers.ModelHandlers.UserTimings.data(); + await Trace.Handlers.ModelHandlers.UserTimings.finalize(); + return Trace.Handlers.ModelHandlers.UserTimings.data(); } before(async function () { const events = await TraceLoader.rawEvents(this, 'user-timings.json.gz'); @@ -21,44 +21,44 @@ describe('UserTimingsHandler', function () { describe('performance.measure events parsing', function () { it('parses the start and end events and returns a list of blocks', async () => { assert.lengthOf(timingsData.performanceMeasures, 3); - assert.strictEqual(TraceModel.Helpers.Trace.extractId(timingsData.performanceMeasures[0]), 'blink.user_timing:0x9072211:first measure'); + assert.strictEqual(Trace.Helpers.Trace.extractId(timingsData.performanceMeasures[0]), 'blink.user_timing:0x9072211:first measure'); assert.strictEqual(timingsData.performanceMeasures[0].name, 'first measure'); - assert.strictEqual(TraceModel.Helpers.Trace.extractId(timingsData.performanceMeasures[1]), 'blink.user_timing:0x6ece31c8:second measure'); + assert.strictEqual(Trace.Helpers.Trace.extractId(timingsData.performanceMeasures[1]), 'blink.user_timing:0x6ece31c8:second measure'); assert.strictEqual(timingsData.performanceMeasures[1].name, 'second measure'); - assert.strictEqual(TraceModel.Helpers.Trace.extractId(timingsData.performanceMeasures[2]), 'blink.user_timing:0x10c31982:third measure'); + assert.strictEqual(Trace.Helpers.Trace.extractId(timingsData.performanceMeasures[2]), 'blink.user_timing:0x10c31982:third measure'); assert.strictEqual(timingsData.performanceMeasures[2].name, 'third measure'); // Ensure we assign begin + end the right way round by making sure the // beginEvent is the ASYNC_NESTABLE_START and the endEvent is the // ASYNC_NESTABLE_END. for (let i = 0; i < timingsData.performanceMeasures.length; i++) { - assert.strictEqual(timingsData.performanceMeasures[i].args.data.beginEvent.ph, "b" /* TraceModel.Types.TraceEvents.Phase.ASYNC_NESTABLE_START */); - assert.strictEqual(timingsData.performanceMeasures[i].args.data.endEvent.ph, "e" /* TraceModel.Types.TraceEvents.Phase.ASYNC_NESTABLE_END */); + assert.strictEqual(timingsData.performanceMeasures[i].args.data.beginEvent.ph, "b" /* Trace.Types.Events.Phase.ASYNC_NESTABLE_START */); + assert.strictEqual(timingsData.performanceMeasures[i].args.data.endEvent.ph, "e" /* Trace.Types.Events.Phase.ASYNC_NESTABLE_END */); } }); it('sorts the blocks to ensure they are in time order', async function () { const events = await TraceLoader.rawEvents(this, 'user-timings.json.gz'); - TraceModel.Handlers.ModelHandlers.UserTimings.reset(); + Trace.Handlers.ModelHandlers.UserTimings.reset(); // Reverse the array so that the events are in the wrong order. // This _shouldn't_ ever happen in a real trace, but it's best for us to // sort the blocks once we've parsed them just in case. const reversed = events.slice().reverse(); for (const event of reversed) { - TraceModel.Handlers.ModelHandlers.UserTimings.handleEvent(event); + Trace.Handlers.ModelHandlers.UserTimings.handleEvent(event); } - await TraceModel.Handlers.ModelHandlers.UserTimings.finalize(); - const data = TraceModel.Handlers.ModelHandlers.UserTimings.data(); + await Trace.Handlers.ModelHandlers.UserTimings.finalize(); + const data = Trace.Handlers.ModelHandlers.UserTimings.data(); assert.lengthOf(data.performanceMeasures, 3); assert.isTrue(data.performanceMeasures[0].ts <= data.performanceMeasures[1].ts); assert.isTrue(data.performanceMeasures[1].ts <= data.performanceMeasures[2].ts); }); it('calculates the duration correctly from the begin/end event timestamps', async function () { const events = await TraceLoader.rawEvents(this, 'user-timings.json.gz'); - TraceModel.Handlers.ModelHandlers.UserTimings.reset(); + Trace.Handlers.ModelHandlers.UserTimings.reset(); for (const event of events) { - TraceModel.Handlers.ModelHandlers.UserTimings.handleEvent(event); + Trace.Handlers.ModelHandlers.UserTimings.handleEvent(event); } - await TraceModel.Handlers.ModelHandlers.UserTimings.finalize(); - const data = TraceModel.Handlers.ModelHandlers.UserTimings.data(); + await Trace.Handlers.ModelHandlers.UserTimings.finalize(); + const data = Trace.Handlers.ModelHandlers.UserTimings.data(); for (const timing of data.performanceMeasures) { // Ensure for each timing pair we've set the dur correctly. assert.strictEqual(timing.dur, timing.args.data.endEvent.ts - timing.args.data.beginEvent.ts); @@ -109,40 +109,40 @@ describe('UserTimingsHandler', function () { describe('console timings', function () { before(async function () { const events = await TraceLoader.rawEvents(this, 'timings-track.json.gz'); - TraceModel.Handlers.ModelHandlers.UserTimings.reset(); + Trace.Handlers.ModelHandlers.UserTimings.reset(); for (const event of events) { - TraceModel.Handlers.ModelHandlers.UserTimings.handleEvent(event); + Trace.Handlers.ModelHandlers.UserTimings.handleEvent(event); } - await TraceModel.Handlers.ModelHandlers.UserTimings.finalize(); - timingsData = TraceModel.Handlers.ModelHandlers.UserTimings.data(); + await Trace.Handlers.ModelHandlers.UserTimings.finalize(); + timingsData = Trace.Handlers.ModelHandlers.UserTimings.data(); }); describe('console.time events parsing', function () { it('parses the start and end events and returns a list of blocks', async () => { assert.lengthOf(timingsData.consoleTimings, 3); - assert.strictEqual(TraceModel.Helpers.Trace.extractId(timingsData.consoleTimings[0]), 'blink.console:0x12c00282160:first console time'); + assert.strictEqual(Trace.Helpers.Trace.extractId(timingsData.consoleTimings[0]), 'blink.console:0x12c00282160:first console time'); assert.strictEqual(timingsData.consoleTimings[0].name, 'first console time'); - assert.strictEqual(TraceModel.Helpers.Trace.extractId(timingsData.consoleTimings[1]), 'blink.console:0x12c00282160:second console time'); + assert.strictEqual(Trace.Helpers.Trace.extractId(timingsData.consoleTimings[1]), 'blink.console:0x12c00282160:second console time'); assert.strictEqual(timingsData.consoleTimings[1].name, 'second console time'); // Ensure we assign begin + end the right way round by making sure the // beginEvent is the ASYNC_NESTABLE_START and the endEvent is the // ASYNC_NESTABLE_END. for (let i = 0; i < timingsData.consoleTimings.length; i++) { - assert.strictEqual(timingsData.consoleTimings[i].args.data.beginEvent.ph, "b" /* TraceModel.Types.TraceEvents.Phase.ASYNC_NESTABLE_START */); - assert.strictEqual(timingsData.consoleTimings[i].args.data.endEvent.ph, "e" /* TraceModel.Types.TraceEvents.Phase.ASYNC_NESTABLE_END */); + assert.strictEqual(timingsData.consoleTimings[i].args.data.beginEvent.ph, "b" /* Trace.Types.Events.Phase.ASYNC_NESTABLE_START */); + assert.strictEqual(timingsData.consoleTimings[i].args.data.endEvent.ph, "e" /* Trace.Types.Events.Phase.ASYNC_NESTABLE_END */); } }); it('sorts the blocks to ensure they are in time order', async function () { const events = await TraceLoader.rawEvents(this, 'timings-track.json.gz'); - TraceModel.Handlers.ModelHandlers.UserTimings.reset(); + Trace.Handlers.ModelHandlers.UserTimings.reset(); // Reverse the array so that the events are in the wrong order. // This _shouldn't_ ever happen in a real trace, but it's best for us to // sort the blocks once we've parsed them just in case. const reversed = events.slice().reverse(); for (const event of reversed) { - TraceModel.Handlers.ModelHandlers.UserTimings.handleEvent(event); + Trace.Handlers.ModelHandlers.UserTimings.handleEvent(event); } - await TraceModel.Handlers.ModelHandlers.UserTimings.finalize(); - const data = TraceModel.Handlers.ModelHandlers.UserTimings.data(); + await Trace.Handlers.ModelHandlers.UserTimings.finalize(); + const data = Trace.Handlers.ModelHandlers.UserTimings.data(); assert.lengthOf(data.consoleTimings, 3); assert.isTrue(data.consoleTimings[0].ts <= data.consoleTimings[1].ts); assert.isTrue(data.consoleTimings[1].ts <= data.consoleTimings[2].ts); diff --git a/public/models/trace/handlers/UserTimingsHandler.test.js.map b/public/models/trace/handlers/UserTimingsHandler.test.js.map index 258b9281d..9953bbacc 100644 --- a/public/models/trace/handlers/UserTimingsHandler.test.js.map +++ b/public/models/trace/handlers/UserTimingsHandler.test.js.map @@ -1 +1 @@ -{"version":3,"file":"UserTimingsHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/UserTimingsHandler.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as TraceModel from '../trace.js';\n\ndescribe('UserTimingsHandler', function() {\n let timingsData: TraceModel.Handlers.ModelHandlers.UserTimings.UserTimingsData;\n describe('performance timings', function() {\n async function getTimingsDataFromEvents(events: readonly TraceModel.Types.TraceEvents.TraceEventData[]):\n Promise {\n TraceModel.Handlers.ModelHandlers.UserTimings.reset();\n for (const event of events) {\n TraceModel.Handlers.ModelHandlers.UserTimings.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.UserTimings.finalize();\n return TraceModel.Handlers.ModelHandlers.UserTimings.data();\n }\n before(async function() {\n const events = await TraceLoader.rawEvents(this, 'user-timings.json.gz');\n timingsData = await getTimingsDataFromEvents(events);\n });\n describe('performance.measure events parsing', function() {\n it('parses the start and end events and returns a list of blocks', async () => {\n assert.lengthOf(timingsData.performanceMeasures, 3);\n assert.strictEqual(\n TraceModel.Helpers.Trace.extractId(timingsData.performanceMeasures[0]),\n 'blink.user_timing:0x9072211:first measure');\n assert.strictEqual(timingsData.performanceMeasures[0].name, 'first measure');\n assert.strictEqual(\n TraceModel.Helpers.Trace.extractId(timingsData.performanceMeasures[1]),\n 'blink.user_timing:0x6ece31c8:second measure');\n assert.strictEqual(timingsData.performanceMeasures[1].name, 'second measure');\n assert.strictEqual(\n TraceModel.Helpers.Trace.extractId(timingsData.performanceMeasures[2]),\n 'blink.user_timing:0x10c31982:third measure');\n assert.strictEqual(timingsData.performanceMeasures[2].name, 'third measure');\n\n // Ensure we assign begin + end the right way round by making sure the\n // beginEvent is the ASYNC_NESTABLE_START and the endEvent is the\n // ASYNC_NESTABLE_END.\n for (let i = 0; i < timingsData.performanceMeasures.length; i++) {\n assert.strictEqual(\n timingsData.performanceMeasures[i].args.data.beginEvent.ph,\n TraceModel.Types.TraceEvents.Phase.ASYNC_NESTABLE_START);\n assert.strictEqual(\n timingsData.performanceMeasures[i].args.data.endEvent.ph,\n TraceModel.Types.TraceEvents.Phase.ASYNC_NESTABLE_END);\n }\n });\n\n it('sorts the blocks to ensure they are in time order', async function() {\n const events = await TraceLoader.rawEvents(this, 'user-timings.json.gz');\n TraceModel.Handlers.ModelHandlers.UserTimings.reset();\n // Reverse the array so that the events are in the wrong order.\n // This _shouldn't_ ever happen in a real trace, but it's best for us to\n // sort the blocks once we've parsed them just in case.\n const reversed = events.slice().reverse();\n for (const event of reversed) {\n TraceModel.Handlers.ModelHandlers.UserTimings.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.UserTimings.finalize();\n const data = TraceModel.Handlers.ModelHandlers.UserTimings.data();\n assert.lengthOf(data.performanceMeasures, 3);\n assert.isTrue(data.performanceMeasures[0].ts <= data.performanceMeasures[1].ts);\n assert.isTrue(data.performanceMeasures[1].ts <= data.performanceMeasures[2].ts);\n });\n\n it('calculates the duration correctly from the begin/end event timestamps', async function() {\n const events = await TraceLoader.rawEvents(this, 'user-timings.json.gz');\n TraceModel.Handlers.ModelHandlers.UserTimings.reset();\n for (const event of events) {\n TraceModel.Handlers.ModelHandlers.UserTimings.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.UserTimings.finalize();\n const data = TraceModel.Handlers.ModelHandlers.UserTimings.data();\n for (const timing of data.performanceMeasures) {\n // Ensure for each timing pair we've set the dur correctly.\n assert.strictEqual(timing.dur, timing.args.data.endEvent.ts - timing.args.data.beginEvent.ts);\n }\n });\n it('correctly extracts nested timings in the correct order', async function() {\n const events = await TraceLoader.rawEvents(this, 'user-timings-complex.json.gz');\n const complexTimingsData = await getTimingsDataFromEvents(events);\n const userTimingEventNames = [];\n for (const event of complexTimingsData.performanceMeasures) {\n // This trace has multiple user timings events, in this instance we only care about the ones that include 'nested' in the name.\n if (event.name.includes('nested')) {\n userTimingEventNames.push(event.name);\n }\n }\n assert.deepEqual(userTimingEventNames, [\n 'nested-a',\n 'nested-b',\n 'nested-c',\n 'nested-d',\n ]);\n });\n it('correctly orders measures when one measure encapsulates the others', async function() {\n const events = await TraceLoader.rawEvents(this, 'user-timings-complex.json.gz');\n const complexTimingsData = await getTimingsDataFromEvents(events);\n const userTimingEventNames = [];\n for (const event of complexTimingsData.performanceMeasures) {\n // This trace has multiple user timings events, in this instance we only care about the ones that start with 'duration'\n if (event.name.startsWith('duration')) {\n userTimingEventNames.push(event.name);\n }\n }\n assert.deepEqual(userTimingEventNames, [\n 'durationTimeTotal',\n 'durationTime1',\n 'durationTime2',\n ]);\n });\n });\n describe('performance.mark events parsing', function() {\n it('parses performance mark events correctly', function() {\n assert.lengthOf(timingsData.performanceMarks, 2);\n assert.strictEqual(timingsData.performanceMarks[0].name, 'mark1');\n assert.strictEqual(timingsData.performanceMarks[1].name, 'mark3');\n });\n });\n });\n describe('console timings', function() {\n before(async function() {\n const events = await TraceLoader.rawEvents(this, 'timings-track.json.gz');\n TraceModel.Handlers.ModelHandlers.UserTimings.reset();\n for (const event of events) {\n TraceModel.Handlers.ModelHandlers.UserTimings.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.UserTimings.finalize();\n timingsData = TraceModel.Handlers.ModelHandlers.UserTimings.data();\n });\n describe('console.time events parsing', function() {\n it('parses the start and end events and returns a list of blocks', async () => {\n assert.lengthOf(timingsData.consoleTimings, 3);\n assert.strictEqual(\n TraceModel.Helpers.Trace.extractId(timingsData.consoleTimings[0]),\n 'blink.console:0x12c00282160:first console time');\n assert.strictEqual(timingsData.consoleTimings[0].name, 'first console time');\n assert.strictEqual(\n TraceModel.Helpers.Trace.extractId(timingsData.consoleTimings[1]),\n 'blink.console:0x12c00282160:second console time');\n assert.strictEqual(timingsData.consoleTimings[1].name, 'second console time');\n\n // Ensure we assign begin + end the right way round by making sure the\n // beginEvent is the ASYNC_NESTABLE_START and the endEvent is the\n // ASYNC_NESTABLE_END.\n for (let i = 0; i < timingsData.consoleTimings.length; i++) {\n assert.strictEqual(\n timingsData.consoleTimings[i].args.data.beginEvent.ph,\n TraceModel.Types.TraceEvents.Phase.ASYNC_NESTABLE_START);\n assert.strictEqual(\n timingsData.consoleTimings[i].args.data.endEvent.ph,\n TraceModel.Types.TraceEvents.Phase.ASYNC_NESTABLE_END);\n }\n });\n\n it('sorts the blocks to ensure they are in time order', async function() {\n const events = await TraceLoader.rawEvents(this, 'timings-track.json.gz');\n TraceModel.Handlers.ModelHandlers.UserTimings.reset();\n // Reverse the array so that the events are in the wrong order.\n // This _shouldn't_ ever happen in a real trace, but it's best for us to\n // sort the blocks once we've parsed them just in case.\n const reversed = events.slice().reverse();\n for (const event of reversed) {\n TraceModel.Handlers.ModelHandlers.UserTimings.handleEvent(event);\n }\n await TraceModel.Handlers.ModelHandlers.UserTimings.finalize();\n const data = TraceModel.Handlers.ModelHandlers.UserTimings.data();\n assert.lengthOf(data.consoleTimings, 3);\n assert.isTrue(data.consoleTimings[0].ts <= data.consoleTimings[1].ts);\n assert.isTrue(data.consoleTimings[1].ts <= data.consoleTimings[2].ts);\n });\n\n it('calculates the duration correctly from the begin/end event timestamps', async () => {\n for (const consoleTiming of timingsData.consoleTimings) {\n // Ensure for each timing pair we've set the dur correctly.\n assert.strictEqual(\n consoleTiming.dur, consoleTiming.args.data.endEvent.ts - consoleTiming.args.data.beginEvent.ts);\n }\n });\n });\n describe('console.timestamp events parsing', function() {\n it('parses performance mark events correctly', function() {\n assert.lengthOf(timingsData.timestampEvents, 3);\n assert.strictEqual(timingsData.timestampEvents[0].args.data.message, 'a timestamp');\n assert.strictEqual(timingsData.timestampEvents[1].args.data.message, 'another timestamp');\n assert.strictEqual(timingsData.timestampEvents[2].args.data.message, 'yet another timestamp');\n });\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"UserTimingsHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/UserTimingsHandler.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Trace from '../trace.js';\n\ndescribe('UserTimingsHandler', function() {\n let timingsData: Trace.Handlers.ModelHandlers.UserTimings.UserTimingsData;\n describe('performance timings', function() {\n async function getTimingsDataFromEvents(events: readonly Trace.Types.Events.Event[]):\n Promise {\n Trace.Handlers.ModelHandlers.UserTimings.reset();\n for (const event of events) {\n Trace.Handlers.ModelHandlers.UserTimings.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.UserTimings.finalize();\n return Trace.Handlers.ModelHandlers.UserTimings.data();\n }\n before(async function() {\n const events = await TraceLoader.rawEvents(this, 'user-timings.json.gz');\n timingsData = await getTimingsDataFromEvents(events);\n });\n describe('performance.measure events parsing', function() {\n it('parses the start and end events and returns a list of blocks', async () => {\n assert.lengthOf(timingsData.performanceMeasures, 3);\n assert.strictEqual(\n Trace.Helpers.Trace.extractId(timingsData.performanceMeasures[0]),\n 'blink.user_timing:0x9072211:first measure');\n assert.strictEqual(timingsData.performanceMeasures[0].name, 'first measure');\n assert.strictEqual(\n Trace.Helpers.Trace.extractId(timingsData.performanceMeasures[1]),\n 'blink.user_timing:0x6ece31c8:second measure');\n assert.strictEqual(timingsData.performanceMeasures[1].name, 'second measure');\n assert.strictEqual(\n Trace.Helpers.Trace.extractId(timingsData.performanceMeasures[2]),\n 'blink.user_timing:0x10c31982:third measure');\n assert.strictEqual(timingsData.performanceMeasures[2].name, 'third measure');\n\n // Ensure we assign begin + end the right way round by making sure the\n // beginEvent is the ASYNC_NESTABLE_START and the endEvent is the\n // ASYNC_NESTABLE_END.\n for (let i = 0; i < timingsData.performanceMeasures.length; i++) {\n assert.strictEqual(\n timingsData.performanceMeasures[i].args.data.beginEvent.ph,\n Trace.Types.Events.Phase.ASYNC_NESTABLE_START);\n assert.strictEqual(\n timingsData.performanceMeasures[i].args.data.endEvent.ph, Trace.Types.Events.Phase.ASYNC_NESTABLE_END);\n }\n });\n\n it('sorts the blocks to ensure they are in time order', async function() {\n const events = await TraceLoader.rawEvents(this, 'user-timings.json.gz');\n Trace.Handlers.ModelHandlers.UserTimings.reset();\n // Reverse the array so that the events are in the wrong order.\n // This _shouldn't_ ever happen in a real trace, but it's best for us to\n // sort the blocks once we've parsed them just in case.\n const reversed = events.slice().reverse();\n for (const event of reversed) {\n Trace.Handlers.ModelHandlers.UserTimings.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.UserTimings.finalize();\n const data = Trace.Handlers.ModelHandlers.UserTimings.data();\n assert.lengthOf(data.performanceMeasures, 3);\n assert.isTrue(data.performanceMeasures[0].ts <= data.performanceMeasures[1].ts);\n assert.isTrue(data.performanceMeasures[1].ts <= data.performanceMeasures[2].ts);\n });\n\n it('calculates the duration correctly from the begin/end event timestamps', async function() {\n const events = await TraceLoader.rawEvents(this, 'user-timings.json.gz');\n Trace.Handlers.ModelHandlers.UserTimings.reset();\n for (const event of events) {\n Trace.Handlers.ModelHandlers.UserTimings.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.UserTimings.finalize();\n const data = Trace.Handlers.ModelHandlers.UserTimings.data();\n for (const timing of data.performanceMeasures) {\n // Ensure for each timing pair we've set the dur correctly.\n assert.strictEqual(timing.dur, timing.args.data.endEvent.ts - timing.args.data.beginEvent.ts);\n }\n });\n it('correctly extracts nested timings in the correct order', async function() {\n const events = await TraceLoader.rawEvents(this, 'user-timings-complex.json.gz');\n const complexTimingsData = await getTimingsDataFromEvents(events);\n const userTimingEventNames = [];\n for (const event of complexTimingsData.performanceMeasures) {\n // This trace has multiple user timings events, in this instance we only care about the ones that include 'nested' in the name.\n if (event.name.includes('nested')) {\n userTimingEventNames.push(event.name);\n }\n }\n assert.deepEqual(userTimingEventNames, [\n 'nested-a',\n 'nested-b',\n 'nested-c',\n 'nested-d',\n ]);\n });\n it('correctly orders measures when one measure encapsulates the others', async function() {\n const events = await TraceLoader.rawEvents(this, 'user-timings-complex.json.gz');\n const complexTimingsData = await getTimingsDataFromEvents(events);\n const userTimingEventNames = [];\n for (const event of complexTimingsData.performanceMeasures) {\n // This trace has multiple user timings events, in this instance we only care about the ones that start with 'duration'\n if (event.name.startsWith('duration')) {\n userTimingEventNames.push(event.name);\n }\n }\n assert.deepEqual(userTimingEventNames, [\n 'durationTimeTotal',\n 'durationTime1',\n 'durationTime2',\n ]);\n });\n });\n describe('performance.mark events parsing', function() {\n it('parses performance mark events correctly', function() {\n assert.lengthOf(timingsData.performanceMarks, 2);\n assert.strictEqual(timingsData.performanceMarks[0].name, 'mark1');\n assert.strictEqual(timingsData.performanceMarks[1].name, 'mark3');\n });\n });\n });\n describe('console timings', function() {\n before(async function() {\n const events = await TraceLoader.rawEvents(this, 'timings-track.json.gz');\n Trace.Handlers.ModelHandlers.UserTimings.reset();\n for (const event of events) {\n Trace.Handlers.ModelHandlers.UserTimings.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.UserTimings.finalize();\n timingsData = Trace.Handlers.ModelHandlers.UserTimings.data();\n });\n describe('console.time events parsing', function() {\n it('parses the start and end events and returns a list of blocks', async () => {\n assert.lengthOf(timingsData.consoleTimings, 3);\n assert.strictEqual(\n Trace.Helpers.Trace.extractId(timingsData.consoleTimings[0]),\n 'blink.console:0x12c00282160:first console time');\n assert.strictEqual(timingsData.consoleTimings[0].name, 'first console time');\n assert.strictEqual(\n Trace.Helpers.Trace.extractId(timingsData.consoleTimings[1]),\n 'blink.console:0x12c00282160:second console time');\n assert.strictEqual(timingsData.consoleTimings[1].name, 'second console time');\n\n // Ensure we assign begin + end the right way round by making sure the\n // beginEvent is the ASYNC_NESTABLE_START and the endEvent is the\n // ASYNC_NESTABLE_END.\n for (let i = 0; i < timingsData.consoleTimings.length; i++) {\n assert.strictEqual(\n timingsData.consoleTimings[i].args.data.beginEvent.ph, Trace.Types.Events.Phase.ASYNC_NESTABLE_START);\n assert.strictEqual(\n timingsData.consoleTimings[i].args.data.endEvent.ph, Trace.Types.Events.Phase.ASYNC_NESTABLE_END);\n }\n });\n\n it('sorts the blocks to ensure they are in time order', async function() {\n const events = await TraceLoader.rawEvents(this, 'timings-track.json.gz');\n Trace.Handlers.ModelHandlers.UserTimings.reset();\n // Reverse the array so that the events are in the wrong order.\n // This _shouldn't_ ever happen in a real trace, but it's best for us to\n // sort the blocks once we've parsed them just in case.\n const reversed = events.slice().reverse();\n for (const event of reversed) {\n Trace.Handlers.ModelHandlers.UserTimings.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.UserTimings.finalize();\n const data = Trace.Handlers.ModelHandlers.UserTimings.data();\n assert.lengthOf(data.consoleTimings, 3);\n assert.isTrue(data.consoleTimings[0].ts <= data.consoleTimings[1].ts);\n assert.isTrue(data.consoleTimings[1].ts <= data.consoleTimings[2].ts);\n });\n\n it('calculates the duration correctly from the begin/end event timestamps', async () => {\n for (const consoleTiming of timingsData.consoleTimings) {\n // Ensure for each timing pair we've set the dur correctly.\n assert.strictEqual(\n consoleTiming.dur, consoleTiming.args.data.endEvent.ts - consoleTiming.args.data.beginEvent.ts);\n }\n });\n });\n describe('console.timestamp events parsing', function() {\n it('parses performance mark events correctly', function() {\n assert.lengthOf(timingsData.timestampEvents, 3);\n assert.strictEqual(timingsData.timestampEvents[0].args.data.message, 'a timestamp');\n assert.strictEqual(timingsData.timestampEvents[1].args.data.message, 'another timestamp');\n assert.strictEqual(timingsData.timestampEvents[2].args.data.message, 'yet another timestamp');\n });\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/WarningsHandler.d.ts b/public/models/trace/handlers/WarningsHandler.d.ts index ca539f386..b1cc314b3 100644 --- a/public/models/trace/handlers/WarningsHandler.d.ts +++ b/public/models/trace/handlers/WarningsHandler.d.ts @@ -1,14 +1,14 @@ import * as Types from '../types/types.js'; -import { type TraceEventHandlerName } from './types.js'; +import { type HandlerName } from './types.js'; export interface WarningsData { - perEvent: Map; - perWarning: Map; + perEvent: Map; + perWarning: Map; } export type Warning = 'LONG_TASK' | 'IDLE_CALLBACK_OVER_TIME' | 'FORCED_REFLOW' | 'LONG_INTERACTION'; export declare const FORCED_REFLOW_THRESHOLD: Types.Timing.MicroSeconds; export declare const LONG_MAIN_THREAD_TASK_THRESHOLD: Types.Timing.MicroSeconds; export declare function reset(): void; -export declare function handleEvent(event: Types.TraceEvents.TraceEventData): void; -export declare function deps(): TraceEventHandlerName[]; +export declare function handleEvent(event: Types.Events.Event): void; +export declare function deps(): HandlerName[]; export declare function finalize(): Promise; export declare function data(): WarningsData; diff --git a/public/models/trace/handlers/WarningsHandler.js b/public/models/trace/handlers/WarningsHandler.js index a50f5755c..7586371fa 100644 --- a/public/models/trace/handlers/WarningsHandler.js +++ b/public/models/trace/handlers/WarningsHandler.js @@ -40,14 +40,14 @@ function storeWarning(event, warning) { } export function handleEvent(event) { processForcedReflowWarning(event); - if (event.name === "RunTask" /* Types.TraceEvents.KnownEventName.RUN_TASK */) { + if (event.name === "RunTask" /* Types.Events.Name.RUN_TASK */) { const { duration } = Helpers.Timing.eventTimingsMicroSeconds(event); if (duration > LONG_MAIN_THREAD_TASK_THRESHOLD) { storeWarning(event, 'LONG_TASK'); } return; } - if (Types.TraceEvents.isTraceEventFireIdleCallback(event)) { + if (Types.Events.isFireIdleCallback(event)) { const { duration } = Helpers.Timing.eventTimingsMilliSeconds(event); if (duration > event.args.data.allottedMilliseconds) { storeWarning(event, 'IDLE_CALLBACK_OVER_TIME'); @@ -65,11 +65,10 @@ export function handleEvent(event) { function processForcedReflowWarning(event) { // Update the event and the JS invocation stacks. accomodateEventInStack(event, allEventsStack); - accomodateEventInStack(event, jsInvokeStack, /* pushEventToStack */ Types.TraceEvents.isJSInvocationEvent(event)); + accomodateEventInStack(event, jsInvokeStack, /* pushEventToStack */ Types.Events.isJSInvocationEvent(event)); if (jsInvokeStack.length) { // Current event falls inside a JS call. - if (event.name === "Layout" /* Types.TraceEvents.KnownEventName.LAYOUT */ || - event.name === "UpdateLayoutTree" /* Types.TraceEvents.KnownEventName.UPDATE_LAYOUT_TREE */) { + if (event.name === "Layout" /* Types.Events.Name.LAYOUT */ || event.name === "UpdateLayoutTree" /* Types.Events.Name.UPDATE_LAYOUT_TREE */) { // A forced reflow happened. However we need to check if // the threshold is surpassed to add a warning. Accumulate the // event to check for this after the current Task is over. diff --git a/public/models/trace/handlers/WarningsHandler.js.map b/public/models/trace/handlers/WarningsHandler.js.map index 05f7ebae7..d2b4027a3 100644 --- a/public/models/trace/handlers/WarningsHandler.js.map +++ b/public/models/trace/handlers/WarningsHandler.js.map @@ -1 +1 @@ -{"version":3,"file":"WarningsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/WarningsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {type TraceEventHandlerName} from './types.js';\nimport {data as userInteractionsHandlerData} from './UserInteractionsHandler.js';\n\nexport interface WarningsData {\n // Tracks warnings keyed by the event.\n perEvent: Map;\n // The same data in reverse: for each type of warning, track the events.\n // Useful if we need to enumerate events by type of issue\n perWarning: Map;\n}\n\nexport type Warning = 'LONG_TASK'|'IDLE_CALLBACK_OVER_TIME'|'FORCED_REFLOW'|'LONG_INTERACTION';\n\nconst warningsPerEvent: WarningsData['perEvent'] = new Map();\nconst eventsPerWarning: WarningsData['perWarning'] = new Map();\n\n/**\n * Tracks the stack formed by nested trace events up to a given point\n */\nconst allEventsStack: Types.TraceEvents.TraceEventData[] = [];\n/**\n * Tracks the stack formed by JS invocation trace events up to a given point.\n * F.e. FunctionCall, EvaluateScript, V8Execute.\n * Not to be confused with ProfileCalls.\n */\nconst jsInvokeStack: Types.TraceEvents.TraceEventData[] = [];\n/**\n * Tracks reflow events in a task.\n */\nconst taskReflowEvents: Types.TraceEvents.TraceEventData[] = [];\n\nexport const FORCED_REFLOW_THRESHOLD = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(30));\n\nexport const LONG_MAIN_THREAD_TASK_THRESHOLD = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(50));\n\nexport function reset(): void {\n warningsPerEvent.clear();\n eventsPerWarning.clear();\n allEventsStack.length = 0;\n jsInvokeStack.length = 0;\n taskReflowEvents.length = 0;\n}\n\nfunction storeWarning(event: Types.TraceEvents.TraceEventData, warning: Warning): void {\n const existingWarnings = Platform.MapUtilities.getWithDefault(warningsPerEvent, event, () => []);\n existingWarnings.push(warning);\n warningsPerEvent.set(event, existingWarnings);\n\n const existingEvents = Platform.MapUtilities.getWithDefault(eventsPerWarning, warning, () => []);\n existingEvents.push(event);\n eventsPerWarning.set(warning, existingEvents);\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n processForcedReflowWarning(event);\n if (event.name === Types.TraceEvents.KnownEventName.RUN_TASK) {\n const {duration} = Helpers.Timing.eventTimingsMicroSeconds(event);\n if (duration > LONG_MAIN_THREAD_TASK_THRESHOLD) {\n storeWarning(event, 'LONG_TASK');\n }\n return;\n }\n\n if (Types.TraceEvents.isTraceEventFireIdleCallback(event)) {\n const {duration} = Helpers.Timing.eventTimingsMilliSeconds(event);\n if (duration > event.args.data.allottedMilliseconds) {\n storeWarning(event, 'IDLE_CALLBACK_OVER_TIME');\n }\n return;\n }\n}\n\n/**\n * Reflows* are added a warning to if:\n * 1. They are forced/sync, meaning they are invoked by JS and finish\n * during the Script execution.\n * 2. Their duration exceeds a threshold.\n * - *Reflow: The style recalculation and layout steps in a render task.\n */\nfunction processForcedReflowWarning(event: Types.TraceEvents.TraceEventData): void {\n // Update the event and the JS invocation stacks.\n accomodateEventInStack(event, allEventsStack);\n accomodateEventInStack(event, jsInvokeStack, /* pushEventToStack */ Types.TraceEvents.isJSInvocationEvent(event));\n if (jsInvokeStack.length) {\n // Current event falls inside a JS call.\n if (event.name === Types.TraceEvents.KnownEventName.LAYOUT ||\n event.name === Types.TraceEvents.KnownEventName.UPDATE_LAYOUT_TREE) {\n // A forced reflow happened. However we need to check if\n // the threshold is surpassed to add a warning. Accumulate the\n // event to check for this after the current Task is over.\n taskReflowEvents.push(event);\n return;\n }\n }\n if (allEventsStack.length === 1) {\n // We hit a new task. Check if the forced reflows in the previous\n // task exceeded the threshold and add a warning if so.\n const totalTime = taskReflowEvents.reduce((time, event) => time + (event.dur || 0), 0);\n if (totalTime >= FORCED_REFLOW_THRESHOLD) {\n taskReflowEvents.forEach(reflowEvent => storeWarning(reflowEvent, 'FORCED_REFLOW'));\n }\n taskReflowEvents.length = 0;\n }\n}\n\n/**\n * Updates a given trace event stack given a new event.\n */\nfunction accomodateEventInStack(\n event: Types.TraceEvents.TraceEventData, stack: Types.TraceEvents.TraceEventData[], pushEventToStack = true): void {\n let nextItem = stack.at(-1);\n while (nextItem && event.ts > nextItem.ts + (nextItem.dur || 0)) {\n stack.pop();\n nextItem = stack.at(-1);\n }\n if (!pushEventToStack) {\n return;\n }\n stack.push(event);\n}\n\nexport function deps(): TraceEventHandlerName[] {\n return ['UserInteractions'];\n}\n\nexport async function finalize(): Promise {\n // These events do exist on the UserInteractionsHandler, but we also put\n // them into the WarningsHandler so that the warnings handler can be the\n // source of truth and the way to look up all warnings for a given event.\n // Otherwise, we would have to look up warnings across multiple handlers for\n // a given event, which will start to get messy very quickly.\n const longInteractions = userInteractionsHandlerData().interactionsOverThreshold;\n for (const interaction of longInteractions) {\n storeWarning(interaction, 'LONG_INTERACTION');\n }\n}\n\nexport function data(): WarningsData {\n return {\n perEvent: warningsPerEvent,\n perWarning: eventsPerWarning,\n };\n}\n"]} \ No newline at end of file +{"version":3,"file":"WarningsHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/WarningsHandler.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {type HandlerName} from './types.js';\nimport {data as userInteractionsHandlerData} from './UserInteractionsHandler.js';\n\nexport interface WarningsData {\n // Tracks warnings keyed by the event.\n perEvent: Map;\n // The same data in reverse: for each type of warning, track the events.\n // Useful if we need to enumerate events by type of issue\n perWarning: Map;\n}\n\nexport type Warning = 'LONG_TASK'|'IDLE_CALLBACK_OVER_TIME'|'FORCED_REFLOW'|'LONG_INTERACTION';\n\nconst warningsPerEvent: WarningsData['perEvent'] = new Map();\nconst eventsPerWarning: WarningsData['perWarning'] = new Map();\n\n/**\n * Tracks the stack formed by nested trace events up to a given point\n */\nconst allEventsStack: Types.Events.Event[] = [];\n/**\n * Tracks the stack formed by JS invocation trace events up to a given point.\n * F.e. FunctionCall, EvaluateScript, V8Execute.\n * Not to be confused with ProfileCalls.\n */\nconst jsInvokeStack: Types.Events.Event[] = [];\n/**\n * Tracks reflow events in a task.\n */\nconst taskReflowEvents: Types.Events.Event[] = [];\n\nexport const FORCED_REFLOW_THRESHOLD = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(30));\n\nexport const LONG_MAIN_THREAD_TASK_THRESHOLD = Helpers.Timing.millisecondsToMicroseconds(Types.Timing.MilliSeconds(50));\n\nexport function reset(): void {\n warningsPerEvent.clear();\n eventsPerWarning.clear();\n allEventsStack.length = 0;\n jsInvokeStack.length = 0;\n taskReflowEvents.length = 0;\n}\n\nfunction storeWarning(event: Types.Events.Event, warning: Warning): void {\n const existingWarnings = Platform.MapUtilities.getWithDefault(warningsPerEvent, event, () => []);\n existingWarnings.push(warning);\n warningsPerEvent.set(event, existingWarnings);\n\n const existingEvents = Platform.MapUtilities.getWithDefault(eventsPerWarning, warning, () => []);\n existingEvents.push(event);\n eventsPerWarning.set(warning, existingEvents);\n}\n\nexport function handleEvent(event: Types.Events.Event): void {\n processForcedReflowWarning(event);\n if (event.name === Types.Events.Name.RUN_TASK) {\n const {duration} = Helpers.Timing.eventTimingsMicroSeconds(event);\n if (duration > LONG_MAIN_THREAD_TASK_THRESHOLD) {\n storeWarning(event, 'LONG_TASK');\n }\n return;\n }\n\n if (Types.Events.isFireIdleCallback(event)) {\n const {duration} = Helpers.Timing.eventTimingsMilliSeconds(event);\n if (duration > event.args.data.allottedMilliseconds) {\n storeWarning(event, 'IDLE_CALLBACK_OVER_TIME');\n }\n return;\n }\n}\n\n/**\n * Reflows* are added a warning to if:\n * 1. They are forced/sync, meaning they are invoked by JS and finish\n * during the Script execution.\n * 2. Their duration exceeds a threshold.\n * - *Reflow: The style recalculation and layout steps in a render task.\n */\nfunction processForcedReflowWarning(event: Types.Events.Event): void {\n // Update the event and the JS invocation stacks.\n accomodateEventInStack(event, allEventsStack);\n accomodateEventInStack(event, jsInvokeStack, /* pushEventToStack */ Types.Events.isJSInvocationEvent(event));\n if (jsInvokeStack.length) {\n // Current event falls inside a JS call.\n if (event.name === Types.Events.Name.LAYOUT || event.name === Types.Events.Name.UPDATE_LAYOUT_TREE) {\n // A forced reflow happened. However we need to check if\n // the threshold is surpassed to add a warning. Accumulate the\n // event to check for this after the current Task is over.\n taskReflowEvents.push(event);\n return;\n }\n }\n if (allEventsStack.length === 1) {\n // We hit a new task. Check if the forced reflows in the previous\n // task exceeded the threshold and add a warning if so.\n const totalTime = taskReflowEvents.reduce((time, event) => time + (event.dur || 0), 0);\n if (totalTime >= FORCED_REFLOW_THRESHOLD) {\n taskReflowEvents.forEach(reflowEvent => storeWarning(reflowEvent, 'FORCED_REFLOW'));\n }\n taskReflowEvents.length = 0;\n }\n}\n\n/**\n * Updates a given trace event stack given a new event.\n */\nfunction accomodateEventInStack(event: Types.Events.Event, stack: Types.Events.Event[], pushEventToStack = true): void {\n let nextItem = stack.at(-1);\n while (nextItem && event.ts > nextItem.ts + (nextItem.dur || 0)) {\n stack.pop();\n nextItem = stack.at(-1);\n }\n if (!pushEventToStack) {\n return;\n }\n stack.push(event);\n}\n\nexport function deps(): HandlerName[] {\n return ['UserInteractions'];\n}\n\nexport async function finalize(): Promise {\n // These events do exist on the UserInteractionsHandler, but we also put\n // them into the WarningsHandler so that the warnings handler can be the\n // source of truth and the way to look up all warnings for a given event.\n // Otherwise, we would have to look up warnings across multiple handlers for\n // a given event, which will start to get messy very quickly.\n const longInteractions = userInteractionsHandlerData().interactionsOverThreshold;\n for (const interaction of longInteractions) {\n storeWarning(interaction, 'LONG_INTERACTION');\n }\n}\n\nexport function data(): WarningsData {\n return {\n perEvent: warningsPerEvent,\n perWarning: eventsPerWarning,\n };\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/WarningsHandler.test.js b/public/models/trace/handlers/WarningsHandler.test.js index 5d3f8c1b9..3284c9eb5 100644 --- a/public/models/trace/handlers/WarningsHandler.test.js +++ b/public/models/trace/handlers/WarningsHandler.test.js @@ -3,28 +3,28 @@ // found in the LICENSE file. import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; -import * as TraceEngine from '../trace.js'; +import * as Trace from '../trace.js'; describeWithEnvironment('WarningsHandler', function () { beforeEach(() => { - TraceEngine.Handlers.ModelHandlers.Warnings.reset(); + Trace.Handlers.ModelHandlers.Warnings.reset(); }); it('identifies long tasks', async function () { const events = await TraceLoader.rawEvents(this, 'slow-interaction-keydown.json.gz'); for (const event of events) { - TraceEngine.Handlers.ModelHandlers.Warnings.handleEvent(event); + Trace.Handlers.ModelHandlers.Warnings.handleEvent(event); } - const data = TraceEngine.Handlers.ModelHandlers.Warnings.data(); + const data = Trace.Handlers.ModelHandlers.Warnings.data(); // We expect one long task. assert.strictEqual(data.perEvent.size, 1); const event = Array.from(data.perEvent.keys()).at(0); - assert.strictEqual(event?.name, "RunTask" /* TraceEngine.Types.TraceEvents.KnownEventName.RUN_TASK */); + assert.strictEqual(event?.name, "RunTask" /* Trace.Types.Events.Name.RUN_TASK */); }); it('identifies idle callbacks that ran over the allotted time', async function () { const events = await TraceLoader.rawEvents(this, 'idle-callback.json.gz'); for (const event of events) { - TraceEngine.Handlers.ModelHandlers.Warnings.handleEvent(event); + Trace.Handlers.ModelHandlers.Warnings.handleEvent(event); } - const data = TraceEngine.Handlers.ModelHandlers.Warnings.data(); + const data = Trace.Handlers.ModelHandlers.Warnings.data(); const longIdleCallbacks = data.perWarning.get('IDLE_CALLBACK_OVER_TIME') || []; assert.lengthOf(longIdleCallbacks, 1); const event = longIdleCallbacks[0]; @@ -33,36 +33,36 @@ describeWithEnvironment('WarningsHandler', function () { it('identifies reflows that take over 30ms', async function () { const events = await TraceLoader.rawEvents(this, 'large-layout-small-recalc.json.gz'); for (const event of events) { - TraceEngine.Handlers.ModelHandlers.Warnings.handleEvent(event); + Trace.Handlers.ModelHandlers.Warnings.handleEvent(event); } - const data = TraceEngine.Handlers.ModelHandlers.Warnings.data(); + const data = Trace.Handlers.ModelHandlers.Warnings.data(); const forcedReflow = data.perWarning.get('FORCED_REFLOW') || []; assert.lengthOf(forcedReflow, 2); const stylesRecalc = forcedReflow[0]; const layout = forcedReflow[1]; assert.deepEqual(data.perEvent.get(stylesRecalc), ['FORCED_REFLOW']); assert.deepEqual(data.perEvent.get(layout), ['FORCED_REFLOW']); - assert.strictEqual(stylesRecalc.name, "UpdateLayoutTree" /* TraceEngine.Types.TraceEvents.KnownEventName.UPDATE_LAYOUT_TREE */); - assert.strictEqual(layout.name, "Layout" /* TraceEngine.Types.TraceEvents.KnownEventName.LAYOUT */); + assert.strictEqual(stylesRecalc.name, "UpdateLayoutTree" /* Trace.Types.Events.Name.UPDATE_LAYOUT_TREE */); + assert.strictEqual(layout.name, "Layout" /* Trace.Types.Events.Name.LAYOUT */); }); it('ignores reflows that are not forced by JS', async function () { const events = await TraceLoader.rawEvents(this, 'large-recalc-style.json.gz'); for (const event of events) { - TraceEngine.Handlers.ModelHandlers.Warnings.handleEvent(event); + Trace.Handlers.ModelHandlers.Warnings.handleEvent(event); } - const data = TraceEngine.Handlers.ModelHandlers.Warnings.data(); + const data = Trace.Handlers.ModelHandlers.Warnings.data(); const forcedStyle = data.perWarning.get('FORCED_REFLOW') || []; assert.lengthOf(forcedStyle, 0); }); it('identifies long interactions', async function () { // We run the entire model here as the WarningsHandler actually depends on the UserInteractionsHandler to fetch this data - const { traceData } = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz'); // These events do exist on the UserInteractionsHandler, but we also put // them into the WarningsHandler so that the warnings handler can be the // source of truth and the way to look up all warnings for a given event. - const { interactionsOverThreshold } = traceData.UserInteractions; + const { interactionsOverThreshold } = parsedTrace.UserInteractions; for (const interaction of interactionsOverThreshold) { - const warnings = traceData.Warnings.perEvent.get(interaction); + const warnings = parsedTrace.Warnings.perEvent.get(interaction); assert.deepEqual(warnings, ['LONG_INTERACTION']); } }); diff --git a/public/models/trace/handlers/WarningsHandler.test.js.map b/public/models/trace/handlers/WarningsHandler.test.js.map index 2e40caaa7..0da5231ce 100644 --- a/public/models/trace/handlers/WarningsHandler.test.js.map +++ b/public/models/trace/handlers/WarningsHandler.test.js.map @@ -1 +1 @@ -{"version":3,"file":"WarningsHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/WarningsHandler.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as TraceEngine from '../trace.js';\n\ndescribeWithEnvironment('WarningsHandler', function() {\n beforeEach(() => {\n TraceEngine.Handlers.ModelHandlers.Warnings.reset();\n });\n\n it('identifies long tasks', async function() {\n const events = await TraceLoader.rawEvents(this, 'slow-interaction-keydown.json.gz');\n for (const event of events) {\n TraceEngine.Handlers.ModelHandlers.Warnings.handleEvent(event);\n }\n const data = TraceEngine.Handlers.ModelHandlers.Warnings.data();\n // We expect one long task.\n assert.strictEqual(data.perEvent.size, 1);\n const event = Array.from(data.perEvent.keys()).at(0);\n assert.strictEqual(event?.name, TraceEngine.Types.TraceEvents.KnownEventName.RUN_TASK);\n });\n\n it('identifies idle callbacks that ran over the allotted time', async function() {\n const events = await TraceLoader.rawEvents(this, 'idle-callback.json.gz');\n for (const event of events) {\n TraceEngine.Handlers.ModelHandlers.Warnings.handleEvent(event);\n }\n const data = TraceEngine.Handlers.ModelHandlers.Warnings.data();\n const longIdleCallbacks = data.perWarning.get('IDLE_CALLBACK_OVER_TIME') || [];\n assert.lengthOf(longIdleCallbacks, 1);\n const event = longIdleCallbacks[0];\n assert.deepEqual(data.perEvent.get(event), ['IDLE_CALLBACK_OVER_TIME']);\n });\n\n it('identifies reflows that take over 30ms', async function() {\n const events = await TraceLoader.rawEvents(this, 'large-layout-small-recalc.json.gz');\n for (const event of events) {\n TraceEngine.Handlers.ModelHandlers.Warnings.handleEvent(event);\n }\n const data = TraceEngine.Handlers.ModelHandlers.Warnings.data();\n const forcedReflow = data.perWarning.get('FORCED_REFLOW') || [];\n assert.lengthOf(forcedReflow, 2);\n const stylesRecalc = forcedReflow[0];\n const layout = forcedReflow[1];\n assert.deepEqual(data.perEvent.get(stylesRecalc), ['FORCED_REFLOW']);\n assert.deepEqual(data.perEvent.get(layout), ['FORCED_REFLOW']);\n assert.strictEqual(stylesRecalc.name, TraceEngine.Types.TraceEvents.KnownEventName.UPDATE_LAYOUT_TREE);\n assert.strictEqual(layout.name, TraceEngine.Types.TraceEvents.KnownEventName.LAYOUT);\n });\n\n it('ignores reflows that are not forced by JS', async function() {\n const events = await TraceLoader.rawEvents(this, 'large-recalc-style.json.gz');\n for (const event of events) {\n TraceEngine.Handlers.ModelHandlers.Warnings.handleEvent(event);\n }\n const data = TraceEngine.Handlers.ModelHandlers.Warnings.data();\n const forcedStyle = data.perWarning.get('FORCED_REFLOW') || [];\n assert.lengthOf(forcedStyle, 0);\n });\n\n it('identifies long interactions', async function() {\n // We run the entire model here as the WarningsHandler actually depends on the UserInteractionsHandler to fetch this data\n const {traceData} = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz');\n\n // These events do exist on the UserInteractionsHandler, but we also put\n // them into the WarningsHandler so that the warnings handler can be the\n // source of truth and the way to look up all warnings for a given event.\n const {interactionsOverThreshold} = traceData.UserInteractions;\n\n for (const interaction of interactionsOverThreshold) {\n const warnings = traceData.Warnings.perEvent.get(interaction);\n assert.deepEqual(warnings, ['LONG_INTERACTION']);\n }\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"WarningsHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/WarningsHandler.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Trace from '../trace.js';\n\ndescribeWithEnvironment('WarningsHandler', function() {\n beforeEach(() => {\n Trace.Handlers.ModelHandlers.Warnings.reset();\n });\n\n it('identifies long tasks', async function() {\n const events = await TraceLoader.rawEvents(this, 'slow-interaction-keydown.json.gz');\n for (const event of events) {\n Trace.Handlers.ModelHandlers.Warnings.handleEvent(event);\n }\n const data = Trace.Handlers.ModelHandlers.Warnings.data();\n // We expect one long task.\n assert.strictEqual(data.perEvent.size, 1);\n const event = Array.from(data.perEvent.keys()).at(0);\n assert.strictEqual(event?.name, Trace.Types.Events.Name.RUN_TASK);\n });\n\n it('identifies idle callbacks that ran over the allotted time', async function() {\n const events = await TraceLoader.rawEvents(this, 'idle-callback.json.gz');\n for (const event of events) {\n Trace.Handlers.ModelHandlers.Warnings.handleEvent(event);\n }\n const data = Trace.Handlers.ModelHandlers.Warnings.data();\n const longIdleCallbacks = data.perWarning.get('IDLE_CALLBACK_OVER_TIME') || [];\n assert.lengthOf(longIdleCallbacks, 1);\n const event = longIdleCallbacks[0];\n assert.deepEqual(data.perEvent.get(event), ['IDLE_CALLBACK_OVER_TIME']);\n });\n\n it('identifies reflows that take over 30ms', async function() {\n const events = await TraceLoader.rawEvents(this, 'large-layout-small-recalc.json.gz');\n for (const event of events) {\n Trace.Handlers.ModelHandlers.Warnings.handleEvent(event);\n }\n const data = Trace.Handlers.ModelHandlers.Warnings.data();\n const forcedReflow = data.perWarning.get('FORCED_REFLOW') || [];\n assert.lengthOf(forcedReflow, 2);\n const stylesRecalc = forcedReflow[0];\n const layout = forcedReflow[1];\n assert.deepEqual(data.perEvent.get(stylesRecalc), ['FORCED_REFLOW']);\n assert.deepEqual(data.perEvent.get(layout), ['FORCED_REFLOW']);\n assert.strictEqual(stylesRecalc.name, Trace.Types.Events.Name.UPDATE_LAYOUT_TREE);\n assert.strictEqual(layout.name, Trace.Types.Events.Name.LAYOUT);\n });\n\n it('ignores reflows that are not forced by JS', async function() {\n const events = await TraceLoader.rawEvents(this, 'large-recalc-style.json.gz');\n for (const event of events) {\n Trace.Handlers.ModelHandlers.Warnings.handleEvent(event);\n }\n const data = Trace.Handlers.ModelHandlers.Warnings.data();\n const forcedStyle = data.perWarning.get('FORCED_REFLOW') || [];\n assert.lengthOf(forcedStyle, 0);\n });\n\n it('identifies long interactions', async function() {\n // We run the entire model here as the WarningsHandler actually depends on the UserInteractionsHandler to fetch this data\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz');\n\n // These events do exist on the UserInteractionsHandler, but we also put\n // them into the WarningsHandler so that the warnings handler can be the\n // source of truth and the way to look up all warnings for a given event.\n const {interactionsOverThreshold} = parsedTrace.UserInteractions;\n\n for (const interaction of interactionsOverThreshold) {\n const warnings = parsedTrace.Warnings.perEvent.get(interaction);\n assert.deepEqual(warnings, ['LONG_INTERACTION']);\n }\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/WorkersHandler.d.ts b/public/models/trace/handlers/WorkersHandler.d.ts index 88c601bcc..89f032d73 100644 --- a/public/models/trace/handlers/WorkersHandler.d.ts +++ b/public/models/trace/handlers/WorkersHandler.d.ts @@ -1,11 +1,11 @@ import * as Types from '../types/types.js'; export interface WorkersData { - workerSessionIdEvents: readonly Types.TraceEvents.TraceEventTracingSessionIdForWorker[]; - workerIdByThread: Map; - workerURLById: Map; + workerSessionIdEvents: readonly Types.Events.TracingSessionIdForWorker[]; + workerIdByThread: Map; + workerURLById: Map; } export declare function initialize(): void; export declare function reset(): void; -export declare function handleEvent(event: Types.TraceEvents.TraceEventData): void; +export declare function handleEvent(event: Types.Events.Event): void; export declare function finalize(): Promise; export declare function data(): WorkersData; diff --git a/public/models/trace/handlers/WorkersHandler.js b/public/models/trace/handlers/WorkersHandler.js index ab5156b9d..3332fa011 100644 --- a/public/models/trace/handlers/WorkersHandler.js +++ b/public/models/trace/handlers/WorkersHandler.js @@ -22,7 +22,7 @@ export function handleEvent(event) { if (handlerState !== 2 /* HandlerState.INITIALIZED */) { throw new Error('Workers Handler is not initialized'); } - if (Types.TraceEvents.isTraceEventTracingSessionIdForWorker(event)) { + if (Types.Events.isTracingSessionIdForWorker(event)) { sessionIdEvents.push(event); } } diff --git a/public/models/trace/handlers/WorkersHandler.js.map b/public/models/trace/handlers/WorkersHandler.js.map index 4f7f30039..9081b2220 100644 --- a/public/models/trace/handlers/WorkersHandler.js.map +++ b/public/models/trace/handlers/WorkersHandler.js.map @@ -1 +1 @@ -{"version":3,"file":"WorkersHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/WorkersHandler.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAS3C,IAAI,YAAY,qCAA6B,CAAC;AAE9C,MAAM,eAAe,GAA4D,EAAE,CAAC;AACpF,MAAM,gBAAgB,GAAgE,IAAI,GAAG,EAAE,CAAC;AAChG,MAAM,aAAa,GAA4C,IAAI,GAAG,EAAE,CAAC;AAEzE,MAAM,UAAU,UAAU;IACxB,IAAI,YAAY,uCAA+B,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IAED,YAAY,mCAA2B,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,KAAK;IACnB,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC;IAC3B,gBAAgB,CAAC,KAAK,EAAE,CAAC;IACzB,aAAa,CAAC,KAAK,EAAE,CAAC;IACtB,YAAY,qCAA6B,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAuC;IACjE,IAAI,YAAY,qCAA6B,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IACD,IAAI,KAAK,CAAC,WAAW,CAAC,qCAAqC,CAAC,KAAK,CAAC,EAAE,CAAC;QACnE,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,IAAI,YAAY,qCAA6B,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAChD,CAAC;IACD,KAAK,MAAM,cAAc,IAAI,eAAe,EAAE,CAAC;QAC7C,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAC9B,SAAS;QACX,CAAC;QACD,gBAAgB,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACjG,aAAa,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrF,CAAC;IACD,YAAY,iCAAyB,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,IAAI;IAClB,IAAI,YAAY,mCAA2B,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACtD,CAAC;IAED,OAAO;QACL,qBAAqB,EAAE,eAAe;QACtC,gBAAgB;QAChB,aAAa;KACd,CAAC;AACJ,CAAC","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Types from '../types/types.js';\n\nimport {HandlerState} from './types.js';\n\nexport interface WorkersData {\n workerSessionIdEvents: readonly Types.TraceEvents.TraceEventTracingSessionIdForWorker[];\n workerIdByThread: Map;\n workerURLById: Map;\n}\nlet handlerState = HandlerState.UNINITIALIZED;\n\nconst sessionIdEvents: Types.TraceEvents.TraceEventTracingSessionIdForWorker[] = [];\nconst workerIdByThread: Map = new Map();\nconst workerURLById: Map = new Map();\n\nexport function initialize(): void {\n if (handlerState !== HandlerState.UNINITIALIZED) {\n throw new Error('Workers Handler was not reset');\n }\n\n handlerState = HandlerState.INITIALIZED;\n}\n\nexport function reset(): void {\n sessionIdEvents.length = 0;\n workerIdByThread.clear();\n workerURLById.clear();\n handlerState = HandlerState.UNINITIALIZED;\n}\n\nexport function handleEvent(event: Types.TraceEvents.TraceEventData): void {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Workers Handler is not initialized');\n }\n if (Types.TraceEvents.isTraceEventTracingSessionIdForWorker(event)) {\n sessionIdEvents.push(event);\n }\n}\n\nexport async function finalize(): Promise {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Handler is not initialized');\n }\n for (const sessionIdEvent of sessionIdEvents) {\n if (!sessionIdEvent.args.data) {\n continue;\n }\n workerIdByThread.set(sessionIdEvent.args.data.workerThreadId, sessionIdEvent.args.data.workerId);\n workerURLById.set(sessionIdEvent.args.data.workerId, sessionIdEvent.args.data.url);\n }\n handlerState = HandlerState.FINALIZED;\n}\n\nexport function data(): WorkersData {\n if (handlerState !== HandlerState.FINALIZED) {\n throw new Error('Workers Handler is not finalized');\n }\n\n return {\n workerSessionIdEvents: sessionIdEvents,\n workerIdByThread,\n workerURLById,\n };\n}\n"]} \ No newline at end of file +{"version":3,"file":"WorkersHandler.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/WorkersHandler.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAS3C,IAAI,YAAY,qCAA6B,CAAC;AAE9C,MAAM,eAAe,GAA6C,EAAE,CAAC;AACrE,MAAM,gBAAgB,GAAsD,IAAI,GAAG,EAAE,CAAC;AACtF,MAAM,aAAa,GAAuC,IAAI,GAAG,EAAE,CAAC;AAEpE,MAAM,UAAU,UAAU;IACxB,IAAI,YAAY,uCAA+B,EAAE,CAAC;QAChD,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IAED,YAAY,mCAA2B,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,KAAK;IACnB,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC;IAC3B,gBAAgB,CAAC,KAAK,EAAE,CAAC;IACzB,aAAa,CAAC,KAAK,EAAE,CAAC;IACtB,YAAY,qCAA6B,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAyB;IACnD,IAAI,YAAY,qCAA6B,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,CAAC,2BAA2B,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,IAAI,YAAY,qCAA6B,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAChD,CAAC;IACD,KAAK,MAAM,cAAc,IAAI,eAAe,EAAE,CAAC;QAC7C,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YAC9B,SAAS;QACX,CAAC;QACD,gBAAgB,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACjG,aAAa,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACrF,CAAC;IACD,YAAY,iCAAyB,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,IAAI;IAClB,IAAI,YAAY,mCAA2B,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;IACtD,CAAC;IAED,OAAO;QACL,qBAAqB,EAAE,eAAe;QACtC,gBAAgB;QAChB,aAAa;KACd,CAAC;AACJ,CAAC","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Types from '../types/types.js';\n\nimport {HandlerState} from './types.js';\n\nexport interface WorkersData {\n workerSessionIdEvents: readonly Types.Events.TracingSessionIdForWorker[];\n workerIdByThread: Map;\n workerURLById: Map;\n}\nlet handlerState = HandlerState.UNINITIALIZED;\n\nconst sessionIdEvents: Types.Events.TracingSessionIdForWorker[] = [];\nconst workerIdByThread: Map = new Map();\nconst workerURLById: Map = new Map();\n\nexport function initialize(): void {\n if (handlerState !== HandlerState.UNINITIALIZED) {\n throw new Error('Workers Handler was not reset');\n }\n\n handlerState = HandlerState.INITIALIZED;\n}\n\nexport function reset(): void {\n sessionIdEvents.length = 0;\n workerIdByThread.clear();\n workerURLById.clear();\n handlerState = HandlerState.UNINITIALIZED;\n}\n\nexport function handleEvent(event: Types.Events.Event): void {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Workers Handler is not initialized');\n }\n if (Types.Events.isTracingSessionIdForWorker(event)) {\n sessionIdEvents.push(event);\n }\n}\n\nexport async function finalize(): Promise {\n if (handlerState !== HandlerState.INITIALIZED) {\n throw new Error('Handler is not initialized');\n }\n for (const sessionIdEvent of sessionIdEvents) {\n if (!sessionIdEvent.args.data) {\n continue;\n }\n workerIdByThread.set(sessionIdEvent.args.data.workerThreadId, sessionIdEvent.args.data.workerId);\n workerURLById.set(sessionIdEvent.args.data.workerId, sessionIdEvent.args.data.url);\n }\n handlerState = HandlerState.FINALIZED;\n}\n\nexport function data(): WorkersData {\n if (handlerState !== HandlerState.FINALIZED) {\n throw new Error('Workers Handler is not finalized');\n }\n\n return {\n workerSessionIdEvents: sessionIdEvents,\n workerIdByThread,\n workerURLById,\n };\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/WorkersHandler.test.js b/public/models/trace/handlers/WorkersHandler.test.js index 9842f89f6..5468f8750 100644 --- a/public/models/trace/handlers/WorkersHandler.test.js +++ b/public/models/trace/handlers/WorkersHandler.test.js @@ -2,63 +2,63 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import { TraceLoader } from '../../../testing/TraceLoader.js'; -import * as TraceEngine from '../trace.js'; +import * as Trace from '../trace.js'; describe('WorkersHandler', () => { beforeEach(async function () { - TraceEngine.Handlers.ModelHandlers.Workers.reset(); + Trace.Handlers.ModelHandlers.Workers.reset(); const events = await TraceLoader.rawEvents(this, 'two-workers.json.gz'); - TraceEngine.Handlers.ModelHandlers.Workers.initialize(); + Trace.Handlers.ModelHandlers.Workers.initialize(); for (const event of events) { - TraceEngine.Handlers.ModelHandlers.Workers.handleEvent(event); + Trace.Handlers.ModelHandlers.Workers.handleEvent(event); } - await TraceEngine.Handlers.ModelHandlers.Workers.finalize(); + await Trace.Handlers.ModelHandlers.Workers.finalize(); }); afterEach(() => { - TraceEngine.Handlers.ModelHandlers.Workers.reset(); + Trace.Handlers.ModelHandlers.Workers.reset(); }); it('collects the worker session ID metadata events', async function () { - const data = TraceEngine.Handlers.ModelHandlers.Workers.data(); + const data = Trace.Handlers.ModelHandlers.Workers.data(); assert.deepEqual(data.workerSessionIdEvents, [ { name: 'TracingSessionIdForWorker', cat: 'disabled-by-default-devtools.timeline', - ph: "I" /* TraceEngine.Types.TraceEvents.Phase.INSTANT */, - tid: TraceEngine.Types.TraceEvents.ThreadID(37651), - pid: TraceEngine.Types.TraceEvents.ProcessID(71044), - s: "t" /* TraceEngine.Types.TraceEvents.TraceEventScope.THREAD */, - ts: TraceEngine.Types.Timing.MicroSeconds(107351291649), - tts: TraceEngine.Types.Timing.MicroSeconds(934), + ph: "I" /* Trace.Types.Events.Phase.INSTANT */, + tid: Trace.Types.Events.ThreadID(37651), + pid: Trace.Types.Events.ProcessID(71044), + s: "t" /* Trace.Types.Events.Scope.THREAD */, + ts: Trace.Types.Timing.MicroSeconds(107351291649), + tts: Trace.Types.Timing.MicroSeconds(934), args: { data: { frame: '372333E30ECABDA706136ED37FD9FA2B', url: 'https://chromedevtools.github.io/performance-stories/two-workers/fib-worker.js', - workerId: TraceEngine.Types.TraceEvents.WorkerId('990A76F8BED5B771144F505FF9313D06'), - workerThreadId: TraceEngine.Types.TraceEvents.ThreadID(37651), + workerId: Trace.Types.Events.WorkerId('990A76F8BED5B771144F505FF9313D06'), + workerThreadId: Trace.Types.Events.ThreadID(37651), }, }, }, { name: 'TracingSessionIdForWorker', cat: 'disabled-by-default-devtools.timeline', - ph: "I" /* TraceEngine.Types.TraceEvents.Phase.INSTANT */, - tid: TraceEngine.Types.TraceEvents.ThreadID(35351), - pid: TraceEngine.Types.TraceEvents.ProcessID(71044), - s: "t" /* TraceEngine.Types.TraceEvents.TraceEventScope.THREAD */, - ts: TraceEngine.Types.Timing.MicroSeconds(107351292507), - tts: TraceEngine.Types.Timing.MicroSeconds(817), + ph: "I" /* Trace.Types.Events.Phase.INSTANT */, + tid: Trace.Types.Events.ThreadID(35351), + pid: Trace.Types.Events.ProcessID(71044), + s: "t" /* Trace.Types.Events.Scope.THREAD */, + ts: Trace.Types.Timing.MicroSeconds(107351292507), + tts: Trace.Types.Timing.MicroSeconds(817), args: { data: { frame: '372333E30ECABDA706136ED37FD9FA2B', url: 'https://chromedevtools.github.io/performance-stories/two-workers/fib-worker.js', - workerId: TraceEngine.Types.TraceEvents.WorkerId('E59E70C44C7664657CE822BB7DC54085'), - workerThreadId: TraceEngine.Types.TraceEvents.ThreadID(35351), + workerId: Trace.Types.Events.WorkerId('E59E70C44C7664657CE822BB7DC54085'), + workerThreadId: Trace.Types.Events.ThreadID(35351), }, }, }, ]); }); it('collects thread id for workers', async function () { - const data = TraceEngine.Handlers.ModelHandlers.Workers.data(); + const data = Trace.Handlers.ModelHandlers.Workers.data(); const [[thread1, worker1], [thread2, worker2]] = data.workerIdByThread.entries(); assert.strictEqual(thread1, 37651); assert.strictEqual(worker1, '990A76F8BED5B771144F505FF9313D06'); @@ -66,7 +66,7 @@ describe('WorkersHandler', () => { assert.strictEqual(worker2, 'E59E70C44C7664657CE822BB7DC54085'); }); it('collects the url of workers', async function () { - const data = TraceEngine.Handlers.ModelHandlers.Workers.data(); + const data = Trace.Handlers.ModelHandlers.Workers.data(); const [[thread1, worker1], [thread2, worker2]] = data.workerURLById.entries(); assert.strictEqual(thread1, '990A76F8BED5B771144F505FF9313D06'); assert.strictEqual(worker1, 'https://chromedevtools.github.io/performance-stories/two-workers/fib-worker.js'); diff --git a/public/models/trace/handlers/WorkersHandler.test.js.map b/public/models/trace/handlers/WorkersHandler.test.js.map index 32ef7b889..ca9f83e22 100644 --- a/public/models/trace/handlers/WorkersHandler.test.js.map +++ b/public/models/trace/handlers/WorkersHandler.test.js.map @@ -1 +1 @@ -{"version":3,"file":"WorkersHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/WorkersHandler.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as TraceEngine from '../trace.js';\n\ndescribe('WorkersHandler', () => {\n beforeEach(async function() {\n TraceEngine.Handlers.ModelHandlers.Workers.reset();\n const events = await TraceLoader.rawEvents(this, 'two-workers.json.gz');\n TraceEngine.Handlers.ModelHandlers.Workers.initialize();\n for (const event of events) {\n TraceEngine.Handlers.ModelHandlers.Workers.handleEvent(event);\n }\n await TraceEngine.Handlers.ModelHandlers.Workers.finalize();\n });\n afterEach(() => {\n TraceEngine.Handlers.ModelHandlers.Workers.reset();\n });\n\n it('collects the worker session ID metadata events', async function() {\n const data = TraceEngine.Handlers.ModelHandlers.Workers.data();\n assert.deepEqual(data.workerSessionIdEvents, [\n {\n name: 'TracingSessionIdForWorker',\n cat: 'disabled-by-default-devtools.timeline',\n ph: TraceEngine.Types.TraceEvents.Phase.INSTANT,\n tid: TraceEngine.Types.TraceEvents.ThreadID(37651),\n pid: TraceEngine.Types.TraceEvents.ProcessID(71044),\n s: TraceEngine.Types.TraceEvents.TraceEventScope.THREAD,\n ts: TraceEngine.Types.Timing.MicroSeconds(107351291649),\n tts: TraceEngine.Types.Timing.MicroSeconds(934),\n args: {\n data: {\n frame: '372333E30ECABDA706136ED37FD9FA2B',\n url: 'https://chromedevtools.github.io/performance-stories/two-workers/fib-worker.js',\n workerId: TraceEngine.Types.TraceEvents.WorkerId('990A76F8BED5B771144F505FF9313D06'),\n workerThreadId: TraceEngine.Types.TraceEvents.ThreadID(37651),\n },\n },\n },\n {\n name: 'TracingSessionIdForWorker',\n cat: 'disabled-by-default-devtools.timeline',\n ph: TraceEngine.Types.TraceEvents.Phase.INSTANT,\n tid: TraceEngine.Types.TraceEvents.ThreadID(35351),\n pid: TraceEngine.Types.TraceEvents.ProcessID(71044),\n s: TraceEngine.Types.TraceEvents.TraceEventScope.THREAD,\n ts: TraceEngine.Types.Timing.MicroSeconds(107351292507),\n tts: TraceEngine.Types.Timing.MicroSeconds(817),\n args: {\n data: {\n frame: '372333E30ECABDA706136ED37FD9FA2B',\n url: 'https://chromedevtools.github.io/performance-stories/two-workers/fib-worker.js',\n workerId: TraceEngine.Types.TraceEvents.WorkerId('E59E70C44C7664657CE822BB7DC54085'),\n workerThreadId: TraceEngine.Types.TraceEvents.ThreadID(35351),\n },\n },\n },\n ]);\n });\n\n it('collects thread id for workers', async function() {\n const data = TraceEngine.Handlers.ModelHandlers.Workers.data();\n const [[thread1, worker1], [thread2, worker2]] = data.workerIdByThread.entries();\n assert.strictEqual(thread1, 37651);\n assert.strictEqual(worker1, '990A76F8BED5B771144F505FF9313D06');\n assert.strictEqual(thread2, 35351);\n assert.strictEqual(worker2, 'E59E70C44C7664657CE822BB7DC54085');\n });\n\n it('collects the url of workers', async function() {\n const data = TraceEngine.Handlers.ModelHandlers.Workers.data();\n const [[thread1, worker1], [thread2, worker2]] = data.workerURLById.entries();\n assert.strictEqual(thread1, '990A76F8BED5B771144F505FF9313D06');\n assert.strictEqual(worker1, 'https://chromedevtools.github.io/performance-stories/two-workers/fib-worker.js');\n assert.strictEqual(thread2, 'E59E70C44C7664657CE822BB7DC54085');\n assert.strictEqual(worker2, 'https://chromedevtools.github.io/performance-stories/two-workers/fib-worker.js');\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"WorkersHandler.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/WorkersHandler.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,EAAC,WAAW,EAAC,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,KAAK,MAAM,aAAa,CAAC;AAErC,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,UAAU,CAAC,KAAK;QACd,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAC7C,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC;QACxE,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QAClD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1D,CAAC;QACD,MAAM,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;IACxD,CAAC,CAAC,CAAC;IACH,SAAS,CAAC,GAAG,EAAE;QACb,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK;QACxD,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QACzD,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,qBAAqB,EAAE;YAC3C;gBACE,IAAI,EAAE,2BAA2B;gBACjC,GAAG,EAAE,uCAAuC;gBAC5C,EAAE,4CAAkC;gBACpC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACvC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;gBACxC,CAAC,2CAAiC;gBAClC,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC;gBACjD,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC;gBACzC,IAAI,EAAE;oBACJ,IAAI,EAAE;wBACJ,KAAK,EAAE,kCAAkC;wBACzC,GAAG,EAAE,gFAAgF;wBACrF,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,kCAAkC,CAAC;wBACzE,cAAc,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;qBACnD;iBACF;aACF;YACD;gBACE,IAAI,EAAE,2BAA2B;gBACjC,GAAG,EAAE,uCAAuC;gBAC5C,EAAE,4CAAkC;gBACpC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;gBACvC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC;gBACxC,CAAC,2CAAiC;gBAClC,EAAE,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC;gBACjD,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC;gBACzC,IAAI,EAAE;oBACJ,IAAI,EAAE;wBACJ,KAAK,EAAE,kCAAkC;wBACzC,GAAG,EAAE,gFAAgF;wBACrF,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,kCAAkC,CAAC;wBACzE,cAAc,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;qBACnD;iBACF;aACF;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gCAAgC,EAAE,KAAK;QACxC,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QACzD,MAAM,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC;QACjF,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACnC,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,kCAAkC,CAAC,CAAC;QAChE,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACnC,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,kCAAkC,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6BAA6B,EAAE,KAAK;QACrC,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QACzD,MAAM,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC;QAC9E,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,kCAAkC,CAAC,CAAC;QAChE,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,gFAAgF,CAAC,CAAC;QAC9G,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,kCAAkC,CAAC,CAAC;QAChE,MAAM,CAAC,WAAW,CAAC,OAAO,EAAE,gFAAgF,CAAC,CAAC;IAChH,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Trace from '../trace.js';\n\ndescribe('WorkersHandler', () => {\n beforeEach(async function() {\n Trace.Handlers.ModelHandlers.Workers.reset();\n const events = await TraceLoader.rawEvents(this, 'two-workers.json.gz');\n Trace.Handlers.ModelHandlers.Workers.initialize();\n for (const event of events) {\n Trace.Handlers.ModelHandlers.Workers.handleEvent(event);\n }\n await Trace.Handlers.ModelHandlers.Workers.finalize();\n });\n afterEach(() => {\n Trace.Handlers.ModelHandlers.Workers.reset();\n });\n\n it('collects the worker session ID metadata events', async function() {\n const data = Trace.Handlers.ModelHandlers.Workers.data();\n assert.deepEqual(data.workerSessionIdEvents, [\n {\n name: 'TracingSessionIdForWorker',\n cat: 'disabled-by-default-devtools.timeline',\n ph: Trace.Types.Events.Phase.INSTANT,\n tid: Trace.Types.Events.ThreadID(37651),\n pid: Trace.Types.Events.ProcessID(71044),\n s: Trace.Types.Events.Scope.THREAD,\n ts: Trace.Types.Timing.MicroSeconds(107351291649),\n tts: Trace.Types.Timing.MicroSeconds(934),\n args: {\n data: {\n frame: '372333E30ECABDA706136ED37FD9FA2B',\n url: 'https://chromedevtools.github.io/performance-stories/two-workers/fib-worker.js',\n workerId: Trace.Types.Events.WorkerId('990A76F8BED5B771144F505FF9313D06'),\n workerThreadId: Trace.Types.Events.ThreadID(37651),\n },\n },\n },\n {\n name: 'TracingSessionIdForWorker',\n cat: 'disabled-by-default-devtools.timeline',\n ph: Trace.Types.Events.Phase.INSTANT,\n tid: Trace.Types.Events.ThreadID(35351),\n pid: Trace.Types.Events.ProcessID(71044),\n s: Trace.Types.Events.Scope.THREAD,\n ts: Trace.Types.Timing.MicroSeconds(107351292507),\n tts: Trace.Types.Timing.MicroSeconds(817),\n args: {\n data: {\n frame: '372333E30ECABDA706136ED37FD9FA2B',\n url: 'https://chromedevtools.github.io/performance-stories/two-workers/fib-worker.js',\n workerId: Trace.Types.Events.WorkerId('E59E70C44C7664657CE822BB7DC54085'),\n workerThreadId: Trace.Types.Events.ThreadID(35351),\n },\n },\n },\n ]);\n });\n\n it('collects thread id for workers', async function() {\n const data = Trace.Handlers.ModelHandlers.Workers.data();\n const [[thread1, worker1], [thread2, worker2]] = data.workerIdByThread.entries();\n assert.strictEqual(thread1, 37651);\n assert.strictEqual(worker1, '990A76F8BED5B771144F505FF9313D06');\n assert.strictEqual(thread2, 35351);\n assert.strictEqual(worker2, 'E59E70C44C7664657CE822BB7DC54085');\n });\n\n it('collects the url of workers', async function() {\n const data = Trace.Handlers.ModelHandlers.Workers.data();\n const [[thread1, worker1], [thread2, worker2]] = data.workerURLById.entries();\n assert.strictEqual(thread1, '990A76F8BED5B771144F505FF9313D06');\n assert.strictEqual(worker1, 'https://chromedevtools.github.io/performance-stories/two-workers/fib-worker.js');\n assert.strictEqual(thread2, 'E59E70C44C7664657CE822BB7DC54085');\n assert.strictEqual(worker2, 'https://chromedevtools.github.io/performance-stories/two-workers/fib-worker.js');\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/handlers-tsconfig.json b/public/models/trace/handlers/handlers-tsconfig.json index bf7912b66..3195eef0e 100644 --- a/public/models/trace/handlers/handlers-tsconfig.json +++ b/public/models/trace/handlers/handlers-tsconfig.json @@ -31,7 +31,6 @@ "files": [ "../../../../../../../front_end/models/trace/handlers/AnimationHandler.ts", "../../../../../../../front_end/models/trace/handlers/AuctionWorkletsHandler.ts", - "../../../../../../../front_end/models/trace/handlers/EnhancedTracesHandler.ts", "../../../../../../../front_end/models/trace/handlers/ExtensionTraceDataHandler.ts", "../../../../../../../front_end/models/trace/handlers/FramesHandler.ts", "../../../../../../../front_end/models/trace/handlers/GPUHandler.ts", diff --git a/public/models/trace/handlers/types.d.ts b/public/models/trace/handlers/types.d.ts index edf4c9bc9..57c3916c8 100644 --- a/public/models/trace/handlers/types.d.ts +++ b/public/models/trace/handlers/types.d.ts @@ -1,34 +1,34 @@ import type * as Types from './../types/types.js'; import type * as ModelHandlers from './ModelHandlers.js'; -export interface TraceEventHandler { +export interface Handler { reset(): void; initialize?(freshRecording?: boolean): void; handleEvent(data: {}): void; finalize?(): Promise; data(): unknown; - deps?(): TraceEventHandlerName[]; + deps?(): HandlerName[]; handleUserConfig?(config: Types.Configuration.Configuration): void; } -export type TraceEventHandlerName = keyof typeof ModelHandlers; +export type HandlerName = keyof typeof ModelHandlers; export type EnabledHandlerDataWithMeta = { Meta: Readonly>; } & { [K in keyof T]: Readonly>; }; export type HandlersWithMeta = { Meta: typeof ModelHandlers.Meta; } & { [K in keyof T]: T[K]; }; -export type TraceParseData = Readonly>; +export type ParsedTrace = Readonly>; type DeepWriteable = { -readonly [P in keyof T]: DeepWriteable; }; -export type TraceParseDataMutable = DeepWriteable; +export type ParsedTraceMutable = DeepWriteable; export type Handlers = typeof ModelHandlers; export declare const enum HandlerState { UNINITIALIZED = 1, diff --git a/public/models/trace/handlers/types.js.map b/public/models/trace/handlers/types.js.map index a402a73fd..8a3e35940 100644 --- a/public/models/trace/handlers/types.js.map +++ b/public/models/trace/handlers/types.js.map @@ -1 +1 @@ -{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/types.ts"],"names":[],"mappings":"","sourcesContent":["\n// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport type * as Types from './../types/types.js';\nimport type * as ModelHandlers from './ModelHandlers.js';\n\nexport interface TraceEventHandler {\n reset(): void;\n initialize?(freshRecording?: boolean): void;\n handleEvent(data: {}): void;\n finalize?(): Promise;\n data(): unknown;\n deps?(): TraceEventHandlerName[];\n handleUserConfig?(config: Types.Configuration.Configuration): void;\n}\nexport type TraceEventHandlerName = keyof typeof ModelHandlers;\n\n// This type maps TraceEventHandler names to the return type of their data\n// function. So, for example, if we are given an object with a key of 'foo'\n// and a value which is a TraceHandler containing a data() function that\n// returns a string, this type will be { foo: string }.\n//\n// This allows us to model the behavior of the TraceProcessor in the model,\n// which takes an object with TraceEventHandlers as part of its config, and\n// which ultimately returns an object keyed off the names of the\n// TraceEventHandlers, and with values that are derived from each\n// TraceEventHandler's data function.\n//\n// So, concretely, we provide a TraceEventHandler for calculating the #time\n// bounds of a trace called TraceBounds, whose data() function returns a\n// TraceWindow. The HandlerData, therefore, would determine that the\n// TraceProcessor would contain a key called 'TraceBounds' whose value is\n// a TraceWindow.\nexport type EnabledHandlerDataWithMeta = {\n // We allow the user to configure which handlers are created by passing them\n // in when constructing a model instance. However, we then ensure that the\n // Meta handler is added to that, as the Model relies on some of the data\n // from the Meta handler when creating the file. Therefore, this type\n // explicitly defines that the Meta data is present, before then extending it\n // with the index type to represent all the other handlers.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n Meta: Readonly>,\n}&{\n // For every key in the object, look up the TraceEventHandler's data function\n // and use its return type as the value for the object.\n [K in keyof T]: Readonly>;\n};\n\nexport type HandlersWithMeta = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n Meta: typeof ModelHandlers.Meta,\n}&{\n [K in keyof T]: T[K];\n};\n\n// Represents the final parsed data from all of the handlers. If you instantiate a\n// TraceProcessor with a subset of handlers, you should instead use\n// `EnabledHandlerDataWithMeta<>`.\nexport type TraceParseData = Readonly>;\n\ntype DeepWriteable = {\n -readonly[P in keyof T]: DeepWriteable\n};\nexport type TraceParseDataMutable = DeepWriteable;\n\nexport type Handlers = typeof ModelHandlers;\n\nexport const enum HandlerState {\n UNINITIALIZED = 1,\n INITIALIZED = 2,\n FINALIZED = 3,\n}\n"]} \ No newline at end of file +{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/handlers/types.ts"],"names":[],"mappings":"","sourcesContent":["\n// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport type * as Types from './../types/types.js';\nimport type * as ModelHandlers from './ModelHandlers.js';\n\nexport interface Handler {\n reset(): void;\n initialize?(freshRecording?: boolean): void;\n handleEvent(data: {}): void;\n finalize?(): Promise;\n data(): unknown;\n deps?(): HandlerName[];\n handleUserConfig?(config: Types.Configuration.Configuration): void;\n}\nexport type HandlerName = keyof typeof ModelHandlers;\n\n// This type maps Handler names to the return type of their data\n// function. So, for example, if we are given an object with a key of 'foo'\n// and a value which is a TraceHandler containing a data() function that\n// returns a string, this type will be { foo: string }.\n//\n// This allows us to model the behavior of the TraceProcessor in the model,\n// which takes an object with Handlers as part of its config, and\n// which ultimately returns an object keyed off the names of the\n// Handlers, and with values that are derived from each\n// Handler's data function.\n//\n// So, concretely, we provide a Handler for calculating the #time\n// bounds of a trace called TraceBounds, whose data() function returns a\n// TraceWindow. The HandlerData, therefore, would determine that the\n// TraceProcessor would contain a key called 'TraceBounds' whose value is\n// a TraceWindow.\nexport type EnabledHandlerDataWithMeta = {\n // We allow the user to configure which handlers are created by passing them\n // in when constructing a model instance. However, we then ensure that the\n // Meta handler is added to that, as the Model relies on some of the data\n // from the Meta handler when creating the file. Therefore, this type\n // explicitly defines that the Meta data is present, before then extending it\n // with the index type to represent all the other handlers.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n Meta: Readonly>,\n}&{\n // For every key in the object, look up the Handler's data function\n // and use its return type as the value for the object.\n [K in keyof T]: Readonly>;\n};\n\nexport type HandlersWithMeta = {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n Meta: typeof ModelHandlers.Meta,\n}&{\n [K in keyof T]: T[K];\n};\n\n// Represents the final parsed data from all of the handlers. If you instantiate a\n// TraceProcessor with a subset of handlers, you should instead use\n// `EnabledHandlerDataWithMeta<>`.\nexport type ParsedTrace = Readonly>;\n\ntype DeepWriteable = {\n -readonly[P in keyof T]: DeepWriteable\n};\nexport type ParsedTraceMutable = DeepWriteable;\n\nexport type Handlers = typeof ModelHandlers;\n\nexport const enum HandlerState {\n UNINITIALIZED = 1,\n INITIALIZED = 2,\n FINALIZED = 3,\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/handlers/unittests-tsconfig.json b/public/models/trace/handlers/unittests-tsconfig.json index 756c5b2c4..28960e4d1 100644 --- a/public/models/trace/handlers/unittests-tsconfig.json +++ b/public/models/trace/handlers/unittests-tsconfig.json @@ -40,7 +40,6 @@ "files": [ "../../../../../../../front_end/models/trace/handlers/AnimationHandler.test.ts", "../../../../../../../front_end/models/trace/handlers/AuctionWorkletsHandler.test.ts", - "../../../../../../../front_end/models/trace/handlers/EnhancedTracesHandler.test.ts", "../../../../../../../front_end/models/trace/handlers/ExtensionTraceDataHandler.test.ts", "../../../../../../../front_end/models/trace/handlers/FramesHandler.test.ts", "../../../../../../../front_end/models/trace/handlers/GPUHandler.test.ts", diff --git a/public/models/trace/helpers/Extensions.d.ts b/public/models/trace/helpers/Extensions.d.ts index e44384d2c..5ac949747 100644 --- a/public/models/trace/helpers/Extensions.d.ts +++ b/public/models/trace/helpers/Extensions.d.ts @@ -1,6 +1,6 @@ import type * as Types from '../types/types.js'; import { type TraceEntryNode } from './TreeHelpers.js'; -export declare function buildTrackDataFromExtensionEntries(extensionEntries: Types.Extensions.SyntheticExtensionTrackEntry[], extensionTrackData: Types.Extensions.ExtensionTrackData[], entryToNode: Map): { +export declare function buildTrackDataFromExtensionEntries(extensionEntries: Types.Extensions.SyntheticExtensionTrackEntry[], extensionTrackData: Types.Extensions.ExtensionTrackData[], entryToNode: Map): { extensionTrackData: Types.Extensions.ExtensionTrackData[]; - entryToNode?: Map; + entryToNode?: Map; }; diff --git a/public/models/trace/helpers/Extensions.js.map b/public/models/trace/helpers/Extensions.js.map index 3b2e4657a..e87a4d2ac 100644 --- a/public/models/trace/helpers/Extensions.js.map +++ b/public/models/trace/helpers/Extensions.js.map @@ -1 +1 @@ -{"version":3,"file":"Extensions.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/Extensions.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,QAAQ,MAAM,oCAAoC,CAAC;AAG/D,OAAO,EAAC,sBAAsB,EAAC,MAAM,YAAY,CAAC;AAClD,OAAO,EAAC,uBAAuB,EAAuB,MAAM,EAAC,MAAM,kBAAkB,CAAC;AAEtF,MAAM,UAAU,kCAAkC,CAC9C,gBAAiE,EACjE,kBAAyD,EACzD,WAAkE;IAKpE,MAAM,WAAW,GAAG,IAAI,GAAG,EAA+C,CAAC;IAC3E,KAAK,MAAM,KAAK,IAAI,gBAAgB,EAAE,CAAC;QACrC,mEAAmE;QACnE,iEAAiE;QACjE,kEAAkE;QAClE,8DAA8D;QAC9D,mCAAmC;QACnC,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,cAAc,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QACtE,MAAM,WAAW,GACb,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,WAAW,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;YACL,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK;YAC/C,YAAY,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC;YAC5C,cAAc,EAAE,EAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAC;SACzC,CAAC,CAAC,CAAC;QAE/D,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAClD,WAAW,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QACpD,CAAC;QACD,MAAM,cAAc,GAAG,WAAW,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpE,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IACD,gEAAgE;IAChE,kBAAkB;IAClB,KAAK,MAAM,SAAS,IAAI,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC;QAC7C,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,CAAC;YAC9D,sBAAsB,CAAC,OAAO,CAAC,CAAC;YAChC,IAAI,uBAAuB,CAAC,OAAO,CAAC,EAAE,CAAC;gBACrC,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;oBACxD,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;gBAC/B,CAAC;YACH,CAAC;QACH,CAAC;QACD,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,EAAC,kBAAkB,EAAE,WAAW,EAAC,CAAC;AAC3C,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport type * as Types from '../types/types.js';\n\nimport {sortTraceEventsInPlace} from './Trace.js';\nimport {canBuildTreesFromEvents, type TraceEntryNode, treify} from './TreeHelpers.js';\n\nexport function buildTrackDataFromExtensionEntries(\n extensionEntries: Types.Extensions.SyntheticExtensionTrackEntry[],\n extensionTrackData: Types.Extensions.ExtensionTrackData[],\n entryToNode: Map,\n ): {\n extensionTrackData: Types.Extensions.ExtensionTrackData[],\n entryToNode?: Map,\n} {\n const dataByTrack = new Map();\n for (const entry of extensionEntries) {\n // Batch data by track group. For each batch, add the data of every\n // track in the group. In cases where no track group is provided,\n // we use the standalone track data, but use a fixed prefix in the\n // batch key to prevent collisions where a track group has the\n // same name as a standalone track.\n const key = entry.args.trackGroup || `track-name-${entry.args.track}`;\n const batchedData =\n Platform.MapUtilities.getWithDefault(dataByTrack, key, () => ({\n name: entry.args.trackGroup || entry.args.track,\n isTrackGroup: Boolean(entry.args.trackGroup),\n entriesByTrack: {[entry.args.track]: []},\n }));\n\n if (!batchedData.entriesByTrack[entry.args.track]) {\n batchedData.entriesByTrack[entry.args.track] = [];\n }\n const entriesInTrack = batchedData.entriesByTrack[entry.args.track];\n entriesInTrack.push(entry);\n }\n // Calculate self time if possible for track entries, on a track\n // by track basis.\n for (const trackData of dataByTrack.values()) {\n for (const entries of Object.values(trackData.entriesByTrack)) {\n sortTraceEventsInPlace(entries);\n if (canBuildTreesFromEvents(entries)) {\n for (const [entry, node] of treify(entries).entryToNode) {\n entryToNode.set(entry, node);\n }\n }\n }\n extensionTrackData.push(trackData);\n }\n return {extensionTrackData, entryToNode};\n}\n"]} \ No newline at end of file +{"version":3,"file":"Extensions.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/Extensions.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,QAAQ,MAAM,oCAAoC,CAAC;AAG/D,OAAO,EAAC,sBAAsB,EAAC,MAAM,YAAY,CAAC;AAClD,OAAO,EAAC,uBAAuB,EAAuB,MAAM,EAAC,MAAM,kBAAkB,CAAC;AAEtF,MAAM,UAAU,kCAAkC,CAC9C,gBAAiE,EACjE,kBAAyD,EACzD,WAAoD;IAKtD,MAAM,WAAW,GAAG,IAAI,GAAG,EAA+C,CAAC;IAC3E,KAAK,MAAM,KAAK,IAAI,gBAAgB,EAAE,CAAC;QACrC,mEAAmE;QACnE,iEAAiE;QACjE,kEAAkE;QAClE,8DAA8D;QAC9D,mCAAmC;QACnC,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,cAAc,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QACtE,MAAM,WAAW,GACb,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,WAAW,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;YACL,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK;YAC/C,YAAY,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC;YAC5C,cAAc,EAAE,EAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,EAAC;SACzC,CAAC,CAAC,CAAC;QAE/D,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAClD,WAAW,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;QACpD,CAAC;QACD,MAAM,cAAc,GAAG,WAAW,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpE,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC7B,CAAC;IACD,gEAAgE;IAChE,kBAAkB;IAClB,KAAK,MAAM,SAAS,IAAI,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC;QAC7C,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,CAAC;YAC9D,sBAAsB,CAAC,OAAO,CAAC,CAAC;YAChC,IAAI,uBAAuB,CAAC,OAAO,CAAC,EAAE,CAAC;gBACrC,KAAK,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;oBACxD,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;gBAC/B,CAAC;YACH,CAAC;QACH,CAAC;QACD,kBAAkB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,EAAC,kBAAkB,EAAE,WAAW,EAAC,CAAC;AAC3C,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport type * as Types from '../types/types.js';\n\nimport {sortTraceEventsInPlace} from './Trace.js';\nimport {canBuildTreesFromEvents, type TraceEntryNode, treify} from './TreeHelpers.js';\n\nexport function buildTrackDataFromExtensionEntries(\n extensionEntries: Types.Extensions.SyntheticExtensionTrackEntry[],\n extensionTrackData: Types.Extensions.ExtensionTrackData[],\n entryToNode: Map,\n ): {\n extensionTrackData: Types.Extensions.ExtensionTrackData[],\n entryToNode?: Map,\n} {\n const dataByTrack = new Map();\n for (const entry of extensionEntries) {\n // Batch data by track group. For each batch, add the data of every\n // track in the group. In cases where no track group is provided,\n // we use the standalone track data, but use a fixed prefix in the\n // batch key to prevent collisions where a track group has the\n // same name as a standalone track.\n const key = entry.args.trackGroup || `track-name-${entry.args.track}`;\n const batchedData =\n Platform.MapUtilities.getWithDefault(dataByTrack, key, () => ({\n name: entry.args.trackGroup || entry.args.track,\n isTrackGroup: Boolean(entry.args.trackGroup),\n entriesByTrack: {[entry.args.track]: []},\n }));\n\n if (!batchedData.entriesByTrack[entry.args.track]) {\n batchedData.entriesByTrack[entry.args.track] = [];\n }\n const entriesInTrack = batchedData.entriesByTrack[entry.args.track];\n entriesInTrack.push(entry);\n }\n // Calculate self time if possible for track entries, on a track\n // by track basis.\n for (const trackData of dataByTrack.values()) {\n for (const entries of Object.values(trackData.entriesByTrack)) {\n sortTraceEventsInPlace(entries);\n if (canBuildTreesFromEvents(entries)) {\n for (const [entry, node] of treify(entries).entryToNode) {\n entryToNode.set(entry, node);\n }\n }\n }\n extensionTrackData.push(trackData);\n }\n return {extensionTrackData, entryToNode};\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/helpers/Network.d.ts b/public/models/trace/helpers/Network.d.ts index fdaa0fd3d..ae80a63cc 100644 --- a/public/models/trace/helpers/Network.d.ts +++ b/public/models/trace/helpers/Network.d.ts @@ -1,2 +1,2 @@ import { type SyntheticNetworkRequest } from '../types/TraceEvents.js'; -export declare function isSyntheticNetworkRequestEventRenderBlocking(traceEventData: SyntheticNetworkRequest): boolean; +export declare function isSyntheticNetworkRequestEventRenderBlocking(event: SyntheticNetworkRequest): boolean; diff --git a/public/models/trace/helpers/Network.js b/public/models/trace/helpers/Network.js index 597e64788..2ab35789f 100644 --- a/public/models/trace/helpers/Network.js +++ b/public/models/trace/helpers/Network.js @@ -1,7 +1,7 @@ // Copyright 2024 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. -export function isSyntheticNetworkRequestEventRenderBlocking(traceEventData) { - return traceEventData.args.data.renderBlocking !== 'non_blocking'; +export function isSyntheticNetworkRequestEventRenderBlocking(event) { + return event.args.data.renderBlocking !== 'non_blocking'; } //# sourceMappingURL=Network.js.map \ No newline at end of file diff --git a/public/models/trace/helpers/Network.js.map b/public/models/trace/helpers/Network.js.map index 458aa14e1..30b0df8dc 100644 --- a/public/models/trace/helpers/Network.js.map +++ b/public/models/trace/helpers/Network.js.map @@ -1 +1 @@ -{"version":3,"file":"Network.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/Network.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAI7B,MAAM,UAAU,4CAA4C,CAAC,cAAuC;IAClG,OAAO,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,KAAK,cAAc,CAAC;AACpE,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {type SyntheticNetworkRequest} from '../types/TraceEvents.js';\n\nexport function isSyntheticNetworkRequestEventRenderBlocking(traceEventData: SyntheticNetworkRequest): boolean {\n return traceEventData.args.data.renderBlocking !== 'non_blocking';\n}\n"]} \ No newline at end of file +{"version":3,"file":"Network.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/Network.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAI7B,MAAM,UAAU,4CAA4C,CAAC,KAA8B;IACzF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,KAAK,cAAc,CAAC;AAC3D,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {type SyntheticNetworkRequest} from '../types/TraceEvents.js';\n\nexport function isSyntheticNetworkRequestEventRenderBlocking(event: SyntheticNetworkRequest): boolean {\n return event.args.data.renderBlocking !== 'non_blocking';\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/helpers/SamplesIntegrator.d.ts b/public/models/trace/helpers/SamplesIntegrator.d.ts index 3bdf8bf31..3f58579c7 100644 --- a/public/models/trace/helpers/SamplesIntegrator.d.ts +++ b/public/models/trace/helpers/SamplesIntegrator.d.ts @@ -36,19 +36,19 @@ export declare class SamplesIntegrator { * Keeps track of the individual samples from the CPU Profile. * Only used with Debug Mode experiment enabled. */ - jsSampleEvents: Types.TraceEvents.SyntheticJSSample[]; - constructor(profileModel: CPUProfile.CPUProfileDataModel.CPUProfileDataModel, profileId: Types.TraceEvents.ProfileID, pid: Types.TraceEvents.ProcessID, tid: Types.TraceEvents.ThreadID, configuration?: Types.Configuration.Configuration); - buildProfileCalls(traceEvents: Types.TraceEvents.TraceEventData[]): Types.TraceEvents.SyntheticProfileCall[]; + jsSampleEvents: Types.Events.SyntheticJSSample[]; + constructor(profileModel: CPUProfile.CPUProfileDataModel.CPUProfileDataModel, profileId: Types.Events.ProfileID, pid: Types.Events.ProcessID, tid: Types.Events.ThreadID, configuration?: Types.Configuration.Configuration); + buildProfileCalls(traceEvents: Types.Events.Event[]): Types.Events.SyntheticProfileCall[]; /** * Builds the initial calls with no duration from samples. Their * purpose is to be merged with the trace event array being parsed so * that they can be traversed in order with them and their duration * can be updated as the SampleIntegrator callbacks are invoked. */ - callsFromProfileSamples(): Types.TraceEvents.SyntheticProfileCall[]; + callsFromProfileSamples(): Types.Events.SyntheticProfileCall[]; static framesAreEqual(frame1: Protocol.Runtime.CallFrame, frame2: Protocol.Runtime.CallFrame): boolean; static showNativeName(name: string, runtimeCallStatsEnabled: boolean): boolean; static nativeGroup(nativeName: string): 'Parse' | 'Compile' | null; static isNativeRuntimeFrame(frame: Protocol.Runtime.CallFrame): boolean; - static filterStackFrames(stack: Types.TraceEvents.SyntheticProfileCall[], engineConfig: Types.Configuration.Configuration): void; + static filterStackFrames(stack: Types.Events.SyntheticProfileCall[], engineConfig: Types.Configuration.Configuration): void; } diff --git a/public/models/trace/helpers/SamplesIntegrator.js b/public/models/trace/helpers/SamplesIntegrator.js index 86d38e363..822848a6d 100644 --- a/public/models/trace/helpers/SamplesIntegrator.js +++ b/public/models/trace/helpers/SamplesIntegrator.js @@ -109,11 +109,11 @@ export class SamplesIntegrator { // Because instant trace events have no duration, they don't provide // useful information for possible changes in the duration of calls // in the JS stack. - if (event.ph === "I" /* Types.TraceEvents.Phase.INSTANT */) { + if (event.ph === "I" /* Types.Events.Phase.INSTANT */) { continue; } if (stack.length === 0) { - if (Types.TraceEvents.isProfileCall(event)) { + if (Types.Events.isProfileCall(event)) { this.#onProfileCall(event); continue; } @@ -136,7 +136,7 @@ export class SamplesIntegrator { i--; continue; } - if (Types.TraceEvents.isProfileCall(event)) { + if (Types.Events.isProfileCall(event)) { this.#onProfileCall(event, parentEvent); continue; } @@ -154,8 +154,7 @@ export class SamplesIntegrator { #onTraceEventStart(event) { // Top level events cannot be nested into JS frames so we reset // the stack when we find one. - if (event.name === "RunMicrotasks" /* Types.TraceEvents.KnownEventName.RUN_MICROTASKS */ || - event.name === "RunTask" /* Types.TraceEvents.KnownEventName.RUN_TASK */) { + if (event.name === "RunMicrotasks" /* Types.Events.Name.RUN_MICROTASKS */ || event.name === "RunTask" /* Types.Events.Name.RUN_TASK */) { this.#lockedJsStackDepth = []; this.#truncateJSStack(0, event.ts); this.#fakeJSInvocation = false; @@ -185,10 +184,10 @@ export class SamplesIntegrator { this.#lockedJsStackDepth.push(this.#currentJSStack.length); } #onProfileCall(event, parent) { - if ((parent && Types.TraceEvents.isJSInvocationEvent(parent)) || this.#fakeJSInvocation) { + if ((parent && Types.Events.isJSInvocationEvent(parent)) || this.#fakeJSInvocation) { this.#extractStackTrace(event); } - else if (Types.TraceEvents.isProfileCall(event) && this.#currentJSStack.length === 0) { + else if (Types.Events.isProfileCall(event) && this.#currentJSStack.length === 0) { // Force JS Samples to show up even if we are not inside a JS // invocation event, because we can be missing the start of JS // invocation events if we start tracing half-way through. Pretend @@ -275,7 +274,7 @@ export class SamplesIntegrator { * Update tracked stack using this event's call stack. */ #extractStackTrace(event) { - const stackTrace = Types.TraceEvents.isProfileCall(event) ? this.#makeProfileCallsForStack(event) : this.#currentJSStack; + const stackTrace = Types.Events.isProfileCall(event) ? this.#makeProfileCallsForStack(event) : this.#currentJSStack; SamplesIntegrator.filterStackFrames(stackTrace, this.#engineConfig); const endTime = event.ts + (event.dur || 0); const minFrames = Math.min(stackTrace.length, this.#currentJSStack.length); @@ -366,12 +365,12 @@ export class SamplesIntegrator { } #makeJSSampleEvent(call, timestamp) { const JSSampleEvent = { - name: "JSSample" /* Types.TraceEvents.KnownEventName.JS_SAMPLE */, + name: "JSSample" /* Types.Events.Name.JS_SAMPLE */, cat: 'devtools.timeline', args: { data: { stackTrace: this.#makeProfileCallsForStack(call).map(e => e.callFrame) }, }, - ph: "I" /* Types.TraceEvents.Phase.INSTANT */, + ph: "I" /* Types.Events.Phase.INSTANT */, ts: timestamp, dur: Types.Timing.MicroSeconds(0), pid: this.#processId, diff --git a/public/models/trace/helpers/SamplesIntegrator.js.map b/public/models/trace/helpers/SamplesIntegrator.js.map index f3f6e7904..6f22b83fd 100644 --- a/public/models/trace/helpers/SamplesIntegrator.js.map +++ b/public/models/trace/helpers/SamplesIntegrator.js.map @@ -1 +1 @@ -{"version":3,"file":"SamplesIntegrator.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/SamplesIntegrator.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Protocol from '../../../generated/protocol.js';\nimport type * as CPUProfile from '../../cpu_profile/cpu_profile.js';\nimport * as Types from '../types/types.js';\n\nimport {millisecondsToMicroseconds} from './Timing.js';\nimport {makeProfileCall, mergeEventsInOrder} from './Trace.js';\n\n/**\n * This is a helper that integrates CPU profiling data coming in the\n * shape of samples, with trace events. Samples indicate what the JS\n * stack trace looked at a given point in time, but they don't have\n * duration. The SamplesIntegrator task is to make an approximation\n * of what the duration of each JS call was, given the sample data and\n * given the trace events profiled during that time. At the end of its\n * execution, the SamplesIntegrator returns an array of ProfileCalls\n * (under SamplesIntegrator::buildProfileCalls()), which\n * represent JS calls, with a call frame and duration. These calls have\n * the shape of a complete trace events and can be treated as flame\n * chart entries in the timeline.\n *\n * The approach to build the profile calls consists in tracking the\n * current stack as the following events happen (in order):\n * 1. A sample was done.\n * 2. A trace event started.\n * 3. A trace event ended.\n * Depending on the event and on the data that's coming with it the\n * stack is updated by adding or removing JS calls to it and updating\n * the duration of the calls in the tracking stack.\n *\n * note: Although this approach has been implemented since long ago, and\n * is relatively efficent (adds a complexity over the trace parsing of\n * O(n) where n is the number of samples) it has proven to be faulty.\n * It might be worthwhile experimenting with improvements or with a\n * completely different approach. Improving the approach is tracked in\n * crbug.com/1417439\n */\nexport class SamplesIntegrator {\n /**\n * The result of runing the samples integrator. Holds the JS calls\n * with their approximated duration after integrating samples into the\n * trace event tree.\n */\n #constructedProfileCalls: Types.TraceEvents.SyntheticProfileCall[] = [];\n /**\n * tracks the state of the JS stack at each point in time to update\n * the profile call durations as new events arrive. This doesn't only\n * happen with new profile calls (in which case we would compare the\n * stack in them) but also with trace events (in which case we would\n * update the duration of the events we are tracking at the moment).\n */\n #currentJSStack: Types.TraceEvents.SyntheticProfileCall[] = [];\n /**\n * Process holding the CPU profile and trace events.\n */\n #processId: Types.TraceEvents.ProcessID;\n /**\n * Thread holding the CPU profile and trace events.\n */\n #threadId: Types.TraceEvents.ThreadID;\n /**\n * Tracks the depth of the JS stack at the moment a trace event starts\n * or ends. It is assumed that for the duration of a trace event, the\n * JS stack's depth cannot decrease, since JS calls that started\n * before a trace event cannot end during the trace event. So as trace\n * events arrive, we store the \"locked\" amount of JS frames that were\n * in the stack before the event came.\n */\n #lockedJsStackDepth: number[] = [];\n /**\n * Used to keep track when samples should be integrated even if they\n * are not children of invocation trace events. This is useful in\n * cases where we can be missing the start of JS invocation events if\n * we start tracing half-way through.\n */\n #fakeJSInvocation = false;\n /**\n * The parsed CPU profile, holding the tree hierarchy of JS frames and\n * the sample data.\n */\n #profileModel: CPUProfile.CPUProfileDataModel.CPUProfileDataModel;\n /**\n * Because GC nodes don't have a stack, we artificially add a stack to\n * them which corresponds to that of the previous sample. This map\n * tracks which node is used for the stack of a GC call.\n * Note that GC samples are not shown in the flamechart, however they\n * are used during the construction of for profile calls, as we can\n * infer information about the duration of the executed code when a\n * GC node is sampled.\n */\n #nodeForGC = new Map();\n\n #engineConfig: Types.Configuration.Configuration;\n #profileId: Types.TraceEvents.ProfileID;\n\n /**\n * Keeps track of the individual samples from the CPU Profile.\n * Only used with Debug Mode experiment enabled.\n */\n jsSampleEvents: Types.TraceEvents.SyntheticJSSample[] = [];\n\n constructor(\n profileModel: CPUProfile.CPUProfileDataModel.CPUProfileDataModel, profileId: Types.TraceEvents.ProfileID,\n pid: Types.TraceEvents.ProcessID, tid: Types.TraceEvents.ThreadID,\n configuration?: Types.Configuration.Configuration) {\n this.#profileModel = profileModel;\n this.#threadId = tid;\n this.#processId = pid;\n this.#engineConfig = configuration || Types.Configuration.defaults();\n this.#profileId = profileId;\n }\n\n buildProfileCalls(traceEvents: Types.TraceEvents.TraceEventData[]): Types.TraceEvents.SyntheticProfileCall[] {\n const mergedEvents = mergeEventsInOrder(traceEvents, this.callsFromProfileSamples());\n const stack = [];\n for (let i = 0; i < mergedEvents.length; i++) {\n const event = mergedEvents[i];\n // Because instant trace events have no duration, they don't provide\n // useful information for possible changes in the duration of calls\n // in the JS stack.\n if (event.ph === Types.TraceEvents.Phase.INSTANT) {\n continue;\n }\n if (stack.length === 0) {\n if (Types.TraceEvents.isProfileCall(event)) {\n this.#onProfileCall(event);\n continue;\n }\n stack.push(event);\n this.#onTraceEventStart(event);\n continue;\n }\n\n const parentEvent = stack.at(-1);\n if (parentEvent === undefined) {\n continue;\n }\n const begin = event.ts;\n const parentBegin = parentEvent.ts;\n const parentDuration = parentEvent.dur || 0;\n const parentEnd = parentBegin + parentDuration;\n\n const startsAfterParent = begin >= parentEnd;\n if (startsAfterParent) {\n this.#onTraceEventEnd(parentEvent);\n stack.pop();\n i--;\n continue;\n }\n if (Types.TraceEvents.isProfileCall(event)) {\n this.#onProfileCall(event, parentEvent);\n continue;\n }\n this.#onTraceEventStart(event);\n stack.push(event);\n }\n while (stack.length) {\n const last = stack.pop();\n if (last) {\n this.#onTraceEventEnd(last);\n }\n }\n return this.#constructedProfileCalls;\n }\n\n #onTraceEventStart(event: Types.TraceEvents.TraceEventData): void {\n // Top level events cannot be nested into JS frames so we reset\n // the stack when we find one.\n if (event.name === Types.TraceEvents.KnownEventName.RUN_MICROTASKS ||\n event.name === Types.TraceEvents.KnownEventName.RUN_TASK) {\n this.#lockedJsStackDepth = [];\n this.#truncateJSStack(0, event.ts);\n this.#fakeJSInvocation = false;\n }\n\n if (this.#fakeJSInvocation) {\n this.#truncateJSStack(this.#lockedJsStackDepth.pop() || 0, event.ts);\n this.#fakeJSInvocation = false;\n }\n this.#extractStackTrace(event);\n // Keep track of the call frames in the stack before the event\n // happened. For the duration of this event, these frames cannot\n // change (none can be terminated before this event finishes).\n //\n // Also, every frame that is opened after this event, is considered\n // to be a descendant of the event. So once the event finishes, the\n // frames that were opened after it, need to be closed (see\n // onEndEvent).\n //\n // TODO(crbug.com/1417439):\n // The assumption that every frame opened after an event is a\n // descendant of the event is incorrect. For example, a JS call that\n // parents a trace event might have been sampled after the event was\n // dispatched. In this case the JS call would be discarded if this\n // event isn't an invocation event, otherwise the call will be\n // considered a child of the event. In both cases, the result would\n // be incorrect.\n this.#lockedJsStackDepth.push(this.#currentJSStack.length);\n }\n\n #onProfileCall(event: Types.TraceEvents.SyntheticProfileCall, parent?: Types.TraceEvents.TraceEventData): void {\n if ((parent && Types.TraceEvents.isJSInvocationEvent(parent)) || this.#fakeJSInvocation) {\n this.#extractStackTrace(event);\n } else if (Types.TraceEvents.isProfileCall(event) && this.#currentJSStack.length === 0) {\n // Force JS Samples to show up even if we are not inside a JS\n // invocation event, because we can be missing the start of JS\n // invocation events if we start tracing half-way through. Pretend\n // we have a top-level JS invocation event.\n this.#fakeJSInvocation = true;\n const stackDepthBefore = this.#currentJSStack.length;\n this.#extractStackTrace(event);\n this.#lockedJsStackDepth.push(stackDepthBefore);\n }\n }\n\n #onTraceEventEnd(event: Types.TraceEvents.TraceEventData): void {\n // Because the event has ended, any frames that happened after\n // this event are terminated. Frames that are ancestors to this\n // event are extended to cover its ending.\n const endTime = Types.Timing.MicroSeconds(event.ts + (event.dur ?? 0));\n this.#truncateJSStack(this.#lockedJsStackDepth.pop() || 0, endTime);\n }\n\n /**\n * Builds the initial calls with no duration from samples. Their\n * purpose is to be merged with the trace event array being parsed so\n * that they can be traversed in order with them and their duration\n * can be updated as the SampleIntegrator callbacks are invoked.\n */\n callsFromProfileSamples(): Types.TraceEvents.SyntheticProfileCall[] {\n const samples = this.#profileModel.samples;\n const timestamps = this.#profileModel.timestamps;\n const debugModeEnabled = this.#engineConfig.debugMode;\n if (!samples) {\n return [];\n }\n const calls: Types.TraceEvents.SyntheticProfileCall[] = [];\n let prevNode;\n for (let i = 0; i < samples.length; i++) {\n const node = this.#profileModel.nodeByIndex(i);\n const timestamp = millisecondsToMicroseconds(Types.Timing.MilliSeconds(timestamps[i]));\n if (!node) {\n continue;\n }\n const call = makeProfileCall(node, this.#profileId, i, timestamp, this.#processId, this.#threadId);\n calls.push(call);\n\n if (debugModeEnabled) {\n this.jsSampleEvents.push(this.#makeJSSampleEvent(call, timestamp));\n }\n if (node.id === this.#profileModel.gcNode?.id && prevNode) {\n // GC samples have no stack, so we just put GC node on top of the\n // last recorded sample. Cache the previous sample for future\n // reference.\n this.#nodeForGC.set(call, prevNode);\n continue;\n }\n prevNode = node;\n }\n return calls;\n }\n\n #makeProfileCallsForStack(profileCall: Types.TraceEvents.SyntheticProfileCall):\n Types.TraceEvents.SyntheticProfileCall[] {\n let node = this.#profileModel.nodeById(profileCall.nodeId);\n const isGarbageCollection = node?.id === this.#profileModel.gcNode?.id;\n if (isGarbageCollection) {\n // Because GC don't have a stack, we use the stack of the previous\n // sample.\n node = this.#nodeForGC.get(profileCall) || null;\n }\n if (!node) {\n return [];\n }\n // `node.depth` is 0 based, so to set the size of the array we need\n // to add 1 to its value.\n const callFrames = new Array(node.depth + 1 + Number(isGarbageCollection));\n // Add the stack trace in reverse order (bottom first).\n let i = callFrames.length - 1;\n if (isGarbageCollection) {\n // Place the garbage collection call frame on top of the stack.\n callFrames[i--] = profileCall;\n }\n\n // Many of these ProfileCalls will be GC'd later when we estimate the frame\n // durations\n while (node) {\n callFrames[i--] = makeProfileCall(\n node, profileCall.profileId, profileCall.sampleIndex, profileCall.ts, this.#processId, this.#threadId);\n node = node.parent;\n }\n return callFrames;\n }\n\n /**\n * Update tracked stack using this event's call stack.\n */\n #extractStackTrace(event: Types.TraceEvents.TraceEventData): void {\n const stackTrace =\n Types.TraceEvents.isProfileCall(event) ? this.#makeProfileCallsForStack(event) : this.#currentJSStack;\n SamplesIntegrator.filterStackFrames(stackTrace, this.#engineConfig);\n\n const endTime = event.ts + (event.dur || 0);\n const minFrames = Math.min(stackTrace.length, this.#currentJSStack.length);\n let i;\n // Merge a sample's stack frames with the stack frames we have\n // so far if we detect they are equivalent.\n // Graphically\n // This:\n // Current stack trace Sample\n // [-------A------] [A]\n // [-------B------] [B]\n // [-------C------] [C]\n // ^ t = x1 ^ t = x2\n\n // Becomes this:\n // New stack trace after merge\n // [--------A-------]\n // [--------B-------]\n // [--------C-------]\n // ^ t = x2\n for (i = this.#lockedJsStackDepth.at(-1) || 0; i < minFrames; ++i) {\n const newFrame = stackTrace[i].callFrame;\n const oldFrame = this.#currentJSStack[i].callFrame;\n if (!SamplesIntegrator.framesAreEqual(newFrame, oldFrame)) {\n break;\n }\n // Scoot the right edge of this callFrame to the right\n this.#currentJSStack[i].dur =\n Types.Timing.MicroSeconds(Math.max(this.#currentJSStack[i].dur || 0, endTime - this.#currentJSStack[i].ts));\n }\n\n // If there are call frames in the sample that differ with the stack\n // we have, update the stack, but keeping the common frames in place\n // Graphically\n // This:\n // Current stack trace Sample\n // [-------A------] [A]\n // [-------B------] [B]\n // [-------C------] [C]\n // [-------D------] [E]\n // ^ t = x1 ^ t = x2\n // Becomes this:\n // New stack trace after merge\n // [--------A-------]\n // [--------B-------]\n // [--------C-------]\n // [E]\n // ^ t = x2\n this.#truncateJSStack(i, event.ts);\n\n for (; i < stackTrace.length; ++i) {\n const call = stackTrace[i];\n if (call.nodeId === this.#profileModel.programNode?.id || call.nodeId === this.#profileModel.root?.id ||\n call.nodeId === this.#profileModel.idleNode?.id || call.nodeId === this.#profileModel.gcNode?.id) {\n // Skip (root), (program) and (idle) frames, since this are not\n // relevant for web profiling and we don't want to show them in\n // the timeline.\n continue;\n }\n this.#currentJSStack.push(call);\n this.#constructedProfileCalls.push(call);\n }\n }\n\n /**\n * When a call stack that differs from the one we are tracking has\n * been detected in the samples, the latter is \"truncated\" by\n * setting the ending time of its call frames and removing the top\n * call frames that aren't shared with the new call stack. This way,\n * we can update the tracked stack with the new call frames on top.\n * @param depth the amount of call frames from bottom to top that\n * should be kept in the tracking stack trace. AKA amount of shared\n * call frames between two stacks.\n * @param time the new end of the call frames in the stack.\n */\n #truncateJSStack(depth: number, time: Types.Timing.MicroSeconds): void {\n if (this.#lockedJsStackDepth.length) {\n const lockedDepth = this.#lockedJsStackDepth.at(-1);\n if (lockedDepth && depth < lockedDepth) {\n console.error(`Child stack is shallower (${depth}) than the parent stack (${lockedDepth}) at ${time}`);\n depth = lockedDepth;\n }\n }\n if (this.#currentJSStack.length < depth) {\n console.error(`Trying to truncate higher than the current stack size at ${time}`);\n depth = this.#currentJSStack.length;\n }\n for (let k = 0; k < this.#currentJSStack.length; ++k) {\n this.#currentJSStack[k].dur = Types.Timing.MicroSeconds(Math.max(time - this.#currentJSStack[k].ts, 0));\n }\n this.#currentJSStack.length = depth;\n }\n\n #makeJSSampleEvent(call: Types.TraceEvents.SyntheticProfileCall, timestamp: Types.Timing.MicroSeconds):\n Types.TraceEvents.SyntheticJSSample {\n const JSSampleEvent: Types.TraceEvents.SyntheticJSSample = {\n name: Types.TraceEvents.KnownEventName.JS_SAMPLE,\n cat: 'devtools.timeline',\n args: {\n data: {stackTrace: this.#makeProfileCallsForStack(call).map(e => e.callFrame)},\n },\n ph: Types.TraceEvents.Phase.INSTANT,\n ts: timestamp,\n dur: Types.Timing.MicroSeconds(0),\n pid: this.#processId,\n tid: this.#threadId,\n };\n return JSSampleEvent;\n }\n\n static framesAreEqual(frame1: Protocol.Runtime.CallFrame, frame2: Protocol.Runtime.CallFrame): boolean {\n return frame1.scriptId === frame2.scriptId && frame1.functionName === frame2.functionName &&\n frame1.lineNumber === frame2.lineNumber;\n }\n\n static showNativeName(name: string, runtimeCallStatsEnabled: boolean): boolean {\n return runtimeCallStatsEnabled && Boolean(SamplesIntegrator.nativeGroup(name));\n }\n\n static nativeGroup(nativeName: string): 'Parse'|'Compile'|null {\n if (nativeName.startsWith('Parse')) {\n return 'Parse';\n }\n if (nativeName.startsWith('Compile') || nativeName.startsWith('Recompile')) {\n return 'Compile';\n }\n return null;\n }\n\n static isNativeRuntimeFrame(frame: Protocol.Runtime.CallFrame): boolean {\n return frame.url === 'native V8Runtime';\n }\n\n static filterStackFrames(\n stack: Types.TraceEvents.SyntheticProfileCall[], engineConfig: Types.Configuration.Configuration): void {\n const showAllEvents = engineConfig.showAllEvents;\n if (showAllEvents) {\n return;\n }\n let previousNativeFrameName: string|null = null;\n let j = 0;\n for (let i = 0; i < stack.length; ++i) {\n const frame = stack[i].callFrame;\n const nativeRuntimeFrame = SamplesIntegrator.isNativeRuntimeFrame(frame);\n if (nativeRuntimeFrame &&\n !SamplesIntegrator.showNativeName(frame.functionName, engineConfig.includeRuntimeCallStats)) {\n continue;\n }\n const nativeFrameName = nativeRuntimeFrame ? SamplesIntegrator.nativeGroup(frame.functionName) : null;\n if (previousNativeFrameName && previousNativeFrameName === nativeFrameName) {\n continue;\n }\n previousNativeFrameName = nativeFrameName;\n stack[j++] = stack[i];\n }\n stack.length = j;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"SamplesIntegrator.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/SamplesIntegrator.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Protocol from '../../../generated/protocol.js';\nimport type * as CPUProfile from '../../cpu_profile/cpu_profile.js';\nimport * as Types from '../types/types.js';\n\nimport {millisecondsToMicroseconds} from './Timing.js';\nimport {makeProfileCall, mergeEventsInOrder} from './Trace.js';\n\n/**\n * This is a helper that integrates CPU profiling data coming in the\n * shape of samples, with trace events. Samples indicate what the JS\n * stack trace looked at a given point in time, but they don't have\n * duration. The SamplesIntegrator task is to make an approximation\n * of what the duration of each JS call was, given the sample data and\n * given the trace events profiled during that time. At the end of its\n * execution, the SamplesIntegrator returns an array of ProfileCalls\n * (under SamplesIntegrator::buildProfileCalls()), which\n * represent JS calls, with a call frame and duration. These calls have\n * the shape of a complete trace events and can be treated as flame\n * chart entries in the timeline.\n *\n * The approach to build the profile calls consists in tracking the\n * current stack as the following events happen (in order):\n * 1. A sample was done.\n * 2. A trace event started.\n * 3. A trace event ended.\n * Depending on the event and on the data that's coming with it the\n * stack is updated by adding or removing JS calls to it and updating\n * the duration of the calls in the tracking stack.\n *\n * note: Although this approach has been implemented since long ago, and\n * is relatively efficent (adds a complexity over the trace parsing of\n * O(n) where n is the number of samples) it has proven to be faulty.\n * It might be worthwhile experimenting with improvements or with a\n * completely different approach. Improving the approach is tracked in\n * crbug.com/1417439\n */\nexport class SamplesIntegrator {\n /**\n * The result of runing the samples integrator. Holds the JS calls\n * with their approximated duration after integrating samples into the\n * trace event tree.\n */\n #constructedProfileCalls: Types.Events.SyntheticProfileCall[] = [];\n /**\n * tracks the state of the JS stack at each point in time to update\n * the profile call durations as new events arrive. This doesn't only\n * happen with new profile calls (in which case we would compare the\n * stack in them) but also with trace events (in which case we would\n * update the duration of the events we are tracking at the moment).\n */\n #currentJSStack: Types.Events.SyntheticProfileCall[] = [];\n /**\n * Process holding the CPU profile and trace events.\n */\n #processId: Types.Events.ProcessID;\n /**\n * Thread holding the CPU profile and trace events.\n */\n #threadId: Types.Events.ThreadID;\n /**\n * Tracks the depth of the JS stack at the moment a trace event starts\n * or ends. It is assumed that for the duration of a trace event, the\n * JS stack's depth cannot decrease, since JS calls that started\n * before a trace event cannot end during the trace event. So as trace\n * events arrive, we store the \"locked\" amount of JS frames that were\n * in the stack before the event came.\n */\n #lockedJsStackDepth: number[] = [];\n /**\n * Used to keep track when samples should be integrated even if they\n * are not children of invocation trace events. This is useful in\n * cases where we can be missing the start of JS invocation events if\n * we start tracing half-way through.\n */\n #fakeJSInvocation = false;\n /**\n * The parsed CPU profile, holding the tree hierarchy of JS frames and\n * the sample data.\n */\n #profileModel: CPUProfile.CPUProfileDataModel.CPUProfileDataModel;\n /**\n * Because GC nodes don't have a stack, we artificially add a stack to\n * them which corresponds to that of the previous sample. This map\n * tracks which node is used for the stack of a GC call.\n * Note that GC samples are not shown in the flamechart, however they\n * are used during the construction of for profile calls, as we can\n * infer information about the duration of the executed code when a\n * GC node is sampled.\n */\n #nodeForGC = new Map();\n\n #engineConfig: Types.Configuration.Configuration;\n #profileId: Types.Events.ProfileID;\n\n /**\n * Keeps track of the individual samples from the CPU Profile.\n * Only used with Debug Mode experiment enabled.\n */\n jsSampleEvents: Types.Events.SyntheticJSSample[] = [];\n\n constructor(\n profileModel: CPUProfile.CPUProfileDataModel.CPUProfileDataModel, profileId: Types.Events.ProfileID,\n pid: Types.Events.ProcessID, tid: Types.Events.ThreadID, configuration?: Types.Configuration.Configuration) {\n this.#profileModel = profileModel;\n this.#threadId = tid;\n this.#processId = pid;\n this.#engineConfig = configuration || Types.Configuration.defaults();\n this.#profileId = profileId;\n }\n\n buildProfileCalls(traceEvents: Types.Events.Event[]): Types.Events.SyntheticProfileCall[] {\n const mergedEvents = mergeEventsInOrder(traceEvents, this.callsFromProfileSamples());\n const stack = [];\n for (let i = 0; i < mergedEvents.length; i++) {\n const event = mergedEvents[i];\n // Because instant trace events have no duration, they don't provide\n // useful information for possible changes in the duration of calls\n // in the JS stack.\n if (event.ph === Types.Events.Phase.INSTANT) {\n continue;\n }\n if (stack.length === 0) {\n if (Types.Events.isProfileCall(event)) {\n this.#onProfileCall(event);\n continue;\n }\n stack.push(event);\n this.#onTraceEventStart(event);\n continue;\n }\n\n const parentEvent = stack.at(-1);\n if (parentEvent === undefined) {\n continue;\n }\n const begin = event.ts;\n const parentBegin = parentEvent.ts;\n const parentDuration = parentEvent.dur || 0;\n const parentEnd = parentBegin + parentDuration;\n\n const startsAfterParent = begin >= parentEnd;\n if (startsAfterParent) {\n this.#onTraceEventEnd(parentEvent);\n stack.pop();\n i--;\n continue;\n }\n if (Types.Events.isProfileCall(event)) {\n this.#onProfileCall(event, parentEvent);\n continue;\n }\n this.#onTraceEventStart(event);\n stack.push(event);\n }\n while (stack.length) {\n const last = stack.pop();\n if (last) {\n this.#onTraceEventEnd(last);\n }\n }\n return this.#constructedProfileCalls;\n }\n\n #onTraceEventStart(event: Types.Events.Event): void {\n // Top level events cannot be nested into JS frames so we reset\n // the stack when we find one.\n if (event.name === Types.Events.Name.RUN_MICROTASKS || event.name === Types.Events.Name.RUN_TASK) {\n this.#lockedJsStackDepth = [];\n this.#truncateJSStack(0, event.ts);\n this.#fakeJSInvocation = false;\n }\n\n if (this.#fakeJSInvocation) {\n this.#truncateJSStack(this.#lockedJsStackDepth.pop() || 0, event.ts);\n this.#fakeJSInvocation = false;\n }\n this.#extractStackTrace(event);\n // Keep track of the call frames in the stack before the event\n // happened. For the duration of this event, these frames cannot\n // change (none can be terminated before this event finishes).\n //\n // Also, every frame that is opened after this event, is considered\n // to be a descendant of the event. So once the event finishes, the\n // frames that were opened after it, need to be closed (see\n // onEndEvent).\n //\n // TODO(crbug.com/1417439):\n // The assumption that every frame opened after an event is a\n // descendant of the event is incorrect. For example, a JS call that\n // parents a trace event might have been sampled after the event was\n // dispatched. In this case the JS call would be discarded if this\n // event isn't an invocation event, otherwise the call will be\n // considered a child of the event. In both cases, the result would\n // be incorrect.\n this.#lockedJsStackDepth.push(this.#currentJSStack.length);\n }\n\n #onProfileCall(event: Types.Events.SyntheticProfileCall, parent?: Types.Events.Event): void {\n if ((parent && Types.Events.isJSInvocationEvent(parent)) || this.#fakeJSInvocation) {\n this.#extractStackTrace(event);\n } else if (Types.Events.isProfileCall(event) && this.#currentJSStack.length === 0) {\n // Force JS Samples to show up even if we are not inside a JS\n // invocation event, because we can be missing the start of JS\n // invocation events if we start tracing half-way through. Pretend\n // we have a top-level JS invocation event.\n this.#fakeJSInvocation = true;\n const stackDepthBefore = this.#currentJSStack.length;\n this.#extractStackTrace(event);\n this.#lockedJsStackDepth.push(stackDepthBefore);\n }\n }\n\n #onTraceEventEnd(event: Types.Events.Event): void {\n // Because the event has ended, any frames that happened after\n // this event are terminated. Frames that are ancestors to this\n // event are extended to cover its ending.\n const endTime = Types.Timing.MicroSeconds(event.ts + (event.dur ?? 0));\n this.#truncateJSStack(this.#lockedJsStackDepth.pop() || 0, endTime);\n }\n\n /**\n * Builds the initial calls with no duration from samples. Their\n * purpose is to be merged with the trace event array being parsed so\n * that they can be traversed in order with them and their duration\n * can be updated as the SampleIntegrator callbacks are invoked.\n */\n callsFromProfileSamples(): Types.Events.SyntheticProfileCall[] {\n const samples = this.#profileModel.samples;\n const timestamps = this.#profileModel.timestamps;\n const debugModeEnabled = this.#engineConfig.debugMode;\n if (!samples) {\n return [];\n }\n const calls: Types.Events.SyntheticProfileCall[] = [];\n let prevNode;\n for (let i = 0; i < samples.length; i++) {\n const node = this.#profileModel.nodeByIndex(i);\n const timestamp = millisecondsToMicroseconds(Types.Timing.MilliSeconds(timestamps[i]));\n if (!node) {\n continue;\n }\n const call = makeProfileCall(node, this.#profileId, i, timestamp, this.#processId, this.#threadId);\n calls.push(call);\n\n if (debugModeEnabled) {\n this.jsSampleEvents.push(this.#makeJSSampleEvent(call, timestamp));\n }\n if (node.id === this.#profileModel.gcNode?.id && prevNode) {\n // GC samples have no stack, so we just put GC node on top of the\n // last recorded sample. Cache the previous sample for future\n // reference.\n this.#nodeForGC.set(call, prevNode);\n continue;\n }\n prevNode = node;\n }\n return calls;\n }\n\n #makeProfileCallsForStack(profileCall: Types.Events.SyntheticProfileCall): Types.Events.SyntheticProfileCall[] {\n let node = this.#profileModel.nodeById(profileCall.nodeId);\n const isGarbageCollection = node?.id === this.#profileModel.gcNode?.id;\n if (isGarbageCollection) {\n // Because GC don't have a stack, we use the stack of the previous\n // sample.\n node = this.#nodeForGC.get(profileCall) || null;\n }\n if (!node) {\n return [];\n }\n // `node.depth` is 0 based, so to set the size of the array we need\n // to add 1 to its value.\n const callFrames = new Array(node.depth + 1 + Number(isGarbageCollection));\n // Add the stack trace in reverse order (bottom first).\n let i = callFrames.length - 1;\n if (isGarbageCollection) {\n // Place the garbage collection call frame on top of the stack.\n callFrames[i--] = profileCall;\n }\n\n // Many of these ProfileCalls will be GC'd later when we estimate the frame\n // durations\n while (node) {\n callFrames[i--] = makeProfileCall(\n node, profileCall.profileId, profileCall.sampleIndex, profileCall.ts, this.#processId, this.#threadId);\n node = node.parent;\n }\n return callFrames;\n }\n\n /**\n * Update tracked stack using this event's call stack.\n */\n #extractStackTrace(event: Types.Events.Event): void {\n const stackTrace = Types.Events.isProfileCall(event) ? this.#makeProfileCallsForStack(event) : this.#currentJSStack;\n SamplesIntegrator.filterStackFrames(stackTrace, this.#engineConfig);\n\n const endTime = event.ts + (event.dur || 0);\n const minFrames = Math.min(stackTrace.length, this.#currentJSStack.length);\n let i;\n // Merge a sample's stack frames with the stack frames we have\n // so far if we detect they are equivalent.\n // Graphically\n // This:\n // Current stack trace Sample\n // [-------A------] [A]\n // [-------B------] [B]\n // [-------C------] [C]\n // ^ t = x1 ^ t = x2\n\n // Becomes this:\n // New stack trace after merge\n // [--------A-------]\n // [--------B-------]\n // [--------C-------]\n // ^ t = x2\n for (i = this.#lockedJsStackDepth.at(-1) || 0; i < minFrames; ++i) {\n const newFrame = stackTrace[i].callFrame;\n const oldFrame = this.#currentJSStack[i].callFrame;\n if (!SamplesIntegrator.framesAreEqual(newFrame, oldFrame)) {\n break;\n }\n // Scoot the right edge of this callFrame to the right\n this.#currentJSStack[i].dur =\n Types.Timing.MicroSeconds(Math.max(this.#currentJSStack[i].dur || 0, endTime - this.#currentJSStack[i].ts));\n }\n\n // If there are call frames in the sample that differ with the stack\n // we have, update the stack, but keeping the common frames in place\n // Graphically\n // This:\n // Current stack trace Sample\n // [-------A------] [A]\n // [-------B------] [B]\n // [-------C------] [C]\n // [-------D------] [E]\n // ^ t = x1 ^ t = x2\n // Becomes this:\n // New stack trace after merge\n // [--------A-------]\n // [--------B-------]\n // [--------C-------]\n // [E]\n // ^ t = x2\n this.#truncateJSStack(i, event.ts);\n\n for (; i < stackTrace.length; ++i) {\n const call = stackTrace[i];\n if (call.nodeId === this.#profileModel.programNode?.id || call.nodeId === this.#profileModel.root?.id ||\n call.nodeId === this.#profileModel.idleNode?.id || call.nodeId === this.#profileModel.gcNode?.id) {\n // Skip (root), (program) and (idle) frames, since this are not\n // relevant for web profiling and we don't want to show them in\n // the timeline.\n continue;\n }\n this.#currentJSStack.push(call);\n this.#constructedProfileCalls.push(call);\n }\n }\n\n /**\n * When a call stack that differs from the one we are tracking has\n * been detected in the samples, the latter is \"truncated\" by\n * setting the ending time of its call frames and removing the top\n * call frames that aren't shared with the new call stack. This way,\n * we can update the tracked stack with the new call frames on top.\n * @param depth the amount of call frames from bottom to top that\n * should be kept in the tracking stack trace. AKA amount of shared\n * call frames between two stacks.\n * @param time the new end of the call frames in the stack.\n */\n #truncateJSStack(depth: number, time: Types.Timing.MicroSeconds): void {\n if (this.#lockedJsStackDepth.length) {\n const lockedDepth = this.#lockedJsStackDepth.at(-1);\n if (lockedDepth && depth < lockedDepth) {\n console.error(`Child stack is shallower (${depth}) than the parent stack (${lockedDepth}) at ${time}`);\n depth = lockedDepth;\n }\n }\n if (this.#currentJSStack.length < depth) {\n console.error(`Trying to truncate higher than the current stack size at ${time}`);\n depth = this.#currentJSStack.length;\n }\n for (let k = 0; k < this.#currentJSStack.length; ++k) {\n this.#currentJSStack[k].dur = Types.Timing.MicroSeconds(Math.max(time - this.#currentJSStack[k].ts, 0));\n }\n this.#currentJSStack.length = depth;\n }\n\n #makeJSSampleEvent(call: Types.Events.SyntheticProfileCall, timestamp: Types.Timing.MicroSeconds):\n Types.Events.SyntheticJSSample {\n const JSSampleEvent: Types.Events.SyntheticJSSample = {\n name: Types.Events.Name.JS_SAMPLE,\n cat: 'devtools.timeline',\n args: {\n data: {stackTrace: this.#makeProfileCallsForStack(call).map(e => e.callFrame)},\n },\n ph: Types.Events.Phase.INSTANT,\n ts: timestamp,\n dur: Types.Timing.MicroSeconds(0),\n pid: this.#processId,\n tid: this.#threadId,\n };\n return JSSampleEvent;\n }\n\n static framesAreEqual(frame1: Protocol.Runtime.CallFrame, frame2: Protocol.Runtime.CallFrame): boolean {\n return frame1.scriptId === frame2.scriptId && frame1.functionName === frame2.functionName &&\n frame1.lineNumber === frame2.lineNumber;\n }\n\n static showNativeName(name: string, runtimeCallStatsEnabled: boolean): boolean {\n return runtimeCallStatsEnabled && Boolean(SamplesIntegrator.nativeGroup(name));\n }\n\n static nativeGroup(nativeName: string): 'Parse'|'Compile'|null {\n if (nativeName.startsWith('Parse')) {\n return 'Parse';\n }\n if (nativeName.startsWith('Compile') || nativeName.startsWith('Recompile')) {\n return 'Compile';\n }\n return null;\n }\n\n static isNativeRuntimeFrame(frame: Protocol.Runtime.CallFrame): boolean {\n return frame.url === 'native V8Runtime';\n }\n\n static filterStackFrames(stack: Types.Events.SyntheticProfileCall[], engineConfig: Types.Configuration.Configuration):\n void {\n const showAllEvents = engineConfig.showAllEvents;\n if (showAllEvents) {\n return;\n }\n let previousNativeFrameName: string|null = null;\n let j = 0;\n for (let i = 0; i < stack.length; ++i) {\n const frame = stack[i].callFrame;\n const nativeRuntimeFrame = SamplesIntegrator.isNativeRuntimeFrame(frame);\n if (nativeRuntimeFrame &&\n !SamplesIntegrator.showNativeName(frame.functionName, engineConfig.includeRuntimeCallStats)) {\n continue;\n }\n const nativeFrameName = nativeRuntimeFrame ? SamplesIntegrator.nativeGroup(frame.functionName) : null;\n if (previousNativeFrameName && previousNativeFrameName === nativeFrameName) {\n continue;\n }\n previousNativeFrameName = nativeFrameName;\n stack[j++] = stack[i];\n }\n stack.length = j;\n }\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/helpers/SamplesIntegrator.test.js b/public/models/trace/helpers/SamplesIntegrator.test.js index e540c840a..5773f0fd9 100644 --- a/public/models/trace/helpers/SamplesIntegrator.test.js +++ b/public/models/trace/helpers/SamplesIntegrator.test.js @@ -5,14 +5,14 @@ import * as CPUProfile from '../../../models/cpu_profile/cpu_profile.js'; import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; import { makeCompleteEvent } from '../../../testing/TraceHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; -import * as TraceModel from '../trace.js'; +import * as Trace from '../trace.js'; describeWithEnvironment('SamplesIntegrator', function () { const scriptId = 'Peperoni'; const url = ''; const lineNumber = -1; const columnNumber = -1; - const pid = TraceModel.Types.TraceEvents.ProcessID(0); - const tid = TraceModel.Types.TraceEvents.ThreadID(0); + const pid = Trace.Types.Events.ProcessID(0); + const tid = Trace.Types.Events.ThreadID(0); // Profile contains the following samples: // |a||a||a||a| // |b||b| @@ -33,10 +33,10 @@ describeWithEnvironment('SamplesIntegrator', function () { timeDeltas: new Array(4).fill(100), }; const parsedBasicProfile = new CPUProfile.CPUProfileDataModel.CPUProfileDataModel(basicCDPProfile); - const PROFILE_ID = TraceModel.Types.TraceEvents.ProfileID('fake-profile-id'); + const PROFILE_ID = Trace.Types.Events.ProfileID('fake-profile-id'); describe('callsFromProfileSamples', () => { it('generates empty profile calls from a profile with samples', () => { - const integrator = new TraceModel.Helpers.SamplesIntegrator.SamplesIntegrator(parsedBasicProfile, PROFILE_ID, pid, tid); + const integrator = new Trace.Helpers.SamplesIntegrator.SamplesIntegrator(parsedBasicProfile, PROFILE_ID, pid, tid); const calls = integrator.callsFromProfileSamples(); assert.strictEqual(calls.length, basicCDPProfile.samples?.length); let currentTimestamp = 0; @@ -56,11 +56,11 @@ describeWithEnvironment('SamplesIntegrator', function () { }); it('generates JSSamples from samples under debug mode', () => { const config = { - ...TraceModel.Types.Configuration.defaults(), + ...Trace.Types.Configuration.defaults(), }; config.debugMode = true; - assert.strictEqual(TraceModel.Types.Configuration.defaults().debugMode, false, 'Default config should not be mutable'); - const integrator = new TraceModel.Helpers.SamplesIntegrator.SamplesIntegrator(parsedBasicProfile, PROFILE_ID, pid, tid, config); + assert.strictEqual(Trace.Types.Configuration.defaults().debugMode, false, 'Default config should not be mutable'); + const integrator = new Trace.Helpers.SamplesIntegrator.SamplesIntegrator(parsedBasicProfile, PROFILE_ID, pid, tid, config); integrator.callsFromProfileSamples(); const jsSampleEvents = integrator.jsSampleEvents; assert.strictEqual(jsSampleEvents[0].ts, 100); @@ -79,14 +79,14 @@ describeWithEnvironment('SamplesIntegrator', function () { }); describe('buildProfileCalls', () => { it('generates profile calls using trace events and JS samples from a trace file', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'recursive-blocking-js.json.gz'); - const samplesData = traceData.Samples; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'recursive-blocking-js.json.gz'); + const samplesData = parsedTrace.Samples; assert.strictEqual(samplesData.profilesInProcess.size, 1); const [[pid, profileByThread]] = samplesData.profilesInProcess.entries(); const [[tid, cpuProfileData]] = profileByThread.entries(); const parsedProfile = cpuProfileData.parsedProfile; - const samplesIntegrator = new TraceModel.Helpers.SamplesIntegrator.SamplesIntegrator(parsedProfile, PROFILE_ID, pid, tid); - const traceEvents = traceData.Renderer.allTraceEntries.filter(event => event.pid === pid && event.tid === tid); + const samplesIntegrator = new Trace.Helpers.SamplesIntegrator.SamplesIntegrator(parsedProfile, PROFILE_ID, pid, tid); + const traceEvents = parsedTrace.Renderer.allTraceEntries.filter(event => event.pid === pid && event.tid === tid); if (!traceEvents) { throw new Error('Trace events were unexpectedly not found.'); } @@ -99,8 +99,8 @@ describeWithEnvironment('SamplesIntegrator', function () { // |----Trace Event----| // |----a----| // |-b-| - const integrator = new TraceModel.Helpers.SamplesIntegrator.SamplesIntegrator(parsedBasicProfile, PROFILE_ID, pid, tid); - const callEvent = makeCompleteEvent("FunctionCall" /* TraceModel.Types.TraceEvents.KnownEventName.FUNCTION_CALL */, 0, 500); + const integrator = new Trace.Helpers.SamplesIntegrator.SamplesIntegrator(parsedBasicProfile, PROFILE_ID, pid, tid); + const callEvent = makeCompleteEvent("FunctionCall" /* Trace.Types.Events.Name.FUNCTION_CALL */, 0, 500); const traceEvents = [callEvent]; const constructedCalls = integrator.buildProfileCalls(traceEvents); assert.strictEqual(constructedCalls.length, 2); @@ -112,7 +112,7 @@ describeWithEnvironment('SamplesIntegrator', function () { assert.strictEqual(constructedCalls[1].dur, 200); }); it('creates JS frame events without a top-level V8 invocation', () => { - const integrator = new TraceModel.Helpers.SamplesIntegrator.SamplesIntegrator(parsedBasicProfile, PROFILE_ID, pid, tid); + const integrator = new Trace.Helpers.SamplesIntegrator.SamplesIntegrator(parsedBasicProfile, PROFILE_ID, pid, tid); const traceEvents = []; const constructedCalls = integrator.buildProfileCalls(traceEvents); assert.strictEqual(constructedCalls.length, 2); @@ -147,8 +147,8 @@ describeWithEnvironment('SamplesIntegrator', function () { // |----a----| |--Trace Event--| // |-------b-------| const parsedProfile = new CPUProfile.CPUProfileDataModel.CPUProfileDataModel(cdpProfile); - const integrator = new TraceModel.Helpers.SamplesIntegrator.SamplesIntegrator(parsedProfile, PROFILE_ID, pid, tid); - const callEvent = makeCompleteEvent("FunctionCall" /* TraceModel.Types.TraceEvents.KnownEventName.FUNCTION_CALL */, 250, 250); + const integrator = new Trace.Helpers.SamplesIntegrator.SamplesIntegrator(parsedProfile, PROFILE_ID, pid, tid); + const callEvent = makeCompleteEvent("FunctionCall" /* Trace.Types.Events.Name.FUNCTION_CALL */, 250, 250); const traceEvents = [callEvent]; const constructedCalls = integrator.buildProfileCalls(traceEvents); assert.strictEqual(constructedCalls.length, 2); @@ -186,8 +186,8 @@ describeWithEnvironment('SamplesIntegrator', function () { // |-----------------v8.run--------------------| // |--V8.ParseFuntion--||---a---||-----b------| const parsedProfile = new CPUProfile.CPUProfileDataModel.CPUProfileDataModel(cdpProfile); - const integrator = new TraceModel.Helpers.SamplesIntegrator.SamplesIntegrator(parsedProfile, PROFILE_ID, pid, tid); - const evaluateScript = makeCompleteEvent("EvaluateScript" /* TraceModel.Types.TraceEvents.KnownEventName.EVALUATE_SCRIPT */, 0, 500); + const integrator = new Trace.Helpers.SamplesIntegrator.SamplesIntegrator(parsedProfile, PROFILE_ID, pid, tid); + const evaluateScript = makeCompleteEvent("EvaluateScript" /* Trace.Types.Events.Name.EVALUATE_SCRIPT */, 0, 500); const v8Run = makeCompleteEvent('v8.run', 10, 490); const parseFunction = makeCompleteEvent('V8.ParseFunction', 12, 1); const traceEvents = [evaluateScript, v8Run, parseFunction]; @@ -227,12 +227,12 @@ describeWithEnvironment('SamplesIntegrator', function () { // |--------a-------||------RunMicroTasks------| // |-----------a------------| // |-----------b------------| - const runTask = makeCompleteEvent("RunTask" /* TraceModel.Types.TraceEvents.KnownEventName.RUN_TASK */, 0, 100); - const evaluateScript = makeCompleteEvent("EvaluateScript" /* TraceModel.Types.TraceEvents.KnownEventName.EVALUATE_SCRIPT */, 0, 100); - const runMicroTasks = makeCompleteEvent("RunMicrotasks" /* TraceModel.Types.TraceEvents.KnownEventName.RUN_MICROTASKS */, 50, 100); + const runTask = makeCompleteEvent("RunTask" /* Trace.Types.Events.Name.RUN_TASK */, 0, 100); + const evaluateScript = makeCompleteEvent("EvaluateScript" /* Trace.Types.Events.Name.EVALUATE_SCRIPT */, 0, 100); + const runMicroTasks = makeCompleteEvent("RunMicrotasks" /* Trace.Types.Events.Name.RUN_MICROTASKS */, 50, 100); const traceEvents = [runTask, evaluateScript, runMicroTasks]; const parsedProfile = new CPUProfile.CPUProfileDataModel.CPUProfileDataModel(cdpProfile); - const integrator = new TraceModel.Helpers.SamplesIntegrator.SamplesIntegrator(parsedProfile, PROFILE_ID, pid, tid); + const integrator = new Trace.Helpers.SamplesIntegrator.SamplesIntegrator(parsedProfile, PROFILE_ID, pid, tid); const constructedCalls = integrator.buildProfileCalls(traceEvents); assert.strictEqual(constructedCalls.length, 3); const framesForFunctionA = constructedCalls.filter(c => c.callFrame.functionName === 'a'); @@ -247,14 +247,14 @@ describeWithEnvironment('SamplesIntegrator', function () { assert.strictEqual(framesForFunctionA[1].dur, runMicroTasks.ts + (runMicroTasks.dur || 0) - expectedBTimestamp); }); it('skips samples from (program), (idle), (root) and (garbage collector) nodes', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'recursive-blocking-js.json.gz'); - const samplesData = traceData.Samples; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'recursive-blocking-js.json.gz'); + const samplesData = parsedTrace.Samples; assert.strictEqual(samplesData.profilesInProcess.size, 1); const [[pid, profileByThread]] = samplesData.profilesInProcess.entries(); const [[tid, cpuProfileData]] = profileByThread.entries(); const parsedProfile = cpuProfileData.parsedProfile; - const samplesIntegrator = new TraceModel.Helpers.SamplesIntegrator.SamplesIntegrator(parsedProfile, PROFILE_ID, pid, tid); - const traceEvents = traceData.Renderer.allTraceEntries.filter(event => event.pid === pid && event.tid === tid); + const samplesIntegrator = new Trace.Helpers.SamplesIntegrator.SamplesIntegrator(parsedProfile, PROFILE_ID, pid, tid); + const traceEvents = parsedTrace.Renderer.allTraceEntries.filter(event => event.pid === pid && event.tid === tid); if (!traceEvents) { throw new Error('Trace events were unexpectedly not found.'); } diff --git a/public/models/trace/helpers/SamplesIntegrator.test.js.map b/public/models/trace/helpers/SamplesIntegrator.test.js.map index 6cfe919de..5b25db726 100644 --- a/public/models/trace/helpers/SamplesIntegrator.test.js.map +++ b/public/models/trace/helpers/SamplesIntegrator.test.js.map @@ -1 +1 @@ -{"version":3,"file":"SamplesIntegrator.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/SamplesIntegrator.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAG7B,OAAO,KAAK,UAAU,MAAM,4CAA4C,CAAC;AACzE,OAAO,EAAC,uBAAuB,EAAC,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EAAC,iBAAiB,EAAC,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAC,WAAW,EAAC,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,UAAU,MAAM,aAAa,CAAC;AAE1C,uBAAuB,CAAC,mBAAmB,EAAE;IAC3C,MAAM,QAAQ,GAAG,UAAuC,CAAC;IACzD,MAAM,GAAG,GAAG,EAAE,CAAC;IACf,MAAM,UAAU,GAAG,CAAC,CAAC,CAAC;IACtB,MAAM,YAAY,GAAG,CAAC,CAAC,CAAC;IACxB,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IACtD,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAErD,0CAA0C;IAC1C,eAAe;IACf,eAAe;IACf,MAAM,eAAe,GAA8B;QACjD,SAAS,EAAE,CAAC;QACZ,OAAO,EAAE,IAAI;QACb,KAAK,EAAE;YACL;gBACE,EAAE,EAAE,CAAC;gBACL,QAAQ,EAAE,CAAC;gBACX,SAAS,EAAE,EAAC,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAC;gBAC5E,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;aACjB;YACD,EAAC,EAAE,EAAE,CAAC,EAAE,SAAS,EAAE,EAAC,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAC;YAC/F,EAAC,EAAE,EAAE,CAAC,EAAE,SAAS,EAAE,EAAC,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAC,EAAC;SACjF;QACD,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACrB,UAAU,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;KACnC,CAAC;IAEF,MAAM,kBAAkB,GAAG,IAAI,UAAU,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,eAAe,CAAC,CAAC;IACnG,MAAM,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;IAE7E,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACvC,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;YACnE,MAAM,UAAU,GACZ,IAAI,UAAU,CAAC,OAAO,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,kBAAkB,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YACzG,MAAM,KAAK,GAAG,UAAU,CAAC,uBAAuB,EAAE,CAAC;YACnD,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,eAAe,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAClE,IAAI,gBAAgB,GAAG,CAAC,CAAC;YACzB,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YACjF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBACtB,gBAAgB,IAAI,eAAe,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;gBACzD,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;gBAChC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;gBAChC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;gBAE9C,mEAAmE;gBACnE,UAAU;gBACV,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;gBAC/C,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;gBACxC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAChC,CAAC;QACH,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;YAC3D,MAAM,MAAM,GAAG;gBACb,GAAG,UAAU,CAAC,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE;aAC7C,CAAC;YACF,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC;YACxB,MAAM,CAAC,WAAW,CACd,UAAU,CAAC,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,sCAAsC,CAAC,CAAC;YAExG,MAAM,UAAU,GACZ,IAAI,UAAU,CAAC,OAAO,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,kBAAkB,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;YACjH,UAAU,CAAC,uBAAuB,EAAE,CAAC;YACrC,MAAM,cAAc,GAAG,UAAU,CAAC,cAAc,CAAC;YAEjD,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAC9C,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAC9C,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAC9C,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAE9C,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAC7C,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAC7C,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAC7C,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAE7C,MAAM,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;YAC/F,MAAM,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;YAC/F,MAAM,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YACpG,MAAM,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;QACtG,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,EAAE,CAAC,6EAA6E,EAAE,KAAK;YACrF,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,+BAA+B,CAAC,CAAC;YACzF,MAAM,WAAW,GAAG,SAAS,CAAC,OAAO,CAAC;YACtC,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC1D,MAAM,CAAC,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,GAAG,WAAW,CAAC,iBAAiB,CAAC,OAAO,EAAE,CAAC;YACzE,MAAM,CAAC,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,GAAG,eAAe,CAAC,OAAO,EAAE,CAAC;YAC1D,MAAM,aAAa,GAAG,cAAc,CAAC,aAAa,CAAC;YACnD,MAAM,iBAAiB,GACnB,IAAI,UAAU,CAAC,OAAO,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,aAAa,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YACpG,MAAM,WAAW,GAAG,SAAS,CAAC,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,IAAI,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;YAC/G,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;YAC/D,CAAC;YACD,MAAM,gBAAgB,GAAG,iBAAiB,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YAC1E,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;YACjE,uDAAuD;YACvD,oBAAoB;YACpB,wBAAwB;YACxB,wBAAwB;YACxB,wBAAwB;YACxB,MAAM,UAAU,GACZ,IAAI,UAAU,CAAC,OAAO,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,kBAAkB,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YACzG,MAAM,SAAS,GAAG,iBAAiB,iFAA4D,CAAC,EAAE,GAAG,CAAC,CAAC;YACvG,MAAM,WAAW,GAAG,CAAC,SAAS,CAAC,CAAC;YAChC,MAAM,gBAAgB,GAAG,UAAU,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YACnE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;YACpE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAChD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACjD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;YACpE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAChD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;YACnE,MAAM,UAAU,GACZ,IAAI,UAAU,CAAC,OAAO,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,kBAAkB,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YACzG,MAAM,WAAW,GAAsD,EAAE,CAAC;YAC1E,MAAM,gBAAgB,GAAG,UAAU,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YACnE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;YACpE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAChD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACjD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;YACpE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAChD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;YACzE,0CAA0C;YAC1C,YAAY;YACZ,MAAM,UAAU,GAA8B;gBAC5C,SAAS,EAAE,CAAC;gBACZ,OAAO,EAAE,IAAI;gBACb,KAAK,EAAE;oBACL;wBACE,EAAE,EAAE,CAAC;wBACL,QAAQ,EAAE,CAAC;wBACX,SAAS,EAAE,EAAC,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAC;wBAC5E,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;qBACjB;oBACD,EAAC,EAAE,EAAE,CAAC,EAAE,SAAS,EAAE,EAAC,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAC,EAAC;oBAChF,EAAC,EAAE,EAAE,CAAC,EAAE,SAAS,EAAE,EAAC,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAC,EAAC;iBACjF;gBACD,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gBACrB,UAAU,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;aACnC,CAAC;YAEF,uDAAuD;YACvD,oBAAoB;YACpB,iCAAiC;YACjC,iCAAiC;YACjC,MAAM,aAAa,GAAG,IAAI,UAAU,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC;YACzF,MAAM,UAAU,GACZ,IAAI,UAAU,CAAC,OAAO,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,aAAa,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YACpG,MAAM,SAAS,GAAG,iBAAiB,iFAA4D,GAAG,EAAE,GAAG,CAAC,CAAC;YACzG,MAAM,WAAW,GAAG,CAAC,SAAS,CAAC,CAAC;YAChC,MAAM,gBAAgB,GAAG,UAAU,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YACnE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;YACpE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAChD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACjD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;YACpE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAChD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,iHAAiH;QACjH,4FAA4F;QAC5F,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;YACnE,0CAA0C;YAC1C,YAAY;YACZ,MAAM,UAAU,GAA8B;gBAC5C,SAAS,EAAE,CAAC;gBACZ,OAAO,EAAE,IAAI;gBACb,KAAK,EAAE;oBACL;wBACE,EAAE,EAAE,CAAC;wBACL,QAAQ,EAAE,CAAC;wBACX,SAAS,EAAE,EAAC,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAC;wBAC5E,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;qBACjB;oBACD,EAAC,EAAE,EAAE,CAAC,EAAE,SAAS,EAAE,EAAC,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAC,EAAC;oBAChF,EAAC,EAAE,EAAE,CAAC,EAAE,SAAS,EAAE,EAAC,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAC,EAAC;iBACjF;gBACD,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gBACrB,UAAU,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;aACnC,CAAC;YAEF,uDAAuD;YACvD,oBAAoB;YACpB,sDAAsD;YACtD,sDAAsD;YACtD,sDAAsD;YAEtD,MAAM,aAAa,GAAG,IAAI,UAAU,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC;YACzF,MAAM,UAAU,GACZ,IAAI,UAAU,CAAC,OAAO,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,aAAa,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YACpG,MAAM,cAAc,GAAG,iBAAiB,qFAA8D,CAAC,EAAE,GAAG,CAAC,CAAC;YAC9G,MAAM,KAAK,GAAG,iBAAiB,CAAC,QAAQ,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;YACnD,MAAM,aAAa,GAAG,iBAAiB,CAAC,kBAAkB,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;YAEnE,MAAM,WAAW,GAAG,CAAC,cAAc,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;YAC3D,MAAM,gBAAgB,GAAG,UAAU,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YACnE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;YACpE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAChD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACjD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;YACpE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAChD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,yEAAyE,EAAE,GAAG,EAAE;YACjF,0CAA0C;YAC1C,eAAe;YACf,eAAe;YACf,MAAM,UAAU,GAA8B;gBAC5C,SAAS,EAAE,CAAC;gBACZ,OAAO,EAAE,IAAI;gBACb,KAAK,EAAE;oBACL;wBACE,EAAE,EAAE,CAAC;wBACL,QAAQ,EAAE,CAAC;wBACX,SAAS,EAAE,EAAC,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAC;wBAC5E,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;qBACjB;oBACD,EAAC,EAAE,EAAE,CAAC,EAAE,SAAS,EAAE,EAAC,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAC;oBAC/F,EAAC,EAAE,EAAE,CAAC,EAAE,SAAS,EAAE,EAAC,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAC,EAAC;iBACjF;gBACD,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gBACrB,UAAU,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;aAClC,CAAC;YAEF,uDAAuD;YACvD,oBAAoB;YACpB,+DAA+D;YAC/D,+DAA+D;YAC/D,6DAA6D;YAC7D,4DAA4D;YAC5D,4DAA4D;YAC5D,MAAM,OAAO,GAAG,iBAAiB,uEAAuD,CAAC,EAAE,GAAG,CAAC,CAAC;YAChG,MAAM,cAAc,GAAG,iBAAiB,qFAA8D,CAAC,EAAE,GAAG,CAAC,CAAC;YAC9G,MAAM,aAAa,GAAG,iBAAiB,mFAA6D,EAAE,EAAE,GAAG,CAAC,CAAC;YAC7G,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,cAAc,EAAE,aAAa,CAAC,CAAC;YAC7D,MAAM,aAAa,GAAG,IAAI,UAAU,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC;YACzF,MAAM,UAAU,GACZ,IAAI,UAAU,CAAC,OAAO,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,aAAa,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YACpG,MAAM,gBAAgB,GAAG,UAAU,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YAEnE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAC/C,MAAM,kBAAkB,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,KAAK,GAAG,CAAC,CAAC;YAC1F,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACjD,MAAM,kBAAkB,GAAG,EAAE,CAAC;YAC9B,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACjD,yDAAyD;YACzD,+BAA+B;YAC/B,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,aAAa,CAAC,EAAE,GAAG,kBAAkB,CAAC,CAAC;YACrF,MAAM,kBAAkB,GAAG,EAAE,CAAC;YAC9B,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,kBAAkB,CAAC,CAAC;YACjE,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,aAAa,CAAC,EAAE,GAAG,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,kBAAkB,CAAC,CAAC;QAClH,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,4EAA4E,EAAE,KAAK;YACpF,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,+BAA+B,CAAC,CAAC;YACzF,MAAM,WAAW,GAAG,SAAS,CAAC,OAAO,CAAC;YACtC,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC1D,MAAM,CAAC,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,GAAG,WAAW,CAAC,iBAAiB,CAAC,OAAO,EAAE,CAAC;YACzE,MAAM,CAAC,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,GAAG,eAAe,CAAC,OAAO,EAAE,CAAC;YAC1D,MAAM,aAAa,GAAG,cAAc,CAAC,aAAa,CAAC;YACnD,MAAM,iBAAiB,GACnB,IAAI,UAAU,CAAC,OAAO,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,aAAa,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YACpG,MAAM,WAAW,GAAG,SAAS,CAAC,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,IAAI,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;YAC/G,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;YAC/D,CAAC;YACD,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC;YACpC,MAAM,WAAW,GAAG,aAAa,CAAC,WAAW,CAAC;YAC9C,MAAM,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC;YACxC,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC;YACpC,IAAI,WAAW,KAAK,SAAS,IAAI,QAAQ,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBAChF,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;YAC7D,CAAC;YACD,MAAM,gBAAgB,GAAG,iBAAiB,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YAE1E,MAAM,aAAa,GAAG,gBAAgB,CAAC,MAAM,CACzC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,EAAE;gBACpF,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC;YAChC,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Protocol from '../../../generated/protocol.js';\nimport * as CPUProfile from '../../../models/cpu_profile/cpu_profile.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {makeCompleteEvent} from '../../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as TraceModel from '../trace.js';\n\ndescribeWithEnvironment('SamplesIntegrator', function() {\n const scriptId = 'Peperoni' as Protocol.Runtime.ScriptId;\n const url = '';\n const lineNumber = -1;\n const columnNumber = -1;\n const pid = TraceModel.Types.TraceEvents.ProcessID(0);\n const tid = TraceModel.Types.TraceEvents.ThreadID(0);\n\n // Profile contains the following samples:\n // |a||a||a||a|\n // |b||b|\n const basicCDPProfile: Protocol.Profiler.Profile = {\n startTime: 0,\n endTime: 3000,\n nodes: [\n {\n id: 1,\n hitCount: 0,\n callFrame: {functionName: '(root)', scriptId, url, lineNumber, columnNumber},\n children: [2, 3],\n },\n {id: 2, callFrame: {functionName: 'a', scriptId, url, lineNumber, columnNumber}, children: [3]},\n {id: 3, callFrame: {functionName: 'b', scriptId, url, lineNumber, columnNumber}},\n ],\n samples: [2, 2, 3, 3],\n timeDeltas: new Array(4).fill(100),\n };\n\n const parsedBasicProfile = new CPUProfile.CPUProfileDataModel.CPUProfileDataModel(basicCDPProfile);\n const PROFILE_ID = TraceModel.Types.TraceEvents.ProfileID('fake-profile-id');\n\n describe('callsFromProfileSamples', () => {\n it('generates empty profile calls from a profile with samples', () => {\n const integrator =\n new TraceModel.Helpers.SamplesIntegrator.SamplesIntegrator(parsedBasicProfile, PROFILE_ID, pid, tid);\n const calls = integrator.callsFromProfileSamples();\n assert.strictEqual(calls.length, basicCDPProfile.samples?.length);\n let currentTimestamp = 0;\n assert.deepEqual(calls.map(c => c.callFrame.functionName), ['a', 'a', 'b', 'b']);\n for (let i = 0; i < calls.length; i++) {\n const call = calls[i];\n currentTimestamp += basicCDPProfile.timeDeltas?.[i] || 0;\n assert.strictEqual(call.dur, 0);\n assert.strictEqual(call.dur, 0);\n assert.strictEqual(call.ts, currentTimestamp);\n\n // Ensure each ProfileCall has been \"linked\" to the Profile and the\n // sample.\n assert.strictEqual(call.profileId, PROFILE_ID);\n assert.strictEqual(call.sampleIndex, i);\n assert.isDefined(call.nodeId);\n }\n });\n it('generates JSSamples from samples under debug mode', () => {\n const config = {\n ...TraceModel.Types.Configuration.defaults(),\n };\n config.debugMode = true;\n assert.strictEqual(\n TraceModel.Types.Configuration.defaults().debugMode, false, 'Default config should not be mutable');\n\n const integrator =\n new TraceModel.Helpers.SamplesIntegrator.SamplesIntegrator(parsedBasicProfile, PROFILE_ID, pid, tid, config);\n integrator.callsFromProfileSamples();\n const jsSampleEvents = integrator.jsSampleEvents;\n\n assert.strictEqual(jsSampleEvents[0].ts, 100);\n assert.strictEqual(jsSampleEvents[1].ts, 200);\n assert.strictEqual(jsSampleEvents[2].ts, 300);\n assert.strictEqual(jsSampleEvents[3].ts, 400);\n\n assert.strictEqual(jsSampleEvents[0].dur, 0);\n assert.strictEqual(jsSampleEvents[1].dur, 0);\n assert.strictEqual(jsSampleEvents[2].dur, 0);\n assert.strictEqual(jsSampleEvents[3].dur, 0);\n\n assert.deepStrictEqual(jsSampleEvents[0].args.data.stackTrace.map(f => f.functionName), ['a']);\n assert.deepStrictEqual(jsSampleEvents[1].args.data.stackTrace.map(f => f.functionName), ['a']);\n assert.deepStrictEqual(jsSampleEvents[2].args.data.stackTrace.map(f => f.functionName), ['a', 'b']);\n assert.deepStrictEqual(jsSampleEvents[3].args.data.stackTrace.map(f => f.functionName), ['a', 'b']);\n });\n });\n\n describe('buildProfileCalls', () => {\n it('generates profile calls using trace events and JS samples from a trace file', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'recursive-blocking-js.json.gz');\n const samplesData = traceData.Samples;\n assert.strictEqual(samplesData.profilesInProcess.size, 1);\n const [[pid, profileByThread]] = samplesData.profilesInProcess.entries();\n const [[tid, cpuProfileData]] = profileByThread.entries();\n const parsedProfile = cpuProfileData.parsedProfile;\n const samplesIntegrator =\n new TraceModel.Helpers.SamplesIntegrator.SamplesIntegrator(parsedProfile, PROFILE_ID, pid, tid);\n const traceEvents = traceData.Renderer.allTraceEntries.filter(event => event.pid === pid && event.tid === tid);\n if (!traceEvents) {\n throw new Error('Trace events were unexpectedly not found.');\n }\n const constructedCalls = samplesIntegrator.buildProfileCalls(traceEvents);\n assert.strictEqual(constructedCalls.length, 5131);\n });\n\n it('creates JS profile calls with a top-level V8 invocation', () => {\n // After integrating with trace events, the flame chart\n // should look like:\n // |----Trace Event----|\n // |----a----|\n // |-b-|\n const integrator =\n new TraceModel.Helpers.SamplesIntegrator.SamplesIntegrator(parsedBasicProfile, PROFILE_ID, pid, tid);\n const callEvent = makeCompleteEvent(TraceModel.Types.TraceEvents.KnownEventName.FUNCTION_CALL, 0, 500);\n const traceEvents = [callEvent];\n const constructedCalls = integrator.buildProfileCalls(traceEvents);\n assert.strictEqual(constructedCalls.length, 2);\n assert.strictEqual(constructedCalls[0].callFrame.functionName, 'a');\n assert.strictEqual(constructedCalls[0].ts, 100);\n assert.strictEqual(constructedCalls[0].dur, 400);\n assert.strictEqual(constructedCalls[1].callFrame.functionName, 'b');\n assert.strictEqual(constructedCalls[1].ts, 300);\n assert.strictEqual(constructedCalls[1].dur, 200);\n });\n\n it('creates JS frame events without a top-level V8 invocation', () => {\n const integrator =\n new TraceModel.Helpers.SamplesIntegrator.SamplesIntegrator(parsedBasicProfile, PROFILE_ID, pid, tid);\n const traceEvents: TraceModel.Types.TraceEvents.TraceEventComplete[] = [];\n const constructedCalls = integrator.buildProfileCalls(traceEvents);\n assert.strictEqual(constructedCalls.length, 2);\n assert.strictEqual(constructedCalls[0].callFrame.functionName, 'a');\n assert.strictEqual(constructedCalls[0].ts, 100);\n assert.strictEqual(constructedCalls[0].dur, 300);\n assert.strictEqual(constructedCalls[1].callFrame.functionName, 'b');\n assert.strictEqual(constructedCalls[1].ts, 300);\n assert.strictEqual(constructedCalls[1].dur, 100);\n });\n\n it('creates JS frame events for mixed with/without top-level events', () => {\n // Profile contains the following samples:\n // |a|a|b|b|\n const cdpProfile: Protocol.Profiler.Profile = {\n startTime: 0,\n endTime: 3000,\n nodes: [\n {\n id: 1,\n hitCount: 0,\n callFrame: {functionName: '(root)', scriptId, url, lineNumber, columnNumber},\n children: [2, 3],\n },\n {id: 2, callFrame: {functionName: 'a', scriptId, url, lineNumber, columnNumber}},\n {id: 3, callFrame: {functionName: 'b', scriptId, url, lineNumber, columnNumber}},\n ],\n samples: [2, 2, 3, 3],\n timeDeltas: new Array(4).fill(100),\n };\n\n // After integrating with trace events, the flame chart\n // should look like:\n // |----a----| |--Trace Event--|\n // |-------b-------|\n const parsedProfile = new CPUProfile.CPUProfileDataModel.CPUProfileDataModel(cdpProfile);\n const integrator =\n new TraceModel.Helpers.SamplesIntegrator.SamplesIntegrator(parsedProfile, PROFILE_ID, pid, tid);\n const callEvent = makeCompleteEvent(TraceModel.Types.TraceEvents.KnownEventName.FUNCTION_CALL, 250, 250);\n const traceEvents = [callEvent];\n const constructedCalls = integrator.buildProfileCalls(traceEvents);\n assert.strictEqual(constructedCalls.length, 2);\n assert.strictEqual(constructedCalls[0].callFrame.functionName, 'a');\n assert.strictEqual(constructedCalls[0].ts, 100);\n assert.strictEqual(constructedCalls[0].dur, 150);\n assert.strictEqual(constructedCalls[1].callFrame.functionName, 'b');\n assert.strictEqual(constructedCalls[1].ts, 300);\n assert.strictEqual(constructedCalls[1].dur, 200);\n });\n\n // EvaluateScript and FunctionCall are two obvious \"invocation events\", but there are others (and sometimes none)\n // We must ensure we get reasonable JSFrames even when the invocation events are unexpected.\n it('creates JS frame events with v8.run trace event as parent', () => {\n // Profile contains the following samples:\n // |a|a|b|b|\n const cdpProfile: Protocol.Profiler.Profile = {\n startTime: 0,\n endTime: 3000,\n nodes: [\n {\n id: 1,\n hitCount: 0,\n callFrame: {functionName: '(root)', scriptId, url, lineNumber, columnNumber},\n children: [2, 3],\n },\n {id: 2, callFrame: {functionName: 'a', scriptId, url, lineNumber, columnNumber}},\n {id: 3, callFrame: {functionName: 'b', scriptId, url, lineNumber, columnNumber}},\n ],\n samples: [2, 2, 3, 3],\n timeDeltas: new Array(4).fill(100),\n };\n\n // After integrating with trace events, the flame chart\n // should look like:\n // |----------------EvaluateScript-----------------|\n // |-----------------v8.run--------------------|\n // |--V8.ParseFuntion--||---a---||-----b------|\n\n const parsedProfile = new CPUProfile.CPUProfileDataModel.CPUProfileDataModel(cdpProfile);\n const integrator =\n new TraceModel.Helpers.SamplesIntegrator.SamplesIntegrator(parsedProfile, PROFILE_ID, pid, tid);\n const evaluateScript = makeCompleteEvent(TraceModel.Types.TraceEvents.KnownEventName.EVALUATE_SCRIPT, 0, 500);\n const v8Run = makeCompleteEvent('v8.run', 10, 490);\n const parseFunction = makeCompleteEvent('V8.ParseFunction', 12, 1);\n\n const traceEvents = [evaluateScript, v8Run, parseFunction];\n const constructedCalls = integrator.buildProfileCalls(traceEvents);\n assert.strictEqual(constructedCalls.length, 2);\n assert.strictEqual(constructedCalls[0].callFrame.functionName, 'a');\n assert.strictEqual(constructedCalls[0].ts, 100);\n assert.strictEqual(constructedCalls[0].dur, 200);\n assert.strictEqual(constructedCalls[1].callFrame.functionName, 'b');\n assert.strictEqual(constructedCalls[1].ts, 300);\n assert.strictEqual(constructedCalls[1].dur, 200);\n });\n it('restarts the call frame stack when a new top level event is encountered', () => {\n // Profile contains the following samples:\n // |a||a||a||a|\n // |b||b|\n const cdpProfile: Protocol.Profiler.Profile = {\n startTime: 0,\n endTime: 3000,\n nodes: [\n {\n id: 1,\n hitCount: 0,\n callFrame: {functionName: '(root)', scriptId, url, lineNumber, columnNumber},\n children: [2, 3],\n },\n {id: 2, callFrame: {functionName: 'a', scriptId, url, lineNumber, columnNumber}, children: [3]},\n {id: 3, callFrame: {functionName: 'b', scriptId, url, lineNumber, columnNumber}},\n ],\n samples: [2, 2, 3, 3],\n timeDeltas: new Array(4).fill(20),\n };\n\n // After integrating with trace events, the flame chart\n // should look like:\n // |-------------------------RunTask------------------------|\n // |----------------------EvaluateScript--------------------|\n // |--------a-------||------RunMicroTasks------|\n // |-----------a------------|\n // |-----------b------------|\n const runTask = makeCompleteEvent(TraceModel.Types.TraceEvents.KnownEventName.RUN_TASK, 0, 100);\n const evaluateScript = makeCompleteEvent(TraceModel.Types.TraceEvents.KnownEventName.EVALUATE_SCRIPT, 0, 100);\n const runMicroTasks = makeCompleteEvent(TraceModel.Types.TraceEvents.KnownEventName.RUN_MICROTASKS, 50, 100);\n const traceEvents = [runTask, evaluateScript, runMicroTasks];\n const parsedProfile = new CPUProfile.CPUProfileDataModel.CPUProfileDataModel(cdpProfile);\n const integrator =\n new TraceModel.Helpers.SamplesIntegrator.SamplesIntegrator(parsedProfile, PROFILE_ID, pid, tid);\n const constructedCalls = integrator.buildProfileCalls(traceEvents);\n\n assert.strictEqual(constructedCalls.length, 3);\n const framesForFunctionA = constructedCalls.filter(c => c.callFrame.functionName === 'a');\n assert.strictEqual(framesForFunctionA.length, 2);\n const expectedATimestamp = 20;\n assert.strictEqual(framesForFunctionA[0].ts, 20);\n // First frame for function A should be finished when the\n // RunMicrotasks event started.\n assert.strictEqual(framesForFunctionA[0].dur, runMicroTasks.ts - expectedATimestamp);\n const expectedBTimestamp = 60;\n assert.strictEqual(framesForFunctionA[1].ts, expectedBTimestamp);\n assert.strictEqual(framesForFunctionA[1].dur, runMicroTasks.ts + (runMicroTasks.dur || 0) - expectedBTimestamp);\n });\n it('skips samples from (program), (idle), (root) and (garbage collector) nodes', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'recursive-blocking-js.json.gz');\n const samplesData = traceData.Samples;\n assert.strictEqual(samplesData.profilesInProcess.size, 1);\n const [[pid, profileByThread]] = samplesData.profilesInProcess.entries();\n const [[tid, cpuProfileData]] = profileByThread.entries();\n const parsedProfile = cpuProfileData.parsedProfile;\n const samplesIntegrator =\n new TraceModel.Helpers.SamplesIntegrator.SamplesIntegrator(parsedProfile, PROFILE_ID, pid, tid);\n const traceEvents = traceData.Renderer.allTraceEntries.filter(event => event.pid === pid && event.tid === tid);\n if (!traceEvents) {\n throw new Error('Trace events were unexpectedly not found.');\n }\n const rootNode = parsedProfile.root;\n const programNode = parsedProfile.programNode;\n const idleNode = parsedProfile.idleNode;\n const gcNode = parsedProfile.gcNode;\n if (programNode === undefined || idleNode === undefined || gcNode === undefined) {\n throw new Error('Could not find program, idle or gc node');\n }\n const constructedCalls = samplesIntegrator.buildProfileCalls(traceEvents);\n\n const filteredNodes = constructedCalls.filter(\n c => c.nodeId === rootNode.id || c.nodeId === idleNode.id || c.nodeId === programNode.id ||\n c.nodeId === gcNode.id);\n assert.strictEqual(filteredNodes.length, 0);\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"SamplesIntegrator.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/SamplesIntegrator.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAG7B,OAAO,KAAK,UAAU,MAAM,4CAA4C,CAAC;AACzE,OAAO,EAAC,uBAAuB,EAAC,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EAAC,iBAAiB,EAAC,MAAM,kCAAkC,CAAC;AACnE,OAAO,EAAC,WAAW,EAAC,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,KAAK,MAAM,aAAa,CAAC;AAErC,uBAAuB,CAAC,mBAAmB,EAAE;IAC3C,MAAM,QAAQ,GAAG,UAAuC,CAAC;IACzD,MAAM,GAAG,GAAG,EAAE,CAAC;IACf,MAAM,UAAU,GAAG,CAAC,CAAC,CAAC;IACtB,MAAM,YAAY,GAAG,CAAC,CAAC,CAAC;IACxB,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAC5C,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAE3C,0CAA0C;IAC1C,eAAe;IACf,eAAe;IACf,MAAM,eAAe,GAA8B;QACjD,SAAS,EAAE,CAAC;QACZ,OAAO,EAAE,IAAI;QACb,KAAK,EAAE;YACL;gBACE,EAAE,EAAE,CAAC;gBACL,QAAQ,EAAE,CAAC;gBACX,SAAS,EAAE,EAAC,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAC;gBAC5E,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;aACjB;YACD,EAAC,EAAE,EAAE,CAAC,EAAE,SAAS,EAAE,EAAC,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAC;YAC/F,EAAC,EAAE,EAAE,CAAC,EAAE,SAAS,EAAE,EAAC,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAC,EAAC;SACjF;QACD,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACrB,UAAU,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;KACnC,CAAC;IAEF,MAAM,kBAAkB,GAAG,IAAI,UAAU,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,eAAe,CAAC,CAAC;IACnG,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;IAEnE,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACvC,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;YACnE,MAAM,UAAU,GACZ,IAAI,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,kBAAkB,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YACpG,MAAM,KAAK,GAAG,UAAU,CAAC,uBAAuB,EAAE,CAAC;YACnD,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE,eAAe,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YAClE,IAAI,gBAAgB,GAAG,CAAC,CAAC;YACzB,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YACjF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBACtB,gBAAgB,IAAI,eAAe,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;gBACzD,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;gBAChC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;gBAChC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,gBAAgB,CAAC,CAAC;gBAE9C,mEAAmE;gBACnE,UAAU;gBACV,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;gBAC/C,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;gBACxC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAChC,CAAC;QACH,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;YAC3D,MAAM,MAAM,GAAG;gBACb,GAAG,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE;aACxC,CAAC;YACF,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC;YACxB,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,SAAS,EAAE,KAAK,EAAE,sCAAsC,CAAC,CAAC;YAElH,MAAM,UAAU,GACZ,IAAI,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,kBAAkB,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;YAC5G,UAAU,CAAC,uBAAuB,EAAE,CAAC;YACrC,MAAM,cAAc,GAAG,UAAU,CAAC,cAAc,CAAC;YAEjD,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAC9C,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAC9C,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAC9C,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAE9C,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAC7C,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAC7C,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAC7C,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YAE7C,MAAM,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;YAC/F,MAAM,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;YAC/F,MAAM,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;YACpG,MAAM,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;QACtG,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,EAAE,CAAC,6EAA6E,EAAE,KAAK;YACrF,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,+BAA+B,CAAC,CAAC;YAC3F,MAAM,WAAW,GAAG,WAAW,CAAC,OAAO,CAAC;YACxC,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC1D,MAAM,CAAC,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,GAAG,WAAW,CAAC,iBAAiB,CAAC,OAAO,EAAE,CAAC;YACzE,MAAM,CAAC,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,GAAG,eAAe,CAAC,OAAO,EAAE,CAAC;YAC1D,MAAM,aAAa,GAAG,cAAc,CAAC,aAAa,CAAC;YACnD,MAAM,iBAAiB,GACnB,IAAI,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,aAAa,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YAC/F,MAAM,WAAW,GAAG,WAAW,CAAC,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,IAAI,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;YACjH,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;YAC/D,CAAC;YACD,MAAM,gBAAgB,GAAG,iBAAiB,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YAC1E,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;YACjE,uDAAuD;YACvD,oBAAoB;YACpB,wBAAwB;YACxB,wBAAwB;YACxB,wBAAwB;YACxB,MAAM,UAAU,GACZ,IAAI,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,kBAAkB,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YACpG,MAAM,SAAS,GAAG,iBAAiB,6DAAwC,CAAC,EAAE,GAAG,CAAC,CAAC;YACnF,MAAM,WAAW,GAAG,CAAC,SAAS,CAAC,CAAC;YAChC,MAAM,gBAAgB,GAAG,UAAU,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YACnE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;YACpE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAChD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACjD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;YACpE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAChD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;YACnE,MAAM,UAAU,GACZ,IAAI,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,kBAAkB,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YACpG,MAAM,WAAW,GAAkC,EAAE,CAAC;YACtD,MAAM,gBAAgB,GAAG,UAAU,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YACnE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;YACpE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAChD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACjD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;YACpE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAChD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iEAAiE,EAAE,GAAG,EAAE;YACzE,0CAA0C;YAC1C,YAAY;YACZ,MAAM,UAAU,GAA8B;gBAC5C,SAAS,EAAE,CAAC;gBACZ,OAAO,EAAE,IAAI;gBACb,KAAK,EAAE;oBACL;wBACE,EAAE,EAAE,CAAC;wBACL,QAAQ,EAAE,CAAC;wBACX,SAAS,EAAE,EAAC,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAC;wBAC5E,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;qBACjB;oBACD,EAAC,EAAE,EAAE,CAAC,EAAE,SAAS,EAAE,EAAC,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAC,EAAC;oBAChF,EAAC,EAAE,EAAE,CAAC,EAAE,SAAS,EAAE,EAAC,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAC,EAAC;iBACjF;gBACD,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gBACrB,UAAU,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;aACnC,CAAC;YAEF,uDAAuD;YACvD,oBAAoB;YACpB,iCAAiC;YACjC,iCAAiC;YACjC,MAAM,aAAa,GAAG,IAAI,UAAU,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC;YACzF,MAAM,UAAU,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,aAAa,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YAC9G,MAAM,SAAS,GAAG,iBAAiB,6DAAwC,GAAG,EAAE,GAAG,CAAC,CAAC;YACrF,MAAM,WAAW,GAAG,CAAC,SAAS,CAAC,CAAC;YAChC,MAAM,gBAAgB,GAAG,UAAU,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YACnE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;YACpE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAChD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACjD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;YACpE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAChD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,iHAAiH;QACjH,4FAA4F;QAC5F,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;YACnE,0CAA0C;YAC1C,YAAY;YACZ,MAAM,UAAU,GAA8B;gBAC5C,SAAS,EAAE,CAAC;gBACZ,OAAO,EAAE,IAAI;gBACb,KAAK,EAAE;oBACL;wBACE,EAAE,EAAE,CAAC;wBACL,QAAQ,EAAE,CAAC;wBACX,SAAS,EAAE,EAAC,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAC;wBAC5E,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;qBACjB;oBACD,EAAC,EAAE,EAAE,CAAC,EAAE,SAAS,EAAE,EAAC,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAC,EAAC;oBAChF,EAAC,EAAE,EAAE,CAAC,EAAE,SAAS,EAAE,EAAC,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAC,EAAC;iBACjF;gBACD,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gBACrB,UAAU,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;aACnC,CAAC;YAEF,uDAAuD;YACvD,oBAAoB;YACpB,sDAAsD;YACtD,sDAAsD;YACtD,sDAAsD;YAEtD,MAAM,aAAa,GAAG,IAAI,UAAU,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC;YACzF,MAAM,UAAU,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,aAAa,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YAC9G,MAAM,cAAc,GAAG,iBAAiB,iEAA0C,CAAC,EAAE,GAAG,CAAC,CAAC;YAC1F,MAAM,KAAK,GAAG,iBAAiB,CAAC,QAAQ,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;YACnD,MAAM,aAAa,GAAG,iBAAiB,CAAC,kBAAkB,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;YAEnE,MAAM,WAAW,GAAG,CAAC,cAAc,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC;YAC3D,MAAM,gBAAgB,GAAG,UAAU,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YACnE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;YACpE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAChD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACjD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;YACpE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAChD,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,yEAAyE,EAAE,GAAG,EAAE;YACjF,0CAA0C;YAC1C,eAAe;YACf,eAAe;YACf,MAAM,UAAU,GAA8B;gBAC5C,SAAS,EAAE,CAAC;gBACZ,OAAO,EAAE,IAAI;gBACb,KAAK,EAAE;oBACL;wBACE,EAAE,EAAE,CAAC;wBACL,QAAQ,EAAE,CAAC;wBACX,SAAS,EAAE,EAAC,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAC;wBAC5E,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;qBACjB;oBACD,EAAC,EAAE,EAAE,CAAC,EAAE,SAAS,EAAE,EAAC,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAC;oBAC/F,EAAC,EAAE,EAAE,CAAC,EAAE,SAAS,EAAE,EAAC,YAAY,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,UAAU,EAAE,YAAY,EAAC,EAAC;iBACjF;gBACD,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gBACrB,UAAU,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;aAClC,CAAC;YAEF,uDAAuD;YACvD,oBAAoB;YACpB,+DAA+D;YAC/D,+DAA+D;YAC/D,6DAA6D;YAC7D,4DAA4D;YAC5D,4DAA4D;YAC5D,MAAM,OAAO,GAAG,iBAAiB,mDAAmC,CAAC,EAAE,GAAG,CAAC,CAAC;YAC5E,MAAM,cAAc,GAAG,iBAAiB,iEAA0C,CAAC,EAAE,GAAG,CAAC,CAAC;YAC1F,MAAM,aAAa,GAAG,iBAAiB,+DAAyC,EAAE,EAAE,GAAG,CAAC,CAAC;YACzF,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,cAAc,EAAE,aAAa,CAAC,CAAC;YAC7D,MAAM,aAAa,GAAG,IAAI,UAAU,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC;YACzF,MAAM,UAAU,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,aAAa,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YAC9G,MAAM,gBAAgB,GAAG,UAAU,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YAEnE,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAC/C,MAAM,kBAAkB,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,YAAY,KAAK,GAAG,CAAC,CAAC;YAC1F,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YACjD,MAAM,kBAAkB,GAAG,EAAE,CAAC;YAC9B,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACjD,yDAAyD;YACzD,+BAA+B;YAC/B,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,aAAa,CAAC,EAAE,GAAG,kBAAkB,CAAC,CAAC;YACrF,MAAM,kBAAkB,GAAG,EAAE,CAAC;YAC9B,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,kBAAkB,CAAC,CAAC;YACjE,MAAM,CAAC,WAAW,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,aAAa,CAAC,EAAE,GAAG,CAAC,aAAa,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,kBAAkB,CAAC,CAAC;QAClH,CAAC,CAAC,CAAC;QACH,EAAE,CAAC,4EAA4E,EAAE,KAAK;YACpF,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,+BAA+B,CAAC,CAAC;YAC3F,MAAM,WAAW,GAAG,WAAW,CAAC,OAAO,CAAC;YACxC,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC1D,MAAM,CAAC,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC,GAAG,WAAW,CAAC,iBAAiB,CAAC,OAAO,EAAE,CAAC;YACzE,MAAM,CAAC,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,GAAG,eAAe,CAAC,OAAO,EAAE,CAAC;YAC1D,MAAM,aAAa,GAAG,cAAc,CAAC,aAAa,CAAC;YACnD,MAAM,iBAAiB,GACnB,IAAI,KAAK,CAAC,OAAO,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,aAAa,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;YAC/F,MAAM,WAAW,GAAG,WAAW,CAAC,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,KAAK,GAAG,IAAI,KAAK,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;YACjH,IAAI,CAAC,WAAW,EAAE,CAAC;gBACjB,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;YAC/D,CAAC;YACD,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC;YACpC,MAAM,WAAW,GAAG,aAAa,CAAC,WAAW,CAAC;YAC9C,MAAM,QAAQ,GAAG,aAAa,CAAC,QAAQ,CAAC;YACxC,MAAM,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC;YACpC,IAAI,WAAW,KAAK,SAAS,IAAI,QAAQ,KAAK,SAAS,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;gBAChF,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;YAC7D,CAAC;YACD,MAAM,gBAAgB,GAAG,iBAAiB,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;YAE1E,MAAM,aAAa,GAAG,gBAAgB,CAAC,MAAM,CACzC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,EAAE;gBACpF,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC;YAChC,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Protocol from '../../../generated/protocol.js';\nimport * as CPUProfile from '../../../models/cpu_profile/cpu_profile.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {makeCompleteEvent} from '../../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Trace from '../trace.js';\n\ndescribeWithEnvironment('SamplesIntegrator', function() {\n const scriptId = 'Peperoni' as Protocol.Runtime.ScriptId;\n const url = '';\n const lineNumber = -1;\n const columnNumber = -1;\n const pid = Trace.Types.Events.ProcessID(0);\n const tid = Trace.Types.Events.ThreadID(0);\n\n // Profile contains the following samples:\n // |a||a||a||a|\n // |b||b|\n const basicCDPProfile: Protocol.Profiler.Profile = {\n startTime: 0,\n endTime: 3000,\n nodes: [\n {\n id: 1,\n hitCount: 0,\n callFrame: {functionName: '(root)', scriptId, url, lineNumber, columnNumber},\n children: [2, 3],\n },\n {id: 2, callFrame: {functionName: 'a', scriptId, url, lineNumber, columnNumber}, children: [3]},\n {id: 3, callFrame: {functionName: 'b', scriptId, url, lineNumber, columnNumber}},\n ],\n samples: [2, 2, 3, 3],\n timeDeltas: new Array(4).fill(100),\n };\n\n const parsedBasicProfile = new CPUProfile.CPUProfileDataModel.CPUProfileDataModel(basicCDPProfile);\n const PROFILE_ID = Trace.Types.Events.ProfileID('fake-profile-id');\n\n describe('callsFromProfileSamples', () => {\n it('generates empty profile calls from a profile with samples', () => {\n const integrator =\n new Trace.Helpers.SamplesIntegrator.SamplesIntegrator(parsedBasicProfile, PROFILE_ID, pid, tid);\n const calls = integrator.callsFromProfileSamples();\n assert.strictEqual(calls.length, basicCDPProfile.samples?.length);\n let currentTimestamp = 0;\n assert.deepEqual(calls.map(c => c.callFrame.functionName), ['a', 'a', 'b', 'b']);\n for (let i = 0; i < calls.length; i++) {\n const call = calls[i];\n currentTimestamp += basicCDPProfile.timeDeltas?.[i] || 0;\n assert.strictEqual(call.dur, 0);\n assert.strictEqual(call.dur, 0);\n assert.strictEqual(call.ts, currentTimestamp);\n\n // Ensure each ProfileCall has been \"linked\" to the Profile and the\n // sample.\n assert.strictEqual(call.profileId, PROFILE_ID);\n assert.strictEqual(call.sampleIndex, i);\n assert.isDefined(call.nodeId);\n }\n });\n it('generates JSSamples from samples under debug mode', () => {\n const config = {\n ...Trace.Types.Configuration.defaults(),\n };\n config.debugMode = true;\n assert.strictEqual(Trace.Types.Configuration.defaults().debugMode, false, 'Default config should not be mutable');\n\n const integrator =\n new Trace.Helpers.SamplesIntegrator.SamplesIntegrator(parsedBasicProfile, PROFILE_ID, pid, tid, config);\n integrator.callsFromProfileSamples();\n const jsSampleEvents = integrator.jsSampleEvents;\n\n assert.strictEqual(jsSampleEvents[0].ts, 100);\n assert.strictEqual(jsSampleEvents[1].ts, 200);\n assert.strictEqual(jsSampleEvents[2].ts, 300);\n assert.strictEqual(jsSampleEvents[3].ts, 400);\n\n assert.strictEqual(jsSampleEvents[0].dur, 0);\n assert.strictEqual(jsSampleEvents[1].dur, 0);\n assert.strictEqual(jsSampleEvents[2].dur, 0);\n assert.strictEqual(jsSampleEvents[3].dur, 0);\n\n assert.deepStrictEqual(jsSampleEvents[0].args.data.stackTrace.map(f => f.functionName), ['a']);\n assert.deepStrictEqual(jsSampleEvents[1].args.data.stackTrace.map(f => f.functionName), ['a']);\n assert.deepStrictEqual(jsSampleEvents[2].args.data.stackTrace.map(f => f.functionName), ['a', 'b']);\n assert.deepStrictEqual(jsSampleEvents[3].args.data.stackTrace.map(f => f.functionName), ['a', 'b']);\n });\n });\n\n describe('buildProfileCalls', () => {\n it('generates profile calls using trace events and JS samples from a trace file', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'recursive-blocking-js.json.gz');\n const samplesData = parsedTrace.Samples;\n assert.strictEqual(samplesData.profilesInProcess.size, 1);\n const [[pid, profileByThread]] = samplesData.profilesInProcess.entries();\n const [[tid, cpuProfileData]] = profileByThread.entries();\n const parsedProfile = cpuProfileData.parsedProfile;\n const samplesIntegrator =\n new Trace.Helpers.SamplesIntegrator.SamplesIntegrator(parsedProfile, PROFILE_ID, pid, tid);\n const traceEvents = parsedTrace.Renderer.allTraceEntries.filter(event => event.pid === pid && event.tid === tid);\n if (!traceEvents) {\n throw new Error('Trace events were unexpectedly not found.');\n }\n const constructedCalls = samplesIntegrator.buildProfileCalls(traceEvents);\n assert.strictEqual(constructedCalls.length, 5131);\n });\n\n it('creates JS profile calls with a top-level V8 invocation', () => {\n // After integrating with trace events, the flame chart\n // should look like:\n // |----Trace Event----|\n // |----a----|\n // |-b-|\n const integrator =\n new Trace.Helpers.SamplesIntegrator.SamplesIntegrator(parsedBasicProfile, PROFILE_ID, pid, tid);\n const callEvent = makeCompleteEvent(Trace.Types.Events.Name.FUNCTION_CALL, 0, 500);\n const traceEvents = [callEvent];\n const constructedCalls = integrator.buildProfileCalls(traceEvents);\n assert.strictEqual(constructedCalls.length, 2);\n assert.strictEqual(constructedCalls[0].callFrame.functionName, 'a');\n assert.strictEqual(constructedCalls[0].ts, 100);\n assert.strictEqual(constructedCalls[0].dur, 400);\n assert.strictEqual(constructedCalls[1].callFrame.functionName, 'b');\n assert.strictEqual(constructedCalls[1].ts, 300);\n assert.strictEqual(constructedCalls[1].dur, 200);\n });\n\n it('creates JS frame events without a top-level V8 invocation', () => {\n const integrator =\n new Trace.Helpers.SamplesIntegrator.SamplesIntegrator(parsedBasicProfile, PROFILE_ID, pid, tid);\n const traceEvents: Trace.Types.Events.Complete[] = [];\n const constructedCalls = integrator.buildProfileCalls(traceEvents);\n assert.strictEqual(constructedCalls.length, 2);\n assert.strictEqual(constructedCalls[0].callFrame.functionName, 'a');\n assert.strictEqual(constructedCalls[0].ts, 100);\n assert.strictEqual(constructedCalls[0].dur, 300);\n assert.strictEqual(constructedCalls[1].callFrame.functionName, 'b');\n assert.strictEqual(constructedCalls[1].ts, 300);\n assert.strictEqual(constructedCalls[1].dur, 100);\n });\n\n it('creates JS frame events for mixed with/without top-level events', () => {\n // Profile contains the following samples:\n // |a|a|b|b|\n const cdpProfile: Protocol.Profiler.Profile = {\n startTime: 0,\n endTime: 3000,\n nodes: [\n {\n id: 1,\n hitCount: 0,\n callFrame: {functionName: '(root)', scriptId, url, lineNumber, columnNumber},\n children: [2, 3],\n },\n {id: 2, callFrame: {functionName: 'a', scriptId, url, lineNumber, columnNumber}},\n {id: 3, callFrame: {functionName: 'b', scriptId, url, lineNumber, columnNumber}},\n ],\n samples: [2, 2, 3, 3],\n timeDeltas: new Array(4).fill(100),\n };\n\n // After integrating with trace events, the flame chart\n // should look like:\n // |----a----| |--Trace Event--|\n // |-------b-------|\n const parsedProfile = new CPUProfile.CPUProfileDataModel.CPUProfileDataModel(cdpProfile);\n const integrator = new Trace.Helpers.SamplesIntegrator.SamplesIntegrator(parsedProfile, PROFILE_ID, pid, tid);\n const callEvent = makeCompleteEvent(Trace.Types.Events.Name.FUNCTION_CALL, 250, 250);\n const traceEvents = [callEvent];\n const constructedCalls = integrator.buildProfileCalls(traceEvents);\n assert.strictEqual(constructedCalls.length, 2);\n assert.strictEqual(constructedCalls[0].callFrame.functionName, 'a');\n assert.strictEqual(constructedCalls[0].ts, 100);\n assert.strictEqual(constructedCalls[0].dur, 150);\n assert.strictEqual(constructedCalls[1].callFrame.functionName, 'b');\n assert.strictEqual(constructedCalls[1].ts, 300);\n assert.strictEqual(constructedCalls[1].dur, 200);\n });\n\n // EvaluateScript and FunctionCall are two obvious \"invocation events\", but there are others (and sometimes none)\n // We must ensure we get reasonable JSFrames even when the invocation events are unexpected.\n it('creates JS frame events with v8.run trace event as parent', () => {\n // Profile contains the following samples:\n // |a|a|b|b|\n const cdpProfile: Protocol.Profiler.Profile = {\n startTime: 0,\n endTime: 3000,\n nodes: [\n {\n id: 1,\n hitCount: 0,\n callFrame: {functionName: '(root)', scriptId, url, lineNumber, columnNumber},\n children: [2, 3],\n },\n {id: 2, callFrame: {functionName: 'a', scriptId, url, lineNumber, columnNumber}},\n {id: 3, callFrame: {functionName: 'b', scriptId, url, lineNumber, columnNumber}},\n ],\n samples: [2, 2, 3, 3],\n timeDeltas: new Array(4).fill(100),\n };\n\n // After integrating with trace events, the flame chart\n // should look like:\n // |----------------EvaluateScript-----------------|\n // |-----------------v8.run--------------------|\n // |--V8.ParseFuntion--||---a---||-----b------|\n\n const parsedProfile = new CPUProfile.CPUProfileDataModel.CPUProfileDataModel(cdpProfile);\n const integrator = new Trace.Helpers.SamplesIntegrator.SamplesIntegrator(parsedProfile, PROFILE_ID, pid, tid);\n const evaluateScript = makeCompleteEvent(Trace.Types.Events.Name.EVALUATE_SCRIPT, 0, 500);\n const v8Run = makeCompleteEvent('v8.run', 10, 490);\n const parseFunction = makeCompleteEvent('V8.ParseFunction', 12, 1);\n\n const traceEvents = [evaluateScript, v8Run, parseFunction];\n const constructedCalls = integrator.buildProfileCalls(traceEvents);\n assert.strictEqual(constructedCalls.length, 2);\n assert.strictEqual(constructedCalls[0].callFrame.functionName, 'a');\n assert.strictEqual(constructedCalls[0].ts, 100);\n assert.strictEqual(constructedCalls[0].dur, 200);\n assert.strictEqual(constructedCalls[1].callFrame.functionName, 'b');\n assert.strictEqual(constructedCalls[1].ts, 300);\n assert.strictEqual(constructedCalls[1].dur, 200);\n });\n it('restarts the call frame stack when a new top level event is encountered', () => {\n // Profile contains the following samples:\n // |a||a||a||a|\n // |b||b|\n const cdpProfile: Protocol.Profiler.Profile = {\n startTime: 0,\n endTime: 3000,\n nodes: [\n {\n id: 1,\n hitCount: 0,\n callFrame: {functionName: '(root)', scriptId, url, lineNumber, columnNumber},\n children: [2, 3],\n },\n {id: 2, callFrame: {functionName: 'a', scriptId, url, lineNumber, columnNumber}, children: [3]},\n {id: 3, callFrame: {functionName: 'b', scriptId, url, lineNumber, columnNumber}},\n ],\n samples: [2, 2, 3, 3],\n timeDeltas: new Array(4).fill(20),\n };\n\n // After integrating with trace events, the flame chart\n // should look like:\n // |-------------------------RunTask------------------------|\n // |----------------------EvaluateScript--------------------|\n // |--------a-------||------RunMicroTasks------|\n // |-----------a------------|\n // |-----------b------------|\n const runTask = makeCompleteEvent(Trace.Types.Events.Name.RUN_TASK, 0, 100);\n const evaluateScript = makeCompleteEvent(Trace.Types.Events.Name.EVALUATE_SCRIPT, 0, 100);\n const runMicroTasks = makeCompleteEvent(Trace.Types.Events.Name.RUN_MICROTASKS, 50, 100);\n const traceEvents = [runTask, evaluateScript, runMicroTasks];\n const parsedProfile = new CPUProfile.CPUProfileDataModel.CPUProfileDataModel(cdpProfile);\n const integrator = new Trace.Helpers.SamplesIntegrator.SamplesIntegrator(parsedProfile, PROFILE_ID, pid, tid);\n const constructedCalls = integrator.buildProfileCalls(traceEvents);\n\n assert.strictEqual(constructedCalls.length, 3);\n const framesForFunctionA = constructedCalls.filter(c => c.callFrame.functionName === 'a');\n assert.strictEqual(framesForFunctionA.length, 2);\n const expectedATimestamp = 20;\n assert.strictEqual(framesForFunctionA[0].ts, 20);\n // First frame for function A should be finished when the\n // RunMicrotasks event started.\n assert.strictEqual(framesForFunctionA[0].dur, runMicroTasks.ts - expectedATimestamp);\n const expectedBTimestamp = 60;\n assert.strictEqual(framesForFunctionA[1].ts, expectedBTimestamp);\n assert.strictEqual(framesForFunctionA[1].dur, runMicroTasks.ts + (runMicroTasks.dur || 0) - expectedBTimestamp);\n });\n it('skips samples from (program), (idle), (root) and (garbage collector) nodes', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'recursive-blocking-js.json.gz');\n const samplesData = parsedTrace.Samples;\n assert.strictEqual(samplesData.profilesInProcess.size, 1);\n const [[pid, profileByThread]] = samplesData.profilesInProcess.entries();\n const [[tid, cpuProfileData]] = profileByThread.entries();\n const parsedProfile = cpuProfileData.parsedProfile;\n const samplesIntegrator =\n new Trace.Helpers.SamplesIntegrator.SamplesIntegrator(parsedProfile, PROFILE_ID, pid, tid);\n const traceEvents = parsedTrace.Renderer.allTraceEntries.filter(event => event.pid === pid && event.tid === tid);\n if (!traceEvents) {\n throw new Error('Trace events were unexpectedly not found.');\n }\n const rootNode = parsedProfile.root;\n const programNode = parsedProfile.programNode;\n const idleNode = parsedProfile.idleNode;\n const gcNode = parsedProfile.gcNode;\n if (programNode === undefined || idleNode === undefined || gcNode === undefined) {\n throw new Error('Could not find program, idle or gc node');\n }\n const constructedCalls = samplesIntegrator.buildProfileCalls(traceEvents);\n\n const filteredNodes = constructedCalls.filter(\n c => c.nodeId === rootNode.id || c.nodeId === idleNode.id || c.nodeId === programNode.id ||\n c.nodeId === gcNode.id);\n assert.strictEqual(filteredNodes.length, 0);\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/helpers/SyntheticEvents.d.ts b/public/models/trace/helpers/SyntheticEvents.d.ts index 49e2e208a..fa06184f1 100644 --- a/public/models/trace/helpers/SyntheticEvents.d.ts +++ b/public/models/trace/helpers/SyntheticEvents.d.ts @@ -2,19 +2,19 @@ import type * as Types from '../types/types.js'; export declare class SyntheticEventsManager { #private; static activate(manager: SyntheticEventsManager): void; - static createAndActivate(rawEvents: readonly Types.TraceEvents.TraceEventData[]): SyntheticEventsManager; + static createAndActivate(rawEvents: readonly Types.Events.Event[]): SyntheticEventsManager; static getActiveManager(): SyntheticEventsManager; static reset(): void; - static registerSyntheticBasedEvent(syntheticEvent: Omit): T; - static registerServerTiming(syntheticEvent: Omit): Types.TraceEvents.SyntheticServerTiming; + static registerSyntheticEvent(syntheticEvent: Omit): T; + static registerServerTiming(syntheticEvent: Omit): Types.Events.SyntheticServerTiming; private constructor(); /** * Registers and returns a branded synthetic event. Synthetic events need to * be created with this method to ensure they are registered and made * available to load events using serialized keys. */ - registerSyntheticBasedEvent(syntheticEvent: Omit): T; - syntheticEventForRawEventIndex(rawEventIndex: number): Types.TraceEvents.SyntheticBasedEvent; - getSyntheticTraceEvents(): Types.TraceEvents.SyntheticBasedEvent[]; - getRawTraceEvents(): readonly Types.TraceEvents.TraceEventData[]; + registerSyntheticEvent(syntheticEvent: Omit): T; + syntheticEventForRawEventIndex(rawEventIndex: number): Types.Events.SyntheticBased; + getSyntheticTraces(): Types.Events.SyntheticBased[]; + getRawTraceEvents(): readonly Types.Events.Event[]; } diff --git a/public/models/trace/helpers/SyntheticEvents.js b/public/models/trace/helpers/SyntheticEvents.js index 47024db09..5d66b9829 100644 --- a/public/models/trace/helpers/SyntheticEvents.js +++ b/public/models/trace/helpers/SyntheticEvents.js @@ -7,7 +7,7 @@ export class SyntheticEventsManager { * All synthetic entries created in a trace from a corresponding trace events. * (ProfileCalls are excluded because they are not based on a real trace event) */ - #syntheticTraceEvents = []; + #syntheticTraces = []; /** * All raw entries from a trace. */ @@ -29,9 +29,9 @@ export class SyntheticEventsManager { static reset() { activeManager = null; } - static registerSyntheticBasedEvent(syntheticEvent) { + static registerSyntheticEvent(syntheticEvent) { try { - return SyntheticEventsManager.getActiveManager().registerSyntheticBasedEvent(syntheticEvent); + return SyntheticEventsManager.getActiveManager().registerSyntheticEvent(syntheticEvent); } catch (e) { // If no active manager has been initialized, we assume the trace engine is @@ -53,24 +53,24 @@ export class SyntheticEventsManager { * be created with this method to ensure they are registered and made * available to load events using serialized keys. */ - registerSyntheticBasedEvent(syntheticEvent) { + registerSyntheticEvent(syntheticEvent) { const rawIndex = this.#rawTraceEvents.indexOf(syntheticEvent.rawSourceEvent); if (rawIndex < 0) { throw new Error('Attempted to register a synthetic event paired to an unknown raw event.'); } const eventAsSynthetic = syntheticEvent; - this.#syntheticTraceEvents[rawIndex] = eventAsSynthetic; + this.#syntheticTraces[rawIndex] = eventAsSynthetic; return eventAsSynthetic; } syntheticEventForRawEventIndex(rawEventIndex) { - const syntheticEvent = this.#syntheticTraceEvents.at(rawEventIndex); + const syntheticEvent = this.#syntheticTraces.at(rawEventIndex); if (!syntheticEvent) { throw new Error(`Attempted to get a synthetic event from an unknown raw event index: ${rawEventIndex}`); } return syntheticEvent; } - getSyntheticTraceEvents() { - return this.#syntheticTraceEvents; + getSyntheticTraces() { + return this.#syntheticTraces; } getRawTraceEvents() { return this.#rawTraceEvents; diff --git a/public/models/trace/helpers/SyntheticEvents.js.map b/public/models/trace/helpers/SyntheticEvents.js.map index b1064825b..6f59cd821 100644 --- a/public/models/trace/helpers/SyntheticEvents.js.map +++ b/public/models/trace/helpers/SyntheticEvents.js.map @@ -1 +1 @@ -{"version":3,"file":"SyntheticEvents.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/SyntheticEvents.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAI7B,IAAI,aAAa,GAAgC,IAAI,CAAC;AAEtD,MAAM,OAAO,sBAAsB;IACjC;;;OAGG;IACH,qBAAqB,GAA4C,EAAE,CAAC;IACpE;;OAEG;IACH,eAAe,GAAgD,EAAE,CAAC;IAElE,MAAM,CAAC,QAAQ,CAAC,OAA+B;QAC7C,aAAa,GAAG,OAAO,CAAC;IAC1B,CAAC;IAED,MAAM,CAAC,iBAAiB,CAAC,SAAsD;QAC7E,MAAM,OAAO,GAAG,IAAI,sBAAsB,CAAC,SAAS,CAAC,CAAC;QACtD,sBAAsB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACzC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,CAAC,gBAAgB;QACrB,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;QACpF,CAAC;QACD,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,MAAM,CAAC,KAAK;QACV,aAAa,GAAG,IAAI,CAAC;IACvB,CAAC;IAED,MAAM,CAAC,2BAA2B,CAAkD,cAA+B;QAEjH,IAAI,CAAC;YACH,OAAO,sBAAsB,CAAC,gBAAgB,EAAE,CAAC,2BAA2B,CAAC,cAAc,CAAC,CAAC;QAC/F,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,2EAA2E;YAC3E,sEAAsE;YACtE,sEAAsE;YACtE,+BAA+B;YAC/B,OAAO,cAAmB,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,MAAM,CAAC,oBAAoB,CAAC,cAAqE;QAE/F,uCAAuC;QACvC,OAAO,cAAyD,CAAC;IACnE,CAAC;IAED,YAAoB,SAAsD;QACxE,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;IACnC,CAAC;IAED;;;;OAIG;IACH,2BAA2B,CAAkD,cAA+B;QAC1G,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;QAC7E,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,yEAAyE,CAAC,CAAC;QAC7F,CAAC;QACD,MAAM,gBAAgB,GAAG,cAAmB,CAAC;QAC7C,IAAI,CAAC,qBAAqB,CAAC,QAAQ,CAAC,GAAG,gBAAgB,CAAC;QACxD,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,8BAA8B,CAAC,aAAqB;QAClD,MAAM,cAAc,GAAG,IAAI,CAAC,qBAAqB,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC;QACpE,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,uEAAuE,aAAa,EAAE,CAAC,CAAC;QAC1G,CAAC;QACD,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,uBAAuB;QACrB,OAAO,IAAI,CAAC,qBAAqB,CAAC;IACpC,CAAC;IAED,iBAAiB;QACf,OAAO,IAAI,CAAC,eAAe,CAAC;IAC9B,CAAC;CACF","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Types from '../types/types.js';\n\nlet activeManager: SyntheticEventsManager|null = null;\n\nexport class SyntheticEventsManager {\n /**\n * All synthetic entries created in a trace from a corresponding trace events.\n * (ProfileCalls are excluded because they are not based on a real trace event)\n */\n #syntheticTraceEvents: Types.TraceEvents.SyntheticBasedEvent[] = [];\n /**\n * All raw entries from a trace.\n */\n #rawTraceEvents: readonly Types.TraceEvents.TraceEventData[] = [];\n\n static activate(manager: SyntheticEventsManager): void {\n activeManager = manager;\n }\n\n static createAndActivate(rawEvents: readonly Types.TraceEvents.TraceEventData[]): SyntheticEventsManager {\n const manager = new SyntheticEventsManager(rawEvents);\n SyntheticEventsManager.activate(manager);\n return manager;\n }\n\n static getActiveManager(): SyntheticEventsManager {\n if (!activeManager) {\n throw new Error('Attempted to get a SyntheticEventsManager without initializing');\n }\n return activeManager;\n }\n\n static reset(): void {\n activeManager = null;\n }\n\n static registerSyntheticBasedEvent(syntheticEvent: Omit):\n T {\n try {\n return SyntheticEventsManager.getActiveManager().registerSyntheticBasedEvent(syntheticEvent);\n } catch (e) {\n // If no active manager has been initialized, we assume the trace engine is\n // not running as part of the Performance panel. In this case we don't\n // register synthetic events because we don't need to support timeline\n // modifications serialization.\n return syntheticEvent as T;\n }\n }\n\n static registerServerTiming(syntheticEvent: Omit):\n Types.TraceEvents.SyntheticServerTiming {\n // TODO(crbug.com/340811171): Implement\n return syntheticEvent as Types.TraceEvents.SyntheticServerTiming;\n }\n\n private constructor(rawEvents: readonly Types.TraceEvents.TraceEventData[]) {\n this.#rawTraceEvents = rawEvents;\n }\n\n /**\n * Registers and returns a branded synthetic event. Synthetic events need to\n * be created with this method to ensure they are registered and made\n * available to load events using serialized keys.\n */\n registerSyntheticBasedEvent(syntheticEvent: Omit): T {\n const rawIndex = this.#rawTraceEvents.indexOf(syntheticEvent.rawSourceEvent);\n if (rawIndex < 0) {\n throw new Error('Attempted to register a synthetic event paired to an unknown raw event.');\n }\n const eventAsSynthetic = syntheticEvent as T;\n this.#syntheticTraceEvents[rawIndex] = eventAsSynthetic;\n return eventAsSynthetic;\n }\n\n syntheticEventForRawEventIndex(rawEventIndex: number): Types.TraceEvents.SyntheticBasedEvent {\n const syntheticEvent = this.#syntheticTraceEvents.at(rawEventIndex);\n if (!syntheticEvent) {\n throw new Error(`Attempted to get a synthetic event from an unknown raw event index: ${rawEventIndex}`);\n }\n return syntheticEvent;\n }\n\n getSyntheticTraceEvents(): Types.TraceEvents.SyntheticBasedEvent[] {\n return this.#syntheticTraceEvents;\n }\n\n getRawTraceEvents(): readonly Types.TraceEvents.TraceEventData[] {\n return this.#rawTraceEvents;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"SyntheticEvents.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/SyntheticEvents.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAI7B,IAAI,aAAa,GAAgC,IAAI,CAAC;AAEtD,MAAM,OAAO,sBAAsB;IACjC;;;OAGG;IACH,gBAAgB,GAAkC,EAAE,CAAC;IACrD;;OAEG;IACH,eAAe,GAAkC,EAAE,CAAC;IAEpD,MAAM,CAAC,QAAQ,CAAC,OAA+B;QAC7C,aAAa,GAAG,OAAO,CAAC;IAC1B,CAAC;IAED,MAAM,CAAC,iBAAiB,CAAC,SAAwC;QAC/D,MAAM,OAAO,GAAG,IAAI,sBAAsB,CAAC,SAAS,CAAC,CAAC;QACtD,sBAAsB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACzC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM,CAAC,gBAAgB;QACrB,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,gEAAgE,CAAC,CAAC;QACpF,CAAC;QACD,OAAO,aAAa,CAAC;IACvB,CAAC;IAED,MAAM,CAAC,KAAK;QACV,aAAa,GAAG,IAAI,CAAC;IACvB,CAAC;IAED,MAAM,CAAC,sBAAsB,CAAwC,cAA+B;QAClG,IAAI,CAAC;YACH,OAAO,sBAAsB,CAAC,gBAAgB,EAAE,CAAC,sBAAsB,CAAC,cAAc,CAAC,CAAC;QAC1F,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,2EAA2E;YAC3E,sEAAsE;YACtE,sEAAsE;YACtE,+BAA+B;YAC/B,OAAO,cAAmB,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,MAAM,CAAC,oBAAoB,CAAC,cAAgE;QAE1F,uCAAuC;QACvC,OAAO,cAAoD,CAAC;IAC9D,CAAC;IAED,YAAoB,SAAwC;QAC1D,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;IACnC,CAAC;IAED;;;;OAIG;IACH,sBAAsB,CAAwC,cAA+B;QAC3F,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;QAC7E,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,yEAAyE,CAAC,CAAC;QAC7F,CAAC;QACD,MAAM,gBAAgB,GAAG,cAAmB,CAAC;QAC7C,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,GAAG,gBAAgB,CAAC;QACnD,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,8BAA8B,CAAC,aAAqB;QAClD,MAAM,cAAc,GAAG,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC;QAC/D,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,uEAAuE,aAAa,EAAE,CAAC,CAAC;QAC1G,CAAC;QACD,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,kBAAkB;QAChB,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC/B,CAAC;IAED,iBAAiB;QACf,OAAO,IAAI,CAAC,eAAe,CAAC;IAC9B,CAAC;CACF","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Types from '../types/types.js';\n\nlet activeManager: SyntheticEventsManager|null = null;\n\nexport class SyntheticEventsManager {\n /**\n * All synthetic entries created in a trace from a corresponding trace events.\n * (ProfileCalls are excluded because they are not based on a real trace event)\n */\n #syntheticTraces: Types.Events.SyntheticBased[] = [];\n /**\n * All raw entries from a trace.\n */\n #rawTraceEvents: readonly Types.Events.Event[] = [];\n\n static activate(manager: SyntheticEventsManager): void {\n activeManager = manager;\n }\n\n static createAndActivate(rawEvents: readonly Types.Events.Event[]): SyntheticEventsManager {\n const manager = new SyntheticEventsManager(rawEvents);\n SyntheticEventsManager.activate(manager);\n return manager;\n }\n\n static getActiveManager(): SyntheticEventsManager {\n if (!activeManager) {\n throw new Error('Attempted to get a SyntheticEventsManager without initializing');\n }\n return activeManager;\n }\n\n static reset(): void {\n activeManager = null;\n }\n\n static registerSyntheticEvent(syntheticEvent: Omit): T {\n try {\n return SyntheticEventsManager.getActiveManager().registerSyntheticEvent(syntheticEvent);\n } catch (e) {\n // If no active manager has been initialized, we assume the trace engine is\n // not running as part of the Performance panel. In this case we don't\n // register synthetic events because we don't need to support timeline\n // modifications serialization.\n return syntheticEvent as T;\n }\n }\n\n static registerServerTiming(syntheticEvent: Omit):\n Types.Events.SyntheticServerTiming {\n // TODO(crbug.com/340811171): Implement\n return syntheticEvent as Types.Events.SyntheticServerTiming;\n }\n\n private constructor(rawEvents: readonly Types.Events.Event[]) {\n this.#rawTraceEvents = rawEvents;\n }\n\n /**\n * Registers and returns a branded synthetic event. Synthetic events need to\n * be created with this method to ensure they are registered and made\n * available to load events using serialized keys.\n */\n registerSyntheticEvent(syntheticEvent: Omit): T {\n const rawIndex = this.#rawTraceEvents.indexOf(syntheticEvent.rawSourceEvent);\n if (rawIndex < 0) {\n throw new Error('Attempted to register a synthetic event paired to an unknown raw event.');\n }\n const eventAsSynthetic = syntheticEvent as T;\n this.#syntheticTraces[rawIndex] = eventAsSynthetic;\n return eventAsSynthetic;\n }\n\n syntheticEventForRawEventIndex(rawEventIndex: number): Types.Events.SyntheticBased {\n const syntheticEvent = this.#syntheticTraces.at(rawEventIndex);\n if (!syntheticEvent) {\n throw new Error(`Attempted to get a synthetic event from an unknown raw event index: ${rawEventIndex}`);\n }\n return syntheticEvent;\n }\n\n getSyntheticTraces(): Types.Events.SyntheticBased[] {\n return this.#syntheticTraces;\n }\n\n getRawTraceEvents(): readonly Types.Events.Event[] {\n return this.#rawTraceEvents;\n }\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/helpers/SyntheticEvents.test.js b/public/models/trace/helpers/SyntheticEvents.test.js index fca1ad7a8..b963de8c1 100644 --- a/public/models/trace/helpers/SyntheticEvents.test.js +++ b/public/models/trace/helpers/SyntheticEvents.test.js @@ -2,51 +2,49 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import { TraceLoader } from '../../../testing/TraceLoader.js'; -import * as TraceModel from '../trace.js'; +import * as Trace from '../trace.js'; describe('SyntheticEvents', function () { beforeEach(() => { - TraceModel.Helpers.SyntheticEvents.SyntheticEventsManager.reset(); + Trace.Helpers.SyntheticEvents.SyntheticEventsManager.reset(); }); afterEach(() => { - TraceModel.Helpers.SyntheticEvents.SyntheticEventsManager.reset(); + Trace.Helpers.SyntheticEvents.SyntheticEventsManager.reset(); }); describe('Initialization', function () { it('does not throw when invoking getActiveManager after executing the trace engine', async function () { const events = await TraceLoader.fixtureContents(this, 'basic.json.gz'); await TraceLoader.executeTraceEngineOnFileContents(events); - assert.doesNotThrow(TraceModel.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager); + assert.doesNotThrow(Trace.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager); }); it('activates the latest trace manager but can then activate an alternative manager', async function () { // Exact traces do not matter, as long as they are different const events1 = await TraceLoader.rawEvents(this, 'basic.json.gz'); const events2 = await TraceLoader.rawEvents(this, 'basic-stack.json.gz'); - const manager1 = TraceModel.Helpers.SyntheticEvents.SyntheticEventsManager.createAndActivate(events1); - const manager2 = TraceModel.Helpers.SyntheticEvents.SyntheticEventsManager.createAndActivate(events2); + const manager1 = Trace.Helpers.SyntheticEvents.SyntheticEventsManager.createAndActivate(events1); + const manager2 = Trace.Helpers.SyntheticEvents.SyntheticEventsManager.createAndActivate(events2); // Manager2 is active as it was the last one to be initialized - assert.strictEqual(TraceModel.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager(), manager2); - TraceModel.Helpers.SyntheticEvents.SyntheticEventsManager.activate(manager1); - assert.strictEqual(TraceModel.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager(), manager1); + assert.strictEqual(Trace.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager(), manager2); + Trace.Helpers.SyntheticEvents.SyntheticEventsManager.activate(manager1); + assert.strictEqual(Trace.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager(), manager1); }); }); - describe('SyntheticBasedEvent registration', () => { + describe('SyntheticBased registration', () => { it('stores synthetic based events at the same index as their corresponding raw event in the source array', async function () { const contents = await TraceLoader.fixtureContents(this, 'web-dev.json.gz'); - const rawEvents = 'traceEvents' in contents ? - contents.traceEvents : - contents; - const { traceData } = await TraceLoader.executeTraceEngineOnFileContents(rawEvents); + const rawEvents = 'traceEvents' in contents ? contents.traceEvents : contents; + const { parsedTrace } = await TraceLoader.executeTraceEngineOnFileContents(rawEvents); const allSyntheticEvents = [ - ...traceData.Animations.animations, - ...traceData.NetworkRequests.byTime, - ...traceData.Screenshots, + ...parsedTrace.Animations.animations, + ...parsedTrace.NetworkRequests.byTime, + ...parsedTrace.Screenshots, ]; - const syntheticEventsManager = TraceModel.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager(); + const syntheticEventsManager = Trace.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager(); for (const syntheticEvent of allSyntheticEvents) { const rawEventIndex = rawEvents.indexOf(syntheticEvent.rawSourceEvent); // Test synthetic events are stored in the correct position. assert.strictEqual(syntheticEventsManager.syntheticEventForRawEventIndex(rawEventIndex), syntheticEvent); } - const allSyntheticEventsInManagerCount = syntheticEventsManager.getSyntheticTraceEvents().reduce((count, event) => event !== undefined ? (count + 1) : 0, 0); + const allSyntheticEventsInManagerCount = syntheticEventsManager.getSyntheticTraces().reduce((count, event) => event !== undefined ? (count + 1) : 0, 0); // Test synthetic events are stored only once. assert.strictEqual(allSyntheticEventsInManagerCount, allSyntheticEvents.length); }); diff --git a/public/models/trace/helpers/SyntheticEvents.test.js.map b/public/models/trace/helpers/SyntheticEvents.test.js.map index 2c1354f6b..ea2e90ba3 100644 --- a/public/models/trace/helpers/SyntheticEvents.test.js.map +++ b/public/models/trace/helpers/SyntheticEvents.test.js.map @@ -1 +1 @@ -{"version":3,"file":"SyntheticEvents.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/SyntheticEvents.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,EAAC,WAAW,EAAC,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,UAAU,MAAM,aAAa,CAAC;AAE1C,QAAQ,CAAC,iBAAiB,EAAE;IAC1B,UAAU,CAAC,GAAG,EAAE;QACd,UAAU,CAAC,OAAO,CAAC,eAAe,CAAC,sBAAsB,CAAC,KAAK,EAAE,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,UAAU,CAAC,OAAO,CAAC,eAAe,CAAC,sBAAsB,CAAC,KAAK,EAAE,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,gBAAgB,EAAE;QACzB,EAAE,CAAC,gFAAgF,EAAE,KAAK;YACxF,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,eAAe,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;YACxE,MAAM,WAAW,CAAC,gCAAgC,CAAC,MAAM,CAAC,CAAC;YAC3D,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,OAAO,CAAC,eAAe,CAAC,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;QAClG,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iFAAiF,EAAE,KAAK;YACzF,4DAA4D;YAC5D,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,IAAI,EAAE,eAAe,CAAC,CAAC;YACnE,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,SAAS,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC;YAEzE,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,eAAe,CAAC,sBAAsB,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;YACtG,MAAM,QAAQ,GAAG,UAAU,CAAC,OAAO,CAAC,eAAe,CAAC,sBAAsB,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;YAEtG,8DAA8D;YAC9D,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC,eAAe,CAAC,sBAAsB,CAAC,gBAAgB,EAAE,EAAE,QAAQ,CAAC,CAAC;YAC3G,UAAU,CAAC,OAAO,CAAC,eAAe,CAAC,sBAAsB,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAC7E,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC,eAAe,CAAC,sBAAsB,CAAC,gBAAgB,EAAE,EAAE,QAAQ,CAAC,CAAC;QAC7G,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAChD,EAAE,CAAC,sGAAsG,EACtG,KAAK;YACH,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,eAAe,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC5E,MAAM,SAAS,GAAG,aAAa,IAAI,QAAQ,CAAC,CAAC;gBACzC,QAAQ,CAAC,WAA4D,CAAC,CAAC;gBACvE,QAAQ,CAAC;YACb,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,WAAW,CAAC,gCAAgC,CAAC,SAAS,CAAC,CAAC;YAClF,MAAM,kBAAkB,GAAG;gBACzB,GAAG,SAAS,CAAC,UAAU,CAAC,UAAU;gBAClC,GAAG,SAAS,CAAC,eAAe,CAAC,MAAM;gBACnC,GAAG,SAAS,CAAC,WAAW;aACzB,CAAC;YACF,MAAM,sBAAsB,GAAG,UAAU,CAAC,OAAO,CAAC,eAAe,CAAC,sBAAsB,CAAC,gBAAgB,EAAE,CAAC;YAC5G,KAAK,MAAM,cAAc,IAAI,kBAAkB,EAAE,CAAC;gBAChD,MAAM,aAAa,GAAG,SAAS,CAAC,OAAO,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;gBACvE,4DAA4D;gBAC5D,MAAM,CAAC,WAAW,CAAC,sBAAsB,CAAC,8BAA8B,CAAC,aAAa,CAAC,EAAE,cAAc,CAAC,CAAC;YAC3G,CAAC;YACD,MAAM,gCAAgC,GAAG,sBAAsB,CAAC,uBAAuB,EAAE,CAAC,MAAM,CAC5F,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAChE,8CAA8C;YAC9C,MAAM,CAAC,WAAW,CAAC,gCAAgC,EAAE,kBAAkB,CAAC,MAAM,CAAC,CAAC;QAClF,CAAC,CAAC,CAAC;IACR,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as TraceModel from '../trace.js';\n\ndescribe('SyntheticEvents', function() {\n beforeEach(() => {\n TraceModel.Helpers.SyntheticEvents.SyntheticEventsManager.reset();\n });\n\n afterEach(() => {\n TraceModel.Helpers.SyntheticEvents.SyntheticEventsManager.reset();\n });\n\n describe('Initialization', function() {\n it('does not throw when invoking getActiveManager after executing the trace engine', async function() {\n const events = await TraceLoader.fixtureContents(this, 'basic.json.gz');\n await TraceLoader.executeTraceEngineOnFileContents(events);\n assert.doesNotThrow(TraceModel.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager);\n });\n\n it('activates the latest trace manager but can then activate an alternative manager', async function() {\n // Exact traces do not matter, as long as they are different\n const events1 = await TraceLoader.rawEvents(this, 'basic.json.gz');\n const events2 = await TraceLoader.rawEvents(this, 'basic-stack.json.gz');\n\n const manager1 = TraceModel.Helpers.SyntheticEvents.SyntheticEventsManager.createAndActivate(events1);\n const manager2 = TraceModel.Helpers.SyntheticEvents.SyntheticEventsManager.createAndActivate(events2);\n\n // Manager2 is active as it was the last one to be initialized\n assert.strictEqual(TraceModel.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager(), manager2);\n TraceModel.Helpers.SyntheticEvents.SyntheticEventsManager.activate(manager1);\n assert.strictEqual(TraceModel.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager(), manager1);\n });\n });\n\n describe('SyntheticBasedEvent registration', () => {\n it('stores synthetic based events at the same index as their corresponding raw event in the source array',\n async function() {\n const contents = await TraceLoader.fixtureContents(this, 'web-dev.json.gz');\n const rawEvents = 'traceEvents' in contents ?\n contents.traceEvents as TraceModel.Types.TraceEvents.TraceEventData[] :\n contents;\n const {traceData} = await TraceLoader.executeTraceEngineOnFileContents(rawEvents);\n const allSyntheticEvents = [\n ...traceData.Animations.animations,\n ...traceData.NetworkRequests.byTime,\n ...traceData.Screenshots,\n ];\n const syntheticEventsManager = TraceModel.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager();\n for (const syntheticEvent of allSyntheticEvents) {\n const rawEventIndex = rawEvents.indexOf(syntheticEvent.rawSourceEvent);\n // Test synthetic events are stored in the correct position.\n assert.strictEqual(syntheticEventsManager.syntheticEventForRawEventIndex(rawEventIndex), syntheticEvent);\n }\n const allSyntheticEventsInManagerCount = syntheticEventsManager.getSyntheticTraceEvents().reduce(\n (count, event) => event !== undefined ? (count + 1) : 0, 0);\n // Test synthetic events are stored only once.\n assert.strictEqual(allSyntheticEventsInManagerCount, allSyntheticEvents.length);\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"SyntheticEvents.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/SyntheticEvents.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Trace from '../trace.js';\n\ndescribe('SyntheticEvents', function() {\n beforeEach(() => {\n Trace.Helpers.SyntheticEvents.SyntheticEventsManager.reset();\n });\n\n afterEach(() => {\n Trace.Helpers.SyntheticEvents.SyntheticEventsManager.reset();\n });\n\n describe('Initialization', function() {\n it('does not throw when invoking getActiveManager after executing the trace engine', async function() {\n const events = await TraceLoader.fixtureContents(this, 'basic.json.gz');\n await TraceLoader.executeTraceEngineOnFileContents(events);\n assert.doesNotThrow(Trace.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager);\n });\n\n it('activates the latest trace manager but can then activate an alternative manager', async function() {\n // Exact traces do not matter, as long as they are different\n const events1 = await TraceLoader.rawEvents(this, 'basic.json.gz');\n const events2 = await TraceLoader.rawEvents(this, 'basic-stack.json.gz');\n\n const manager1 = Trace.Helpers.SyntheticEvents.SyntheticEventsManager.createAndActivate(events1);\n const manager2 = Trace.Helpers.SyntheticEvents.SyntheticEventsManager.createAndActivate(events2);\n\n // Manager2 is active as it was the last one to be initialized\n assert.strictEqual(Trace.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager(), manager2);\n Trace.Helpers.SyntheticEvents.SyntheticEventsManager.activate(manager1);\n assert.strictEqual(Trace.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager(), manager1);\n });\n });\n\n describe('SyntheticBased registration', () => {\n it('stores synthetic based events at the same index as their corresponding raw event in the source array',\n async function() {\n const contents = await TraceLoader.fixtureContents(this, 'web-dev.json.gz');\n const rawEvents = 'traceEvents' in contents ? contents.traceEvents as Trace.Types.Events.Event[] : contents;\n const {parsedTrace} = await TraceLoader.executeTraceEngineOnFileContents(rawEvents);\n const allSyntheticEvents = [\n ...parsedTrace.Animations.animations,\n ...parsedTrace.NetworkRequests.byTime,\n ...parsedTrace.Screenshots,\n ];\n const syntheticEventsManager = Trace.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager();\n for (const syntheticEvent of allSyntheticEvents) {\n const rawEventIndex = rawEvents.indexOf(syntheticEvent.rawSourceEvent);\n // Test synthetic events are stored in the correct position.\n assert.strictEqual(syntheticEventsManager.syntheticEventForRawEventIndex(rawEventIndex), syntheticEvent);\n }\n const allSyntheticEventsInManagerCount = syntheticEventsManager.getSyntheticTraces().reduce(\n (count, event) => event !== undefined ? (count + 1) : 0, 0);\n // Test synthetic events are stored only once.\n assert.strictEqual(allSyntheticEventsInManagerCount, allSyntheticEvents.length);\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/helpers/Timing.d.ts b/public/models/trace/helpers/Timing.d.ts index 7b6c42839..7c235e90d 100644 --- a/public/models/trace/helpers/Timing.d.ts +++ b/public/models/trace/helpers/Timing.d.ts @@ -4,16 +4,16 @@ export declare const secondsToMilliseconds: (value: Types.Timing.Seconds) => Typ export declare const secondsToMicroseconds: (value: Types.Timing.Seconds) => Types.Timing.MicroSeconds; export declare const microSecondsToMilliseconds: (value: Types.Timing.MicroSeconds) => Types.Timing.MilliSeconds; export declare const microSecondsToSeconds: (value: Types.Timing.MicroSeconds) => Types.Timing.Seconds; -export declare function timeStampForEventAdjustedByClosestNavigation(event: Types.TraceEvents.TraceEventData, traceBounds: Types.Timing.TraceWindowMicroSeconds, navigationsByNavigationId: Map, navigationsByFrameId: Map): Types.Timing.MicroSeconds; +export declare function timeStampForEventAdjustedByClosestNavigation(event: Types.Events.Event, traceBounds: Types.Timing.TraceWindowMicroSeconds, navigationsByNavigationId: Map, navigationsByFrameId: Map): Types.Timing.MicroSeconds; export declare function expandWindowByPercentOrToOneMillisecond(annotationWindow: Types.Timing.TraceWindowMicroSeconds, maxTraceWindow: Types.Timing.TraceWindowMicroSeconds, percentage: number): Types.Timing.TraceWindowMicroSeconds; export interface EventTimingsData { startTime: ValueType; endTime: ValueType; duration: ValueType; } -export declare function eventTimingsMicroSeconds(event: Types.TraceEvents.TraceEventData): EventTimingsData; -export declare function eventTimingsMilliSeconds(event: Types.TraceEvents.TraceEventData): EventTimingsData; -export declare function eventTimingsSeconds(event: Types.TraceEvents.TraceEventData): EventTimingsData; +export declare function eventTimingsMicroSeconds(event: Types.Events.Event): EventTimingsData; +export declare function eventTimingsMilliSeconds(event: Types.Events.Event): EventTimingsData; +export declare function eventTimingsSeconds(event: Types.Events.Event): EventTimingsData; export declare function traceWindowMilliSeconds(bounds: Types.Timing.TraceWindowMicroSeconds): Types.Timing.TraceWindowMilliSeconds; export declare function traceWindowMillisecondsToMicroSeconds(bounds: Types.Timing.TraceWindowMilliSeconds): Types.Timing.TraceWindowMicroSeconds; export declare function traceWindowFromMilliSeconds(min: Types.Timing.MilliSeconds, max: Types.Timing.MilliSeconds): Types.Timing.TraceWindowMicroSeconds; @@ -36,7 +36,7 @@ export interface BoundsIncludeTimeRange { */ export declare function boundsIncludeTimeRange(data: BoundsIncludeTimeRange): boolean; /** Checks to see if the event is within or overlaps the bounds */ -export declare function eventIsInBounds(event: Types.TraceEvents.TraceEventData, bounds: Types.Timing.TraceWindowMicroSeconds): boolean; +export declare function eventIsInBounds(event: Types.Events.Event, bounds: Types.Timing.TraceWindowMicroSeconds): boolean; export declare function timestampIsInBounds(bounds: Types.Timing.TraceWindowMicroSeconds, timestamp: Types.Timing.MicroSeconds): boolean; export interface WindowFitsInsideBounds { window: Types.Timing.TraceWindowMicroSeconds; diff --git a/public/models/trace/helpers/Timing.js.map b/public/models/trace/helpers/Timing.js.map index a208af34e..34ce60694 100644 --- a/public/models/trace/helpers/Timing.js.map +++ b/public/models/trace/helpers/Timing.js.map @@ -1 +1 @@ -{"version":3,"file":"Timing.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/Timing.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Types from '../types/types.js';\n\nimport {getNavigationForTraceEvent} from './Trace.js';\n\nexport const millisecondsToMicroseconds = (value: Types.Timing.MilliSeconds): Types.Timing.MicroSeconds =>\n Types.Timing.MicroSeconds(value * 1000);\n\nexport const secondsToMilliseconds = (value: Types.Timing.Seconds): Types.Timing.MilliSeconds =>\n Types.Timing.MilliSeconds(value * 1000);\n\nexport const secondsToMicroseconds = (value: Types.Timing.Seconds): Types.Timing.MicroSeconds =>\n millisecondsToMicroseconds(secondsToMilliseconds(value));\n\nexport const microSecondsToMilliseconds = (value: Types.Timing.MicroSeconds): Types.Timing.MilliSeconds =>\n Types.Timing.MilliSeconds(value / 1000);\n\nexport const microSecondsToSeconds = (value: Types.Timing.MicroSeconds): Types.Timing.Seconds =>\n Types.Timing.Seconds(value / 1000 / 1000);\n\nexport function timeStampForEventAdjustedByClosestNavigation(\n event: Types.TraceEvents.TraceEventData,\n traceBounds: Types.Timing.TraceWindowMicroSeconds,\n navigationsByNavigationId: Map,\n navigationsByFrameId: Map,\n ): Types.Timing.MicroSeconds {\n let eventTimeStamp = event.ts - traceBounds.min;\n if (event.args?.data?.navigationId) {\n const navigationForEvent = navigationsByNavigationId.get(event.args.data.navigationId);\n if (navigationForEvent) {\n eventTimeStamp = event.ts - navigationForEvent.ts;\n }\n } else if (event.args?.data?.frame) {\n const navigationForEvent = getNavigationForTraceEvent(event, event.args.data.frame, navigationsByFrameId);\n if (navigationForEvent) {\n eventTimeStamp = event.ts - navigationForEvent.ts;\n }\n }\n return Types.Timing.MicroSeconds(eventTimeStamp);\n}\n\n// Expands the trace window by a provided percentage or, if it the expanded window is smaller than 1 millisecond, expands it to 1 millisecond.\n// If the expanded window is outside of the max trace window, cut the overflowing bound to the max trace window bound.\nexport function expandWindowByPercentOrToOneMillisecond(\n annotationWindow: Types.Timing.TraceWindowMicroSeconds, maxTraceWindow: Types.Timing.TraceWindowMicroSeconds,\n percentage: number): Types.Timing.TraceWindowMicroSeconds {\n // Expand min and max of the window by half of the provided percentage. That way, in total, the window will be expanded by the provided percentage.\n let newMin = annotationWindow.min - annotationWindow.range * (percentage / 100) / 2;\n let newMax = annotationWindow.max + annotationWindow.range * (percentage / 100) / 2;\n\n if (newMax - newMin < 1_000) {\n const rangeMiddle = (annotationWindow.min + annotationWindow.max) / 2;\n newMin = rangeMiddle - 500;\n newMax = rangeMiddle + 500;\n }\n\n newMin = Math.max(newMin, maxTraceWindow.min);\n newMax = Math.min(newMax, maxTraceWindow.max);\n\n const expandedWindow: Types.Timing.TraceWindowMicroSeconds = {\n min: Types.Timing.MicroSeconds(newMin),\n max: Types.Timing.MicroSeconds(newMax),\n range: Types.Timing.MicroSeconds(newMax - newMin),\n };\n\n return expandedWindow;\n}\n\nexport interface EventTimingsData<\n ValueType extends Types.Timing.MicroSeconds|Types.Timing.MilliSeconds|Types.Timing.Seconds,\n> {\n startTime: ValueType;\n endTime: ValueType;\n duration: ValueType;\n}\n\nexport function eventTimingsMicroSeconds(event: Types.TraceEvents.TraceEventData):\n EventTimingsData {\n return {\n startTime: event.ts,\n endTime: Types.Timing.MicroSeconds(event.ts + (event.dur ?? Types.Timing.MicroSeconds(0))),\n duration: Types.Timing.MicroSeconds(event.dur || 0),\n };\n}\nexport function eventTimingsMilliSeconds(event: Types.TraceEvents.TraceEventData):\n EventTimingsData {\n const microTimes = eventTimingsMicroSeconds(event);\n return {\n startTime: microSecondsToMilliseconds(microTimes.startTime),\n endTime: microSecondsToMilliseconds(microTimes.endTime),\n duration: microSecondsToMilliseconds(microTimes.duration),\n };\n}\nexport function eventTimingsSeconds(event: Types.TraceEvents.TraceEventData): EventTimingsData {\n const microTimes = eventTimingsMicroSeconds(event);\n return {\n startTime: microSecondsToSeconds(microTimes.startTime),\n endTime: microSecondsToSeconds(microTimes.endTime),\n duration: microSecondsToSeconds(microTimes.duration),\n };\n}\n\nexport function traceWindowMilliSeconds(bounds: Types.Timing.TraceWindowMicroSeconds):\n Types.Timing.TraceWindowMilliSeconds {\n return {\n min: microSecondsToMilliseconds(bounds.min),\n max: microSecondsToMilliseconds(bounds.max),\n range: microSecondsToMilliseconds(bounds.range),\n };\n}\n\nexport function traceWindowMillisecondsToMicroSeconds(bounds: Types.Timing.TraceWindowMilliSeconds):\n Types.Timing.TraceWindowMicroSeconds {\n return {\n min: millisecondsToMicroseconds(bounds.min),\n max: millisecondsToMicroseconds(bounds.max),\n range: millisecondsToMicroseconds(bounds.range),\n };\n}\n\nexport function traceWindowFromMilliSeconds(\n min: Types.Timing.MilliSeconds, max: Types.Timing.MilliSeconds): Types.Timing.TraceWindowMicroSeconds {\n const traceWindow: Types.Timing.TraceWindowMicroSeconds = {\n min: millisecondsToMicroseconds(min),\n max: millisecondsToMicroseconds(max),\n range: Types.Timing.MicroSeconds(millisecondsToMicroseconds(max) - millisecondsToMicroseconds(min)),\n };\n return traceWindow;\n}\n\nexport function traceWindowFromMicroSeconds(\n min: Types.Timing.MicroSeconds, max: Types.Timing.MicroSeconds): Types.Timing.TraceWindowMicroSeconds {\n const traceWindow: Types.Timing.TraceWindowMicroSeconds = {\n min,\n max,\n range: Types.Timing.MicroSeconds(max - min),\n };\n return traceWindow;\n}\n\nexport interface BoundsIncludeTimeRange {\n timeRange: Types.Timing.TraceWindowMicroSeconds;\n bounds: Types.Timing.TraceWindowMicroSeconds;\n}\n\n/**\n * Checks to see if the timeRange is within the bounds. By \"within\" we mean\n * \"has any overlap\":\n * |------------------------|\n * == no overlap (entirely before)\n * ========= overlap\n * ========= overlap\n * ========= overlap\n * ==== no overlap (entirely after)\n * ============================== overlap (time range is larger than bounds)\n * |------------------------|\n */\nexport function boundsIncludeTimeRange(data: BoundsIncludeTimeRange): boolean {\n const {min: visibleMin, max: visibleMax} = data.bounds;\n const {min: rangeMin, max: rangeMax} = data.timeRange;\n\n return visibleMin <= rangeMax && visibleMax >= rangeMin;\n}\n\n/** Checks to see if the event is within or overlaps the bounds */\nexport function eventIsInBounds(\n event: Types.TraceEvents.TraceEventData, bounds: Types.Timing.TraceWindowMicroSeconds): boolean {\n const startTime = event.ts;\n return startTime <= bounds.max && bounds.min <= (startTime + (event.dur ?? 0));\n}\n\nexport function timestampIsInBounds(\n bounds: Types.Timing.TraceWindowMicroSeconds, timestamp: Types.Timing.MicroSeconds): boolean {\n return timestamp >= bounds.min && timestamp <= bounds.max;\n}\n\nexport interface WindowFitsInsideBounds {\n window: Types.Timing.TraceWindowMicroSeconds;\n bounds: Types.Timing.TraceWindowMicroSeconds;\n}\nexport function windowFitsInsideBounds(data: WindowFitsInsideBounds): boolean {\n return data.window.min >= data.bounds.min && data.window.max <= data.bounds.max;\n}\n"]} \ No newline at end of file +{"version":3,"file":"Timing.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/Timing.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Types from '../types/types.js';\n\nimport {getNavigationForTraceEvent} from './Trace.js';\n\nexport const millisecondsToMicroseconds = (value: Types.Timing.MilliSeconds): Types.Timing.MicroSeconds =>\n Types.Timing.MicroSeconds(value * 1000);\n\nexport const secondsToMilliseconds = (value: Types.Timing.Seconds): Types.Timing.MilliSeconds =>\n Types.Timing.MilliSeconds(value * 1000);\n\nexport const secondsToMicroseconds = (value: Types.Timing.Seconds): Types.Timing.MicroSeconds =>\n millisecondsToMicroseconds(secondsToMilliseconds(value));\n\nexport const microSecondsToMilliseconds = (value: Types.Timing.MicroSeconds): Types.Timing.MilliSeconds =>\n Types.Timing.MilliSeconds(value / 1000);\n\nexport const microSecondsToSeconds = (value: Types.Timing.MicroSeconds): Types.Timing.Seconds =>\n Types.Timing.Seconds(value / 1000 / 1000);\n\nexport function timeStampForEventAdjustedByClosestNavigation(\n event: Types.Events.Event,\n traceBounds: Types.Timing.TraceWindowMicroSeconds,\n navigationsByNavigationId: Map,\n navigationsByFrameId: Map,\n ): Types.Timing.MicroSeconds {\n let eventTimeStamp = event.ts - traceBounds.min;\n if (event.args?.data?.navigationId) {\n const navigationForEvent = navigationsByNavigationId.get(event.args.data.navigationId);\n if (navigationForEvent) {\n eventTimeStamp = event.ts - navigationForEvent.ts;\n }\n } else if (event.args?.data?.frame) {\n const navigationForEvent = getNavigationForTraceEvent(event, event.args.data.frame, navigationsByFrameId);\n if (navigationForEvent) {\n eventTimeStamp = event.ts - navigationForEvent.ts;\n }\n }\n return Types.Timing.MicroSeconds(eventTimeStamp);\n}\n\n// Expands the trace window by a provided percentage or, if it the expanded window is smaller than 1 millisecond, expands it to 1 millisecond.\n// If the expanded window is outside of the max trace window, cut the overflowing bound to the max trace window bound.\nexport function expandWindowByPercentOrToOneMillisecond(\n annotationWindow: Types.Timing.TraceWindowMicroSeconds, maxTraceWindow: Types.Timing.TraceWindowMicroSeconds,\n percentage: number): Types.Timing.TraceWindowMicroSeconds {\n // Expand min and max of the window by half of the provided percentage. That way, in total, the window will be expanded by the provided percentage.\n let newMin = annotationWindow.min - annotationWindow.range * (percentage / 100) / 2;\n let newMax = annotationWindow.max + annotationWindow.range * (percentage / 100) / 2;\n\n if (newMax - newMin < 1_000) {\n const rangeMiddle = (annotationWindow.min + annotationWindow.max) / 2;\n newMin = rangeMiddle - 500;\n newMax = rangeMiddle + 500;\n }\n\n newMin = Math.max(newMin, maxTraceWindow.min);\n newMax = Math.min(newMax, maxTraceWindow.max);\n\n const expandedWindow: Types.Timing.TraceWindowMicroSeconds = {\n min: Types.Timing.MicroSeconds(newMin),\n max: Types.Timing.MicroSeconds(newMax),\n range: Types.Timing.MicroSeconds(newMax - newMin),\n };\n\n return expandedWindow;\n}\n\nexport interface EventTimingsData<\n ValueType extends Types.Timing.MicroSeconds|Types.Timing.MilliSeconds|Types.Timing.Seconds,\n> {\n startTime: ValueType;\n endTime: ValueType;\n duration: ValueType;\n}\n\nexport function eventTimingsMicroSeconds(event: Types.Events.Event): EventTimingsData {\n return {\n startTime: event.ts,\n endTime: Types.Timing.MicroSeconds(event.ts + (event.dur ?? Types.Timing.MicroSeconds(0))),\n duration: Types.Timing.MicroSeconds(event.dur || 0),\n };\n}\nexport function eventTimingsMilliSeconds(event: Types.Events.Event): EventTimingsData {\n const microTimes = eventTimingsMicroSeconds(event);\n return {\n startTime: microSecondsToMilliseconds(microTimes.startTime),\n endTime: microSecondsToMilliseconds(microTimes.endTime),\n duration: microSecondsToMilliseconds(microTimes.duration),\n };\n}\nexport function eventTimingsSeconds(event: Types.Events.Event): EventTimingsData {\n const microTimes = eventTimingsMicroSeconds(event);\n return {\n startTime: microSecondsToSeconds(microTimes.startTime),\n endTime: microSecondsToSeconds(microTimes.endTime),\n duration: microSecondsToSeconds(microTimes.duration),\n };\n}\n\nexport function traceWindowMilliSeconds(bounds: Types.Timing.TraceWindowMicroSeconds):\n Types.Timing.TraceWindowMilliSeconds {\n return {\n min: microSecondsToMilliseconds(bounds.min),\n max: microSecondsToMilliseconds(bounds.max),\n range: microSecondsToMilliseconds(bounds.range),\n };\n}\n\nexport function traceWindowMillisecondsToMicroSeconds(bounds: Types.Timing.TraceWindowMilliSeconds):\n Types.Timing.TraceWindowMicroSeconds {\n return {\n min: millisecondsToMicroseconds(bounds.min),\n max: millisecondsToMicroseconds(bounds.max),\n range: millisecondsToMicroseconds(bounds.range),\n };\n}\n\nexport function traceWindowFromMilliSeconds(\n min: Types.Timing.MilliSeconds, max: Types.Timing.MilliSeconds): Types.Timing.TraceWindowMicroSeconds {\n const traceWindow: Types.Timing.TraceWindowMicroSeconds = {\n min: millisecondsToMicroseconds(min),\n max: millisecondsToMicroseconds(max),\n range: Types.Timing.MicroSeconds(millisecondsToMicroseconds(max) - millisecondsToMicroseconds(min)),\n };\n return traceWindow;\n}\n\nexport function traceWindowFromMicroSeconds(\n min: Types.Timing.MicroSeconds, max: Types.Timing.MicroSeconds): Types.Timing.TraceWindowMicroSeconds {\n const traceWindow: Types.Timing.TraceWindowMicroSeconds = {\n min,\n max,\n range: Types.Timing.MicroSeconds(max - min),\n };\n return traceWindow;\n}\n\nexport interface BoundsIncludeTimeRange {\n timeRange: Types.Timing.TraceWindowMicroSeconds;\n bounds: Types.Timing.TraceWindowMicroSeconds;\n}\n\n/**\n * Checks to see if the timeRange is within the bounds. By \"within\" we mean\n * \"has any overlap\":\n * |------------------------|\n * == no overlap (entirely before)\n * ========= overlap\n * ========= overlap\n * ========= overlap\n * ==== no overlap (entirely after)\n * ============================== overlap (time range is larger than bounds)\n * |------------------------|\n */\nexport function boundsIncludeTimeRange(data: BoundsIncludeTimeRange): boolean {\n const {min: visibleMin, max: visibleMax} = data.bounds;\n const {min: rangeMin, max: rangeMax} = data.timeRange;\n\n return visibleMin <= rangeMax && visibleMax >= rangeMin;\n}\n\n/** Checks to see if the event is within or overlaps the bounds */\nexport function eventIsInBounds(event: Types.Events.Event, bounds: Types.Timing.TraceWindowMicroSeconds): boolean {\n const startTime = event.ts;\n return startTime <= bounds.max && bounds.min <= (startTime + (event.dur ?? 0));\n}\n\nexport function timestampIsInBounds(\n bounds: Types.Timing.TraceWindowMicroSeconds, timestamp: Types.Timing.MicroSeconds): boolean {\n return timestamp >= bounds.min && timestamp <= bounds.max;\n}\n\nexport interface WindowFitsInsideBounds {\n window: Types.Timing.TraceWindowMicroSeconds;\n bounds: Types.Timing.TraceWindowMicroSeconds;\n}\nexport function windowFitsInsideBounds(data: WindowFitsInsideBounds): boolean {\n return data.window.min >= data.bounds.min && data.window.max <= data.bounds.max;\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/helpers/Timing.test.js b/public/models/trace/helpers/Timing.test.js index 8d8b9edf0..c4a42580f 100644 --- a/public/models/trace/helpers/Timing.test.js +++ b/public/models/trace/helpers/Timing.test.js @@ -3,33 +3,33 @@ // found in the LICENSE file. import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; -import * as TraceModel from '../trace.js'; +import * as Trace from '../trace.js'; function milliToMicro(value) { - return TraceModel.Types.Timing.MicroSeconds(value * 1000); + return Trace.Types.Timing.MicroSeconds(value * 1000); } describeWithEnvironment('Timing helpers', () => { describe('Timing conversions', () => { it('can convert milliseconds to microseconds', () => { - const input = TraceModel.Types.Timing.MilliSeconds(1); - const expected = TraceModel.Types.Timing.MicroSeconds(1000); - assert.strictEqual(TraceModel.Helpers.Timing.millisecondsToMicroseconds(input), expected); + const input = Trace.Types.Timing.MilliSeconds(1); + const expected = Trace.Types.Timing.MicroSeconds(1000); + assert.strictEqual(Trace.Helpers.Timing.millisecondsToMicroseconds(input), expected); }); it('can convert seconds to milliseconds', () => { - const input = TraceModel.Types.Timing.Seconds(1); - const expected = TraceModel.Types.Timing.MilliSeconds(1000); - assert.strictEqual(TraceModel.Helpers.Timing.secondsToMilliseconds(input), expected); + const input = Trace.Types.Timing.Seconds(1); + const expected = Trace.Types.Timing.MilliSeconds(1000); + assert.strictEqual(Trace.Helpers.Timing.secondsToMilliseconds(input), expected); }); it('can convert seconds to microseconds', () => { - const input = TraceModel.Types.Timing.Seconds(1); + const input = Trace.Types.Timing.Seconds(1); // 1 Second = 1000 Milliseconds // 1000 Milliseconds = 1,000,000 Microseconds - const expected = TraceModel.Types.Timing.MicroSeconds(1_000_000); - assert.strictEqual(TraceModel.Helpers.Timing.secondsToMicroseconds(input), expected); + const expected = Trace.Types.Timing.MicroSeconds(1_000_000); + assert.strictEqual(Trace.Helpers.Timing.secondsToMicroseconds(input), expected); }); it('can convert microSeconds milliseconds', () => { - const input = TraceModel.Types.Timing.MicroSeconds(1_000_000); - const expected = TraceModel.Types.Timing.MilliSeconds(1_000); - assert.strictEqual(TraceModel.Helpers.Timing.microSecondsToMilliseconds(input), expected); + const input = Trace.Types.Timing.MicroSeconds(1_000_000); + const expected = Trace.Types.Timing.MilliSeconds(1_000); + assert.strictEqual(Trace.Helpers.Timing.microSecondsToMilliseconds(input), expected); }); }); it('eventTimingsMicroSeconds returns the right numbers', async () => { @@ -37,10 +37,10 @@ describeWithEnvironment('Timing helpers', () => { ts: 10, dur: 5, }; - assert.deepEqual(TraceModel.Helpers.Timing.eventTimingsMicroSeconds(event), { - startTime: TraceModel.Types.Timing.MicroSeconds(10), - endTime: TraceModel.Types.Timing.MicroSeconds(15), - duration: TraceModel.Types.Timing.MicroSeconds(5), + assert.deepEqual(Trace.Helpers.Timing.eventTimingsMicroSeconds(event), { + startTime: Trace.Types.Timing.MicroSeconds(10), + endTime: Trace.Types.Timing.MicroSeconds(15), + duration: Trace.Types.Timing.MicroSeconds(5), }); }); it('eventTimingsMilliSeconds returns the right numbers', async () => { @@ -48,10 +48,10 @@ describeWithEnvironment('Timing helpers', () => { ts: 10_000, dur: 5_000, }; - assert.deepEqual(TraceModel.Helpers.Timing.eventTimingsMilliSeconds(event), { - startTime: TraceModel.Types.Timing.MilliSeconds(10), - endTime: TraceModel.Types.Timing.MilliSeconds(15), - duration: TraceModel.Types.Timing.MilliSeconds(5), + assert.deepEqual(Trace.Helpers.Timing.eventTimingsMilliSeconds(event), { + startTime: Trace.Types.Timing.MilliSeconds(10), + endTime: Trace.Types.Timing.MilliSeconds(15), + duration: Trace.Types.Timing.MilliSeconds(5), }); }); it('eventTimingsSeconds returns the right numbers', async () => { @@ -59,16 +59,16 @@ describeWithEnvironment('Timing helpers', () => { ts: 100_000, // 100k microseconds = 100ms = 0.1second dur: 50_000, // 50k microseconds = 50ms = 0.05second }; - assert.deepEqual(TraceModel.Helpers.Timing.eventTimingsSeconds(event), { - startTime: TraceModel.Types.Timing.Seconds(0.1), - endTime: TraceModel.Types.Timing.Seconds(0.15), - duration: TraceModel.Types.Timing.Seconds(0.05), + assert.deepEqual(Trace.Helpers.Timing.eventTimingsSeconds(event), { + startTime: Trace.Types.Timing.Seconds(0.1), + endTime: Trace.Types.Timing.Seconds(0.15), + duration: Trace.Types.Timing.Seconds(0.05), }); }); describe('timeStampForEventAdjustedByClosestNavigation', () => { it('can use the navigation ID to adjust the time correctly', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const lcpEvent = traceData.PageLoadMetrics.allMarkerEvents.find(event => { + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const lcpEvent = parsedTrace.PageLoadMetrics.allMarkerEvents.find(event => { // Just one LCP Event so we do not need to worry about ordering and finding the right one. return event.name === 'largestContentfulPaint::Candidate'; }); @@ -77,36 +77,36 @@ describeWithEnvironment('Timing helpers', () => { } // Ensure we are testing the navigationID path! assert.exists(lcpEvent.args.data?.navigationId); - const adjustedTime = TraceModel.Helpers.Timing.timeStampForEventAdjustedByClosestNavigation(lcpEvent, traceData.Meta.traceBounds, traceData.Meta.navigationsByNavigationId, traceData.Meta.navigationsByFrameId); - const unadjustedTime = TraceModel.Helpers.Timing.microSecondsToMilliseconds(TraceModel.Types.Timing.MicroSeconds(lcpEvent.ts - traceData.Meta.traceBounds.min)); + const adjustedTime = Trace.Helpers.Timing.timeStampForEventAdjustedByClosestNavigation(lcpEvent, parsedTrace.Meta.traceBounds, parsedTrace.Meta.navigationsByNavigationId, parsedTrace.Meta.navigationsByFrameId); + const unadjustedTime = Trace.Helpers.Timing.microSecondsToMilliseconds(Trace.Types.Timing.MicroSeconds(lcpEvent.ts - parsedTrace.Meta.traceBounds.min)); assert.strictEqual(unadjustedTime.toFixed(2), String(130.31)); // To make the assertion easier to read. - const timeAsMS = TraceModel.Helpers.Timing.microSecondsToMilliseconds(adjustedTime); + const timeAsMS = Trace.Helpers.Timing.microSecondsToMilliseconds(adjustedTime); assert.strictEqual(timeAsMS.toFixed(2), String(118.44)); }); it('can use the frame ID to adjust the time correctly', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const dclEvent = traceData.PageLoadMetrics.allMarkerEvents.find(event => { - return event.name === 'MarkDOMContent' && event.args.data?.frame === traceData.Meta.mainFrameId; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const dclEvent = parsedTrace.PageLoadMetrics.allMarkerEvents.find(event => { + return event.name === 'MarkDOMContent' && event.args.data?.frame === parsedTrace.Meta.mainFrameId; }); if (!dclEvent) { throw new Error('Could not find DCL event'); } // Ensure we are testing the frameID path! assert.isUndefined(dclEvent.args.data?.navigationId); - const unadjustedTime = TraceModel.Helpers.Timing.microSecondsToMilliseconds(TraceModel.Types.Timing.MicroSeconds(dclEvent.ts - traceData.Meta.traceBounds.min)); + const unadjustedTime = Trace.Helpers.Timing.microSecondsToMilliseconds(Trace.Types.Timing.MicroSeconds(dclEvent.ts - parsedTrace.Meta.traceBounds.min)); assert.strictEqual(unadjustedTime.toFixed(2), String(190.79)); - const adjustedTime = TraceModel.Helpers.Timing.timeStampForEventAdjustedByClosestNavigation(dclEvent, traceData.Meta.traceBounds, traceData.Meta.navigationsByNavigationId, traceData.Meta.navigationsByFrameId); + const adjustedTime = Trace.Helpers.Timing.timeStampForEventAdjustedByClosestNavigation(dclEvent, parsedTrace.Meta.traceBounds, parsedTrace.Meta.navigationsByNavigationId, parsedTrace.Meta.navigationsByFrameId); // To make the assertion easier to read. - const timeAsMS = TraceModel.Helpers.Timing.microSecondsToMilliseconds(adjustedTime); + const timeAsMS = Trace.Helpers.Timing.microSecondsToMilliseconds(adjustedTime); assert.strictEqual(timeAsMS.toFixed(2), String(178.92)); }); }); describe('expandWindowByPercentOrToOneMillisecond', () => { it('can expand trace window by a percentage', async function () { - const traceWindow = TraceModel.Helpers.Timing.traceWindowFromMicroSeconds(milliToMicro(40), milliToMicro(60)); - const maxTraceWindow = TraceModel.Helpers.Timing.traceWindowFromMicroSeconds(milliToMicro(0), milliToMicro(100)); - const expandedTraceWindow = TraceModel.Helpers.Timing.expandWindowByPercentOrToOneMillisecond(traceWindow, maxTraceWindow, 50); + const traceWindow = Trace.Helpers.Timing.traceWindowFromMicroSeconds(milliToMicro(40), milliToMicro(60)); + const maxTraceWindow = Trace.Helpers.Timing.traceWindowFromMicroSeconds(milliToMicro(0), milliToMicro(100)); + const expandedTraceWindow = Trace.Helpers.Timing.expandWindowByPercentOrToOneMillisecond(traceWindow, maxTraceWindow, 50); // Since initial window was 20ms, make sure the that it is 30ms after being expanded by 50% assert.strictEqual(expandedTraceWindow.range, 30000); // min and max bounds are expanded by 25% from the initial window bounds @@ -115,9 +115,9 @@ describeWithEnvironment('Timing helpers', () => { }); it('if the expanded window is smaller than 1 millisecond, expands it to 1 millisecond ', async function () { // Trace window that is smaller than 1 millisecond - const traceWindow = TraceModel.Helpers.Timing.traceWindowFromMicroSeconds(TraceModel.Types.Timing.MicroSeconds(1000), TraceModel.Types.Timing.MicroSeconds(1500)); - const maxTraceWindow = TraceModel.Helpers.Timing.traceWindowFromMicroSeconds(milliToMicro(0), milliToMicro(100)); - const expandedTraceWindow = TraceModel.Helpers.Timing.expandWindowByPercentOrToOneMillisecond(traceWindow, maxTraceWindow, 5); + const traceWindow = Trace.Helpers.Timing.traceWindowFromMicroSeconds(Trace.Types.Timing.MicroSeconds(1000), Trace.Types.Timing.MicroSeconds(1500)); + const maxTraceWindow = Trace.Helpers.Timing.traceWindowFromMicroSeconds(milliToMicro(0), milliToMicro(100)); + const expandedTraceWindow = Trace.Helpers.Timing.expandWindowByPercentOrToOneMillisecond(traceWindow, maxTraceWindow, 5); // Make sure the window was expanded to 1 millisecond instead of 5 percent. assert.strictEqual(expandedTraceWindow.range, 1000); // The middle of the window should not change @@ -126,9 +126,9 @@ describeWithEnvironment('Timing helpers', () => { assert.strictEqual(expandedTraceWindow.max, 1750); }); it('window does not expand past the provided max window', async function () { - const traceWindow = TraceModel.Helpers.Timing.traceWindowFromMicroSeconds(milliToMicro(5), milliToMicro(55)); - const maxTraceWindow = TraceModel.Helpers.Timing.traceWindowFromMicroSeconds(milliToMicro(0), milliToMicro(100)); - const expandedTraceWindow = TraceModel.Helpers.Timing.expandWindowByPercentOrToOneMillisecond(traceWindow, maxTraceWindow, 50); + const traceWindow = Trace.Helpers.Timing.traceWindowFromMicroSeconds(milliToMicro(5), milliToMicro(55)); + const maxTraceWindow = Trace.Helpers.Timing.traceWindowFromMicroSeconds(milliToMicro(0), milliToMicro(100)); + const expandedTraceWindow = Trace.Helpers.Timing.expandWindowByPercentOrToOneMillisecond(traceWindow, maxTraceWindow, 50); assert.strictEqual(expandedTraceWindow.range, 67500); // Since the expanded window min bound would be smaller than the max window min bound, the expanded window min should be equal to the max window min assert.strictEqual(expandedTraceWindow.min, 0); @@ -136,7 +136,7 @@ describeWithEnvironment('Timing helpers', () => { }); }); describe('BoundsIncludeTimeRange', () => { - const { boundsIncludeTimeRange, traceWindowFromMicroSeconds } = TraceModel.Helpers.Timing; + const { boundsIncludeTimeRange, traceWindowFromMicroSeconds } = Trace.Helpers.Timing; it('is false for an event that is outside the LHS of the visible bounds', () => { const bounds = traceWindowFromMicroSeconds(milliToMicro(50), milliToMicro(100)); const timeRange = traceWindowFromMicroSeconds(milliToMicro(10), milliToMicro(20)); @@ -187,16 +187,16 @@ describeWithEnvironment('Timing helpers', () => { }); }); describe('timestampIsInBounds', () => { - const { eventIsInBounds } = TraceModel.Helpers.Timing; - const { MicroSeconds } = TraceModel.Types.Timing; + const { eventIsInBounds } = Trace.Helpers.Timing; + const { MicroSeconds } = Trace.Types.Timing; const bounds = { min: MicroSeconds(100), max: MicroSeconds(200), range: MicroSeconds(100), }; const makeEvent = (ts, dur) => ({ - ts: TraceModel.Types.Timing.MicroSeconds(ts), - dur: TraceModel.Types.Timing.MicroSeconds(dur), + ts: Trace.Types.Timing.MicroSeconds(ts), + dur: Trace.Types.Timing.MicroSeconds(dur), }); // Left boundary assert.isTrue(eventIsInBounds(makeEvent(101, 1), bounds)); @@ -213,8 +213,8 @@ describeWithEnvironment('Timing helpers', () => { assert.isFalse(eventIsInBounds(makeEvent(300, 50), bounds)); }); describe('timestampIsInBounds', () => { - const { timestampIsInBounds } = TraceModel.Helpers.Timing; - const { MicroSeconds } = TraceModel.Types.Timing; + const { timestampIsInBounds } = Trace.Helpers.Timing; + const { MicroSeconds } = Trace.Types.Timing; it('is true if the value is in the bounds and false otherwise', async () => { const bounds = { min: MicroSeconds(1), diff --git a/public/models/trace/helpers/Timing.test.js.map b/public/models/trace/helpers/Timing.test.js.map index 435bcd0fd..ac0b5b346 100644 --- a/public/models/trace/helpers/Timing.test.js.map +++ b/public/models/trace/helpers/Timing.test.js.map @@ -1 +1 @@ -{"version":3,"file":"Timing.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/Timing.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as TraceModel from '../trace.js';\n\nfunction milliToMicro(value: number) {\n return TraceModel.Types.Timing.MicroSeconds(value * 1000);\n}\n\ndescribeWithEnvironment('Timing helpers', () => {\n describe('Timing conversions', () => {\n it('can convert milliseconds to microseconds', () => {\n const input = TraceModel.Types.Timing.MilliSeconds(1);\n const expected = TraceModel.Types.Timing.MicroSeconds(1000);\n assert.strictEqual(TraceModel.Helpers.Timing.millisecondsToMicroseconds(input), expected);\n });\n\n it('can convert seconds to milliseconds', () => {\n const input = TraceModel.Types.Timing.Seconds(1);\n const expected = TraceModel.Types.Timing.MilliSeconds(1000);\n assert.strictEqual(TraceModel.Helpers.Timing.secondsToMilliseconds(input), expected);\n });\n\n it('can convert seconds to microseconds', () => {\n const input = TraceModel.Types.Timing.Seconds(1);\n // 1 Second = 1000 Milliseconds\n // 1000 Milliseconds = 1,000,000 Microseconds\n const expected = TraceModel.Types.Timing.MicroSeconds(1_000_000);\n assert.strictEqual(TraceModel.Helpers.Timing.secondsToMicroseconds(input), expected);\n });\n\n it('can convert microSeconds milliseconds', () => {\n const input = TraceModel.Types.Timing.MicroSeconds(1_000_000);\n const expected = TraceModel.Types.Timing.MilliSeconds(1_000);\n assert.strictEqual(TraceModel.Helpers.Timing.microSecondsToMilliseconds(input), expected);\n });\n });\n\n it('eventTimingsMicroSeconds returns the right numbers', async () => {\n const event = {\n ts: 10,\n dur: 5,\n } as unknown as TraceModel.Types.TraceEvents.TraceEventData;\n assert.deepEqual(TraceModel.Helpers.Timing.eventTimingsMicroSeconds(event), {\n startTime: TraceModel.Types.Timing.MicroSeconds(10),\n endTime: TraceModel.Types.Timing.MicroSeconds(15),\n duration: TraceModel.Types.Timing.MicroSeconds(5),\n });\n });\n\n it('eventTimingsMilliSeconds returns the right numbers', async () => {\n const event = {\n ts: 10_000,\n dur: 5_000,\n } as unknown as TraceModel.Types.TraceEvents.TraceEventData;\n assert.deepEqual(TraceModel.Helpers.Timing.eventTimingsMilliSeconds(event), {\n startTime: TraceModel.Types.Timing.MilliSeconds(10),\n endTime: TraceModel.Types.Timing.MilliSeconds(15),\n duration: TraceModel.Types.Timing.MilliSeconds(5),\n });\n });\n\n it('eventTimingsSeconds returns the right numbers', async () => {\n const event = {\n ts: 100_000, // 100k microseconds = 100ms = 0.1second\n dur: 50_000, // 50k microseconds = 50ms = 0.05second\n } as unknown as TraceModel.Types.TraceEvents.TraceEventData;\n assert.deepEqual(TraceModel.Helpers.Timing.eventTimingsSeconds(event), {\n startTime: TraceModel.Types.Timing.Seconds(0.1),\n endTime: TraceModel.Types.Timing.Seconds(0.15),\n duration: TraceModel.Types.Timing.Seconds(0.05),\n });\n });\n\n describe('timeStampForEventAdjustedByClosestNavigation', () => {\n it('can use the navigation ID to adjust the time correctly', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const lcpEvent = traceData.PageLoadMetrics.allMarkerEvents.find(event => {\n // Just one LCP Event so we do not need to worry about ordering and finding the right one.\n return event.name === 'largestContentfulPaint::Candidate';\n });\n if (!lcpEvent) {\n throw new Error('Could not find LCP event');\n }\n // Ensure we are testing the navigationID path!\n assert.exists(lcpEvent.args.data?.navigationId);\n const adjustedTime = TraceModel.Helpers.Timing.timeStampForEventAdjustedByClosestNavigation(\n lcpEvent,\n traceData.Meta.traceBounds,\n traceData.Meta.navigationsByNavigationId,\n traceData.Meta.navigationsByFrameId,\n );\n\n const unadjustedTime = TraceModel.Helpers.Timing.microSecondsToMilliseconds(\n TraceModel.Types.Timing.MicroSeconds(lcpEvent.ts - traceData.Meta.traceBounds.min),\n );\n assert.strictEqual(unadjustedTime.toFixed(2), String(130.31));\n\n // To make the assertion easier to read.\n const timeAsMS = TraceModel.Helpers.Timing.microSecondsToMilliseconds(adjustedTime);\n assert.strictEqual(timeAsMS.toFixed(2), String(118.44));\n });\n\n it('can use the frame ID to adjust the time correctly', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const dclEvent = traceData.PageLoadMetrics.allMarkerEvents.find(event => {\n return event.name === 'MarkDOMContent' && event.args.data?.frame === traceData.Meta.mainFrameId;\n });\n if (!dclEvent) {\n throw new Error('Could not find DCL event');\n }\n // Ensure we are testing the frameID path!\n assert.isUndefined(dclEvent.args.data?.navigationId);\n\n const unadjustedTime = TraceModel.Helpers.Timing.microSecondsToMilliseconds(\n TraceModel.Types.Timing.MicroSeconds(dclEvent.ts - traceData.Meta.traceBounds.min),\n );\n assert.strictEqual(unadjustedTime.toFixed(2), String(190.79));\n const adjustedTime = TraceModel.Helpers.Timing.timeStampForEventAdjustedByClosestNavigation(\n dclEvent,\n traceData.Meta.traceBounds,\n traceData.Meta.navigationsByNavigationId,\n traceData.Meta.navigationsByFrameId,\n );\n\n // To make the assertion easier to read.\n const timeAsMS = TraceModel.Helpers.Timing.microSecondsToMilliseconds(adjustedTime);\n assert.strictEqual(timeAsMS.toFixed(2), String(178.92));\n });\n });\n\n describe('expandWindowByPercentOrToOneMillisecond', () => {\n it('can expand trace window by a percentage', async function() {\n const traceWindow = TraceModel.Helpers.Timing.traceWindowFromMicroSeconds(\n milliToMicro(40),\n milliToMicro(60),\n );\n\n const maxTraceWindow = TraceModel.Helpers.Timing.traceWindowFromMicroSeconds(\n milliToMicro(0),\n milliToMicro(100),\n );\n\n const expandedTraceWindow =\n TraceModel.Helpers.Timing.expandWindowByPercentOrToOneMillisecond(traceWindow, maxTraceWindow, 50);\n\n // Since initial window was 20ms, make sure the that it is 30ms after being expanded by 50%\n assert.strictEqual(expandedTraceWindow.range, 30000);\n // min and max bounds are expanded by 25% from the initial window bounds\n assert.strictEqual(expandedTraceWindow.min, 35000);\n assert.strictEqual(expandedTraceWindow.max, 65000);\n });\n\n it('if the expanded window is smaller than 1 millisecond, expands it to 1 millisecond ', async function() {\n // Trace window that is smaller than 1 millisecond\n const traceWindow = TraceModel.Helpers.Timing.traceWindowFromMicroSeconds(\n TraceModel.Types.Timing.MicroSeconds(1000),\n TraceModel.Types.Timing.MicroSeconds(1500),\n );\n const maxTraceWindow = TraceModel.Helpers.Timing.traceWindowFromMicroSeconds(\n milliToMicro(0),\n milliToMicro(100),\n );\n\n const expandedTraceWindow =\n TraceModel.Helpers.Timing.expandWindowByPercentOrToOneMillisecond(traceWindow, maxTraceWindow, 5);\n\n // Make sure the window was expanded to 1 millisecond instead of 5 percent.\n assert.strictEqual(expandedTraceWindow.range, 1000);\n // The middle of the window should not change\n assert.strictEqual(\n (traceWindow.max + traceWindow.min) / 2, (expandedTraceWindow.max + expandedTraceWindow.min) / 2);\n\n assert.strictEqual(expandedTraceWindow.min, 750);\n assert.strictEqual(expandedTraceWindow.max, 1750);\n });\n\n it('window does not expand past the provided max window', async function() {\n const traceWindow = TraceModel.Helpers.Timing.traceWindowFromMicroSeconds(\n milliToMicro(5),\n milliToMicro(55),\n );\n const maxTraceWindow = TraceModel.Helpers.Timing.traceWindowFromMicroSeconds(\n milliToMicro(0),\n milliToMicro(100),\n );\n\n const expandedTraceWindow =\n TraceModel.Helpers.Timing.expandWindowByPercentOrToOneMillisecond(traceWindow, maxTraceWindow, 50);\n assert.strictEqual(expandedTraceWindow.range, 67500);\n // Since the expanded window min bound would be smaller than the max window min bound, the expanded window min should be equal to the max window min\n assert.strictEqual(expandedTraceWindow.min, 0);\n assert.strictEqual(expandedTraceWindow.max, 67500);\n });\n });\n\n describe('BoundsIncludeTimeRange', () => {\n const {boundsIncludeTimeRange, traceWindowFromMicroSeconds} = TraceModel.Helpers.Timing;\n\n it('is false for an event that is outside the LHS of the visible bounds', () => {\n const bounds = traceWindowFromMicroSeconds(\n milliToMicro(50),\n milliToMicro(100),\n );\n\n const timeRange = traceWindowFromMicroSeconds(\n milliToMicro(10),\n milliToMicro(20),\n );\n\n assert.isFalse(boundsIncludeTimeRange({\n bounds,\n timeRange,\n }));\n });\n\n it('is false for an event that is outside the RHS of the visible bounds', () => {\n const bounds = traceWindowFromMicroSeconds(\n milliToMicro(50),\n milliToMicro(100),\n );\n\n const timeRange = traceWindowFromMicroSeconds(\n milliToMicro(101),\n milliToMicro(200),\n );\n\n assert.isFalse(boundsIncludeTimeRange({\n bounds,\n timeRange,\n }));\n });\n\n it('is true for an event that overlaps the LHS of the bounds', () => {\n const bounds = traceWindowFromMicroSeconds(\n milliToMicro(50),\n milliToMicro(100),\n );\n\n const timeRange = traceWindowFromMicroSeconds(\n milliToMicro(0),\n milliToMicro(52),\n );\n\n assert.isTrue(boundsIncludeTimeRange({\n bounds,\n timeRange,\n }));\n });\n\n it('is true for an event that overlaps the RHS of the bounds', () => {\n const bounds = traceWindowFromMicroSeconds(\n milliToMicro(50),\n milliToMicro(100),\n );\n\n const timeRange = traceWindowFromMicroSeconds(\n milliToMicro(99),\n milliToMicro(101),\n );\n\n assert.isTrue(boundsIncludeTimeRange({\n bounds,\n timeRange,\n }));\n });\n\n it('is true for an event that is entirely within the bounds', () => {\n const bounds = traceWindowFromMicroSeconds(\n milliToMicro(50),\n milliToMicro(100),\n );\n\n const timeRange = traceWindowFromMicroSeconds(\n milliToMicro(51),\n milliToMicro(75),\n );\n\n assert.isTrue(boundsIncludeTimeRange({\n bounds,\n timeRange,\n }));\n });\n\n it('is true for an event that is larger than the bounds', () => {\n const bounds = traceWindowFromMicroSeconds(\n milliToMicro(50),\n milliToMicro(100),\n );\n\n const timeRange = traceWindowFromMicroSeconds(\n milliToMicro(0),\n milliToMicro(200),\n );\n\n assert.isTrue(boundsIncludeTimeRange({\n bounds,\n timeRange,\n }));\n });\n });\n\n describe('timestampIsInBounds', () => {\n const {eventIsInBounds} = TraceModel.Helpers.Timing;\n const {MicroSeconds} = TraceModel.Types.Timing;\n\n const bounds: TraceModel.Types.Timing.TraceWindowMicroSeconds = {\n min: MicroSeconds(100),\n max: MicroSeconds(200),\n range: MicroSeconds(100),\n };\n\n const makeEvent = (ts: number, dur: number) => ({\n ts: TraceModel.Types.Timing.MicroSeconds(ts),\n dur: TraceModel.Types.Timing.MicroSeconds(dur),\n }) as unknown as TraceModel.Types.TraceEvents.TraceEventData;\n\n // Left boundary\n assert.isTrue(eventIsInBounds(makeEvent(101, 1), bounds));\n assert.isTrue(eventIsInBounds(makeEvent(100, 1), bounds));\n assert.isTrue(eventIsInBounds(makeEvent(99, 1), bounds));\n assert.isTrue(eventIsInBounds(makeEvent(150, 500), bounds));\n assert.isFalse(eventIsInBounds(makeEvent(98, 1), bounds));\n assert.isFalse(eventIsInBounds(makeEvent(0, 1), bounds));\n assert.isFalse(eventIsInBounds(makeEvent(0, 0), bounds));\n\n // Right boundary\n assert.isTrue(eventIsInBounds(makeEvent(199, 1), bounds));\n assert.isTrue(eventIsInBounds(makeEvent(200, 1), bounds));\n assert.isFalse(eventIsInBounds(makeEvent(201, 1), bounds));\n assert.isFalse(eventIsInBounds(makeEvent(300, 50), bounds));\n });\n\n describe('timestampIsInBounds', () => {\n const {timestampIsInBounds} = TraceModel.Helpers.Timing;\n const {MicroSeconds} = TraceModel.Types.Timing;\n it('is true if the value is in the bounds and false otherwise', async () => {\n const bounds: TraceModel.Types.Timing.TraceWindowMicroSeconds = {\n min: MicroSeconds(1),\n max: MicroSeconds(10),\n range: MicroSeconds(9),\n };\n\n assert.isTrue(timestampIsInBounds(bounds, MicroSeconds(1)));\n assert.isTrue(timestampIsInBounds(bounds, MicroSeconds(5)));\n assert.isTrue(timestampIsInBounds(bounds, MicroSeconds(10)));\n assert.isFalse(timestampIsInBounds(bounds, MicroSeconds(0)));\n assert.isFalse(timestampIsInBounds(bounds, MicroSeconds(11)));\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"Timing.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/Timing.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Trace from '../trace.js';\n\nfunction milliToMicro(value: number) {\n return Trace.Types.Timing.MicroSeconds(value * 1000);\n}\n\ndescribeWithEnvironment('Timing helpers', () => {\n describe('Timing conversions', () => {\n it('can convert milliseconds to microseconds', () => {\n const input = Trace.Types.Timing.MilliSeconds(1);\n const expected = Trace.Types.Timing.MicroSeconds(1000);\n assert.strictEqual(Trace.Helpers.Timing.millisecondsToMicroseconds(input), expected);\n });\n\n it('can convert seconds to milliseconds', () => {\n const input = Trace.Types.Timing.Seconds(1);\n const expected = Trace.Types.Timing.MilliSeconds(1000);\n assert.strictEqual(Trace.Helpers.Timing.secondsToMilliseconds(input), expected);\n });\n\n it('can convert seconds to microseconds', () => {\n const input = Trace.Types.Timing.Seconds(1);\n // 1 Second = 1000 Milliseconds\n // 1000 Milliseconds = 1,000,000 Microseconds\n const expected = Trace.Types.Timing.MicroSeconds(1_000_000);\n assert.strictEqual(Trace.Helpers.Timing.secondsToMicroseconds(input), expected);\n });\n\n it('can convert microSeconds milliseconds', () => {\n const input = Trace.Types.Timing.MicroSeconds(1_000_000);\n const expected = Trace.Types.Timing.MilliSeconds(1_000);\n assert.strictEqual(Trace.Helpers.Timing.microSecondsToMilliseconds(input), expected);\n });\n });\n\n it('eventTimingsMicroSeconds returns the right numbers', async () => {\n const event = {\n ts: 10,\n dur: 5,\n } as unknown as Trace.Types.Events.Event;\n assert.deepEqual(Trace.Helpers.Timing.eventTimingsMicroSeconds(event), {\n startTime: Trace.Types.Timing.MicroSeconds(10),\n endTime: Trace.Types.Timing.MicroSeconds(15),\n duration: Trace.Types.Timing.MicroSeconds(5),\n });\n });\n\n it('eventTimingsMilliSeconds returns the right numbers', async () => {\n const event = {\n ts: 10_000,\n dur: 5_000,\n } as unknown as Trace.Types.Events.Event;\n assert.deepEqual(Trace.Helpers.Timing.eventTimingsMilliSeconds(event), {\n startTime: Trace.Types.Timing.MilliSeconds(10),\n endTime: Trace.Types.Timing.MilliSeconds(15),\n duration: Trace.Types.Timing.MilliSeconds(5),\n });\n });\n\n it('eventTimingsSeconds returns the right numbers', async () => {\n const event = {\n ts: 100_000, // 100k microseconds = 100ms = 0.1second\n dur: 50_000, // 50k microseconds = 50ms = 0.05second\n } as unknown as Trace.Types.Events.Event;\n assert.deepEqual(Trace.Helpers.Timing.eventTimingsSeconds(event), {\n startTime: Trace.Types.Timing.Seconds(0.1),\n endTime: Trace.Types.Timing.Seconds(0.15),\n duration: Trace.Types.Timing.Seconds(0.05),\n });\n });\n\n describe('timeStampForEventAdjustedByClosestNavigation', () => {\n it('can use the navigation ID to adjust the time correctly', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const lcpEvent = parsedTrace.PageLoadMetrics.allMarkerEvents.find(event => {\n // Just one LCP Event so we do not need to worry about ordering and finding the right one.\n return event.name === 'largestContentfulPaint::Candidate';\n });\n if (!lcpEvent) {\n throw new Error('Could not find LCP event');\n }\n // Ensure we are testing the navigationID path!\n assert.exists(lcpEvent.args.data?.navigationId);\n const adjustedTime = Trace.Helpers.Timing.timeStampForEventAdjustedByClosestNavigation(\n lcpEvent,\n parsedTrace.Meta.traceBounds,\n parsedTrace.Meta.navigationsByNavigationId,\n parsedTrace.Meta.navigationsByFrameId,\n );\n\n const unadjustedTime = Trace.Helpers.Timing.microSecondsToMilliseconds(\n Trace.Types.Timing.MicroSeconds(lcpEvent.ts - parsedTrace.Meta.traceBounds.min),\n );\n assert.strictEqual(unadjustedTime.toFixed(2), String(130.31));\n\n // To make the assertion easier to read.\n const timeAsMS = Trace.Helpers.Timing.microSecondsToMilliseconds(adjustedTime);\n assert.strictEqual(timeAsMS.toFixed(2), String(118.44));\n });\n\n it('can use the frame ID to adjust the time correctly', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const dclEvent = parsedTrace.PageLoadMetrics.allMarkerEvents.find(event => {\n return event.name === 'MarkDOMContent' && event.args.data?.frame === parsedTrace.Meta.mainFrameId;\n });\n if (!dclEvent) {\n throw new Error('Could not find DCL event');\n }\n // Ensure we are testing the frameID path!\n assert.isUndefined(dclEvent.args.data?.navigationId);\n\n const unadjustedTime = Trace.Helpers.Timing.microSecondsToMilliseconds(\n Trace.Types.Timing.MicroSeconds(dclEvent.ts - parsedTrace.Meta.traceBounds.min),\n );\n assert.strictEqual(unadjustedTime.toFixed(2), String(190.79));\n const adjustedTime = Trace.Helpers.Timing.timeStampForEventAdjustedByClosestNavigation(\n dclEvent,\n parsedTrace.Meta.traceBounds,\n parsedTrace.Meta.navigationsByNavigationId,\n parsedTrace.Meta.navigationsByFrameId,\n );\n\n // To make the assertion easier to read.\n const timeAsMS = Trace.Helpers.Timing.microSecondsToMilliseconds(adjustedTime);\n assert.strictEqual(timeAsMS.toFixed(2), String(178.92));\n });\n });\n\n describe('expandWindowByPercentOrToOneMillisecond', () => {\n it('can expand trace window by a percentage', async function() {\n const traceWindow = Trace.Helpers.Timing.traceWindowFromMicroSeconds(\n milliToMicro(40),\n milliToMicro(60),\n );\n\n const maxTraceWindow = Trace.Helpers.Timing.traceWindowFromMicroSeconds(\n milliToMicro(0),\n milliToMicro(100),\n );\n\n const expandedTraceWindow =\n Trace.Helpers.Timing.expandWindowByPercentOrToOneMillisecond(traceWindow, maxTraceWindow, 50);\n\n // Since initial window was 20ms, make sure the that it is 30ms after being expanded by 50%\n assert.strictEqual(expandedTraceWindow.range, 30000);\n // min and max bounds are expanded by 25% from the initial window bounds\n assert.strictEqual(expandedTraceWindow.min, 35000);\n assert.strictEqual(expandedTraceWindow.max, 65000);\n });\n\n it('if the expanded window is smaller than 1 millisecond, expands it to 1 millisecond ', async function() {\n // Trace window that is smaller than 1 millisecond\n const traceWindow = Trace.Helpers.Timing.traceWindowFromMicroSeconds(\n Trace.Types.Timing.MicroSeconds(1000),\n Trace.Types.Timing.MicroSeconds(1500),\n );\n const maxTraceWindow = Trace.Helpers.Timing.traceWindowFromMicroSeconds(\n milliToMicro(0),\n milliToMicro(100),\n );\n\n const expandedTraceWindow =\n Trace.Helpers.Timing.expandWindowByPercentOrToOneMillisecond(traceWindow, maxTraceWindow, 5);\n\n // Make sure the window was expanded to 1 millisecond instead of 5 percent.\n assert.strictEqual(expandedTraceWindow.range, 1000);\n // The middle of the window should not change\n assert.strictEqual(\n (traceWindow.max + traceWindow.min) / 2, (expandedTraceWindow.max + expandedTraceWindow.min) / 2);\n\n assert.strictEqual(expandedTraceWindow.min, 750);\n assert.strictEqual(expandedTraceWindow.max, 1750);\n });\n\n it('window does not expand past the provided max window', async function() {\n const traceWindow = Trace.Helpers.Timing.traceWindowFromMicroSeconds(\n milliToMicro(5),\n milliToMicro(55),\n );\n const maxTraceWindow = Trace.Helpers.Timing.traceWindowFromMicroSeconds(\n milliToMicro(0),\n milliToMicro(100),\n );\n\n const expandedTraceWindow =\n Trace.Helpers.Timing.expandWindowByPercentOrToOneMillisecond(traceWindow, maxTraceWindow, 50);\n assert.strictEqual(expandedTraceWindow.range, 67500);\n // Since the expanded window min bound would be smaller than the max window min bound, the expanded window min should be equal to the max window min\n assert.strictEqual(expandedTraceWindow.min, 0);\n assert.strictEqual(expandedTraceWindow.max, 67500);\n });\n });\n\n describe('BoundsIncludeTimeRange', () => {\n const {boundsIncludeTimeRange, traceWindowFromMicroSeconds} = Trace.Helpers.Timing;\n\n it('is false for an event that is outside the LHS of the visible bounds', () => {\n const bounds = traceWindowFromMicroSeconds(\n milliToMicro(50),\n milliToMicro(100),\n );\n\n const timeRange = traceWindowFromMicroSeconds(\n milliToMicro(10),\n milliToMicro(20),\n );\n\n assert.isFalse(boundsIncludeTimeRange({\n bounds,\n timeRange,\n }));\n });\n\n it('is false for an event that is outside the RHS of the visible bounds', () => {\n const bounds = traceWindowFromMicroSeconds(\n milliToMicro(50),\n milliToMicro(100),\n );\n\n const timeRange = traceWindowFromMicroSeconds(\n milliToMicro(101),\n milliToMicro(200),\n );\n\n assert.isFalse(boundsIncludeTimeRange({\n bounds,\n timeRange,\n }));\n });\n\n it('is true for an event that overlaps the LHS of the bounds', () => {\n const bounds = traceWindowFromMicroSeconds(\n milliToMicro(50),\n milliToMicro(100),\n );\n\n const timeRange = traceWindowFromMicroSeconds(\n milliToMicro(0),\n milliToMicro(52),\n );\n\n assert.isTrue(boundsIncludeTimeRange({\n bounds,\n timeRange,\n }));\n });\n\n it('is true for an event that overlaps the RHS of the bounds', () => {\n const bounds = traceWindowFromMicroSeconds(\n milliToMicro(50),\n milliToMicro(100),\n );\n\n const timeRange = traceWindowFromMicroSeconds(\n milliToMicro(99),\n milliToMicro(101),\n );\n\n assert.isTrue(boundsIncludeTimeRange({\n bounds,\n timeRange,\n }));\n });\n\n it('is true for an event that is entirely within the bounds', () => {\n const bounds = traceWindowFromMicroSeconds(\n milliToMicro(50),\n milliToMicro(100),\n );\n\n const timeRange = traceWindowFromMicroSeconds(\n milliToMicro(51),\n milliToMicro(75),\n );\n\n assert.isTrue(boundsIncludeTimeRange({\n bounds,\n timeRange,\n }));\n });\n\n it('is true for an event that is larger than the bounds', () => {\n const bounds = traceWindowFromMicroSeconds(\n milliToMicro(50),\n milliToMicro(100),\n );\n\n const timeRange = traceWindowFromMicroSeconds(\n milliToMicro(0),\n milliToMicro(200),\n );\n\n assert.isTrue(boundsIncludeTimeRange({\n bounds,\n timeRange,\n }));\n });\n });\n\n describe('timestampIsInBounds', () => {\n const {eventIsInBounds} = Trace.Helpers.Timing;\n const {MicroSeconds} = Trace.Types.Timing;\n\n const bounds: Trace.Types.Timing.TraceWindowMicroSeconds = {\n min: MicroSeconds(100),\n max: MicroSeconds(200),\n range: MicroSeconds(100),\n };\n\n const makeEvent = (ts: number, dur: number) => ({\n ts: Trace.Types.Timing.MicroSeconds(ts),\n dur: Trace.Types.Timing.MicroSeconds(dur),\n }) as unknown as Trace.Types.Events.Event;\n\n // Left boundary\n assert.isTrue(eventIsInBounds(makeEvent(101, 1), bounds));\n assert.isTrue(eventIsInBounds(makeEvent(100, 1), bounds));\n assert.isTrue(eventIsInBounds(makeEvent(99, 1), bounds));\n assert.isTrue(eventIsInBounds(makeEvent(150, 500), bounds));\n assert.isFalse(eventIsInBounds(makeEvent(98, 1), bounds));\n assert.isFalse(eventIsInBounds(makeEvent(0, 1), bounds));\n assert.isFalse(eventIsInBounds(makeEvent(0, 0), bounds));\n\n // Right boundary\n assert.isTrue(eventIsInBounds(makeEvent(199, 1), bounds));\n assert.isTrue(eventIsInBounds(makeEvent(200, 1), bounds));\n assert.isFalse(eventIsInBounds(makeEvent(201, 1), bounds));\n assert.isFalse(eventIsInBounds(makeEvent(300, 50), bounds));\n });\n\n describe('timestampIsInBounds', () => {\n const {timestampIsInBounds} = Trace.Helpers.Timing;\n const {MicroSeconds} = Trace.Types.Timing;\n it('is true if the value is in the bounds and false otherwise', async () => {\n const bounds: Trace.Types.Timing.TraceWindowMicroSeconds = {\n min: MicroSeconds(1),\n max: MicroSeconds(10),\n range: MicroSeconds(9),\n };\n\n assert.isTrue(timestampIsInBounds(bounds, MicroSeconds(1)));\n assert.isTrue(timestampIsInBounds(bounds, MicroSeconds(5)));\n assert.isTrue(timestampIsInBounds(bounds, MicroSeconds(10)));\n assert.isFalse(timestampIsInBounds(bounds, MicroSeconds(0)));\n assert.isFalse(timestampIsInBounds(bounds, MicroSeconds(11)));\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/helpers/Trace.d.ts b/public/models/trace/helpers/Trace.d.ts index 5ebdbab27..6d33483ea 100644 --- a/public/models/trace/helpers/Trace.d.ts +++ b/public/models/trace/helpers/Trace.d.ts @@ -1,11 +1,11 @@ import type * as Protocol from '../../../generated/protocol.js'; import type * as CPUProfile from '../../cpu_profile/cpu_profile.js'; import * as Types from '../types/types.js'; -type MatchedPairType = Types.TraceEvents.SyntheticEventPair; +type MatchedPairType = Types.Events.SyntheticEventPair; type MatchingPairableAsyncEvents = { - begin: Types.TraceEvents.TraceEventPairableAsyncBegin | null; - end: Types.TraceEvents.TraceEventPairableAsyncEnd | null; - instant?: Types.TraceEvents.TraceEventPairableAsyncInstant[]; + begin: Types.Events.PairableAsyncBegin | null; + end: Types.Events.PairableAsyncEnd | null; + instant?: Types.Events.PairableAsyncInstant[]; }; /** * Extracts the raw stack trace of known trace events. Most likely than @@ -14,10 +14,10 @@ type MatchingPairableAsyncEvents = { * one based this function can yield unexpected results when used * indiscriminately. */ -export declare function stackTraceForEvent(event: Types.TraceEvents.TraceEventData): Types.TraceEvents.TraceEventCallFrame[] | null; +export declare function stackTraceForEvent(event: Types.Events.Event): Types.Events.CallFrame[] | null; export declare function extractOriginFromTrace(firstNavigationURL: string): string | null; -export type EventsInThread = Map; -export declare function addEventToProcessThread(event: T, eventsInProcessThread: Map>): void; +export type EventsInThread = Map; +export declare function addEventToProcessThread(event: T, eventsInProcessThread: Map>): void; type TimeSpan = { ts: Types.Timing.MicroSeconds; dur?: Types.Timing.MicroSeconds; @@ -35,11 +35,11 @@ export declare function sortTraceEventsInPlace(events: { * Returns an array of ordered events that results after merging the two * ordered input arrays. */ -export declare function mergeEventsInOrder(eventsArray1: readonly T1[], eventsArray2: readonly T2[]): (T1 | T2)[]; -export declare function getNavigationForTraceEvent(event: Types.TraceEvents.TraceEventData, eventFrameId: string, navigationsByFrameId: Map): Types.TraceEvents.TraceEventNavigationStart | null; -export declare function extractId(event: Types.TraceEvents.TraceEventPairableAsync | MatchedPairType): string | undefined; -export declare function activeURLForFrameAtTime(frameId: string, time: Types.Timing.MicroSeconds, rendererProcessesByFrame: Map(eventsArray1: readonly T1[], eventsArray2: readonly T2[]): (T1 | T2)[]; +export declare function getNavigationForTraceEvent(event: Types.Events.Event, eventFrameId: string, navigationsByFrameId: Map): Types.Events.NavigationStart | null; +export declare function extractId(event: Types.Events.PairableAsync | MatchedPairType): string | undefined; +export declare function activeURLForFrameAtTime(frameId: string, time: Types.Timing.MicroSeconds, rendererProcessesByFrame: Map>): string | null; /** @@ -52,27 +52,27 @@ export declare function activeURLForFrameAtTime(frameId: string, time: Types.Tim * * See `panels/timeline/docs/profile_calls.md` for more context on how these events are created. */ -export declare function makeProfileCall(node: CPUProfile.ProfileTreeModel.ProfileNode, profileId: Types.TraceEvents.ProfileID, sampleIndex: number, ts: Types.Timing.MicroSeconds, pid: Types.TraceEvents.ProcessID, tid: Types.TraceEvents.ThreadID): Types.TraceEvents.SyntheticProfileCall; +export declare function makeProfileCall(node: CPUProfile.ProfileTreeModel.ProfileNode, profileId: Types.Events.ProfileID, sampleIndex: number, ts: Types.Timing.MicroSeconds, pid: Types.Events.ProcessID, tid: Types.Events.ThreadID): Types.Events.SyntheticProfileCall; /** - * Matches beginning events with TraceEventPairableAsyncEnd and TraceEventPairableAsyncInstant (ASYNC_NESTABLE_INSTANT) + * Matches beginning events with PairableAsyncEnd and PairableAsyncInstant (ASYNC_NESTABLE_INSTANT) * if provided, though currently only coming from Animations. Traces may contain multiple instant events so we need to * account for that. * * @returns {Map} Map of the animation's ID to it's matching events. */ -export declare function matchEvents(unpairedEvents: Types.TraceEvents.TraceEventPairableAsync[]): Map; -export declare function createSortedSyntheticEvents(matchedPairs: Map; +export declare function createSortedSyntheticEvents(matchedPairs: Map, syntheticEventCallback?: (syntheticEvent: MatchedPairType) => void): MatchedPairType[]; -export declare function createMatchedSortedSyntheticEvents(unpairedAsyncEvents: T[], syntheticEventCallback?: (syntheticEvent: MatchedPairType) => void): MatchedPairType[]; +export declare function createMatchedSortedSyntheticEvents(unpairedAsyncEvents: T[], syntheticEventCallback?: (syntheticEvent: MatchedPairType) => void): MatchedPairType[]; /** * Different trace events return line/column numbers that are 1 or 0 indexed. * This function knows which events return 1 indexed numbers and normalizes * them. The UI expects 0 indexed line numbers, so that is what we return. */ -export declare function getZeroIndexedLineAndColumnForEvent(event: Types.TraceEvents.TraceEventData): { +export declare function getZeroIndexedLineAndColumnForEvent(event: Types.Events.Event): { lineNumber?: number; columnNumber?: number; }; @@ -82,19 +82,19 @@ export declare function getZeroIndexedLineAndColumnForEvent(event: Types.TraceEv * This function knows which events return 1 indexed numbers and normalizes * them. The UI expects 0 indexed line numbers, so that is what we return. */ -export declare function getZeroIndexedStackTraceForEvent(event: Types.TraceEvents.TraceEventData): Types.TraceEvents.TraceEventCallFrame[] | null; +export declare function getZeroIndexedStackTraceForEvent(event: Types.Events.Event): Types.Events.CallFrame[] | null; /** * Given a 1-based call frame creates a 0-based one. */ -export declare function makeZeroBasedCallFrame(callFrame: Types.TraceEvents.TraceEventCallFrame): Types.TraceEvents.TraceEventCallFrame; -export declare function frameIDForEvent(event: Types.TraceEvents.TraceEventData): string | null; -export declare function isTopLevelEvent(event: Types.TraceEvents.TraceEventData): boolean; -export declare function findUpdateLayoutTreeEvents(events: Types.TraceEvents.TraceEventData[], startTime: Types.Timing.MicroSeconds, endTime?: Types.Timing.MicroSeconds): Types.TraceEvents.TraceEventUpdateLayoutTree[]; +export declare function makeZeroBasedCallFrame(callFrame: Types.Events.CallFrame): Types.Events.CallFrame; +export declare function frameIDForEvent(event: Types.Events.Event): string | null; +export declare function isTopLevelEvent(event: Types.Events.Event): boolean; +export declare function findUpdateLayoutTreeEvents(events: Types.Events.Event[], startTime: Types.Timing.MicroSeconds, endTime?: Types.Timing.MicroSeconds): Types.Events.UpdateLayoutTree[]; export interface ForEachEventConfig { - onStartEvent: (event: Types.TraceEvents.TraceEventData) => void; - onEndEvent: (event: Types.TraceEvents.TraceEventData) => void; - onInstantEvent?: (event: Types.TraceEvents.TraceEventData) => void; - eventFilter?: (event: Types.TraceEvents.TraceEventData) => boolean; + onStartEvent: (event: Types.Events.Event) => void; + onEndEvent: (event: Types.Events.Event) => void; + onInstantEvent?: (event: Types.Events.Event) => void; + eventFilter?: (event: Types.Events.Event) => boolean; startTime?: Types.Timing.MicroSeconds; endTime?: Types.Timing.MicroSeconds; ignoreAsyncEvents?: boolean; @@ -129,7 +129,7 @@ export interface ForEachEventConfig { * By default, async events are skipped. This behaviour can be * overriden making use of the config.ignoreAsyncEvents parameter. */ -export declare function forEachEvent(events: Types.TraceEvents.TraceEventData[], config: ForEachEventConfig): void; -export declare function eventHasCategory(event: Types.TraceEvents.TraceEventData, category: string): boolean; -export declare function nodeIdForInvalidationEvent(event: Types.TraceEvents.InvalidationTrackingEvent): Protocol.DOM.BackendNodeId | null; +export declare function forEachEvent(events: Types.Events.Event[], config: ForEachEventConfig): void; +export declare function eventHasCategory(event: Types.Events.Event, category: string): boolean; +export declare function nodeIdForInvalidationEvent(event: Types.Events.InvalidationTrackingEvent): Protocol.DOM.BackendNodeId | null; export {}; diff --git a/public/models/trace/helpers/Trace.js b/public/models/trace/helpers/Trace.js index 48ad82ccf..b8d30771f 100644 --- a/public/models/trace/helpers/Trace.js +++ b/public/models/trace/helpers/Trace.js @@ -20,13 +20,13 @@ export function stackTraceForEvent(event) { if (event.args?.stackTrace) { return event.args.stackTrace; } - if (Types.TraceEvents.isTraceEventUpdateLayoutTree(event)) { + if (Types.Events.isUpdateLayoutTree(event)) { return event.args.beginData?.stackTrace || null; } if (Types.Extensions.isSyntheticExtensionEntry(event)) { return stackTraceForEvent(event.rawSourceEvent); } - if (Types.TraceEvents.isSyntheticUserTiming(event)) { + if (Types.Events.isSyntheticUserTiming(event)) { return stackTraceForEvent(event.rawSourceEvent); } return null; @@ -164,7 +164,7 @@ export function makeProfileCall(node, profileId, sampleIndex, ts, pid, tid) { name: 'ProfileCall', nodeId: node.id, args: {}, - ph: "X" /* Types.TraceEvents.Phase.COMPLETE */, + ph: "X" /* Types.Events.Phase.COMPLETE */, pid, tid, ts, @@ -175,7 +175,7 @@ export function makeProfileCall(node, profileId, sampleIndex, ts, pid, tid) { }; } /** - * Matches beginning events with TraceEventPairableAsyncEnd and TraceEventPairableAsyncInstant (ASYNC_NESTABLE_INSTANT) + * Matches beginning events with PairableAsyncEnd and PairableAsyncInstant (ASYNC_NESTABLE_INSTANT) * if provided, though currently only coming from Animations. Traces may contain multiple instant events so we need to * account for that. * @@ -196,9 +196,9 @@ export function matchEvents(unpairedEvents) { const otherEventsWithID = Platform.MapUtilities.getWithDefault(matchedPairs, syntheticId, () => { return { begin: null, end: null, instant: [] }; }); - const isStartEvent = event.ph === "b" /* Types.TraceEvents.Phase.ASYNC_NESTABLE_START */; - const isEndEvent = event.ph === "e" /* Types.TraceEvents.Phase.ASYNC_NESTABLE_END */; - const isInstantEvent = event.ph === "n" /* Types.TraceEvents.Phase.ASYNC_NESTABLE_INSTANT */; + const isStartEvent = event.ph === "b" /* Types.Events.Phase.ASYNC_NESTABLE_START */; + const isEndEvent = event.ph === "e" /* Types.Events.Phase.ASYNC_NESTABLE_END */; + const isInstantEvent = event.ph === "n" /* Types.Events.Phase.ASYNC_NESTABLE_INSTANT */; if (isStartEvent) { otherEventsWithID.begin = event; } @@ -245,7 +245,7 @@ export function createSortedSyntheticEvents(matchedPairs, syntheticEventCallback continue; } const targetEvent = endEvent || beginEvent; - const event = SyntheticEventsManager.registerSyntheticBasedEvent({ + const event = SyntheticEventsManager.registerSyntheticEvent({ rawSourceEvent: beginEvent, cat: targetEvent.cat, ph: targetEvent.ph, @@ -294,10 +294,10 @@ export function getZeroIndexedLineAndColumnForEvent(event) { switch (event.name) { // All these events have line/column numbers which are 1 indexed; so we // subtract to make them 0 indexed. - case "FunctionCall" /* Types.TraceEvents.KnownEventName.FUNCTION_CALL */: - case "EvaluateScript" /* Types.TraceEvents.KnownEventName.EVALUATE_SCRIPT */: - case "v8.compile" /* Types.TraceEvents.KnownEventName.COMPILE */: - case "v8.produceCache" /* Types.TraceEvents.KnownEventName.CACHE_SCRIPT */: { + case "FunctionCall" /* Types.Events.Name.FUNCTION_CALL */: + case "EvaluateScript" /* Types.Events.Name.EVALUATE_SCRIPT */: + case "v8.compile" /* Types.Events.Name.COMPILE */: + case "v8.produceCache" /* Types.Events.Name.CACHE_SCRIPT */: { return { lineNumber: typeof lineNumber === 'number' ? lineNumber - 1 : undefined, columnNumber: typeof columnNumber === 'number' ? columnNumber - 1 : undefined, @@ -321,13 +321,13 @@ export function getZeroIndexedStackTraceForEvent(event) { } return stack.map(callFrame => { switch (event.name) { - case "ScheduleStyleRecalculation" /* Types.TraceEvents.KnownEventName.SCHEDULE_STYLE_RECALCULATION */: - case "InvalidateLayout" /* Types.TraceEvents.KnownEventName.INVALIDATE_LAYOUT */: - case "UpdateLayoutTree" /* Types.TraceEvents.KnownEventName.UPDATE_LAYOUT_TREE */: { + case "ScheduleStyleRecalculation" /* Types.Events.Name.SCHEDULE_STYLE_RECALCULATION */: + case "InvalidateLayout" /* Types.Events.Name.INVALIDATE_LAYOUT */: + case "UpdateLayoutTree" /* Types.Events.Name.UPDATE_LAYOUT_TREE */: { return makeZeroBasedCallFrame(callFrame); } default: { - if (Types.TraceEvents.isTraceEventUserTiming(event) || Types.Extensions.isSyntheticExtensionEntry(event)) { + if (Types.Events.isUserTiming(event) || Types.Extensions.isSyntheticExtensionEntry(event)) { return makeZeroBasedCallFrame(callFrame); } } @@ -398,7 +398,7 @@ export function isTopLevelEvent(event) { // TODO(crbug.com/341234884): do we need this? return true; } - return event.cat.includes(DevToolsTimelineEventCategory) && event.name === "RunTask" /* Types.TraceEvents.KnownEventName.RUN_TASK */; + return event.cat.includes(DevToolsTimelineEventCategory) && event.name === "RunTask" /* Types.Events.Name.RUN_TASK */; } function topLevelEventIndexEndingAfter(events, time) { let index = Platform.ArrayUtilities.upperBound(events, time, (time, event) => time - event.ts) - 1; @@ -412,7 +412,7 @@ export function findUpdateLayoutTreeEvents(events, startTime, endTime) { const startEventIndex = topLevelEventIndexEndingAfter(events, startTime); for (let i = startEventIndex; i < events.length; i++) { const event = events[i]; - if (!Types.TraceEvents.isTraceEventUpdateLayoutTree(event)) { + if (!Types.Events.isUpdateLayoutTree(event)) { continue; } if (event.ts >= (endTime || Infinity)) { @@ -467,8 +467,8 @@ export function forEachEvent(events, config) { if (currentEventTimings.startTime > globalEndTime) { break; } - const isIgnoredAsyncEvent = ignoreAsyncEvents && Types.TraceEvents.isAsyncPhase(currentEvent.ph); - if (isIgnoredAsyncEvent || Types.TraceEvents.isFlowPhase(currentEvent.ph)) { + const isIgnoredAsyncEvent = ignoreAsyncEvents && Types.Events.isPhaseAsync(currentEvent.ph); + if (isIgnoredAsyncEvent || Types.Events.isFlowPhase(currentEvent.ph)) { continue; } // If we have now reached an event that is after a bunch of events, we need diff --git a/public/models/trace/helpers/Trace.js.map b/public/models/trace/helpers/Trace.js.map index d55bd4d13..0e8d2ad42 100644 --- a/public/models/trace/helpers/Trace.js.map +++ b/public/models/trace/helpers/Trace.js.map @@ -1 +1 @@ -{"version":3,"file":"Trace.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/Trace.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../../core/common/common.js';\nimport * as Platform from '../../../core/platform/platform.js';\nimport type * as Protocol from '../../../generated/protocol.js';\nimport type * as CPUProfile from '../../cpu_profile/cpu_profile.js';\nimport * as Types from '../types/types.js';\n\nimport {SyntheticEventsManager} from './SyntheticEvents.js';\nimport {eventTimingsMicroSeconds} from './Timing.js';\n\ntype MatchedPairType = Types.TraceEvents.SyntheticEventPair;\ntype MatchingPairableAsyncEvents = {\n begin: Types.TraceEvents.TraceEventPairableAsyncBegin|null,\n end: Types.TraceEvents.TraceEventPairableAsyncEnd|null,\n instant?: Types.TraceEvents.TraceEventPairableAsyncInstant[],\n};\n\n/**\n * Extracts the raw stack trace of known trace events. Most likely than\n * not you want to use `getZeroIndexedStackTraceForEvent`, which returns\n * the stack with zero based numbering. Since some trace events are\n * one based this function can yield unexpected results when used\n * indiscriminately.\n */\nexport function stackTraceForEvent(event: Types.TraceEvents.TraceEventData): Types.TraceEvents.TraceEventCallFrame[]|\n null {\n if (event.args?.data?.stackTrace) {\n return event.args.data.stackTrace;\n }\n if (event.args?.stackTrace) {\n return event.args.stackTrace;\n }\n if (Types.TraceEvents.isTraceEventUpdateLayoutTree(event)) {\n return event.args.beginData?.stackTrace || null;\n }\n if (Types.Extensions.isSyntheticExtensionEntry(event)) {\n return stackTraceForEvent(event.rawSourceEvent);\n }\n if (Types.TraceEvents.isSyntheticUserTiming(event)) {\n return stackTraceForEvent(event.rawSourceEvent);\n }\n return null;\n}\n\nexport function extractOriginFromTrace(firstNavigationURL: string): string|null {\n const url = Common.ParsedURL.ParsedURL.fromString(firstNavigationURL);\n if (url) {\n // We do this to save some space in the toolbar - seeing the `www` is less\n // useful than seeing `foo.com` if it's truncated at narrow widths\n if (url.host.startsWith('www.')) {\n return url.host.slice(4);\n }\n return url.host;\n }\n return null;\n}\n\nexport type EventsInThread = Map;\n// Each thread contains events. Events indicate the thread and process IDs, which are\n// used to store the event in the correct process thread entry below.\nexport function addEventToProcessThread(\n event: T,\n eventsInProcessThread: Map>,\n ): void {\n const {tid, pid} = event;\n let eventsInThread = eventsInProcessThread.get(pid);\n if (!eventsInThread) {\n eventsInThread = new Map();\n }\n\n let events = eventsInThread.get(tid);\n if (!events) {\n events = [];\n }\n\n events.push(event);\n eventsInThread.set(event.tid, events);\n eventsInProcessThread.set(event.pid, eventsInThread);\n}\n\ntype TimeSpan = {\n ts: Types.Timing.MicroSeconds,\n dur?: Types.Timing.MicroSeconds,\n};\nexport function eventTimeComparator(a: TimeSpan, b: TimeSpan): -1|0|1 {\n const aBeginTime = a.ts;\n const bBeginTime = b.ts;\n if (aBeginTime < bBeginTime) {\n return -1;\n }\n if (aBeginTime > bBeginTime) {\n return 1;\n }\n const aDuration = a.dur ?? 0;\n const bDuration = b.dur ?? 0;\n const aEndTime = aBeginTime + aDuration;\n const bEndTime = bBeginTime + bDuration;\n if (aEndTime > bEndTime) {\n return -1;\n }\n if (aEndTime < bEndTime) {\n return 1;\n }\n return 0;\n}\n/**\n * Sorts all the events in place, in order, by their start time. If they have\n * the same start time, orders them by longest first.\n */\nexport function sortTraceEventsInPlace(events: {ts: Types.Timing.MicroSeconds, dur?: Types.Timing.MicroSeconds}[]):\n void {\n events.sort(eventTimeComparator);\n}\n\n/**\n * Returns an array of ordered events that results after merging the two\n * ordered input arrays.\n */\nexport function\nmergeEventsInOrder(\n eventsArray1: readonly T1[], eventsArray2: readonly T2[]): (T1|T2)[] {\n const result = [];\n let i = 0;\n let j = 0;\n while (i < eventsArray1.length && j < eventsArray2.length) {\n const event1 = eventsArray1[i];\n const event2 = eventsArray2[j];\n const compareValue = eventTimeComparator(event1, event2);\n if (compareValue <= 0) {\n result.push(event1);\n i++;\n }\n if (compareValue === 1) {\n result.push(event2);\n j++;\n }\n }\n while (i < eventsArray1.length) {\n result.push(eventsArray1[i++]);\n }\n while (j < eventsArray2.length) {\n result.push(eventsArray2[j++]);\n }\n return result;\n}\n\nexport function getNavigationForTraceEvent(\n event: Types.TraceEvents.TraceEventData,\n eventFrameId: string,\n navigationsByFrameId: Map,\n ): Types.TraceEvents.TraceEventNavigationStart|null {\n const navigations = navigationsByFrameId.get(eventFrameId);\n if (!navigations || eventFrameId === '') {\n // This event's navigation has been filtered out by the meta handler as a noise event\n // or contains an empty frameId.\n return null;\n }\n\n const eventNavigationIndex =\n Platform.ArrayUtilities.nearestIndexFromEnd(navigations, navigation => navigation.ts <= event.ts);\n\n if (eventNavigationIndex === null) {\n // This event's navigation has been filtered out by the meta handler as a noise event.\n return null;\n }\n return navigations[eventNavigationIndex];\n}\n\nexport function extractId(event: Types.TraceEvents.TraceEventPairableAsync|\n MatchedPairType): string|undefined {\n return event.id ?? event.id2?.global ?? event.id2?.local;\n}\n\nexport function activeURLForFrameAtTime(\n frameId: string, time: Types.Timing.MicroSeconds,\n rendererProcessesByFrame:\n Map>): string|null {\n const processData = rendererProcessesByFrame.get(frameId);\n if (!processData) {\n return null;\n }\n for (const processes of processData.values()) {\n for (const processInfo of processes) {\n if (processInfo.window.min > time || processInfo.window.max < time) {\n continue;\n }\n return processInfo.frame.url;\n }\n }\n return null;\n}\n\n/**\n * @param node the node attached to the profile call. Here a node represents a function in the call tree.\n * @param profileId the profile ID that the sample came from that backs this call.\n * @param sampleIndex the index of the sample in the given profile that this call was created from\n * @param ts the timestamp of the profile call\n * @param pid the process ID of the profile call\n * @param tid the thread ID of the profile call\n *\n * See `panels/timeline/docs/profile_calls.md` for more context on how these events are created.\n */\nexport function makeProfileCall(\n node: CPUProfile.ProfileTreeModel.ProfileNode, profileId: Types.TraceEvents.ProfileID, sampleIndex: number,\n ts: Types.Timing.MicroSeconds, pid: Types.TraceEvents.ProcessID,\n tid: Types.TraceEvents.ThreadID): Types.TraceEvents.SyntheticProfileCall {\n return {\n cat: '',\n name: 'ProfileCall',\n nodeId: node.id,\n args: {},\n ph: Types.TraceEvents.Phase.COMPLETE,\n pid,\n tid,\n ts,\n dur: Types.Timing.MicroSeconds(0),\n callFrame: node.callFrame,\n sampleIndex,\n profileId,\n };\n}\n\n/**\n * Matches beginning events with TraceEventPairableAsyncEnd and TraceEventPairableAsyncInstant (ASYNC_NESTABLE_INSTANT)\n * if provided, though currently only coming from Animations. Traces may contain multiple instant events so we need to\n * account for that.\n *\n * @returns {Map} Map of the animation's ID to it's matching events.\n */\nexport function matchEvents(unpairedEvents: Types.TraceEvents.TraceEventPairableAsync[]):\n Map {\n // map to store begin and end of the event\n const matchedPairs: Map = new Map();\n\n // looking for start and end\n for (const event of unpairedEvents) {\n const syntheticId = getSyntheticId(event);\n if (syntheticId === undefined) {\n continue;\n }\n // Create a synthetic id to prevent collisions across categories.\n // Console timings can be dispatched with the same id, so use the\n // event name as well to generate unique ids.\n const otherEventsWithID = Platform.MapUtilities.getWithDefault(matchedPairs, syntheticId, () => {\n return {begin: null, end: null, instant: []};\n });\n\n const isStartEvent = event.ph === Types.TraceEvents.Phase.ASYNC_NESTABLE_START;\n const isEndEvent = event.ph === Types.TraceEvents.Phase.ASYNC_NESTABLE_END;\n const isInstantEvent = event.ph === Types.TraceEvents.Phase.ASYNC_NESTABLE_INSTANT;\n\n if (isStartEvent) {\n otherEventsWithID.begin = event as Types.TraceEvents.TraceEventPairableAsyncBegin;\n } else if (isEndEvent) {\n otherEventsWithID.end = event as Types.TraceEvents.TraceEventPairableAsyncEnd;\n } else if (isInstantEvent) {\n if (!otherEventsWithID.instant) {\n otherEventsWithID.instant = [];\n }\n otherEventsWithID.instant.push(event as Types.TraceEvents.TraceEventPairableAsyncInstant);\n }\n }\n return matchedPairs;\n}\n\nfunction getSyntheticId(event: Types.TraceEvents.TraceEventPairableAsync): string|undefined {\n const id = extractId(event);\n return id && `${event.cat}:${id}:${event.name}`;\n}\n\nexport function createSortedSyntheticEvents(\n matchedPairs: Map,\n syntheticEventCallback?: (syntheticEvent: MatchedPairType) => void,\n ): MatchedPairType[] {\n const syntheticEvents: MatchedPairType[] = [];\n for (const [id, eventsTriplet] of matchedPairs.entries()) {\n const beginEvent = eventsTriplet.begin;\n const endEvent = eventsTriplet.end;\n const instantEvents = eventsTriplet.instant;\n if (!beginEvent || !(endEvent || instantEvents)) {\n // This should never happen, the backend only creates the events once it\n // has them both (beginEvent & endEvent/instantEvents), so we should never get into this state.\n // If we do, something is very wrong, so let's just drop that problematic event.\n continue;\n }\n const triplet = {beginEvent, endEvent, instantEvents};\n /**\n * When trying to pair events with instant events present, there are times when these\n * ASYNC_NESTABLE_INSTANT ('n') don't have a corresponding ASYNC_NESTABLE_END ('e') event.\n * In these cases, pair without needing the endEvent.\n */\n function eventsArePairable(data: {\n beginEvent: Types.TraceEvents.TraceEventPairableAsyncBegin,\n endEvent: Types.TraceEvents.TraceEventPairableAsyncEnd|null,\n instantEvents?: Types.TraceEvents.TraceEventPairableAsyncInstant[],\n }): data is MatchedPairType['args']['data'] {\n const instantEventsMatch = data.instantEvents ? data.instantEvents.some(e => id === getSyntheticId(e)) : false;\n const endEventMatch = data.endEvent ? id === getSyntheticId(data.endEvent) : false;\n return Boolean(id) && (instantEventsMatch || endEventMatch);\n }\n if (!eventsArePairable(triplet)) {\n continue;\n }\n const targetEvent = endEvent || beginEvent;\n\n const event = SyntheticEventsManager.registerSyntheticBasedEvent>({\n rawSourceEvent: beginEvent,\n cat: targetEvent.cat,\n ph: targetEvent.ph,\n pid: targetEvent.pid,\n tid: targetEvent.tid,\n id,\n // Both events have the same name, so it doesn't matter which we pick to\n // use as the description\n name: beginEvent.name,\n dur: Types.Timing.MicroSeconds(targetEvent.ts - beginEvent.ts),\n ts: beginEvent.ts,\n args: {\n data: triplet,\n },\n });\n\n if (event.dur < 0) {\n // We have seen in the backend that sometimes animation events get\n // generated with multiple begin entries, or multiple end entries, and this\n // can cause invalid data on the performance panel, so we drop them.\n // crbug.com/1472375\n continue;\n }\n syntheticEventCallback?.(event);\n syntheticEvents.push(event);\n }\n return syntheticEvents.sort((a, b) => a.ts - b.ts);\n}\n\nexport function createMatchedSortedSyntheticEvents(\n unpairedAsyncEvents: T[],\n syntheticEventCallback?: (syntheticEvent: MatchedPairType) => void): MatchedPairType[] {\n const matchedPairs = matchEvents(unpairedAsyncEvents);\n const syntheticEvents = createSortedSyntheticEvents(matchedPairs, syntheticEventCallback);\n return syntheticEvents;\n}\n\n/**\n * Different trace events return line/column numbers that are 1 or 0 indexed.\n * This function knows which events return 1 indexed numbers and normalizes\n * them. The UI expects 0 indexed line numbers, so that is what we return.\n */\nexport function getZeroIndexedLineAndColumnForEvent(event: Types.TraceEvents.TraceEventData): {\n lineNumber?: number,\n columnNumber?: number,\n} {\n // Some events emit line numbers that are 1 indexed, but the UI layer expects\n // numbers to be 0 indexed. So here, if the event matches a known 1-indexed\n // number event, we subtract one from the line and column numbers.\n // Otherwise, if the event has args.data.lineNumber/colNumber, we return it\n // as is.\n const numbers = getRawLineAndColumnNumbersForEvent(event);\n const {lineNumber, columnNumber} = numbers;\n\n switch (event.name) {\n // All these events have line/column numbers which are 1 indexed; so we\n // subtract to make them 0 indexed.\n case Types.TraceEvents.KnownEventName.FUNCTION_CALL:\n case Types.TraceEvents.KnownEventName.EVALUATE_SCRIPT:\n case Types.TraceEvents.KnownEventName.COMPILE:\n case Types.TraceEvents.KnownEventName.CACHE_SCRIPT: {\n return {\n lineNumber: typeof lineNumber === 'number' ? lineNumber - 1 : undefined,\n columnNumber: typeof columnNumber === 'number' ? columnNumber - 1 : undefined,\n };\n }\n default: {\n return numbers;\n }\n }\n}\n\n/**\n * Different trace events contain stack traces with line/column numbers\n * that are 1 or 0 indexed.\n * This function knows which events return 1 indexed numbers and normalizes\n * them. The UI expects 0 indexed line numbers, so that is what we return.\n */\nexport function getZeroIndexedStackTraceForEvent(event: Types.TraceEvents.TraceEventData):\n Types.TraceEvents.TraceEventCallFrame[]|null {\n const stack = stackTraceForEvent(event);\n if (!stack) {\n return null;\n }\n return stack.map(callFrame => {\n switch (event.name) {\n case Types.TraceEvents.KnownEventName.SCHEDULE_STYLE_RECALCULATION:\n case Types.TraceEvents.KnownEventName.INVALIDATE_LAYOUT:\n case Types.TraceEvents.KnownEventName.UPDATE_LAYOUT_TREE: {\n return makeZeroBasedCallFrame(callFrame);\n }\n default: {\n if (Types.TraceEvents.isTraceEventUserTiming(event) || Types.Extensions.isSyntheticExtensionEntry(event)) {\n return makeZeroBasedCallFrame(callFrame);\n }\n }\n }\n return callFrame;\n });\n}\n\n/**\n * Given a 1-based call frame creates a 0-based one.\n */\nexport function makeZeroBasedCallFrame(callFrame: Types.TraceEvents.TraceEventCallFrame):\n Types.TraceEvents.TraceEventCallFrame {\n const normalizedCallFrame = {...callFrame};\n\n normalizedCallFrame.lineNumber = callFrame.lineNumber && callFrame.lineNumber - 1;\n normalizedCallFrame.columnNumber = callFrame.columnNumber && callFrame.columnNumber - 1;\n return normalizedCallFrame;\n}\n\n/**\n * NOTE: you probably do not want this function! (Which is why it is not exported).\n *\n * Some trace events have 0 indexed line/column numbers, and others have 1\n * indexed. This function does NOT normalize them, but\n * `getZeroIndexedLineAndColumnNumbersForEvent` does. It is best to use that!\n *\n * @see {@link getZeroIndexedLineAndColumnForEvent}\n **/\nfunction getRawLineAndColumnNumbersForEvent(event: Types.TraceEvents.TraceEventData): {\n lineNumber?: number,\n columnNumber?: number,\n} {\n if (!event.args?.data) {\n return {\n lineNumber: undefined,\n columnNumber: undefined,\n };\n }\n let lineNumber: number|undefined = undefined;\n let columnNumber: number|undefined = undefined;\n if ('lineNumber' in event.args.data && typeof event.args.data.lineNumber === 'number') {\n lineNumber = event.args.data.lineNumber;\n }\n if ('columnNumber' in event.args.data && typeof event.args.data.columnNumber === 'number') {\n columnNumber = event.args.data.columnNumber;\n }\n\n return {lineNumber, columnNumber};\n}\n\nexport function frameIDForEvent(event: Types.TraceEvents.TraceEventData): string|null {\n // There are a few events (for example UpdateLayoutTree, ParseHTML) that have\n // the frame stored in args.beginData\n // Rather than list them all we just check for the presence of the field, so\n // we are robust against future trace events also doing this.\n // This check seems very robust, but it also helps satisfy TypeScript and\n // prevents us against unexpected data.\n if (event.args && 'beginData' in event.args && typeof event.args.beginData === 'object' &&\n event.args.beginData !== null && 'frame' in event.args.beginData &&\n typeof event.args.beginData.frame === 'string') {\n return event.args.beginData.frame;\n }\n // Otherwise, we expect frame to be in args.data\n if (event.args?.data?.frame) {\n return event.args.data.frame;\n }\n\n // No known frame for this event.\n return null;\n}\n\nconst DevToolsTimelineEventCategory = 'disabled-by-default-devtools.timeline';\nexport function isTopLevelEvent(event: Types.TraceEvents.TraceEventData): boolean {\n if (event.name === 'JSRoot' && event.cat === 'toplevel') {\n // This is used in TimelineJSProfile to insert a fake event prior to the\n // CPU Profile in order to ensure the trace isn't truncated. So if we see\n // this, we want to treat it as a top level event.\n // TODO(crbug.com/341234884): do we need this?\n return true;\n }\n return event.cat.includes(DevToolsTimelineEventCategory) && event.name === Types.TraceEvents.KnownEventName.RUN_TASK;\n}\n\nfunction topLevelEventIndexEndingAfter(\n events: Types.TraceEvents.TraceEventData[], time: Types.Timing.MicroSeconds): number {\n let index = Platform.ArrayUtilities.upperBound(events, time, (time, event) => time - event.ts) - 1;\n while (index > 0 && !isTopLevelEvent(events[index])) {\n index--;\n }\n return Math.max(index, 0);\n}\nexport function findUpdateLayoutTreeEvents(\n events: Types.TraceEvents.TraceEventData[], startTime: Types.Timing.MicroSeconds,\n endTime?: Types.Timing.MicroSeconds): Types.TraceEvents.TraceEventUpdateLayoutTree[] {\n const foundEvents: Types.TraceEvents.TraceEventUpdateLayoutTree[] = [];\n const startEventIndex = topLevelEventIndexEndingAfter(events, startTime);\n for (let i = startEventIndex; i < events.length; i++) {\n const event = events[i];\n if (!Types.TraceEvents.isTraceEventUpdateLayoutTree(event)) {\n continue;\n }\n if (event.ts >= (endTime || Infinity)) {\n continue;\n }\n foundEvents.push(event);\n }\n return foundEvents;\n}\n\nexport interface ForEachEventConfig {\n onStartEvent: (event: Types.TraceEvents.TraceEventData) => void;\n onEndEvent: (event: Types.TraceEvents.TraceEventData) => void;\n onInstantEvent?: (event: Types.TraceEvents.TraceEventData) => void;\n eventFilter?: (event: Types.TraceEvents.TraceEventData) => boolean;\n startTime?: Types.Timing.MicroSeconds;\n endTime?: Types.Timing.MicroSeconds;\n /* If async events should be skipped. Defaults to true */\n ignoreAsyncEvents?: boolean;\n}\n\n/**\n * Iterates events in a tree hierarchically, from top to bottom,\n * calling back on every event's start and end in the order\n * dictated by the corresponding timestamp.\n *\n * Events are assumed to be in ascendent order by timestamp.\n *\n * Events with 0 duration are treated as instant events. These do not have a\n * begin and end, but will be passed to the config.onInstantEvent callback as\n * they are discovered. Do not provide this callback if you are not interested\n * in them.\n *\n * For example, given this tree, the following callbacks\n * are expected to be made in the following order\n * |---------------A---------------|\n * |------B------||-------D------|\n * |---C---|\n *\n * 1. Start A\n * 3. Start B\n * 4. Start C\n * 5. End C\n * 6. End B\n * 7. Start D\n * 8. End D\n * 9. End A\n *\n * By default, async events are skipped. This behaviour can be\n * overriden making use of the config.ignoreAsyncEvents parameter.\n */\nexport function forEachEvent(\n events: Types.TraceEvents.TraceEventData[],\n config: ForEachEventConfig,\n ): void {\n const globalStartTime = config.startTime ?? Types.Timing.MicroSeconds(0);\n const globalEndTime = config.endTime || Types.Timing.MicroSeconds(Infinity);\n const ignoreAsyncEvents = config.ignoreAsyncEvents === false ? false : true;\n\n const stack: Types.TraceEvents.TraceEventData[] = [];\n const startEventIndex = topLevelEventIndexEndingAfter(events, globalStartTime);\n for (let i = startEventIndex; i < events.length; i++) {\n const currentEvent = events[i];\n const currentEventTimings = eventTimingsMicroSeconds(currentEvent);\n if (currentEventTimings.endTime < globalStartTime) {\n continue;\n }\n if (currentEventTimings.startTime > globalEndTime) {\n break;\n }\n\n const isIgnoredAsyncEvent = ignoreAsyncEvents && Types.TraceEvents.isAsyncPhase(currentEvent.ph);\n if (isIgnoredAsyncEvent || Types.TraceEvents.isFlowPhase(currentEvent.ph)) {\n continue;\n }\n\n // If we have now reached an event that is after a bunch of events, we need\n // to call the onEndEvent callback for those events before moving on.\n let lastEventOnStack = stack.at(-1);\n let lastEventEndTime = lastEventOnStack ? eventTimingsMicroSeconds(lastEventOnStack).endTime : null;\n while (lastEventOnStack && lastEventEndTime && lastEventEndTime <= currentEventTimings.startTime) {\n stack.pop();\n config.onEndEvent(lastEventOnStack);\n lastEventOnStack = stack.at(-1);\n lastEventEndTime = lastEventOnStack ? eventTimingsMicroSeconds(lastEventOnStack).endTime : null;\n }\n\n // Now we have dealt with all events prior to this one, see if we need to care about this one.\n if (config.eventFilter && !config.eventFilter(currentEvent)) {\n // The user has chosen to filter this event out, so continue on and do nothing\n continue;\n }\n\n if (currentEventTimings.duration) {\n config.onStartEvent(currentEvent);\n stack.push(currentEvent);\n } else if (config.onInstantEvent) {\n // An event with 0 duration is an instant event.\n config.onInstantEvent(currentEvent);\n }\n }\n\n // Now we have finished looping over all events; any events remaining on the\n // stack need to have their onEndEvent called.\n while (stack.length) {\n const last = stack.pop();\n if (last) {\n config.onEndEvent(last);\n }\n }\n}\n\n// Parsed categories are cached to prevent calling cat.split()\n// multiple times on the same categories string.\nconst parsedCategories = new Map>();\nexport function eventHasCategory(event: Types.TraceEvents.TraceEventData, category: string): boolean {\n let parsedCategoriesForEvent = parsedCategories.get(event.cat);\n if (!parsedCategoriesForEvent) {\n parsedCategoriesForEvent = new Set(event.cat.split(',') || []);\n }\n return parsedCategoriesForEvent.has(category);\n}\n\nexport function nodeIdForInvalidationEvent(event: Types.TraceEvents.InvalidationTrackingEvent):\n Protocol.DOM.BackendNodeId|null {\n return event.args.data.nodeId ?? null;\n}\n"]} \ No newline at end of file +{"version":3,"file":"Trace.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/Trace.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../../core/common/common.js';\nimport * as Platform from '../../../core/platform/platform.js';\nimport type * as Protocol from '../../../generated/protocol.js';\nimport type * as CPUProfile from '../../cpu_profile/cpu_profile.js';\nimport * as Types from '../types/types.js';\n\nimport {SyntheticEventsManager} from './SyntheticEvents.js';\nimport {eventTimingsMicroSeconds} from './Timing.js';\n\ntype MatchedPairType = Types.Events.SyntheticEventPair;\ntype MatchingPairableAsyncEvents = {\n begin: Types.Events.PairableAsyncBegin|null,\n end: Types.Events.PairableAsyncEnd|null,\n instant?: Types.Events.PairableAsyncInstant[],\n};\n\n/**\n * Extracts the raw stack trace of known trace events. Most likely than\n * not you want to use `getZeroIndexedStackTraceForEvent`, which returns\n * the stack with zero based numbering. Since some trace events are\n * one based this function can yield unexpected results when used\n * indiscriminately.\n */\nexport function stackTraceForEvent(event: Types.Events.Event): Types.Events.CallFrame[]|null {\n if (event.args?.data?.stackTrace) {\n return event.args.data.stackTrace;\n }\n if (event.args?.stackTrace) {\n return event.args.stackTrace;\n }\n if (Types.Events.isUpdateLayoutTree(event)) {\n return event.args.beginData?.stackTrace || null;\n }\n if (Types.Extensions.isSyntheticExtensionEntry(event)) {\n return stackTraceForEvent(event.rawSourceEvent);\n }\n if (Types.Events.isSyntheticUserTiming(event)) {\n return stackTraceForEvent(event.rawSourceEvent);\n }\n return null;\n}\n\nexport function extractOriginFromTrace(firstNavigationURL: string): string|null {\n const url = Common.ParsedURL.ParsedURL.fromString(firstNavigationURL);\n if (url) {\n // We do this to save some space in the toolbar - seeing the `www` is less\n // useful than seeing `foo.com` if it's truncated at narrow widths\n if (url.host.startsWith('www.')) {\n return url.host.slice(4);\n }\n return url.host;\n }\n return null;\n}\n\nexport type EventsInThread = Map;\n// Each thread contains events. Events indicate the thread and process IDs, which are\n// used to store the event in the correct process thread entry below.\nexport function addEventToProcessThread(\n event: T,\n eventsInProcessThread: Map>,\n ): void {\n const {tid, pid} = event;\n let eventsInThread = eventsInProcessThread.get(pid);\n if (!eventsInThread) {\n eventsInThread = new Map();\n }\n\n let events = eventsInThread.get(tid);\n if (!events) {\n events = [];\n }\n\n events.push(event);\n eventsInThread.set(event.tid, events);\n eventsInProcessThread.set(event.pid, eventsInThread);\n}\n\ntype TimeSpan = {\n ts: Types.Timing.MicroSeconds,\n dur?: Types.Timing.MicroSeconds,\n};\nexport function eventTimeComparator(a: TimeSpan, b: TimeSpan): -1|0|1 {\n const aBeginTime = a.ts;\n const bBeginTime = b.ts;\n if (aBeginTime < bBeginTime) {\n return -1;\n }\n if (aBeginTime > bBeginTime) {\n return 1;\n }\n const aDuration = a.dur ?? 0;\n const bDuration = b.dur ?? 0;\n const aEndTime = aBeginTime + aDuration;\n const bEndTime = bBeginTime + bDuration;\n if (aEndTime > bEndTime) {\n return -1;\n }\n if (aEndTime < bEndTime) {\n return 1;\n }\n return 0;\n}\n/**\n * Sorts all the events in place, in order, by their start time. If they have\n * the same start time, orders them by longest first.\n */\nexport function sortTraceEventsInPlace(events: {ts: Types.Timing.MicroSeconds, dur?: Types.Timing.MicroSeconds}[]):\n void {\n events.sort(eventTimeComparator);\n}\n\n/**\n * Returns an array of ordered events that results after merging the two\n * ordered input arrays.\n */\nexport function mergeEventsInOrder(\n eventsArray1: readonly T1[], eventsArray2: readonly T2[]): (T1|T2)[] {\n const result = [];\n let i = 0;\n let j = 0;\n while (i < eventsArray1.length && j < eventsArray2.length) {\n const event1 = eventsArray1[i];\n const event2 = eventsArray2[j];\n const compareValue = eventTimeComparator(event1, event2);\n if (compareValue <= 0) {\n result.push(event1);\n i++;\n }\n if (compareValue === 1) {\n result.push(event2);\n j++;\n }\n }\n while (i < eventsArray1.length) {\n result.push(eventsArray1[i++]);\n }\n while (j < eventsArray2.length) {\n result.push(eventsArray2[j++]);\n }\n return result;\n}\n\nexport function getNavigationForTraceEvent(\n event: Types.Events.Event,\n eventFrameId: string,\n navigationsByFrameId: Map,\n ): Types.Events.NavigationStart|null {\n const navigations = navigationsByFrameId.get(eventFrameId);\n if (!navigations || eventFrameId === '') {\n // This event's navigation has been filtered out by the meta handler as a noise event\n // or contains an empty frameId.\n return null;\n }\n\n const eventNavigationIndex =\n Platform.ArrayUtilities.nearestIndexFromEnd(navigations, navigation => navigation.ts <= event.ts);\n\n if (eventNavigationIndex === null) {\n // This event's navigation has been filtered out by the meta handler as a noise event.\n return null;\n }\n return navigations[eventNavigationIndex];\n}\n\nexport function extractId(event: Types.Events.PairableAsync|MatchedPairType): string|\n undefined {\n return event.id ?? event.id2?.global ?? event.id2?.local;\n}\n\nexport function activeURLForFrameAtTime(\n frameId: string, time: Types.Timing.MicroSeconds,\n rendererProcessesByFrame: Map<\n string,\n Map>):\n string|null {\n const processData = rendererProcessesByFrame.get(frameId);\n if (!processData) {\n return null;\n }\n for (const processes of processData.values()) {\n for (const processInfo of processes) {\n if (processInfo.window.min > time || processInfo.window.max < time) {\n continue;\n }\n return processInfo.frame.url;\n }\n }\n return null;\n}\n\n/**\n * @param node the node attached to the profile call. Here a node represents a function in the call tree.\n * @param profileId the profile ID that the sample came from that backs this call.\n * @param sampleIndex the index of the sample in the given profile that this call was created from\n * @param ts the timestamp of the profile call\n * @param pid the process ID of the profile call\n * @param tid the thread ID of the profile call\n *\n * See `panels/timeline/docs/profile_calls.md` for more context on how these events are created.\n */\nexport function makeProfileCall(\n node: CPUProfile.ProfileTreeModel.ProfileNode, profileId: Types.Events.ProfileID, sampleIndex: number,\n ts: Types.Timing.MicroSeconds, pid: Types.Events.ProcessID,\n tid: Types.Events.ThreadID): Types.Events.SyntheticProfileCall {\n return {\n cat: '',\n name: 'ProfileCall',\n nodeId: node.id,\n args: {},\n ph: Types.Events.Phase.COMPLETE,\n pid,\n tid,\n ts,\n dur: Types.Timing.MicroSeconds(0),\n callFrame: node.callFrame,\n sampleIndex,\n profileId,\n };\n}\n\n/**\n * Matches beginning events with PairableAsyncEnd and PairableAsyncInstant (ASYNC_NESTABLE_INSTANT)\n * if provided, though currently only coming from Animations. Traces may contain multiple instant events so we need to\n * account for that.\n *\n * @returns {Map} Map of the animation's ID to it's matching events.\n */\nexport function matchEvents(unpairedEvents: Types.Events.PairableAsync[]): Map {\n // map to store begin and end of the event\n const matchedPairs: Map = new Map();\n\n // looking for start and end\n for (const event of unpairedEvents) {\n const syntheticId = getSyntheticId(event);\n if (syntheticId === undefined) {\n continue;\n }\n // Create a synthetic id to prevent collisions across categories.\n // Console timings can be dispatched with the same id, so use the\n // event name as well to generate unique ids.\n const otherEventsWithID = Platform.MapUtilities.getWithDefault(matchedPairs, syntheticId, () => {\n return {begin: null, end: null, instant: []};\n });\n\n const isStartEvent = event.ph === Types.Events.Phase.ASYNC_NESTABLE_START;\n const isEndEvent = event.ph === Types.Events.Phase.ASYNC_NESTABLE_END;\n const isInstantEvent = event.ph === Types.Events.Phase.ASYNC_NESTABLE_INSTANT;\n\n if (isStartEvent) {\n otherEventsWithID.begin = event as Types.Events.PairableAsyncBegin;\n } else if (isEndEvent) {\n otherEventsWithID.end = event as Types.Events.PairableAsyncEnd;\n } else if (isInstantEvent) {\n if (!otherEventsWithID.instant) {\n otherEventsWithID.instant = [];\n }\n otherEventsWithID.instant.push(event as Types.Events.PairableAsyncInstant);\n }\n }\n return matchedPairs;\n}\n\nfunction getSyntheticId(event: Types.Events.PairableAsync): string|undefined {\n const id = extractId(event);\n return id && `${event.cat}:${id}:${event.name}`;\n}\n\nexport function createSortedSyntheticEvents(\n matchedPairs: Map,\n syntheticEventCallback?: (syntheticEvent: MatchedPairType) => void,\n ): MatchedPairType[] {\n const syntheticEvents: MatchedPairType[] = [];\n for (const [id, eventsTriplet] of matchedPairs.entries()) {\n const beginEvent = eventsTriplet.begin;\n const endEvent = eventsTriplet.end;\n const instantEvents = eventsTriplet.instant;\n if (!beginEvent || !(endEvent || instantEvents)) {\n // This should never happen, the backend only creates the events once it\n // has them both (beginEvent & endEvent/instantEvents), so we should never get into this state.\n // If we do, something is very wrong, so let's just drop that problematic event.\n continue;\n }\n const triplet = {beginEvent, endEvent, instantEvents};\n /**\n * When trying to pair events with instant events present, there are times when these\n * ASYNC_NESTABLE_INSTANT ('n') don't have a corresponding ASYNC_NESTABLE_END ('e') event.\n * In these cases, pair without needing the endEvent.\n */\n function eventsArePairable(data: {\n beginEvent: Types.Events.PairableAsyncBegin,\n endEvent: Types.Events.PairableAsyncEnd|null,\n instantEvents?: Types.Events.PairableAsyncInstant[],\n }): data is MatchedPairType['args']['data'] {\n const instantEventsMatch = data.instantEvents ? data.instantEvents.some(e => id === getSyntheticId(e)) : false;\n const endEventMatch = data.endEvent ? id === getSyntheticId(data.endEvent) : false;\n return Boolean(id) && (instantEventsMatch || endEventMatch);\n }\n if (!eventsArePairable(triplet)) {\n continue;\n }\n const targetEvent = endEvent || beginEvent;\n\n const event = SyntheticEventsManager.registerSyntheticEvent>({\n rawSourceEvent: beginEvent,\n cat: targetEvent.cat,\n ph: targetEvent.ph,\n pid: targetEvent.pid,\n tid: targetEvent.tid,\n id,\n // Both events have the same name, so it doesn't matter which we pick to\n // use as the description\n name: beginEvent.name,\n dur: Types.Timing.MicroSeconds(targetEvent.ts - beginEvent.ts),\n ts: beginEvent.ts,\n args: {\n data: triplet,\n },\n });\n\n if (event.dur < 0) {\n // We have seen in the backend that sometimes animation events get\n // generated with multiple begin entries, or multiple end entries, and this\n // can cause invalid data on the performance panel, so we drop them.\n // crbug.com/1472375\n continue;\n }\n syntheticEventCallback?.(event);\n syntheticEvents.push(event);\n }\n return syntheticEvents.sort((a, b) => a.ts - b.ts);\n}\n\nexport function createMatchedSortedSyntheticEvents(\n unpairedAsyncEvents: T[],\n syntheticEventCallback?: (syntheticEvent: MatchedPairType) => void): MatchedPairType[] {\n const matchedPairs = matchEvents(unpairedAsyncEvents);\n const syntheticEvents = createSortedSyntheticEvents(matchedPairs, syntheticEventCallback);\n return syntheticEvents;\n}\n\n/**\n * Different trace events return line/column numbers that are 1 or 0 indexed.\n * This function knows which events return 1 indexed numbers and normalizes\n * them. The UI expects 0 indexed line numbers, so that is what we return.\n */\nexport function getZeroIndexedLineAndColumnForEvent(event: Types.Events.Event): {\n lineNumber?: number,\n columnNumber?: number,\n} {\n // Some events emit line numbers that are 1 indexed, but the UI layer expects\n // numbers to be 0 indexed. So here, if the event matches a known 1-indexed\n // number event, we subtract one from the line and column numbers.\n // Otherwise, if the event has args.data.lineNumber/colNumber, we return it\n // as is.\n const numbers = getRawLineAndColumnNumbersForEvent(event);\n const {lineNumber, columnNumber} = numbers;\n\n switch (event.name) {\n // All these events have line/column numbers which are 1 indexed; so we\n // subtract to make them 0 indexed.\n case Types.Events.Name.FUNCTION_CALL:\n case Types.Events.Name.EVALUATE_SCRIPT:\n case Types.Events.Name.COMPILE:\n case Types.Events.Name.CACHE_SCRIPT: {\n return {\n lineNumber: typeof lineNumber === 'number' ? lineNumber - 1 : undefined,\n columnNumber: typeof columnNumber === 'number' ? columnNumber - 1 : undefined,\n };\n }\n default: {\n return numbers;\n }\n }\n}\n\n/**\n * Different trace events contain stack traces with line/column numbers\n * that are 1 or 0 indexed.\n * This function knows which events return 1 indexed numbers and normalizes\n * them. The UI expects 0 indexed line numbers, so that is what we return.\n */\nexport function getZeroIndexedStackTraceForEvent(event: Types.Events.Event): Types.Events.CallFrame[]|null {\n const stack = stackTraceForEvent(event);\n if (!stack) {\n return null;\n }\n return stack.map(callFrame => {\n switch (event.name) {\n case Types.Events.Name.SCHEDULE_STYLE_RECALCULATION:\n case Types.Events.Name.INVALIDATE_LAYOUT:\n case Types.Events.Name.UPDATE_LAYOUT_TREE: {\n return makeZeroBasedCallFrame(callFrame);\n }\n default: {\n if (Types.Events.isUserTiming(event) || Types.Extensions.isSyntheticExtensionEntry(event)) {\n return makeZeroBasedCallFrame(callFrame);\n }\n }\n }\n return callFrame;\n });\n}\n\n/**\n * Given a 1-based call frame creates a 0-based one.\n */\nexport function makeZeroBasedCallFrame(callFrame: Types.Events.CallFrame): Types.Events.CallFrame {\n const normalizedCallFrame = {...callFrame};\n\n normalizedCallFrame.lineNumber = callFrame.lineNumber && callFrame.lineNumber - 1;\n normalizedCallFrame.columnNumber = callFrame.columnNumber && callFrame.columnNumber - 1;\n return normalizedCallFrame;\n}\n\n/**\n * NOTE: you probably do not want this function! (Which is why it is not exported).\n *\n * Some trace events have 0 indexed line/column numbers, and others have 1\n * indexed. This function does NOT normalize them, but\n * `getZeroIndexedLineAndColumnNumbersForEvent` does. It is best to use that!\n *\n * @see {@link getZeroIndexedLineAndColumnForEvent}\n **/\nfunction getRawLineAndColumnNumbersForEvent(event: Types.Events.Event): {\n lineNumber?: number,\n columnNumber?: number,\n} {\n if (!event.args?.data) {\n return {\n lineNumber: undefined,\n columnNumber: undefined,\n };\n }\n let lineNumber: number|undefined = undefined;\n let columnNumber: number|undefined = undefined;\n if ('lineNumber' in event.args.data && typeof event.args.data.lineNumber === 'number') {\n lineNumber = event.args.data.lineNumber;\n }\n if ('columnNumber' in event.args.data && typeof event.args.data.columnNumber === 'number') {\n columnNumber = event.args.data.columnNumber;\n }\n\n return {lineNumber, columnNumber};\n}\n\nexport function frameIDForEvent(event: Types.Events.Event): string|null {\n // There are a few events (for example UpdateLayoutTree, ParseHTML) that have\n // the frame stored in args.beginData\n // Rather than list them all we just check for the presence of the field, so\n // we are robust against future trace events also doing this.\n // This check seems very robust, but it also helps satisfy TypeScript and\n // prevents us against unexpected data.\n if (event.args && 'beginData' in event.args && typeof event.args.beginData === 'object' &&\n event.args.beginData !== null && 'frame' in event.args.beginData &&\n typeof event.args.beginData.frame === 'string') {\n return event.args.beginData.frame;\n }\n // Otherwise, we expect frame to be in args.data\n if (event.args?.data?.frame) {\n return event.args.data.frame;\n }\n\n // No known frame for this event.\n return null;\n}\n\nconst DevToolsTimelineEventCategory = 'disabled-by-default-devtools.timeline';\nexport function isTopLevelEvent(event: Types.Events.Event): boolean {\n if (event.name === 'JSRoot' && event.cat === 'toplevel') {\n // This is used in TimelineJSProfile to insert a fake event prior to the\n // CPU Profile in order to ensure the trace isn't truncated. So if we see\n // this, we want to treat it as a top level event.\n // TODO(crbug.com/341234884): do we need this?\n return true;\n }\n return event.cat.includes(DevToolsTimelineEventCategory) && event.name === Types.Events.Name.RUN_TASK;\n}\n\nfunction topLevelEventIndexEndingAfter(events: Types.Events.Event[], time: Types.Timing.MicroSeconds): number {\n let index = Platform.ArrayUtilities.upperBound(events, time, (time, event) => time - event.ts) - 1;\n while (index > 0 && !isTopLevelEvent(events[index])) {\n index--;\n }\n return Math.max(index, 0);\n}\nexport function findUpdateLayoutTreeEvents(\n events: Types.Events.Event[], startTime: Types.Timing.MicroSeconds,\n endTime?: Types.Timing.MicroSeconds): Types.Events.UpdateLayoutTree[] {\n const foundEvents: Types.Events.UpdateLayoutTree[] = [];\n const startEventIndex = topLevelEventIndexEndingAfter(events, startTime);\n for (let i = startEventIndex; i < events.length; i++) {\n const event = events[i];\n if (!Types.Events.isUpdateLayoutTree(event)) {\n continue;\n }\n if (event.ts >= (endTime || Infinity)) {\n continue;\n }\n foundEvents.push(event);\n }\n return foundEvents;\n}\n\nexport interface ForEachEventConfig {\n onStartEvent: (event: Types.Events.Event) => void;\n onEndEvent: (event: Types.Events.Event) => void;\n onInstantEvent?: (event: Types.Events.Event) => void;\n eventFilter?: (event: Types.Events.Event) => boolean;\n startTime?: Types.Timing.MicroSeconds;\n endTime?: Types.Timing.MicroSeconds;\n /* If async events should be skipped. Defaults to true */\n ignoreAsyncEvents?: boolean;\n}\n\n/**\n * Iterates events in a tree hierarchically, from top to bottom,\n * calling back on every event's start and end in the order\n * dictated by the corresponding timestamp.\n *\n * Events are assumed to be in ascendent order by timestamp.\n *\n * Events with 0 duration are treated as instant events. These do not have a\n * begin and end, but will be passed to the config.onInstantEvent callback as\n * they are discovered. Do not provide this callback if you are not interested\n * in them.\n *\n * For example, given this tree, the following callbacks\n * are expected to be made in the following order\n * |---------------A---------------|\n * |------B------||-------D------|\n * |---C---|\n *\n * 1. Start A\n * 3. Start B\n * 4. Start C\n * 5. End C\n * 6. End B\n * 7. Start D\n * 8. End D\n * 9. End A\n *\n * By default, async events are skipped. This behaviour can be\n * overriden making use of the config.ignoreAsyncEvents parameter.\n */\nexport function forEachEvent(\n events: Types.Events.Event[],\n config: ForEachEventConfig,\n ): void {\n const globalStartTime = config.startTime ?? Types.Timing.MicroSeconds(0);\n const globalEndTime = config.endTime || Types.Timing.MicroSeconds(Infinity);\n const ignoreAsyncEvents = config.ignoreAsyncEvents === false ? false : true;\n\n const stack: Types.Events.Event[] = [];\n const startEventIndex = topLevelEventIndexEndingAfter(events, globalStartTime);\n for (let i = startEventIndex; i < events.length; i++) {\n const currentEvent = events[i];\n const currentEventTimings = eventTimingsMicroSeconds(currentEvent);\n if (currentEventTimings.endTime < globalStartTime) {\n continue;\n }\n if (currentEventTimings.startTime > globalEndTime) {\n break;\n }\n\n const isIgnoredAsyncEvent = ignoreAsyncEvents && Types.Events.isPhaseAsync(currentEvent.ph);\n if (isIgnoredAsyncEvent || Types.Events.isFlowPhase(currentEvent.ph)) {\n continue;\n }\n\n // If we have now reached an event that is after a bunch of events, we need\n // to call the onEndEvent callback for those events before moving on.\n let lastEventOnStack = stack.at(-1);\n let lastEventEndTime = lastEventOnStack ? eventTimingsMicroSeconds(lastEventOnStack).endTime : null;\n while (lastEventOnStack && lastEventEndTime && lastEventEndTime <= currentEventTimings.startTime) {\n stack.pop();\n config.onEndEvent(lastEventOnStack);\n lastEventOnStack = stack.at(-1);\n lastEventEndTime = lastEventOnStack ? eventTimingsMicroSeconds(lastEventOnStack).endTime : null;\n }\n\n // Now we have dealt with all events prior to this one, see if we need to care about this one.\n if (config.eventFilter && !config.eventFilter(currentEvent)) {\n // The user has chosen to filter this event out, so continue on and do nothing\n continue;\n }\n\n if (currentEventTimings.duration) {\n config.onStartEvent(currentEvent);\n stack.push(currentEvent);\n } else if (config.onInstantEvent) {\n // An event with 0 duration is an instant event.\n config.onInstantEvent(currentEvent);\n }\n }\n\n // Now we have finished looping over all events; any events remaining on the\n // stack need to have their onEndEvent called.\n while (stack.length) {\n const last = stack.pop();\n if (last) {\n config.onEndEvent(last);\n }\n }\n}\n\n// Parsed categories are cached to prevent calling cat.split()\n// multiple times on the same categories string.\nconst parsedCategories = new Map>();\nexport function eventHasCategory(event: Types.Events.Event, category: string): boolean {\n let parsedCategoriesForEvent = parsedCategories.get(event.cat);\n if (!parsedCategoriesForEvent) {\n parsedCategoriesForEvent = new Set(event.cat.split(',') || []);\n }\n return parsedCategoriesForEvent.has(category);\n}\n\nexport function nodeIdForInvalidationEvent(event: Types.Events.InvalidationTrackingEvent): Protocol.DOM.BackendNodeId|\n null {\n return event.args.data.nodeId ?? null;\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/helpers/Trace.test.js b/public/models/trace/helpers/Trace.test.js index 6401fb3f2..46103ff33 100644 --- a/public/models/trace/helpers/Trace.test.js +++ b/public/models/trace/helpers/Trace.test.js @@ -4,22 +4,22 @@ import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; import { getMainThread, makeAsyncEndEvent, makeAsyncStartEvent, makeCompleteEvent, makeInstantEvent, } from '../../../testing/TraceHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; -import * as TraceModel from '../trace.js'; +import * as Trace from '../trace.js'; describeWithEnvironment('TraceModel helpers', function () { describe('extractOriginFromTrace', () => { it('extracts the origin of a parsed trace correctly', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const origin = TraceModel.Helpers.Trace.extractOriginFromTrace(traceData.Meta.mainFrameURL); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const origin = Trace.Helpers.Trace.extractOriginFromTrace(parsedTrace.Meta.mainFrameURL); assert.strictEqual(origin, 'web.dev'); }); it('will remove the `www` if it is present', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'multiple-navigations.json.gz'); - const origin = TraceModel.Helpers.Trace.extractOriginFromTrace(traceData.Meta.mainFrameURL); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'multiple-navigations.json.gz'); + const origin = Trace.Helpers.Trace.extractOriginFromTrace(parsedTrace.Meta.mainFrameURL); assert.strictEqual(origin, 'google.com'); }); it('returns null when no origin is found', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'basic.json.gz'); - const origin = TraceModel.Helpers.Trace.extractOriginFromTrace(traceData.Meta.mainFrameURL); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'basic.json.gz'); + const origin = Trace.Helpers.Trace.extractOriginFromTrace(parsedTrace.Meta.mainFrameURL); assert.isNull(origin); }); }); @@ -29,16 +29,16 @@ describeWithEnvironment('TraceModel helpers', function () { name: 'process_name', tid, pid, - ts: TraceModel.Types.Timing.MicroSeconds(0), + ts: Trace.Types.Timing.MicroSeconds(0), cat: 'test', - ph: "M" /* TraceModel.Types.TraceEvents.Phase.METADATA */, + ph: "M" /* Trace.Types.Events.Phase.METADATA */, }; } function pid(x) { - return TraceModel.Types.TraceEvents.ProcessID(x); + return Trace.Types.Events.ProcessID(x); } function tid(x) { - return TraceModel.Types.TraceEvents.ThreadID(x); + return Trace.Types.Events.ThreadID(x); } const eventMap = new Map(); beforeEach(() => { @@ -46,24 +46,24 @@ describeWithEnvironment('TraceModel helpers', function () { }); it('will create a process and thread if it does not exist yet', async () => { const event = makeTraceEvent(pid(1), tid(1)); - TraceModel.Helpers.Trace.addEventToProcessThread(event, eventMap); + Trace.Helpers.Trace.addEventToProcessThread(event, eventMap); assert.strictEqual(eventMap.get(pid(1))?.size, 1); const threadEvents = eventMap.get(pid(1))?.get(tid(1)); assert.strictEqual(threadEvents?.length, 1); }); it('adds new events to existing threads correctly', async () => { const event = makeTraceEvent(pid(1), tid(1)); - TraceModel.Helpers.Trace.addEventToProcessThread(event, eventMap); + Trace.Helpers.Trace.addEventToProcessThread(event, eventMap); const newEvent = makeTraceEvent(pid(1), tid(1)); - TraceModel.Helpers.Trace.addEventToProcessThread(newEvent, eventMap); + Trace.Helpers.Trace.addEventToProcessThread(newEvent, eventMap); assert.deepEqual(eventMap.get(pid(1))?.get(tid(1)), [event, newEvent]); }); }); describe('sortTraceEventsInPlace', () => { function makeFakeEvent(ts, dur) { return { - ts: TraceModel.Types.Timing.MicroSeconds(ts), - dur: TraceModel.Types.Timing.MicroSeconds(dur), + ts: Trace.Types.Timing.MicroSeconds(ts), + dur: Trace.Types.Timing.MicroSeconds(dur), }; } it('sorts by start time in ASC order', () => { @@ -71,7 +71,7 @@ describeWithEnvironment('TraceModel helpers', function () { const event2 = makeFakeEvent(2, 1); const event3 = makeFakeEvent(3, 1); const events = [event3, event1, event2]; - TraceModel.Helpers.Trace.sortTraceEventsInPlace(events); + Trace.Helpers.Trace.sortTraceEventsInPlace(events); assert.deepEqual(events, [event1, event2, event3]); }); it('sorts by longest duration if the timestamps are the same', () => { @@ -79,45 +79,45 @@ describeWithEnvironment('TraceModel helpers', function () { const event2 = makeFakeEvent(1, 2); const event3 = makeFakeEvent(1, 3); const events = [event1, event2, event3]; - TraceModel.Helpers.Trace.sortTraceEventsInPlace(events); + Trace.Helpers.Trace.sortTraceEventsInPlace(events); assert.deepEqual(events, [event3, event2, event1]); }); }); describe('getNavigationForTraceEvent', () => { it('returns the correct navigation for a request', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'multiple-navigations.json.gz'); - const { NetworkRequests, Meta } = traceData; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'multiple-navigations.json.gz'); + const { NetworkRequests, Meta } = parsedTrace; const request1 = NetworkRequests.byTime[0]; - const navigationForFirstRequest = TraceModel.Helpers.Trace.getNavigationForTraceEvent(request1, request1.args.data.frame, Meta.navigationsByFrameId); + const navigationForFirstRequest = Trace.Helpers.Trace.getNavigationForTraceEvent(request1, request1.args.data.frame, Meta.navigationsByFrameId); assert.isUndefined(navigationForFirstRequest?.ts); const request2 = NetworkRequests.byTime[1]; - const navigationForSecondRequest = TraceModel.Helpers.Trace.getNavigationForTraceEvent(request2, request2.args.data.frame, Meta.navigationsByFrameId); - assert.strictEqual(navigationForSecondRequest?.ts, TraceModel.Types.Timing.MicroSeconds(636471400029)); + const navigationForSecondRequest = Trace.Helpers.Trace.getNavigationForTraceEvent(request2, request2.args.data.frame, Meta.navigationsByFrameId); + assert.strictEqual(navigationForSecondRequest?.ts, Trace.Types.Timing.MicroSeconds(636471400029)); }); it('returns the correct navigation for a page load event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'multiple-navigations.json.gz'); - const { Meta, PageLoadMetrics } = traceData; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'multiple-navigations.json.gz'); + const { Meta, PageLoadMetrics } = parsedTrace; const firstNavigationId = Meta.navigationsByNavigationId.keys().next().value; const fcp = PageLoadMetrics.metricScoresByFrameId.get(Meta.mainFrameId) ?.get(firstNavigationId) - ?.get("FCP" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP */); + ?.get("FCP" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP */); if (!fcp || !fcp.event) { assert.fail('FCP not found'); } - const navigationForFirstRequest = TraceModel.Helpers.Trace.getNavigationForTraceEvent(fcp.event, Meta.mainFrameId, Meta.navigationsByFrameId); + const navigationForFirstRequest = Trace.Helpers.Trace.getNavigationForTraceEvent(fcp.event, Meta.mainFrameId, Meta.navigationsByFrameId); assert.strictEqual(navigationForFirstRequest?.args.data?.navigationId, firstNavigationId); }); }); describe('extractId', () => { it('returns the correct id for an event', async () => { const fakeEventWithId = { id: 'id' }; - const id = TraceModel.Helpers.Trace.extractId(fakeEventWithId); + const id = Trace.Helpers.Trace.extractId(fakeEventWithId); assert.strictEqual(id, fakeEventWithId.id); const fakeEventWithGlobalId2 = { id2: { global: 'globalId2' } }; - const globalId2 = TraceModel.Helpers.Trace.extractId(fakeEventWithGlobalId2); + const globalId2 = Trace.Helpers.Trace.extractId(fakeEventWithGlobalId2); assert.strictEqual(globalId2, fakeEventWithGlobalId2.id2?.global); const fakeEventWithLocalId2 = { id2: { local: 'localId2' } }; - const localId2 = TraceModel.Helpers.Trace.extractId(fakeEventWithLocalId2); + const localId2 = Trace.Helpers.Trace.extractId(fakeEventWithLocalId2); assert.strictEqual(localId2, fakeEventWithLocalId2.id2?.local); }); }); @@ -167,7 +167,7 @@ describeWithEnvironment('TraceModel helpers', function () { ts: 9, }, ]; - const ordered = TraceModel.Helpers.Trace.mergeEventsInOrder(array1, array2); + const ordered = Trace.Helpers.Trace.mergeEventsInOrder(array1, array2); for (let i = 1; i < ordered.length; i++) { assert.isAbove(ordered[i].ts, ordered[i - 1].ts); } @@ -226,7 +226,7 @@ describeWithEnvironment('TraceModel helpers', function () { dur: 0, }, ]; - const ordered = TraceModel.Helpers.Trace.mergeEventsInOrder(array1, array2); + const ordered = Trace.Helpers.Trace.mergeEventsInOrder(array1, array2); for (let i = 1; i < ordered.length; i++) { assert.isAbove(ordered[i].ts, ordered[i - 1].ts); } @@ -285,7 +285,7 @@ describeWithEnvironment('TraceModel helpers', function () { dur: 0, }, ]; - const ordered = TraceModel.Helpers.Trace.mergeEventsInOrder(array1, array2); + const ordered = Trace.Helpers.Trace.mergeEventsInOrder(array1, array2); for (let i = 1; i < ordered.length; i++) { const dur = ordered[i].dur; const durPrev = ordered[i - 1].dur; @@ -323,7 +323,7 @@ describeWithEnvironment('TraceModel helpers', function () { }, ]; const array2 = [...array1]; - const ordered = TraceModel.Helpers.Trace.mergeEventsInOrder(array1, array2); + const ordered = Trace.Helpers.Trace.mergeEventsInOrder(array1, array2); for (let i = 1; i < ordered.length; i++) { const dur = ordered[i].dur; const durPrev = ordered[i - 1].dur; @@ -335,19 +335,19 @@ describeWithEnvironment('TraceModel helpers', function () { }); describe('activeURLForFrameAtTime', () => { it('extracts the active url for a frame at a given time', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'simple-js-program.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'simple-js-program.json.gz'); const frameId = '1F729458403A23CF1D8D246095129AC4'; - const firstURL = TraceModel.Helpers.Trace.activeURLForFrameAtTime(frameId, TraceModel.Types.Timing.MicroSeconds(251126654355), traceData.Meta.rendererProcessesByFrame); + const firstURL = Trace.Helpers.Trace.activeURLForFrameAtTime(frameId, Trace.Types.Timing.MicroSeconds(251126654355), parsedTrace.Meta.rendererProcessesByFrame); assert.strictEqual(firstURL, 'about:blank'); - const secondURL = TraceModel.Helpers.Trace.activeURLForFrameAtTime(frameId, TraceModel.Types.Timing.MicroSeconds(251126663398), traceData.Meta.rendererProcessesByFrame); + const secondURL = Trace.Helpers.Trace.activeURLForFrameAtTime(frameId, Trace.Types.Timing.MicroSeconds(251126663398), parsedTrace.Meta.rendererProcessesByFrame); assert.strictEqual(secondURL, 'https://www.google.com'); }); }); describe('createMatchedSortedSyntheticEvents', () => { it('matches up arbitrary async events', async function () { const events = await TraceLoader.rawEvents(this, 'user-timings.json.gz'); - const asyncEvents = events.filter(event => TraceModel.Types.TraceEvents.isTraceEventAsyncPhase(event)); - const synthEvents = TraceModel.Helpers.Trace.createMatchedSortedSyntheticEvents(asyncEvents); + const asyncEvents = events.filter(event => Trace.Types.Events.isPhaseAsync(event.ph)); + const synthEvents = Trace.Helpers.Trace.createMatchedSortedSyntheticEvents(asyncEvents); // There's a lot of events, let's only assert one event per name const seen = new Set(); // Make a readable output of each event to assert @@ -382,8 +382,8 @@ describeWithEnvironment('TraceModel helpers', function () { describe('createSortedSyntheticEvents()', () => { it('correctly creates synthetic events when instant animation events are present', async function () { const events = await TraceLoader.rawEvents(this, 'instant-animation-events.json.gz'); - const animationEvents = events.filter(event => TraceModel.Types.TraceEvents.isTraceEventAnimation(event)); - const animationSynthEvents = TraceModel.Helpers.Trace.createMatchedSortedSyntheticEvents(animationEvents); + const animationEvents = events.filter(event => Trace.Types.Events.isAnimation(event)); + const animationSynthEvents = Trace.Helpers.Trace.createMatchedSortedSyntheticEvents(animationEvents); const wantPairs = new Map([ [ 'blink.animations,devtools.timeline,benchmark,rail:0x11d00230380:Animation', @@ -429,13 +429,13 @@ describeWithEnvironment('TraceModel helpers', function () { describe('getZeroIndexedLineAndColumnNumbersForEvent', () => { it('subtracts one from the line number of a function call', async () => { const fakeFunctionCall = { - name: "FunctionCall" /* TraceModel.Types.TraceEvents.KnownEventName.FUNCTION_CALL */, - ph: "X" /* TraceModel.Types.TraceEvents.Phase.COMPLETE */, + name: "FunctionCall" /* Trace.Types.Events.Name.FUNCTION_CALL */, + ph: "X" /* Trace.Types.Events.Phase.COMPLETE */, cat: 'devtools-timeline', - dur: TraceModel.Types.Timing.MicroSeconds(100), - ts: TraceModel.Types.Timing.MicroSeconds(100), - pid: TraceModel.Types.TraceEvents.ProcessID(1), - tid: TraceModel.Types.TraceEvents.ThreadID(1), + dur: Trace.Types.Timing.MicroSeconds(100), + ts: Trace.Types.Timing.MicroSeconds(100), + pid: Trace.Types.Events.ProcessID(1), + tid: Trace.Types.Events.ThreadID(1), args: { data: { functionName: 'test', @@ -446,7 +446,7 @@ describeWithEnvironment('TraceModel helpers', function () { }, }, }; - assert.deepEqual(TraceModel.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(fakeFunctionCall), { + assert.deepEqual(Trace.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(fakeFunctionCall), { lineNumber: 0, columnNumber: 0, }); @@ -454,46 +454,46 @@ describeWithEnvironment('TraceModel helpers', function () { }); describe('frameIDForEvent', () => { it('returns the frame ID from beginData if the event has it', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); - const parseHTMLEvent = traceData.Renderer.allTraceEntries.find(TraceModel.Types.TraceEvents.isTraceEventParseHTML); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); + const parseHTMLEvent = parsedTrace.Renderer.allTraceEntries.find(Trace.Types.Events.isParseHTML); assert.isOk(parseHTMLEvent); - const frameId = TraceModel.Helpers.Trace.frameIDForEvent(parseHTMLEvent); + const frameId = Trace.Helpers.Trace.frameIDForEvent(parseHTMLEvent); assert.isNotNull(frameId); assert.strictEqual(frameId, parseHTMLEvent.args.beginData.frame); }); it('returns the frame ID from args.data if the event has it', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); - const invalidateLayoutEvent = traceData.Renderer.allTraceEntries.find(TraceModel.Types.TraceEvents.isTraceEventInvalidateLayout); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); + const invalidateLayoutEvent = parsedTrace.Renderer.allTraceEntries.find(Trace.Types.Events.isInvalidateLayout); assert.isOk(invalidateLayoutEvent); - const frameId = TraceModel.Helpers.Trace.frameIDForEvent(invalidateLayoutEvent); + const frameId = Trace.Helpers.Trace.frameIDForEvent(invalidateLayoutEvent); assert.isNotNull(frameId); assert.strictEqual(frameId, invalidateLayoutEvent.args.data.frame); }); it('returns null if the event does not have a frame', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); - const v8CompileEvent = traceData.Renderer.allTraceEntries.find(TraceModel.Types.TraceEvents.isTraceEventV8Compile); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); + const v8CompileEvent = parsedTrace.Renderer.allTraceEntries.find(Trace.Types.Events.isV8Compile); assert.isOk(v8CompileEvent); - const frameId = TraceModel.Helpers.Trace.frameIDForEvent(v8CompileEvent); + const frameId = Trace.Helpers.Trace.frameIDForEvent(v8CompileEvent); assert.isNull(frameId); }); }); describe('findUpdateLayoutTreeEvents', () => { it('returns the set of UpdateLayoutTree events within the right time range', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'selector-stats.json.gz'); - const mainThread = getMainThread(traceData.Renderer); - const foundEvents = TraceModel.Helpers.Trace.findUpdateLayoutTreeEvents(mainThread.entries, traceData.Meta.traceBounds.min); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'selector-stats.json.gz'); + const mainThread = getMainThread(parsedTrace.Renderer); + const foundEvents = Trace.Helpers.Trace.findUpdateLayoutTreeEvents(mainThread.entries, parsedTrace.Meta.traceBounds.min); assert.lengthOf(foundEvents, 11); const lastEvent = foundEvents.at(-1); assert.isOk(lastEvent); // Check we can filter by endTime by making the endTime less than the start // time of the last event: - const filteredByEndTimeEvents = TraceModel.Helpers.Trace.findUpdateLayoutTreeEvents(mainThread.entries, traceData.Meta.traceBounds.min, TraceModel.Types.Timing.MicroSeconds(lastEvent.ts - 1_000)); + const filteredByEndTimeEvents = Trace.Helpers.Trace.findUpdateLayoutTreeEvents(mainThread.entries, parsedTrace.Meta.traceBounds.min, Trace.Types.Timing.MicroSeconds(lastEvent.ts - 1_000)); assert.lengthOf(filteredByEndTimeEvents, 10); }); }); describe('forEachEvent', () => { - const pid = TraceModel.Types.TraceEvents.ProcessID(1); - const tid = TraceModel.Types.TraceEvents.ThreadID(1); + const pid = Trace.Types.Events.ProcessID(1); + const tid = Trace.Types.Events.ThreadID(1); it('iterates through the events in the expected tree-like order', async () => { // |------------- RunTask -------------||-- RunTask --| // |-- RunMicrotasks --||-- Layout --| @@ -507,7 +507,7 @@ describeWithEnvironment('TraceModel helpers', function () { ]; const onStartEvent = sinon.spy(_event => { }); const onEndEvent = sinon.spy(_event => { }); - TraceModel.Helpers.Trace.forEachEvent(traceEvents, { + Trace.Helpers.Trace.forEachEvent(traceEvents, { onEndEvent, onStartEvent, }); @@ -528,11 +528,11 @@ describeWithEnvironment('TraceModel helpers', function () { ]; const onStartEvent = sinon.spy(_event => { }); const onEndEvent = sinon.spy(_event => { }); - TraceModel.Helpers.Trace.forEachEvent(traceEvents, { + Trace.Helpers.Trace.forEachEvent(traceEvents, { onEndEvent, onStartEvent, - startTime: TraceModel.Types.Timing.MicroSeconds(5), - endTime: TraceModel.Types.Timing.MicroSeconds(9), + startTime: Trace.Types.Timing.MicroSeconds(5), + endTime: Trace.Types.Timing.MicroSeconds(9), }); const eventsFromStartEventCalls = onStartEvent.getCalls().map(a => a.args[0]); const eventsFromEndEventCalls = onEndEvent.getCalls().map(a => a.args[0]); @@ -554,7 +554,7 @@ describeWithEnvironment('TraceModel helpers', function () { ]; const onStartEvent = sinon.spy(_event => { }); const onEndEvent = sinon.spy(_event => { }); - TraceModel.Helpers.Trace.forEachEvent(traceEvents, { + Trace.Helpers.Trace.forEachEvent(traceEvents, { onEndEvent, onStartEvent, eventFilter(event) { @@ -573,7 +573,7 @@ describeWithEnvironment('TraceModel helpers', function () { const onStartEvent = sinon.spy(_event => { }); const onEndEvent = sinon.spy(_event => { }); const onInstantEvent = sinon.spy(_event => { }); - TraceModel.Helpers.Trace.forEachEvent(traceEvents, { + Trace.Helpers.Trace.forEachEvent(traceEvents, { onEndEvent, onStartEvent, onInstantEvent, @@ -590,7 +590,7 @@ describeWithEnvironment('TraceModel helpers', function () { const onStartEvent = sinon.spy(_event => { }); const onEndEvent = sinon.spy(_event => { }); const onInstantEvent = sinon.spy(_event => { }); - TraceModel.Helpers.Trace.forEachEvent(traceEvents, { + Trace.Helpers.Trace.forEachEvent(traceEvents, { onEndEvent, onStartEvent, onInstantEvent, @@ -607,7 +607,7 @@ describeWithEnvironment('TraceModel helpers', function () { const onStartEvent = sinon.spy(_event => { }); const onEndEvent = sinon.spy(_event => { }); const onInstantEvent = sinon.spy(_event => { }); - TraceModel.Helpers.Trace.forEachEvent(traceEvents, { + Trace.Helpers.Trace.forEachEvent(traceEvents, { onEndEvent, onStartEvent, onInstantEvent, @@ -620,10 +620,10 @@ describeWithEnvironment('TraceModel helpers', function () { }); describe('isTopLevelEvent', () => { it('is true for a RunTask event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const runTask = traceData.Renderer.allTraceEntries.find(TraceModel.Types.TraceEvents.isTraceEventRunTask); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const runTask = parsedTrace.Renderer.allTraceEntries.find(Trace.Types.Events.isRunTask); assert.isOk(runTask); - assert.isTrue(TraceModel.Helpers.Trace.isTopLevelEvent(runTask)); + assert.isTrue(Trace.Helpers.Trace.isTopLevelEvent(runTask)); }); }); }); diff --git a/public/models/trace/helpers/Trace.test.js.map b/public/models/trace/helpers/Trace.test.js.map index ca023afbb..dc0f1318e 100644 --- a/public/models/trace/helpers/Trace.test.js.map +++ b/public/models/trace/helpers/Trace.test.js.map @@ -1 +1 @@ -{"version":3,"file":"Trace.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/Trace.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {\n getMainThread,\n makeAsyncEndEvent,\n makeAsyncStartEvent,\n makeCompleteEvent,\n makeInstantEvent,\n} from '../../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as TraceModel from '../trace.js';\n\ndescribeWithEnvironment('TraceModel helpers', function() {\n describe('extractOriginFromTrace', () => {\n it('extracts the origin of a parsed trace correctly', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const origin = TraceModel.Helpers.Trace.extractOriginFromTrace(traceData.Meta.mainFrameURL);\n assert.strictEqual(origin, 'web.dev');\n });\n\n it('will remove the `www` if it is present', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'multiple-navigations.json.gz');\n const origin = TraceModel.Helpers.Trace.extractOriginFromTrace(traceData.Meta.mainFrameURL);\n assert.strictEqual(origin, 'google.com');\n });\n\n it('returns null when no origin is found', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'basic.json.gz');\n const origin = TraceModel.Helpers.Trace.extractOriginFromTrace(traceData.Meta.mainFrameURL);\n assert.isNull(origin);\n });\n });\n\n describe('addEventToProcessThread', () => {\n function makeTraceEvent(pid: TraceModel.Types.TraceEvents.ProcessID, tid: TraceModel.Types.TraceEvents.ThreadID):\n TraceModel.Types.TraceEvents.TraceEventData {\n return {\n name: 'process_name',\n tid,\n pid,\n ts: TraceModel.Types.Timing.MicroSeconds(0),\n cat: 'test',\n ph: TraceModel.Types.TraceEvents.Phase.METADATA,\n };\n }\n\n function pid(x: number): TraceModel.Types.TraceEvents.ProcessID {\n return TraceModel.Types.TraceEvents.ProcessID(x);\n }\n function tid(x: number): TraceModel.Types.TraceEvents.ThreadID {\n return TraceModel.Types.TraceEvents.ThreadID(x);\n }\n\n const eventMap = new Map<\n TraceModel.Types.TraceEvents.ProcessID,\n Map>();\n\n beforeEach(() => {\n eventMap.clear();\n });\n\n it('will create a process and thread if it does not exist yet', async () => {\n const event = makeTraceEvent(pid(1), tid(1));\n TraceModel.Helpers.Trace.addEventToProcessThread(event, eventMap);\n assert.strictEqual(eventMap.get(pid(1))?.size, 1);\n const threadEvents = eventMap.get(pid(1))?.get(tid(1));\n assert.strictEqual(threadEvents?.length, 1);\n });\n\n it('adds new events to existing threads correctly', async () => {\n const event = makeTraceEvent(pid(1), tid(1));\n TraceModel.Helpers.Trace.addEventToProcessThread(event, eventMap);\n const newEvent = makeTraceEvent(pid(1), tid(1));\n TraceModel.Helpers.Trace.addEventToProcessThread(newEvent, eventMap);\n assert.deepEqual(eventMap.get(pid(1))?.get(tid(1)), [event, newEvent]);\n });\n });\n\n describe('sortTraceEventsInPlace', () => {\n function makeFakeEvent(ts: number, dur: number): TraceModel.Types.TraceEvents.TraceEventData {\n return {\n ts: TraceModel.Types.Timing.MicroSeconds(ts),\n dur: TraceModel.Types.Timing.MicroSeconds(dur),\n } as unknown as TraceModel.Types.TraceEvents.TraceEventData;\n }\n\n it('sorts by start time in ASC order', () => {\n const event1 = makeFakeEvent(1, 1);\n const event2 = makeFakeEvent(2, 1);\n const event3 = makeFakeEvent(3, 1);\n const events = [event3, event1, event2];\n TraceModel.Helpers.Trace.sortTraceEventsInPlace(events);\n assert.deepEqual(events, [event1, event2, event3]);\n });\n\n it('sorts by longest duration if the timestamps are the same', () => {\n const event1 = makeFakeEvent(1, 1);\n const event2 = makeFakeEvent(1, 2);\n const event3 = makeFakeEvent(1, 3);\n const events = [event1, event2, event3];\n TraceModel.Helpers.Trace.sortTraceEventsInPlace(events);\n assert.deepEqual(events, [event3, event2, event1]);\n });\n });\n\n describe('getNavigationForTraceEvent', () => {\n it('returns the correct navigation for a request', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'multiple-navigations.json.gz');\n const {NetworkRequests, Meta} = traceData;\n const request1 = NetworkRequests.byTime[0];\n const navigationForFirstRequest = TraceModel.Helpers.Trace.getNavigationForTraceEvent(\n request1, request1.args.data.frame, Meta.navigationsByFrameId);\n assert.isUndefined(navigationForFirstRequest?.ts);\n\n const request2 = NetworkRequests.byTime[1];\n const navigationForSecondRequest = TraceModel.Helpers.Trace.getNavigationForTraceEvent(\n request2, request2.args.data.frame, Meta.navigationsByFrameId);\n assert.strictEqual(navigationForSecondRequest?.ts, TraceModel.Types.Timing.MicroSeconds(636471400029));\n });\n\n it('returns the correct navigation for a page load event', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'multiple-navigations.json.gz');\n const {Meta, PageLoadMetrics} = traceData;\n const firstNavigationId = Meta.navigationsByNavigationId.keys().next().value;\n\n const fcp = PageLoadMetrics.metricScoresByFrameId.get(Meta.mainFrameId)\n ?.get(firstNavigationId)\n ?.get(TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP);\n if (!fcp || !fcp.event) {\n assert.fail('FCP not found');\n }\n const navigationForFirstRequest =\n TraceModel.Helpers.Trace.getNavigationForTraceEvent(fcp.event, Meta.mainFrameId, Meta.navigationsByFrameId);\n assert.strictEqual(navigationForFirstRequest?.args.data?.navigationId, firstNavigationId);\n });\n });\n\n describe('extractId', () => {\n it('returns the correct id for an event', async () => {\n const fakeEventWithId = {id: 'id'} as unknown as TraceModel.Types.TraceEvents.TraceEventPairableAsync;\n const id = TraceModel.Helpers.Trace.extractId(fakeEventWithId);\n assert.strictEqual(id, fakeEventWithId.id);\n\n const fakeEventWithGlobalId2 = {id2: {global: 'globalId2'}} as unknown as\n TraceModel.Types.TraceEvents.TraceEventPairableAsync;\n const globalId2 = TraceModel.Helpers.Trace.extractId(fakeEventWithGlobalId2);\n assert.strictEqual(globalId2, fakeEventWithGlobalId2.id2?.global);\n\n const fakeEventWithLocalId2 = {id2: {local: 'localId2'}} as unknown as\n TraceModel.Types.TraceEvents.TraceEventPairableAsync;\n const localId2 = TraceModel.Helpers.Trace.extractId(fakeEventWithLocalId2);\n assert.strictEqual(localId2, fakeEventWithLocalId2.id2?.local);\n });\n });\n describe('mergeEventsInOrder', () => {\n it('merges two ordered arrays of trace events with no duration', async () => {\n const array1 = [\n {\n name: 'a',\n ts: 0,\n },\n {\n name: 'b',\n ts: 2,\n },\n {\n name: 'c',\n ts: 4,\n },\n {\n name: 'd',\n ts: 6,\n },\n {\n name: 'e',\n ts: 8,\n },\n ] as TraceModel.Types.TraceEvents.TraceEventData[];\n\n const array2 = [\n {\n name: 'a',\n ts: 1,\n },\n {\n name: 'b',\n ts: 3,\n },\n {\n name: 'c',\n ts: 5,\n },\n {\n name: 'd',\n ts: 7,\n },\n {\n name: 'e',\n ts: 9,\n },\n ] as TraceModel.Types.TraceEvents.TraceEventData[];\n const ordered = TraceModel.Helpers.Trace.mergeEventsInOrder(array1, array2);\n for (let i = 1; i < ordered.length; i++) {\n assert.isAbove(ordered[i].ts, ordered[i - 1].ts);\n }\n });\n it('merges two ordered arrays of trace events with duration', async () => {\n const array1 = [\n {\n name: 'a',\n ts: 0,\n dur: 10,\n },\n {\n name: 'b',\n ts: 2,\n dur: 12,\n },\n {\n name: 'c',\n ts: 4,\n dur: 2,\n },\n {\n name: 'd',\n ts: 6,\n dur: 9,\n },\n {\n name: 'e',\n ts: 8,\n dur: 100,\n },\n ] as TraceModel.Types.TraceEvents.TraceEventData[];\n\n const array2 = [\n {\n name: 'a',\n ts: 1,\n dur: 2,\n },\n {\n name: 'b',\n ts: 3,\n dur: 1,\n },\n {\n name: 'c',\n ts: 5,\n dur: 99,\n },\n {\n name: 'd',\n ts: 7,\n },\n {\n name: 'e',\n ts: 9,\n dur: 0,\n },\n ] as TraceModel.Types.TraceEvents.TraceEventData[];\n const ordered = TraceModel.Helpers.Trace.mergeEventsInOrder(array1, array2);\n for (let i = 1; i < ordered.length; i++) {\n assert.isAbove(ordered[i].ts, ordered[i - 1].ts);\n }\n });\n it('merges two ordered arrays of trace events when timestamps collide', async () => {\n const array1 = [\n {\n name: 'a',\n ts: 0,\n dur: 10,\n },\n {\n name: 'b',\n ts: 2,\n dur: 12,\n },\n {\n name: 'c',\n ts: 4,\n dur: 2,\n },\n {\n name: 'd',\n ts: 6,\n dur: 9,\n },\n {\n name: 'e',\n ts: 8,\n dur: 100,\n },\n ] as TraceModel.Types.TraceEvents.TraceEventData[];\n\n const array2 = [\n {\n name: 'a',\n ts: 0,\n dur: 2,\n },\n {\n name: 'b',\n ts: 2,\n dur: 1,\n },\n {\n name: 'c',\n ts: 4,\n dur: 99,\n },\n {\n name: 'd',\n ts: 7,\n },\n {\n name: 'e',\n ts: 9,\n dur: 0,\n },\n ] as TraceModel.Types.TraceEvents.TraceEventData[];\n const ordered = TraceModel.Helpers.Trace.mergeEventsInOrder(array1, array2);\n for (let i = 1; i < ordered.length; i++) {\n const dur = ordered[i].dur;\n const durPrev = ordered[i - 1].dur;\n const eventsHaveDuration = dur !== undefined && durPrev !== undefined;\n const correctOrderForSharedTimestamp =\n eventsHaveDuration && ordered[i].ts === ordered[i - 1].ts && dur <= durPrev;\n assert.isTrue(ordered[i].ts > ordered[i - 1].ts || correctOrderForSharedTimestamp);\n }\n });\n it('merges two ordered arrays of trace events when timestamps and durations collide', async () => {\n const array1 = [\n {\n name: 'a',\n ts: 0,\n dur: 10,\n },\n {\n name: 'b',\n ts: 2,\n dur: 10,\n },\n {\n name: 'c',\n ts: 4,\n dur: 10,\n },\n {\n name: 'd',\n ts: 6,\n dur: 10,\n },\n {\n name: 'e',\n ts: 8,\n dur: 10,\n },\n ] as TraceModel.Types.TraceEvents.TraceEventData[];\n\n const array2 = [...array1];\n const ordered = TraceModel.Helpers.Trace.mergeEventsInOrder(array1, array2);\n for (let i = 1; i < ordered.length; i++) {\n const dur = ordered[i].dur;\n const durPrev = ordered[i - 1].dur;\n const eventsHaveDuration = dur !== undefined && durPrev !== undefined;\n const correctOrderForSharedTimestamp =\n eventsHaveDuration && ordered[i].ts === ordered[i - 1].ts && dur <= durPrev;\n assert.isTrue(ordered[i].ts > ordered[i - 1].ts || correctOrderForSharedTimestamp);\n }\n });\n });\n describe('activeURLForFrameAtTime', () => {\n it('extracts the active url for a frame at a given time', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'simple-js-program.json.gz');\n const frameId = '1F729458403A23CF1D8D246095129AC4';\n const firstURL = TraceModel.Helpers.Trace.activeURLForFrameAtTime(\n frameId, TraceModel.Types.Timing.MicroSeconds(251126654355), traceData.Meta.rendererProcessesByFrame);\n assert.strictEqual(firstURL, 'about:blank');\n const secondURL = TraceModel.Helpers.Trace.activeURLForFrameAtTime(\n frameId, TraceModel.Types.Timing.MicroSeconds(251126663398), traceData.Meta.rendererProcessesByFrame);\n assert.strictEqual(secondURL, 'https://www.google.com');\n });\n });\n\n describe('createMatchedSortedSyntheticEvents', () => {\n it('matches up arbitrary async events', async function() {\n const events = await TraceLoader.rawEvents(this, 'user-timings.json.gz');\n const asyncEvents = events.filter(event => TraceModel.Types.TraceEvents.isTraceEventAsyncPhase(event)) as\n TraceModel.Types.TraceEvents.TraceEventPairableAsync[];\n const synthEvents = TraceModel.Helpers.Trace.createMatchedSortedSyntheticEvents(asyncEvents);\n\n // There's a lot of events, let's only assert one event per name\n const seen = new Set();\n // Make a readable output of each event to assert\n const eventSummary = (e: TraceModel.Types.TraceEvents.SyntheticEventPair) =>\n `@ ${(e.ts / 1000 - 1003e5).toFixed(3).padEnd(9)} for ${(e.dur / 1000).toFixed(3).padStart(8)}: ${e.name}`;\n const eventsSummary = synthEvents\n .filter(e => {\n const alreadySeen = seen.has(e.name);\n seen.add(e.name);\n return !alreadySeen;\n })\n .map(eventSummary);\n\n assert.deepEqual(eventsSummary, [\n '@ 22336.946 for 16.959: PipelineReporter',\n '@ 22350.590 for 3.315: BeginImplFrameToSendBeginMainFrame',\n '@ 40732.328 for 0.834: SendBeginMainFrameToCommit',\n '@ 40733.162 for 0.307: Commit',\n '@ 40733.469 for 0.097: EndCommitToActivation',\n '@ 40733.566 for 0.019: Activation',\n '@ 40733.585 for 1.775: EndActivateToSubmitCompositorFrame',\n '@ 40735.360 for 58.412: SubmitCompositorFrameToPresentationCompositorFrame',\n '@ 40735.360 for 0.148: SubmitToReceiveCompositorFrame',\n '@ 40735.508 for 3.667: ReceiveCompositorFrameToStartDraw',\n '@ 40739.175 for 54.136: StartDrawToSwapStart',\n '@ 40793.311 for 0.461: Swap',\n '@ 40810.809 for 205.424: first measure',\n '@ 40810.809 for 606.224: second measure',\n '@ 40825.971 for 11.802: InputLatency::MouseMove',\n '@ 41818.833 for 2005.601: third measure',\n ]);\n assert.strictEqual(synthEvents.length, 237);\n });\n describe('createSortedSyntheticEvents()', () => {\n it('correctly creates synthetic events when instant animation events are present', async function() {\n const events = await TraceLoader.rawEvents(this, 'instant-animation-events.json.gz');\n const animationEvents = events.filter(event => TraceModel.Types.TraceEvents.isTraceEventAnimation(event)) as\n TraceModel.Types.TraceEvents.TraceEventAnimation[];\n const animationSynthEvents = TraceModel.Helpers.Trace.createMatchedSortedSyntheticEvents(animationEvents);\n const wantPairs = new Map}>([\n [\n 'blink.animations,devtools.timeline,benchmark,rail:0x11d00230380:Animation',\n {compositeFailed: 8224, unsupportedProperties: ['width']},\n ],\n ['blink.animations,devtools.timeline,benchmark,rail:0x11d00234738:Animation', {compositeFailed: 0}],\n [\n 'blink.animations,devtools.timeline,benchmark,rail:0x11d00234b08:Animation',\n {compositeFailed: 8224, unsupportedProperties: ['height']},\n ],\n [\n 'blink.animations,devtools.timeline,benchmark,rail:0x11d00234ed8:Animation',\n {compositeFailed: 8224, unsupportedProperties: ['font-size']},\n ],\n ]);\n // Ensure we have the correct numner of synthetic events created.\n assert.deepEqual(wantPairs.size, animationSynthEvents.length);\n\n animationSynthEvents.forEach(event => {\n const id = event.id;\n assert.exists(id);\n assert.exists(wantPairs.get(id));\n\n const beginEvent = event.args.data.beginEvent;\n const endEvent = event.args.data.endEvent;\n const instantEvents = event.args.data.instantEvents;\n\n assert.exists(beginEvent);\n\n // Check that the individual event ids match the synthetic id.\n assert.isTrue(beginEvent.id2?.local && id.includes(beginEvent.id2?.local));\n if (endEvent) {\n assert.isTrue(endEvent.id2?.local && id?.includes(endEvent.id2?.local));\n }\n assert.isTrue(instantEvents?.every(event => event.id2?.local && id.includes(event.id2?.local)));\n\n assert.strictEqual(instantEvents.length, 2);\n\n // Check that the non-composited data matches the expected.\n const nonCompositedEvents = instantEvents.filter(event => event.args.data.compositeFailed);\n nonCompositedEvents.forEach(event => {\n assert.strictEqual(event.args.data.compositeFailed, wantPairs.get(id)?.compositeFailed);\n assert.deepEqual(event.args.data.unsupportedProperties, wantPairs.get(id)?.unsupportedProperties);\n });\n });\n });\n });\n });\n\n describe('getZeroIndexedLineAndColumnNumbersForEvent', () => {\n it('subtracts one from the line number of a function call', async () => {\n const fakeFunctionCall: TraceModel.Types.TraceEvents.TraceEventFunctionCall = {\n name: TraceModel.Types.TraceEvents.KnownEventName.FUNCTION_CALL,\n ph: TraceModel.Types.TraceEvents.Phase.COMPLETE,\n cat: 'devtools-timeline',\n dur: TraceModel.Types.Timing.MicroSeconds(100),\n ts: TraceModel.Types.Timing.MicroSeconds(100),\n pid: TraceModel.Types.TraceEvents.ProcessID(1),\n tid: TraceModel.Types.TraceEvents.ThreadID(1),\n args: {\n data: {\n functionName: 'test',\n url: 'https://google.com/test.js',\n scriptId: Number(123),\n lineNumber: 1,\n columnNumber: 1,\n },\n },\n };\n assert.deepEqual(TraceModel.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(fakeFunctionCall), {\n lineNumber: 0,\n columnNumber: 0,\n });\n });\n });\n\n describe('frameIDForEvent', () => {\n it('returns the frame ID from beginData if the event has it', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n const parseHTMLEvent =\n traceData.Renderer.allTraceEntries.find(TraceModel.Types.TraceEvents.isTraceEventParseHTML);\n assert.isOk(parseHTMLEvent);\n const frameId = TraceModel.Helpers.Trace.frameIDForEvent(parseHTMLEvent);\n assert.isNotNull(frameId);\n assert.strictEqual(frameId, parseHTMLEvent.args.beginData.frame);\n });\n\n it('returns the frame ID from args.data if the event has it', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n const invalidateLayoutEvent =\n traceData.Renderer.allTraceEntries.find(TraceModel.Types.TraceEvents.isTraceEventInvalidateLayout);\n assert.isOk(invalidateLayoutEvent);\n const frameId = TraceModel.Helpers.Trace.frameIDForEvent(invalidateLayoutEvent);\n assert.isNotNull(frameId);\n assert.strictEqual(frameId, invalidateLayoutEvent.args.data.frame);\n });\n\n it('returns null if the event does not have a frame', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n const v8CompileEvent =\n traceData.Renderer.allTraceEntries.find(TraceModel.Types.TraceEvents.isTraceEventV8Compile);\n assert.isOk(v8CompileEvent);\n const frameId = TraceModel.Helpers.Trace.frameIDForEvent(v8CompileEvent);\n assert.isNull(frameId);\n });\n });\n\n describe('findUpdateLayoutTreeEvents', () => {\n it('returns the set of UpdateLayoutTree events within the right time range', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'selector-stats.json.gz');\n const mainThread = getMainThread(traceData.Renderer);\n const foundEvents = TraceModel.Helpers.Trace.findUpdateLayoutTreeEvents(\n mainThread.entries,\n traceData.Meta.traceBounds.min,\n );\n assert.lengthOf(foundEvents, 11);\n\n const lastEvent = foundEvents.at(-1);\n assert.isOk(lastEvent);\n\n // Check we can filter by endTime by making the endTime less than the start\n // time of the last event:\n const filteredByEndTimeEvents = TraceModel.Helpers.Trace.findUpdateLayoutTreeEvents(\n mainThread.entries,\n traceData.Meta.traceBounds.min,\n TraceModel.Types.Timing.MicroSeconds(lastEvent.ts - 1_000),\n );\n assert.lengthOf(filteredByEndTimeEvents, 10);\n });\n });\n\n describe('forEachEvent', () => {\n const pid = TraceModel.Types.TraceEvents.ProcessID(1);\n const tid = TraceModel.Types.TraceEvents.ThreadID(1);\n\n it('iterates through the events in the expected tree-like order', async () => {\n // |------------- RunTask -------------||-- RunTask --|\n // |-- RunMicrotasks --||-- Layout --|\n // |- FunctionCall -|\n const traceEvents = [\n makeCompleteEvent('RunTask', 0, 10, '*', pid, tid), // 0..10\n makeCompleteEvent('RunMicrotasks', 1, 3, '*', pid, tid), // 1..4\n makeCompleteEvent('FunctionCall', 2, 1, '*', pid, tid), // 2..3\n makeCompleteEvent('Layout', 5, 3, '*', pid, tid), // 5..8\n makeCompleteEvent('RunTask', 11, 3, '*', pid, tid), // 11..14\n ];\n const onStartEvent = sinon.spy<(e: TraceModel.Types.TraceEvents.TraceEventData) => void>(_event => {});\n const onEndEvent = sinon.spy<(e: TraceModel.Types.TraceEvents.TraceEventData) => void>(_event => {});\n\n TraceModel.Helpers.Trace.forEachEvent(traceEvents, {\n onEndEvent,\n onStartEvent,\n });\n const eventsFromStartEventCalls = onStartEvent.getCalls().map(a => a.args[0]);\n const eventsFromEndEventCalls = onEndEvent.getCalls().map(a => a.args[0]);\n assert.deepEqual(\n eventsFromStartEventCalls.map(e => e.name),\n ['RunTask', 'RunMicrotasks', 'FunctionCall', 'Layout', 'RunTask'],\n );\n assert.deepEqual(\n eventsFromEndEventCalls.map(e => e.name),\n ['FunctionCall', 'RunMicrotasks', 'Layout', 'RunTask', 'RunTask'],\n );\n });\n\n it('allows for a custom start and end time', async () => {\n // |------------- RunTask -------------||-- RunTask --|\n // |-- RunMicrotasks --||-- Layout --|\n // |- FunctionCall -|\n const traceEvents = [\n makeCompleteEvent('RunTask', 0, 10, '*', pid, tid), // 0..10\n makeCompleteEvent('RunMicrotasks', 1, 3, '*', pid, tid), // 1..4\n makeCompleteEvent('FunctionCall', 2, 1, '*', pid, tid), // 2..3\n makeCompleteEvent('Layout', 5, 3, '*', pid, tid), // 5..8\n ];\n const onStartEvent = sinon.spy<(e: TraceModel.Types.TraceEvents.TraceEventData) => void>(_event => {});\n const onEndEvent = sinon.spy<(e: TraceModel.Types.TraceEvents.TraceEventData) => void>(_event => {});\n\n TraceModel.Helpers.Trace.forEachEvent(traceEvents, {\n onEndEvent,\n onStartEvent,\n startTime: TraceModel.Types.Timing.MicroSeconds(5),\n endTime: TraceModel.Types.Timing.MicroSeconds(9),\n });\n const eventsFromStartEventCalls = onStartEvent.getCalls().map(a => a.args[0]);\n const eventsFromEndEventCalls = onEndEvent.getCalls().map(a => a.args[0]);\n // We expect the RunTask event (0-10) and the Layout event (5-8) as\n // those fit in the 5-9 custom time range.\n assert.deepEqual(\n eventsFromStartEventCalls.map(e => e.name),\n ['RunTask', 'Layout'],\n );\n assert.deepEqual(\n eventsFromEndEventCalls.map(e => e.name),\n ['Layout', 'RunTask'],\n );\n });\n\n it('lets the user filter out events with a custom filter', async () => {\n // |------------- RunTask -------------||-- RunTask --|\n // |-- RunMicrotasks --||-- Layout --|\n // |- FunctionCall -|\n const traceEvents = [\n makeCompleteEvent('RunTask', 0, 10, '*', pid, tid), // 0..10\n makeCompleteEvent('RunMicrotasks', 1, 3, '*', pid, tid), // 1..4\n makeCompleteEvent('FunctionCall', 2, 1, '*', pid, tid), // 2..3\n makeCompleteEvent('Layout', 5, 3, '*', pid, tid), // 5..8\n makeCompleteEvent('RunTask', 11, 3, '*', pid, tid), // 11..14\n ];\n const onStartEvent = sinon.spy<(e: TraceModel.Types.TraceEvents.TraceEventData) => void>(_event => {});\n const onEndEvent = sinon.spy<(e: TraceModel.Types.TraceEvents.TraceEventData) => void>(_event => {});\n\n TraceModel.Helpers.Trace.forEachEvent(traceEvents, {\n onEndEvent,\n onStartEvent,\n eventFilter(event) {\n return event.name !== 'RunTask';\n },\n });\n const eventsFromStartEventCalls = onStartEvent.getCalls().map(a => a.args[0]);\n const eventsFromEndEventCalls = onEndEvent.getCalls().map(a => a.args[0]);\n\n assert.deepEqual(\n eventsFromStartEventCalls.map(e => e.name),\n ['RunMicrotasks', 'FunctionCall', 'Layout'],\n );\n assert.deepEqual(\n eventsFromEndEventCalls.map(e => e.name),\n ['FunctionCall', 'RunMicrotasks', 'Layout'],\n );\n });\n\n it('calls the onInstantEvent callback when it finds an event with 0 duration', async () => {\n const traceEvents = [\n makeInstantEvent('FakeInstantEvent', 0, '*', pid, tid),\n ];\n const onStartEvent = sinon.spy<(e: TraceModel.Types.TraceEvents.TraceEventData) => void>(_event => {});\n const onEndEvent = sinon.spy<(e: TraceModel.Types.TraceEvents.TraceEventData) => void>(_event => {});\n const onInstantEvent = sinon.spy<(e: TraceModel.Types.TraceEvents.TraceEventData) => void>(_event => {});\n\n TraceModel.Helpers.Trace.forEachEvent(traceEvents, {\n onEndEvent,\n onStartEvent,\n onInstantEvent,\n });\n\n assert.strictEqual(onStartEvent.callCount, 0);\n assert.strictEqual(onEndEvent.callCount, 0);\n assert.strictEqual(onInstantEvent.callCount, 1);\n });\n\n it('skips async events by default', async () => {\n const traceEvents = [\n makeAsyncStartEvent('FakeAsync', 0, pid, tid),\n makeAsyncEndEvent('FakeAsync', 0, pid, tid),\n ];\n const onStartEvent = sinon.spy<(e: TraceModel.Types.TraceEvents.TraceEventData) => void>(_event => {});\n const onEndEvent = sinon.spy<(e: TraceModel.Types.TraceEvents.TraceEventData) => void>(_event => {});\n const onInstantEvent = sinon.spy<(e: TraceModel.Types.TraceEvents.TraceEventData) => void>(_event => {});\n\n TraceModel.Helpers.Trace.forEachEvent(traceEvents, {\n onEndEvent,\n onStartEvent,\n onInstantEvent,\n });\n\n assert.strictEqual(onStartEvent.callCount, 0);\n assert.strictEqual(onEndEvent.callCount, 0);\n assert.strictEqual(onInstantEvent.callCount, 0);\n });\n\n it('can be configured to include async events', async () => {\n const traceEvents = [\n makeAsyncStartEvent('FakeAsync', 0, pid, tid),\n makeAsyncEndEvent('FakeAsync', 0, pid, tid),\n ];\n const onStartEvent = sinon.spy<(e: TraceModel.Types.TraceEvents.TraceEventData) => void>(_event => {});\n const onEndEvent = sinon.spy<(e: TraceModel.Types.TraceEvents.TraceEventData) => void>(_event => {});\n const onInstantEvent = sinon.spy<(e: TraceModel.Types.TraceEvents.TraceEventData) => void>(_event => {});\n\n TraceModel.Helpers.Trace.forEachEvent(traceEvents, {\n onEndEvent,\n onStartEvent,\n onInstantEvent,\n ignoreAsyncEvents: false,\n });\n\n assert.strictEqual(onStartEvent.callCount, 0);\n assert.strictEqual(onEndEvent.callCount, 0);\n assert.strictEqual(onInstantEvent.callCount, 2);\n });\n });\n\n describe('isTopLevelEvent', () => {\n it('is true for a RunTask event', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const runTask = traceData.Renderer.allTraceEntries.find(TraceModel.Types.TraceEvents.isTraceEventRunTask);\n assert.isOk(runTask);\n\n assert.isTrue(TraceModel.Helpers.Trace.isTopLevelEvent(runTask));\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"Trace.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/Trace.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {\n getMainThread,\n makeAsyncEndEvent,\n makeAsyncStartEvent,\n makeCompleteEvent,\n makeInstantEvent,\n} from '../../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Trace from '../trace.js';\n\ndescribeWithEnvironment('TraceModel helpers', function() {\n describe('extractOriginFromTrace', () => {\n it('extracts the origin of a parsed trace correctly', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const origin = Trace.Helpers.Trace.extractOriginFromTrace(parsedTrace.Meta.mainFrameURL);\n assert.strictEqual(origin, 'web.dev');\n });\n\n it('will remove the `www` if it is present', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'multiple-navigations.json.gz');\n const origin = Trace.Helpers.Trace.extractOriginFromTrace(parsedTrace.Meta.mainFrameURL);\n assert.strictEqual(origin, 'google.com');\n });\n\n it('returns null when no origin is found', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'basic.json.gz');\n const origin = Trace.Helpers.Trace.extractOriginFromTrace(parsedTrace.Meta.mainFrameURL);\n assert.isNull(origin);\n });\n });\n\n describe('addEventToProcessThread', () => {\n function makeTraceEvent(\n pid: Trace.Types.Events.ProcessID, tid: Trace.Types.Events.ThreadID): Trace.Types.Events.Event {\n return {\n name: 'process_name',\n tid,\n pid,\n ts: Trace.Types.Timing.MicroSeconds(0),\n cat: 'test',\n ph: Trace.Types.Events.Phase.METADATA,\n };\n }\n\n function pid(x: number): Trace.Types.Events.ProcessID {\n return Trace.Types.Events.ProcessID(x);\n }\n function tid(x: number): Trace.Types.Events.ThreadID {\n return Trace.Types.Events.ThreadID(x);\n }\n\n const eventMap =\n new Map>();\n\n beforeEach(() => {\n eventMap.clear();\n });\n\n it('will create a process and thread if it does not exist yet', async () => {\n const event = makeTraceEvent(pid(1), tid(1));\n Trace.Helpers.Trace.addEventToProcessThread(event, eventMap);\n assert.strictEqual(eventMap.get(pid(1))?.size, 1);\n const threadEvents = eventMap.get(pid(1))?.get(tid(1));\n assert.strictEqual(threadEvents?.length, 1);\n });\n\n it('adds new events to existing threads correctly', async () => {\n const event = makeTraceEvent(pid(1), tid(1));\n Trace.Helpers.Trace.addEventToProcessThread(event, eventMap);\n const newEvent = makeTraceEvent(pid(1), tid(1));\n Trace.Helpers.Trace.addEventToProcessThread(newEvent, eventMap);\n assert.deepEqual(eventMap.get(pid(1))?.get(tid(1)), [event, newEvent]);\n });\n });\n\n describe('sortTraceEventsInPlace', () => {\n function makeFakeEvent(ts: number, dur: number): Trace.Types.Events.Event {\n return {\n ts: Trace.Types.Timing.MicroSeconds(ts),\n dur: Trace.Types.Timing.MicroSeconds(dur),\n } as unknown as Trace.Types.Events.Event;\n }\n\n it('sorts by start time in ASC order', () => {\n const event1 = makeFakeEvent(1, 1);\n const event2 = makeFakeEvent(2, 1);\n const event3 = makeFakeEvent(3, 1);\n const events = [event3, event1, event2];\n Trace.Helpers.Trace.sortTraceEventsInPlace(events);\n assert.deepEqual(events, [event1, event2, event3]);\n });\n\n it('sorts by longest duration if the timestamps are the same', () => {\n const event1 = makeFakeEvent(1, 1);\n const event2 = makeFakeEvent(1, 2);\n const event3 = makeFakeEvent(1, 3);\n const events = [event1, event2, event3];\n Trace.Helpers.Trace.sortTraceEventsInPlace(events);\n assert.deepEqual(events, [event3, event2, event1]);\n });\n });\n\n describe('getNavigationForTraceEvent', () => {\n it('returns the correct navigation for a request', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'multiple-navigations.json.gz');\n const {NetworkRequests, Meta} = parsedTrace;\n const request1 = NetworkRequests.byTime[0];\n const navigationForFirstRequest =\n Trace.Helpers.Trace.getNavigationForTraceEvent(request1, request1.args.data.frame, Meta.navigationsByFrameId);\n assert.isUndefined(navigationForFirstRequest?.ts);\n\n const request2 = NetworkRequests.byTime[1];\n const navigationForSecondRequest =\n Trace.Helpers.Trace.getNavigationForTraceEvent(request2, request2.args.data.frame, Meta.navigationsByFrameId);\n assert.strictEqual(navigationForSecondRequest?.ts, Trace.Types.Timing.MicroSeconds(636471400029));\n });\n\n it('returns the correct navigation for a page load event', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'multiple-navigations.json.gz');\n const {Meta, PageLoadMetrics} = parsedTrace;\n const firstNavigationId = Meta.navigationsByNavigationId.keys().next().value;\n\n const fcp = PageLoadMetrics.metricScoresByFrameId.get(Meta.mainFrameId)\n ?.get(firstNavigationId)\n ?.get(Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP);\n if (!fcp || !fcp.event) {\n assert.fail('FCP not found');\n }\n const navigationForFirstRequest =\n Trace.Helpers.Trace.getNavigationForTraceEvent(fcp.event, Meta.mainFrameId, Meta.navigationsByFrameId);\n assert.strictEqual(navigationForFirstRequest?.args.data?.navigationId, firstNavigationId);\n });\n });\n\n describe('extractId', () => {\n it('returns the correct id for an event', async () => {\n const fakeEventWithId = {id: 'id'} as unknown as Trace.Types.Events.PairableAsync;\n const id = Trace.Helpers.Trace.extractId(fakeEventWithId);\n assert.strictEqual(id, fakeEventWithId.id);\n\n const fakeEventWithGlobalId2 = {id2: {global: 'globalId2'}} as unknown as Trace.Types.Events.PairableAsync;\n const globalId2 = Trace.Helpers.Trace.extractId(fakeEventWithGlobalId2);\n assert.strictEqual(globalId2, fakeEventWithGlobalId2.id2?.global);\n\n const fakeEventWithLocalId2 = {id2: {local: 'localId2'}} as unknown as Trace.Types.Events.PairableAsync;\n const localId2 = Trace.Helpers.Trace.extractId(fakeEventWithLocalId2);\n assert.strictEqual(localId2, fakeEventWithLocalId2.id2?.local);\n });\n });\n describe('mergeEventsInOrder', () => {\n it('merges two ordered arrays of trace events with no duration', async () => {\n const array1 = [\n {\n name: 'a',\n ts: 0,\n },\n {\n name: 'b',\n ts: 2,\n },\n {\n name: 'c',\n ts: 4,\n },\n {\n name: 'd',\n ts: 6,\n },\n {\n name: 'e',\n ts: 8,\n },\n ] as Trace.Types.Events.Event[];\n\n const array2 = [\n {\n name: 'a',\n ts: 1,\n },\n {\n name: 'b',\n ts: 3,\n },\n {\n name: 'c',\n ts: 5,\n },\n {\n name: 'd',\n ts: 7,\n },\n {\n name: 'e',\n ts: 9,\n },\n ] as Trace.Types.Events.Event[];\n const ordered = Trace.Helpers.Trace.mergeEventsInOrder(array1, array2);\n for (let i = 1; i < ordered.length; i++) {\n assert.isAbove(ordered[i].ts, ordered[i - 1].ts);\n }\n });\n it('merges two ordered arrays of trace events with duration', async () => {\n const array1 = [\n {\n name: 'a',\n ts: 0,\n dur: 10,\n },\n {\n name: 'b',\n ts: 2,\n dur: 12,\n },\n {\n name: 'c',\n ts: 4,\n dur: 2,\n },\n {\n name: 'd',\n ts: 6,\n dur: 9,\n },\n {\n name: 'e',\n ts: 8,\n dur: 100,\n },\n ] as Trace.Types.Events.Event[];\n\n const array2 = [\n {\n name: 'a',\n ts: 1,\n dur: 2,\n },\n {\n name: 'b',\n ts: 3,\n dur: 1,\n },\n {\n name: 'c',\n ts: 5,\n dur: 99,\n },\n {\n name: 'd',\n ts: 7,\n },\n {\n name: 'e',\n ts: 9,\n dur: 0,\n },\n ] as Trace.Types.Events.Event[];\n const ordered = Trace.Helpers.Trace.mergeEventsInOrder(array1, array2);\n for (let i = 1; i < ordered.length; i++) {\n assert.isAbove(ordered[i].ts, ordered[i - 1].ts);\n }\n });\n it('merges two ordered arrays of trace events when timestamps collide', async () => {\n const array1 = [\n {\n name: 'a',\n ts: 0,\n dur: 10,\n },\n {\n name: 'b',\n ts: 2,\n dur: 12,\n },\n {\n name: 'c',\n ts: 4,\n dur: 2,\n },\n {\n name: 'd',\n ts: 6,\n dur: 9,\n },\n {\n name: 'e',\n ts: 8,\n dur: 100,\n },\n ] as Trace.Types.Events.Event[];\n\n const array2 = [\n {\n name: 'a',\n ts: 0,\n dur: 2,\n },\n {\n name: 'b',\n ts: 2,\n dur: 1,\n },\n {\n name: 'c',\n ts: 4,\n dur: 99,\n },\n {\n name: 'd',\n ts: 7,\n },\n {\n name: 'e',\n ts: 9,\n dur: 0,\n },\n ] as Trace.Types.Events.Event[];\n const ordered = Trace.Helpers.Trace.mergeEventsInOrder(array1, array2);\n for (let i = 1; i < ordered.length; i++) {\n const dur = ordered[i].dur;\n const durPrev = ordered[i - 1].dur;\n const eventsHaveDuration = dur !== undefined && durPrev !== undefined;\n const correctOrderForSharedTimestamp =\n eventsHaveDuration && ordered[i].ts === ordered[i - 1].ts && dur <= durPrev;\n assert.isTrue(ordered[i].ts > ordered[i - 1].ts || correctOrderForSharedTimestamp);\n }\n });\n it('merges two ordered arrays of trace events when timestamps and durations collide', async () => {\n const array1 = [\n {\n name: 'a',\n ts: 0,\n dur: 10,\n },\n {\n name: 'b',\n ts: 2,\n dur: 10,\n },\n {\n name: 'c',\n ts: 4,\n dur: 10,\n },\n {\n name: 'd',\n ts: 6,\n dur: 10,\n },\n {\n name: 'e',\n ts: 8,\n dur: 10,\n },\n ] as Trace.Types.Events.Event[];\n\n const array2 = [...array1];\n const ordered = Trace.Helpers.Trace.mergeEventsInOrder(array1, array2);\n for (let i = 1; i < ordered.length; i++) {\n const dur = ordered[i].dur;\n const durPrev = ordered[i - 1].dur;\n const eventsHaveDuration = dur !== undefined && durPrev !== undefined;\n const correctOrderForSharedTimestamp =\n eventsHaveDuration && ordered[i].ts === ordered[i - 1].ts && dur <= durPrev;\n assert.isTrue(ordered[i].ts > ordered[i - 1].ts || correctOrderForSharedTimestamp);\n }\n });\n });\n describe('activeURLForFrameAtTime', () => {\n it('extracts the active url for a frame at a given time', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'simple-js-program.json.gz');\n const frameId = '1F729458403A23CF1D8D246095129AC4';\n const firstURL = Trace.Helpers.Trace.activeURLForFrameAtTime(\n frameId, Trace.Types.Timing.MicroSeconds(251126654355), parsedTrace.Meta.rendererProcessesByFrame);\n assert.strictEqual(firstURL, 'about:blank');\n const secondURL = Trace.Helpers.Trace.activeURLForFrameAtTime(\n frameId, Trace.Types.Timing.MicroSeconds(251126663398), parsedTrace.Meta.rendererProcessesByFrame);\n assert.strictEqual(secondURL, 'https://www.google.com');\n });\n });\n\n describe('createMatchedSortedSyntheticEvents', () => {\n it('matches up arbitrary async events', async function() {\n const events = await TraceLoader.rawEvents(this, 'user-timings.json.gz');\n const asyncEvents =\n events.filter(event => Trace.Types.Events.isPhaseAsync(event.ph)) as Trace.Types.Events.PairableAsync[];\n const synthEvents = Trace.Helpers.Trace.createMatchedSortedSyntheticEvents(asyncEvents);\n\n // There's a lot of events, let's only assert one event per name\n const seen = new Set();\n // Make a readable output of each event to assert\n const eventSummary = (e: Trace.Types.Events.SyntheticEventPair) =>\n `@ ${(e.ts / 1000 - 1003e5).toFixed(3).padEnd(9)} for ${(e.dur / 1000).toFixed(3).padStart(8)}: ${e.name}`;\n const eventsSummary = synthEvents\n .filter(e => {\n const alreadySeen = seen.has(e.name);\n seen.add(e.name);\n return !alreadySeen;\n })\n .map(eventSummary);\n\n assert.deepEqual(eventsSummary, [\n '@ 22336.946 for 16.959: PipelineReporter',\n '@ 22350.590 for 3.315: BeginImplFrameToSendBeginMainFrame',\n '@ 40732.328 for 0.834: SendBeginMainFrameToCommit',\n '@ 40733.162 for 0.307: Commit',\n '@ 40733.469 for 0.097: EndCommitToActivation',\n '@ 40733.566 for 0.019: Activation',\n '@ 40733.585 for 1.775: EndActivateToSubmitCompositorFrame',\n '@ 40735.360 for 58.412: SubmitCompositorFrameToPresentationCompositorFrame',\n '@ 40735.360 for 0.148: SubmitToReceiveCompositorFrame',\n '@ 40735.508 for 3.667: ReceiveCompositorFrameToStartDraw',\n '@ 40739.175 for 54.136: StartDrawToSwapStart',\n '@ 40793.311 for 0.461: Swap',\n '@ 40810.809 for 205.424: first measure',\n '@ 40810.809 for 606.224: second measure',\n '@ 40825.971 for 11.802: InputLatency::MouseMove',\n '@ 41818.833 for 2005.601: third measure',\n ]);\n assert.strictEqual(synthEvents.length, 237);\n });\n describe('createSortedSyntheticEvents()', () => {\n it('correctly creates synthetic events when instant animation events are present', async function() {\n const events = await TraceLoader.rawEvents(this, 'instant-animation-events.json.gz');\n const animationEvents =\n events.filter(event => Trace.Types.Events.isAnimation(event)) as Trace.Types.Events.Animation[];\n const animationSynthEvents = Trace.Helpers.Trace.createMatchedSortedSyntheticEvents(animationEvents);\n const wantPairs = new Map}>([\n [\n 'blink.animations,devtools.timeline,benchmark,rail:0x11d00230380:Animation',\n {compositeFailed: 8224, unsupportedProperties: ['width']},\n ],\n ['blink.animations,devtools.timeline,benchmark,rail:0x11d00234738:Animation', {compositeFailed: 0}],\n [\n 'blink.animations,devtools.timeline,benchmark,rail:0x11d00234b08:Animation',\n {compositeFailed: 8224, unsupportedProperties: ['height']},\n ],\n [\n 'blink.animations,devtools.timeline,benchmark,rail:0x11d00234ed8:Animation',\n {compositeFailed: 8224, unsupportedProperties: ['font-size']},\n ],\n ]);\n // Ensure we have the correct numner of synthetic events created.\n assert.deepEqual(wantPairs.size, animationSynthEvents.length);\n\n animationSynthEvents.forEach(event => {\n const id = event.id;\n assert.exists(id);\n assert.exists(wantPairs.get(id));\n\n const beginEvent = event.args.data.beginEvent;\n const endEvent = event.args.data.endEvent;\n const instantEvents = event.args.data.instantEvents;\n\n assert.exists(beginEvent);\n\n // Check that the individual event ids match the synthetic id.\n assert.isTrue(beginEvent.id2?.local && id.includes(beginEvent.id2?.local));\n if (endEvent) {\n assert.isTrue(endEvent.id2?.local && id?.includes(endEvent.id2?.local));\n }\n assert.isTrue(instantEvents?.every(event => event.id2?.local && id.includes(event.id2?.local)));\n\n assert.strictEqual(instantEvents.length, 2);\n\n // Check that the non-composited data matches the expected.\n const nonCompositedEvents = instantEvents.filter(event => event.args.data.compositeFailed);\n nonCompositedEvents.forEach(event => {\n assert.strictEqual(event.args.data.compositeFailed, wantPairs.get(id)?.compositeFailed);\n assert.deepEqual(event.args.data.unsupportedProperties, wantPairs.get(id)?.unsupportedProperties);\n });\n });\n });\n });\n });\n\n describe('getZeroIndexedLineAndColumnNumbersForEvent', () => {\n it('subtracts one from the line number of a function call', async () => {\n const fakeFunctionCall: Trace.Types.Events.FunctionCall = {\n name: Trace.Types.Events.Name.FUNCTION_CALL,\n ph: Trace.Types.Events.Phase.COMPLETE,\n cat: 'devtools-timeline',\n dur: Trace.Types.Timing.MicroSeconds(100),\n ts: Trace.Types.Timing.MicroSeconds(100),\n pid: Trace.Types.Events.ProcessID(1),\n tid: Trace.Types.Events.ThreadID(1),\n args: {\n data: {\n functionName: 'test',\n url: 'https://google.com/test.js',\n scriptId: Number(123),\n lineNumber: 1,\n columnNumber: 1,\n },\n },\n };\n assert.deepEqual(Trace.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(fakeFunctionCall), {\n lineNumber: 0,\n columnNumber: 0,\n });\n });\n });\n\n describe('frameIDForEvent', () => {\n it('returns the frame ID from beginData if the event has it', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n const parseHTMLEvent = parsedTrace.Renderer.allTraceEntries.find(Trace.Types.Events.isParseHTML);\n assert.isOk(parseHTMLEvent);\n const frameId = Trace.Helpers.Trace.frameIDForEvent(parseHTMLEvent);\n assert.isNotNull(frameId);\n assert.strictEqual(frameId, parseHTMLEvent.args.beginData.frame);\n });\n\n it('returns the frame ID from args.data if the event has it', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n const invalidateLayoutEvent = parsedTrace.Renderer.allTraceEntries.find(Trace.Types.Events.isInvalidateLayout);\n assert.isOk(invalidateLayoutEvent);\n const frameId = Trace.Helpers.Trace.frameIDForEvent(invalidateLayoutEvent);\n assert.isNotNull(frameId);\n assert.strictEqual(frameId, invalidateLayoutEvent.args.data.frame);\n });\n\n it('returns null if the event does not have a frame', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n const v8CompileEvent = parsedTrace.Renderer.allTraceEntries.find(Trace.Types.Events.isV8Compile);\n assert.isOk(v8CompileEvent);\n const frameId = Trace.Helpers.Trace.frameIDForEvent(v8CompileEvent);\n assert.isNull(frameId);\n });\n });\n\n describe('findUpdateLayoutTreeEvents', () => {\n it('returns the set of UpdateLayoutTree events within the right time range', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'selector-stats.json.gz');\n const mainThread = getMainThread(parsedTrace.Renderer);\n const foundEvents = Trace.Helpers.Trace.findUpdateLayoutTreeEvents(\n mainThread.entries,\n parsedTrace.Meta.traceBounds.min,\n );\n assert.lengthOf(foundEvents, 11);\n\n const lastEvent = foundEvents.at(-1);\n assert.isOk(lastEvent);\n\n // Check we can filter by endTime by making the endTime less than the start\n // time of the last event:\n const filteredByEndTimeEvents = Trace.Helpers.Trace.findUpdateLayoutTreeEvents(\n mainThread.entries,\n parsedTrace.Meta.traceBounds.min,\n Trace.Types.Timing.MicroSeconds(lastEvent.ts - 1_000),\n );\n assert.lengthOf(filteredByEndTimeEvents, 10);\n });\n });\n\n describe('forEachEvent', () => {\n const pid = Trace.Types.Events.ProcessID(1);\n const tid = Trace.Types.Events.ThreadID(1);\n\n it('iterates through the events in the expected tree-like order', async () => {\n // |------------- RunTask -------------||-- RunTask --|\n // |-- RunMicrotasks --||-- Layout --|\n // |- FunctionCall -|\n const traceEvents = [\n makeCompleteEvent('RunTask', 0, 10, '*', pid, tid), // 0..10\n makeCompleteEvent('RunMicrotasks', 1, 3, '*', pid, tid), // 1..4\n makeCompleteEvent('FunctionCall', 2, 1, '*', pid, tid), // 2..3\n makeCompleteEvent('Layout', 5, 3, '*', pid, tid), // 5..8\n makeCompleteEvent('RunTask', 11, 3, '*', pid, tid), // 11..14\n ];\n const onStartEvent = sinon.spy<(e: Trace.Types.Events.Event) => void>(_event => {});\n const onEndEvent = sinon.spy<(e: Trace.Types.Events.Event) => void>(_event => {});\n\n Trace.Helpers.Trace.forEachEvent(traceEvents, {\n onEndEvent,\n onStartEvent,\n });\n const eventsFromStartEventCalls = onStartEvent.getCalls().map(a => a.args[0]);\n const eventsFromEndEventCalls = onEndEvent.getCalls().map(a => a.args[0]);\n assert.deepEqual(\n eventsFromStartEventCalls.map(e => e.name),\n ['RunTask', 'RunMicrotasks', 'FunctionCall', 'Layout', 'RunTask'],\n );\n assert.deepEqual(\n eventsFromEndEventCalls.map(e => e.name),\n ['FunctionCall', 'RunMicrotasks', 'Layout', 'RunTask', 'RunTask'],\n );\n });\n\n it('allows for a custom start and end time', async () => {\n // |------------- RunTask -------------||-- RunTask --|\n // |-- RunMicrotasks --||-- Layout --|\n // |- FunctionCall -|\n const traceEvents = [\n makeCompleteEvent('RunTask', 0, 10, '*', pid, tid), // 0..10\n makeCompleteEvent('RunMicrotasks', 1, 3, '*', pid, tid), // 1..4\n makeCompleteEvent('FunctionCall', 2, 1, '*', pid, tid), // 2..3\n makeCompleteEvent('Layout', 5, 3, '*', pid, tid), // 5..8\n ];\n const onStartEvent = sinon.spy<(e: Trace.Types.Events.Event) => void>(_event => {});\n const onEndEvent = sinon.spy<(e: Trace.Types.Events.Event) => void>(_event => {});\n\n Trace.Helpers.Trace.forEachEvent(traceEvents, {\n onEndEvent,\n onStartEvent,\n startTime: Trace.Types.Timing.MicroSeconds(5),\n endTime: Trace.Types.Timing.MicroSeconds(9),\n });\n const eventsFromStartEventCalls = onStartEvent.getCalls().map(a => a.args[0]);\n const eventsFromEndEventCalls = onEndEvent.getCalls().map(a => a.args[0]);\n // We expect the RunTask event (0-10) and the Layout event (5-8) as\n // those fit in the 5-9 custom time range.\n assert.deepEqual(\n eventsFromStartEventCalls.map(e => e.name),\n ['RunTask', 'Layout'],\n );\n assert.deepEqual(\n eventsFromEndEventCalls.map(e => e.name),\n ['Layout', 'RunTask'],\n );\n });\n\n it('lets the user filter out events with a custom filter', async () => {\n // |------------- RunTask -------------||-- RunTask --|\n // |-- RunMicrotasks --||-- Layout --|\n // |- FunctionCall -|\n const traceEvents = [\n makeCompleteEvent('RunTask', 0, 10, '*', pid, tid), // 0..10\n makeCompleteEvent('RunMicrotasks', 1, 3, '*', pid, tid), // 1..4\n makeCompleteEvent('FunctionCall', 2, 1, '*', pid, tid), // 2..3\n makeCompleteEvent('Layout', 5, 3, '*', pid, tid), // 5..8\n makeCompleteEvent('RunTask', 11, 3, '*', pid, tid), // 11..14\n ];\n const onStartEvent = sinon.spy<(e: Trace.Types.Events.Event) => void>(_event => {});\n const onEndEvent = sinon.spy<(e: Trace.Types.Events.Event) => void>(_event => {});\n\n Trace.Helpers.Trace.forEachEvent(traceEvents, {\n onEndEvent,\n onStartEvent,\n eventFilter(event) {\n return event.name !== 'RunTask';\n },\n });\n const eventsFromStartEventCalls = onStartEvent.getCalls().map(a => a.args[0]);\n const eventsFromEndEventCalls = onEndEvent.getCalls().map(a => a.args[0]);\n\n assert.deepEqual(\n eventsFromStartEventCalls.map(e => e.name),\n ['RunMicrotasks', 'FunctionCall', 'Layout'],\n );\n assert.deepEqual(\n eventsFromEndEventCalls.map(e => e.name),\n ['FunctionCall', 'RunMicrotasks', 'Layout'],\n );\n });\n\n it('calls the onInstantEvent callback when it finds an event with 0 duration', async () => {\n const traceEvents = [\n makeInstantEvent('FakeInstantEvent', 0, '*', pid, tid),\n ];\n const onStartEvent = sinon.spy<(e: Trace.Types.Events.Event) => void>(_event => {});\n const onEndEvent = sinon.spy<(e: Trace.Types.Events.Event) => void>(_event => {});\n const onInstantEvent = sinon.spy<(e: Trace.Types.Events.Event) => void>(_event => {});\n\n Trace.Helpers.Trace.forEachEvent(traceEvents, {\n onEndEvent,\n onStartEvent,\n onInstantEvent,\n });\n\n assert.strictEqual(onStartEvent.callCount, 0);\n assert.strictEqual(onEndEvent.callCount, 0);\n assert.strictEqual(onInstantEvent.callCount, 1);\n });\n\n it('skips async events by default', async () => {\n const traceEvents = [\n makeAsyncStartEvent('FakeAsync', 0, pid, tid),\n makeAsyncEndEvent('FakeAsync', 0, pid, tid),\n ];\n const onStartEvent = sinon.spy<(e: Trace.Types.Events.Event) => void>(_event => {});\n const onEndEvent = sinon.spy<(e: Trace.Types.Events.Event) => void>(_event => {});\n const onInstantEvent = sinon.spy<(e: Trace.Types.Events.Event) => void>(_event => {});\n\n Trace.Helpers.Trace.forEachEvent(traceEvents, {\n onEndEvent,\n onStartEvent,\n onInstantEvent,\n });\n\n assert.strictEqual(onStartEvent.callCount, 0);\n assert.strictEqual(onEndEvent.callCount, 0);\n assert.strictEqual(onInstantEvent.callCount, 0);\n });\n\n it('can be configured to include async events', async () => {\n const traceEvents = [\n makeAsyncStartEvent('FakeAsync', 0, pid, tid),\n makeAsyncEndEvent('FakeAsync', 0, pid, tid),\n ];\n const onStartEvent = sinon.spy<(e: Trace.Types.Events.Event) => void>(_event => {});\n const onEndEvent = sinon.spy<(e: Trace.Types.Events.Event) => void>(_event => {});\n const onInstantEvent = sinon.spy<(e: Trace.Types.Events.Event) => void>(_event => {});\n\n Trace.Helpers.Trace.forEachEvent(traceEvents, {\n onEndEvent,\n onStartEvent,\n onInstantEvent,\n ignoreAsyncEvents: false,\n });\n\n assert.strictEqual(onStartEvent.callCount, 0);\n assert.strictEqual(onEndEvent.callCount, 0);\n assert.strictEqual(onInstantEvent.callCount, 2);\n });\n });\n\n describe('isTopLevelEvent', () => {\n it('is true for a RunTask event', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const runTask = parsedTrace.Renderer.allTraceEntries.find(Trace.Types.Events.isRunTask);\n assert.isOk(runTask);\n\n assert.isTrue(Trace.Helpers.Trace.isTopLevelEvent(runTask));\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/helpers/TreeHelpers.d.ts b/public/models/trace/helpers/TreeHelpers.d.ts index f9d5475a6..666dfc1af 100644 --- a/public/models/trace/helpers/TreeHelpers.d.ts +++ b/public/models/trace/helpers/TreeHelpers.d.ts @@ -1,13 +1,13 @@ import * as Types from '../types/types.js'; export declare const makeTraceEntryNodeId: () => TraceEntryNodeId; export declare const makeEmptyTraceEntryTree: () => TraceEntryTree; -export declare const makeEmptyTraceEntryNode: (entry: Types.TraceEvents.TraceEventData, id: TraceEntryNodeId) => TraceEntryNode; +export declare const makeEmptyTraceEntryNode: (entry: Types.Events.Event, id: TraceEntryNodeId) => TraceEntryNode; export interface TraceEntryTree { roots: Set; maxDepth: number; } export interface TraceEntryNode { - entry: Types.TraceEvents.TraceEventData; + entry: Types.Events.Event; depth: number; selfTime?: Types.Timing.MicroSeconds; id: TraceEntryNodeId; @@ -34,13 +34,13 @@ export type TraceEntryNodeId = number & TraceEntryNodeIdTag; * * Complexity: O(n), where n = number of events */ -export declare function treify(entries: Types.TraceEvents.TraceEventData[], options?: { +export declare function treify(entries: Types.Events.Event[], options?: { filter: { - has: (name: Types.TraceEvents.KnownEventName) => boolean; + has: (name: Types.Events.Name) => boolean; }; }): { tree: TraceEntryTree; - entryToNode: Map; + entryToNode: Map; }; /** * Iterates events in a tree hierarchically, from top to bottom, @@ -63,7 +63,7 @@ export declare function treify(entries: Types.TraceEvents.TraceEventData[], opti * 9. End A * */ -export declare function walkTreeFromEntry(entryToNode: Map, rootEntry: Types.TraceEvents.TraceEventData, onEntryStart: (entry: Types.TraceEvents.TraceEventData) => void, onEntryEnd: (entry: Types.TraceEvents.TraceEventData) => void): void; +export declare function walkTreeFromEntry(entryToNode: Map, rootEntry: Types.Events.Event, onEntryStart: (entry: Types.Events.Event) => void, onEntryEnd: (entry: Types.Events.Event) => void): void; /** * Given a Helpers.TreeHelpers.RendererTree, this will iterates events in hierarchically, visiting * each root node and working from top to bottom, calling back on every event's @@ -87,7 +87,7 @@ export declare function walkTreeFromEntry(entryToNode: Map, tree: TraceEntryTree, onEntryStart: (entry: Types.TraceEvents.TraceEventData) => void, onEntryEnd: (entry: Types.TraceEvents.TraceEventData) => void, traceWindowToInclude?: Types.Timing.TraceWindowMicroSeconds, minDuration?: Types.Timing.MicroSeconds): void; +export declare function walkEntireTree(entryToNode: Map, tree: TraceEntryTree, onEntryStart: (entry: Types.Events.Event) => void, onEntryEnd: (entry: Types.Events.Event) => void, traceWindowToInclude?: Types.Timing.TraceWindowMicroSeconds, minDuration?: Types.Timing.MicroSeconds): void; /** * Determines if the given events, which are assumed to be ordered can * be organized into tree structures. @@ -107,5 +107,5 @@ export declare function walkEntireTree(entryToNode: Map (++nodeIdCount) as TraceEntryNodeId;\n\nexport const makeEmptyTraceEntryTree = (): TraceEntryTree => ({\n roots: new Set(),\n maxDepth: 0,\n});\n\nexport const makeEmptyTraceEntryNode =\n (entry: Types.TraceEvents.TraceEventData, id: TraceEntryNodeId): TraceEntryNode => ({\n entry,\n id,\n parent: null,\n children: [],\n depth: 0,\n });\n\nexport interface TraceEntryTree {\n roots: Set;\n maxDepth: number;\n}\n\nexport interface TraceEntryNode {\n entry: Types.TraceEvents.TraceEventData;\n depth: number;\n selfTime?: Types.Timing.MicroSeconds;\n id: TraceEntryNodeId;\n parent: TraceEntryNode|null;\n children: TraceEntryNode[];\n}\n\nclass TraceEntryNodeIdTag {\n /* eslint-disable-next-line no-unused-private-class-members */\n readonly #tag: (symbol|undefined);\n}\nexport type TraceEntryNodeId = number&TraceEntryNodeIdTag;\n\n/**\n * Builds a hierarchy of the entries (trace events and profile calls) in\n * a particular thread of a particular process, assuming that they're\n * sorted, by iterating through all of the events in order.\n *\n * The approach is analogous to how a parser would be implemented. A\n * stack maintains local context. A scanner peeks and pops from the data\n * stream. Various \"tokens\" (events) are treated as \"whitespace\"\n * (ignored).\n *\n * The tree starts out empty and is populated as the hierarchy is built.\n * The nodes are also assumed to be created empty, with no known parent\n * or children.\n *\n * Complexity: O(n), where n = number of events\n */\nexport function treify(entries: Types.TraceEvents.TraceEventData[], options?: {\n filter: {has: (name: Types.TraceEvents.KnownEventName) => boolean},\n}): {tree: TraceEntryTree, entryToNode: Map} {\n // As we construct the tree, store a map of each entry to its node. This\n // means if you are iterating over a list of RendererEntry events you can\n // easily look up that node in the tree.\n const entryToNode = new Map();\n\n const stack = [];\n // Reset the node id counter for every new renderer.\n nodeIdCount = -1;\n const tree = makeEmptyTraceEntryTree();\n\n for (let i = 0; i < entries.length; i++) {\n const event = entries[i];\n // If the current event should not be part of the tree, then simply proceed\n // with the next event.\n if (options && !options.filter.has(event.name as Types.TraceEvents.KnownEventName)) {\n continue;\n }\n\n const duration = event.dur || 0;\n const nodeId = makeTraceEntryNodeId();\n const node = makeEmptyTraceEntryNode(event, nodeId);\n\n // If the parent stack is empty, then the current event is a root. Create a\n // node for it, mark it as a root, then proceed with the next event.\n if (stack.length === 0) {\n tree.roots.add(node);\n node.selfTime = Types.Timing.MicroSeconds(duration);\n stack.push(node);\n tree.maxDepth = Math.max(tree.maxDepth, stack.length);\n entryToNode.set(event, node);\n continue;\n }\n\n const parentNode = stack.at(-1);\n if (parentNode === undefined) {\n throw new Error('Impossible: no parent node found in the stack');\n }\n\n const parentEvent = parentNode.entry;\n\n const begin = event.ts;\n const parentBegin = parentEvent.ts;\n const parentDuration = parentEvent.dur || 0;\n const end = begin + duration;\n const parentEnd = parentBegin + parentDuration;\n // Check the relationship between the parent event at the top of the stack,\n // and the current event being processed. There are only 4 distinct\n // possiblities, only 2 of them actually valid, given the assumed sorting:\n // 1. Current event starts before the parent event, ends whenever. (invalid)\n // 2. Current event starts after the parent event, ends whenever. (valid)\n // 3. Current event starts during the parent event, ends after. (invalid)\n // 4. Current event starts and ends during the parent event. (valid)\n\n // 1. If the current event starts before the parent event, then the data is\n // not sorted properly, messed up some way, or this logic is incomplete.\n const startsBeforeParent = begin < parentBegin;\n if (startsBeforeParent) {\n throw new Error('Impossible: current event starts before the parent event');\n }\n\n // 2. If the current event starts after the parent event, then it's a new\n // parent. Pop, then handle current event again.\n const startsAfterParent = begin >= parentEnd;\n if (startsAfterParent) {\n stack.pop();\n i--;\n // The last created node has been discarded, so discard this id.\n nodeIdCount--;\n continue;\n }\n // 3. If the current event starts during the parent event, but ends\n // after it, then the data is messed up some way, for example a\n // profile call was sampled too late after its start, ignore the\n // problematic event.\n const endsAfterParent = end > parentEnd;\n if (endsAfterParent) {\n continue;\n }\n\n // 4. The only remaining case is the common case, where the current event is\n // contained within the parent event. Create a node for the current\n // event, establish the parent/child relationship, then proceed with the\n // next event.\n node.depth = stack.length;\n node.parent = parentNode;\n parentNode.children.push(node);\n node.selfTime = Types.Timing.MicroSeconds(duration);\n if (parentNode.selfTime !== undefined) {\n parentNode.selfTime = Types.Timing.MicroSeconds(parentNode.selfTime - (event.dur || 0));\n }\n stack.push(node);\n tree.maxDepth = Math.max(tree.maxDepth, stack.length);\n entryToNode.set(event, node);\n }\n return {tree, entryToNode};\n}\n\n/**\n * Iterates events in a tree hierarchically, from top to bottom,\n * calling back on every event's start and end in the order\n * as it traverses down and then up the tree.\n *\n * For example, given this tree, the following callbacks\n * are expected to be made in the following order\n * |---------------A---------------|\n * |------B------||-------D------|\n * |---C---|\n *\n * 1. Start A\n * 3. Start B\n * 4. Start C\n * 5. End C\n * 6. End B\n * 7. Start D\n * 8. End D\n * 9. End A\n *\n */\nexport function walkTreeFromEntry(\n entryToNode: Map,\n rootEntry: Types.TraceEvents.TraceEventData,\n onEntryStart: (entry: Types.TraceEvents.TraceEventData) => void,\n onEntryEnd: (entry: Types.TraceEvents.TraceEventData) => void,\n ): void {\n const startNode = entryToNode.get(rootEntry);\n if (!startNode) {\n return;\n }\n walkTreeByNode(entryToNode, startNode, onEntryStart, onEntryEnd);\n}\n\n/**\n * Given a Helpers.TreeHelpers.RendererTree, this will iterates events in hierarchically, visiting\n * each root node and working from top to bottom, calling back on every event's\n * start and end in the order as it traverses down and then up the tree.\n *\n * For example, given this tree, the following callbacks\n * are expected to be made in the following order\n * |------------- Task A -------------||-- Task E --|\n * |-- Task B --||-- Task D --|\n * |- Task C -|\n *\n * 1. Start A\n * 3. Start B\n * 4. Start C\n * 5. End C\n * 6. End B\n * 7. Start D\n * 8. End D\n * 9. End A\n * 10. Start E\n * 11. End E\n *\n */\n\nexport function walkEntireTree(\n entryToNode: Map,\n tree: TraceEntryTree,\n onEntryStart: (entry: Types.TraceEvents.TraceEventData) => void,\n onEntryEnd: (entry: Types.TraceEvents.TraceEventData) => void,\n traceWindowToInclude?: Types.Timing.TraceWindowMicroSeconds,\n minDuration?: Types.Timing.MicroSeconds,\n ): void {\n for (const rootNode of tree.roots) {\n walkTreeByNode(entryToNode, rootNode, onEntryStart, onEntryEnd, traceWindowToInclude, minDuration);\n }\n}\n\nfunction walkTreeByNode(\n entryToNode: Map,\n rootNode: TraceEntryNode,\n onEntryStart: (entry: Types.TraceEvents.TraceEventData) => void,\n onEntryEnd: (entry: Types.TraceEvents.TraceEventData) => void,\n traceWindowToInclude?: Types.Timing.TraceWindowMicroSeconds,\n minDuration?: Types.Timing.MicroSeconds,\n ): void {\n if (traceWindowToInclude && !treeNodeIsInWindow(rootNode, traceWindowToInclude)) {\n // If this node is not within the provided window, we can skip it. We also\n // can skip all its children too, as we know they won't be in the window if\n // their parent is not.\n return;\n }\n\n if (typeof minDuration !== 'undefined') {\n const duration = Types.Timing.MicroSeconds(\n rootNode.entry.ts + Types.Timing.MicroSeconds(rootNode.entry.dur ?? 0),\n );\n if (duration < minDuration) {\n return;\n }\n }\n\n onEntryStart(rootNode.entry);\n for (const child of rootNode.children) {\n walkTreeByNode(entryToNode, child, onEntryStart, onEntryEnd, traceWindowToInclude, minDuration);\n }\n onEntryEnd(rootNode.entry);\n}\n\n/**\n * Returns true if the provided node is partially or fully within the trace\n * window. The entire node does not have to fit inside the window, but it does\n * have to partially intersect it.\n */\nfunction treeNodeIsInWindow(node: TraceEntryNode, traceWindow: Types.Timing.TraceWindowMicroSeconds): boolean {\n return eventIsInBounds(node.entry, traceWindow);\n}\n\n/**\n * Determines if the given events, which are assumed to be ordered can\n * be organized into tree structures.\n * This condition is met if there is *not* a pair of async events\n * e1 and e2 where:\n *\n * e1.startTime < e2.startTime && e1.endTime > e2.startTime && e1.endTime < e2.endTime.\n * or, graphically:\n * |------- e1 ------|\n * |------- e2 --------|\n *\n * Because a parent-child relationship cannot be made from the example\n * above, a tree cannot be made from the set of events.\n *\n * Sync events from the same thread are tree-able by definition.\n *\n * Note that this will also return true if multiple trees can be\n * built, for example if none of the events overlap with each other.\n */\nexport function canBuildTreesFromEvents(events: readonly Types.TraceEvents.TraceEventData[]): boolean {\n const stack: Types.TraceEvents.TraceEventData[] = [];\n for (const event of events) {\n const startTime = event.ts;\n const endTime = event.ts + (event.dur ?? 0);\n let parent = stack.at(-1);\n if (parent === undefined) {\n stack.push(event);\n continue;\n }\n let parentEndTime = parent.ts + (parent.dur ?? 0);\n // Discard events that are not parents for this event. The parent\n // is one whose end time is after this event start time.\n while (stack.length && startTime >= parentEndTime) {\n stack.pop();\n parent = stack.at(-1);\n\n if (parent === undefined) {\n break;\n }\n parentEndTime = parent.ts + (parent.dur ?? 0);\n }\n if (stack.length && endTime > parentEndTime) {\n // If such an event exists but its end time is before this\n // event's end time, then a tree cannot be made using this\n // events.\n return false;\n }\n stack.push(event);\n }\n return true;\n}\n"]} \ No newline at end of file +{"version":3,"file":"TreeHelpers.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/TreeHelpers.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Types from '../types/types.js';\n\nimport {eventIsInBounds} from './Timing.js';\n\nlet nodeIdCount = 0;\nexport const makeTraceEntryNodeId = (): TraceEntryNodeId => (++nodeIdCount) as TraceEntryNodeId;\n\nexport const makeEmptyTraceEntryTree = (): TraceEntryTree => ({\n roots: new Set(),\n maxDepth: 0,\n});\n\nexport const makeEmptyTraceEntryNode = (entry: Types.Events.Event, id: TraceEntryNodeId): TraceEntryNode => ({\n entry,\n id,\n parent: null,\n children: [],\n depth: 0,\n});\n\nexport interface TraceEntryTree {\n roots: Set;\n maxDepth: number;\n}\n\nexport interface TraceEntryNode {\n entry: Types.Events.Event;\n depth: number;\n selfTime?: Types.Timing.MicroSeconds;\n id: TraceEntryNodeId;\n parent: TraceEntryNode|null;\n children: TraceEntryNode[];\n}\n\nclass TraceEntryNodeIdTag {\n /* eslint-disable-next-line no-unused-private-class-members */\n readonly #tag: (symbol|undefined);\n}\nexport type TraceEntryNodeId = number&TraceEntryNodeIdTag;\n\n/**\n * Builds a hierarchy of the entries (trace events and profile calls) in\n * a particular thread of a particular process, assuming that they're\n * sorted, by iterating through all of the events in order.\n *\n * The approach is analogous to how a parser would be implemented. A\n * stack maintains local context. A scanner peeks and pops from the data\n * stream. Various \"tokens\" (events) are treated as \"whitespace\"\n * (ignored).\n *\n * The tree starts out empty and is populated as the hierarchy is built.\n * The nodes are also assumed to be created empty, with no known parent\n * or children.\n *\n * Complexity: O(n), where n = number of events\n */\nexport function treify(entries: Types.Events.Event[], options?: {\n filter: {has: (name: Types.Events.Name) => boolean},\n}): {tree: TraceEntryTree, entryToNode: Map} {\n // As we construct the tree, store a map of each entry to its node. This\n // means if you are iterating over a list of RendererEntry events you can\n // easily look up that node in the tree.\n const entryToNode = new Map();\n\n const stack = [];\n // Reset the node id counter for every new renderer.\n nodeIdCount = -1;\n const tree = makeEmptyTraceEntryTree();\n\n for (let i = 0; i < entries.length; i++) {\n const event = entries[i];\n // If the current event should not be part of the tree, then simply proceed\n // with the next event.\n if (options && !options.filter.has(event.name as Types.Events.Name)) {\n continue;\n }\n\n const duration = event.dur || 0;\n const nodeId = makeTraceEntryNodeId();\n const node = makeEmptyTraceEntryNode(event, nodeId);\n\n // If the parent stack is empty, then the current event is a root. Create a\n // node for it, mark it as a root, then proceed with the next event.\n if (stack.length === 0) {\n tree.roots.add(node);\n node.selfTime = Types.Timing.MicroSeconds(duration);\n stack.push(node);\n tree.maxDepth = Math.max(tree.maxDepth, stack.length);\n entryToNode.set(event, node);\n continue;\n }\n\n const parentNode = stack.at(-1);\n if (parentNode === undefined) {\n throw new Error('Impossible: no parent node found in the stack');\n }\n\n const parentEvent = parentNode.entry;\n\n const begin = event.ts;\n const parentBegin = parentEvent.ts;\n const parentDuration = parentEvent.dur || 0;\n const end = begin + duration;\n const parentEnd = parentBegin + parentDuration;\n // Check the relationship between the parent event at the top of the stack,\n // and the current event being processed. There are only 4 distinct\n // possiblities, only 2 of them actually valid, given the assumed sorting:\n // 1. Current event starts before the parent event, ends whenever. (invalid)\n // 2. Current event starts after the parent event, ends whenever. (valid)\n // 3. Current event starts during the parent event, ends after. (invalid)\n // 4. Current event starts and ends during the parent event. (valid)\n\n // 1. If the current event starts before the parent event, then the data is\n // not sorted properly, messed up some way, or this logic is incomplete.\n const startsBeforeParent = begin < parentBegin;\n if (startsBeforeParent) {\n throw new Error('Impossible: current event starts before the parent event');\n }\n\n // 2. If the current event starts after the parent event, then it's a new\n // parent. Pop, then handle current event again.\n const startsAfterParent = begin >= parentEnd;\n if (startsAfterParent) {\n stack.pop();\n i--;\n // The last created node has been discarded, so discard this id.\n nodeIdCount--;\n continue;\n }\n // 3. If the current event starts during the parent event, but ends\n // after it, then the data is messed up some way, for example a\n // profile call was sampled too late after its start, ignore the\n // problematic event.\n const endsAfterParent = end > parentEnd;\n if (endsAfterParent) {\n continue;\n }\n\n // 4. The only remaining case is the common case, where the current event is\n // contained within the parent event. Create a node for the current\n // event, establish the parent/child relationship, then proceed with the\n // next event.\n node.depth = stack.length;\n node.parent = parentNode;\n parentNode.children.push(node);\n node.selfTime = Types.Timing.MicroSeconds(duration);\n if (parentNode.selfTime !== undefined) {\n parentNode.selfTime = Types.Timing.MicroSeconds(parentNode.selfTime - (event.dur || 0));\n }\n stack.push(node);\n tree.maxDepth = Math.max(tree.maxDepth, stack.length);\n entryToNode.set(event, node);\n }\n return {tree, entryToNode};\n}\n\n/**\n * Iterates events in a tree hierarchically, from top to bottom,\n * calling back on every event's start and end in the order\n * as it traverses down and then up the tree.\n *\n * For example, given this tree, the following callbacks\n * are expected to be made in the following order\n * |---------------A---------------|\n * |------B------||-------D------|\n * |---C---|\n *\n * 1. Start A\n * 3. Start B\n * 4. Start C\n * 5. End C\n * 6. End B\n * 7. Start D\n * 8. End D\n * 9. End A\n *\n */\nexport function walkTreeFromEntry(\n entryToNode: Map,\n rootEntry: Types.Events.Event,\n onEntryStart: (entry: Types.Events.Event) => void,\n onEntryEnd: (entry: Types.Events.Event) => void,\n ): void {\n const startNode = entryToNode.get(rootEntry);\n if (!startNode) {\n return;\n }\n walkTreeByNode(entryToNode, startNode, onEntryStart, onEntryEnd);\n}\n\n/**\n * Given a Helpers.TreeHelpers.RendererTree, this will iterates events in hierarchically, visiting\n * each root node and working from top to bottom, calling back on every event's\n * start and end in the order as it traverses down and then up the tree.\n *\n * For example, given this tree, the following callbacks\n * are expected to be made in the following order\n * |------------- Task A -------------||-- Task E --|\n * |-- Task B --||-- Task D --|\n * |- Task C -|\n *\n * 1. Start A\n * 3. Start B\n * 4. Start C\n * 5. End C\n * 6. End B\n * 7. Start D\n * 8. End D\n * 9. End A\n * 10. Start E\n * 11. End E\n *\n */\n\nexport function walkEntireTree(\n entryToNode: Map,\n tree: TraceEntryTree,\n onEntryStart: (entry: Types.Events.Event) => void,\n onEntryEnd: (entry: Types.Events.Event) => void,\n traceWindowToInclude?: Types.Timing.TraceWindowMicroSeconds,\n minDuration?: Types.Timing.MicroSeconds,\n ): void {\n for (const rootNode of tree.roots) {\n walkTreeByNode(entryToNode, rootNode, onEntryStart, onEntryEnd, traceWindowToInclude, minDuration);\n }\n}\n\nfunction walkTreeByNode(\n entryToNode: Map,\n rootNode: TraceEntryNode,\n onEntryStart: (entry: Types.Events.Event) => void,\n onEntryEnd: (entry: Types.Events.Event) => void,\n traceWindowToInclude?: Types.Timing.TraceWindowMicroSeconds,\n minDuration?: Types.Timing.MicroSeconds,\n ): void {\n if (traceWindowToInclude && !treeNodeIsInWindow(rootNode, traceWindowToInclude)) {\n // If this node is not within the provided window, we can skip it. We also\n // can skip all its children too, as we know they won't be in the window if\n // their parent is not.\n return;\n }\n\n if (typeof minDuration !== 'undefined') {\n const duration = Types.Timing.MicroSeconds(\n rootNode.entry.ts + Types.Timing.MicroSeconds(rootNode.entry.dur ?? 0),\n );\n if (duration < minDuration) {\n return;\n }\n }\n\n onEntryStart(rootNode.entry);\n for (const child of rootNode.children) {\n walkTreeByNode(entryToNode, child, onEntryStart, onEntryEnd, traceWindowToInclude, minDuration);\n }\n onEntryEnd(rootNode.entry);\n}\n\n/**\n * Returns true if the provided node is partially or fully within the trace\n * window. The entire node does not have to fit inside the window, but it does\n * have to partially intersect it.\n */\nfunction treeNodeIsInWindow(node: TraceEntryNode, traceWindow: Types.Timing.TraceWindowMicroSeconds): boolean {\n return eventIsInBounds(node.entry, traceWindow);\n}\n\n/**\n * Determines if the given events, which are assumed to be ordered can\n * be organized into tree structures.\n * This condition is met if there is *not* a pair of async events\n * e1 and e2 where:\n *\n * e1.startTime < e2.startTime && e1.endTime > e2.startTime && e1.endTime < e2.endTime.\n * or, graphically:\n * |------- e1 ------|\n * |------- e2 --------|\n *\n * Because a parent-child relationship cannot be made from the example\n * above, a tree cannot be made from the set of events.\n *\n * Sync events from the same thread are tree-able by definition.\n *\n * Note that this will also return true if multiple trees can be\n * built, for example if none of the events overlap with each other.\n */\nexport function canBuildTreesFromEvents(events: readonly Types.Events.Event[]): boolean {\n const stack: Types.Events.Event[] = [];\n for (const event of events) {\n const startTime = event.ts;\n const endTime = event.ts + (event.dur ?? 0);\n let parent = stack.at(-1);\n if (parent === undefined) {\n stack.push(event);\n continue;\n }\n let parentEndTime = parent.ts + (parent.dur ?? 0);\n // Discard events that are not parents for this event. The parent\n // is one whose end time is after this event start time.\n while (stack.length && startTime >= parentEndTime) {\n stack.pop();\n parent = stack.at(-1);\n\n if (parent === undefined) {\n break;\n }\n parentEndTime = parent.ts + (parent.dur ?? 0);\n }\n if (stack.length && endTime > parentEndTime) {\n // If such an event exists but its end time is before this\n // event's end time, then a tree cannot be made using this\n // events.\n return false;\n }\n stack.push(event);\n }\n return true;\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/helpers/TreeHelpers.test.js b/public/models/trace/helpers/TreeHelpers.test.js index f0dfaadd1..23dfc83da 100644 --- a/public/models/trace/helpers/TreeHelpers.test.js +++ b/public/models/trace/helpers/TreeHelpers.test.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import { getEventsIn, makeCompleteEvent, makeProfileCall, prettyPrint, } from '../../../testing/TraceHelpers.js'; -import * as TraceModel from '../trace.js'; +import * as Trace from '../trace.js'; describe('TreeHelpers', () => { describe('treify', () => { it('can build a hierarchy of events without filters', async () => { @@ -18,8 +18,8 @@ describe('TreeHelpers', () => { makeCompleteEvent('C', 2, 1), // 2..3 makeCompleteEvent('E', 11, 3), // 11..14 ]; - TraceModel.Helpers.Trace.sortTraceEventsInPlace(data); - const { tree } = TraceModel.Helpers.TreeHelpers.treify(data, { filter: { has: () => true } }); + Trace.Helpers.Trace.sortTraceEventsInPlace(data); + const { tree } = Trace.Helpers.TreeHelpers.treify(data, { filter: { has: () => true } }); assert.strictEqual(tree.maxDepth, 3, 'Got the correct tree max depth'); const rootsEvents = [...tree.roots].map(n => n ? n.entry : null); assert.deepEqual(rootsEvents.map(e => e ? { name: e.name, ts: e.ts, dur: e.dur } : null), [ @@ -72,9 +72,9 @@ describe('TreeHelpers', () => { makeCompleteEvent('C', 2, 1), // 2..3 makeCompleteEvent('E', 11, 3), // 11..14 ]; - TraceModel.Helpers.Trace.sortTraceEventsInPlace(data); + Trace.Helpers.Trace.sortTraceEventsInPlace(data); const filter = new Set(['A', 'D']); - const { tree } = TraceModel.Helpers.TreeHelpers.treify(data, { filter }); + const { tree } = Trace.Helpers.TreeHelpers.treify(data, { filter }); assert.strictEqual(tree.maxDepth, 2, 'Got the correct tree max depth'); const rootsEvents = [...tree.roots].map(n => n.entry); assert.deepEqual(rootsEvents.map(e => e ? { name: e.name, ts: e.ts, dur: e.dur } : null), [ @@ -110,8 +110,8 @@ describe('TreeHelpers', () => { makeCompleteEvent('C', 2, 1), // 2..3 (finishes when B finishes) makeCompleteEvent('E', 10, 3), // 10..13 (starts when A finishes) ]; - TraceModel.Helpers.Trace.sortTraceEventsInPlace(data); - const { tree } = TraceModel.Helpers.TreeHelpers.treify(data, { filter: { has: () => true } }); + Trace.Helpers.Trace.sortTraceEventsInPlace(data); + const { tree } = Trace.Helpers.TreeHelpers.treify(data, { filter: { has: () => true } }); assert.strictEqual(tree.maxDepth, 3, 'Got the correct tree max depth'); const rootsEvents = [...tree.roots].map(n => n.entry); assert.deepEqual(rootsEvents.map(e => e ? { name: e.name, ts: e.ts, dur: e.dur } : null), [ @@ -164,8 +164,8 @@ describe('TreeHelpers', () => { makeCompleteEvent('C', 2, 1), // 2..3 (finishes when B finishes) makeCompleteEvent('E', 10, 3), // 10..13 (starts when A finishes) ]; - TraceModel.Helpers.Trace.sortTraceEventsInPlace(data); - const { tree } = TraceModel.Helpers.TreeHelpers.treify(data, { filter: { has: () => true } }); + Trace.Helpers.Trace.sortTraceEventsInPlace(data); + const { tree } = Trace.Helpers.TreeHelpers.treify(data, { filter: { has: () => true } }); const nodeA = [...tree.roots].at(0); const nodeE = [...tree.roots].at(1); if (!nodeA || !nodeE) { @@ -193,46 +193,46 @@ describe('TreeHelpers', () => { assert.fail('Total time for task was not found'); return; } - assert.strictEqual(taskCTotalTime, TraceModel.Types.Timing.MicroSeconds(1)); + assert.strictEqual(taskCTotalTime, Trace.Types.Timing.MicroSeconds(1)); assert.strictEqual(nodeC.selfTime, taskCTotalTime); const taskBTotalTime = taskB.dur; if (taskBTotalTime === undefined) { assert.fail('Total time for task was not found'); return; } - assert.strictEqual(taskBTotalTime, TraceModel.Types.Timing.MicroSeconds(3)); - assert.strictEqual(nodeB.selfTime, TraceModel.Types.Timing.MicroSeconds(taskBTotalTime - taskCTotalTime)); + assert.strictEqual(taskBTotalTime, Trace.Types.Timing.MicroSeconds(3)); + assert.strictEqual(nodeB.selfTime, Trace.Types.Timing.MicroSeconds(taskBTotalTime - taskCTotalTime)); const taskDTotalTime = taskD.dur; if (taskDTotalTime === undefined) { assert.fail('Total time for task was not found'); return; } - assert.strictEqual(taskDTotalTime, TraceModel.Types.Timing.MicroSeconds(3)); + assert.strictEqual(taskDTotalTime, Trace.Types.Timing.MicroSeconds(3)); assert.strictEqual(nodeD.selfTime, taskDTotalTime); const taskATotalTime = taskA.dur; if (taskATotalTime === undefined) { assert.fail('Total time for task was not found'); return; } - assert.strictEqual(taskATotalTime, TraceModel.Types.Timing.MicroSeconds(10)); - assert.strictEqual(nodeA.selfTime, TraceModel.Types.Timing.MicroSeconds(taskATotalTime - taskBTotalTime - taskDTotalTime)); + assert.strictEqual(taskATotalTime, Trace.Types.Timing.MicroSeconds(10)); + assert.strictEqual(nodeA.selfTime, Trace.Types.Timing.MicroSeconds(taskATotalTime - taskBTotalTime - taskDTotalTime)); const taskETotalTime = taskE.dur; if (taskETotalTime === undefined) { assert.fail('Total time for task was not found'); return; } - assert.strictEqual(taskETotalTime, TraceModel.Types.Timing.MicroSeconds(3)); + assert.strictEqual(taskETotalTime, Trace.Types.Timing.MicroSeconds(3)); assert.strictEqual(nodeD.selfTime, taskETotalTime); }); describe('building hierarchies trace events and profile calls', () => { it('builds a hierarchy from trace events and profile calls', async () => { - const evaluateScript = makeCompleteEvent("EvaluateScript" /* TraceModel.Types.TraceEvents.KnownEventName.EVALUATE_SCRIPT */, 0, 500); + const evaluateScript = makeCompleteEvent("EvaluateScript" /* Trace.Types.Events.Name.EVALUATE_SCRIPT */, 0, 500); const v8Run = makeCompleteEvent('v8.run', 10, 490); const parseFunction = makeCompleteEvent('V8.ParseFunction', 12, 1); const traceEvents = [evaluateScript, v8Run, parseFunction]; const profileCalls = [makeProfileCall('a', 100, 200), makeProfileCall('b', 300, 200)]; - const allEntries = TraceModel.Helpers.Trace.mergeEventsInOrder(traceEvents, profileCalls); - const { tree } = TraceModel.Helpers.TreeHelpers.treify(allEntries, { filter: { has: () => true } }); + const allEntries = Trace.Helpers.Trace.mergeEventsInOrder(traceEvents, profileCalls); + const { tree } = Trace.Helpers.TreeHelpers.treify(allEntries, { filter: { has: () => true } }); assert.strictEqual(prettyPrint(tree), ` -EvaluateScript [0.5ms] -v8.run [0.49ms] @@ -247,7 +247,7 @@ describe('TreeHelpers', () => { makeProfileCall('c', 300, 200), makeProfileCall('d', 400, 100), ]; - const { tree } = TraceModel.Helpers.TreeHelpers.treify(allEntries, { filter: { has: () => true } }); + const { tree } = Trace.Helpers.TreeHelpers.treify(allEntries, { filter: { has: () => true } }); assert.strictEqual(prettyPrint(tree), ` -ProfileCall (a) [0.2ms] -ProfileCall (b) [0.2ms] @@ -270,8 +270,8 @@ describe('TreeHelpers', () => { makeCompleteEvent('C', 2, 1), // 2..3 makeCompleteEvent('E', 11, 3), // 11..14 ]; - TraceModel.Helpers.Trace.sortTraceEventsInPlace(data); - const { tree, entryToNode } = TraceModel.Helpers.TreeHelpers.treify(data, { filter: { has: () => true } }); + Trace.Helpers.Trace.sortTraceEventsInPlace(data); + const { tree, entryToNode } = Trace.Helpers.TreeHelpers.treify(data, { filter: { has: () => true } }); const callOrder = []; function onEntryStart(entry) { callOrder.push({ type: 'START', entryName: entry.name }); @@ -279,7 +279,7 @@ describe('TreeHelpers', () => { function onEntryEnd(entry) { callOrder.push({ type: 'END', entryName: entry.name }); } - TraceModel.Helpers.TreeHelpers.walkEntireTree(entryToNode, tree, onEntryStart, onEntryEnd); + Trace.Helpers.TreeHelpers.walkEntireTree(entryToNode, tree, onEntryStart, onEntryEnd); assert.deepEqual(callOrder, [ { type: 'START', entryName: 'A' }, { type: 'START', entryName: 'B' }, @@ -307,8 +307,8 @@ describe('TreeHelpers', () => { makeCompleteEvent('C', 2, 1), // 2..3 makeCompleteEvent('E', 11, 3), // 11..14 ]; - TraceModel.Helpers.Trace.sortTraceEventsInPlace(data); - const { tree, entryToNode } = TraceModel.Helpers.TreeHelpers.treify(data, { filter: { has: () => true } }); + Trace.Helpers.Trace.sortTraceEventsInPlace(data); + const { tree, entryToNode } = Trace.Helpers.TreeHelpers.treify(data, { filter: { has: () => true } }); const callOrder = []; function onEntryStart(entry) { callOrder.push({ type: 'START', entryName: entry.name }); @@ -316,10 +316,10 @@ describe('TreeHelpers', () => { function onEntryEnd(entry) { callOrder.push({ type: 'END', entryName: entry.name }); } - TraceModel.Helpers.TreeHelpers.walkEntireTree(entryToNode, tree, onEntryStart, onEntryEnd, { - min: TraceModel.Types.Timing.MicroSeconds(5), - max: TraceModel.Types.Timing.MicroSeconds(10), - range: TraceModel.Types.Timing.MicroSeconds(5), + Trace.Helpers.TreeHelpers.walkEntireTree(entryToNode, tree, onEntryStart, onEntryEnd, { + min: Trace.Types.Timing.MicroSeconds(5), + max: Trace.Types.Timing.MicroSeconds(10), + range: Trace.Types.Timing.MicroSeconds(5), }); assert.deepEqual(callOrder, [ { type: 'START', entryName: 'A' }, @@ -341,8 +341,8 @@ describe('TreeHelpers', () => { makeCompleteEvent('C', 2, 1), // 2..3 makeCompleteEvent('E', 11, 3), // 11..14 ]; - TraceModel.Helpers.Trace.sortTraceEventsInPlace(data); - const { tree, entryToNode } = TraceModel.Helpers.TreeHelpers.treify(data, { filter: { has: () => true } }); + Trace.Helpers.Trace.sortTraceEventsInPlace(data); + const { tree, entryToNode } = Trace.Helpers.TreeHelpers.treify(data, { filter: { has: () => true } }); const callOrder = []; function onEntryStart(entry) { callOrder.push({ type: 'START', entryName: entry.name }); @@ -355,7 +355,7 @@ describe('TreeHelpers', () => { throw new Error('Could not find root node'); } assert.strictEqual(rootNode.entry.name, 'A'); - TraceModel.Helpers.TreeHelpers.walkTreeFromEntry(entryToNode, rootNode.entry, onEntryStart, onEntryEnd); + Trace.Helpers.TreeHelpers.walkTreeFromEntry(entryToNode, rootNode.entry, onEntryStart, onEntryEnd); assert.deepEqual(callOrder, [ { type: 'START', entryName: 'A' }, { type: 'START', entryName: 'B' }, @@ -379,7 +379,7 @@ describe('TreeHelpers', () => { makeCompleteEvent('f', 51, 24), makeCompleteEvent('g', 76, 24), ]; - assert.isTrue(TraceModel.Helpers.TreeHelpers.canBuildTreesFromEvents(data)); + assert.isTrue(Trace.Helpers.TreeHelpers.canBuildTreesFromEvents(data)); }); it('returns false if a pair of events (e1, e2) exists such that e1 overlaps with e2 without one fully containing the other', () => { const data = [ @@ -392,7 +392,7 @@ describe('TreeHelpers', () => { makeCompleteEvent('f', 51, 24), makeCompleteEvent('g', 76, 24), ]; - assert.isFalse(TraceModel.Helpers.TreeHelpers.canBuildTreesFromEvents(data)); + assert.isFalse(Trace.Helpers.TreeHelpers.canBuildTreesFromEvents(data)); }); }); }); diff --git a/public/models/trace/helpers/TreeHelpers.test.js.map b/public/models/trace/helpers/TreeHelpers.test.js.map index 4d63899bb..2a6af851e 100644 --- a/public/models/trace/helpers/TreeHelpers.test.js.map +++ b/public/models/trace/helpers/TreeHelpers.test.js.map @@ -1 +1 @@ -{"version":3,"file":"TreeHelpers.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/TreeHelpers.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {\n getEventsIn,\n makeCompleteEvent,\n makeProfileCall,\n prettyPrint,\n} from '../../../testing/TraceHelpers.js';\nimport * as TraceModel from '../trace.js';\n\ndescribe('TreeHelpers', () => {\n describe('treify', () => {\n it('can build a hierarchy of events without filters', async () => {\n /**\n * |------------- Task A -------------||-- Task E --|\n * |-- Task B --||-- Task D --|\n * |- Task C -|\n */\n const data = [\n makeCompleteEvent('A', 0, 10), // 0..10\n makeCompleteEvent('B', 1, 3), // 1..4\n makeCompleteEvent('D', 5, 3), // 5..8\n makeCompleteEvent('C', 2, 1), // 2..3\n makeCompleteEvent('E', 11, 3), // 11..14\n ];\n\n TraceModel.Helpers.Trace.sortTraceEventsInPlace(data);\n const {tree} = TraceModel.Helpers.TreeHelpers.treify(data, {filter: {has: () => true}});\n\n assert.strictEqual(tree.maxDepth, 3, 'Got the correct tree max depth');\n\n const rootsEvents = [...tree.roots].map(n => n ? n.entry : null);\n assert.deepEqual(rootsEvents.map(e => e ? {name: e.name, ts: e.ts, dur: e.dur} : null) as unknown[], [\n {name: 'A', ts: 0, dur: 10},\n {name: 'E', ts: 11, dur: 3},\n ]);\n\n const nodeA = [...tree.roots].at(0);\n const nodeE = [...tree.roots].at(1);\n if (!nodeA || !nodeE) {\n assert(false, 'Root nodes were not found');\n return;\n }\n\n const childrenOfA = getEventsIn(nodeA.children.values());\n assert.deepEqual(childrenOfA.map(e => e ? {name: e.name, ts: e.ts, dur: e.dur} : null) as unknown[], [\n {name: 'B', ts: 1, dur: 3},\n {name: 'D', ts: 5, dur: 3},\n ]);\n\n const childrenOfE = getEventsIn(nodeE.children.values());\n assert.deepEqual(childrenOfE, []);\n\n const nodeB = [...nodeA.children].at(0);\n const nodeD = [...nodeA.children].at(1);\n if (!nodeB || !nodeD) {\n assert(false, 'Child nodes were not found');\n return;\n }\n\n const childrenOfB = getEventsIn(nodeB.children.values());\n assert.deepEqual(childrenOfB.map(e => e ? {name: e.name, ts: e.ts, dur: e.dur} : null) as unknown[], [\n {name: 'C', ts: 2, dur: 1},\n ]);\n\n const childrenOfD = getEventsIn(nodeD.children.values());\n assert.deepEqual(childrenOfD, []);\n\n const nodeC = [...nodeB.children].at(0);\n if (!nodeC) {\n assert(false, 'Child nodes were not found');\n return;\n }\n\n const childrenOfC = getEventsIn(nodeC.children.values());\n assert.deepEqual(childrenOfC, []);\n });\n\n it('can build a hierarchy of events with filters', async () => {\n /**\n * |------------- Task A -------------||-- ?????? --|\n * |-- ?????? --||-- Task D --|\n * |- ?????? -|\n */\n const data = [\n makeCompleteEvent('A', 0, 10), // 0..10\n makeCompleteEvent('B', 1, 3), // 1..4\n makeCompleteEvent('D', 5, 3), // 5..8\n makeCompleteEvent('C', 2, 1), // 2..3\n makeCompleteEvent('E', 11, 3), // 11..14\n ];\n\n TraceModel.Helpers.Trace.sortTraceEventsInPlace(data);\n const filter = new Set(['A', 'D']);\n const {tree} = TraceModel.Helpers.TreeHelpers.treify(data, {filter});\n\n assert.strictEqual(tree.maxDepth, 2, 'Got the correct tree max depth');\n\n const rootsEvents = [...tree.roots].map(n => n.entry);\n assert.deepEqual(rootsEvents.map(e => e ? {name: e.name, ts: e.ts, dur: e.dur} : null) as unknown[], [\n {name: 'A', ts: 0, dur: 10},\n ]);\n\n const nodeA = [...tree.roots].at(0);\n if (!nodeA) {\n assert(false, 'Root nodes were not found');\n return;\n }\n\n const childrenOfA = getEventsIn(nodeA.children.values());\n assert.deepEqual(childrenOfA.map(e => e ? {name: e.name, ts: e.ts, dur: e.dur} : null) as unknown[], [\n {name: 'D', ts: 5, dur: 3},\n ]);\n\n const nodeD = [...nodeA.children].at(0);\n if (!nodeD) {\n assert(false, 'Child nodes were not found');\n return;\n }\n\n const childrenOfD = getEventsIn(nodeD.children.values());\n assert.deepEqual(childrenOfD, []);\n });\n\n it('can build a hierarchy of events that start and end close to each other', async () => {\n /**\n * |------------- Task A -------------||-- Task E --|\n * |-- Task B --||-- Task D --|\n * |- Task C -|\n */\n const data = [\n makeCompleteEvent('A', 0, 10), // 0..10\n makeCompleteEvent('B', 0, 3), // 0..3 (starts same time as A)\n makeCompleteEvent('D', 3, 3), // 3..6 (starts when B finishes)\n makeCompleteEvent('C', 2, 1), // 2..3 (finishes when B finishes)\n makeCompleteEvent('E', 10, 3), // 10..13 (starts when A finishes)\n ];\n\n TraceModel.Helpers.Trace.sortTraceEventsInPlace(data);\n const {tree} = TraceModel.Helpers.TreeHelpers.treify(data, {filter: {has: () => true}});\n\n assert.strictEqual(tree.maxDepth, 3, 'Got the correct tree max depth');\n\n const rootsEvents = [...tree.roots].map(n => n.entry);\n assert.deepEqual(rootsEvents.map(e => e ? {name: e.name, ts: e.ts, dur: e.dur} : null) as unknown[], [\n {name: 'A', ts: 0, dur: 10},\n {name: 'E', ts: 10, dur: 3},\n ]);\n\n const nodeA = [...tree.roots].at(0);\n const nodeE = [...tree.roots].at(1);\n if (!nodeA || !nodeE) {\n assert(false, 'Root nodes were not found');\n return;\n }\n\n const childrenOfA = getEventsIn(nodeA.children.values());\n assert.deepEqual(childrenOfA.map(e => e ? {name: e.name, ts: e.ts, dur: e.dur} : null) as unknown[], [\n {name: 'B', ts: 0, dur: 3},\n {name: 'D', ts: 3, dur: 3},\n ]);\n\n const childrenOfE = getEventsIn(nodeE.children.values());\n assert.deepEqual(childrenOfE, []);\n\n const nodeB = [...nodeA.children].at(0);\n const nodeD = [...nodeA.children].at(1);\n if (!nodeB || !nodeD) {\n assert(false, 'Child nodes were not found');\n return;\n }\n\n const childrenOfB = getEventsIn(nodeB.children.values());\n assert.deepEqual(childrenOfB.map(e => e ? {name: e.name, ts: e.ts, dur: e.dur} : null) as unknown[], [\n {name: 'C', ts: 2, dur: 1},\n ]);\n\n const childrenOfD = getEventsIn(nodeD.children.values());\n assert.deepEqual(childrenOfD, []);\n\n const nodeC = [...nodeB.children].at(0);\n if (!nodeC) {\n assert(false, 'Child nodes were not found');\n return;\n }\n\n const childrenOfC = getEventsIn(nodeC.children.values());\n assert.deepEqual(childrenOfC, []);\n });\n\n it('correctly calculates the total and self times of a hierarchy of events', async () => {\n /**\n * |------------- Task A -------------||-- Task E --|\n * |-- Task B --||-- Task D --|\n * |- Task C -|\n */\n const data = [\n makeCompleteEvent('A', 0, 10), // 0..10\n makeCompleteEvent('B', 0, 3), // 0..3 (starts same time as A)\n makeCompleteEvent('D', 3, 3), // 3..6 (starts when B finishes)\n makeCompleteEvent('C', 2, 1), // 2..3 (finishes when B finishes)\n makeCompleteEvent('E', 10, 3), // 10..13 (starts when A finishes)\n ] as TraceModel.Types.TraceEvents.TraceEventData[];\n\n TraceModel.Helpers.Trace.sortTraceEventsInPlace(data);\n const {tree} = TraceModel.Helpers.TreeHelpers.treify(data, {filter: {has: () => true}});\n\n const nodeA = [...tree.roots].at(0);\n const nodeE = [...tree.roots].at(1);\n if (!nodeA || !nodeE) {\n assert(false, 'Root nodes were not found');\n return;\n }\n const taskA = nodeA.entry;\n const taskE = nodeE.entry;\n const nodeD = [...nodeA.children].at(1);\n const nodeB = [...nodeA.children].at(0);\n if (!nodeB || !nodeD) {\n assert(false, 'Child nodes were not found');\n return;\n }\n const taskD = nodeD.entry;\n const taskB = nodeB.entry;\n\n const nodeC = [...nodeB.children].at(0);\n\n if (!nodeC) {\n assert(false, 'Child nodes were not found');\n return;\n }\n const taskC = nodeC.entry;\n\n const taskCTotalTime = taskC.dur;\n if (taskCTotalTime === undefined) {\n assert.fail('Total time for task was not found');\n return;\n }\n assert.strictEqual(taskCTotalTime, TraceModel.Types.Timing.MicroSeconds(1));\n assert.strictEqual(nodeC.selfTime, taskCTotalTime);\n\n const taskBTotalTime = taskB.dur;\n if (taskBTotalTime === undefined) {\n assert.fail('Total time for task was not found');\n return;\n }\n assert.strictEqual(taskBTotalTime, TraceModel.Types.Timing.MicroSeconds(3));\n assert.strictEqual(nodeB.selfTime, TraceModel.Types.Timing.MicroSeconds(taskBTotalTime - taskCTotalTime));\n\n const taskDTotalTime = taskD.dur;\n if (taskDTotalTime === undefined) {\n assert.fail('Total time for task was not found');\n return;\n }\n assert.strictEqual(taskDTotalTime, TraceModel.Types.Timing.MicroSeconds(3));\n assert.strictEqual(nodeD.selfTime, taskDTotalTime);\n\n const taskATotalTime = taskA.dur;\n if (taskATotalTime === undefined) {\n assert.fail('Total time for task was not found');\n return;\n }\n assert.strictEqual(taskATotalTime, TraceModel.Types.Timing.MicroSeconds(10));\n assert.strictEqual(\n nodeA.selfTime, TraceModel.Types.Timing.MicroSeconds(taskATotalTime - taskBTotalTime - taskDTotalTime));\n\n const taskETotalTime = taskE.dur;\n if (taskETotalTime === undefined) {\n assert.fail('Total time for task was not found');\n return;\n }\n assert.strictEqual(taskETotalTime, TraceModel.Types.Timing.MicroSeconds(3));\n assert.strictEqual(nodeD.selfTime, taskETotalTime);\n });\n describe('building hierarchies trace events and profile calls', () => {\n it('builds a hierarchy from trace events and profile calls', async () => {\n const evaluateScript = makeCompleteEvent(TraceModel.Types.TraceEvents.KnownEventName.EVALUATE_SCRIPT, 0, 500);\n const v8Run = makeCompleteEvent('v8.run', 10, 490);\n const parseFunction = makeCompleteEvent('V8.ParseFunction', 12, 1);\n\n const traceEvents: TraceModel.Types.TraceEvents.TraceEventData[] = [evaluateScript, v8Run, parseFunction];\n\n const profileCalls = [makeProfileCall('a', 100, 200), makeProfileCall('b', 300, 200)];\n const allEntries = TraceModel.Helpers.Trace.mergeEventsInOrder(traceEvents, profileCalls);\n const {tree} = TraceModel.Helpers.TreeHelpers.treify(allEntries, {filter: {has: () => true}});\n assert.strictEqual(prettyPrint(tree), `\n-EvaluateScript [0.5ms]\n -v8.run [0.49ms]\n -V8.ParseFunction [0.001ms]\n -ProfileCall (a) [0.2ms]\n -ProfileCall (b) [0.2ms]`);\n });\n\n it('builds a hierarchy from only profile calls', async () => {\n const allEntries = [\n makeProfileCall('a', 100, 200),\n makeProfileCall('b', 300, 200),\n makeProfileCall('c', 300, 200),\n makeProfileCall('d', 400, 100),\n ];\n const {tree} = TraceModel.Helpers.TreeHelpers.treify(allEntries, {filter: {has: () => true}});\n assert.strictEqual(prettyPrint(tree), `\n-ProfileCall (a) [0.2ms]\n-ProfileCall (b) [0.2ms]\n -ProfileCall (c) [0.2ms]\n -ProfileCall (d) [0.1ms]`);\n });\n });\n });\n describe('walking trees', () => {\n it('walkEntireTree walks the entire tree and visits all the roots as well as all children', async () => {\n /**\n * |------------- Task A -------------||-- Task E --|\n * |-- Task B --||-- Task D --|\n * |- Task C -|\n */\n const data = [\n makeCompleteEvent('A', 0, 10), // 0..10\n makeCompleteEvent('B', 1, 3), // 1..4\n makeCompleteEvent('D', 5, 3), // 5..8\n makeCompleteEvent('C', 2, 1), // 2..3\n makeCompleteEvent('E', 11, 3), // 11..14\n ];\n TraceModel.Helpers.Trace.sortTraceEventsInPlace(data);\n const {tree, entryToNode} = TraceModel.Helpers.TreeHelpers.treify(data, {filter: {has: () => true}});\n\n const callOrder: Array<{type: 'START' | 'END', entryName: string}> = [];\n function onEntryStart(entry: TraceModel.Types.TraceEvents.TraceEventData): void {\n callOrder.push({type: 'START', entryName: entry.name});\n }\n function onEntryEnd(entry: TraceModel.Types.TraceEvents.TraceEventData): void {\n callOrder.push({type: 'END', entryName: entry.name});\n }\n TraceModel.Helpers.TreeHelpers.walkEntireTree(entryToNode, tree, onEntryStart, onEntryEnd);\n assert.deepEqual(callOrder, [\n {type: 'START', entryName: 'A'},\n {type: 'START', entryName: 'B'},\n {type: 'START', entryName: 'C'},\n {type: 'END', entryName: 'C'},\n {type: 'END', entryName: 'B'},\n {type: 'START', entryName: 'D'},\n {type: 'END', entryName: 'D'},\n {type: 'END', entryName: 'A'},\n {type: 'START', entryName: 'E'},\n {type: 'END', entryName: 'E'},\n ]);\n });\n\n it('walkEntireTree can take a trace window and will only run for events in that window', async () => {\n /**\n * | min: 5 - max 10| <<<< custom trace window\n * |------------- Task A -------------||-- Task E --|\n * |-- Task B --||-- Task D --|\n * |- Task C -|\n */\n const data = [\n makeCompleteEvent('A', 0, 10), // 0..10\n makeCompleteEvent('B', 1, 3), // 1..4\n makeCompleteEvent('D', 5, 3), // 5..8\n makeCompleteEvent('C', 2, 1), // 2..3\n makeCompleteEvent('E', 11, 3), // 11..14\n ];\n TraceModel.Helpers.Trace.sortTraceEventsInPlace(data);\n const {tree, entryToNode} = TraceModel.Helpers.TreeHelpers.treify(data, {filter: {has: () => true}});\n\n const callOrder: Array<{type: 'START' | 'END', entryName: string}> = [];\n function onEntryStart(entry: TraceModel.Types.TraceEvents.TraceEventData): void {\n callOrder.push({type: 'START', entryName: entry.name});\n }\n function onEntryEnd(entry: TraceModel.Types.TraceEvents.TraceEventData): void {\n callOrder.push({type: 'END', entryName: entry.name});\n }\n TraceModel.Helpers.TreeHelpers.walkEntireTree(entryToNode, tree, onEntryStart, onEntryEnd, {\n min: TraceModel.Types.Timing.MicroSeconds(5),\n max: TraceModel.Types.Timing.MicroSeconds(10),\n range: TraceModel.Types.Timing.MicroSeconds(5),\n });\n\n assert.deepEqual(callOrder, [\n {type: 'START', entryName: 'A'},\n {type: 'START', entryName: 'D'},\n {type: 'END', entryName: 'D'},\n {type: 'END', entryName: 'A'},\n ]);\n });\n\n it('walkTreeFromEntry walks the tree down and then back up and calls onEntryStart and onEntryEnd', async () => {\n /**\n * |------------- Task A -------------||-- Task E --|\n * |-- Task B --||-- Task D --|\n * |- Task C -|\n */\n const data = [\n makeCompleteEvent('A', 0, 10), // 0..10\n makeCompleteEvent('B', 1, 3), // 1..4\n makeCompleteEvent('D', 5, 3), // 5..8\n makeCompleteEvent('C', 2, 1), // 2..3\n makeCompleteEvent('E', 11, 3), // 11..14\n ];\n TraceModel.Helpers.Trace.sortTraceEventsInPlace(data);\n const {tree, entryToNode} = TraceModel.Helpers.TreeHelpers.treify(data, {filter: {has: () => true}});\n\n const callOrder: Array<{type: 'START' | 'END', entryName: string}> = [];\n function onEntryStart(entry: TraceModel.Types.TraceEvents.TraceEventData): void {\n callOrder.push({type: 'START', entryName: entry.name});\n }\n function onEntryEnd(entry: TraceModel.Types.TraceEvents.TraceEventData): void {\n callOrder.push({type: 'END', entryName: entry.name});\n }\n const rootNode = Array.from(tree.roots).at(0);\n if (!rootNode) {\n throw new Error('Could not find root node');\n }\n assert.strictEqual(rootNode.entry.name, 'A');\n TraceModel.Helpers.TreeHelpers.walkTreeFromEntry(entryToNode, rootNode.entry, onEntryStart, onEntryEnd);\n assert.deepEqual(callOrder, [\n {type: 'START', entryName: 'A'},\n {type: 'START', entryName: 'B'},\n {type: 'START', entryName: 'C'},\n {type: 'END', entryName: 'C'},\n {type: 'END', entryName: 'B'},\n {type: 'START', entryName: 'D'},\n {type: 'END', entryName: 'D'},\n {type: 'END', entryName: 'A'},\n ]);\n });\n });\n describe('canBuildTreesFromEvents', () => {\n it('returns true if no pair of events (e1, e2) exists such that e1 overlaps with e2 without one fully containing the other',\n () => {\n const data = [\n makeCompleteEvent('a', 0, 100),\n makeCompleteEvent('b', 0, 50),\n makeCompleteEvent('c', 0, 25),\n makeCompleteEvent('d', 26, 24),\n makeCompleteEvent('e', 51, 49),\n makeCompleteEvent('f', 51, 24),\n makeCompleteEvent('g', 76, 24),\n ];\n assert.isTrue(TraceModel.Helpers.TreeHelpers.canBuildTreesFromEvents(data));\n });\n it('returns false if a pair of events (e1, e2) exists such that e1 overlaps with e2 without one fully containing the other',\n () => {\n const data = [\n makeCompleteEvent('a', 0, 100),\n makeCompleteEvent('b', 0, 50),\n makeCompleteEvent('c', 0, 25),\n // d overlaps with b but isn't fully contained by it.\n makeCompleteEvent('d', 26, 50),\n makeCompleteEvent('e', 51, 49),\n makeCompleteEvent('f', 51, 24),\n makeCompleteEvent('g', 76, 24),\n ];\n assert.isFalse(TraceModel.Helpers.TreeHelpers.canBuildTreesFromEvents(data));\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"TreeHelpers.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/helpers/TreeHelpers.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {\n getEventsIn,\n makeCompleteEvent,\n makeProfileCall,\n prettyPrint,\n} from '../../../testing/TraceHelpers.js';\nimport * as Trace from '../trace.js';\n\ndescribe('TreeHelpers', () => {\n describe('treify', () => {\n it('can build a hierarchy of events without filters', async () => {\n /**\n * |------------- Task A -------------||-- Task E --|\n * |-- Task B --||-- Task D --|\n * |- Task C -|\n */\n const data = [\n makeCompleteEvent('A', 0, 10), // 0..10\n makeCompleteEvent('B', 1, 3), // 1..4\n makeCompleteEvent('D', 5, 3), // 5..8\n makeCompleteEvent('C', 2, 1), // 2..3\n makeCompleteEvent('E', 11, 3), // 11..14\n ];\n\n Trace.Helpers.Trace.sortTraceEventsInPlace(data);\n const {tree} = Trace.Helpers.TreeHelpers.treify(data, {filter: {has: () => true}});\n\n assert.strictEqual(tree.maxDepth, 3, 'Got the correct tree max depth');\n\n const rootsEvents = [...tree.roots].map(n => n ? n.entry : null);\n assert.deepEqual(rootsEvents.map(e => e ? {name: e.name, ts: e.ts, dur: e.dur} : null) as unknown[], [\n {name: 'A', ts: 0, dur: 10},\n {name: 'E', ts: 11, dur: 3},\n ]);\n\n const nodeA = [...tree.roots].at(0);\n const nodeE = [...tree.roots].at(1);\n if (!nodeA || !nodeE) {\n assert(false, 'Root nodes were not found');\n return;\n }\n\n const childrenOfA = getEventsIn(nodeA.children.values());\n assert.deepEqual(childrenOfA.map(e => e ? {name: e.name, ts: e.ts, dur: e.dur} : null) as unknown[], [\n {name: 'B', ts: 1, dur: 3},\n {name: 'D', ts: 5, dur: 3},\n ]);\n\n const childrenOfE = getEventsIn(nodeE.children.values());\n assert.deepEqual(childrenOfE, []);\n\n const nodeB = [...nodeA.children].at(0);\n const nodeD = [...nodeA.children].at(1);\n if (!nodeB || !nodeD) {\n assert(false, 'Child nodes were not found');\n return;\n }\n\n const childrenOfB = getEventsIn(nodeB.children.values());\n assert.deepEqual(childrenOfB.map(e => e ? {name: e.name, ts: e.ts, dur: e.dur} : null) as unknown[], [\n {name: 'C', ts: 2, dur: 1},\n ]);\n\n const childrenOfD = getEventsIn(nodeD.children.values());\n assert.deepEqual(childrenOfD, []);\n\n const nodeC = [...nodeB.children].at(0);\n if (!nodeC) {\n assert(false, 'Child nodes were not found');\n return;\n }\n\n const childrenOfC = getEventsIn(nodeC.children.values());\n assert.deepEqual(childrenOfC, []);\n });\n\n it('can build a hierarchy of events with filters', async () => {\n /**\n * |------------- Task A -------------||-- ?????? --|\n * |-- ?????? --||-- Task D --|\n * |- ?????? -|\n */\n const data = [\n makeCompleteEvent('A', 0, 10), // 0..10\n makeCompleteEvent('B', 1, 3), // 1..4\n makeCompleteEvent('D', 5, 3), // 5..8\n makeCompleteEvent('C', 2, 1), // 2..3\n makeCompleteEvent('E', 11, 3), // 11..14\n ];\n\n Trace.Helpers.Trace.sortTraceEventsInPlace(data);\n const filter = new Set(['A', 'D']);\n const {tree} = Trace.Helpers.TreeHelpers.treify(data, {filter});\n\n assert.strictEqual(tree.maxDepth, 2, 'Got the correct tree max depth');\n\n const rootsEvents = [...tree.roots].map(n => n.entry);\n assert.deepEqual(rootsEvents.map(e => e ? {name: e.name, ts: e.ts, dur: e.dur} : null) as unknown[], [\n {name: 'A', ts: 0, dur: 10},\n ]);\n\n const nodeA = [...tree.roots].at(0);\n if (!nodeA) {\n assert(false, 'Root nodes were not found');\n return;\n }\n\n const childrenOfA = getEventsIn(nodeA.children.values());\n assert.deepEqual(childrenOfA.map(e => e ? {name: e.name, ts: e.ts, dur: e.dur} : null) as unknown[], [\n {name: 'D', ts: 5, dur: 3},\n ]);\n\n const nodeD = [...nodeA.children].at(0);\n if (!nodeD) {\n assert(false, 'Child nodes were not found');\n return;\n }\n\n const childrenOfD = getEventsIn(nodeD.children.values());\n assert.deepEqual(childrenOfD, []);\n });\n\n it('can build a hierarchy of events that start and end close to each other', async () => {\n /**\n * |------------- Task A -------------||-- Task E --|\n * |-- Task B --||-- Task D --|\n * |- Task C -|\n */\n const data = [\n makeCompleteEvent('A', 0, 10), // 0..10\n makeCompleteEvent('B', 0, 3), // 0..3 (starts same time as A)\n makeCompleteEvent('D', 3, 3), // 3..6 (starts when B finishes)\n makeCompleteEvent('C', 2, 1), // 2..3 (finishes when B finishes)\n makeCompleteEvent('E', 10, 3), // 10..13 (starts when A finishes)\n ];\n\n Trace.Helpers.Trace.sortTraceEventsInPlace(data);\n const {tree} = Trace.Helpers.TreeHelpers.treify(data, {filter: {has: () => true}});\n\n assert.strictEqual(tree.maxDepth, 3, 'Got the correct tree max depth');\n\n const rootsEvents = [...tree.roots].map(n => n.entry);\n assert.deepEqual(rootsEvents.map(e => e ? {name: e.name, ts: e.ts, dur: e.dur} : null) as unknown[], [\n {name: 'A', ts: 0, dur: 10},\n {name: 'E', ts: 10, dur: 3},\n ]);\n\n const nodeA = [...tree.roots].at(0);\n const nodeE = [...tree.roots].at(1);\n if (!nodeA || !nodeE) {\n assert(false, 'Root nodes were not found');\n return;\n }\n\n const childrenOfA = getEventsIn(nodeA.children.values());\n assert.deepEqual(childrenOfA.map(e => e ? {name: e.name, ts: e.ts, dur: e.dur} : null) as unknown[], [\n {name: 'B', ts: 0, dur: 3},\n {name: 'D', ts: 3, dur: 3},\n ]);\n\n const childrenOfE = getEventsIn(nodeE.children.values());\n assert.deepEqual(childrenOfE, []);\n\n const nodeB = [...nodeA.children].at(0);\n const nodeD = [...nodeA.children].at(1);\n if (!nodeB || !nodeD) {\n assert(false, 'Child nodes were not found');\n return;\n }\n\n const childrenOfB = getEventsIn(nodeB.children.values());\n assert.deepEqual(childrenOfB.map(e => e ? {name: e.name, ts: e.ts, dur: e.dur} : null) as unknown[], [\n {name: 'C', ts: 2, dur: 1},\n ]);\n\n const childrenOfD = getEventsIn(nodeD.children.values());\n assert.deepEqual(childrenOfD, []);\n\n const nodeC = [...nodeB.children].at(0);\n if (!nodeC) {\n assert(false, 'Child nodes were not found');\n return;\n }\n\n const childrenOfC = getEventsIn(nodeC.children.values());\n assert.deepEqual(childrenOfC, []);\n });\n\n it('correctly calculates the total and self times of a hierarchy of events', async () => {\n /**\n * |------------- Task A -------------||-- Task E --|\n * |-- Task B --||-- Task D --|\n * |- Task C -|\n */\n const data = [\n makeCompleteEvent('A', 0, 10), // 0..10\n makeCompleteEvent('B', 0, 3), // 0..3 (starts same time as A)\n makeCompleteEvent('D', 3, 3), // 3..6 (starts when B finishes)\n makeCompleteEvent('C', 2, 1), // 2..3 (finishes when B finishes)\n makeCompleteEvent('E', 10, 3), // 10..13 (starts when A finishes)\n ] as Trace.Types.Events.Event[];\n\n Trace.Helpers.Trace.sortTraceEventsInPlace(data);\n const {tree} = Trace.Helpers.TreeHelpers.treify(data, {filter: {has: () => true}});\n\n const nodeA = [...tree.roots].at(0);\n const nodeE = [...tree.roots].at(1);\n if (!nodeA || !nodeE) {\n assert(false, 'Root nodes were not found');\n return;\n }\n const taskA = nodeA.entry;\n const taskE = nodeE.entry;\n const nodeD = [...nodeA.children].at(1);\n const nodeB = [...nodeA.children].at(0);\n if (!nodeB || !nodeD) {\n assert(false, 'Child nodes were not found');\n return;\n }\n const taskD = nodeD.entry;\n const taskB = nodeB.entry;\n\n const nodeC = [...nodeB.children].at(0);\n\n if (!nodeC) {\n assert(false, 'Child nodes were not found');\n return;\n }\n const taskC = nodeC.entry;\n\n const taskCTotalTime = taskC.dur;\n if (taskCTotalTime === undefined) {\n assert.fail('Total time for task was not found');\n return;\n }\n assert.strictEqual(taskCTotalTime, Trace.Types.Timing.MicroSeconds(1));\n assert.strictEqual(nodeC.selfTime, taskCTotalTime);\n\n const taskBTotalTime = taskB.dur;\n if (taskBTotalTime === undefined) {\n assert.fail('Total time for task was not found');\n return;\n }\n assert.strictEqual(taskBTotalTime, Trace.Types.Timing.MicroSeconds(3));\n assert.strictEqual(nodeB.selfTime, Trace.Types.Timing.MicroSeconds(taskBTotalTime - taskCTotalTime));\n\n const taskDTotalTime = taskD.dur;\n if (taskDTotalTime === undefined) {\n assert.fail('Total time for task was not found');\n return;\n }\n assert.strictEqual(taskDTotalTime, Trace.Types.Timing.MicroSeconds(3));\n assert.strictEqual(nodeD.selfTime, taskDTotalTime);\n\n const taskATotalTime = taskA.dur;\n if (taskATotalTime === undefined) {\n assert.fail('Total time for task was not found');\n return;\n }\n assert.strictEqual(taskATotalTime, Trace.Types.Timing.MicroSeconds(10));\n assert.strictEqual(\n nodeA.selfTime, Trace.Types.Timing.MicroSeconds(taskATotalTime - taskBTotalTime - taskDTotalTime));\n\n const taskETotalTime = taskE.dur;\n if (taskETotalTime === undefined) {\n assert.fail('Total time for task was not found');\n return;\n }\n assert.strictEqual(taskETotalTime, Trace.Types.Timing.MicroSeconds(3));\n assert.strictEqual(nodeD.selfTime, taskETotalTime);\n });\n describe('building hierarchies trace events and profile calls', () => {\n it('builds a hierarchy from trace events and profile calls', async () => {\n const evaluateScript = makeCompleteEvent(Trace.Types.Events.Name.EVALUATE_SCRIPT, 0, 500);\n const v8Run = makeCompleteEvent('v8.run', 10, 490);\n const parseFunction = makeCompleteEvent('V8.ParseFunction', 12, 1);\n\n const traceEvents: Trace.Types.Events.Event[] = [evaluateScript, v8Run, parseFunction];\n\n const profileCalls = [makeProfileCall('a', 100, 200), makeProfileCall('b', 300, 200)];\n const allEntries = Trace.Helpers.Trace.mergeEventsInOrder(traceEvents, profileCalls);\n const {tree} = Trace.Helpers.TreeHelpers.treify(allEntries, {filter: {has: () => true}});\n assert.strictEqual(prettyPrint(tree), `\n-EvaluateScript [0.5ms]\n -v8.run [0.49ms]\n -V8.ParseFunction [0.001ms]\n -ProfileCall (a) [0.2ms]\n -ProfileCall (b) [0.2ms]`);\n });\n\n it('builds a hierarchy from only profile calls', async () => {\n const allEntries = [\n makeProfileCall('a', 100, 200),\n makeProfileCall('b', 300, 200),\n makeProfileCall('c', 300, 200),\n makeProfileCall('d', 400, 100),\n ];\n const {tree} = Trace.Helpers.TreeHelpers.treify(allEntries, {filter: {has: () => true}});\n assert.strictEqual(prettyPrint(tree), `\n-ProfileCall (a) [0.2ms]\n-ProfileCall (b) [0.2ms]\n -ProfileCall (c) [0.2ms]\n -ProfileCall (d) [0.1ms]`);\n });\n });\n });\n describe('walking trees', () => {\n it('walkEntireTree walks the entire tree and visits all the roots as well as all children', async () => {\n /**\n * |------------- Task A -------------||-- Task E --|\n * |-- Task B --||-- Task D --|\n * |- Task C -|\n */\n const data = [\n makeCompleteEvent('A', 0, 10), // 0..10\n makeCompleteEvent('B', 1, 3), // 1..4\n makeCompleteEvent('D', 5, 3), // 5..8\n makeCompleteEvent('C', 2, 1), // 2..3\n makeCompleteEvent('E', 11, 3), // 11..14\n ];\n Trace.Helpers.Trace.sortTraceEventsInPlace(data);\n const {tree, entryToNode} = Trace.Helpers.TreeHelpers.treify(data, {filter: {has: () => true}});\n\n const callOrder: Array<{type: 'START' | 'END', entryName: string}> = [];\n function onEntryStart(entry: Trace.Types.Events.Event): void {\n callOrder.push({type: 'START', entryName: entry.name});\n }\n function onEntryEnd(entry: Trace.Types.Events.Event): void {\n callOrder.push({type: 'END', entryName: entry.name});\n }\n Trace.Helpers.TreeHelpers.walkEntireTree(entryToNode, tree, onEntryStart, onEntryEnd);\n assert.deepEqual(callOrder, [\n {type: 'START', entryName: 'A'},\n {type: 'START', entryName: 'B'},\n {type: 'START', entryName: 'C'},\n {type: 'END', entryName: 'C'},\n {type: 'END', entryName: 'B'},\n {type: 'START', entryName: 'D'},\n {type: 'END', entryName: 'D'},\n {type: 'END', entryName: 'A'},\n {type: 'START', entryName: 'E'},\n {type: 'END', entryName: 'E'},\n ]);\n });\n\n it('walkEntireTree can take a trace window and will only run for events in that window', async () => {\n /**\n * | min: 5 - max 10| <<<< custom trace window\n * |------------- Task A -------------||-- Task E --|\n * |-- Task B --||-- Task D --|\n * |- Task C -|\n */\n const data = [\n makeCompleteEvent('A', 0, 10), // 0..10\n makeCompleteEvent('B', 1, 3), // 1..4\n makeCompleteEvent('D', 5, 3), // 5..8\n makeCompleteEvent('C', 2, 1), // 2..3\n makeCompleteEvent('E', 11, 3), // 11..14\n ];\n Trace.Helpers.Trace.sortTraceEventsInPlace(data);\n const {tree, entryToNode} = Trace.Helpers.TreeHelpers.treify(data, {filter: {has: () => true}});\n\n const callOrder: Array<{type: 'START' | 'END', entryName: string}> = [];\n function onEntryStart(entry: Trace.Types.Events.Event): void {\n callOrder.push({type: 'START', entryName: entry.name});\n }\n function onEntryEnd(entry: Trace.Types.Events.Event): void {\n callOrder.push({type: 'END', entryName: entry.name});\n }\n Trace.Helpers.TreeHelpers.walkEntireTree(entryToNode, tree, onEntryStart, onEntryEnd, {\n min: Trace.Types.Timing.MicroSeconds(5),\n max: Trace.Types.Timing.MicroSeconds(10),\n range: Trace.Types.Timing.MicroSeconds(5),\n });\n\n assert.deepEqual(callOrder, [\n {type: 'START', entryName: 'A'},\n {type: 'START', entryName: 'D'},\n {type: 'END', entryName: 'D'},\n {type: 'END', entryName: 'A'},\n ]);\n });\n\n it('walkTreeFromEntry walks the tree down and then back up and calls onEntryStart and onEntryEnd', async () => {\n /**\n * |------------- Task A -------------||-- Task E --|\n * |-- Task B --||-- Task D --|\n * |- Task C -|\n */\n const data = [\n makeCompleteEvent('A', 0, 10), // 0..10\n makeCompleteEvent('B', 1, 3), // 1..4\n makeCompleteEvent('D', 5, 3), // 5..8\n makeCompleteEvent('C', 2, 1), // 2..3\n makeCompleteEvent('E', 11, 3), // 11..14\n ];\n Trace.Helpers.Trace.sortTraceEventsInPlace(data);\n const {tree, entryToNode} = Trace.Helpers.TreeHelpers.treify(data, {filter: {has: () => true}});\n\n const callOrder: Array<{type: 'START' | 'END', entryName: string}> = [];\n function onEntryStart(entry: Trace.Types.Events.Event): void {\n callOrder.push({type: 'START', entryName: entry.name});\n }\n function onEntryEnd(entry: Trace.Types.Events.Event): void {\n callOrder.push({type: 'END', entryName: entry.name});\n }\n const rootNode = Array.from(tree.roots).at(0);\n if (!rootNode) {\n throw new Error('Could not find root node');\n }\n assert.strictEqual(rootNode.entry.name, 'A');\n Trace.Helpers.TreeHelpers.walkTreeFromEntry(entryToNode, rootNode.entry, onEntryStart, onEntryEnd);\n assert.deepEqual(callOrder, [\n {type: 'START', entryName: 'A'},\n {type: 'START', entryName: 'B'},\n {type: 'START', entryName: 'C'},\n {type: 'END', entryName: 'C'},\n {type: 'END', entryName: 'B'},\n {type: 'START', entryName: 'D'},\n {type: 'END', entryName: 'D'},\n {type: 'END', entryName: 'A'},\n ]);\n });\n });\n describe('canBuildTreesFromEvents', () => {\n it('returns true if no pair of events (e1, e2) exists such that e1 overlaps with e2 without one fully containing the other',\n () => {\n const data = [\n makeCompleteEvent('a', 0, 100),\n makeCompleteEvent('b', 0, 50),\n makeCompleteEvent('c', 0, 25),\n makeCompleteEvent('d', 26, 24),\n makeCompleteEvent('e', 51, 49),\n makeCompleteEvent('f', 51, 24),\n makeCompleteEvent('g', 76, 24),\n ];\n assert.isTrue(Trace.Helpers.TreeHelpers.canBuildTreesFromEvents(data));\n });\n it('returns false if a pair of events (e1, e2) exists such that e1 overlaps with e2 without one fully containing the other',\n () => {\n const data = [\n makeCompleteEvent('a', 0, 100),\n makeCompleteEvent('b', 0, 50),\n makeCompleteEvent('c', 0, 25),\n // d overlaps with b but isn't fully contained by it.\n makeCompleteEvent('d', 26, 50),\n makeCompleteEvent('e', 51, 49),\n makeCompleteEvent('f', 51, 24),\n makeCompleteEvent('g', 76, 24),\n ];\n assert.isFalse(Trace.Helpers.TreeHelpers.canBuildTreesFromEvents(data));\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/Common.d.ts b/public/models/trace/insights/Common.d.ts index c9eefdc29..601361168 100644 --- a/public/models/trace/insights/Common.d.ts +++ b/public/models/trace/insights/Common.d.ts @@ -1,9 +1,9 @@ import type * as Handlers from '../handlers/handlers.js'; import type * as Types from '../types/types.js'; -import { type NavigationInsightContext } from './types.js'; +import { type InsightSetContextWithNavigation } from './types.js'; /** * Finds a network request given a navigation context and URL. * Considers redirects. */ -export declare function findRequest(traceData: Pick, context: NavigationInsightContext, url: string): Types.TraceEvents.SyntheticNetworkRequest | null; -export declare function findLCPRequest(traceData: Pick, context: NavigationInsightContext, lcpEvent: Types.TraceEvents.TraceEventLargestContentfulPaintCandidate): Types.TraceEvents.SyntheticNetworkRequest | null; +export declare function findRequest(parsedTrace: Pick, context: InsightSetContextWithNavigation, url: string): Types.Events.SyntheticNetworkRequest | null; +export declare function findLCPRequest(parsedTrace: Pick, context: InsightSetContextWithNavigation, lcpEvent: Types.Events.LargestContentfulPaintCandidate): Types.Events.SyntheticNetworkRequest | null; diff --git a/public/models/trace/insights/Common.js b/public/models/trace/insights/Common.js index af23b02ab..e64244c8f 100644 --- a/public/models/trace/insights/Common.js +++ b/public/models/trace/insights/Common.js @@ -6,23 +6,23 @@ import * as Helpers from '../helpers/helpers.js'; * Finds a network request given a navigation context and URL. * Considers redirects. */ -export function findRequest(traceData, context, url) { - const request = traceData.NetworkRequests.byTime.find(req => { +export function findRequest(parsedTrace, context, url) { + const request = parsedTrace.NetworkRequests.byTime.find(req => { const urlMatch = req.args.data.url === url || req.args.data.redirects.some(r => r.url === url); if (!urlMatch) { return false; } - const nav = Helpers.Trace.getNavigationForTraceEvent(req, context.frameId, traceData.Meta.navigationsByFrameId); + const nav = Helpers.Trace.getNavigationForTraceEvent(req, context.frameId, parsedTrace.Meta.navigationsByFrameId); return nav === context.navigation; }); return request ?? null; } -export function findLCPRequest(traceData, context, lcpEvent) { +export function findLCPRequest(parsedTrace, context, lcpEvent) { const lcpNodeId = lcpEvent.args.data?.nodeId; if (!lcpNodeId) { throw new Error('no lcp node id'); } - const imagePaint = traceData.LargestImagePaint.get(lcpNodeId); + const imagePaint = parsedTrace.LargestImagePaint.get(lcpNodeId); if (!imagePaint) { return null; } @@ -30,7 +30,7 @@ export function findLCPRequest(traceData, context, lcpEvent) { if (!lcpUrl) { throw new Error('no lcp url'); } - const lcpRequest = findRequest(traceData, context, lcpUrl); + const lcpRequest = findRequest(parsedTrace, context, lcpUrl); if (!lcpRequest) { throw new Error('no lcp request found'); } diff --git a/public/models/trace/insights/Common.js.map b/public/models/trace/insights/Common.js.map index 5212ccf1f..9be12e3bd 100644 --- a/public/models/trace/insights/Common.js.map +++ b/public/models/trace/insights/Common.js.map @@ -1 +1 @@ -{"version":3,"file":"Common.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/Common.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAG7B,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AAKjD;;;GAGG;AACH,MAAM,UAAU,WAAW,CACvB,SAAwE,EAAE,OAAiC,EAC3G,GAAW;IACb,MAAM,OAAO,GAAG,SAAS,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QAC1D,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;QAC/F,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAChH,OAAO,GAAG,KAAK,OAAO,CAAC,UAAU,CAAC;IACpC,CAAC,CAAC,CAAC;IACH,OAAO,OAAO,IAAI,IAAI,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,cAAc,CAC1B,SAA4F,EAC5F,OAAiC,EAAE,QAAqE;IAE1G,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC;IAC7C,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;IACpC,CAAC;IAED,MAAM,UAAU,GAAG,SAAS,CAAC,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAC9D,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC;IAC9C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC;IAChC,CAAC;IACD,MAAM,UAAU,GAAG,WAAW,CAAC,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAE3D,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC1C,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport type * as Types from '../types/types.js';\n\nimport {type NavigationInsightContext} from './types.js';\n\n/**\n * Finds a network request given a navigation context and URL.\n * Considers redirects.\n */\nexport function findRequest(\n traceData: Pick, context: NavigationInsightContext,\n url: string): Types.TraceEvents.SyntheticNetworkRequest|null {\n const request = traceData.NetworkRequests.byTime.find(req => {\n const urlMatch = req.args.data.url === url || req.args.data.redirects.some(r => r.url === url);\n if (!urlMatch) {\n return false;\n }\n\n const nav = Helpers.Trace.getNavigationForTraceEvent(req, context.frameId, traceData.Meta.navigationsByFrameId);\n return nav === context.navigation;\n });\n return request ?? null;\n}\n\nexport function findLCPRequest(\n traceData: Pick,\n context: NavigationInsightContext, lcpEvent: Types.TraceEvents.TraceEventLargestContentfulPaintCandidate):\n Types.TraceEvents.SyntheticNetworkRequest|null {\n const lcpNodeId = lcpEvent.args.data?.nodeId;\n if (!lcpNodeId) {\n throw new Error('no lcp node id');\n }\n\n const imagePaint = traceData.LargestImagePaint.get(lcpNodeId);\n if (!imagePaint) {\n return null;\n }\n\n const lcpUrl = imagePaint.args.data?.imageUrl;\n if (!lcpUrl) {\n throw new Error('no lcp url');\n }\n const lcpRequest = findRequest(traceData, context, lcpUrl);\n\n if (!lcpRequest) {\n throw new Error('no lcp request found');\n }\n\n return lcpRequest;\n}\n"]} \ No newline at end of file +{"version":3,"file":"Common.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/Common.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAG7B,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AAKjD;;;GAGG;AACH,MAAM,UAAU,WAAW,CACvB,WAAuE,EAAE,OAAwC,EACjH,GAAW;IACb,MAAM,OAAO,GAAG,WAAW,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QAC5D,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;QAC/F,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAClH,OAAO,GAAG,KAAK,OAAO,CAAC,UAAU,CAAC;IACpC,CAAC,CAAC,CAAC;IACH,OAAO,OAAO,IAAI,IAAI,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,cAAc,CAC1B,WAA2F,EAC3F,OAAwC,EACxC,QAAsD;IACxD,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC;IAC7C,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;IACpC,CAAC;IAED,MAAM,UAAU,GAAG,WAAW,CAAC,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAChE,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC;IAC9C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,CAAC;IAChC,CAAC;IACD,MAAM,UAAU,GAAG,WAAW,CAAC,WAAW,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAE7D,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;IAC1C,CAAC;IAED,OAAO,UAAU,CAAC;AACpB,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport type * as Types from '../types/types.js';\n\nimport {type InsightSetContextWithNavigation} from './types.js';\n\n/**\n * Finds a network request given a navigation context and URL.\n * Considers redirects.\n */\nexport function findRequest(\n parsedTrace: Pick, context: InsightSetContextWithNavigation,\n url: string): Types.Events.SyntheticNetworkRequest|null {\n const request = parsedTrace.NetworkRequests.byTime.find(req => {\n const urlMatch = req.args.data.url === url || req.args.data.redirects.some(r => r.url === url);\n if (!urlMatch) {\n return false;\n }\n\n const nav = Helpers.Trace.getNavigationForTraceEvent(req, context.frameId, parsedTrace.Meta.navigationsByFrameId);\n return nav === context.navigation;\n });\n return request ?? null;\n}\n\nexport function findLCPRequest(\n parsedTrace: Pick,\n context: InsightSetContextWithNavigation,\n lcpEvent: Types.Events.LargestContentfulPaintCandidate): Types.Events.SyntheticNetworkRequest|null {\n const lcpNodeId = lcpEvent.args.data?.nodeId;\n if (!lcpNodeId) {\n throw new Error('no lcp node id');\n }\n\n const imagePaint = parsedTrace.LargestImagePaint.get(lcpNodeId);\n if (!imagePaint) {\n return null;\n }\n\n const lcpUrl = imagePaint.args.data?.imageUrl;\n if (!lcpUrl) {\n throw new Error('no lcp url');\n }\n const lcpRequest = findRequest(parsedTrace, context, lcpUrl);\n\n if (!lcpRequest) {\n throw new Error('no lcp request found');\n }\n\n return lcpRequest;\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/CumulativeLayoutShift.d.ts b/public/models/trace/insights/CumulativeLayoutShift.d.ts index 7ac15a80d..0ce13542f 100644 --- a/public/models/trace/insights/CumulativeLayoutShift.d.ts +++ b/public/models/trace/insights/CumulativeLayoutShift.d.ts @@ -1,9 +1,9 @@ import * as Types from '../types/types.js'; -import { type InsightResult, type NavigationInsightContext, type RequiredData } from './types.js'; +import { type InsightResult, type InsightSetContext, type RequiredData } from './types.js'; export type CLSInsightResult = InsightResult<{ animationFailures?: readonly NoncompositedAnimationFailure[]; - shifts?: Map; - clusters: Types.TraceEvents.SyntheticLayoutShiftCluster[]; + shifts?: Map; + clusters: Types.Events.SyntheticLayoutShiftCluster[]; }>; export declare function deps(): ['Meta', 'Animations', 'LayoutShifts', 'NetworkRequests']; export declare const enum AnimationFailureReasons { @@ -27,10 +27,11 @@ export interface NoncompositedAnimationFailure { /** * Unsupported properties. */ - unsupportedProperties?: Types.TraceEvents.TraceEventAnimation['args']['data']['unsupportedProperties']; + unsupportedProperties?: Types.Events.Animation['args']['data']['unsupportedProperties']; } export interface LayoutShiftRootCausesData { iframeIds: string[]; - fontRequests: Types.TraceEvents.SyntheticNetworkRequest[]; + fontRequests: Types.Events.SyntheticNetworkRequest[]; } -export declare function generateInsight(traceParsedData: RequiredData, context: NavigationInsightContext): CLSInsightResult; +export declare function getNonCompositedFailure(event: Types.Events.SyntheticAnimationPair): NoncompositedAnimationFailure[]; +export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): CLSInsightResult; diff --git a/public/models/trace/insights/CumulativeLayoutShift.js b/public/models/trace/insights/CumulativeLayoutShift.js index 6166bd8e7..9e4a045b1 100644 --- a/public/models/trace/insights/CumulativeLayoutShift.js +++ b/public/models/trace/insights/CumulativeLayoutShift.js @@ -46,34 +46,27 @@ function isInInvalidationWindow(event, targetEvent) { const eventEnd = event.dur ? event.ts + event.dur : event.ts; return eventEnd < targetEvent.ts && eventEnd >= targetEvent.ts - INVALIDATION_WINDOW; } -/** - * Returns a list of NoncompositedAnimationFailures. - */ -function getNonCompositedAnimations(animations) { +export function getNonCompositedFailure(event) { const failures = []; - for (const event of animations) { - const beginEvent = event.args.data.beginEvent; - const instantEvents = event.args.data.instantEvents || []; - /** - * Animation events containing composite information are ASYNC_NESTABLE_INSTANT ('n'). - * An animation may also contain multiple 'n' events, so we look through those with useful non-composited data. - */ - for (const event of instantEvents) { - const failureMask = event.args.data.compositeFailed; - const unsupportedProperties = event.args.data.unsupportedProperties; - if (!failureMask || !unsupportedProperties) { - continue; - } - const failureReasons = ACTIONABLE_FAILURE_REASONS.filter(reason => failureMask & reason.flag).map(reason => { - return reason.failure; - }); - const failure = { - name: beginEvent.args.data.displayName, - failureReasons, - unsupportedProperties, - }; - failures.push(failure); + const beginEvent = event.args.data.beginEvent; + const instantEvents = event.args.data.instantEvents || []; + /** + * Animation events containing composite information are ASYNC_NESTABLE_INSTANT ('n'). + * An animation may also contain multiple 'n' events, so we look through those with useful non-composited data. + */ + for (const event of instantEvents) { + const failureMask = event.args.data.compositeFailed; + const unsupportedProperties = event.args.data.unsupportedProperties; + if (!failureMask || !unsupportedProperties) { + continue; } + const failureReasons = ACTIONABLE_FAILURE_REASONS.filter(reason => failureMask & reason.flag).map(reason => reason.failure); + const failure = { + name: beginEvent.args.data.displayName, + failureReasons, + unsupportedProperties, + }; + failures.push(failure); } return failures; } @@ -188,22 +181,28 @@ function getFontRootCauses(networkRequests, prePaintEvents, shiftsByPrePaint, ro } return rootCausesByShift; } -export function generateInsight(traceParsedData, context) { +export function generateInsight(parsedTrace, context) { + // TODO(crbug.com/366049346) make this work w/o a navigation. + if (!context.navigation) { + return { + clusters: [], + }; + } const isWithinSameNavigation = ((event) => { - const nav = Helpers.Trace.getNavigationForTraceEvent(event, context.frameId, traceParsedData.Meta.navigationsByFrameId); + const nav = Helpers.Trace.getNavigationForTraceEvent(event, context.frameId, parsedTrace.Meta.navigationsByFrameId); return nav === context.navigation; }); - const compositeAnimationEvents = traceParsedData.Animations.animations.filter(isWithinSameNavigation); - const animationFailures = getNonCompositedAnimations(compositeAnimationEvents); - const iframeEvents = traceParsedData.LayoutShifts.renderFrameImplCreateChildFrameEvents.filter(isWithinSameNavigation); - const networkRequests = traceParsedData.NetworkRequests.byTime.filter(isWithinSameNavigation); - const domLoadingEvents = traceParsedData.LayoutShifts.domLoadingEvents.filter(isWithinSameNavigation); + const compositeAnimationEvents = parsedTrace.Animations.animations.filter(isWithinSameNavigation); + const animationFailures = compositeAnimationEvents.map(getNonCompositedFailure).flat(); + const iframeEvents = parsedTrace.LayoutShifts.renderFrameImplCreateChildFrameEvents.filter(isWithinSameNavigation); + const networkRequests = parsedTrace.NetworkRequests.byTime.filter(isWithinSameNavigation); + const domLoadingEvents = parsedTrace.LayoutShifts.domLoadingEvents.filter(isWithinSameNavigation); // Sort by cumulative score, since for insights we interpret these for their "bad" scores. - const clusters = traceParsedData.LayoutShifts.clustersByNavigationId.get(context.navigationId) + const clusters = parsedTrace.LayoutShifts.clustersByNavigationId.get(context.navigationId) ?.sort((a, b) => b.clusterCumulativeScore - a.clusterCumulativeScore) ?? []; const layoutShifts = clusters.flatMap(cluster => cluster.events); - const prePaintEvents = traceParsedData.LayoutShifts.prePaintEvents.filter(isWithinSameNavigation); + const prePaintEvents = parsedTrace.LayoutShifts.prePaintEvents.filter(isWithinSameNavigation); // Get root causes. const rootCausesByShift = new Map(); const shiftsByPrePaint = getShiftsByPrePaintEvents(layoutShifts, prePaintEvents); diff --git a/public/models/trace/insights/CumulativeLayoutShift.js.map b/public/models/trace/insights/CumulativeLayoutShift.js.map index 03a0ac21e..b9cc3cccc 100644 --- a/public/models/trace/insights/CumulativeLayoutShift.js.map +++ b/public/models/trace/insights/CumulativeLayoutShift.js.map @@ -1 +1 @@ -{"version":3,"file":"CumulativeLayoutShift.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/CumulativeLayoutShift.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {\n type InsightResult,\n type NavigationInsightContext,\n type RequiredData,\n} from './types.js';\n\nexport type CLSInsightResult = InsightResult<{\n animationFailures?: readonly NoncompositedAnimationFailure[],\n shifts?: Map,\n clusters: Types.TraceEvents.SyntheticLayoutShiftCluster[],\n}>;\n\nexport function deps(): ['Meta', 'Animations', 'LayoutShifts', 'NetworkRequests'] {\n return ['Meta', 'Animations', 'LayoutShifts', 'NetworkRequests'];\n}\n\nexport const enum AnimationFailureReasons {\n UNSUPPORTED_CSS_PROPERTY = 'UNSUPPORTED_CSS_PROPERTY',\n TRANSFROM_BOX_SIZE_DEPENDENT = 'TRANSFROM_BOX_SIZE_DEPENDENT',\n FILTER_MAY_MOVE_PIXELS = 'FILTER_MAY_MOVE_PIXELS',\n NON_REPLACE_COMPOSITE_MODE = 'NON_REPLACE_COMPOSITE_MODE',\n INCOMPATIBLE_ANIMATIONS = 'INCOMPATIBLE_ANIMATIONS',\n UNSUPPORTED_TIMING_PARAMS = 'UNSUPPORTED_TIMING_PARAMS',\n}\n\nexport interface NoncompositedAnimationFailure {\n /**\n * Animation name.\n */\n name?: string;\n /**\n * Failure reason based on mask number defined in\n * https://source.chromium.org/search?q=f:compositor_animations.h%20%22enum%20FailureReason%22.\n */\n failureReasons: AnimationFailureReasons[];\n /**\n * Unsupported properties.\n */\n unsupportedProperties?: Types.TraceEvents.TraceEventAnimation['args']['data']['unsupportedProperties'];\n}\n\n/**\n * Each failure reason is represented by a bit flag. The bit shift operator '<<' is used to define\n * which bit corresponds to each failure reason.\n * https://source.chromium.org/search?q=f:compositor_animations.h%20%22enum%20FailureReason%22\n * @type {{flag: number, failure: AnimationFailureReasons}[]}\n */\nconst ACTIONABLE_FAILURE_REASONS = [\n {\n flag: 1 << 13,\n failure: AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY,\n },\n {\n flag: 1 << 11,\n failure: AnimationFailureReasons.TRANSFROM_BOX_SIZE_DEPENDENT,\n },\n {\n flag: 1 << 12,\n failure: AnimationFailureReasons.FILTER_MAY_MOVE_PIXELS,\n },\n {\n flag: 1 << 4,\n failure: AnimationFailureReasons.NON_REPLACE_COMPOSITE_MODE,\n },\n {\n flag: 1 << 6,\n failure: AnimationFailureReasons.INCOMPATIBLE_ANIMATIONS,\n },\n {\n flag: 1 << 3,\n failure: AnimationFailureReasons.UNSUPPORTED_TIMING_PARAMS,\n },\n];\n\n// 500ms window.\n// Use this window to consider events and requests that may have caused a layout shift.\nconst INVALIDATION_WINDOW = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(0.5));\n\nexport interface LayoutShiftRootCausesData {\n iframeIds: string[];\n fontRequests: Types.TraceEvents.SyntheticNetworkRequest[];\n}\n\nfunction isInInvalidationWindow(\n event: Types.TraceEvents.TraceEventData, targetEvent: Types.TraceEvents.TraceEventData): boolean {\n const eventEnd = event.dur ? event.ts + event.dur : event.ts;\n return eventEnd < targetEvent.ts && eventEnd >= targetEvent.ts - INVALIDATION_WINDOW;\n}\n\n/**\n * Returns a list of NoncompositedAnimationFailures.\n */\nfunction getNonCompositedAnimations(animations: readonly Types.TraceEvents.SyntheticAnimationPair[]):\n NoncompositedAnimationFailure[] {\n const failures: NoncompositedAnimationFailure[] = [];\n for (const event of animations) {\n const beginEvent = event.args.data.beginEvent;\n const instantEvents = event.args.data.instantEvents || [];\n /**\n * Animation events containing composite information are ASYNC_NESTABLE_INSTANT ('n').\n * An animation may also contain multiple 'n' events, so we look through those with useful non-composited data.\n */\n for (const event of instantEvents) {\n const failureMask = event.args.data.compositeFailed;\n const unsupportedProperties = event.args.data.unsupportedProperties;\n if (!failureMask || !unsupportedProperties) {\n continue;\n }\n const failureReasons = ACTIONABLE_FAILURE_REASONS.filter(reason => failureMask & reason.flag).map(reason => {\n return reason.failure;\n });\n const failure: NoncompositedAnimationFailure = {\n name: beginEvent.args.data.displayName,\n failureReasons,\n unsupportedProperties,\n };\n failures.push(failure);\n }\n }\n return failures;\n}\n\n/**\n * Given an array of layout shift and PrePaint events, returns a mapping from\n * PrePaint events to layout shifts dispatched within it.\n */\nfunction getShiftsByPrePaintEvents(\n layoutShifts: Types.TraceEvents.TraceEventLayoutShift[],\n prePaintEvents: Types.TraceEvents.TraceEventPrePaint[],\n ): Map {\n // Maps from PrePaint events to LayoutShifts that occured in each one.\n const shiftsByPrePaint = new Map();\n\n // Associate all shifts to their corresponding PrePaint.\n for (const prePaintEvent of prePaintEvents) {\n const firstShiftIndex =\n Platform.ArrayUtilities.nearestIndexFromBeginning(layoutShifts, shift => shift.ts >= prePaintEvent.ts);\n if (firstShiftIndex === null) {\n // No layout shifts registered after this PrePaint start. Continue.\n continue;\n }\n for (let i = firstShiftIndex; i < layoutShifts.length; i++) {\n const shift = layoutShifts[i];\n if (shift.ts >= prePaintEvent.ts && shift.ts <= prePaintEvent.ts + prePaintEvent.dur) {\n const shiftsInPrePaint = Platform.MapUtilities.getWithDefault(shiftsByPrePaint, prePaintEvent, () => []);\n shiftsInPrePaint.push(shift);\n }\n if (shift.ts > prePaintEvent.ts + prePaintEvent.dur) {\n // Reached all layoutShifts of this PrePaint. Break out to continue with the next prePaint event.\n break;\n }\n }\n }\n return shiftsByPrePaint;\n}\n\n/**\n * This gets the first prePaint event that follows the provided event and returns it.\n */\nfunction getNextPrePaintEvent(\n prePaintEvents: Types.TraceEvents.TraceEventPrePaint[],\n targetEvent: Types.TraceEvents.TraceEventData): Types.TraceEvents.TraceEventPrePaint|undefined {\n // Get the first PrePaint event that happened after the targetEvent.\n const nextPrePaintIndex = Platform.ArrayUtilities.nearestIndexFromBeginning(\n prePaintEvents, prePaint => prePaint.ts > targetEvent.ts + (targetEvent.dur || 0));\n // No PrePaint event registered after this event\n if (nextPrePaintIndex === null) {\n return undefined;\n }\n\n return prePaintEvents[nextPrePaintIndex];\n}\n\n/**\n * An Iframe is considered a root cause if the iframe event occurs before a prePaint event\n * and within this prePaint event a layout shift(s) occurs.\n */\nfunction getIframeRootCauses(\n iframeCreatedEvents: readonly Types.TraceEvents.TraceEventRenderFrameImplCreateChildFrame[],\n prePaintEvents: Types.TraceEvents.TraceEventPrePaint[],\n shiftsByPrePaint: Map,\n rootCausesByShift: Map,\n domLoadingEvents: readonly Types.TraceEvents.TraceEventDomLoading[]):\n Map {\n for (const iframeEvent of iframeCreatedEvents) {\n const nextPrePaint = getNextPrePaintEvent(prePaintEvents, iframeEvent);\n // If no following prePaint, this is not a root cause.\n if (!nextPrePaint) {\n continue;\n }\n const shifts = shiftsByPrePaint.get(nextPrePaint);\n // if no layout shift(s), this is not a root cause.\n if (!shifts) {\n continue;\n }\n for (const shift of shifts) {\n const rootCausesForShift = Platform.MapUtilities.getWithDefault(rootCausesByShift, shift, () => {\n return {\n iframeIds: [],\n fontRequests: [],\n };\n });\n\n // Look for the first dom event that occurs within the bounds of the iframe event.\n // This contains the frame id.\n const domEvent = domLoadingEvents.find(e => {\n const maxIframe = Types.Timing.MicroSeconds(iframeEvent.ts + (iframeEvent.dur ?? 0));\n return e.ts >= iframeEvent.ts && e.ts <= maxIframe;\n });\n if (domEvent && domEvent.args.frame) {\n rootCausesForShift.iframeIds.push(domEvent.args.frame);\n }\n }\n }\n return rootCausesByShift;\n}\n\n/**\n * A font request is considered a root cause if the request occurs before a prePaint event\n * and within this prePaint event a layout shift(s) occurs. Additionally, this font request should\n * happen within the INVALIDATION_WINDOW of the prePaint event.\n */\nfunction getFontRootCauses(\n networkRequests: Types.TraceEvents.SyntheticNetworkRequest[],\n prePaintEvents: Types.TraceEvents.TraceEventPrePaint[],\n shiftsByPrePaint: Map,\n rootCausesByShift: Map):\n Map {\n const fontRequests =\n networkRequests.filter(req => req.args.data.resourceType === 'Font' && req.args.data.mimeType.startsWith('font'));\n\n for (const req of fontRequests) {\n const nextPrePaint = getNextPrePaintEvent(prePaintEvents, req);\n if (!nextPrePaint) {\n continue;\n }\n\n // If the req is outside the INVALIDATION_WINDOW, it could not be a root cause.\n if (!isInInvalidationWindow(req, nextPrePaint)) {\n continue;\n }\n\n // Get the shifts that belong to this prepaint\n const shifts = shiftsByPrePaint.get(nextPrePaint);\n\n // if no layout shift(s) in this prePaint, the request is not a root cause.\n if (!shifts) {\n continue;\n }\n // Include the root cause to the shifts in this prePaint.\n for (const shift of shifts) {\n const rootCausesForShift = Platform.MapUtilities.getWithDefault(rootCausesByShift, shift, () => {\n return {\n iframeIds: [],\n fontRequests: [],\n };\n });\n rootCausesForShift.fontRequests.push(req);\n }\n }\n return rootCausesByShift;\n}\n\nexport function generateInsight(\n traceParsedData: RequiredData, context: NavigationInsightContext): CLSInsightResult {\n const isWithinSameNavigation = ((event: Types.TraceEvents.TraceEventData): boolean => {\n const nav =\n Helpers.Trace.getNavigationForTraceEvent(event, context.frameId, traceParsedData.Meta.navigationsByFrameId);\n return nav === context.navigation;\n });\n\n const compositeAnimationEvents = traceParsedData.Animations.animations.filter(isWithinSameNavigation);\n const animationFailures = getNonCompositedAnimations(compositeAnimationEvents);\n\n const iframeEvents =\n traceParsedData.LayoutShifts.renderFrameImplCreateChildFrameEvents.filter(isWithinSameNavigation);\n const networkRequests = traceParsedData.NetworkRequests.byTime.filter(isWithinSameNavigation);\n\n const domLoadingEvents = traceParsedData.LayoutShifts.domLoadingEvents.filter(isWithinSameNavigation);\n\n // Sort by cumulative score, since for insights we interpret these for their \"bad\" scores.\n const clusters = traceParsedData.LayoutShifts.clustersByNavigationId.get(context.navigationId)\n ?.sort((a, b) => b.clusterCumulativeScore - a.clusterCumulativeScore) ??\n [];\n const layoutShifts = clusters.flatMap(cluster => cluster.events);\n const prePaintEvents = traceParsedData.LayoutShifts.prePaintEvents.filter(isWithinSameNavigation);\n\n // Get root causes.\n const rootCausesByShift = new Map();\n const shiftsByPrePaint = getShiftsByPrePaintEvents(layoutShifts, prePaintEvents);\n\n for (const shift of layoutShifts) {\n rootCausesByShift.set(shift, {iframeIds: [], fontRequests: []});\n }\n\n getIframeRootCauses(iframeEvents, prePaintEvents, shiftsByPrePaint, rootCausesByShift, domLoadingEvents);\n getFontRootCauses(networkRequests, prePaintEvents, shiftsByPrePaint, rootCausesByShift);\n\n return {\n animationFailures,\n shifts: rootCausesByShift,\n clusters,\n };\n}\n"]} \ No newline at end of file +{"version":3,"file":"CumulativeLayoutShift.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/CumulativeLayoutShift.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {\n type InsightResult,\n type InsightSetContext,\n type RequiredData,\n} from './types.js';\n\nexport type CLSInsightResult = InsightResult<{\n animationFailures?: readonly NoncompositedAnimationFailure[],\n shifts?: Map,\n clusters: Types.Events.SyntheticLayoutShiftCluster[],\n}>;\n\nexport function deps(): ['Meta', 'Animations', 'LayoutShifts', 'NetworkRequests'] {\n return ['Meta', 'Animations', 'LayoutShifts', 'NetworkRequests'];\n}\n\nexport const enum AnimationFailureReasons {\n UNSUPPORTED_CSS_PROPERTY = 'UNSUPPORTED_CSS_PROPERTY',\n TRANSFROM_BOX_SIZE_DEPENDENT = 'TRANSFROM_BOX_SIZE_DEPENDENT',\n FILTER_MAY_MOVE_PIXELS = 'FILTER_MAY_MOVE_PIXELS',\n NON_REPLACE_COMPOSITE_MODE = 'NON_REPLACE_COMPOSITE_MODE',\n INCOMPATIBLE_ANIMATIONS = 'INCOMPATIBLE_ANIMATIONS',\n UNSUPPORTED_TIMING_PARAMS = 'UNSUPPORTED_TIMING_PARAMS',\n}\n\nexport interface NoncompositedAnimationFailure {\n /**\n * Animation name.\n */\n name?: string;\n /**\n * Failure reason based on mask number defined in\n * https://source.chromium.org/search?q=f:compositor_animations.h%20%22enum%20FailureReason%22.\n */\n failureReasons: AnimationFailureReasons[];\n /**\n * Unsupported properties.\n */\n unsupportedProperties?: Types.Events.Animation['args']['data']['unsupportedProperties'];\n}\n\n/**\n * Each failure reason is represented by a bit flag. The bit shift operator '<<' is used to define\n * which bit corresponds to each failure reason.\n * https://source.chromium.org/search?q=f:compositor_animations.h%20%22enum%20FailureReason%22\n * @type {{flag: number, failure: AnimationFailureReasons}[]}\n */\nconst ACTIONABLE_FAILURE_REASONS = [\n {\n flag: 1 << 13,\n failure: AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY,\n },\n {\n flag: 1 << 11,\n failure: AnimationFailureReasons.TRANSFROM_BOX_SIZE_DEPENDENT,\n },\n {\n flag: 1 << 12,\n failure: AnimationFailureReasons.FILTER_MAY_MOVE_PIXELS,\n },\n {\n flag: 1 << 4,\n failure: AnimationFailureReasons.NON_REPLACE_COMPOSITE_MODE,\n },\n {\n flag: 1 << 6,\n failure: AnimationFailureReasons.INCOMPATIBLE_ANIMATIONS,\n },\n {\n flag: 1 << 3,\n failure: AnimationFailureReasons.UNSUPPORTED_TIMING_PARAMS,\n },\n];\n\n// 500ms window.\n// Use this window to consider events and requests that may have caused a layout shift.\nconst INVALIDATION_WINDOW = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(0.5));\n\nexport interface LayoutShiftRootCausesData {\n iframeIds: string[];\n fontRequests: Types.Events.SyntheticNetworkRequest[];\n}\n\nfunction isInInvalidationWindow(event: Types.Events.Event, targetEvent: Types.Events.Event): boolean {\n const eventEnd = event.dur ? event.ts + event.dur : event.ts;\n return eventEnd < targetEvent.ts && eventEnd >= targetEvent.ts - INVALIDATION_WINDOW;\n}\n\nexport function getNonCompositedFailure(event: Types.Events.SyntheticAnimationPair): NoncompositedAnimationFailure[] {\n const failures: NoncompositedAnimationFailure[] = [];\n const beginEvent = event.args.data.beginEvent;\n const instantEvents = event.args.data.instantEvents || [];\n /**\n * Animation events containing composite information are ASYNC_NESTABLE_INSTANT ('n').\n * An animation may also contain multiple 'n' events, so we look through those with useful non-composited data.\n */\n for (const event of instantEvents) {\n const failureMask = event.args.data.compositeFailed;\n const unsupportedProperties = event.args.data.unsupportedProperties;\n if (!failureMask || !unsupportedProperties) {\n continue;\n }\n const failureReasons =\n ACTIONABLE_FAILURE_REASONS.filter(reason => failureMask & reason.flag).map(reason => reason.failure);\n const failure: NoncompositedAnimationFailure = {\n name: beginEvent.args.data.displayName,\n failureReasons,\n unsupportedProperties,\n };\n failures.push(failure);\n }\n return failures;\n}\n\n/**\n * Given an array of layout shift and PrePaint events, returns a mapping from\n * PrePaint events to layout shifts dispatched within it.\n */\nfunction getShiftsByPrePaintEvents(\n layoutShifts: Types.Events.LayoutShift[],\n prePaintEvents: Types.Events.PrePaint[],\n ): Map {\n // Maps from PrePaint events to LayoutShifts that occured in each one.\n const shiftsByPrePaint = new Map();\n\n // Associate all shifts to their corresponding PrePaint.\n for (const prePaintEvent of prePaintEvents) {\n const firstShiftIndex =\n Platform.ArrayUtilities.nearestIndexFromBeginning(layoutShifts, shift => shift.ts >= prePaintEvent.ts);\n if (firstShiftIndex === null) {\n // No layout shifts registered after this PrePaint start. Continue.\n continue;\n }\n for (let i = firstShiftIndex; i < layoutShifts.length; i++) {\n const shift = layoutShifts[i];\n if (shift.ts >= prePaintEvent.ts && shift.ts <= prePaintEvent.ts + prePaintEvent.dur) {\n const shiftsInPrePaint = Platform.MapUtilities.getWithDefault(shiftsByPrePaint, prePaintEvent, () => []);\n shiftsInPrePaint.push(shift);\n }\n if (shift.ts > prePaintEvent.ts + prePaintEvent.dur) {\n // Reached all layoutShifts of this PrePaint. Break out to continue with the next prePaint event.\n break;\n }\n }\n }\n return shiftsByPrePaint;\n}\n\n/**\n * This gets the first prePaint event that follows the provided event and returns it.\n */\nfunction getNextPrePaintEvent(\n prePaintEvents: Types.Events.PrePaint[], targetEvent: Types.Events.Event): Types.Events.PrePaint|undefined {\n // Get the first PrePaint event that happened after the targetEvent.\n const nextPrePaintIndex = Platform.ArrayUtilities.nearestIndexFromBeginning(\n prePaintEvents, prePaint => prePaint.ts > targetEvent.ts + (targetEvent.dur || 0));\n // No PrePaint event registered after this event\n if (nextPrePaintIndex === null) {\n return undefined;\n }\n\n return prePaintEvents[nextPrePaintIndex];\n}\n\n/**\n * An Iframe is considered a root cause if the iframe event occurs before a prePaint event\n * and within this prePaint event a layout shift(s) occurs.\n */\nfunction getIframeRootCauses(\n iframeCreatedEvents: readonly Types.Events.RenderFrameImplCreateChildFrame[],\n prePaintEvents: Types.Events.PrePaint[], shiftsByPrePaint: Map,\n rootCausesByShift: Map,\n domLoadingEvents: readonly Types.Events.DomLoading[]): Map {\n for (const iframeEvent of iframeCreatedEvents) {\n const nextPrePaint = getNextPrePaintEvent(prePaintEvents, iframeEvent);\n // If no following prePaint, this is not a root cause.\n if (!nextPrePaint) {\n continue;\n }\n const shifts = shiftsByPrePaint.get(nextPrePaint);\n // if no layout shift(s), this is not a root cause.\n if (!shifts) {\n continue;\n }\n for (const shift of shifts) {\n const rootCausesForShift = Platform.MapUtilities.getWithDefault(rootCausesByShift, shift, () => {\n return {\n iframeIds: [],\n fontRequests: [],\n };\n });\n\n // Look for the first dom event that occurs within the bounds of the iframe event.\n // This contains the frame id.\n const domEvent = domLoadingEvents.find(e => {\n const maxIframe = Types.Timing.MicroSeconds(iframeEvent.ts + (iframeEvent.dur ?? 0));\n return e.ts >= iframeEvent.ts && e.ts <= maxIframe;\n });\n if (domEvent && domEvent.args.frame) {\n rootCausesForShift.iframeIds.push(domEvent.args.frame);\n }\n }\n }\n return rootCausesByShift;\n}\n\n/**\n * A font request is considered a root cause if the request occurs before a prePaint event\n * and within this prePaint event a layout shift(s) occurs. Additionally, this font request should\n * happen within the INVALIDATION_WINDOW of the prePaint event.\n */\nfunction getFontRootCauses(\n networkRequests: Types.Events.SyntheticNetworkRequest[], prePaintEvents: Types.Events.PrePaint[],\n shiftsByPrePaint: Map,\n rootCausesByShift: Map):\n Map {\n const fontRequests =\n networkRequests.filter(req => req.args.data.resourceType === 'Font' && req.args.data.mimeType.startsWith('font'));\n\n for (const req of fontRequests) {\n const nextPrePaint = getNextPrePaintEvent(prePaintEvents, req);\n if (!nextPrePaint) {\n continue;\n }\n\n // If the req is outside the INVALIDATION_WINDOW, it could not be a root cause.\n if (!isInInvalidationWindow(req, nextPrePaint)) {\n continue;\n }\n\n // Get the shifts that belong to this prepaint\n const shifts = shiftsByPrePaint.get(nextPrePaint);\n\n // if no layout shift(s) in this prePaint, the request is not a root cause.\n if (!shifts) {\n continue;\n }\n // Include the root cause to the shifts in this prePaint.\n for (const shift of shifts) {\n const rootCausesForShift = Platform.MapUtilities.getWithDefault(rootCausesByShift, shift, () => {\n return {\n iframeIds: [],\n fontRequests: [],\n };\n });\n rootCausesForShift.fontRequests.push(req);\n }\n }\n return rootCausesByShift;\n}\n\nexport function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): CLSInsightResult {\n // TODO(crbug.com/366049346) make this work w/o a navigation.\n if (!context.navigation) {\n return {\n clusters: [],\n };\n }\n\n const isWithinSameNavigation = ((event: Types.Events.Event): boolean => {\n const nav = Helpers.Trace.getNavigationForTraceEvent(event, context.frameId, parsedTrace.Meta.navigationsByFrameId);\n return nav === context.navigation;\n });\n\n const compositeAnimationEvents = parsedTrace.Animations.animations.filter(isWithinSameNavigation);\n const animationFailures = compositeAnimationEvents.map(getNonCompositedFailure).flat();\n\n const iframeEvents = parsedTrace.LayoutShifts.renderFrameImplCreateChildFrameEvents.filter(isWithinSameNavigation);\n const networkRequests = parsedTrace.NetworkRequests.byTime.filter(isWithinSameNavigation);\n\n const domLoadingEvents = parsedTrace.LayoutShifts.domLoadingEvents.filter(isWithinSameNavigation);\n\n // Sort by cumulative score, since for insights we interpret these for their \"bad\" scores.\n const clusters = parsedTrace.LayoutShifts.clustersByNavigationId.get(context.navigationId)\n ?.sort((a, b) => b.clusterCumulativeScore - a.clusterCumulativeScore) ??\n [];\n const layoutShifts = clusters.flatMap(cluster => cluster.events);\n const prePaintEvents = parsedTrace.LayoutShifts.prePaintEvents.filter(isWithinSameNavigation);\n\n // Get root causes.\n const rootCausesByShift = new Map();\n const shiftsByPrePaint = getShiftsByPrePaintEvents(layoutShifts, prePaintEvents);\n\n for (const shift of layoutShifts) {\n rootCausesByShift.set(shift, {iframeIds: [], fontRequests: []});\n }\n\n getIframeRootCauses(iframeEvents, prePaintEvents, shiftsByPrePaint, rootCausesByShift, domLoadingEvents);\n getFontRootCauses(networkRequests, prePaintEvents, shiftsByPrePaint, rootCausesByShift);\n\n return {\n animationFailures,\n shifts: rootCausesByShift,\n clusters,\n };\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/CumulativeLayoutShift.test.d.ts b/public/models/trace/insights/CumulativeLayoutShift.test.d.ts index 848a04692..29614938e 100644 --- a/public/models/trace/insights/CumulativeLayoutShift.test.d.ts +++ b/public/models/trace/insights/CumulativeLayoutShift.test.d.ts @@ -1,5 +1,4 @@ -import type * as TraceModel from '../trace.js'; export declare function processTrace(testContext: Mocha.Suite | Mocha.Context | null, traceFile: string): Promise<{ - data: Readonly>; - insights: TraceModel.Insights.Types.TraceInsightData; + data: Readonly>; + insights: import("./types.js").TraceInsightSets; }>; diff --git a/public/models/trace/insights/CumulativeLayoutShift.test.js b/public/models/trace/insights/CumulativeLayoutShift.test.js index 94338ddf1..316707c09 100644 --- a/public/models/trace/insights/CumulativeLayoutShift.test.js +++ b/public/models/trace/insights/CumulativeLayoutShift.test.js @@ -2,27 +2,17 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; +import { getFirstOrError, getInsight } from '../../../testing/InsightHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; import * as Helpers from '../helpers/helpers.js'; import * as Types from '../types/types.js'; import { InsightRunners } from './insights.js'; export async function processTrace(testContext, traceFile) { - const { traceData, insights } = await TraceLoader.traceEngine(testContext, traceFile); + const { parsedTrace, insights } = await TraceLoader.traceEngine(testContext, traceFile); if (!insights) { throw new Error('No insights'); } - return { data: traceData, insights }; -} -function getInsight(insights, navigationId) { - const navInsights = insights.get(navigationId); - if (!navInsights) { - throw new Error('missing navInsights'); - } - const insight = navInsights.CumulativeLayoutShift; - if (insight instanceof Error) { - throw insight; - } - return insight; + return { data: parsedTrace, insights }; } // Root cause invalidation window. const INVALIDATION_WINDOW = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(0.5)); @@ -30,9 +20,8 @@ describeWithEnvironment('CumulativeLayoutShift', function () { 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'); - const navId = data.Meta.navigationsByNavigationId.keys().next().value; - assert.isOk(navId); - const insight = getInsight(insights, navId); + const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsight('CumulativeLayoutShift', insights, firstNav); const { animationFailures } = insight; const expected = [ { @@ -50,9 +39,8 @@ describeWithEnvironment('CumulativeLayoutShift', function () { }); it('returns no insights when there are no non-composited animations', async function () { const { data, insights } = await processTrace(this, 'lcp-images.json.gz'); - const navId = data.Meta.navigationsByNavigationId.keys().next().value; - assert.isOk(navId); - const insight = getInsight(insights, navId); + const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsight('CumulativeLayoutShift', insights, firstNav); const { animationFailures } = insight; assert.isEmpty(animationFailures); }); @@ -60,9 +48,8 @@ describeWithEnvironment('CumulativeLayoutShift', function () { describe('layout shifts', function () { it('returns correct layout shifts', async function () { const { data, insights } = await processTrace(this, 'cls-single-frame.json.gz'); - const navId = data.Meta.navigationsByNavigationId.keys().next().value; - assert.isOk(navId); - const insight = getInsight(insights, navId); + const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsight('CumulativeLayoutShift', insights, firstNav); const { shifts } = insight; assert.exists(shifts); assert.strictEqual(shifts.size, 7); @@ -71,9 +58,8 @@ describeWithEnvironment('CumulativeLayoutShift', function () { it('handles potential iframe root cause correctly', async function () { // Trace has a single iframe that gets created before the first layout shift and causes a layout shift. const { data, insights } = await processTrace(this, 'iframe-shift.json.gz'); - const navId = data.Meta.navigationsByNavigationId.keys().next().value; - assert.isOk(navId); - const insight = getInsight(insights, navId); + const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsight('CumulativeLayoutShift', insights, firstNav); const { shifts } = insight; assert.exists(shifts); assert.strictEqual(shifts.size, 3); @@ -98,9 +84,8 @@ describeWithEnvironment('CumulativeLayoutShift', function () { it('handles potential font root cause correctly', async function () { // Trace has font load before the second layout shift. const { data, insights } = await processTrace(this, 'iframe-shift.json.gz'); - const navId = data.Meta.navigationsByNavigationId.keys().next().value; - assert.isOk(navId); - const insight = getInsight(insights, navId); + const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsight('CumulativeLayoutShift', insights, firstNav); const { shifts } = insight; assert.exists(shifts); assert.strictEqual(shifts.size, 3); @@ -128,9 +113,8 @@ describeWithEnvironment('CumulativeLayoutShift', function () { describe('clusters', function () { it('returns clusters correctly', async function () { const { data, insights } = await processTrace(this, 'iframe-shift.json.gz'); - const navId = data.Meta.navigationsByNavigationId.keys().next().value; - assert.isOk(navId); - const insight = getInsight(insights, navId); + const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsight('CumulativeLayoutShift', insights, firstNav); const { shifts, clusters } = insight; assert.exists(clusters); assert.exists(shifts); diff --git a/public/models/trace/insights/CumulativeLayoutShift.test.js.map b/public/models/trace/insights/CumulativeLayoutShift.test.js.map index 6977e0f00..5746bc69b 100644 --- a/public/models/trace/insights/CumulativeLayoutShift.test.js.map +++ b/public/models/trace/insights/CumulativeLayoutShift.test.js.map @@ -1 +1 @@ -{"version":3,"file":"CumulativeLayoutShift.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/CumulativeLayoutShift.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport type * as TraceModel from '../trace.js';\nimport * as Types from '../types/types.js';\n\nimport {InsightRunners} from './insights.js';\n\nexport async function processTrace(testContext: Mocha.Suite|Mocha.Context|null, traceFile: string) {\n const {traceData, insights} = await TraceLoader.traceEngine(testContext, traceFile);\n if (!insights) {\n throw new Error('No insights');\n }\n\n return {data: traceData, insights};\n}\n\nfunction getInsight(insights: TraceModel.Insights.Types.TraceInsightData, navigationId: string) {\n const navInsights = insights.get(navigationId);\n if (!navInsights) {\n throw new Error('missing navInsights');\n }\n const insight = navInsights.CumulativeLayoutShift;\n if (insight instanceof Error) {\n throw insight;\n }\n return insight;\n}\n\n// Root cause invalidation window.\nconst INVALIDATION_WINDOW = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(0.5));\n\ndescribeWithEnvironment('CumulativeLayoutShift', function() {\n describe('non composited animations', function() {\n it('gets the correct non composited animations', async function() {\n const {data, insights} = await processTrace(this, 'non-composited-animation.json.gz');\n const navId = data.Meta.navigationsByNavigationId.keys().next().value;\n assert.isOk(navId);\n const insight = getInsight(insights, navId);\n const {animationFailures} = insight;\n\n const expected: InsightRunners.CumulativeLayoutShift.NoncompositedAnimationFailure[] = [\n {\n name: 'simple-animation',\n failureReasons: [InsightRunners.CumulativeLayoutShift.AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY],\n unsupportedProperties: ['color'],\n },\n {\n name: 'top',\n failureReasons: [InsightRunners.CumulativeLayoutShift.AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY],\n unsupportedProperties: ['top'],\n },\n ];\n assert.deepStrictEqual(animationFailures, expected);\n });\n it('returns no insights when there are no non-composited animations', async function() {\n const {data, insights} = await processTrace(this, 'lcp-images.json.gz');\n const navId = data.Meta.navigationsByNavigationId.keys().next().value;\n assert.isOk(navId);\n const insight = getInsight(insights, navId);\n const {animationFailures} = insight;\n\n assert.isEmpty(animationFailures);\n });\n });\n describe('layout shifts', function() {\n it('returns correct layout shifts', async function() {\n const {data, insights} = await processTrace(this, 'cls-single-frame.json.gz');\n const navId = data.Meta.navigationsByNavigationId.keys().next().value;\n assert.isOk(navId);\n const insight = getInsight(insights, navId);\n const {shifts} = insight;\n\n assert.exists(shifts);\n assert.strictEqual(shifts.size, 7);\n });\n\n describe('root causes', function() {\n it('handles potential iframe root cause correctly', async function() {\n // Trace has a single iframe that gets created before the first layout shift and causes a layout shift.\n const {data, insights} = await processTrace(this, 'iframe-shift.json.gz');\n const navId = data.Meta.navigationsByNavigationId.keys().next().value;\n assert.isOk(navId);\n const insight = getInsight(insights, navId);\n const {shifts} = insight;\n\n assert.exists(shifts);\n assert.strictEqual(shifts.size, 3);\n\n const shift1 = Array.from(shifts)[0][0];\n const shiftIframes = shifts.get(shift1)?.iframeIds;\n assert.exists(shiftIframes);\n assert.strictEqual(shiftIframes.length, 1);\n\n const iframe = shiftIframes[0];\n\n // Find the event with the matching frame id to make sure we got the right id.\n const dlEvent = data.LayoutShifts.domLoadingEvents.find(e => {\n return e.args.frame === iframe;\n });\n assert.exists(dlEvent);\n\n // Ensure the iframe happens within the invalidation window.\n assert.isTrue(dlEvent.ts < shift1.ts && dlEvent.ts >= shift1.ts - INVALIDATION_WINDOW);\n // Other shifts should not have iframe root causes.\n const shift2 = Array.from(shifts)[1][0];\n assert.isEmpty(shifts.get(shift2)?.iframeIds);\n const shift3 = Array.from(shifts)[2][0];\n assert.isEmpty(shifts.get(shift3)?.iframeIds);\n });\n\n it('handles potential font root cause correctly', async function() {\n // Trace has font load before the second layout shift.\n const {data, insights} = await processTrace(this, 'iframe-shift.json.gz');\n const navId = data.Meta.navigationsByNavigationId.keys().next().value;\n assert.isOk(navId);\n const insight = getInsight(insights, navId);\n const {shifts} = insight;\n\n assert.exists(shifts);\n assert.strictEqual(shifts.size, 3);\n\n const layoutShiftEvents = Array.from(shifts.entries());\n\n const shift2 = layoutShiftEvents.at(1);\n assert.isOk(shift2);\n const shiftEvent = shift2[0];\n\n const shiftFonts = shift2[1].fontRequests;\n assert.exists(shiftFonts);\n assert.strictEqual(shiftFonts.length, 1);\n\n const fontRequest = shiftFonts[0];\n const fontRequestEndTime = fontRequest.ts + fontRequest.dur;\n // Ensure the font loads within the invalidation window.\n assert.isTrue(fontRequestEndTime < shiftEvent.ts && fontRequestEndTime >= shiftEvent.ts - INVALIDATION_WINDOW);\n\n // Other shifts should not have font root causes.\n const shift1 = layoutShiftEvents.at(0);\n assert.isOk(shift1);\n assert.isEmpty(shift1[1].fontRequests);\n\n const shift3 = layoutShiftEvents.at(2);\n assert.isOk(shift3);\n assert.isEmpty(shift3[1].fontRequests);\n });\n });\n });\n describe('clusters', function() {\n it('returns clusters correctly', async function() {\n const {data, insights} = await processTrace(this, 'iframe-shift.json.gz');\n const navId = data.Meta.navigationsByNavigationId.keys().next().value;\n assert.isOk(navId);\n const insight = getInsight(insights, navId);\n const {shifts, clusters} = insight;\n\n assert.exists(clusters);\n assert.exists(shifts);\n assert.strictEqual(clusters.length, 2);\n for (const cluster of clusters) {\n // Check that the cluster events exist in shifts map.\n for (const shiftEvent of cluster.events) {\n assert.exists(shifts.get(shiftEvent));\n }\n }\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"CumulativeLayoutShift.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/CumulativeLayoutShift.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {getFirstOrError, getInsight} from '../../../testing/InsightHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {InsightRunners} from './insights.js';\n\nexport async function processTrace(testContext: Mocha.Suite|Mocha.Context|null, traceFile: string) {\n const {parsedTrace, insights} = await TraceLoader.traceEngine(testContext, traceFile);\n if (!insights) {\n throw new Error('No insights');\n }\n\n return {data: parsedTrace, insights};\n}\n\n// Root cause invalidation window.\nconst INVALIDATION_WINDOW = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(0.5));\n\ndescribeWithEnvironment('CumulativeLayoutShift', function() {\n describe('non composited animations', function() {\n it('gets the correct non composited animations', async function() {\n const {data, insights} = await processTrace(this, 'non-composited-animation.json.gz');\n const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values());\n const insight = getInsight('CumulativeLayoutShift', insights, firstNav);\n const {animationFailures} = insight;\n\n const expected: InsightRunners.CumulativeLayoutShift.NoncompositedAnimationFailure[] = [\n {\n name: 'simple-animation',\n failureReasons: [InsightRunners.CumulativeLayoutShift.AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY],\n unsupportedProperties: ['color'],\n },\n {\n name: 'top',\n failureReasons: [InsightRunners.CumulativeLayoutShift.AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY],\n unsupportedProperties: ['top'],\n },\n ];\n assert.deepStrictEqual(animationFailures, expected);\n });\n it('returns no insights when there are no non-composited animations', async function() {\n const {data, insights} = await processTrace(this, 'lcp-images.json.gz');\n const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values());\n const insight = getInsight('CumulativeLayoutShift', insights, firstNav);\n const {animationFailures} = insight;\n\n assert.isEmpty(animationFailures);\n });\n });\n describe('layout shifts', function() {\n it('returns correct layout shifts', async function() {\n const {data, insights} = await processTrace(this, 'cls-single-frame.json.gz');\n const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values());\n const insight = getInsight('CumulativeLayoutShift', insights, firstNav);\n const {shifts} = insight;\n\n assert.exists(shifts);\n assert.strictEqual(shifts.size, 7);\n });\n\n describe('root causes', function() {\n it('handles potential iframe root cause correctly', async function() {\n // Trace has a single iframe that gets created before the first layout shift and causes a layout shift.\n const {data, insights} = await processTrace(this, 'iframe-shift.json.gz');\n const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values());\n const insight = getInsight('CumulativeLayoutShift', insights, firstNav);\n const {shifts} = insight;\n\n assert.exists(shifts);\n assert.strictEqual(shifts.size, 3);\n\n const shift1 = Array.from(shifts)[0][0];\n const shiftIframes = shifts.get(shift1)?.iframeIds;\n assert.exists(shiftIframes);\n assert.strictEqual(shiftIframes.length, 1);\n\n const iframe = shiftIframes[0];\n\n // Find the event with the matching frame id to make sure we got the right id.\n const dlEvent = data.LayoutShifts.domLoadingEvents.find(e => {\n return e.args.frame === iframe;\n });\n assert.exists(dlEvent);\n\n // Ensure the iframe happens within the invalidation window.\n assert.isTrue(dlEvent.ts < shift1.ts && dlEvent.ts >= shift1.ts - INVALIDATION_WINDOW);\n // Other shifts should not have iframe root causes.\n const shift2 = Array.from(shifts)[1][0];\n assert.isEmpty(shifts.get(shift2)?.iframeIds);\n const shift3 = Array.from(shifts)[2][0];\n assert.isEmpty(shifts.get(shift3)?.iframeIds);\n });\n\n it('handles potential font root cause correctly', async function() {\n // Trace has font load before the second layout shift.\n const {data, insights} = await processTrace(this, 'iframe-shift.json.gz');\n const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values());\n const insight = getInsight('CumulativeLayoutShift', insights, firstNav);\n const {shifts} = insight;\n\n assert.exists(shifts);\n assert.strictEqual(shifts.size, 3);\n\n const layoutShiftEvents = Array.from(shifts.entries());\n\n const shift2 = layoutShiftEvents.at(1);\n assert.isOk(shift2);\n const shiftEvent = shift2[0];\n\n const shiftFonts = shift2[1].fontRequests;\n assert.exists(shiftFonts);\n assert.strictEqual(shiftFonts.length, 1);\n\n const fontRequest = shiftFonts[0];\n const fontRequestEndTime = fontRequest.ts + fontRequest.dur;\n // Ensure the font loads within the invalidation window.\n assert.isTrue(fontRequestEndTime < shiftEvent.ts && fontRequestEndTime >= shiftEvent.ts - INVALIDATION_WINDOW);\n\n // Other shifts should not have font root causes.\n const shift1 = layoutShiftEvents.at(0);\n assert.isOk(shift1);\n assert.isEmpty(shift1[1].fontRequests);\n\n const shift3 = layoutShiftEvents.at(2);\n assert.isOk(shift3);\n assert.isEmpty(shift3[1].fontRequests);\n });\n });\n });\n describe('clusters', function() {\n it('returns clusters correctly', async function() {\n const {data, insights} = await processTrace(this, 'iframe-shift.json.gz');\n const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values());\n const insight = getInsight('CumulativeLayoutShift', insights, firstNav);\n const {shifts, clusters} = insight;\n\n assert.exists(clusters);\n assert.exists(shifts);\n assert.strictEqual(clusters.length, 2);\n for (const cluster of clusters) {\n // Check that the cluster events exist in shifts map.\n for (const shiftEvent of cluster.events) {\n assert.exists(shifts.get(shiftEvent));\n }\n }\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/DocumentLatency.d.ts b/public/models/trace/insights/DocumentLatency.d.ts index bc489f8aa..6faea7d8e 100644 --- a/public/models/trace/insights/DocumentLatency.d.ts +++ b/public/models/trace/insights/DocumentLatency.d.ts @@ -1,11 +1,13 @@ import * as Types from '../types/types.js'; -import { type InsightResult, type NavigationInsightContext, type RequiredData } from './types.js'; +import { type InsightResult, type InsightSetContext, type RequiredData } from './types.js'; export type DocumentLatencyInsightResult = InsightResult<{ - serverResponseTime: Types.Timing.MilliSeconds; - serverResponseTooSlow: boolean; - redirectDuration: Types.Timing.MilliSeconds; - uncompressedResponseBytes: number; - documentRequest?: Types.TraceEvents.SyntheticNetworkRequest; + data?: { + serverResponseTime: Types.Timing.MilliSeconds; + serverResponseTooSlow: boolean; + redirectDuration: Types.Timing.MilliSeconds; + uncompressedResponseBytes: number; + documentRequest?: Types.Events.SyntheticNetworkRequest; + }; }>; export declare function deps(): ['Meta', 'NetworkRequests']; -export declare function generateInsight(traceParsedData: RequiredData, context: NavigationInsightContext): DocumentLatencyInsightResult; +export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): DocumentLatencyInsightResult; diff --git a/public/models/trace/insights/DocumentLatency.js b/public/models/trace/insights/DocumentLatency.js index 33a9c632d..34986c745 100644 --- a/public/models/trace/insights/DocumentLatency.js +++ b/public/models/trace/insights/DocumentLatency.js @@ -79,8 +79,11 @@ function getCompressionSavings(request) { // no percent threshold. return estimatedSavings < IGNORE_THRESHOLD_IN_BYTES ? 0 : estimatedSavings; } -export function generateInsight(traceParsedData, context) { - const documentRequest = traceParsedData.NetworkRequests.byTime.find(req => req.args.data.requestId === context.navigationId); +export function generateInsight(parsedTrace, context) { + if (!context.navigation) { + return {}; + } + const documentRequest = parsedTrace.NetworkRequests.byTime.find(req => req.args.data.requestId === context.navigationId); if (!documentRequest) { throw new Error('missing document request'); } @@ -100,11 +103,13 @@ export function generateInsight(traceParsedData, context) { LCP: overallSavingsMs, }; return { - serverResponseTime, - serverResponseTooSlow, - redirectDuration: Types.Timing.MilliSeconds(redirectDuration), - uncompressedResponseBytes: getCompressionSavings(documentRequest), - documentRequest, + data: { + serverResponseTime, + serverResponseTooSlow, + redirectDuration: Types.Timing.MilliSeconds(redirectDuration), + uncompressedResponseBytes: getCompressionSavings(documentRequest), + documentRequest, + }, metricSavings, }; } diff --git a/public/models/trace/insights/DocumentLatency.js.map b/public/models/trace/insights/DocumentLatency.js.map index 229067c9a..642ae6b10 100644 --- a/public/models/trace/insights/DocumentLatency.js.map +++ b/public/models/trace/insights/DocumentLatency.js.map @@ -1 +1 @@ -{"version":3,"file":"DocumentLatency.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/DocumentLatency.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Types from '../types/types.js';\n\nimport {type InsightResult, type NavigationInsightContext, type RequiredData} from './types.js';\n\n// Due to the way that DevTools throttling works we cannot see if server response took less than ~570ms.\n// We set our failure threshold to 600ms to avoid those false positives but we want devs to shoot for 100ms.\nconst TOO_SLOW_THRESHOLD_MS = 600;\nconst TARGET_MS = 100;\n\n// Threshold for compression savings.\nconst IGNORE_THRESHOLD_IN_BYTES = 1400;\n\nexport type DocumentLatencyInsightResult = InsightResult<{\n serverResponseTime: Types.Timing.MilliSeconds,\n serverResponseTooSlow: boolean,\n redirectDuration: Types.Timing.MilliSeconds,\n uncompressedResponseBytes: number,\n documentRequest?: Types.TraceEvents.SyntheticNetworkRequest,\n}>;\n\nexport function deps(): ['Meta', 'NetworkRequests'] {\n return ['Meta', 'NetworkRequests'];\n}\n\nfunction getServerTiming(request: Types.TraceEvents.SyntheticNetworkRequest): Types.Timing.MilliSeconds|null {\n const timing = request.args.data.timing;\n if (!timing) {\n return null;\n }\n\n return Types.Timing.MilliSeconds(Math.round(timing.receiveHeadersStart - timing.sendEnd));\n}\n\nfunction getCompressionSavings(request: Types.TraceEvents.SyntheticNetworkRequest): number {\n // Check from headers if compression was already applied.\n // Older devtools logs are lower case, while modern logs are Cased-Like-This.\n const patterns = [\n /^content-encoding$/i,\n /^x-content-encoding-over-network$/i,\n ];\n const compressionTypes = ['gzip', 'br', 'deflate', 'zstd'];\n const isCompressed = request.args.data.responseHeaders.some(\n header => patterns.some(p => header.name.match(p)) && compressionTypes.includes(header.value));\n if (isCompressed) {\n return 0;\n }\n\n // We don't know how many bytes this asset used on the network, but we can guess it was\n // roughly the size of the content gzipped.\n // See https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/optimize-encoding-and-transfer for specific CSS/Script examples\n // See https://discuss.httparchive.org/t/file-size-and-compression-savings/145 for fallback multipliers\n // See https://letstalkaboutwebperf.com/en/gzip-brotli-server-config/ for MIME types to compress\n const originalSize = request.args.data.decodedBodyLength;\n let estimatedSavings = 0;\n switch (request.args.data.mimeType) {\n case 'text/css':\n // Stylesheets tend to compress extremely well.\n estimatedSavings = Math.round(originalSize * 0.8);\n break;\n case 'text/html':\n case 'text/javascript':\n // Scripts and HTML compress fairly well too.\n estimatedSavings = Math.round(originalSize * 0.67);\n break;\n case 'text/plain':\n case 'text/xml':\n case 'text/x-component':\n case 'application/javascript':\n case 'application/json':\n case 'application/manifest+json':\n case 'application/vnd.api+json':\n case 'application/xml':\n case 'application/xhtml+xml':\n case 'application/rss+xml':\n case 'application/atom+xml':\n case 'application/vnd.ms-fontobject':\n case 'application/x-font-ttf':\n case 'application/x-font-opentype':\n case 'application/x-font-truetype':\n case 'image/svg+xml':\n case 'image/x-icon':\n case 'image/vnd.microsoft.icon':\n case 'font/ttf':\n case 'font/eot':\n case 'font/otf':\n case 'font/opentype':\n // Use the average savings in HTTPArchive.\n estimatedSavings = Math.round(originalSize * 0.5);\n break;\n default: // Any other MIME types are likely already compressed.\n }\n // Check if the estimated savings are greater than the byte ignore threshold.\n // Note that the estimated gzip savings are always more than 10%, so there is\n // no percent threshold.\n return estimatedSavings < IGNORE_THRESHOLD_IN_BYTES ? 0 : estimatedSavings;\n}\n\nexport function generateInsight(\n traceParsedData: RequiredData, context: NavigationInsightContext): DocumentLatencyInsightResult {\n const documentRequest =\n traceParsedData.NetworkRequests.byTime.find(req => req.args.data.requestId === context.navigationId);\n if (!documentRequest) {\n throw new Error('missing document request');\n }\n\n const serverResponseTime = getServerTiming(documentRequest);\n if (serverResponseTime === null) {\n throw new Error('missing document request timing');\n }\n\n const serverResponseTooSlow = serverResponseTime > TOO_SLOW_THRESHOLD_MS;\n\n let overallSavingsMs = 0;\n if (serverResponseTime > TOO_SLOW_THRESHOLD_MS) {\n overallSavingsMs = Math.max(serverResponseTime - TARGET_MS, 0);\n }\n\n const redirectDuration = Math.round(documentRequest.args.data.syntheticData.redirectionDuration / 1000);\n overallSavingsMs += redirectDuration;\n\n const metricSavings = {\n FCP: overallSavingsMs,\n LCP: overallSavingsMs,\n };\n\n return {\n serverResponseTime,\n serverResponseTooSlow,\n redirectDuration: Types.Timing.MilliSeconds(redirectDuration),\n uncompressedResponseBytes: getCompressionSavings(documentRequest),\n documentRequest,\n metricSavings,\n };\n}\n"]} \ No newline at end of file +{"version":3,"file":"DocumentLatency.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/DocumentLatency.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Types from '../types/types.js';\n\nimport {type InsightResult, type InsightSetContext, type RequiredData} from './types.js';\n\n// Due to the way that DevTools throttling works we cannot see if server response took less than ~570ms.\n// We set our failure threshold to 600ms to avoid those false positives but we want devs to shoot for 100ms.\nconst TOO_SLOW_THRESHOLD_MS = 600;\nconst TARGET_MS = 100;\n\n// Threshold for compression savings.\nconst IGNORE_THRESHOLD_IN_BYTES = 1400;\n\nexport type DocumentLatencyInsightResult = InsightResult<{\n data?: {\n serverResponseTime: Types.Timing.MilliSeconds,\n serverResponseTooSlow: boolean,\n redirectDuration: Types.Timing.MilliSeconds,\n uncompressedResponseBytes: number,\n documentRequest?: Types.Events.SyntheticNetworkRequest,\n },\n}>;\n\nexport function deps(): ['Meta', 'NetworkRequests'] {\n return ['Meta', 'NetworkRequests'];\n}\n\nfunction getServerTiming(request: Types.Events.SyntheticNetworkRequest): Types.Timing.MilliSeconds|null {\n const timing = request.args.data.timing;\n if (!timing) {\n return null;\n }\n\n return Types.Timing.MilliSeconds(Math.round(timing.receiveHeadersStart - timing.sendEnd));\n}\n\nfunction getCompressionSavings(request: Types.Events.SyntheticNetworkRequest): number {\n // Check from headers if compression was already applied.\n // Older devtools logs are lower case, while modern logs are Cased-Like-This.\n const patterns = [\n /^content-encoding$/i,\n /^x-content-encoding-over-network$/i,\n ];\n const compressionTypes = ['gzip', 'br', 'deflate', 'zstd'];\n const isCompressed = request.args.data.responseHeaders.some(\n header => patterns.some(p => header.name.match(p)) && compressionTypes.includes(header.value));\n if (isCompressed) {\n return 0;\n }\n\n // We don't know how many bytes this asset used on the network, but we can guess it was\n // roughly the size of the content gzipped.\n // See https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/optimize-encoding-and-transfer for specific CSS/Script examples\n // See https://discuss.httparchive.org/t/file-size-and-compression-savings/145 for fallback multipliers\n // See https://letstalkaboutwebperf.com/en/gzip-brotli-server-config/ for MIME types to compress\n const originalSize = request.args.data.decodedBodyLength;\n let estimatedSavings = 0;\n switch (request.args.data.mimeType) {\n case 'text/css':\n // Stylesheets tend to compress extremely well.\n estimatedSavings = Math.round(originalSize * 0.8);\n break;\n case 'text/html':\n case 'text/javascript':\n // Scripts and HTML compress fairly well too.\n estimatedSavings = Math.round(originalSize * 0.67);\n break;\n case 'text/plain':\n case 'text/xml':\n case 'text/x-component':\n case 'application/javascript':\n case 'application/json':\n case 'application/manifest+json':\n case 'application/vnd.api+json':\n case 'application/xml':\n case 'application/xhtml+xml':\n case 'application/rss+xml':\n case 'application/atom+xml':\n case 'application/vnd.ms-fontobject':\n case 'application/x-font-ttf':\n case 'application/x-font-opentype':\n case 'application/x-font-truetype':\n case 'image/svg+xml':\n case 'image/x-icon':\n case 'image/vnd.microsoft.icon':\n case 'font/ttf':\n case 'font/eot':\n case 'font/otf':\n case 'font/opentype':\n // Use the average savings in HTTPArchive.\n estimatedSavings = Math.round(originalSize * 0.5);\n break;\n default: // Any other MIME types are likely already compressed.\n }\n // Check if the estimated savings are greater than the byte ignore threshold.\n // Note that the estimated gzip savings are always more than 10%, so there is\n // no percent threshold.\n return estimatedSavings < IGNORE_THRESHOLD_IN_BYTES ? 0 : estimatedSavings;\n}\n\nexport function generateInsight(\n parsedTrace: RequiredData, context: InsightSetContext): DocumentLatencyInsightResult {\n if (!context.navigation) {\n return {};\n }\n\n const documentRequest =\n parsedTrace.NetworkRequests.byTime.find(req => req.args.data.requestId === context.navigationId);\n if (!documentRequest) {\n throw new Error('missing document request');\n }\n\n const serverResponseTime = getServerTiming(documentRequest);\n if (serverResponseTime === null) {\n throw new Error('missing document request timing');\n }\n\n const serverResponseTooSlow = serverResponseTime > TOO_SLOW_THRESHOLD_MS;\n\n let overallSavingsMs = 0;\n if (serverResponseTime > TOO_SLOW_THRESHOLD_MS) {\n overallSavingsMs = Math.max(serverResponseTime - TARGET_MS, 0);\n }\n\n const redirectDuration = Math.round(documentRequest.args.data.syntheticData.redirectionDuration / 1000);\n overallSavingsMs += redirectDuration;\n\n const metricSavings = {\n FCP: overallSavingsMs,\n LCP: overallSavingsMs,\n };\n\n return {\n data: {\n serverResponseTime,\n serverResponseTooSlow,\n redirectDuration: Types.Timing.MilliSeconds(redirectDuration),\n uncompressedResponseBytes: getCompressionSavings(documentRequest),\n documentRequest,\n },\n metricSavings,\n };\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/DocumentLatency.test.d.ts b/public/models/trace/insights/DocumentLatency.test.d.ts index cdc9b4ae2..aec4618f2 100644 --- a/public/models/trace/insights/DocumentLatency.test.d.ts +++ b/public/models/trace/insights/DocumentLatency.test.d.ts @@ -1,5 +1,5 @@ -import * as TraceModel from '../trace.js'; +import * as Trace from '../trace.js'; export declare function processTrace(testContext: Mocha.Suite | Mocha.Context | null, traceFile: string): Promise<{ - data: Readonly>; - insights: TraceModel.Insights.Types.TraceInsightData; + data: Readonly>; + insights: Trace.Insights.Types.TraceInsightSets; }>; diff --git a/public/models/trace/insights/DocumentLatency.test.js b/public/models/trace/insights/DocumentLatency.test.js index bcc2a318b..f531825f3 100644 --- a/public/models/trace/insights/DocumentLatency.test.js +++ b/public/models/trace/insights/DocumentLatency.test.js @@ -2,47 +2,37 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; +import { createContextForNavigation, getFirstOrError, getInsight } from '../../../testing/InsightHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; -import * as TraceModel from '../trace.js'; +import * as Trace from '../trace.js'; import * as Types from '../types/types.js'; export async function processTrace(testContext, traceFile) { - const { traceData, insights } = await TraceLoader.traceEngine(testContext, traceFile); + const { parsedTrace, insights } = await TraceLoader.traceEngine(testContext, traceFile); if (!insights) { throw new Error('No insights'); } - return { data: traceData, insights }; -} -function getInsight(insights, navigationId) { - const navInsights = insights.get(navigationId); - if (!navInsights) { - throw new Error('missing navInsights'); - } - const insight = navInsights.DocumentLatency; - if (insight instanceof Error) { - throw insight; - } - return insight; + return { data: parsedTrace, insights }; } describeWithEnvironment('DocumentLatency', function () { 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); - assert.strictEqual(insight.redirectDuration, 1779); + const insight = getInsight('DocumentLatency', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values())); + assert.strictEqual(insight.data?.redirectDuration, 1779); assert.deepEqual(insight.metricSavings, { FCP: 1779, LCP: 1779 }); }); it('reports no savings for server with low response time', async () => { const { data, insights } = await processTrace(this, 'lantern/paul/trace.json.gz'); - const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value); - assert.strictEqual(insight.serverResponseTime, 43); - assert(!insight.serverResponseTooSlow); + const insight = getInsight('DocumentLatency', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values())); + assert.strictEqual(insight.data?.serverResponseTime, 43); + assert(!insight.data?.serverResponseTooSlow); assert.deepEqual(insight.metricSavings, { FCP: 0, LCP: 0 }); }); it('reports savings for server with high response time', async function () { const traceEvents = [...await TraceLoader.rawEvents(this, 'lantern/paul/trace.json.gz')]; - const processor = TraceModel.Processor.TraceProcessor.createWithAllHandlers(); + const processor = Trace.Processor.TraceProcessor.createWithAllHandlers(); const mainRequestEventIndex = traceEvents.findIndex(e => e.name === 'ResourceReceiveResponse'); const mainRequestEvent = structuredClone(traceEvents[mainRequestEventIndex]); - assert(Types.TraceEvents.isTraceEventResourceReceiveResponse(mainRequestEvent)); + assert(Types.Events.isResourceReceiveResponse(mainRequestEvent)); assert.strictEqual(mainRequestEvent.args.data.requestId, '1000C0FDC0A75327167272FC7438E999'); if (!mainRequestEvent.args.data.timing) { throw new Error('missing timing field'); @@ -51,50 +41,42 @@ describeWithEnvironment('DocumentLatency', function () { Types.Timing.MilliSeconds(mainRequestEvent.args.data.timing.receiveHeadersStart + 1000); traceEvents[mainRequestEventIndex] = mainRequestEvent; await processor.parse(traceEvents); - const data = processor.traceParsedData; + const data = processor.parsedTrace; if (!data) { - throw new Error('missing traceParsedData'); + throw new Error('missing parsedTrace'); } - const [navigationId, navigation] = data.Meta.navigationsByNavigationId.entries().next().value; - const context = { - frameId: data.Meta.mainFrameId, - navigation, - navigationId, - }; - const insight = TraceModel.Insights.InsightRunners.DocumentLatency.generateInsight(data, context); - assert.strictEqual(insight.serverResponseTime, 1043); - assert(insight.serverResponseTooSlow); + const navigation = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const context = createContextForNavigation(navigation, data.Meta.mainFrameId); + const insight = Trace.Insights.InsightRunners.DocumentLatency.generateInsight(data, context); + assert.strictEqual(insight.data?.serverResponseTime, 1043); + assert(insight.data?.serverResponseTooSlow); assert.deepEqual(insight.metricSavings, { FCP: 943, LCP: 943 }); }); it('reports no compression savings for compressed text', async () => { const { data, insights } = await processTrace(this, 'lantern/paul/trace.json.gz'); - const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value); - assert.strictEqual(insight.uncompressedResponseBytes, 0); + const insight = getInsight('DocumentLatency', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values())); + assert.strictEqual(insight.data?.uncompressedResponseBytes, 0); assert.deepEqual(insight.metricSavings, { FCP: 0, LCP: 0 }); }); it('reports compression savings for uncompressed text', async function () { const traceEvents = [...await TraceLoader.rawEvents(this, 'lantern/paul/trace.json.gz')]; - const processor = TraceModel.Processor.TraceProcessor.createWithAllHandlers(); + const processor = Trace.Processor.TraceProcessor.createWithAllHandlers(); const mainRequestEventIndex = traceEvents.findIndex(e => e.name === 'ResourceReceiveResponse'); const mainRequestEvent = structuredClone(traceEvents[mainRequestEventIndex]); - assert(Types.TraceEvents.isTraceEventResourceReceiveResponse(mainRequestEvent)); + assert(Types.Events.isResourceReceiveResponse(mainRequestEvent)); assert.strictEqual(mainRequestEvent.args.data.requestId, '1000C0FDC0A75327167272FC7438E999'); // Delete content-encoding header. mainRequestEvent.args.data.headers = mainRequestEvent.args.data.headers?.filter(h => h.name !== 'content-encoding'); traceEvents[mainRequestEventIndex] = mainRequestEvent; await processor.parse(traceEvents); - const data = processor.traceParsedData; + const data = processor.parsedTrace; if (!data) { - throw new Error('missing traceParsedData'); + throw new Error('missing parsedTrace'); } - const [navigationId, navigation] = data.Meta.navigationsByNavigationId.entries().next().value; - const context = { - frameId: data.Meta.mainFrameId, - navigation, - navigationId, - }; - const insight = TraceModel.Insights.InsightRunners.DocumentLatency.generateInsight(data, context); - assert.strictEqual(insight.uncompressedResponseBytes, 39799); + const navigation = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const context = createContextForNavigation(navigation, data.Meta.mainFrameId); + const insight = Trace.Insights.InsightRunners.DocumentLatency.generateInsight(data, context); + assert.strictEqual(insight.data?.uncompressedResponseBytes, 39799); assert.deepEqual(insight.metricSavings, { FCP: 0, LCP: 0 }); }); }); diff --git a/public/models/trace/insights/DocumentLatency.test.js.map b/public/models/trace/insights/DocumentLatency.test.js.map index f28c9eed8..94168624d 100644 --- a/public/models/trace/insights/DocumentLatency.test.js.map +++ b/public/models/trace/insights/DocumentLatency.test.js.map @@ -1 +1 @@ -{"version":3,"file":"DocumentLatency.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/DocumentLatency.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as TraceModel from '../trace.js';\nimport * as Types from '../types/types.js';\n\nexport async function processTrace(testContext: Mocha.Suite|Mocha.Context|null, traceFile: string) {\n const {traceData, insights} = await TraceLoader.traceEngine(testContext, traceFile);\n if (!insights) {\n throw new Error('No insights');\n }\n\n return {data: traceData, insights};\n}\n\nfunction getInsight(insights: TraceModel.Insights.Types.TraceInsightData, navigationId: string) {\n const navInsights = insights.get(navigationId);\n if (!navInsights) {\n throw new Error('missing navInsights');\n }\n const insight = navInsights.DocumentLatency;\n if (insight instanceof Error) {\n throw insight;\n }\n return insight;\n}\n\ndescribeWithEnvironment('DocumentLatency', function() {\n it('reports savings for main document with redirects', async () => {\n const {data, insights} = await processTrace(this, 'lantern/redirect/trace.json.gz');\n const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value);\n assert.strictEqual(insight.redirectDuration, 1779);\n assert.deepEqual(insight.metricSavings, {FCP: 1779, LCP: 1779});\n });\n\n it('reports no savings for server with low response time', async () => {\n const {data, insights} = await processTrace(this, 'lantern/paul/trace.json.gz');\n const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value);\n assert.strictEqual(insight.serverResponseTime, 43);\n assert(!insight.serverResponseTooSlow);\n assert.deepEqual(insight.metricSavings, {FCP: 0, LCP: 0});\n });\n\n it('reports savings for server with high response time', async function() {\n const traceEvents = [...await TraceLoader.rawEvents(this, 'lantern/paul/trace.json.gz')];\n const processor = TraceModel.Processor.TraceProcessor.createWithAllHandlers();\n\n const mainRequestEventIndex = traceEvents.findIndex(e => e.name === 'ResourceReceiveResponse');\n const mainRequestEvent = structuredClone(traceEvents[mainRequestEventIndex]);\n assert(Types.TraceEvents.isTraceEventResourceReceiveResponse(mainRequestEvent));\n assert.strictEqual(mainRequestEvent.args.data.requestId, '1000C0FDC0A75327167272FC7438E999');\n if (!mainRequestEvent.args.data.timing) {\n throw new Error('missing timing field');\n }\n mainRequestEvent.args.data.timing.receiveHeadersStart =\n Types.Timing.MilliSeconds(mainRequestEvent.args.data.timing.receiveHeadersStart + 1000);\n traceEvents[mainRequestEventIndex] = mainRequestEvent;\n\n await processor.parse(traceEvents);\n const data = processor.traceParsedData;\n if (!data) {\n throw new Error('missing traceParsedData');\n }\n\n const [navigationId, navigation] = data.Meta.navigationsByNavigationId.entries().next().value;\n const context = {\n frameId: data.Meta.mainFrameId,\n navigation,\n navigationId,\n };\n const insight = TraceModel.Insights.InsightRunners.DocumentLatency.generateInsight(data, context);\n assert.strictEqual(insight.serverResponseTime, 1043);\n assert(insight.serverResponseTooSlow);\n assert.deepEqual(insight.metricSavings, {FCP: 943, LCP: 943});\n });\n\n it('reports no compression savings for compressed text', async () => {\n const {data, insights} = await processTrace(this, 'lantern/paul/trace.json.gz');\n const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value);\n assert.strictEqual(insight.uncompressedResponseBytes, 0);\n assert.deepEqual(insight.metricSavings, {FCP: 0, LCP: 0});\n });\n\n it('reports compression savings for uncompressed text', async function() {\n const traceEvents = [...await TraceLoader.rawEvents(this, 'lantern/paul/trace.json.gz')];\n const processor = TraceModel.Processor.TraceProcessor.createWithAllHandlers();\n\n const mainRequestEventIndex = traceEvents.findIndex(e => e.name === 'ResourceReceiveResponse');\n const mainRequestEvent = structuredClone(traceEvents[mainRequestEventIndex]);\n assert(Types.TraceEvents.isTraceEventResourceReceiveResponse(mainRequestEvent));\n assert.strictEqual(mainRequestEvent.args.data.requestId, '1000C0FDC0A75327167272FC7438E999');\n // Delete content-encoding header.\n mainRequestEvent.args.data.headers = mainRequestEvent.args.data.headers?.filter(h => h.name !== 'content-encoding');\n traceEvents[mainRequestEventIndex] = mainRequestEvent;\n\n await processor.parse(traceEvents);\n const data = processor.traceParsedData;\n if (!data) {\n throw new Error('missing traceParsedData');\n }\n\n const [navigationId, navigation] = data.Meta.navigationsByNavigationId.entries().next().value;\n const context = {\n frameId: data.Meta.mainFrameId,\n navigation,\n navigationId,\n };\n const insight = TraceModel.Insights.InsightRunners.DocumentLatency.generateInsight(data, context);\n assert.strictEqual(insight.uncompressedResponseBytes, 39799);\n assert.deepEqual(insight.metricSavings, {FCP: 0, LCP: 0});\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"DocumentLatency.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/DocumentLatency.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {createContextForNavigation, getFirstOrError, getInsight} from '../../../testing/InsightHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Trace from '../trace.js';\nimport * as Types from '../types/types.js';\n\nexport async function processTrace(testContext: Mocha.Suite|Mocha.Context|null, traceFile: string) {\n const {parsedTrace, insights} = await TraceLoader.traceEngine(testContext, traceFile);\n if (!insights) {\n throw new Error('No insights');\n }\n\n return {data: parsedTrace, insights};\n}\n\ndescribeWithEnvironment('DocumentLatency', function() {\n it('reports savings for main document with redirects', async () => {\n const {data, insights} = await processTrace(this, 'lantern/redirect/trace.json.gz');\n const insight =\n getInsight('DocumentLatency', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values()));\n assert.strictEqual(insight.data?.redirectDuration, 1779);\n assert.deepEqual(insight.metricSavings, {FCP: 1779, LCP: 1779});\n });\n\n it('reports no savings for server with low response time', async () => {\n const {data, insights} = await processTrace(this, 'lantern/paul/trace.json.gz');\n const insight =\n getInsight('DocumentLatency', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values()));\n assert.strictEqual(insight.data?.serverResponseTime, 43);\n assert(!insight.data?.serverResponseTooSlow);\n assert.deepEqual(insight.metricSavings, {FCP: 0, LCP: 0});\n });\n\n it('reports savings for server with high response time', async function() {\n const traceEvents = [...await TraceLoader.rawEvents(this, 'lantern/paul/trace.json.gz')];\n const processor = Trace.Processor.TraceProcessor.createWithAllHandlers();\n\n const mainRequestEventIndex = traceEvents.findIndex(e => e.name === 'ResourceReceiveResponse');\n const mainRequestEvent = structuredClone(traceEvents[mainRequestEventIndex]);\n assert(Types.Events.isResourceReceiveResponse(mainRequestEvent));\n assert.strictEqual(mainRequestEvent.args.data.requestId, '1000C0FDC0A75327167272FC7438E999');\n if (!mainRequestEvent.args.data.timing) {\n throw new Error('missing timing field');\n }\n mainRequestEvent.args.data.timing.receiveHeadersStart =\n Types.Timing.MilliSeconds(mainRequestEvent.args.data.timing.receiveHeadersStart + 1000);\n traceEvents[mainRequestEventIndex] = mainRequestEvent;\n\n await processor.parse(traceEvents);\n const data = processor.parsedTrace;\n if (!data) {\n throw new Error('missing parsedTrace');\n }\n\n const navigation = getFirstOrError(data.Meta.navigationsByNavigationId.values());\n const context = createContextForNavigation(navigation, data.Meta.mainFrameId);\n const insight = Trace.Insights.InsightRunners.DocumentLatency.generateInsight(data, context);\n assert.strictEqual(insight.data?.serverResponseTime, 1043);\n assert(insight.data?.serverResponseTooSlow);\n assert.deepEqual(insight.metricSavings, {FCP: 943, LCP: 943});\n });\n\n it('reports no compression savings for compressed text', async () => {\n const {data, insights} = await processTrace(this, 'lantern/paul/trace.json.gz');\n const insight =\n getInsight('DocumentLatency', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values()));\n assert.strictEqual(insight.data?.uncompressedResponseBytes, 0);\n assert.deepEqual(insight.metricSavings, {FCP: 0, LCP: 0});\n });\n\n it('reports compression savings for uncompressed text', async function() {\n const traceEvents = [...await TraceLoader.rawEvents(this, 'lantern/paul/trace.json.gz')];\n const processor = Trace.Processor.TraceProcessor.createWithAllHandlers();\n\n const mainRequestEventIndex = traceEvents.findIndex(e => e.name === 'ResourceReceiveResponse');\n const mainRequestEvent = structuredClone(traceEvents[mainRequestEventIndex]);\n assert(Types.Events.isResourceReceiveResponse(mainRequestEvent));\n assert.strictEqual(mainRequestEvent.args.data.requestId, '1000C0FDC0A75327167272FC7438E999');\n // Delete content-encoding header.\n mainRequestEvent.args.data.headers = mainRequestEvent.args.data.headers?.filter(h => h.name !== 'content-encoding');\n traceEvents[mainRequestEventIndex] = mainRequestEvent;\n\n await processor.parse(traceEvents);\n const data = processor.parsedTrace;\n if (!data) {\n throw new Error('missing parsedTrace');\n }\n\n const navigation = getFirstOrError(data.Meta.navigationsByNavigationId.values());\n const context = createContextForNavigation(navigation, data.Meta.mainFrameId);\n const insight = Trace.Insights.InsightRunners.DocumentLatency.generateInsight(data, context);\n assert.strictEqual(insight.data?.uncompressedResponseBytes, 39799);\n assert.deepEqual(insight.metricSavings, {FCP: 0, LCP: 0});\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/FontDisplay.d.ts b/public/models/trace/insights/FontDisplay.d.ts new file mode 100644 index 000000000..b3a342eb1 --- /dev/null +++ b/public/models/trace/insights/FontDisplay.d.ts @@ -0,0 +1,11 @@ +import * as Types from '../types/types.js'; +import { type InsightResult, type InsightSetContext, type RequiredData } from './types.js'; +export declare function deps(): ['Meta', 'NetworkRequests', 'LayoutShifts']; +export type FontDisplayResult = InsightResult<{ + fonts: Array<{ + request: Types.Events.SyntheticNetworkRequest; + display: string; + wastedTime: Types.Timing.MilliSeconds; + }>; +}>; +export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): FontDisplayResult; diff --git a/public/models/trace/insights/FontDisplay.js b/public/models/trace/insights/FontDisplay.js new file mode 100644 index 000000000..370d2884b --- /dev/null +++ b/public/models/trace/insights/FontDisplay.js @@ -0,0 +1,45 @@ +// Copyright 2024 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 * as Platform from '../../../core/platform/platform.js'; +import * as Helpers from '../helpers/helpers.js'; +import * as Types from '../types/types.js'; +export function deps() { + return ['Meta', 'NetworkRequests', 'LayoutShifts']; +} +export function generateInsight(parsedTrace, context) { + // TODO(b/366049346) make this work w/o a navigation. + if (!context.navigation) { + return { fonts: [] }; + } + const remoteFontLoadEvents = []; + for (const event of parsedTrace.LayoutShifts.beginRemoteFontLoadEvents) { + const navigation = Helpers.Trace.getNavigationForTraceEvent(event, context.frameId, parsedTrace.Meta.navigationsByFrameId); + if (navigation === context.navigation) { + remoteFontLoadEvents.push(event); + } + } + const fonts = []; + for (const event of remoteFontLoadEvents) { + const requestId = `${event.pid}.${event.args.id}`; + const request = parsedTrace.NetworkRequests.byId.get(requestId); + if (!request) { + continue; + } + const display = event.args.display; + let wastedTime = Types.Timing.MilliSeconds(0); + if (/^(block|fallback|auto)$/.test(display)) { + const wastedTimeMicro = Types.Timing.MicroSeconds(request.args.data.syntheticData.finishTime - request.args.data.syntheticData.sendStartTime); + wastedTime = Platform.NumberUtilities.floor(Helpers.Timing.microSecondsToMilliseconds(wastedTimeMicro), 1 / 5); + } + fonts.push({ + request, + display, + wastedTime, + }); + } + return { + fonts, + }; +} +//# sourceMappingURL=FontDisplay.js.map \ No newline at end of file diff --git a/public/models/trace/insights/FontDisplay.js.map b/public/models/trace/insights/FontDisplay.js.map new file mode 100644 index 000000000..32bb82a52 --- /dev/null +++ b/public/models/trace/insights/FontDisplay.js.map @@ -0,0 +1 @@ +{"version":3,"file":"FontDisplay.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/FontDisplay.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,QAAQ,MAAM,oCAAoC,CAAC;AAC/D,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAI3C,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,MAAM,EAAE,iBAAiB,EAAE,cAAc,CAAC,CAAC;AACrD,CAAC;AAUD,MAAM,UAAU,eAAe,CAAC,WAAsC,EAAE,OAA0B;IAChG,qDAAqD;IACrD,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QACxB,OAAO,EAAC,KAAK,EAAE,EAAE,EAAC,CAAC;IACrB,CAAC;IAED,MAAM,oBAAoB,GAAG,EAAE,CAAC;IAChC,KAAK,MAAM,KAAK,IAAI,WAAW,CAAC,YAAY,CAAC,yBAAyB,EAAE,CAAC;QACvE,MAAM,UAAU,GACZ,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC5G,IAAI,UAAU,KAAK,OAAO,CAAC,UAAU,EAAE,CAAC;YACtC,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,MAAM,KAAK,GAAG,EAAE,CAAC;IACjB,KAAK,MAAM,KAAK,IAAI,oBAAoB,EAAE,CAAC;QACzC,MAAM,SAAS,GAAG,GAAG,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QAClD,MAAM,OAAO,GAAG,WAAW,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAChE,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,SAAS;QACX,CAAC;QAED,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC;QACnC,IAAI,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAE9C,IAAI,yBAAyB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5C,MAAM,eAAe,GAAG,KAAK,CAAC,MAAM,CAAC,YAAY,CAC7C,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;YAChG,UAAU,GAAG,QAAQ,CAAC,eAAe,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,eAAe,CAAC,EAAE,CAAC,GAAG,CAAC,CAChF,CAAC;QAChC,CAAC;QAED,KAAK,CAAC,IAAI,CAAC;YACT,OAAO;YACP,OAAO;YACP,UAAU;SACX,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,KAAK;KACN,CAAC;AACJ,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {type InsightResult, type InsightSetContext, type RequiredData} from './types.js';\n\nexport function deps(): ['Meta', 'NetworkRequests', 'LayoutShifts'] {\n return ['Meta', 'NetworkRequests', 'LayoutShifts'];\n}\n\nexport type FontDisplayResult = InsightResult<{\n fonts: Array<{\n request: Types.Events.SyntheticNetworkRequest,\n display: string,\n wastedTime: Types.Timing.MilliSeconds,\n }>,\n}>;\n\nexport function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): FontDisplayResult {\n // TODO(b/366049346) make this work w/o a navigation.\n if (!context.navigation) {\n return {fonts: []};\n }\n\n const remoteFontLoadEvents = [];\n for (const event of parsedTrace.LayoutShifts.beginRemoteFontLoadEvents) {\n const navigation =\n Helpers.Trace.getNavigationForTraceEvent(event, context.frameId, parsedTrace.Meta.navigationsByFrameId);\n if (navigation === context.navigation) {\n remoteFontLoadEvents.push(event);\n }\n }\n\n const fonts = [];\n for (const event of remoteFontLoadEvents) {\n const requestId = `${event.pid}.${event.args.id}`;\n const request = parsedTrace.NetworkRequests.byId.get(requestId);\n if (!request) {\n continue;\n }\n\n const display = event.args.display;\n let wastedTime = Types.Timing.MilliSeconds(0);\n\n if (/^(block|fallback|auto)$/.test(display)) {\n const wastedTimeMicro = Types.Timing.MicroSeconds(\n request.args.data.syntheticData.finishTime - request.args.data.syntheticData.sendStartTime);\n wastedTime = Platform.NumberUtilities.floor(Helpers.Timing.microSecondsToMilliseconds(wastedTimeMicro), 1 / 5) as\n Types.Timing.MilliSeconds;\n }\n\n fonts.push({\n request,\n display,\n wastedTime,\n });\n }\n\n return {\n fonts,\n };\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/FontDisplay.test.d.ts b/public/models/trace/insights/FontDisplay.test.d.ts new file mode 100644 index 000000000..29614938e --- /dev/null +++ b/public/models/trace/insights/FontDisplay.test.d.ts @@ -0,0 +1,4 @@ +export declare function processTrace(testContext: Mocha.Suite | Mocha.Context | null, traceFile: string): Promise<{ + data: Readonly>; + insights: import("./types.js").TraceInsightSets; +}>; diff --git a/public/models/trace/insights/FontDisplay.test.js b/public/models/trace/insights/FontDisplay.test.js new file mode 100644 index 000000000..2c239577a --- /dev/null +++ b/public/models/trace/insights/FontDisplay.test.js @@ -0,0 +1,59 @@ +// Copyright 2024 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 { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; +import { getFirstOrError, getInsight } from '../../../testing/InsightHelpers.js'; +import { TraceLoader } from '../../../testing/TraceLoader.js'; +export async function processTrace(testContext, traceFile) { + const { parsedTrace, insights } = await TraceLoader.traceEngine(testContext, traceFile); + if (!insights) { + throw new Error('No insights'); + } + return { data: parsedTrace, insights }; +} +describeWithEnvironment('FontDisplay', function () { + it('finds no requests for remote fonts', async () => { + const { data, insights } = await processTrace(this, 'load-simple.json.gz'); + assert.strictEqual(insights.size, 2); + const insight = getInsight('FontDisplay', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values())); + assert.strictEqual(insight.fonts.length, 0); + }); + it('finds requests for remote fonts', async () => { + const { data, insights } = await processTrace(this, 'font-display.json.gz'); + assert.strictEqual(insights.size, 1); + const insight = getInsight('FontDisplay', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values())); + assert.deepStrictEqual(insight.fonts.map(f => ({ ...f, request: f.request.args.data.url })), [ + { + request: 'https://fonts.gstatic.com/s/droidsans/v18/SlGVmQWMvZQIdix7AFxXkHNSbRYXags.woff2', + display: 'auto', + wastedTime: 15, + }, + { + request: 'https://fonts.gstatic.com/s/lato/v24/S6u9w4BMUTPHh6UVSwiPGQ3q5d0.woff2', + display: 'auto', + wastedTime: 10, + }, + { + request: 'https://fonts.gstatic.com/s/ptsans/v17/jizaRExUiTo99u79D0KExcOPIDU.woff2', + display: 'auto', + wastedTime: 20, + }, + { + request: 'https://fonts.gstatic.com/s/ptsans/v17/jizfRExUiTo99u79B_mh0O6tLR8a8zI.woff2', + display: 'auto', + wastedTime: 15, + }, + { + request: 'https://fonts.gstatic.com/s/droidsans/v18/SlGWmQWMvZQIdix7AFxXmMh3eDs1ZyHKpWg.woff2', + display: 'auto', + wastedTime: 15, + }, + { + request: 'https://fonts.gstatic.com/s/ptserif/v18/EJRVQgYoZZY2vCFuvAFWzr-_dSb_.woff2', + display: 'auto', + wastedTime: 15, + }, + ]); + }); +}); +//# sourceMappingURL=FontDisplay.test.js.map \ No newline at end of file diff --git a/public/models/trace/insights/FontDisplay.test.js.map b/public/models/trace/insights/FontDisplay.test.js.map new file mode 100644 index 000000000..ff455a059 --- /dev/null +++ b/public/models/trace/insights/FontDisplay.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"FontDisplay.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/FontDisplay.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,EAAC,uBAAuB,EAAC,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EAAC,eAAe,EAAE,UAAU,EAAC,MAAM,oCAAoC,CAAC;AAC/E,OAAO,EAAC,WAAW,EAAC,MAAM,iCAAiC,CAAC;AAE5D,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAA2C,EAAE,SAAiB;IAC/F,MAAM,EAAC,WAAW,EAAE,QAAQ,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IACtF,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,EAAC,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAC,CAAC;AACvC,CAAC;AAED,uBAAuB,CAAC,aAAa,EAAE;IACrC,EAAE,CAAC,oCAAoC,EAAE,KAAK,IAAI,EAAE;QAClD,MAAM,EAAC,IAAI,EAAE,QAAQ,EAAC,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,qBAAqB,CAAC,CAAC;QACzE,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACrC,MAAM,OAAO,GAAG,UAAU,CAAC,aAAa,EAAE,QAAQ,EAAE,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAEnH,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QAC/C,MAAM,EAAC,IAAI,EAAE,QAAQ,EAAC,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC;QAC1E,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACrC,MAAM,OAAO,GAAG,UAAU,CAAC,aAAa,EAAE,QAAQ,EAAE,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAEnH,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAC,GAAG,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAC,CAAC,CAAC,EAAE;YACzF;gBACE,OAAO,EAAE,iFAAiF;gBAC1F,OAAO,EAAE,MAAM;gBACf,UAAU,EAAE,EAAE;aACf;YACD;gBACE,OAAO,EAAE,wEAAwE;gBACjF,OAAO,EAAE,MAAM;gBACf,UAAU,EAAE,EAAE;aACf;YACD;gBACE,OAAO,EAAE,0EAA0E;gBACnF,OAAO,EAAE,MAAM;gBACf,UAAU,EAAE,EAAE;aACf;YACD;gBACE,OAAO,EAAE,8EAA8E;gBACvF,OAAO,EAAE,MAAM;gBACf,UAAU,EAAE,EAAE;aACf;YACD;gBACE,OAAO,EAAE,qFAAqF;gBAC9F,OAAO,EAAE,MAAM;gBACf,UAAU,EAAE,EAAE;aACf;YACD;gBACE,OAAO,EAAE,4EAA4E;gBACrF,OAAO,EAAE,MAAM;gBACf,UAAU,EAAE,EAAE;aACf;SACF,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {getFirstOrError, getInsight} from '../../../testing/InsightHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\n\nexport async function processTrace(testContext: Mocha.Suite|Mocha.Context|null, traceFile: string) {\n const {parsedTrace, insights} = await TraceLoader.traceEngine(testContext, traceFile);\n if (!insights) {\n throw new Error('No insights');\n }\n\n return {data: parsedTrace, insights};\n}\n\ndescribeWithEnvironment('FontDisplay', function() {\n it('finds no requests for remote fonts', async () => {\n const {data, insights} = await processTrace(this, 'load-simple.json.gz');\n assert.strictEqual(insights.size, 2);\n const insight = getInsight('FontDisplay', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values()));\n\n assert.strictEqual(insight.fonts.length, 0);\n });\n\n it('finds requests for remote fonts', async () => {\n const {data, insights} = await processTrace(this, 'font-display.json.gz');\n assert.strictEqual(insights.size, 1);\n const insight = getInsight('FontDisplay', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values()));\n\n assert.deepStrictEqual(insight.fonts.map(f => ({...f, request: f.request.args.data.url})), [\n {\n request: 'https://fonts.gstatic.com/s/droidsans/v18/SlGVmQWMvZQIdix7AFxXkHNSbRYXags.woff2',\n display: 'auto',\n wastedTime: 15,\n },\n {\n request: 'https://fonts.gstatic.com/s/lato/v24/S6u9w4BMUTPHh6UVSwiPGQ3q5d0.woff2',\n display: 'auto',\n wastedTime: 10,\n },\n {\n request: 'https://fonts.gstatic.com/s/ptsans/v17/jizaRExUiTo99u79D0KExcOPIDU.woff2',\n display: 'auto',\n wastedTime: 20,\n },\n {\n request: 'https://fonts.gstatic.com/s/ptsans/v17/jizfRExUiTo99u79B_mh0O6tLR8a8zI.woff2',\n display: 'auto',\n wastedTime: 15,\n },\n {\n request: 'https://fonts.gstatic.com/s/droidsans/v18/SlGWmQWMvZQIdix7AFxXmMh3eDs1ZyHKpWg.woff2',\n display: 'auto',\n wastedTime: 15,\n },\n {\n request: 'https://fonts.gstatic.com/s/ptserif/v18/EJRVQgYoZZY2vCFuvAFWzr-_dSb_.woff2',\n display: 'auto',\n wastedTime: 15,\n },\n ]);\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/InsightRunners.d.ts b/public/models/trace/insights/InsightRunners.d.ts index f99ffa134..a2f4a2474 100644 --- a/public/models/trace/insights/InsightRunners.d.ts +++ b/public/models/trace/insights/InsightRunners.d.ts @@ -1,5 +1,6 @@ export * as CumulativeLayoutShift from './CumulativeLayoutShift.js'; export * as DocumentLatency from './DocumentLatency.js'; +export * as FontDisplay from './FontDisplay.js'; export * as InteractionToNextPaint from './InteractionToNextPaint.js'; export * as LargestContentfulPaint from './LargestContentfulPaint.js'; export * as RenderBlocking from './RenderBlocking.js'; diff --git a/public/models/trace/insights/InsightRunners.js b/public/models/trace/insights/InsightRunners.js index 56582047d..65f913ae4 100644 --- a/public/models/trace/insights/InsightRunners.js +++ b/public/models/trace/insights/InsightRunners.js @@ -3,6 +3,7 @@ // found in the LICENSE file. export * as CumulativeLayoutShift from './CumulativeLayoutShift.js'; export * as DocumentLatency from './DocumentLatency.js'; +export * as FontDisplay from './FontDisplay.js'; export * as InteractionToNextPaint from './InteractionToNextPaint.js'; export * as LargestContentfulPaint from './LargestContentfulPaint.js'; export * as RenderBlocking from './RenderBlocking.js'; diff --git a/public/models/trace/insights/InsightRunners.js.map b/public/models/trace/insights/InsightRunners.js.map index 7edecb767..e4677a716 100644 --- a/public/models/trace/insights/InsightRunners.js.map +++ b/public/models/trace/insights/InsightRunners.js.map @@ -1 +1 @@ -{"version":3,"file":"InsightRunners.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/InsightRunners.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,qBAAqB,MAAM,4BAA4B,CAAC;AACpE,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,sBAAsB,MAAM,6BAA6B,CAAC;AACtE,OAAO,KAAK,sBAAsB,MAAM,6BAA6B,CAAC;AACtE,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,aAAa,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nexport * as CumulativeLayoutShift from './CumulativeLayoutShift.js';\nexport * as DocumentLatency from './DocumentLatency.js';\nexport * as InteractionToNextPaint from './InteractionToNextPaint.js';\nexport * as LargestContentfulPaint from './LargestContentfulPaint.js';\nexport * as RenderBlocking from './RenderBlocking.js';\nexport * as SlowCSSSelector from './SlowCSSSelector.js';\nexport * as ThirdPartyWeb from './ThirdPartyWeb.js';\nexport * as Viewport from './Viewport.js';\n"]} \ No newline at end of file +{"version":3,"file":"InsightRunners.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/InsightRunners.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,qBAAqB,MAAM,4BAA4B,CAAC;AACpE,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC;AAChD,OAAO,KAAK,sBAAsB,MAAM,6BAA6B,CAAC;AACtE,OAAO,KAAK,sBAAsB,MAAM,6BAA6B,CAAC;AACtE,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,aAAa,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nexport * as CumulativeLayoutShift from './CumulativeLayoutShift.js';\nexport * as DocumentLatency from './DocumentLatency.js';\nexport * as FontDisplay from './FontDisplay.js';\nexport * as InteractionToNextPaint from './InteractionToNextPaint.js';\nexport * as LargestContentfulPaint from './LargestContentfulPaint.js';\nexport * as RenderBlocking from './RenderBlocking.js';\nexport * as SlowCSSSelector from './SlowCSSSelector.js';\nexport * as ThirdPartyWeb from './ThirdPartyWeb.js';\nexport * as Viewport from './Viewport.js';\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/InteractionToNextPaint.d.ts b/public/models/trace/insights/InteractionToNextPaint.d.ts index edac9b93e..bed616d20 100644 --- a/public/models/trace/insights/InteractionToNextPaint.d.ts +++ b/public/models/trace/insights/InteractionToNextPaint.d.ts @@ -1,8 +1,8 @@ import { type SyntheticInteractionPair } from '../types/TraceEvents.js'; -import { type InsightResult, type NavigationInsightContext, type RequiredData } from './types.js'; +import { type InsightResult, type InsightSetContext, type RequiredData } from './types.js'; export declare function deps(): ['UserInteractions']; export type INPInsightResult = InsightResult<{ longestInteractionEvent?: SyntheticInteractionPair; highPercentileInteractionEvent?: SyntheticInteractionPair; }>; -export declare function generateInsight(traceParsedData: RequiredData, context: NavigationInsightContext): INPInsightResult; +export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): INPInsightResult; diff --git a/public/models/trace/insights/InteractionToNextPaint.js b/public/models/trace/insights/InteractionToNextPaint.js index 55396c32b..30ccb907e 100644 --- a/public/models/trace/insights/InteractionToNextPaint.js +++ b/public/models/trace/insights/InteractionToNextPaint.js @@ -1,12 +1,13 @@ // Copyright 2024 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 * as Helpers from '../helpers/helpers.js'; export function deps() { return ['UserInteractions']; } -export function generateInsight(traceParsedData, context) { - const interactionEvents = traceParsedData.UserInteractions.interactionEvents.filter(event => { - return event.args.data.navigationId === context.navigationId; +export function generateInsight(parsedTrace, context) { + const interactionEvents = parsedTrace.UserInteractions.interactionEvents.filter(event => { + return Helpers.Timing.eventIsInBounds(event, context.bounds); }); if (!interactionEvents.length) { // A valid result, when there is no user interaction. diff --git a/public/models/trace/insights/InteractionToNextPaint.js.map b/public/models/trace/insights/InteractionToNextPaint.js.map index f21c77da9..608c6dc01 100644 --- a/public/models/trace/insights/InteractionToNextPaint.js.map +++ b/public/models/trace/insights/InteractionToNextPaint.js.map @@ -1 +1 @@ -{"version":3,"file":"InteractionToNextPaint.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/InteractionToNextPaint.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAM7B,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAC9B,CAAC;AAOD,MAAM,UAAU,eAAe,CAC3B,eAA0C,EAAE,OAAiC;IAC/E,MAAM,iBAAiB,GAAG,eAAe,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;QAC1F,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,KAAK,OAAO,CAAC,YAAY,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,CAAC;QAC9B,qDAAqD;QACrD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,sBAAsB,GAAG,IAAI,GAAG,EAAoC,CAAC;IAC3E,KAAK,MAAM,KAAK,IAAI,iBAAiB,EAAE,CAAC;QACtC,MAAM,GAAG,GAAG,KAAK,CAAC,aAAa,CAAC;QAChC,MAAM,OAAO,GAAG,sBAAsB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAChD,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;YACxC,sBAAsB,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IACD,MAAM,2BAA2B,GAAG,CAAC,GAAG,sBAAsB,CAAC,MAAM,EAAE,CAAC,CAAC;IACzE,2BAA2B,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IAE1D,6EAA6E;IAC7E,+EAA+E;IAC/E,6EAA6E;IAC7E,iMAAiM;IACjM,MAAM,mBAAmB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,2BAA2B,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC;IAE7F,OAAO;QACL,uBAAuB,EAAE,2BAA2B,CAAC,CAAC,CAAC;QACvD,8BAA8B,EAAE,2BAA2B,CAAC,mBAAmB,CAAC;KACjF,CAAC;AACJ,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {type SyntheticInteractionPair} from '../types/TraceEvents.js';\n\nimport {type InsightResult, type NavigationInsightContext, type RequiredData} from './types.js';\n\nexport function deps(): ['UserInteractions'] {\n return ['UserInteractions'];\n}\n\nexport type INPInsightResult = InsightResult<{\n longestInteractionEvent?: SyntheticInteractionPair,\n highPercentileInteractionEvent?: SyntheticInteractionPair,\n}>;\n\nexport function generateInsight(\n traceParsedData: RequiredData, context: NavigationInsightContext): INPInsightResult {\n const interactionEvents = traceParsedData.UserInteractions.interactionEvents.filter(event => {\n return event.args.data.navigationId === context.navigationId;\n });\n\n if (!interactionEvents.length) {\n // A valid result, when there is no user interaction.\n return {};\n }\n\n const longestByInteractionId = new Map();\n for (const event of interactionEvents) {\n const key = event.interactionId;\n const longest = longestByInteractionId.get(key);\n if (!longest || event.dur > longest.dur) {\n longestByInteractionId.set(key, event);\n }\n }\n const normalizedInteractionEvents = [...longestByInteractionId.values()];\n normalizedInteractionEvents.sort((a, b) => b.dur - a.dur);\n\n // INP is the \"nearest-rank\"/inverted_cdf 98th percentile, except Chrome only\n // keeps the 10 worst events around, so it can never be more than the 10th from\n // last array element. To keep things simpler, sort desc and pick from front.\n // See https://source.chromium.org/chromium/chromium/src/+/main:components/page_load_metrics/browser/responsiveness_metrics_normalization.cc;l=45-59;drc=cb0f9c8b559d9c7c3cb4ca94fc1118cc015d38ad\n const highPercentileIndex = Math.min(9, Math.floor(normalizedInteractionEvents.length / 50));\n\n return {\n longestInteractionEvent: normalizedInteractionEvents[0],\n highPercentileInteractionEvent: normalizedInteractionEvents[highPercentileIndex],\n };\n}\n"]} \ No newline at end of file +{"version":3,"file":"InteractionToNextPaint.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/InteractionToNextPaint.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AAKjD,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAC9B,CAAC;AAOD,MAAM,UAAU,eAAe,CAAC,WAAsC,EAAE,OAA0B;IAChG,MAAM,iBAAiB,GAAG,WAAW,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;QACtF,OAAO,OAAO,CAAC,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,iBAAiB,CAAC,MAAM,EAAE,CAAC;QAC9B,qDAAqD;QACrD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,sBAAsB,GAAG,IAAI,GAAG,EAAoC,CAAC;IAC3E,KAAK,MAAM,KAAK,IAAI,iBAAiB,EAAE,CAAC;QACtC,MAAM,GAAG,GAAG,KAAK,CAAC,aAAa,CAAC;QAChC,MAAM,OAAO,GAAG,sBAAsB,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAChD,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;YACxC,sBAAsB,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IACD,MAAM,2BAA2B,GAAG,CAAC,GAAG,sBAAsB,CAAC,MAAM,EAAE,CAAC,CAAC;IACzE,2BAA2B,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IAE1D,6EAA6E;IAC7E,+EAA+E;IAC/E,6EAA6E;IAC7E,iMAAiM;IACjM,MAAM,mBAAmB,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,2BAA2B,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC;IAE7F,OAAO;QACL,uBAAuB,EAAE,2BAA2B,CAAC,CAAC,CAAC;QACvD,8BAA8B,EAAE,2BAA2B,CAAC,mBAAmB,CAAC;KACjF,CAAC;AACJ,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Helpers from '../helpers/helpers.js';\nimport {type SyntheticInteractionPair} from '../types/TraceEvents.js';\n\nimport {type InsightResult, type InsightSetContext, type RequiredData} from './types.js';\n\nexport function deps(): ['UserInteractions'] {\n return ['UserInteractions'];\n}\n\nexport type INPInsightResult = InsightResult<{\n longestInteractionEvent?: SyntheticInteractionPair,\n highPercentileInteractionEvent?: SyntheticInteractionPair,\n}>;\n\nexport function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): INPInsightResult {\n const interactionEvents = parsedTrace.UserInteractions.interactionEvents.filter(event => {\n return Helpers.Timing.eventIsInBounds(event, context.bounds);\n });\n\n if (!interactionEvents.length) {\n // A valid result, when there is no user interaction.\n return {};\n }\n\n const longestByInteractionId = new Map();\n for (const event of interactionEvents) {\n const key = event.interactionId;\n const longest = longestByInteractionId.get(key);\n if (!longest || event.dur > longest.dur) {\n longestByInteractionId.set(key, event);\n }\n }\n const normalizedInteractionEvents = [...longestByInteractionId.values()];\n normalizedInteractionEvents.sort((a, b) => b.dur - a.dur);\n\n // INP is the \"nearest-rank\"/inverted_cdf 98th percentile, except Chrome only\n // keeps the 10 worst events around, so it can never be more than the 10th from\n // last array element. To keep things simpler, sort desc and pick from front.\n // See https://source.chromium.org/chromium/chromium/src/+/main:components/page_load_metrics/browser/responsiveness_metrics_normalization.cc;l=45-59;drc=cb0f9c8b559d9c7c3cb4ca94fc1118cc015d38ad\n const highPercentileIndex = Math.min(9, Math.floor(normalizedInteractionEvents.length / 50));\n\n return {\n longestInteractionEvent: normalizedInteractionEvents[0],\n highPercentileInteractionEvent: normalizedInteractionEvents[highPercentileIndex],\n };\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/InteractionToNextPaint.test.d.ts b/public/models/trace/insights/InteractionToNextPaint.test.d.ts index cdc9b4ae2..aec4618f2 100644 --- a/public/models/trace/insights/InteractionToNextPaint.test.d.ts +++ b/public/models/trace/insights/InteractionToNextPaint.test.d.ts @@ -1,5 +1,5 @@ -import * as TraceModel from '../trace.js'; +import * as Trace from '../trace.js'; export declare function processTrace(testContext: Mocha.Suite | Mocha.Context | null, traceFile: string): Promise<{ - data: Readonly>; - insights: TraceModel.Insights.Types.TraceInsightData; + data: Readonly>; + insights: Trace.Insights.Types.TraceInsightSets; }>; diff --git a/public/models/trace/insights/InteractionToNextPaint.test.js b/public/models/trace/insights/InteractionToNextPaint.test.js index d6ef2dc7c..94d87c95f 100644 --- a/public/models/trace/insights/InteractionToNextPaint.test.js +++ b/public/models/trace/insights/InteractionToNextPaint.test.js @@ -2,14 +2,15 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; +import { createContextForNavigation, getFirst } from '../../../testing/InsightHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; -import * as TraceModel from '../trace.js'; +import * as Trace from '../trace.js'; export async function processTrace(testContext, traceFile) { - const { traceData, insights } = await TraceLoader.traceEngine(testContext, traceFile); + const { parsedTrace, insights } = await TraceLoader.traceEngine(testContext, traceFile); if (!insights) { throw new Error('No insights'); } - return { data: traceData, insights }; + return { data: parsedTrace, insights }; } describeWithEnvironment('InteractionToNextPaint', function () { const test = (traceFile, longest, highPercentile) => { @@ -18,16 +19,12 @@ describeWithEnvironment('InteractionToNextPaint', function () { } it(`process ${traceFile}`, async () => { const { data } = await processTrace(this, traceFile); - // TODO(crbug.com/313905799): The traces don't all have navigations, and currently #computeInsights - // doesn't account for analyzing stuff outside a navigation bound. So instead of this ... - // const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value); - // we manually run the insight. - const [navigationId, navigation] = data.Meta.navigationsByNavigationId.entries().next().value ?? []; - const insight = TraceModel.Insights.InsightRunners.InteractionToNextPaint.generateInsight(data, { + const navigation = getFirst(data.Meta.navigationsByNavigationId.values()); + const context = navigation ? createContextForNavigation(navigation, data.Meta.mainFrameId) : { + bounds: data.Meta.traceBounds, frameId: data.Meta.mainFrameId, - navigation, - navigationId, - }); + }; + const insight = Trace.Insights.InsightRunners.InteractionToNextPaint.generateInsight(data, context); assert.strictEqual(insight.longestInteractionEvent?.dur, longest); assert.strictEqual(insight.highPercentileInteractionEvent?.dur, highPercentile); }); diff --git a/public/models/trace/insights/InteractionToNextPaint.test.js.map b/public/models/trace/insights/InteractionToNextPaint.test.js.map index 1c4d8af04..4f362e863 100644 --- a/public/models/trace/insights/InteractionToNextPaint.test.js.map +++ b/public/models/trace/insights/InteractionToNextPaint.test.js.map @@ -1 +1 @@ -{"version":3,"file":"InteractionToNextPaint.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/InteractionToNextPaint.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,EAAC,uBAAuB,EAAC,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EAAC,WAAW,EAAC,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,UAAU,MAAM,aAAa,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAA2C,EAAE,SAAiB;IAC/F,MAAM,EAAC,SAAS,EAAE,QAAQ,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IACpF,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,EAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAC,CAAC;AACrC,CAAC;AAED,uBAAuB,CAAC,wBAAwB,EAAE;IAChD,MAAM,IAAI,GAAG,CAAC,SAAiB,EAAE,OAAgB,EAAE,cAAuB,EAAE,EAAE;QAC5E,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;YACjC,cAAc,GAAG,OAAO,CAAC;QAC3B,CAAC;QAED,EAAE,CAAC,WAAW,SAAS,EAAE,EAAE,KAAK,IAAI,EAAE;YACpC,MAAM,EAAC,IAAI,EAAC,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YAEnD,mGAAmG;YACnG,yFAAyF;YACzF,sGAAsG;YACtG,+BAA+B;YAC/B,MAAM,CAAC,YAAY,EAAE,UAAU,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;YACpG,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,CAAC,cAAc,CAAC,sBAAsB,CAAC,eAAe,CAAC,IAAI,EAAE;gBAC9F,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW;gBAC9B,UAAU;gBACV,YAAY;aACb,CAAC,CAAC;YACH,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,uBAAuB,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;YAClE,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,8BAA8B,EAAE,GAAG,EAAE,cAAc,CAAC,CAAC;QAClF,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,CAAC;IACtC,IAAI,CAAC,kCAAkC,EAAE,MAAM,CAAC,CAAC;IACjD,IAAI,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;IAC3C,IAAI,CAAC,uCAAuC,EAAE,MAAM,CAAC,CAAC;AACxD,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as TraceModel from '../trace.js';\n\nexport async function processTrace(testContext: Mocha.Suite|Mocha.Context|null, traceFile: string) {\n const {traceData, insights} = await TraceLoader.traceEngine(testContext, traceFile);\n if (!insights) {\n throw new Error('No insights');\n }\n\n return {data: traceData, insights};\n}\n\ndescribeWithEnvironment('InteractionToNextPaint', function() {\n const test = (traceFile: string, longest?: number, highPercentile?: number) => {\n if (highPercentile === undefined) {\n highPercentile = longest;\n }\n\n it(`process ${traceFile}`, async () => {\n const {data} = await processTrace(this, traceFile);\n\n // TODO(crbug.com/313905799): The traces don't all have navigations, and currently #computeInsights\n // doesn't account for analyzing stuff outside a navigation bound. So instead of this ...\n // const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value);\n // we manually run the insight.\n const [navigationId, navigation] = data.Meta.navigationsByNavigationId.entries().next().value ?? [];\n const insight = TraceModel.Insights.InsightRunners.InteractionToNextPaint.generateInsight(data, {\n frameId: data.Meta.mainFrameId,\n navigation,\n navigationId,\n });\n assert.strictEqual(insight.longestInteractionEvent?.dur, longest);\n assert.strictEqual(insight.highPercentileInteractionEvent?.dur, highPercentile);\n });\n };\n\n test('lcp-images.json.gz', undefined);\n test('slow-interaction-keydown.json.gz', 163609);\n test('nested-interactions.json.gz', 23370);\n test('slow-interaction-button-click.json.gz', 139238);\n});\n"]} \ No newline at end of file +{"version":3,"file":"InteractionToNextPaint.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/InteractionToNextPaint.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,EAAC,uBAAuB,EAAC,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EAAC,0BAA0B,EAAE,QAAQ,EAAC,MAAM,oCAAoC,CAAC;AACxF,OAAO,EAAC,WAAW,EAAC,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,KAAK,MAAM,aAAa,CAAC;AAErC,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAA2C,EAAE,SAAiB;IAC/F,MAAM,EAAC,WAAW,EAAE,QAAQ,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IACtF,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,EAAC,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAC,CAAC;AACvC,CAAC;AAED,uBAAuB,CAAC,wBAAwB,EAAE;IAChD,MAAM,IAAI,GAAG,CAAC,SAAiB,EAAE,OAAgB,EAAE,cAAuB,EAAE,EAAE;QAC5E,IAAI,cAAc,KAAK,SAAS,EAAE,CAAC;YACjC,cAAc,GAAG,OAAO,CAAC;QAC3B,CAAC;QAED,EAAE,CAAC,WAAW,SAAS,EAAE,EAAE,KAAK,IAAI,EAAE;YACpC,MAAM,EAAC,IAAI,EAAC,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;YACnD,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,MAAM,EAAE,CAAC,CAAC;YAC1E,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC,0BAA0B,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;gBAC3F,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW;gBAC7B,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW;aAC/B,CAAC;YACF,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC,sBAAsB,CAAC,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACpG,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,uBAAuB,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;YAClE,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,8BAA8B,EAAE,GAAG,EAAE,cAAc,CAAC,CAAC;QAClF,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,IAAI,CAAC,oBAAoB,EAAE,SAAS,CAAC,CAAC;IACtC,IAAI,CAAC,kCAAkC,EAAE,MAAM,CAAC,CAAC;IACjD,IAAI,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;IAC3C,IAAI,CAAC,uCAAuC,EAAE,MAAM,CAAC,CAAC;AACxD,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {createContextForNavigation, getFirst} from '../../../testing/InsightHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Trace from '../trace.js';\n\nexport async function processTrace(testContext: Mocha.Suite|Mocha.Context|null, traceFile: string) {\n const {parsedTrace, insights} = await TraceLoader.traceEngine(testContext, traceFile);\n if (!insights) {\n throw new Error('No insights');\n }\n\n return {data: parsedTrace, insights};\n}\n\ndescribeWithEnvironment('InteractionToNextPaint', function() {\n const test = (traceFile: string, longest?: number, highPercentile?: number) => {\n if (highPercentile === undefined) {\n highPercentile = longest;\n }\n\n it(`process ${traceFile}`, async () => {\n const {data} = await processTrace(this, traceFile);\n const navigation = getFirst(data.Meta.navigationsByNavigationId.values());\n const context = navigation ? createContextForNavigation(navigation, data.Meta.mainFrameId) : {\n bounds: data.Meta.traceBounds,\n frameId: data.Meta.mainFrameId,\n };\n const insight = Trace.Insights.InsightRunners.InteractionToNextPaint.generateInsight(data, context);\n assert.strictEqual(insight.longestInteractionEvent?.dur, longest);\n assert.strictEqual(insight.highPercentileInteractionEvent?.dur, highPercentile);\n });\n };\n\n test('lcp-images.json.gz', undefined);\n test('slow-interaction-keydown.json.gz', 163609);\n test('nested-interactions.json.gz', 23370);\n test('slow-interaction-button-click.json.gz', 139238);\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/LargestContentfulPaint.d.ts b/public/models/trace/insights/LargestContentfulPaint.d.ts index 2e33c958f..ddb07c965 100644 --- a/public/models/trace/insights/LargestContentfulPaint.d.ts +++ b/public/models/trace/insights/LargestContentfulPaint.d.ts @@ -1,5 +1,5 @@ import * as Types from '../types/types.js'; -import { type InsightResult, type NavigationInsightContext, type RequiredData } from './types.js'; +import { type InsightResult, type InsightSetContext, type RequiredData } from './types.js'; export declare function deps(): ['NetworkRequests', 'PageLoadMetrics', 'LargestImagePaint', 'Meta']; interface LCPPhases { /** @@ -30,8 +30,8 @@ export type LCPInsightResult = InsightResult<{ shouldIncreasePriorityHint?: boolean; shouldPreloadImage?: boolean; /** The network request for the LCP image, if there was one. */ - lcpRequest?: Types.TraceEvents.SyntheticNetworkRequest; + lcpRequest?: Types.Events.SyntheticNetworkRequest; earliestDiscoveryTimeTs?: Types.Timing.MicroSeconds; }>; -export declare function generateInsight(traceParsedData: RequiredData, context: NavigationInsightContext): LCPInsightResult; +export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): LCPInsightResult; export {}; diff --git a/public/models/trace/insights/LargestContentfulPaint.js b/public/models/trace/insights/LargestContentfulPaint.js index 70267c227..70089079d 100644 --- a/public/models/trace/insights/LargestContentfulPaint.js +++ b/public/models/trace/insights/LargestContentfulPaint.js @@ -36,9 +36,13 @@ function breakdownPhases(nav, docRequest, lcpMs, lcpRequest) { renderDelay, }; } -export function generateInsight(traceParsedData, context) { - const networkRequests = traceParsedData.NetworkRequests; - const frameMetrics = traceParsedData.PageLoadMetrics.metricScoresByFrameId.get(context.frameId); +export function generateInsight(parsedTrace, context) { + // TODO(crbug.com/366049346) make this work w/o a navigation. + if (!context.navigation) { + return {}; + } + const networkRequests = parsedTrace.NetworkRequests; + const frameMetrics = parsedTrace.PageLoadMetrics.metricScoresByFrameId.get(context.frameId); if (!frameMetrics) { throw new Error('no frame metrics'); } @@ -48,14 +52,14 @@ export function generateInsight(traceParsedData, context) { } const metricScore = navMetrics.get("LCP" /* Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP */); const lcpEvent = metricScore?.event; - if (!lcpEvent || !Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate(lcpEvent)) { + if (!lcpEvent || !Types.Events.isLargestContentfulPaintCandidate(lcpEvent)) { return { warnings: [InsightWarning.NO_LCP] }; } // This helps calculate the phases. const lcpMs = Helpers.Timing.microSecondsToMilliseconds(metricScore.timing); // This helps position things on the timeline's UI accurately for a trace. const lcpTs = metricScore.event?.ts ? Helpers.Timing.microSecondsToMilliseconds(metricScore.event?.ts) : undefined; - const lcpRequest = findLCPRequest(traceParsedData, context, lcpEvent); + const lcpRequest = findLCPRequest(parsedTrace, context, lcpEvent); const docRequest = networkRequests.byTime.find(req => req.args.data.requestId === context.navigationId); if (!docRequest) { return { lcpMs, lcpTs, warnings: [InsightWarning.NO_DOCUMENT_REQUEST] }; diff --git a/public/models/trace/insights/LargestContentfulPaint.js.map b/public/models/trace/insights/LargestContentfulPaint.js.map index 4bee9faf3..80b2262c7 100644 --- a/public/models/trace/insights/LargestContentfulPaint.js.map +++ b/public/models/trace/insights/LargestContentfulPaint.js.map @@ -1 +1 @@ -{"version":3,"file":"LargestContentfulPaint.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/LargestContentfulPaint.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {findLCPRequest} from './Common.js';\nimport {type InsightResult, InsightWarning, type NavigationInsightContext, type RequiredData} from './types.js';\n\nexport function deps(): ['NetworkRequests', 'PageLoadMetrics', 'LargestImagePaint', 'Meta'] {\n return ['NetworkRequests', 'PageLoadMetrics', 'LargestImagePaint', 'Meta'];\n}\n\ninterface LCPPhases {\n /**\n * The time between when the user initiates loading the page until when\n * the browser receives the first byte of the html response.\n */\n ttfb: Types.Timing.MilliSeconds;\n /**\n * The time between ttfb and the LCP request request being started.\n * For a text LCP, this is undefined given no request is loaded.\n */\n loadDelay?: Types.Timing.MilliSeconds;\n /**\n * The time it takes to load the LCP request.\n */\n loadTime?: Types.Timing.MilliSeconds;\n /**\n * The time between when the LCP request finishes loading and when\n * the LCP element is rendered.\n */\n renderDelay: Types.Timing.MilliSeconds;\n}\n\nexport type LCPInsightResult = InsightResult<{\n lcpMs?: Types.Timing.MilliSeconds,\n lcpTs?: Types.Timing.MilliSeconds,\n phases?: LCPPhases,\n shouldRemoveLazyLoading?: boolean,\n shouldIncreasePriorityHint?: boolean,\n shouldPreloadImage?: boolean,\n /** The network request for the LCP image, if there was one. */\n lcpRequest?: Types.TraceEvents.SyntheticNetworkRequest,\n earliestDiscoveryTimeTs?: Types.Timing.MicroSeconds,\n}>;\n\nfunction breakdownPhases(\n nav: Types.TraceEvents.TraceEventNavigationStart, docRequest: Types.TraceEvents.SyntheticNetworkRequest,\n lcpMs: Types.Timing.MilliSeconds, lcpRequest: Types.TraceEvents.SyntheticNetworkRequest|null): LCPPhases {\n const docReqTiming = docRequest.args.data.timing;\n if (!docReqTiming) {\n throw new Error('no timing for document request');\n }\n const firstDocByteTs = Helpers.Timing.secondsToMicroseconds(docReqTiming.requestTime) +\n Helpers.Timing.millisecondsToMicroseconds(docReqTiming.receiveHeadersStart);\n\n const firstDocByteTiming = Types.Timing.MicroSeconds(firstDocByteTs - nav.ts);\n const ttfb = Helpers.Timing.microSecondsToMilliseconds(firstDocByteTiming);\n let renderDelay = Types.Timing.MilliSeconds(lcpMs - ttfb);\n\n if (!lcpRequest) {\n return {ttfb, renderDelay};\n }\n\n const lcpStartTs = Types.Timing.MicroSeconds(lcpRequest.ts - nav.ts);\n const requestStart = Helpers.Timing.microSecondsToMilliseconds(lcpStartTs);\n\n const lcpReqEndTs = Types.Timing.MicroSeconds(lcpRequest.args.data.syntheticData.finishTime - nav.ts);\n const requestEnd = Helpers.Timing.microSecondsToMilliseconds(lcpReqEndTs);\n\n const loadDelay = Types.Timing.MilliSeconds(requestStart - ttfb);\n const loadTime = Types.Timing.MilliSeconds(requestEnd - requestStart);\n renderDelay = Types.Timing.MilliSeconds(lcpMs - requestEnd);\n\n return {\n ttfb,\n loadDelay,\n loadTime,\n renderDelay,\n };\n}\n\nexport function generateInsight(\n traceParsedData: RequiredData, context: NavigationInsightContext): LCPInsightResult {\n const networkRequests = traceParsedData.NetworkRequests;\n\n const frameMetrics = traceParsedData.PageLoadMetrics.metricScoresByFrameId.get(context.frameId);\n if (!frameMetrics) {\n throw new Error('no frame metrics');\n }\n\n const navMetrics = frameMetrics.get(context.navigationId);\n if (!navMetrics) {\n throw new Error('no navigation metrics');\n }\n const metricScore = navMetrics.get(Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP);\n const lcpEvent = metricScore?.event;\n if (!lcpEvent || !Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate(lcpEvent)) {\n return {warnings: [InsightWarning.NO_LCP]};\n }\n\n // This helps calculate the phases.\n const lcpMs = Helpers.Timing.microSecondsToMilliseconds(metricScore.timing);\n // This helps position things on the timeline's UI accurately for a trace.\n const lcpTs = metricScore.event?.ts ? Helpers.Timing.microSecondsToMilliseconds(metricScore.event?.ts) : undefined;\n const lcpRequest = findLCPRequest(traceParsedData, context, lcpEvent);\n const docRequest = networkRequests.byTime.find(req => req.args.data.requestId === context.navigationId);\n if (!docRequest) {\n return {lcpMs, lcpTs, warnings: [InsightWarning.NO_DOCUMENT_REQUEST]};\n }\n\n if (!lcpRequest) {\n return {\n lcpMs,\n lcpTs,\n phases: breakdownPhases(context.navigation, docRequest, lcpMs, lcpRequest),\n };\n }\n\n const imageLoadingAttr = lcpEvent.args.data?.loadingAttr;\n const imagePreloaded = lcpRequest?.args.data.isLinkPreload || lcpRequest?.args.data.initiator?.type === 'preload';\n const imageFetchPriorityHint = lcpRequest?.args.data.fetchPriorityHint;\n\n // This is the earliest discovery time an LCP request could have - it's TTFB.\n const earliestDiscoveryTime = docRequest && docRequest.args.data.timing ?\n Helpers.Timing.secondsToMicroseconds(docRequest.args.data.timing.requestTime) +\n Helpers.Timing.millisecondsToMicroseconds(docRequest.args.data.timing.receiveHeadersStart) :\n undefined;\n\n return {\n lcpMs,\n lcpTs,\n phases: breakdownPhases(context.navigation, docRequest, lcpMs, lcpRequest),\n shouldRemoveLazyLoading: imageLoadingAttr === 'lazy',\n shouldIncreasePriorityHint: imageFetchPriorityHint !== 'high',\n shouldPreloadImage: !imagePreloaded,\n lcpRequest,\n earliestDiscoveryTimeTs: earliestDiscoveryTime ? Types.Timing.MicroSeconds(earliestDiscoveryTime) : undefined,\n };\n}\n"]} \ No newline at end of file +{"version":3,"file":"LargestContentfulPaint.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/LargestContentfulPaint.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {findLCPRequest} from './Common.js';\nimport {type InsightResult, type InsightSetContext, InsightWarning, type RequiredData} from './types.js';\n\nexport function deps(): ['NetworkRequests', 'PageLoadMetrics', 'LargestImagePaint', 'Meta'] {\n return ['NetworkRequests', 'PageLoadMetrics', 'LargestImagePaint', 'Meta'];\n}\n\ninterface LCPPhases {\n /**\n * The time between when the user initiates loading the page until when\n * the browser receives the first byte of the html response.\n */\n ttfb: Types.Timing.MilliSeconds;\n /**\n * The time between ttfb and the LCP request request being started.\n * For a text LCP, this is undefined given no request is loaded.\n */\n loadDelay?: Types.Timing.MilliSeconds;\n /**\n * The time it takes to load the LCP request.\n */\n loadTime?: Types.Timing.MilliSeconds;\n /**\n * The time between when the LCP request finishes loading and when\n * the LCP element is rendered.\n */\n renderDelay: Types.Timing.MilliSeconds;\n}\n\nexport type LCPInsightResult = InsightResult<{\n lcpMs?: Types.Timing.MilliSeconds,\n lcpTs?: Types.Timing.MilliSeconds,\n phases?: LCPPhases,\n shouldRemoveLazyLoading?: boolean,\n shouldIncreasePriorityHint?: boolean,\n shouldPreloadImage?: boolean,\n /** The network request for the LCP image, if there was one. */\n lcpRequest?: Types.Events.SyntheticNetworkRequest,\n earliestDiscoveryTimeTs?: Types.Timing.MicroSeconds,\n}>;\n\nfunction breakdownPhases(\n nav: Types.Events.NavigationStart, docRequest: Types.Events.SyntheticNetworkRequest,\n lcpMs: Types.Timing.MilliSeconds, lcpRequest: Types.Events.SyntheticNetworkRequest|null): LCPPhases {\n const docReqTiming = docRequest.args.data.timing;\n if (!docReqTiming) {\n throw new Error('no timing for document request');\n }\n const firstDocByteTs = Helpers.Timing.secondsToMicroseconds(docReqTiming.requestTime) +\n Helpers.Timing.millisecondsToMicroseconds(docReqTiming.receiveHeadersStart);\n\n const firstDocByteTiming = Types.Timing.MicroSeconds(firstDocByteTs - nav.ts);\n const ttfb = Helpers.Timing.microSecondsToMilliseconds(firstDocByteTiming);\n let renderDelay = Types.Timing.MilliSeconds(lcpMs - ttfb);\n\n if (!lcpRequest) {\n return {ttfb, renderDelay};\n }\n\n const lcpStartTs = Types.Timing.MicroSeconds(lcpRequest.ts - nav.ts);\n const requestStart = Helpers.Timing.microSecondsToMilliseconds(lcpStartTs);\n\n const lcpReqEndTs = Types.Timing.MicroSeconds(lcpRequest.args.data.syntheticData.finishTime - nav.ts);\n const requestEnd = Helpers.Timing.microSecondsToMilliseconds(lcpReqEndTs);\n\n const loadDelay = Types.Timing.MilliSeconds(requestStart - ttfb);\n const loadTime = Types.Timing.MilliSeconds(requestEnd - requestStart);\n renderDelay = Types.Timing.MilliSeconds(lcpMs - requestEnd);\n\n return {\n ttfb,\n loadDelay,\n loadTime,\n renderDelay,\n };\n}\n\nexport function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): LCPInsightResult {\n // TODO(crbug.com/366049346) make this work w/o a navigation.\n if (!context.navigation) {\n return {};\n }\n\n const networkRequests = parsedTrace.NetworkRequests;\n\n const frameMetrics = parsedTrace.PageLoadMetrics.metricScoresByFrameId.get(context.frameId);\n if (!frameMetrics) {\n throw new Error('no frame metrics');\n }\n\n const navMetrics = frameMetrics.get(context.navigationId);\n if (!navMetrics) {\n throw new Error('no navigation metrics');\n }\n const metricScore = navMetrics.get(Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP);\n const lcpEvent = metricScore?.event;\n if (!lcpEvent || !Types.Events.isLargestContentfulPaintCandidate(lcpEvent)) {\n return {warnings: [InsightWarning.NO_LCP]};\n }\n\n // This helps calculate the phases.\n const lcpMs = Helpers.Timing.microSecondsToMilliseconds(metricScore.timing);\n // This helps position things on the timeline's UI accurately for a trace.\n const lcpTs = metricScore.event?.ts ? Helpers.Timing.microSecondsToMilliseconds(metricScore.event?.ts) : undefined;\n const lcpRequest = findLCPRequest(parsedTrace, context, lcpEvent);\n const docRequest = networkRequests.byTime.find(req => req.args.data.requestId === context.navigationId);\n if (!docRequest) {\n return {lcpMs, lcpTs, warnings: [InsightWarning.NO_DOCUMENT_REQUEST]};\n }\n\n if (!lcpRequest) {\n return {\n lcpMs,\n lcpTs,\n phases: breakdownPhases(context.navigation, docRequest, lcpMs, lcpRequest),\n };\n }\n\n const imageLoadingAttr = lcpEvent.args.data?.loadingAttr;\n const imagePreloaded = lcpRequest?.args.data.isLinkPreload || lcpRequest?.args.data.initiator?.type === 'preload';\n const imageFetchPriorityHint = lcpRequest?.args.data.fetchPriorityHint;\n\n // This is the earliest discovery time an LCP request could have - it's TTFB.\n const earliestDiscoveryTime = docRequest && docRequest.args.data.timing ?\n Helpers.Timing.secondsToMicroseconds(docRequest.args.data.timing.requestTime) +\n Helpers.Timing.millisecondsToMicroseconds(docRequest.args.data.timing.receiveHeadersStart) :\n undefined;\n\n return {\n lcpMs,\n lcpTs,\n phases: breakdownPhases(context.navigation, docRequest, lcpMs, lcpRequest),\n shouldRemoveLazyLoading: imageLoadingAttr === 'lazy',\n shouldIncreasePriorityHint: imageFetchPriorityHint !== 'high',\n shouldPreloadImage: !imagePreloaded,\n lcpRequest,\n earliestDiscoveryTimeTs: earliestDiscoveryTime ? Types.Timing.MicroSeconds(earliestDiscoveryTime) : undefined,\n };\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/LargestContentfulPaint.test.d.ts b/public/models/trace/insights/LargestContentfulPaint.test.d.ts index 848a04692..29614938e 100644 --- a/public/models/trace/insights/LargestContentfulPaint.test.d.ts +++ b/public/models/trace/insights/LargestContentfulPaint.test.d.ts @@ -1,5 +1,4 @@ -import type * as TraceModel from '../trace.js'; export declare function processTrace(testContext: Mocha.Suite | Mocha.Context | null, traceFile: string): Promise<{ - data: Readonly>; - insights: TraceModel.Insights.Types.TraceInsightData; + data: Readonly>; + insights: import("./types.js").TraceInsightSets; }>; diff --git a/public/models/trace/insights/LargestContentfulPaint.test.js b/public/models/trace/insights/LargestContentfulPaint.test.js index 23b14aaf7..dce1d6355 100644 --- a/public/models/trace/insights/LargestContentfulPaint.test.js +++ b/public/models/trace/insights/LargestContentfulPaint.test.js @@ -2,30 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; +import { getFirstOrError, getInsight } from '../../../testing/InsightHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; import * as Types from '../types/types.js'; export async function processTrace(testContext, traceFile) { - const { traceData, insights } = await TraceLoader.traceEngine(testContext, traceFile); + const { parsedTrace, insights } = await TraceLoader.traceEngine(testContext, traceFile); if (!insights) { throw new Error('No insights'); } - return { data: traceData, insights }; -} -function getInsight(insights, navigationId) { - const navInsights = insights.get(navigationId); - if (!navInsights) { - throw new Error('missing navInsights'); - } - const insight = navInsights.LargestContentfulPaint; - if (insight instanceof Error) { - throw insight; - } - return insight; + return { data: parsedTrace, insights }; } describeWithEnvironment('LargestContentfulPaint', function () { it('calculates 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); + const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsight('LargestContentfulPaint', insights, firstNav); assert.strictEqual(insight.lcpMs, 106.482); const wantTtfb = Types.Timing.MilliSeconds(6.115); const wantRenderDelay = Types.Timing.MilliSeconds(100.367); @@ -33,7 +24,8 @@ describeWithEnvironment('LargestContentfulPaint', function () { }); it('calculates image lcp phases', async () => { const { data, insights } = await processTrace(this, 'lcp-images.json.gz'); - const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value); + const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsight('LargestContentfulPaint', insights, firstNav); assert.strictEqual(insight.lcpMs, 109.623); if (!insight.phases) { throw new Error('No LCP phases'); @@ -48,7 +40,8 @@ describeWithEnvironment('LargestContentfulPaint', function () { }); it('calculates image lcp attributes', async () => { const { data, insights } = await processTrace(this, 'lcp-images.json.gz'); - const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value); + const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsight('LargestContentfulPaint', insights, firstNav); const { shouldIncreasePriorityHint, shouldPreloadImage, shouldRemoveLazyLoading } = insight; assert.strictEqual(shouldRemoveLazyLoading, false); assert.strictEqual(shouldPreloadImage, true); @@ -56,8 +49,8 @@ describeWithEnvironment('LargestContentfulPaint', function () { }); it('calculates the LCP optimal time as the document request download start time', async () => { const { data, insights } = await processTrace(this, 'web-dev-with-commit.json.gz'); - const firstNav = Array.from(data.Meta.navigationsByNavigationId.keys())[0]; - const insight = getInsight(insights, firstNav); + const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsight('LargestContentfulPaint', insights, firstNav); assert.strictEqual(insight.earliestDiscoveryTimeTs, // this is the TTFB for the document request 122411004828); @@ -65,14 +58,16 @@ describeWithEnvironment('LargestContentfulPaint', function () { describe('warnings', function () { it('warns when there is no lcp', async () => { const { data, insights } = await processTrace(this, 'user-timings.json.gz'); - const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value); + const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsight('LargestContentfulPaint', insights, firstNav); assert.strictEqual(insight.lcpMs, undefined); assert.strictEqual(insight.phases, undefined); assert.strictEqual(insight.warnings?.[0], 'NO_LCP'); }); it('no main document url', async () => { const { data, insights } = await processTrace(this, 'about-blank-first.json.gz'); - const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value); + const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const insight = getInsight('LargestContentfulPaint', insights, firstNav); assert.strictEqual(insight.lcpMs, 204.909); assert.strictEqual(insight.phases, undefined); assert.strictEqual(insight.warnings?.[0], 'NO_DOCUMENT_REQUEST'); diff --git a/public/models/trace/insights/LargestContentfulPaint.test.js.map b/public/models/trace/insights/LargestContentfulPaint.test.js.map index 8cf680558..7ea512961 100644 --- a/public/models/trace/insights/LargestContentfulPaint.test.js.map +++ b/public/models/trace/insights/LargestContentfulPaint.test.js.map @@ -1 +1 @@ -{"version":3,"file":"LargestContentfulPaint.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/LargestContentfulPaint.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport type * as TraceModel from '../trace.js';\nimport * as Types from '../types/types.js';\n\nexport async function processTrace(testContext: Mocha.Suite|Mocha.Context|null, traceFile: string) {\n const {traceData, insights} = await TraceLoader.traceEngine(testContext, traceFile);\n if (!insights) {\n throw new Error('No insights');\n }\n\n return {data: traceData, insights};\n}\n\nfunction getInsight(insights: TraceModel.Insights.Types.TraceInsightData, navigationId: string) {\n const navInsights = insights.get(navigationId);\n if (!navInsights) {\n throw new Error('missing navInsights');\n }\n const insight = navInsights.LargestContentfulPaint;\n if (insight instanceof Error) {\n throw insight;\n }\n return insight;\n}\n\ndescribeWithEnvironment('LargestContentfulPaint', function() {\n it('calculates text lcp phases', async () => {\n const {data, insights} = await processTrace(this, 'lcp-web-font.json.gz');\n const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value);\n\n assert.strictEqual(insight.lcpMs, 106.482);\n\n const wantTtfb = Types.Timing.MilliSeconds(6.115);\n const wantRenderDelay = Types.Timing.MilliSeconds(100.367);\n assert.deepEqual(insight.phases, {ttfb: wantTtfb, renderDelay: wantRenderDelay});\n });\n\n it('calculates image lcp phases', async () => {\n const {data, insights} = await processTrace(this, 'lcp-images.json.gz');\n const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value);\n\n assert.strictEqual(insight.lcpMs, 109.623);\n\n if (!insight.phases) {\n throw new Error('No LCP phases');\n }\n\n const phases = {\n ttfb: insight.phases.ttfb?.toFixed(2),\n loadTime: insight.phases.loadTime?.toFixed(2),\n loadDelay: insight.phases.loadDelay?.toFixed(2),\n renderDelay: insight.phases.renderDelay?.toFixed(2),\n };\n assert.deepEqual(phases, {ttfb: '6.94', loadTime: '12.09', loadDelay: '33.74', renderDelay: '56.85'});\n });\n\n it('calculates image lcp attributes', async () => {\n const {data, insights} = await processTrace(this, 'lcp-images.json.gz');\n const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value);\n const {shouldIncreasePriorityHint, shouldPreloadImage, shouldRemoveLazyLoading} = insight;\n\n assert.strictEqual(shouldRemoveLazyLoading, false);\n assert.strictEqual(shouldPreloadImage, true);\n assert.strictEqual(shouldIncreasePriorityHint, true);\n });\n\n it('calculates the LCP optimal time as the document request download start time', async () => {\n const {data, insights} = await processTrace(this, 'web-dev-with-commit.json.gz');\n const firstNav = Array.from(data.Meta.navigationsByNavigationId.keys())[0];\n const insight = getInsight(insights, firstNav);\n assert.strictEqual(\n insight.earliestDiscoveryTimeTs,\n // this is the TTFB for the document request\n 122411004828,\n );\n });\n\n describe('warnings', function() {\n it('warns when there is no lcp', async () => {\n const {data, insights} = await processTrace(this, 'user-timings.json.gz');\n const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value);\n\n assert.strictEqual(insight.lcpMs, undefined);\n assert.strictEqual(insight.phases, undefined);\n assert.strictEqual(insight.warnings?.[0], 'NO_LCP');\n });\n\n it('no main document url', async () => {\n const {data, insights} = await processTrace(this, 'about-blank-first.json.gz');\n const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value);\n\n assert.strictEqual(insight.lcpMs, 204.909);\n assert.strictEqual(insight.phases, undefined);\n assert.strictEqual(insight.warnings?.[0], 'NO_DOCUMENT_REQUEST');\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"LargestContentfulPaint.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/LargestContentfulPaint.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {getFirstOrError, getInsight} from '../../../testing/InsightHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Types from '../types/types.js';\n\nexport async function processTrace(testContext: Mocha.Suite|Mocha.Context|null, traceFile: string) {\n const {parsedTrace, insights} = await TraceLoader.traceEngine(testContext, traceFile);\n if (!insights) {\n throw new Error('No insights');\n }\n\n return {data: parsedTrace, insights};\n}\n\ndescribeWithEnvironment('LargestContentfulPaint', function() {\n it('calculates text lcp phases', async () => {\n const {data, insights} = await processTrace(this, 'lcp-web-font.json.gz');\n const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values());\n const insight = getInsight('LargestContentfulPaint', insights, firstNav);\n\n assert.strictEqual(insight.lcpMs, 106.482);\n\n const wantTtfb = Types.Timing.MilliSeconds(6.115);\n const wantRenderDelay = Types.Timing.MilliSeconds(100.367);\n assert.deepEqual(insight.phases, {ttfb: wantTtfb, renderDelay: wantRenderDelay});\n });\n\n it('calculates image lcp phases', async () => {\n const {data, insights} = await processTrace(this, 'lcp-images.json.gz');\n const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values());\n const insight = getInsight('LargestContentfulPaint', insights, firstNav);\n\n assert.strictEqual(insight.lcpMs, 109.623);\n\n if (!insight.phases) {\n throw new Error('No LCP phases');\n }\n\n const phases = {\n ttfb: insight.phases.ttfb?.toFixed(2),\n loadTime: insight.phases.loadTime?.toFixed(2),\n loadDelay: insight.phases.loadDelay?.toFixed(2),\n renderDelay: insight.phases.renderDelay?.toFixed(2),\n };\n assert.deepEqual(phases, {ttfb: '6.94', loadTime: '12.09', loadDelay: '33.74', renderDelay: '56.85'});\n });\n\n it('calculates image lcp attributes', async () => {\n const {data, insights} = await processTrace(this, 'lcp-images.json.gz');\n const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values());\n const insight = getInsight('LargestContentfulPaint', insights, firstNav);\n const {shouldIncreasePriorityHint, shouldPreloadImage, shouldRemoveLazyLoading} = insight;\n\n assert.strictEqual(shouldRemoveLazyLoading, false);\n assert.strictEqual(shouldPreloadImage, true);\n assert.strictEqual(shouldIncreasePriorityHint, true);\n });\n\n it('calculates the LCP optimal time as the document request download start time', async () => {\n const {data, insights} = await processTrace(this, 'web-dev-with-commit.json.gz');\n const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values());\n const insight = getInsight('LargestContentfulPaint', insights, firstNav);\n assert.strictEqual(\n insight.earliestDiscoveryTimeTs,\n // this is the TTFB for the document request\n 122411004828,\n );\n });\n\n describe('warnings', function() {\n it('warns when there is no lcp', async () => {\n const {data, insights} = await processTrace(this, 'user-timings.json.gz');\n const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values());\n const insight = getInsight('LargestContentfulPaint', insights, firstNav);\n\n assert.strictEqual(insight.lcpMs, undefined);\n assert.strictEqual(insight.phases, undefined);\n assert.strictEqual(insight.warnings?.[0], 'NO_LCP');\n });\n\n it('no main document url', async () => {\n const {data, insights} = await processTrace(this, 'about-blank-first.json.gz');\n const firstNav = getFirstOrError(data.Meta.navigationsByNavigationId.values());\n const insight = getInsight('LargestContentfulPaint', insights, firstNav);\n\n assert.strictEqual(insight.lcpMs, 204.909);\n assert.strictEqual(insight.phases, undefined);\n assert.strictEqual(insight.warnings?.[0], 'NO_DOCUMENT_REQUEST');\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/RenderBlocking.d.ts b/public/models/trace/insights/RenderBlocking.d.ts index 383f6fe8a..dae638b08 100644 --- a/public/models/trace/insights/RenderBlocking.d.ts +++ b/public/models/trace/insights/RenderBlocking.d.ts @@ -1,8 +1,8 @@ import * as Types from '../types/types.js'; -import { type InsightResult, type NavigationInsightContext, type RequiredData } from './types.js'; +import { type InsightResult, type InsightSetContext, type RequiredData } from './types.js'; export type RenderBlockingInsightResult = InsightResult<{ - renderBlockingRequests: Types.TraceEvents.SyntheticNetworkRequest[]; + renderBlockingRequests: Types.Events.SyntheticNetworkRequest[]; requestIdToWastedMs?: Map; }>; export declare function deps(): ['NetworkRequests', 'PageLoadMetrics', 'LargestImagePaint']; -export declare function generateInsight(traceParsedData: RequiredData, context: NavigationInsightContext): RenderBlockingInsightResult; +export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): RenderBlockingInsightResult; diff --git a/public/models/trace/insights/RenderBlocking.js b/public/models/trace/insights/RenderBlocking.js index 1d09caa62..bd01da8b6 100644 --- a/public/models/trace/insights/RenderBlocking.js +++ b/public/models/trace/insights/RenderBlocking.js @@ -51,8 +51,8 @@ function estimateSavingsWithGraphs(deferredIds, lanternContext) { minimalFCPGraph.request.transferSize = originalTransferSize; return Math.round(Math.max(estimateBeforeInline - estimateAfterInline, 0)); } -function hasImageLCP(traceParsedData, context) { - const frameMetrics = traceParsedData.PageLoadMetrics.metricScoresByFrameId.get(context.frameId); +function hasImageLCP(parsedTrace, context) { + const frameMetrics = parsedTrace.PageLoadMetrics.metricScoresByFrameId.get(context.frameId); if (!frameMetrics) { throw new Error('no frame metrics'); } @@ -62,12 +62,12 @@ function hasImageLCP(traceParsedData, context) { } const metricScore = navMetrics.get("LCP" /* Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP */); const lcpEvent = metricScore?.event; - if (!lcpEvent || !Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate(lcpEvent)) { + if (!lcpEvent || !Types.Events.isLargestContentfulPaintCandidate(lcpEvent)) { return false; } - return findLCPRequest(traceParsedData, context, lcpEvent) !== null; + return findLCPRequest(parsedTrace, context, lcpEvent) !== null; } -function computeSavings(traceParsedData, context, renderBlockingRequests) { +function computeSavings(parsedTrace, context, renderBlockingRequests) { if (!context.lantern) { return; } @@ -93,14 +93,20 @@ function computeSavings(traceParsedData, context, renderBlockingRequests) { if (requestIdToWastedMs.size) { metricSavings.FCP = estimateSavingsWithGraphs(deferredNodeIds, context.lantern); // In most cases, render blocking resources only affect LCP if LCP isn't an image. - if (!hasImageLCP(traceParsedData, context)) { + if (!hasImageLCP(parsedTrace, context)) { metricSavings.LCP = metricSavings.FCP; } } return { metricSavings, requestIdToWastedMs }; } -export function generateInsight(traceParsedData, context) { - const firstPaintTs = traceParsedData.PageLoadMetrics.metricScoresByFrameId.get(context.frameId) +export function generateInsight(parsedTrace, context) { + // TODO(crbug.com/366049346) make this work w/o a navigation. + if (!context.navigation) { + return { + renderBlockingRequests: [], + }; + } + const firstPaintTs = parsedTrace.PageLoadMetrics.metricScoresByFrameId.get(context.frameId) ?.get(context.navigationId) ?.get("FP" /* Handlers.ModelHandlers.PageLoadMetrics.MetricName.FP */) ?.event?.ts; @@ -110,8 +116,8 @@ export function generateInsight(traceParsedData, context) { warnings: [InsightWarning.NO_FP], }; } - const renderBlockingRequests = []; - for (const req of traceParsedData.NetworkRequests.byTime) { + let renderBlockingRequests = []; + for (const req of parsedTrace.NetworkRequests.byTime) { if (req.args.data.frame !== context.frameId) { continue; } @@ -135,12 +141,16 @@ export function generateInsight(traceParsedData, context) { continue; } } - const navigation = Helpers.Trace.getNavigationForTraceEvent(req, context.frameId, traceParsedData.Meta.navigationsByFrameId); + const navigation = Helpers.Trace.getNavigationForTraceEvent(req, context.frameId, parsedTrace.Meta.navigationsByFrameId); if (navigation === context.navigation) { renderBlockingRequests.push(req); } } - const savings = computeSavings(traceParsedData, context, renderBlockingRequests); + const savings = computeSavings(parsedTrace, context, renderBlockingRequests); + // Sort by request duration for insights. + renderBlockingRequests = renderBlockingRequests.sort((a, b) => { + return b.dur - a.dur; + }); return { renderBlockingRequests, ...savings, diff --git a/public/models/trace/insights/RenderBlocking.js.map b/public/models/trace/insights/RenderBlocking.js.map index 0249ef170..6bd591b6c 100644 --- a/public/models/trace/insights/RenderBlocking.js.map +++ b/public/models/trace/insights/RenderBlocking.js.map @@ -1 +1 @@ -{"version":3,"file":"RenderBlocking.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/RenderBlocking.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Protocol from '../../../generated/protocol.js';\nimport * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport type * as Lantern from '../lantern/lantern.js';\nimport * as Types from '../types/types.js';\n\nimport {findLCPRequest} from './Common.js';\nimport {\n type InsightResult,\n InsightWarning,\n type LanternContext,\n type NavigationInsightContext,\n type RequiredData,\n} from './types.js';\n\nexport type RenderBlockingInsightResult = InsightResult<{\n renderBlockingRequests: Types.TraceEvents.SyntheticNetworkRequest[],\n requestIdToWastedMs?: Map,\n}>;\n\n// Because of the way we detect blocking stylesheets, asynchronously loaded\n// CSS with link[rel=preload] and an onload handler (see https://github.com/filamentgroup/loadCSS)\n// can be falsely flagged as blocking. Therefore, ignore stylesheets that loaded fast enough\n// to possibly be non-blocking (and they have minimal impact anyway).\nconst MINIMUM_WASTED_MS = 50;\n\nexport function deps(): ['NetworkRequests', 'PageLoadMetrics', 'LargestImagePaint'] {\n return ['NetworkRequests', 'PageLoadMetrics', 'LargestImagePaint'];\n}\n\n/**\n * Given a simulation's nodeTimings, return an object with the nodes/timing keyed by network URL\n */\nfunction getNodesAndTimingByRequestId(nodeTimings: Lantern.Simulation.Result['nodeTimings']):\n Map {\n const requestIdToNode =\n new Map();\n\n for (const [node, nodeTiming] of nodeTimings) {\n if (node.type !== 'network') {\n continue;\n }\n\n requestIdToNode.set(node.request.requestId, {node, nodeTiming});\n }\n\n return requestIdToNode;\n}\n\nfunction estimateSavingsWithGraphs(deferredIds: Set, lanternContext: LanternContext): number {\n const simulator = lanternContext.simulator;\n const fcpGraph = lanternContext.metrics.firstContentfulPaint.optimisticGraph;\n const {nodeTimings} = lanternContext.simulator.simulate(fcpGraph);\n const adjustedNodeTimings = new Map(nodeTimings);\n\n const totalChildNetworkBytes = 0;\n const minimalFCPGraph = fcpGraph.cloneWithRelationships(node => {\n // If a node can be deferred, exclude it from the new FCP graph\n const canDeferRequest = deferredIds.has(node.id);\n return !canDeferRequest;\n });\n\n if (minimalFCPGraph.type !== 'network') {\n throw new Error('minimalFCPGraph not a NetworkNode');\n }\n\n // Recalculate the \"before\" time based on our adjusted node timings.\n const estimateBeforeInline = Math.max(...Array.from(\n Array.from(adjustedNodeTimings).map(timing => timing[1].endTime),\n ));\n\n // Add the inlined bytes to the HTML response\n const originalTransferSize = minimalFCPGraph.request.transferSize;\n const safeTransferSize = originalTransferSize || 0;\n minimalFCPGraph.request.transferSize = safeTransferSize + totalChildNetworkBytes;\n const estimateAfterInline = simulator.simulate(minimalFCPGraph).timeInMs;\n minimalFCPGraph.request.transferSize = originalTransferSize;\n return Math.round(Math.max(estimateBeforeInline - estimateAfterInline, 0));\n}\n\nfunction hasImageLCP(traceParsedData: RequiredData, context: NavigationInsightContext): boolean {\n const frameMetrics = traceParsedData.PageLoadMetrics.metricScoresByFrameId.get(context.frameId);\n if (!frameMetrics) {\n throw new Error('no frame metrics');\n }\n\n const navMetrics = frameMetrics.get(context.navigationId);\n if (!navMetrics) {\n throw new Error('no navigation metrics');\n }\n const metricScore = navMetrics.get(Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP);\n const lcpEvent = metricScore?.event;\n if (!lcpEvent || !Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate(lcpEvent)) {\n return false;\n }\n\n return findLCPRequest(traceParsedData, context, lcpEvent) !== null;\n}\n\nfunction computeSavings(\n traceParsedData: RequiredData, context: NavigationInsightContext,\n renderBlockingRequests: Types.TraceEvents.SyntheticNetworkRequest[]):\n Pick|undefined {\n if (!context.lantern) {\n return;\n }\n\n const nodesAndTimingsByRequestId =\n getNodesAndTimingByRequestId(context.lantern.metrics.firstContentfulPaint.optimisticEstimate.nodeTimings);\n\n const metricSavings = {FCP: 0, LCP: 0};\n const requestIdToWastedMs = new Map();\n const deferredNodeIds = new Set();\n for (const request of renderBlockingRequests) {\n const nodeAndTiming = nodesAndTimingsByRequestId.get(request.args.data.requestId);\n if (!nodeAndTiming) {\n continue;\n }\n\n const {node, nodeTiming} = nodeAndTiming;\n\n // Mark this node and all its dependents as deferrable\n node.traverse(node => deferredNodeIds.add(node.id));\n\n // \"wastedMs\" is the download time of the network request, responseReceived - requestSent\n const wastedMs = Math.round(nodeTiming.duration);\n if (wastedMs < MINIMUM_WASTED_MS) {\n continue;\n }\n\n requestIdToWastedMs.set(node.id, wastedMs);\n }\n\n if (requestIdToWastedMs.size) {\n metricSavings.FCP = estimateSavingsWithGraphs(deferredNodeIds, context.lantern);\n\n // In most cases, render blocking resources only affect LCP if LCP isn't an image.\n if (!hasImageLCP(traceParsedData, context)) {\n metricSavings.LCP = metricSavings.FCP;\n }\n }\n\n return {metricSavings, requestIdToWastedMs};\n}\n\nexport function generateInsight(\n traceParsedData: RequiredData, context: NavigationInsightContext): RenderBlockingInsightResult {\n const firstPaintTs = traceParsedData.PageLoadMetrics.metricScoresByFrameId.get(context.frameId)\n ?.get(context.navigationId)\n ?.get(Handlers.ModelHandlers.PageLoadMetrics.MetricName.FP)\n ?.event?.ts;\n if (!firstPaintTs) {\n return {\n renderBlockingRequests: [],\n warnings: [InsightWarning.NO_FP],\n };\n }\n\n const renderBlockingRequests = [];\n for (const req of traceParsedData.NetworkRequests.byTime) {\n if (req.args.data.frame !== context.frameId) {\n continue;\n }\n\n if (req.args.data.renderBlocking !== 'blocking' && req.args.data.renderBlocking !== 'in_body_parser_blocking') {\n continue;\n }\n\n if (req.args.data.syntheticData.finishTime > firstPaintTs) {\n continue;\n }\n\n // If a request is marked `in_body_parser_blocking` it should only be considered render blocking if it is a\n // high enough priority. Some requests (e.g. scripts) are not marked as high priority if they are fetched\n // after a non-preloaded image. (See \"early\" definition in https://web.dev/articles/fetch-priority)\n //\n // There are edge cases and exceptions (e.g. priority hints) but this gives us the best approximation\n // of render blocking resources in the document body.\n if (req.args.data.renderBlocking === 'in_body_parser_blocking') {\n const priority = req.args.data.priority;\n const isScript = req.args.data.resourceType === Protocol.Network.ResourceType.Script;\n const isBlockingScript = isScript && priority === Protocol.Network.ResourcePriority.High;\n if (priority !== Protocol.Network.ResourcePriority.VeryHigh && !isBlockingScript) {\n continue;\n }\n }\n\n const navigation =\n Helpers.Trace.getNavigationForTraceEvent(req, context.frameId, traceParsedData.Meta.navigationsByFrameId);\n if (navigation === context.navigation) {\n renderBlockingRequests.push(req);\n }\n }\n\n const savings = computeSavings(traceParsedData, context, renderBlockingRequests);\n\n return {\n renderBlockingRequests,\n ...savings,\n };\n}\n"]} \ No newline at end of file +{"version":3,"file":"RenderBlocking.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/RenderBlocking.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Protocol from '../../../generated/protocol.js';\nimport * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport type * as Lantern from '../lantern/lantern.js';\nimport * as Types from '../types/types.js';\n\nimport {findLCPRequest} from './Common.js';\nimport {\n type InsightResult,\n type InsightSetContext,\n type InsightSetContextWithNavigation,\n InsightWarning,\n type LanternContext,\n type RequiredData,\n} from './types.js';\n\nexport type RenderBlockingInsightResult = InsightResult<{\n renderBlockingRequests: Types.Events.SyntheticNetworkRequest[],\n requestIdToWastedMs?: Map,\n}>;\n\n// Because of the way we detect blocking stylesheets, asynchronously loaded\n// CSS with link[rel=preload] and an onload handler (see https://github.com/filamentgroup/loadCSS)\n// can be falsely flagged as blocking. Therefore, ignore stylesheets that loaded fast enough\n// to possibly be non-blocking (and they have minimal impact anyway).\nconst MINIMUM_WASTED_MS = 50;\n\nexport function deps(): ['NetworkRequests', 'PageLoadMetrics', 'LargestImagePaint'] {\n return ['NetworkRequests', 'PageLoadMetrics', 'LargestImagePaint'];\n}\n\n/**\n * Given a simulation's nodeTimings, return an object with the nodes/timing keyed by network URL\n */\nfunction getNodesAndTimingByRequestId(nodeTimings: Lantern.Simulation.Result['nodeTimings']):\n Map {\n const requestIdToNode =\n new Map();\n\n for (const [node, nodeTiming] of nodeTimings) {\n if (node.type !== 'network') {\n continue;\n }\n\n requestIdToNode.set(node.request.requestId, {node, nodeTiming});\n }\n\n return requestIdToNode;\n}\n\nfunction estimateSavingsWithGraphs(deferredIds: Set, lanternContext: LanternContext): number {\n const simulator = lanternContext.simulator;\n const fcpGraph = lanternContext.metrics.firstContentfulPaint.optimisticGraph;\n const {nodeTimings} = lanternContext.simulator.simulate(fcpGraph);\n const adjustedNodeTimings = new Map(nodeTimings);\n\n const totalChildNetworkBytes = 0;\n const minimalFCPGraph = fcpGraph.cloneWithRelationships(node => {\n // If a node can be deferred, exclude it from the new FCP graph\n const canDeferRequest = deferredIds.has(node.id);\n return !canDeferRequest;\n });\n\n if (minimalFCPGraph.type !== 'network') {\n throw new Error('minimalFCPGraph not a NetworkNode');\n }\n\n // Recalculate the \"before\" time based on our adjusted node timings.\n const estimateBeforeInline = Math.max(...Array.from(\n Array.from(adjustedNodeTimings).map(timing => timing[1].endTime),\n ));\n\n // Add the inlined bytes to the HTML response\n const originalTransferSize = minimalFCPGraph.request.transferSize;\n const safeTransferSize = originalTransferSize || 0;\n minimalFCPGraph.request.transferSize = safeTransferSize + totalChildNetworkBytes;\n const estimateAfterInline = simulator.simulate(minimalFCPGraph).timeInMs;\n minimalFCPGraph.request.transferSize = originalTransferSize;\n return Math.round(Math.max(estimateBeforeInline - estimateAfterInline, 0));\n}\n\nfunction hasImageLCP(parsedTrace: RequiredData, context: InsightSetContextWithNavigation): boolean {\n const frameMetrics = parsedTrace.PageLoadMetrics.metricScoresByFrameId.get(context.frameId);\n if (!frameMetrics) {\n throw new Error('no frame metrics');\n }\n\n const navMetrics = frameMetrics.get(context.navigationId);\n if (!navMetrics) {\n throw new Error('no navigation metrics');\n }\n const metricScore = navMetrics.get(Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP);\n const lcpEvent = metricScore?.event;\n if (!lcpEvent || !Types.Events.isLargestContentfulPaintCandidate(lcpEvent)) {\n return false;\n }\n\n return findLCPRequest(parsedTrace, context, lcpEvent) !== null;\n}\n\nfunction computeSavings(\n parsedTrace: RequiredData, context: InsightSetContextWithNavigation,\n renderBlockingRequests: Types.Events.SyntheticNetworkRequest[]):\n Pick|undefined {\n if (!context.lantern) {\n return;\n }\n\n const nodesAndTimingsByRequestId =\n getNodesAndTimingByRequestId(context.lantern.metrics.firstContentfulPaint.optimisticEstimate.nodeTimings);\n\n const metricSavings = {FCP: 0, LCP: 0};\n const requestIdToWastedMs = new Map();\n const deferredNodeIds = new Set();\n for (const request of renderBlockingRequests) {\n const nodeAndTiming = nodesAndTimingsByRequestId.get(request.args.data.requestId);\n if (!nodeAndTiming) {\n continue;\n }\n\n const {node, nodeTiming} = nodeAndTiming;\n\n // Mark this node and all its dependents as deferrable\n node.traverse(node => deferredNodeIds.add(node.id));\n\n // \"wastedMs\" is the download time of the network request, responseReceived - requestSent\n const wastedMs = Math.round(nodeTiming.duration);\n if (wastedMs < MINIMUM_WASTED_MS) {\n continue;\n }\n\n requestIdToWastedMs.set(node.id, wastedMs);\n }\n\n if (requestIdToWastedMs.size) {\n metricSavings.FCP = estimateSavingsWithGraphs(deferredNodeIds, context.lantern);\n\n // In most cases, render blocking resources only affect LCP if LCP isn't an image.\n if (!hasImageLCP(parsedTrace, context)) {\n metricSavings.LCP = metricSavings.FCP;\n }\n }\n\n return {metricSavings, requestIdToWastedMs};\n}\n\nexport function generateInsight(\n parsedTrace: RequiredData, context: InsightSetContext): RenderBlockingInsightResult {\n // TODO(crbug.com/366049346) make this work w/o a navigation.\n if (!context.navigation) {\n return {\n renderBlockingRequests: [],\n };\n }\n\n const firstPaintTs = parsedTrace.PageLoadMetrics.metricScoresByFrameId.get(context.frameId)\n ?.get(context.navigationId)\n ?.get(Handlers.ModelHandlers.PageLoadMetrics.MetricName.FP)\n ?.event?.ts;\n if (!firstPaintTs) {\n return {\n renderBlockingRequests: [],\n warnings: [InsightWarning.NO_FP],\n };\n }\n\n let renderBlockingRequests: Types.Events.SyntheticNetworkRequest[] = [];\n for (const req of parsedTrace.NetworkRequests.byTime) {\n if (req.args.data.frame !== context.frameId) {\n continue;\n }\n\n if (req.args.data.renderBlocking !== 'blocking' && req.args.data.renderBlocking !== 'in_body_parser_blocking') {\n continue;\n }\n\n if (req.args.data.syntheticData.finishTime > firstPaintTs) {\n continue;\n }\n\n // If a request is marked `in_body_parser_blocking` it should only be considered render blocking if it is a\n // high enough priority. Some requests (e.g. scripts) are not marked as high priority if they are fetched\n // after a non-preloaded image. (See \"early\" definition in https://web.dev/articles/fetch-priority)\n //\n // There are edge cases and exceptions (e.g. priority hints) but this gives us the best approximation\n // of render blocking resources in the document body.\n if (req.args.data.renderBlocking === 'in_body_parser_blocking') {\n const priority = req.args.data.priority;\n const isScript = req.args.data.resourceType === Protocol.Network.ResourceType.Script;\n const isBlockingScript = isScript && priority === Protocol.Network.ResourcePriority.High;\n if (priority !== Protocol.Network.ResourcePriority.VeryHigh && !isBlockingScript) {\n continue;\n }\n }\n\n const navigation =\n Helpers.Trace.getNavigationForTraceEvent(req, context.frameId, parsedTrace.Meta.navigationsByFrameId);\n if (navigation === context.navigation) {\n renderBlockingRequests.push(req);\n }\n }\n\n const savings = computeSavings(parsedTrace, context, renderBlockingRequests);\n\n // Sort by request duration for insights.\n renderBlockingRequests = renderBlockingRequests.sort((a, b) => {\n return b.dur - a.dur;\n });\n\n return {\n renderBlockingRequests,\n ...savings,\n };\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/RenderBlocking.test.d.ts b/public/models/trace/insights/RenderBlocking.test.d.ts index 848a04692..ff8663e3e 100644 --- a/public/models/trace/insights/RenderBlocking.test.d.ts +++ b/public/models/trace/insights/RenderBlocking.test.d.ts @@ -1,5 +1,5 @@ -import type * as TraceModel from '../trace.js'; +import { Types } from './insights.js'; export declare function processTrace(testContext: Mocha.Suite | Mocha.Context | null, traceFile: string): Promise<{ - data: Readonly>; - insights: TraceModel.Insights.Types.TraceInsightData; + data: Readonly>; + insights: Types.TraceInsightSets; }>; diff --git a/public/models/trace/insights/RenderBlocking.test.js b/public/models/trace/insights/RenderBlocking.test.js index b39fb1807..0001f66dd 100644 --- a/public/models/trace/insights/RenderBlocking.test.js +++ b/public/models/trace/insights/RenderBlocking.test.js @@ -2,30 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; +import { getInsight } from '../../../testing/InsightHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; +import { Types } from './insights.js'; export async function processTrace(testContext, traceFile) { - const { traceData, insights } = await TraceLoader.traceEngine(testContext, traceFile); + const { parsedTrace, insights } = await TraceLoader.traceEngine(testContext, traceFile); if (!insights) { throw new Error('No insights'); } - return { data: traceData, insights }; -} -function getInsight(insights, navigationId) { - const navInsights = insights.get(navigationId); - if (!navInsights) { - throw new Error('missing navInsights'); - } - const insight = navInsights.RenderBlocking; - if (insight instanceof Error) { - throw insight; - } - return insight; + return { data: parsedTrace, insights }; } describeWithEnvironment('RenderBlockingRequests', function () { it('finds render blocking requests', async () => { const { data, insights } = await processTrace(this, 'load-simple.json.gz'); - assert.strictEqual(insights.size, 1); - const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value); + assert.deepStrictEqual([...insights.keys()], [Types.NO_NAVIGATION, '0BCFC23BC7D7BEDC9F93E912DCCEC1DA']); + const insight = getInsight('RenderBlocking', insights, data.Meta.navigationsByNavigationId.values().next().value); assert.strictEqual(insight.renderBlockingRequests.length, 2); assert.deepEqual(insight.renderBlockingRequests.map(r => r.args.data.url), [ 'https://fonts.googleapis.com/css2?family=Orelega+One&display=swap', @@ -35,47 +26,49 @@ describeWithEnvironment('RenderBlockingRequests', function () { it('returns a warning if navigation does not have a first paint event', async () => { const { data, insights } = await processTrace(this, 'user-timings.json.gz'); assert.strictEqual(insights.size, 1); - const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value); + const insight = getInsight('RenderBlocking', insights, data.Meta.navigationsByNavigationId.values().next().value); assert.strictEqual(insight.renderBlockingRequests.length, 0); assert.strictEqual(insight.warnings?.length, 1); assert.strictEqual(insight.warnings?.[0], 'NO_FP'); }); it('considers only the navigation specified by the context', async () => { const { data, insights } = await processTrace(this, 'multiple-navigations-render-blocking.json.gz'); - assert.strictEqual(insights.size, 2); + assert.deepStrictEqual([...insights.keys()], [Types.NO_NAVIGATION, '8671F33ECE0C8DBAEFBC2F9A2D1D6107', '1AE2016BBCC48AA090FDAE2CBBA01900']); const navigations = Array.from(data.Meta.navigationsByNavigationId.values()); - const insight = getInsight(insights, navigations[0].args.data?.navigationId || ''); + const insight = getInsight('RenderBlocking', insights, navigations[0]); assert(insight.renderBlockingRequests.length > 0, 'no render blocking requests found'); assert(insight.renderBlockingRequests.every(r => r.args.data.syntheticData.sendStartTime > navigations[0].ts), 'a result is not contained by the nav bounds'); assert(insight.renderBlockingRequests.every(r => r.args.data.syntheticData.finishTime < navigations[1].ts), 'a result is not contained by the nav bounds'); }); it('considers navigations separately', async () => { const { data, insights } = await processTrace(this, 'multiple-navigations-render-blocking.json.gz'); - assert.strictEqual(insights.size, 2); + assert.strictEqual(insights.size, 3); const navigations = Array.from(data.Meta.navigationsByNavigationId.values()); - const insightOne = getInsight(insights, navigations[0].args.data?.navigationId || ''); - const insightTwo = getInsight(insights, navigations[1].args.data?.navigationId || ''); - assert.deepStrictEqual(insightOne.renderBlockingRequests.map(r => r.args.data.requestId), ['99116.2']); - assert.deepStrictEqual(insightTwo.renderBlockingRequests.map(r => r.args.data.requestId), ['99116.5']); + const insightOne = getInsight('RenderBlocking', insights); + const insightTwo = getInsight('RenderBlocking', insights, navigations[0]); + const insightThree = getInsight('RenderBlocking', insights, navigations[1]); + assert.deepStrictEqual(insightOne.renderBlockingRequests.map(r => r.args.data.requestId), []); + assert.deepStrictEqual(insightTwo.renderBlockingRequests.map(r => r.args.data.requestId), ['99116.2']); + assert.deepStrictEqual(insightThree.renderBlockingRequests.map(r => r.args.data.requestId), ['99116.5']); }); it('considers only the frame specified by the context', async () => { const { data, insights } = await processTrace(this, 'render-blocking-in-iframe.json.gz'); assert.strictEqual(insights.size, 1); const navigations = Array.from(data.Meta.navigationsByNavigationId.values()); - const insight = getInsight(insights, navigations[0].args.data?.navigationId || ''); + const insight = getInsight('RenderBlocking', insights, navigations[0]); assert(insight.renderBlockingRequests.length > 0, 'no render blocking requests found'); assert(insight.renderBlockingRequests.every(r => r.args.data.frame === data.Meta.mainFrameId), 'a result is not from the main frame'); }); it('ignores blocking request after first paint', async () => { const { data, insights } = await processTrace(this, 'parser-blocking-after-paint.json.gz'); assert.strictEqual(insights.size, 1); - const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value); + const insight = getInsight('RenderBlocking', insights, data.Meta.navigationsByNavigationId.values().next().value); assert.strictEqual(insight.renderBlockingRequests.length, 0); }); it('correctly handles body parser blocking requests', async () => { const { data, insights } = await processTrace(this, 'render-blocking-body.json.gz'); assert.strictEqual(insights.size, 1); - const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value); + const insight = getInsight('RenderBlocking', insights, data.Meta.navigationsByNavigationId.values().next().value); assert.deepStrictEqual(insight.renderBlockingRequests.map(r => r.args.data.url), [ 'http://localhost:8080/render-blocking/style.css', 'http://localhost:8080/render-blocking/script.js?beforeImage', @@ -84,7 +77,7 @@ describeWithEnvironment('RenderBlockingRequests', function () { it('estimates savings with Lantern (image LCP)', async () => { const { data, insights } = await processTrace(this, 'lantern/render-blocking/trace.json.gz'); assert.strictEqual(insights.size, 1); - const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value); + const insight = getInsight('RenderBlocking', insights, data.Meta.navigationsByNavigationId.values().next().value); assert.deepStrictEqual(insight.metricSavings, { FCP: 2250, LCP: 0, @@ -102,7 +95,7 @@ describeWithEnvironment('RenderBlockingRequests', function () { it('estimates savings with Lantern (text LCP)', async () => { const { data, insights } = await processTrace(this, 'lantern/typescript-angular/trace.json.gz'); assert.strictEqual(insights.size, 1); - const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value); + const insight = getInsight('RenderBlocking', insights, data.Meta.navigationsByNavigationId.values().next().value); assert.deepStrictEqual(insight.metricSavings, { FCP: 13, LCP: 13, diff --git a/public/models/trace/insights/RenderBlocking.test.js.map b/public/models/trace/insights/RenderBlocking.test.js.map index 557ec92e2..ea44137e2 100644 --- a/public/models/trace/insights/RenderBlocking.test.js.map +++ b/public/models/trace/insights/RenderBlocking.test.js.map @@ -1 +1 @@ -{"version":3,"file":"RenderBlocking.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/RenderBlocking.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport type * as TraceModel from '../trace.js';\n\nexport async function processTrace(testContext: Mocha.Suite|Mocha.Context|null, traceFile: string) {\n const {traceData, insights} = await TraceLoader.traceEngine(testContext, traceFile);\n if (!insights) {\n throw new Error('No insights');\n }\n\n return {data: traceData, insights};\n}\n\nfunction getInsight(insights: TraceModel.Insights.Types.TraceInsightData, navigationId: string) {\n const navInsights = insights.get(navigationId);\n if (!navInsights) {\n throw new Error('missing navInsights');\n }\n const insight = navInsights.RenderBlocking;\n if (insight instanceof Error) {\n throw insight;\n }\n return insight;\n}\n\ndescribeWithEnvironment('RenderBlockingRequests', function() {\n it('finds render blocking requests', async () => {\n const {data, insights} = await processTrace(this, 'load-simple.json.gz');\n assert.strictEqual(insights.size, 1);\n const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value);\n\n assert.strictEqual(insight.renderBlockingRequests.length, 2);\n assert.deepEqual(insight.renderBlockingRequests.map(r => r.args.data.url), [\n 'https://fonts.googleapis.com/css2?family=Orelega+One&display=swap',\n 'http://localhost:8080/styles.css',\n ]);\n });\n\n it('returns a warning if navigation does not have a first paint event', async () => {\n const {data, insights} = await processTrace(this, 'user-timings.json.gz');\n assert.strictEqual(insights.size, 1);\n const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value);\n\n assert.strictEqual(insight.renderBlockingRequests.length, 0);\n assert.strictEqual(insight.warnings?.length, 1);\n assert.strictEqual(insight.warnings?.[0], 'NO_FP');\n });\n\n it('considers only the navigation specified by the context', async () => {\n const {data, insights} = await processTrace(this, 'multiple-navigations-render-blocking.json.gz');\n assert.strictEqual(insights.size, 2);\n const navigations = Array.from(data.Meta.navigationsByNavigationId.values());\n const insight = getInsight(insights, navigations[0].args.data?.navigationId || '');\n\n assert(insight.renderBlockingRequests.length > 0, 'no render blocking requests found');\n\n assert(\n insight.renderBlockingRequests.every(r => r.args.data.syntheticData.sendStartTime > navigations[0].ts),\n 'a result is not contained by the nav bounds');\n assert(\n insight.renderBlockingRequests.every(r => r.args.data.syntheticData.finishTime < navigations[1].ts),\n 'a result is not contained by the nav bounds');\n });\n\n it('considers navigations separately', async () => {\n const {data, insights} = await processTrace(this, 'multiple-navigations-render-blocking.json.gz');\n assert.strictEqual(insights.size, 2);\n const navigations = Array.from(data.Meta.navigationsByNavigationId.values());\n const insightOne = getInsight(insights, navigations[0].args.data?.navigationId || '');\n const insightTwo = getInsight(insights, navigations[1].args.data?.navigationId || '');\n assert.deepStrictEqual(insightOne.renderBlockingRequests.map(r => r.args.data.requestId), ['99116.2']);\n assert.deepStrictEqual(insightTwo.renderBlockingRequests.map(r => r.args.data.requestId), ['99116.5']);\n });\n\n it('considers only the frame specified by the context', async () => {\n const {data, insights} = await processTrace(this, 'render-blocking-in-iframe.json.gz');\n assert.strictEqual(insights.size, 1);\n const navigations = Array.from(data.Meta.navigationsByNavigationId.values());\n const insight = getInsight(insights, navigations[0].args.data?.navigationId || '');\n\n assert(insight.renderBlockingRequests.length > 0, 'no render blocking requests found');\n\n assert(\n insight.renderBlockingRequests.every(r => r.args.data.frame === data.Meta.mainFrameId),\n 'a result is not from the main frame');\n });\n\n it('ignores blocking request after first paint', async () => {\n const {data, insights} = await processTrace(this, 'parser-blocking-after-paint.json.gz');\n assert.strictEqual(insights.size, 1);\n const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value);\n\n assert.strictEqual(insight.renderBlockingRequests.length, 0);\n });\n\n it('correctly handles body parser blocking requests', async () => {\n const {data, insights} = await processTrace(this, 'render-blocking-body.json.gz');\n assert.strictEqual(insights.size, 1);\n const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value);\n\n assert.deepStrictEqual(insight.renderBlockingRequests.map(r => r.args.data.url), [\n 'http://localhost:8080/render-blocking/style.css',\n 'http://localhost:8080/render-blocking/script.js?beforeImage',\n ]);\n });\n\n it('estimates savings with Lantern (image LCP)', async () => {\n const {data, insights} = await processTrace(this, 'lantern/render-blocking/trace.json.gz');\n assert.strictEqual(insights.size, 1);\n const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value);\n\n assert.deepStrictEqual(insight.metricSavings, {\n FCP: 2250,\n LCP: 0,\n });\n\n assert.exists(insight.requestIdToWastedMs);\n const urlToWastedMs = [...insight.requestIdToWastedMs].map(([requestId, wastedMs]) => {\n const url = insight.renderBlockingRequests.find(r => r.args.data.requestId === requestId)?.args.data.url;\n return [url, wastedMs];\n });\n assert.deepStrictEqual(urlToWastedMs, [\n ['http://localhost:50049/style.css', 2254],\n ['http://localhost:50049/script.js', 304],\n ]);\n });\n\n it('estimates savings with Lantern (text LCP)', async () => {\n const {data, insights} = await processTrace(this, 'lantern/typescript-angular/trace.json.gz');\n assert.strictEqual(insights.size, 1);\n const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value);\n\n assert.deepStrictEqual(insight.metricSavings, {\n FCP: 13,\n LCP: 13,\n });\n assert.exists(insight.requestIdToWastedMs);\n const urlToWastedMs = [...insight.requestIdToWastedMs].map(([requestId, wastedMs]) => {\n const url = insight.renderBlockingRequests.find(r => r.args.data.requestId === requestId)?.args.data.url;\n return [url, wastedMs];\n });\n assert.deepStrictEqual(urlToWastedMs, [\n ['http://[::]:8000/typescript-angular/node_modules/todomvc-common/base.css', 153],\n ['http://[::]:8000/typescript-angular/node_modules/todomvc-app-css/index.css', 303],\n ['http://[::]:8000/typescript-angular/node_modules/todomvc-common/base.js', 303],\n ['http://[::]:8000/typescript-angular/node_modules/angular/angular.js', 303],\n ['http://[::]:8000/typescript-angular/js/Application.js', 303],\n ]);\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"RenderBlocking.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/RenderBlocking.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {getInsight} from '../../../testing/InsightHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\n\nimport {Types} from './insights.js';\n\nexport async function processTrace(testContext: Mocha.Suite|Mocha.Context|null, traceFile: string) {\n const {parsedTrace, insights} = await TraceLoader.traceEngine(testContext, traceFile);\n if (!insights) {\n throw new Error('No insights');\n }\n\n return {data: parsedTrace, insights};\n}\n\ndescribeWithEnvironment('RenderBlockingRequests', function() {\n it('finds render blocking requests', async () => {\n const {data, insights} = await processTrace(this, 'load-simple.json.gz');\n assert.deepStrictEqual([...insights.keys()], [Types.NO_NAVIGATION, '0BCFC23BC7D7BEDC9F93E912DCCEC1DA']);\n const insight = getInsight('RenderBlocking', insights, data.Meta.navigationsByNavigationId.values().next().value);\n\n assert.strictEqual(insight.renderBlockingRequests.length, 2);\n assert.deepEqual(insight.renderBlockingRequests.map(r => r.args.data.url), [\n 'https://fonts.googleapis.com/css2?family=Orelega+One&display=swap',\n 'http://localhost:8080/styles.css',\n ]);\n });\n\n it('returns a warning if navigation does not have a first paint event', async () => {\n const {data, insights} = await processTrace(this, 'user-timings.json.gz');\n assert.strictEqual(insights.size, 1);\n const insight = getInsight('RenderBlocking', insights, data.Meta.navigationsByNavigationId.values().next().value);\n\n assert.strictEqual(insight.renderBlockingRequests.length, 0);\n assert.strictEqual(insight.warnings?.length, 1);\n assert.strictEqual(insight.warnings?.[0], 'NO_FP');\n });\n\n it('considers only the navigation specified by the context', async () => {\n const {data, insights} = await processTrace(this, 'multiple-navigations-render-blocking.json.gz');\n assert.deepStrictEqual(\n [...insights.keys()],\n [Types.NO_NAVIGATION, '8671F33ECE0C8DBAEFBC2F9A2D1D6107', '1AE2016BBCC48AA090FDAE2CBBA01900']);\n const navigations = Array.from(data.Meta.navigationsByNavigationId.values());\n const insight = getInsight('RenderBlocking', insights, navigations[0]);\n\n assert(insight.renderBlockingRequests.length > 0, 'no render blocking requests found');\n\n assert(\n insight.renderBlockingRequests.every(r => r.args.data.syntheticData.sendStartTime > navigations[0].ts),\n 'a result is not contained by the nav bounds');\n assert(\n insight.renderBlockingRequests.every(r => r.args.data.syntheticData.finishTime < navigations[1].ts),\n 'a result is not contained by the nav bounds');\n });\n\n it('considers navigations separately', async () => {\n const {data, insights} = await processTrace(this, 'multiple-navigations-render-blocking.json.gz');\n assert.strictEqual(insights.size, 3);\n const navigations = Array.from(data.Meta.navigationsByNavigationId.values());\n const insightOne = getInsight('RenderBlocking', insights);\n const insightTwo = getInsight('RenderBlocking', insights, navigations[0]);\n const insightThree = getInsight('RenderBlocking', insights, navigations[1]);\n assert.deepStrictEqual(insightOne.renderBlockingRequests.map(r => r.args.data.requestId), []);\n assert.deepStrictEqual(insightTwo.renderBlockingRequests.map(r => r.args.data.requestId), ['99116.2']);\n assert.deepStrictEqual(insightThree.renderBlockingRequests.map(r => r.args.data.requestId), ['99116.5']);\n });\n\n it('considers only the frame specified by the context', async () => {\n const {data, insights} = await processTrace(this, 'render-blocking-in-iframe.json.gz');\n assert.strictEqual(insights.size, 1);\n const navigations = Array.from(data.Meta.navigationsByNavigationId.values());\n const insight = getInsight('RenderBlocking', insights, navigations[0]);\n\n assert(insight.renderBlockingRequests.length > 0, 'no render blocking requests found');\n\n assert(\n insight.renderBlockingRequests.every(r => r.args.data.frame === data.Meta.mainFrameId),\n 'a result is not from the main frame');\n });\n\n it('ignores blocking request after first paint', async () => {\n const {data, insights} = await processTrace(this, 'parser-blocking-after-paint.json.gz');\n assert.strictEqual(insights.size, 1);\n const insight = getInsight('RenderBlocking', insights, data.Meta.navigationsByNavigationId.values().next().value);\n\n assert.strictEqual(insight.renderBlockingRequests.length, 0);\n });\n\n it('correctly handles body parser blocking requests', async () => {\n const {data, insights} = await processTrace(this, 'render-blocking-body.json.gz');\n assert.strictEqual(insights.size, 1);\n const insight = getInsight('RenderBlocking', insights, data.Meta.navigationsByNavigationId.values().next().value);\n\n assert.deepStrictEqual(insight.renderBlockingRequests.map(r => r.args.data.url), [\n 'http://localhost:8080/render-blocking/style.css',\n 'http://localhost:8080/render-blocking/script.js?beforeImage',\n ]);\n });\n\n it('estimates savings with Lantern (image LCP)', async () => {\n const {data, insights} = await processTrace(this, 'lantern/render-blocking/trace.json.gz');\n assert.strictEqual(insights.size, 1);\n const insight = getInsight('RenderBlocking', insights, data.Meta.navigationsByNavigationId.values().next().value);\n\n assert.deepStrictEqual(insight.metricSavings, {\n FCP: 2250,\n LCP: 0,\n });\n\n assert.exists(insight.requestIdToWastedMs);\n const urlToWastedMs = [...insight.requestIdToWastedMs].map(([requestId, wastedMs]) => {\n const url = insight.renderBlockingRequests.find(r => r.args.data.requestId === requestId)?.args.data.url;\n return [url, wastedMs];\n });\n assert.deepStrictEqual(urlToWastedMs, [\n ['http://localhost:50049/style.css', 2254],\n ['http://localhost:50049/script.js', 304],\n ]);\n });\n\n it('estimates savings with Lantern (text LCP)', async () => {\n const {data, insights} = await processTrace(this, 'lantern/typescript-angular/trace.json.gz');\n assert.strictEqual(insights.size, 1);\n const insight = getInsight('RenderBlocking', insights, data.Meta.navigationsByNavigationId.values().next().value);\n\n assert.deepStrictEqual(insight.metricSavings, {\n FCP: 13,\n LCP: 13,\n });\n assert.exists(insight.requestIdToWastedMs);\n const urlToWastedMs = [...insight.requestIdToWastedMs].map(([requestId, wastedMs]) => {\n const url = insight.renderBlockingRequests.find(r => r.args.data.requestId === requestId)?.args.data.url;\n return [url, wastedMs];\n });\n assert.deepStrictEqual(urlToWastedMs, [\n ['http://[::]:8000/typescript-angular/node_modules/todomvc-common/base.css', 153],\n ['http://[::]:8000/typescript-angular/node_modules/todomvc-app-css/index.css', 303],\n ['http://[::]:8000/typescript-angular/node_modules/todomvc-common/base.js', 303],\n ['http://[::]:8000/typescript-angular/node_modules/angular/angular.js', 303],\n ['http://[::]:8000/typescript-angular/js/Application.js', 303],\n ]);\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/SlowCSSSelector.d.ts b/public/models/trace/insights/SlowCSSSelector.d.ts index 30627ee0e..57cd77647 100644 --- a/public/models/trace/insights/SlowCSSSelector.d.ts +++ b/public/models/trace/insights/SlowCSSSelector.d.ts @@ -1,11 +1,11 @@ import * as Types from '../types/types.js'; -import { type InsightResult, type NavigationInsightContext, type RequiredData } from './types.js'; +import { type InsightResult, type InsightSetContext, type RequiredData } from './types.js'; export declare function deps(): ['SelectorStats']; export type SlowCSSSelectorInsightResult = InsightResult<{ totalElapsedMs: Types.Timing.MilliSeconds; totalMatchAttempts: number; totalMatchCount: number; - topElapsedMs: Types.TraceEvents.SelectorTiming[]; - topMatchAttempts: Types.TraceEvents.SelectorTiming[]; + topElapsedMs: Types.Events.SelectorTiming[]; + topMatchAttempts: Types.Events.SelectorTiming[]; }>; -export declare function generateInsight(traceParsedData: RequiredData, context: NavigationInsightContext): SlowCSSSelectorInsightResult; +export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): SlowCSSSelectorInsightResult; diff --git a/public/models/trace/insights/SlowCSSSelector.js b/public/models/trace/insights/SlowCSSSelector.js index 9c93c6223..7b4c143dc 100644 --- a/public/models/trace/insights/SlowCSSSelector.js +++ b/public/models/trace/insights/SlowCSSSelector.js @@ -25,15 +25,14 @@ function aggregateSelectorStats(data) { } return [...selectorMap.values()]; } -export function generateInsight(traceParsedData, context) { - const selectorStatsData = traceParsedData.SelectorStats; - const nav = traceParsedData.Meta.navigationsByNavigationId.get(context.navigationId); - if (!nav) { - throw new Error('no trace navigation'); - } +export function generateInsight( +// eslint-disable-next-line @typescript-eslint/no-unused-vars +parsedTrace, context) { + const selectorStatsData = parsedTrace.SelectorStats; if (!selectorStatsData) { throw new Error('no selector stats data'); } + // TODO(b/357047902): this needs to be scoped to the context.window. const selectorTimings = aggregateSelectorStats(selectorStatsData.dataForUpdateLayoutEvent); let totalElapsedUs = 0; let totalMatchAttempts = 0; diff --git a/public/models/trace/insights/SlowCSSSelector.js.map b/public/models/trace/insights/SlowCSSSelector.js.map index febccdc93..ef3b702a4 100644 --- a/public/models/trace/insights/SlowCSSSelector.js.map +++ b/public/models/trace/insights/SlowCSSSelector.js.map @@ -1 +1 @@ -{"version":3,"file":"SlowCSSSelector.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/SlowCSSSelector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {type SelectorTiming, SelectorTimingsKey} from '../types/TraceEvents.js';\nimport * as Types from '../types/types.js';\n\nimport {type InsightResult, type NavigationInsightContext, type RequiredData} from './types.js';\n\nexport function deps(): ['SelectorStats'] {\n return ['SelectorStats'];\n}\n\nexport type SlowCSSSelectorInsightResult = InsightResult<{\n totalElapsedMs: Types.Timing.MilliSeconds,\n totalMatchAttempts: number,\n totalMatchCount: number,\n topElapsedMs: Types.TraceEvents.SelectorTiming[],\n topMatchAttempts: Types.TraceEvents.SelectorTiming[],\n}>;\n\nfunction aggregateSelectorStats(data: Map): SelectorTiming[] {\n const selectorMap = new Map();\n\n for (const value of data.values()) {\n for (const timing of value.timings) {\n const key = timing[SelectorTimingsKey.Selector] + '_' + timing[SelectorTimingsKey.StyleSheetId];\n const findTiming = selectorMap.get(key);\n if (findTiming !== undefined) {\n findTiming[SelectorTimingsKey.Elapsed] += timing[SelectorTimingsKey.Elapsed];\n findTiming[SelectorTimingsKey.FastRejectCount] += timing[SelectorTimingsKey.FastRejectCount];\n findTiming[SelectorTimingsKey.MatchAttempts] += timing[SelectorTimingsKey.MatchAttempts];\n findTiming[SelectorTimingsKey.MatchCount] += timing[SelectorTimingsKey.MatchCount];\n } else {\n selectorMap.set(key, {...timing});\n }\n }\n }\n\n return [...selectorMap.values()];\n}\n\nexport function generateInsight(\n traceParsedData: RequiredData, context: NavigationInsightContext): SlowCSSSelectorInsightResult {\n const selectorStatsData = traceParsedData.SelectorStats;\n\n const nav = traceParsedData.Meta.navigationsByNavigationId.get(context.navigationId);\n if (!nav) {\n throw new Error('no trace navigation');\n }\n\n if (!selectorStatsData) {\n throw new Error('no selector stats data');\n }\n\n const selectorTimings = aggregateSelectorStats(selectorStatsData.dataForUpdateLayoutEvent);\n\n let totalElapsedUs = 0;\n let totalMatchAttempts = 0;\n let totalMatchCount = 0;\n\n selectorTimings.map(timing => {\n totalElapsedUs += timing[SelectorTimingsKey.Elapsed];\n totalMatchAttempts += timing[SelectorTimingsKey.MatchAttempts];\n totalMatchCount += timing[SelectorTimingsKey.MatchCount];\n });\n\n // sort by elapsed time\n const sortByElapsedMs = selectorTimings.toSorted((a, b) => {\n return b[SelectorTimingsKey.Elapsed] - a[SelectorTimingsKey.Elapsed];\n });\n\n // sort by match attempts\n const sortByMatchAttempts = selectorTimings.toSorted((a, b) => {\n return b[SelectorTimingsKey.MatchAttempts] - a[SelectorTimingsKey.MatchAttempts];\n });\n\n return {\n totalElapsedMs: Types.Timing.MilliSeconds(totalElapsedUs / 1000.0),\n totalMatchAttempts,\n totalMatchCount,\n topElapsedMs: sortByElapsedMs.slice(0, 3),\n topMatchAttempts: sortByMatchAttempts.slice(0, 3),\n };\n}\n"]} \ No newline at end of file +{"version":3,"file":"SlowCSSSelector.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/SlowCSSSelector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {type SelectorTiming, SelectorTimingsKey} from '../types/TraceEvents.js';\nimport * as Types from '../types/types.js';\n\nimport {type InsightResult, type InsightSetContext, type RequiredData} from './types.js';\n\nexport function deps(): ['SelectorStats'] {\n return ['SelectorStats'];\n}\n\nexport type SlowCSSSelectorInsightResult = InsightResult<{\n totalElapsedMs: Types.Timing.MilliSeconds,\n totalMatchAttempts: number,\n totalMatchCount: number,\n topElapsedMs: Types.Events.SelectorTiming[],\n topMatchAttempts: Types.Events.SelectorTiming[],\n}>;\n\nfunction aggregateSelectorStats(data: Map): SelectorTiming[] {\n const selectorMap = new Map();\n\n for (const value of data.values()) {\n for (const timing of value.timings) {\n const key = timing[SelectorTimingsKey.Selector] + '_' + timing[SelectorTimingsKey.StyleSheetId];\n const findTiming = selectorMap.get(key);\n if (findTiming !== undefined) {\n findTiming[SelectorTimingsKey.Elapsed] += timing[SelectorTimingsKey.Elapsed];\n findTiming[SelectorTimingsKey.FastRejectCount] += timing[SelectorTimingsKey.FastRejectCount];\n findTiming[SelectorTimingsKey.MatchAttempts] += timing[SelectorTimingsKey.MatchAttempts];\n findTiming[SelectorTimingsKey.MatchCount] += timing[SelectorTimingsKey.MatchCount];\n } else {\n selectorMap.set(key, {...timing});\n }\n }\n }\n\n return [...selectorMap.values()];\n}\n\nexport function generateInsight(\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n parsedTrace: RequiredData, context: InsightSetContext): SlowCSSSelectorInsightResult {\n const selectorStatsData = parsedTrace.SelectorStats;\n\n if (!selectorStatsData) {\n throw new Error('no selector stats data');\n }\n\n // TODO(b/357047902): this needs to be scoped to the context.window.\n const selectorTimings = aggregateSelectorStats(selectorStatsData.dataForUpdateLayoutEvent);\n\n let totalElapsedUs = 0;\n let totalMatchAttempts = 0;\n let totalMatchCount = 0;\n\n selectorTimings.map(timing => {\n totalElapsedUs += timing[SelectorTimingsKey.Elapsed];\n totalMatchAttempts += timing[SelectorTimingsKey.MatchAttempts];\n totalMatchCount += timing[SelectorTimingsKey.MatchCount];\n });\n\n // sort by elapsed time\n const sortByElapsedMs = selectorTimings.toSorted((a, b) => {\n return b[SelectorTimingsKey.Elapsed] - a[SelectorTimingsKey.Elapsed];\n });\n\n // sort by match attempts\n const sortByMatchAttempts = selectorTimings.toSorted((a, b) => {\n return b[SelectorTimingsKey.MatchAttempts] - a[SelectorTimingsKey.MatchAttempts];\n });\n\n return {\n totalElapsedMs: Types.Timing.MilliSeconds(totalElapsedUs / 1000.0),\n totalMatchAttempts,\n totalMatchCount,\n topElapsedMs: sortByElapsedMs.slice(0, 3),\n topMatchAttempts: sortByMatchAttempts.slice(0, 3),\n };\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/SlowCSSSelector.test.js b/public/models/trace/insights/SlowCSSSelector.test.js index efc794444..e48560b60 100644 --- a/public/models/trace/insights/SlowCSSSelector.test.js +++ b/public/models/trace/insights/SlowCSSSelector.test.js @@ -1,2 +1,3 @@ "use strict"; +// TODO(b/357047902): needs tests. //# sourceMappingURL=SlowCSSSelector.test.js.map \ No newline at end of file diff --git a/public/models/trace/insights/SlowCSSSelector.test.js.map b/public/models/trace/insights/SlowCSSSelector.test.js.map index 536c725e5..ecf19038a 100644 --- a/public/models/trace/insights/SlowCSSSelector.test.js.map +++ b/public/models/trace/insights/SlowCSSSelector.test.js.map @@ -1 +1 @@ -{"version":3,"file":"SlowCSSSelector.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/SlowCSSSelector.test.ts"],"names":[],"mappings":"","sourcesContent":[""]} \ No newline at end of file +{"version":3,"file":"SlowCSSSelector.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/SlowCSSSelector.test.ts"],"names":[],"mappings":";AAAA,kCAAkC","sourcesContent":["// TODO(b/357047902): needs tests.\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/ThirdPartyWeb.d.ts b/public/models/trace/insights/ThirdPartyWeb.d.ts index 96bb76ba8..d86276f61 100644 --- a/public/models/trace/insights/ThirdPartyWeb.d.ts +++ b/public/models/trace/insights/ThirdPartyWeb.d.ts @@ -1,19 +1,18 @@ import * as ThirdPartyWeb from '../../../third_party/third-party-web/third-party-web.js'; import * as Types from '../types/types.js'; -import { type InsightResult, type NavigationInsightContext, type RequiredData } from './types.js'; +import { type InsightResult, type InsightSetContext, type RequiredData } from './types.js'; export declare function deps(): ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting']; -type Entity = typeof ThirdPartyWeb.ThirdPartyWeb.entities[number]; -interface Summary { +export type Entity = typeof ThirdPartyWeb.ThirdPartyWeb.entities[number]; +export interface Summary { transferSize: number; mainThreadTime: Types.Timing.MicroSeconds; } export type ThirdPartyWebInsightResult = InsightResult<{ - entityByRequest: Map; - requestsByEntity: Map; - summaryByRequest: Map; + entityByRequest: Map; + requestsByEntity: Map; + summaryByRequest: Map; summaryByEntity: Map; /** The entity for this navigation's URL. Any other entity is from a third party. */ firstPartyEntity?: Entity; }>; -export declare function generateInsight(traceData: RequiredData, context: NavigationInsightContext): ThirdPartyWebInsightResult; -export {}; +export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): ThirdPartyWebInsightResult; diff --git a/public/models/trace/insights/ThirdPartyWeb.js b/public/models/trace/insights/ThirdPartyWeb.js index 03bd42938..68573fd91 100644 --- a/public/models/trace/insights/ThirdPartyWeb.js +++ b/public/models/trace/insights/ThirdPartyWeb.js @@ -69,13 +69,9 @@ function makeUpEntity(entityCache, url) { entityCache.set(rootDomain, unrecognizedEntity); return unrecognizedEntity; } -function getSelfTimeByUrl(traceData, context) { - const startTime = Types.Timing.MicroSeconds(context.navigation.ts); - // TODO: we should also pass a time window for this navigation to each insight. Use infinity for now. - const endTime = Types.Timing.MicroSeconds(Number.POSITIVE_INFINITY); - const bounds = Helpers.Timing.traceWindowFromMicroSeconds(startTime, endTime); +function getSelfTimeByUrl(parsedTrace, context) { const selfTimeByUrl = new Map(); - for (const process of traceData.Renderer.processes.values()) { + for (const process of parsedTrace.Renderer.processes.values()) { if (!process.isOnMainFrame) { continue; } @@ -85,14 +81,14 @@ function getSelfTimeByUrl(traceData, context) { break; } for (const event of thread.entries) { - if (!Helpers.Timing.eventIsInBounds(event, bounds)) { + if (!Helpers.Timing.eventIsInBounds(event, context.bounds)) { continue; } - const node = traceData.Renderer.entryToNode.get(event); + const node = parsedTrace.Renderer.entryToNode.get(event); if (!node || !node.selfTime) { continue; } - const url = Extras.URLForEntry.get(traceData, event); + const url = Extras.URLForEntry.get(parsedTrace, event); if (!url) { continue; } @@ -133,13 +129,17 @@ function getSummaries(requests, entityByRequest, selfTimeByUrl) { } return { byEntity, byRequest, requestsByEntity }; } -export function generateInsight(traceData, context) { +export function generateInsight(parsedTrace, context) { const networkRequests = []; - for (const req of traceData.NetworkRequests.byTime) { + for (const req of parsedTrace.NetworkRequests.byTime) { + if (!context.navigation) { + break; + } if (req.args.data.frame !== context.frameId) { continue; } - const navigation = Helpers.Trace.getNavigationForTraceEvent(req, context.frameId, traceData.Meta.navigationsByFrameId); + // TODO(crbug.com/366049346): use context.bounds instead + const navigation = Helpers.Trace.getNavigationForTraceEvent(req, context.frameId, parsedTrace.Meta.navigationsByFrameId); if (navigation === context.navigation) { networkRequests.push(req); } @@ -153,9 +153,10 @@ export function generateInsight(traceData, context) { entityByRequest.set(request, entity); } } - const selfTimeByUrl = getSelfTimeByUrl(traceData, context); + const selfTimeByUrl = getSelfTimeByUrl(parsedTrace, context); + // TODO(crbug.com/352244718): re-work to still collect main thread activity if no request is present const summaries = getSummaries(networkRequests, entityByRequest, selfTimeByUrl); - const firstPartyUrl = context.navigation.args.data?.url ?? traceData.Meta.mainFrameURL; + const firstPartyUrl = context.navigation?.args.data?.url ?? parsedTrace.Meta.mainFrameURL; const firstPartyEntity = ThirdPartyWeb.ThirdPartyWeb.getEntity(firstPartyUrl) || makeUpEntity(madeUpEntityCache, firstPartyUrl); return { entityByRequest, diff --git a/public/models/trace/insights/ThirdPartyWeb.js.map b/public/models/trace/insights/ThirdPartyWeb.js.map index dcc059986..f86bcb1a8 100644 --- a/public/models/trace/insights/ThirdPartyWeb.js.map +++ b/public/models/trace/insights/ThirdPartyWeb.js.map @@ -1 +1 @@ -{"version":3,"file":"ThirdPartyWeb.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/ThirdPartyWeb.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as ThirdPartyWeb from '../../../third_party/third-party-web/third-party-web.js';\nimport * as Extras from '../extras/extras.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {type InsightResult, type NavigationInsightContext, type RequiredData} from './types.js';\n\nexport function deps(): ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting'] {\n return ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting'];\n}\n\ntype Entity = typeof ThirdPartyWeb.ThirdPartyWeb.entities[number];\n\ninterface Summary {\n transferSize: number;\n mainThreadTime: Types.Timing.MicroSeconds;\n}\n\nexport type ThirdPartyWebInsightResult = InsightResult<{\n entityByRequest: Map,\n requestsByEntity: Map,\n summaryByRequest: Map,\n summaryByEntity: Map,\n /** The entity for this navigation's URL. Any other entity is from a third party. */\n firstPartyEntity?: Entity,\n}>;\n\n/**\n * Returns the origin portion of a Chrome extension URL.\n */\nfunction getChromeExtensionOrigin(url: URL): string {\n return url.protocol + '//' + url.host;\n}\n\nfunction makeUpChromeExtensionEntity(entityCache: Map, url: string, extensionName?: string): Entity {\n const parsedUrl = new URL(url);\n const origin = getChromeExtensionOrigin(parsedUrl);\n const host = new URL(origin).host;\n const name = extensionName || host;\n\n const cachedEntity = entityCache.get(origin);\n if (cachedEntity) {\n return cachedEntity;\n }\n\n const chromeExtensionEntity = {\n name,\n company: name,\n category: 'Chrome Extension',\n homepage: 'https://chromewebstore.google.com/detail/' + host,\n categories: [],\n domains: [],\n averageExecutionTime: 0,\n totalExecutionTime: 0,\n totalOccurrences: 0,\n };\n\n entityCache.set(origin, chromeExtensionEntity);\n return chromeExtensionEntity;\n}\n\nfunction makeUpEntity(entityCache: Map, url: string): Entity|undefined {\n if (url.startsWith('chrome-extension:')) {\n return makeUpChromeExtensionEntity(entityCache, url);\n }\n\n // Make up an entity only for valid http/https URLs.\n if (!url.startsWith('http')) {\n return;\n }\n\n // NOTE: Lighthouse uses a tld database to determine the root domain, but here\n // we are using third party web's database. Doesn't really work for the case of classifying\n // domains 3pweb doesn't know about, so it will just give us a guess.\n const rootDomain = ThirdPartyWeb.ThirdPartyWeb.getRootDomain(url);\n if (!rootDomain) {\n return;\n }\n\n if (entityCache.has(rootDomain)) {\n return entityCache.get(rootDomain);\n }\n\n const unrecognizedEntity = {\n name: rootDomain,\n company: rootDomain,\n category: '',\n categories: [],\n domains: [rootDomain],\n averageExecutionTime: 0,\n totalExecutionTime: 0,\n totalOccurrences: 0,\n isUnrecognized: true,\n };\n entityCache.set(rootDomain, unrecognizedEntity);\n return unrecognizedEntity;\n}\n\ninterface SummaryMaps {\n byEntity: Map;\n byRequest: Map;\n requestsByEntity: Map;\n}\n\nfunction getSelfTimeByUrl(\n traceData: RequiredData, context: NavigationInsightContext): Map {\n const startTime = Types.Timing.MicroSeconds(context.navigation.ts);\n // TODO: we should also pass a time window for this navigation to each insight. Use infinity for now.\n const endTime = Types.Timing.MicroSeconds(Number.POSITIVE_INFINITY);\n const bounds = Helpers.Timing.traceWindowFromMicroSeconds(startTime, endTime);\n const selfTimeByUrl = new Map();\n\n for (const process of traceData.Renderer.processes.values()) {\n if (!process.isOnMainFrame) {\n continue;\n }\n\n for (const thread of process.threads.values()) {\n if (thread.name === 'CrRendererMain') {\n if (!thread.tree) {\n break;\n }\n\n for (const event of thread.entries) {\n if (!Helpers.Timing.eventIsInBounds(event, bounds)) {\n continue;\n }\n\n const node = traceData.Renderer.entryToNode.get(event);\n if (!node || !node.selfTime) {\n continue;\n }\n\n const url = Extras.URLForEntry.get(traceData as Handlers.Types.TraceParseData, event);\n if (!url) {\n continue;\n }\n\n selfTimeByUrl.set(url, node.selfTime + (selfTimeByUrl.get(url) ?? 0));\n }\n }\n }\n }\n\n return selfTimeByUrl;\n}\n\nfunction getSummaries(\n requests: Types.TraceEvents.SyntheticNetworkRequest[],\n entityByRequest: Map,\n selfTimeByUrl: Map): SummaryMaps {\n const byRequest = new Map();\n const byEntity = new Map();\n const defaultSummary: Summary = {transferSize: 0, mainThreadTime: Types.Timing.MicroSeconds(0)};\n\n for (const request of requests) {\n const urlSummary = byRequest.get(request) || {...defaultSummary};\n urlSummary.transferSize += request.args.data.encodedDataLength;\n urlSummary.mainThreadTime =\n Types.Timing.MicroSeconds(urlSummary.mainThreadTime + (selfTimeByUrl.get(request.args.data.url) ?? 0));\n byRequest.set(request, urlSummary);\n }\n\n // Map each request's stat to a particular entity.\n const requestsByEntity = new Map();\n for (const [request, requestSummary] of byRequest.entries()) {\n const entity = entityByRequest.get(request);\n if (!entity) {\n byRequest.delete(request);\n continue;\n }\n\n const entitySummary = byEntity.get(entity) || {...defaultSummary};\n entitySummary.transferSize += requestSummary.transferSize;\n entitySummary.mainThreadTime =\n Types.Timing.MicroSeconds(entitySummary.mainThreadTime + requestSummary.mainThreadTime);\n byEntity.set(entity, entitySummary);\n\n const entityRequests = requestsByEntity.get(entity) || [];\n entityRequests.push(request);\n requestsByEntity.set(entity, entityRequests);\n }\n\n return {byEntity, byRequest, requestsByEntity};\n}\n\nexport function generateInsight(\n traceData: RequiredData, context: NavigationInsightContext): ThirdPartyWebInsightResult {\n const networkRequests = [];\n for (const req of traceData.NetworkRequests.byTime) {\n if (req.args.data.frame !== context.frameId) {\n continue;\n }\n\n const navigation =\n Helpers.Trace.getNavigationForTraceEvent(req, context.frameId, traceData.Meta.navigationsByFrameId);\n if (navigation === context.navigation) {\n networkRequests.push(req);\n }\n }\n\n const entityByRequest = new Map();\n const madeUpEntityCache = new Map();\n for (const request of networkRequests) {\n const url = request.args.data.url;\n const entity = ThirdPartyWeb.ThirdPartyWeb.getEntity(url) ?? makeUpEntity(madeUpEntityCache, url);\n if (entity) {\n entityByRequest.set(request, entity);\n }\n }\n\n const selfTimeByUrl = getSelfTimeByUrl(traceData, context);\n const summaries = getSummaries(networkRequests, entityByRequest, selfTimeByUrl);\n\n const firstPartyUrl = context.navigation.args.data?.url ?? traceData.Meta.mainFrameURL;\n const firstPartyEntity =\n ThirdPartyWeb.ThirdPartyWeb.getEntity(firstPartyUrl) || makeUpEntity(madeUpEntityCache, firstPartyUrl);\n\n return {\n entityByRequest,\n requestsByEntity: summaries.requestsByEntity,\n summaryByRequest: summaries.byRequest,\n summaryByEntity: summaries.byEntity,\n firstPartyEntity,\n };\n}\n"]} \ No newline at end of file +{"version":3,"file":"ThirdPartyWeb.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/ThirdPartyWeb.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as ThirdPartyWeb from '../../../third_party/third-party-web/third-party-web.js';\nimport * as Extras from '../extras/extras.js';\nimport type * as Handlers from '../handlers/handlers.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {type InsightResult, type InsightSetContext, type RequiredData} from './types.js';\n\nexport function deps(): ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting'] {\n return ['Meta', 'NetworkRequests', 'Renderer', 'ImagePainting'];\n}\n\nexport type Entity = typeof ThirdPartyWeb.ThirdPartyWeb.entities[number];\n\nexport interface Summary {\n transferSize: number;\n mainThreadTime: Types.Timing.MicroSeconds;\n}\n\nexport type ThirdPartyWebInsightResult = InsightResult<{\n entityByRequest: Map,\n requestsByEntity: Map,\n summaryByRequest: Map,\n summaryByEntity: Map,\n /** The entity for this navigation's URL. Any other entity is from a third party. */\n firstPartyEntity?: Entity,\n}>;\n\n/**\n * Returns the origin portion of a Chrome extension URL.\n */\nfunction getChromeExtensionOrigin(url: URL): string {\n return url.protocol + '//' + url.host;\n}\n\nfunction makeUpChromeExtensionEntity(entityCache: Map, url: string, extensionName?: string): Entity {\n const parsedUrl = new URL(url);\n const origin = getChromeExtensionOrigin(parsedUrl);\n const host = new URL(origin).host;\n const name = extensionName || host;\n\n const cachedEntity = entityCache.get(origin);\n if (cachedEntity) {\n return cachedEntity;\n }\n\n const chromeExtensionEntity = {\n name,\n company: name,\n category: 'Chrome Extension',\n homepage: 'https://chromewebstore.google.com/detail/' + host,\n categories: [],\n domains: [],\n averageExecutionTime: 0,\n totalExecutionTime: 0,\n totalOccurrences: 0,\n };\n\n entityCache.set(origin, chromeExtensionEntity);\n return chromeExtensionEntity;\n}\n\nfunction makeUpEntity(entityCache: Map, url: string): Entity|undefined {\n if (url.startsWith('chrome-extension:')) {\n return makeUpChromeExtensionEntity(entityCache, url);\n }\n\n // Make up an entity only for valid http/https URLs.\n if (!url.startsWith('http')) {\n return;\n }\n\n // NOTE: Lighthouse uses a tld database to determine the root domain, but here\n // we are using third party web's database. Doesn't really work for the case of classifying\n // domains 3pweb doesn't know about, so it will just give us a guess.\n const rootDomain = ThirdPartyWeb.ThirdPartyWeb.getRootDomain(url);\n if (!rootDomain) {\n return;\n }\n\n if (entityCache.has(rootDomain)) {\n return entityCache.get(rootDomain);\n }\n\n const unrecognizedEntity = {\n name: rootDomain,\n company: rootDomain,\n category: '',\n categories: [],\n domains: [rootDomain],\n averageExecutionTime: 0,\n totalExecutionTime: 0,\n totalOccurrences: 0,\n isUnrecognized: true,\n };\n entityCache.set(rootDomain, unrecognizedEntity);\n return unrecognizedEntity;\n}\n\ninterface SummaryMaps {\n byEntity: Map;\n byRequest: Map;\n requestsByEntity: Map;\n}\n\nfunction getSelfTimeByUrl(parsedTrace: RequiredData, context: InsightSetContext): Map {\n const selfTimeByUrl = new Map();\n\n for (const process of parsedTrace.Renderer.processes.values()) {\n if (!process.isOnMainFrame) {\n continue;\n }\n\n for (const thread of process.threads.values()) {\n if (thread.name === 'CrRendererMain') {\n if (!thread.tree) {\n break;\n }\n\n for (const event of thread.entries) {\n if (!Helpers.Timing.eventIsInBounds(event, context.bounds)) {\n continue;\n }\n\n const node = parsedTrace.Renderer.entryToNode.get(event);\n if (!node || !node.selfTime) {\n continue;\n }\n\n const url = Extras.URLForEntry.get(parsedTrace as Handlers.Types.ParsedTrace, event);\n if (!url) {\n continue;\n }\n\n selfTimeByUrl.set(url, node.selfTime + (selfTimeByUrl.get(url) ?? 0));\n }\n }\n }\n }\n\n return selfTimeByUrl;\n}\n\nfunction getSummaries(\n requests: Types.Events.SyntheticNetworkRequest[],\n entityByRequest: Map,\n selfTimeByUrl: Map): SummaryMaps {\n const byRequest = new Map();\n const byEntity = new Map();\n const defaultSummary: Summary = {transferSize: 0, mainThreadTime: Types.Timing.MicroSeconds(0)};\n\n for (const request of requests) {\n const urlSummary = byRequest.get(request) || {...defaultSummary};\n urlSummary.transferSize += request.args.data.encodedDataLength;\n urlSummary.mainThreadTime =\n Types.Timing.MicroSeconds(urlSummary.mainThreadTime + (selfTimeByUrl.get(request.args.data.url) ?? 0));\n byRequest.set(request, urlSummary);\n }\n\n // Map each request's stat to a particular entity.\n const requestsByEntity = new Map();\n for (const [request, requestSummary] of byRequest.entries()) {\n const entity = entityByRequest.get(request);\n if (!entity) {\n byRequest.delete(request);\n continue;\n }\n\n const entitySummary = byEntity.get(entity) || {...defaultSummary};\n entitySummary.transferSize += requestSummary.transferSize;\n entitySummary.mainThreadTime =\n Types.Timing.MicroSeconds(entitySummary.mainThreadTime + requestSummary.mainThreadTime);\n byEntity.set(entity, entitySummary);\n\n const entityRequests = requestsByEntity.get(entity) || [];\n entityRequests.push(request);\n requestsByEntity.set(entity, entityRequests);\n }\n\n return {byEntity, byRequest, requestsByEntity};\n}\n\nexport function generateInsight(\n parsedTrace: RequiredData, context: InsightSetContext): ThirdPartyWebInsightResult {\n const networkRequests = [];\n for (const req of parsedTrace.NetworkRequests.byTime) {\n if (!context.navigation) {\n break;\n }\n\n if (req.args.data.frame !== context.frameId) {\n continue;\n }\n\n // TODO(crbug.com/366049346): use context.bounds instead\n const navigation =\n Helpers.Trace.getNavigationForTraceEvent(req, context.frameId, parsedTrace.Meta.navigationsByFrameId);\n if (navigation === context.navigation) {\n networkRequests.push(req);\n }\n }\n\n const entityByRequest = new Map();\n const madeUpEntityCache = new Map();\n for (const request of networkRequests) {\n const url = request.args.data.url;\n const entity = ThirdPartyWeb.ThirdPartyWeb.getEntity(url) ?? makeUpEntity(madeUpEntityCache, url);\n if (entity) {\n entityByRequest.set(request, entity);\n }\n }\n\n const selfTimeByUrl = getSelfTimeByUrl(parsedTrace, context);\n // TODO(crbug.com/352244718): re-work to still collect main thread activity if no request is present\n const summaries = getSummaries(networkRequests, entityByRequest, selfTimeByUrl);\n\n const firstPartyUrl = context.navigation?.args.data?.url ?? parsedTrace.Meta.mainFrameURL;\n const firstPartyEntity =\n ThirdPartyWeb.ThirdPartyWeb.getEntity(firstPartyUrl) || makeUpEntity(madeUpEntityCache, firstPartyUrl);\n\n return {\n entityByRequest,\n requestsByEntity: summaries.requestsByEntity,\n summaryByRequest: summaries.byRequest,\n summaryByEntity: summaries.byEntity,\n firstPartyEntity,\n };\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/ThirdPartyWeb.test.d.ts b/public/models/trace/insights/ThirdPartyWeb.test.d.ts index 848a04692..29614938e 100644 --- a/public/models/trace/insights/ThirdPartyWeb.test.d.ts +++ b/public/models/trace/insights/ThirdPartyWeb.test.d.ts @@ -1,5 +1,4 @@ -import type * as TraceModel from '../trace.js'; export declare function processTrace(testContext: Mocha.Suite | Mocha.Context | null, traceFile: string): Promise<{ - data: Readonly>; - insights: TraceModel.Insights.Types.TraceInsightData; + data: Readonly>; + insights: import("./types.js").TraceInsightSets; }>; diff --git a/public/models/trace/insights/ThirdPartyWeb.test.js b/public/models/trace/insights/ThirdPartyWeb.test.js index def392cff..d1ef92081 100644 --- a/public/models/trace/insights/ThirdPartyWeb.test.js +++ b/public/models/trace/insights/ThirdPartyWeb.test.js @@ -2,30 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; +import { getFirstOrError, getInsight } from '../../../testing/InsightHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; export async function processTrace(testContext, traceFile) { - const { traceData, insights } = await TraceLoader.traceEngine(testContext, traceFile); + const { parsedTrace, insights } = await TraceLoader.traceEngine(testContext, traceFile); if (!insights) { throw new Error('No insights'); } - return { data: traceData, insights }; -} -function getInsight(insights, navigationId) { - const navInsights = insights.get(navigationId); - if (!navInsights) { - throw new Error('missing navInsights'); - } - const insight = navInsights.ThirdPartyWeb; - if (insight instanceof Error) { - throw insight; - } - return insight; + return { data: parsedTrace, insights }; } describeWithEnvironment('ThirdPartyWeb', function () { it('categorizes third party web requests (simple)', async () => { const { data, insights } = await processTrace(this, 'load-simple.json.gz'); - assert.strictEqual(insights.size, 1); - const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value); + assert.strictEqual(insights.size, 2); + const insight = getInsight('ThirdPartyWeb', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values())); const entityByRequestResult = [...insight.entityByRequest.entries()].map(([request, entity]) => { return [request.args.data.url, entity.name]; }); @@ -69,7 +59,7 @@ describeWithEnvironment('ThirdPartyWeb', function () { it('categorizes third party web requests (complex)', async () => { const { data, insights } = await processTrace(this, 'lantern/paul/trace.json.gz'); assert.strictEqual(insights.size, 1); - const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value); + const insight = getInsight('ThirdPartyWeb', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values())); const entityNames = [...insight.entityByRequest.values()].map(entity => entity.name); assert.deepEqual([...new Set(entityNames)], [ 'paulirish.com', diff --git a/public/models/trace/insights/ThirdPartyWeb.test.js.map b/public/models/trace/insights/ThirdPartyWeb.test.js.map index 3559e8760..323028416 100644 --- a/public/models/trace/insights/ThirdPartyWeb.test.js.map +++ b/public/models/trace/insights/ThirdPartyWeb.test.js.map @@ -1 +1 @@ -{"version":3,"file":"ThirdPartyWeb.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/ThirdPartyWeb.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport type * as TraceModel from '../trace.js';\n\nexport async function processTrace(testContext: Mocha.Suite|Mocha.Context|null, traceFile: string) {\n const {traceData, insights} = await TraceLoader.traceEngine(testContext, traceFile);\n if (!insights) {\n throw new Error('No insights');\n }\n\n return {data: traceData, insights};\n}\n\nfunction getInsight(insights: TraceModel.Insights.Types.TraceInsightData, navigationId: string) {\n const navInsights = insights.get(navigationId);\n if (!navInsights) {\n throw new Error('missing navInsights');\n }\n const insight = navInsights.ThirdPartyWeb;\n if (insight instanceof Error) {\n throw insight;\n }\n return insight;\n}\n\ndescribeWithEnvironment('ThirdPartyWeb', function() {\n it('categorizes third party web requests (simple)', async () => {\n const {data, insights} = await processTrace(this, 'load-simple.json.gz');\n assert.strictEqual(insights.size, 1);\n const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value);\n\n const entityByRequestResult = [...insight.entityByRequest.entries()].map(([request, entity]) => {\n return [request.args.data.url, entity.name];\n });\n assert.deepEqual(entityByRequestResult, [\n ['http://localhost:8080/', 'localhost'],\n ['https://fonts.googleapis.com/css2?family=Orelega+One&display=swap', 'Google Fonts'],\n ['http://localhost:8080/styles.css', 'localhost'],\n ['http://localhost:8080/blocking.js', 'localhost'],\n ['http://localhost:8080/module.js', 'localhost'],\n ['https://fonts.gstatic.com/s/orelegaone/v1/3qTpojOggD2XtAdFb-QXZFt93kY.woff2', 'Google Fonts'],\n ]);\n\n const requestsByEntityResult = [...insight.requestsByEntity.entries()].map(([entity, requests]) => {\n return [entity.name, requests.map(r => r.args.data.url)];\n });\n assert.deepEqual(\n requestsByEntityResult,\n [\n [\n 'localhost',\n [\n 'http://localhost:8080/',\n 'http://localhost:8080/styles.css',\n 'http://localhost:8080/blocking.js',\n 'http://localhost:8080/module.js',\n ],\n ],\n [\n 'Google Fonts',\n [\n 'https://fonts.googleapis.com/css2?family=Orelega+One&display=swap',\n 'https://fonts.gstatic.com/s/orelegaone/v1/3qTpojOggD2XtAdFb-QXZFt93kY.woff2',\n ],\n ],\n ],\n );\n\n const summaryResult = [...insight.summaryByEntity.entries()].map(([entity, summary]) => {\n return [entity.name, summary];\n });\n assert.deepEqual(summaryResult, [\n ['localhost', {transferSize: 751, mainThreadTime: 26381}],\n ['Google Fonts', {transferSize: 0, mainThreadTime: 0}],\n ]);\n });\n\n it('categorizes third party web requests (complex)', async () => {\n const {data, insights} = await processTrace(this, 'lantern/paul/trace.json.gz');\n assert.strictEqual(insights.size, 1);\n const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value);\n\n const entityNames = [...insight.entityByRequest.values()].map(entity => entity.name);\n assert.deepEqual([...new Set(entityNames)], [\n 'paulirish.com',\n 'Google Tag Manager',\n 'Google Fonts',\n 'Google Analytics',\n 'Disqus',\n 'Firebase',\n ]);\n\n const requestsByEntityResult = [...insight.requestsByEntity.entries()].map(([entity, requests]) => {\n return [entity.name, requests.map(r => r.args.data.url)];\n });\n assert.deepEqual(\n requestsByEntityResult,\n [\n [\n 'paulirish.com',\n [\n 'https://www.paulirish.com/',\n 'https://www.paulirish.com/assets/wikipedia-flamechart.jpg',\n 'https://www.paulirish.com/avatar150.jpg',\n 'https://www.paulirish.com/javascripts/modernizr-2.0.js',\n 'https://www.paulirish.com/javascripts/ender.js',\n 'https://www.paulirish.com/javascripts/octopress.js',\n 'https://www.paulirish.com/javascripts/firebase-performance-standalone.js',\n 'https://www.paulirish.com/images/noise.png?1418840251',\n 'https://www.paulirish.com/images/code_bg.png?1418840251',\n 'https://www.paulirish.com/favicon.ico',\n ],\n ],\n [\n 'Google Tag Manager',\n [\n 'https://www.googletagmanager.com/gtag/js?id=G-PGXNGYWP8E',\n ],\n ],\n [\n 'Google Fonts',\n [\n 'https://fonts.googleapis.com/css?family=PT+Serif:regular,italic,bold|PT+Sans:regular,italic,bold|Droid+Sans:400,700|Lato:700,900',\n 'https://fonts.gstatic.com/s/droidsans/v18/SlGVmQWMvZQIdix7AFxXkHNSbRYXags.woff2',\n 'https://fonts.gstatic.com/s/lato/v24/S6u9w4BMUTPHh6UVSwiPGQ3q5d0.woff2',\n 'https://fonts.gstatic.com/s/ptsans/v17/jizaRExUiTo99u79D0KExcOPIDU.woff2',\n 'https://fonts.gstatic.com/s/ptsans/v17/jizfRExUiTo99u79B_mh0O6tLR8a8zI.woff2',\n 'https://fonts.gstatic.com/s/droidsans/v18/SlGWmQWMvZQIdix7AFxXmMh3eDs1ZyHKpWg.woff2',\n 'https://fonts.gstatic.com/s/ptserif/v18/EJRVQgYoZZY2vCFuvAFWzr-_dSb_.woff2',\n ],\n ],\n [\n 'Google Analytics',\n [\n 'https://www.google-analytics.com/analytics.js',\n 'https://www.google-analytics.com/g/collect?v=2&tid=G-PGXNGYWP8E>m=45je4580v880158425za200&_p=1715625261583&gcd=13l3l3l3l1&npa=0&dma=0&cid=414801335.1715625262&ul=en-us&sr=412x823&uaa=&uab=64&uafvl=Not%252FA)Brand%3B8.0.0.0%7CChromium%3B126.0.6475.0%7CGoogle%2520Chrome%3B126.0.6475.0&uamb=1&uam=moto%20g%20power%20(2022)&uap=Android&uapv=11.0&uaw=0&are=1&frm=0&pscdl=noapi&_s=1&sid=1715625261&sct=1&seg=0&dl=https%3A%2F%2Fwww.paulirish.com%2F&dt=Paul%20Irish&en=page_view&_fv=1&_nsi=1&_ss=1&_ee=1&tfd=353',\n 'https://www.google-analytics.com/j/collect?v=1&_v=j101&a=272264939&t=pageview&_s=1&dl=https%3A%2F%2Fwww.paulirish.com%2F&ul=en-us&de=UTF-8&dt=Paul%20Irish&sd=30-bit&sr=412x823&vp=412x823&je=0&_u=IADAAEABAAAAACAAI~&jid=1388679807&gjid=654531532&cid=414801335.1715625262&tid=UA-692547-2&_gid=1964734610.1715625262&_r=1&_slc=1&z=1746264594',\n ],\n ],\n [\n 'Disqus',\n [\n 'https://paulirish.disqus.com/count.js',\n ],\n ],\n [\n 'Firebase',\n [\n 'https://firebaseinstallations.googleapis.com/v1/projects/paulirishcom/installations',\n 'https://firebaseremoteconfig.googleapis.com/v1/projects/paulirishcom/namespaces/fireperf:fetch?key=AIzaSyCGxLbbFQxH4BV1fY0RODlxTos9nJa2l_g',\n ],\n ],\n ],\n );\n\n const summaryResult = [...insight.summaryByEntity.entries()].map(([entity, summary]) => {\n return [entity.name, summary];\n });\n assert.deepEqual(summaryResult, [\n ['paulirish.com', {transferSize: 157130, mainThreadTime: 6626}],\n ['Google Tag Manager', {transferSize: 95375, mainThreadTime: 83}],\n ['Google Fonts', {transferSize: 80003, mainThreadTime: 0}],\n ['Google Analytics', {transferSize: 20865, mainThreadTime: 97}],\n ['Disqus', {transferSize: 1551, mainThreadTime: 23}],\n ['Firebase', {transferSize: 2847, mainThreadTime: 0}],\n ]);\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"ThirdPartyWeb.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/ThirdPartyWeb.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {getFirstOrError, getInsight} from '../../../testing/InsightHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\n\nexport async function processTrace(testContext: Mocha.Suite|Mocha.Context|null, traceFile: string) {\n const {parsedTrace, insights} = await TraceLoader.traceEngine(testContext, traceFile);\n if (!insights) {\n throw new Error('No insights');\n }\n\n return {data: parsedTrace, insights};\n}\n\ndescribeWithEnvironment('ThirdPartyWeb', function() {\n it('categorizes third party web requests (simple)', async () => {\n const {data, insights} = await processTrace(this, 'load-simple.json.gz');\n assert.strictEqual(insights.size, 2);\n const insight =\n getInsight('ThirdPartyWeb', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values()));\n\n const entityByRequestResult = [...insight.entityByRequest.entries()].map(([request, entity]) => {\n return [request.args.data.url, entity.name];\n });\n assert.deepEqual(entityByRequestResult, [\n ['http://localhost:8080/', 'localhost'],\n ['https://fonts.googleapis.com/css2?family=Orelega+One&display=swap', 'Google Fonts'],\n ['http://localhost:8080/styles.css', 'localhost'],\n ['http://localhost:8080/blocking.js', 'localhost'],\n ['http://localhost:8080/module.js', 'localhost'],\n ['https://fonts.gstatic.com/s/orelegaone/v1/3qTpojOggD2XtAdFb-QXZFt93kY.woff2', 'Google Fonts'],\n ]);\n\n const requestsByEntityResult = [...insight.requestsByEntity.entries()].map(([entity, requests]) => {\n return [entity.name, requests.map(r => r.args.data.url)];\n });\n assert.deepEqual(\n requestsByEntityResult,\n [\n [\n 'localhost',\n [\n 'http://localhost:8080/',\n 'http://localhost:8080/styles.css',\n 'http://localhost:8080/blocking.js',\n 'http://localhost:8080/module.js',\n ],\n ],\n [\n 'Google Fonts',\n [\n 'https://fonts.googleapis.com/css2?family=Orelega+One&display=swap',\n 'https://fonts.gstatic.com/s/orelegaone/v1/3qTpojOggD2XtAdFb-QXZFt93kY.woff2',\n ],\n ],\n ],\n );\n\n const summaryResult = [...insight.summaryByEntity.entries()].map(([entity, summary]) => {\n return [entity.name, summary];\n });\n assert.deepEqual(summaryResult, [\n ['localhost', {transferSize: 751, mainThreadTime: 26381}],\n ['Google Fonts', {transferSize: 0, mainThreadTime: 0}],\n ]);\n });\n\n it('categorizes third party web requests (complex)', async () => {\n const {data, insights} = await processTrace(this, 'lantern/paul/trace.json.gz');\n assert.strictEqual(insights.size, 1);\n const insight =\n getInsight('ThirdPartyWeb', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values()));\n\n const entityNames = [...insight.entityByRequest.values()].map(entity => entity.name);\n assert.deepEqual([...new Set(entityNames)], [\n 'paulirish.com',\n 'Google Tag Manager',\n 'Google Fonts',\n 'Google Analytics',\n 'Disqus',\n 'Firebase',\n ]);\n\n const requestsByEntityResult = [...insight.requestsByEntity.entries()].map(([entity, requests]) => {\n return [entity.name, requests.map(r => r.args.data.url)];\n });\n assert.deepEqual(\n requestsByEntityResult,\n [\n [\n 'paulirish.com',\n [\n 'https://www.paulirish.com/',\n 'https://www.paulirish.com/assets/wikipedia-flamechart.jpg',\n 'https://www.paulirish.com/avatar150.jpg',\n 'https://www.paulirish.com/javascripts/modernizr-2.0.js',\n 'https://www.paulirish.com/javascripts/ender.js',\n 'https://www.paulirish.com/javascripts/octopress.js',\n 'https://www.paulirish.com/javascripts/firebase-performance-standalone.js',\n 'https://www.paulirish.com/images/noise.png?1418840251',\n 'https://www.paulirish.com/images/code_bg.png?1418840251',\n 'https://www.paulirish.com/favicon.ico',\n ],\n ],\n [\n 'Google Tag Manager',\n [\n 'https://www.googletagmanager.com/gtag/js?id=G-PGXNGYWP8E',\n ],\n ],\n [\n 'Google Fonts',\n [\n 'https://fonts.googleapis.com/css?family=PT+Serif:regular,italic,bold|PT+Sans:regular,italic,bold|Droid+Sans:400,700|Lato:700,900',\n 'https://fonts.gstatic.com/s/droidsans/v18/SlGVmQWMvZQIdix7AFxXkHNSbRYXags.woff2',\n 'https://fonts.gstatic.com/s/lato/v24/S6u9w4BMUTPHh6UVSwiPGQ3q5d0.woff2',\n 'https://fonts.gstatic.com/s/ptsans/v17/jizaRExUiTo99u79D0KExcOPIDU.woff2',\n 'https://fonts.gstatic.com/s/ptsans/v17/jizfRExUiTo99u79B_mh0O6tLR8a8zI.woff2',\n 'https://fonts.gstatic.com/s/droidsans/v18/SlGWmQWMvZQIdix7AFxXmMh3eDs1ZyHKpWg.woff2',\n 'https://fonts.gstatic.com/s/ptserif/v18/EJRVQgYoZZY2vCFuvAFWzr-_dSb_.woff2',\n ],\n ],\n [\n 'Google Analytics',\n [\n 'https://www.google-analytics.com/analytics.js',\n 'https://www.google-analytics.com/g/collect?v=2&tid=G-PGXNGYWP8E>m=45je4580v880158425za200&_p=1715625261583&gcd=13l3l3l3l1&npa=0&dma=0&cid=414801335.1715625262&ul=en-us&sr=412x823&uaa=&uab=64&uafvl=Not%252FA)Brand%3B8.0.0.0%7CChromium%3B126.0.6475.0%7CGoogle%2520Chrome%3B126.0.6475.0&uamb=1&uam=moto%20g%20power%20(2022)&uap=Android&uapv=11.0&uaw=0&are=1&frm=0&pscdl=noapi&_s=1&sid=1715625261&sct=1&seg=0&dl=https%3A%2F%2Fwww.paulirish.com%2F&dt=Paul%20Irish&en=page_view&_fv=1&_nsi=1&_ss=1&_ee=1&tfd=353',\n 'https://www.google-analytics.com/j/collect?v=1&_v=j101&a=272264939&t=pageview&_s=1&dl=https%3A%2F%2Fwww.paulirish.com%2F&ul=en-us&de=UTF-8&dt=Paul%20Irish&sd=30-bit&sr=412x823&vp=412x823&je=0&_u=IADAAEABAAAAACAAI~&jid=1388679807&gjid=654531532&cid=414801335.1715625262&tid=UA-692547-2&_gid=1964734610.1715625262&_r=1&_slc=1&z=1746264594',\n ],\n ],\n [\n 'Disqus',\n [\n 'https://paulirish.disqus.com/count.js',\n ],\n ],\n [\n 'Firebase',\n [\n 'https://firebaseinstallations.googleapis.com/v1/projects/paulirishcom/installations',\n 'https://firebaseremoteconfig.googleapis.com/v1/projects/paulirishcom/namespaces/fireperf:fetch?key=AIzaSyCGxLbbFQxH4BV1fY0RODlxTos9nJa2l_g',\n ],\n ],\n ],\n );\n\n const summaryResult = [...insight.summaryByEntity.entries()].map(([entity, summary]) => {\n return [entity.name, summary];\n });\n assert.deepEqual(summaryResult, [\n ['paulirish.com', {transferSize: 157130, mainThreadTime: 6626}],\n ['Google Tag Manager', {transferSize: 95375, mainThreadTime: 83}],\n ['Google Fonts', {transferSize: 80003, mainThreadTime: 0}],\n ['Google Analytics', {transferSize: 20865, mainThreadTime: 97}],\n ['Disqus', {transferSize: 1551, mainThreadTime: 23}],\n ['Firebase', {transferSize: 2847, mainThreadTime: 0}],\n ]);\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/Viewport.d.ts b/public/models/trace/insights/Viewport.d.ts index 914b28511..2d289391d 100644 --- a/public/models/trace/insights/Viewport.d.ts +++ b/public/models/trace/insights/Viewport.d.ts @@ -1,8 +1,8 @@ import type * as Types from '../types/types.js'; -import { type InsightResult, type NavigationInsightContext, type RequiredData } from './types.js'; +import { type InsightResult, type InsightSetContext, type RequiredData } from './types.js'; export declare function deps(): ['Meta', 'UserInteractions']; export type ViewportInsightResult = InsightResult<{ mobileOptimized: boolean | null; - viewportEvent?: Types.TraceEvents.TraceEventParseMetaViewport; + viewportEvent?: Types.Events.ParseMetaViewport; }>; -export declare function generateInsight(traceParsedData: RequiredData, context: NavigationInsightContext): ViewportInsightResult; +export declare function generateInsight(parsedTrace: RequiredData, context: InsightSetContext): ViewportInsightResult; diff --git a/public/models/trace/insights/Viewport.js b/public/models/trace/insights/Viewport.js index 87ccec653..acac946c8 100644 --- a/public/models/trace/insights/Viewport.js +++ b/public/models/trace/insights/Viewport.js @@ -6,12 +6,16 @@ import { InsightWarning } from './types.js'; export function deps() { return ['Meta', 'UserInteractions']; } -export function generateInsight(traceParsedData, context) { - const compositorEvents = traceParsedData.UserInteractions.beginCommitCompositorFrameEvents.filter(event => { +export function generateInsight(parsedTrace, context) { + // TODO(crbug.com/366049346) + if (!context.navigation) { + return { mobileOptimized: null }; + } + const compositorEvents = parsedTrace.UserInteractions.beginCommitCompositorFrameEvents.filter(event => { if (event.args.frame !== context.frameId) { return false; } - const navigation = Helpers.Trace.getNavigationForTraceEvent(event, context.frameId, traceParsedData.Meta.navigationsByFrameId); + const navigation = Helpers.Trace.getNavigationForTraceEvent(event, context.frameId, parsedTrace.Meta.navigationsByFrameId); return navigation === context.navigation; }); if (!compositorEvents.length) { @@ -21,11 +25,11 @@ export function generateInsight(traceParsedData, context) { warnings: [InsightWarning.NO_LAYOUT], }; } - const viewportEvent = traceParsedData.UserInteractions.parseMetaViewportEvents.find(event => { + const viewportEvent = parsedTrace.UserInteractions.parseMetaViewportEvents.find(event => { if (event.args.data.frame !== context.frameId) { return false; } - const navigation = Helpers.Trace.getNavigationForTraceEvent(event, context.frameId, traceParsedData.Meta.navigationsByFrameId); + const navigation = Helpers.Trace.getNavigationForTraceEvent(event, context.frameId, parsedTrace.Meta.navigationsByFrameId); return navigation === context.navigation; }); // Returns true only if all events are mobile optimized. diff --git a/public/models/trace/insights/Viewport.js.map b/public/models/trace/insights/Viewport.js.map index 0ccf70293..3bde83070 100644 --- a/public/models/trace/insights/Viewport.js.map +++ b/public/models/trace/insights/Viewport.js.map @@ -1 +1 @@ -{"version":3,"file":"Viewport.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/Viewport.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AAGjD,OAAO,EAAqB,cAAc,EAAmD,MAAM,YAAY,CAAC;AAEhH,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;AACtC,CAAC;AAOD,MAAM,UAAU,eAAe,CAC3B,eAA0C,EAAE,OAAiC;IAC/E,MAAM,gBAAgB,GAAG,eAAe,CAAC,gBAAgB,CAAC,gCAAgC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;QACxG,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YACzC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,UAAU,GACZ,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE,eAAe,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAChH,OAAO,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC;QAC7B,uCAAuC;QACvC,OAAO;YACL,eAAe,EAAE,IAAI;YACrB,QAAQ,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC;SACrC,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,eAAe,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;QAC1F,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YAC9C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,UAAU,GACZ,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE,eAAe,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAChH,OAAO,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,wDAAwD;IACxD,KAAK,MAAM,KAAK,IAAI,gBAAgB,EAAE,CAAC;QACrC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACpC,OAAO;gBACL,eAAe,EAAE,KAAK;gBACtB,aAAa;aACd,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,eAAe,EAAE,IAAI;QACrB,aAAa;KACd,CAAC;AACJ,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Helpers from '../helpers/helpers.js';\nimport type * as Types from '../types/types.js';\n\nimport {type InsightResult, InsightWarning, type NavigationInsightContext, type RequiredData} from './types.js';\n\nexport function deps(): ['Meta', 'UserInteractions'] {\n return ['Meta', 'UserInteractions'];\n}\n\nexport type ViewportInsightResult = InsightResult<{\n mobileOptimized: boolean | null,\n viewportEvent?: Types.TraceEvents.TraceEventParseMetaViewport,\n}>;\n\nexport function generateInsight(\n traceParsedData: RequiredData, context: NavigationInsightContext): ViewportInsightResult {\n const compositorEvents = traceParsedData.UserInteractions.beginCommitCompositorFrameEvents.filter(event => {\n if (event.args.frame !== context.frameId) {\n return false;\n }\n\n const navigation =\n Helpers.Trace.getNavigationForTraceEvent(event, context.frameId, traceParsedData.Meta.navigationsByFrameId);\n return navigation === context.navigation;\n });\n\n if (!compositorEvents.length) {\n // Trace doesn't have the data we need.\n return {\n mobileOptimized: null,\n warnings: [InsightWarning.NO_LAYOUT],\n };\n }\n\n const viewportEvent = traceParsedData.UserInteractions.parseMetaViewportEvents.find(event => {\n if (event.args.data.frame !== context.frameId) {\n return false;\n }\n\n const navigation =\n Helpers.Trace.getNavigationForTraceEvent(event, context.frameId, traceParsedData.Meta.navigationsByFrameId);\n return navigation === context.navigation;\n });\n\n // Returns true only if all events are mobile optimized.\n for (const event of compositorEvents) {\n if (!event.args.is_mobile_optimized) {\n return {\n mobileOptimized: false,\n viewportEvent,\n };\n }\n }\n\n return {\n mobileOptimized: true,\n viewportEvent,\n };\n}\n"]} \ No newline at end of file +{"version":3,"file":"Viewport.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/Viewport.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AAGjD,OAAO,EAA6C,cAAc,EAAoB,MAAM,YAAY,CAAC;AAEzG,MAAM,UAAU,IAAI;IAClB,OAAO,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;AACtC,CAAC;AAOD,MAAM,UAAU,eAAe,CAC3B,WAAsC,EAAE,OAA0B;IACpE,4BAA4B;IAC5B,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QACxB,OAAO,EAAC,eAAe,EAAE,IAAI,EAAC,CAAC;IACjC,CAAC;IAED,MAAM,gBAAgB,GAAG,WAAW,CAAC,gBAAgB,CAAC,gCAAgC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;QACpG,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YACzC,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,UAAU,GACZ,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC5G,OAAO,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC;QAC7B,uCAAuC;QACvC,OAAO;YACL,eAAe,EAAE,IAAI;YACrB,QAAQ,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC;SACrC,CAAC;IACJ,CAAC;IAED,MAAM,aAAa,GAAG,WAAW,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;QACtF,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,EAAE,CAAC;YAC9C,OAAO,KAAK,CAAC;QACf,CAAC;QAED,MAAM,UAAU,GACZ,OAAO,CAAC,KAAK,CAAC,0BAA0B,CAAC,KAAK,EAAE,OAAO,CAAC,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC5G,OAAO,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,wDAAwD;IACxD,KAAK,MAAM,KAAK,IAAI,gBAAgB,EAAE,CAAC;QACrC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACpC,OAAO;gBACL,eAAe,EAAE,KAAK;gBACtB,aAAa;aACd,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO;QACL,eAAe,EAAE,IAAI;QACrB,aAAa;KACd,CAAC;AACJ,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Helpers from '../helpers/helpers.js';\nimport type * as Types from '../types/types.js';\n\nimport {type InsightResult, type InsightSetContext, InsightWarning, type RequiredData} from './types.js';\n\nexport function deps(): ['Meta', 'UserInteractions'] {\n return ['Meta', 'UserInteractions'];\n}\n\nexport type ViewportInsightResult = InsightResult<{\n mobileOptimized: boolean | null,\n viewportEvent?: Types.Events.ParseMetaViewport,\n}>;\n\nexport function generateInsight(\n parsedTrace: RequiredData, context: InsightSetContext): ViewportInsightResult {\n // TODO(crbug.com/366049346)\n if (!context.navigation) {\n return {mobileOptimized: null};\n }\n\n const compositorEvents = parsedTrace.UserInteractions.beginCommitCompositorFrameEvents.filter(event => {\n if (event.args.frame !== context.frameId) {\n return false;\n }\n\n const navigation =\n Helpers.Trace.getNavigationForTraceEvent(event, context.frameId, parsedTrace.Meta.navigationsByFrameId);\n return navigation === context.navigation;\n });\n\n if (!compositorEvents.length) {\n // Trace doesn't have the data we need.\n return {\n mobileOptimized: null,\n warnings: [InsightWarning.NO_LAYOUT],\n };\n }\n\n const viewportEvent = parsedTrace.UserInteractions.parseMetaViewportEvents.find(event => {\n if (event.args.data.frame !== context.frameId) {\n return false;\n }\n\n const navigation =\n Helpers.Trace.getNavigationForTraceEvent(event, context.frameId, parsedTrace.Meta.navigationsByFrameId);\n return navigation === context.navigation;\n });\n\n // Returns true only if all events are mobile optimized.\n for (const event of compositorEvents) {\n if (!event.args.is_mobile_optimized) {\n return {\n mobileOptimized: false,\n viewportEvent,\n };\n }\n }\n\n return {\n mobileOptimized: true,\n viewportEvent,\n };\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/Viewport.test.d.ts b/public/models/trace/insights/Viewport.test.d.ts index cdc9b4ae2..aec4618f2 100644 --- a/public/models/trace/insights/Viewport.test.d.ts +++ b/public/models/trace/insights/Viewport.test.d.ts @@ -1,5 +1,5 @@ -import * as TraceModel from '../trace.js'; +import * as Trace from '../trace.js'; export declare function processTrace(testContext: Mocha.Suite | Mocha.Context | null, traceFile: string): Promise<{ - data: Readonly>; - insights: TraceModel.Insights.Types.TraceInsightData; + data: Readonly>; + insights: Trace.Insights.Types.TraceInsightSets; }>; diff --git a/public/models/trace/insights/Viewport.test.js b/public/models/trace/insights/Viewport.test.js index 7f7fc0c12..7bf44b205 100644 --- a/public/models/trace/insights/Viewport.test.js +++ b/public/models/trace/insights/Viewport.test.js @@ -2,46 +2,32 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; +import { createContextForNavigation, getFirstOrError, getInsight } from '../../../testing/InsightHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; -import * as TraceModel from '../trace.js'; +import * as Trace from '../trace.js'; export async function processTrace(testContext, traceFile) { - const { traceData, insights } = await TraceLoader.traceEngine(testContext, traceFile); + const { parsedTrace, insights } = await TraceLoader.traceEngine(testContext, traceFile); if (!insights) { throw new Error('No insights'); } - return { data: traceData, insights }; -} -function getInsight(insights, navigationId) { - const navInsights = insights.get(navigationId); - if (!navInsights) { - throw new Error('missing navInsights'); - } - const insight = navInsights.Viewport; - if (insight instanceof Error) { - throw insight; - } - return insight; + return { data: parsedTrace, insights }; } describeWithEnvironment('Viewport', function () { it('detects mobile optimized viewport', async () => { const { data, insights } = await processTrace(this, 'lcp-images.json.gz'); - const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value); + const insight = getInsight('Viewport', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values())); assert.strictEqual(insight.mobileOptimized, true); }); it('detects mobile unoptimized viewport', async () => { const { data } = await processTrace(this, 'lcp-images.json.gz'); - const [navigationId, navigation] = data.Meta.navigationsByNavigationId.entries().next().value; - const context = { - frameId: data.Meta.mainFrameId, - navigationId, - navigation, - }; + const navigation = getFirstOrError(data.Meta.navigationsByNavigationId.values()); + const context = createContextForNavigation(navigation, data.Meta.mainFrameId); const events = data.UserInteractions.beginCommitCompositorFrameEvents.filter(event => event.args.frame === context.frameId); assert.isNotEmpty(events); for (const event of events) { event.args.is_mobile_optimized = false; } - const insight = TraceModel.Insights.InsightRunners.Viewport.generateInsight(data, context); + const insight = Trace.Insights.InsightRunners.Viewport.generateInsight(data, context); assert.strictEqual(insight.mobileOptimized, false); }); }); diff --git a/public/models/trace/insights/Viewport.test.js.map b/public/models/trace/insights/Viewport.test.js.map index 8fbc00aed..3ea4351ba 100644 --- a/public/models/trace/insights/Viewport.test.js.map +++ b/public/models/trace/insights/Viewport.test.js.map @@ -1 +1 @@ -{"version":3,"file":"Viewport.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/Viewport.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,EAAC,uBAAuB,EAAC,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EAAC,WAAW,EAAC,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,UAAU,MAAM,aAAa,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAA2C,EAAE,SAAiB;IAC/F,MAAM,EAAC,SAAS,EAAE,QAAQ,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IACpF,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,EAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAC,CAAC;AACrC,CAAC;AAED,SAAS,UAAU,CAAC,QAAoD,EAAE,YAAoB;IAC5F,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAC/C,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACzC,CAAC;IACD,MAAM,OAAO,GAAG,WAAW,CAAC,QAAQ,CAAC;IACrC,IAAI,OAAO,YAAY,KAAK,EAAE,CAAC;QAC7B,MAAM,OAAO,CAAC;IAChB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,uBAAuB,CAAC,UAAU,EAAE;IAClC,EAAE,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;QACjD,MAAM,EAAC,IAAI,EAAE,QAAQ,EAAC,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;QACxE,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,IAAI,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC;QAE9F,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,EAAC,IAAI,EAAC,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;QAE9D,MAAM,CAAC,YAAY,EAAE,UAAU,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;QAC9F,MAAM,OAAO,GAAG;YACd,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW;YAC9B,YAAY;YACZ,UAAU;SACX,CAAC;QAEF,MAAM,MAAM,GACR,IAAI,CAAC,gBAAgB,CAAC,gCAAgC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;QACjH,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC1B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,mBAAmB,GAAG,KAAK,CAAC;QACzC,CAAC;QAED,MAAM,OAAO,GAAG,UAAU,CAAC,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC3F,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as TraceModel from '../trace.js';\n\nexport async function processTrace(testContext: Mocha.Suite|Mocha.Context|null, traceFile: string) {\n const {traceData, insights} = await TraceLoader.traceEngine(testContext, traceFile);\n if (!insights) {\n throw new Error('No insights');\n }\n\n return {data: traceData, insights};\n}\n\nfunction getInsight(insights: TraceModel.Insights.Types.TraceInsightData, navigationId: string) {\n const navInsights = insights.get(navigationId);\n if (!navInsights) {\n throw new Error('missing navInsights');\n }\n const insight = navInsights.Viewport;\n if (insight instanceof Error) {\n throw insight;\n }\n return insight;\n}\n\ndescribeWithEnvironment('Viewport', function() {\n it('detects mobile optimized viewport', async () => {\n const {data, insights} = await processTrace(this, 'lcp-images.json.gz');\n const insight = getInsight(insights, data.Meta.navigationsByNavigationId.keys().next().value);\n\n assert.strictEqual(insight.mobileOptimized, true);\n });\n\n it('detects mobile unoptimized viewport', async () => {\n const {data} = await processTrace(this, 'lcp-images.json.gz');\n\n const [navigationId, navigation] = data.Meta.navigationsByNavigationId.entries().next().value;\n const context = {\n frameId: data.Meta.mainFrameId,\n navigationId,\n navigation,\n };\n\n const events =\n data.UserInteractions.beginCommitCompositorFrameEvents.filter(event => event.args.frame === context.frameId);\n assert.isNotEmpty(events);\n for (const event of events) {\n event.args.is_mobile_optimized = false;\n }\n\n const insight = TraceModel.Insights.InsightRunners.Viewport.generateInsight(data, context);\n assert.strictEqual(insight.mobileOptimized, false);\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"Viewport.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/Viewport.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,EAAC,uBAAuB,EAAC,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EAAC,0BAA0B,EAAE,eAAe,EAAE,UAAU,EAAC,MAAM,oCAAoC,CAAC;AAC3G,OAAO,EAAC,WAAW,EAAC,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,KAAK,MAAM,aAAa,CAAC;AAErC,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,WAA2C,EAAE,SAAiB;IAC/F,MAAM,EAAC,WAAW,EAAE,QAAQ,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IACtF,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;IACjC,CAAC;IAED,OAAO,EAAC,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAC,CAAC;AACvC,CAAC;AAED,uBAAuB,CAAC,UAAU,EAAE;IAClC,EAAE,CAAC,mCAAmC,EAAE,KAAK,IAAI,EAAE;QACjD,MAAM,EAAC,IAAI,EAAE,QAAQ,EAAC,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;QACxE,MAAM,OAAO,GAAG,UAAU,CAAC,UAAU,EAAE,QAAQ,EAAE,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QAEhH,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,EAAC,IAAI,EAAC,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;QAC9D,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAC,MAAM,EAAE,CAAC,CAAC;QACjF,MAAM,OAAO,GAAG,0BAA0B,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC9E,MAAM,MAAM,GACR,IAAI,CAAC,gBAAgB,CAAC,gCAAgC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;QACjH,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAC1B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,KAAK,CAAC,IAAI,CAAC,mBAAmB,GAAG,KAAK,CAAC;QACzC,CAAC;QAED,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACtF,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {createContextForNavigation, getFirstOrError, getInsight} from '../../../testing/InsightHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Trace from '../trace.js';\n\nexport async function processTrace(testContext: Mocha.Suite|Mocha.Context|null, traceFile: string) {\n const {parsedTrace, insights} = await TraceLoader.traceEngine(testContext, traceFile);\n if (!insights) {\n throw new Error('No insights');\n }\n\n return {data: parsedTrace, insights};\n}\n\ndescribeWithEnvironment('Viewport', function() {\n it('detects mobile optimized viewport', async () => {\n const {data, insights} = await processTrace(this, 'lcp-images.json.gz');\n const insight = getInsight('Viewport', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values()));\n\n assert.strictEqual(insight.mobileOptimized, true);\n });\n\n it('detects mobile unoptimized viewport', async () => {\n const {data} = await processTrace(this, 'lcp-images.json.gz');\n const navigation = getFirstOrError(data.Meta.navigationsByNavigationId.values());\n const context = createContextForNavigation(navigation, data.Meta.mainFrameId);\n const events =\n data.UserInteractions.beginCommitCompositorFrameEvents.filter(event => event.args.frame === context.frameId);\n assert.isNotEmpty(events);\n for (const event of events) {\n event.args.is_mobile_optimized = false;\n }\n\n const insight = Trace.Insights.InsightRunners.Viewport.generateInsight(data, context);\n assert.strictEqual(insight.mobileOptimized, false);\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/insights-tsconfig.json b/public/models/trace/insights/insights-tsconfig.json index 00e3a748e..eb917a81b 100644 --- a/public/models/trace/insights/insights-tsconfig.json +++ b/public/models/trace/insights/insights-tsconfig.json @@ -32,6 +32,7 @@ "../../../../../../../front_end/models/trace/insights/Common.ts", "../../../../../../../front_end/models/trace/insights/CumulativeLayoutShift.ts", "../../../../../../../front_end/models/trace/insights/DocumentLatency.ts", + "../../../../../../../front_end/models/trace/insights/FontDisplay.ts", "../../../../../../../front_end/models/trace/insights/InsightRunners.ts", "../../../../../../../front_end/models/trace/insights/InteractionToNextPaint.ts", "../../../../../../../front_end/models/trace/insights/LargestContentfulPaint.ts", diff --git a/public/models/trace/insights/types.d.ts b/public/models/trace/insights/types.d.ts index a7d59372b..2689e97c8 100644 --- a/public/models/trace/insights/types.d.ts +++ b/public/models/trace/insights/types.d.ts @@ -3,17 +3,24 @@ import type * as Lantern from '../lantern/lantern.js'; import type * as Types from '../types/types.js'; import type * as InsightsRunners from './InsightRunners.js'; /** - * Context for which navigation an insight should look at. + * Context for the portion of the trace an insight should look at. */ -export interface NavigationInsightContext { +export type InsightSetContext = InsightSetContextWithoutNavigation | InsightSetContextWithNavigation; +export interface InsightSetContextWithoutNavigation { + bounds: Types.Timing.TraceWindowMicroSeconds; frameId: string; - navigation: Types.TraceEvents.TraceEventNavigationStart; + navigation?: never; +} +export interface InsightSetContextWithNavigation { + bounds: Types.Timing.TraceWindowMicroSeconds; + frameId: string; + navigation: Types.Events.NavigationStart; navigationId: string; lantern?: LanternContext; } export interface LanternContext { - graph: Lantern.Graph.Node; - simulator: Lantern.Simulation.Simulator; + graph: Lantern.Graph.Node; + simulator: Lantern.Simulation.Simulator; metrics: Record; } export type InsightRunnersType = typeof InsightsRunners; @@ -34,10 +41,17 @@ export type InsightResult> = R & { }; }; /** - * Contains insights for a specific navigation. + * Contains insights for a specific navigation. If a trace began after a navigation already started, + * this could instead represent the duration from the beginning of the trace up to the first recorded + * navigation (or the end of the trace). */ -export type NavigationInsightData = { - [I in keyof InsightRunnersType]: ReturnType | Error; +export type InsightSets = { + id: string; + label: string; + frameId: string; + bounds: Types.Timing.TraceWindowMicroSeconds; + data: InsightResults; + navigation?: Types.Events.NavigationStart; }; /** * Contains insights for a specific navigation. @@ -46,9 +60,14 @@ export type InsightResults = { [I in keyof InsightRunnersType]: ReturnType; }; /** - * Contains insights for the entire trace. Insights are grouped by `navigationId`. + * Contains insights for the entire trace. Insights are mostly grouped by `navigationId`, with one exception: + * + * If the analyzed trace started after the navigation, and has meaningful work with that span, there is no + * navigation to map it to. In this case NO_NAVIGATION is used for the key. + * TODO(crbug.com/366049346): Consider using a symbol. Wait until no-navigation insights are shown in the panel. */ -export type TraceInsightData = Map; +export type TraceInsightSets = Map; +export declare const NO_NAVIGATION = "NO_NAVIGATION"; /** * Represents the narrow set of dependencies defined by an insight's `deps()` function. `Meta` is always included regardless of `deps()`. */ diff --git a/public/models/trace/insights/types.js b/public/models/trace/insights/types.js index 757a34f21..c0450cec3 100644 --- a/public/models/trace/insights/types.js +++ b/public/models/trace/insights/types.js @@ -9,4 +9,5 @@ export var InsightWarning; InsightWarning["NO_DOCUMENT_REQUEST"] = "NO_DOCUMENT_REQUEST"; InsightWarning["NO_LAYOUT"] = "NO_LAYOUT"; })(InsightWarning || (InsightWarning = {})); +export const NO_NAVIGATION = 'NO_NAVIGATION'; //# sourceMappingURL=types.js.map \ No newline at end of file diff --git a/public/models/trace/insights/types.js.map b/public/models/trace/insights/types.js.map index 231e8642e..a251608f3 100644 --- a/public/models/trace/insights/types.js.map +++ b/public/models/trace/insights/types.js.map @@ -1 +1 @@ -{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/types.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AA0B7B,MAAM,CAAN,IAAY,cAMX;AAND,WAAY,cAAc;IACxB,iCAAe,CAAA;IACf,mCAAiB,CAAA;IACjB,uEAAuE;IACvE,6DAA2C,CAAA;IAC3C,yCAAuB,CAAA;AACzB,CAAC,EANW,cAAc,KAAd,cAAc,QAMzB","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Handlers from '../handlers/handlers.js';\nimport type * as Lantern from '../lantern/lantern.js';\nimport type * as Types from '../types/types.js';\n\nimport type * as InsightsRunners from './InsightRunners.js';\n\n/**\n * Context for which navigation an insight should look at.\n */\nexport interface NavigationInsightContext {\n frameId: string;\n navigation: Types.TraceEvents.TraceEventNavigationStart;\n navigationId: string;\n lantern?: LanternContext;\n}\n\nexport interface LanternContext {\n graph: Lantern.Graph.Node;\n simulator: Lantern.Simulation.Simulator;\n metrics: Record;\n}\n\nexport type InsightRunnersType = typeof InsightsRunners;\n\nexport enum InsightWarning {\n NO_FP = 'NO_FP',\n NO_LCP = 'NO_LCP',\n // No network request could be identified as the primary HTML document.\n NO_DOCUMENT_REQUEST = 'NO_DOCUMENT_REQUEST',\n NO_LAYOUT = 'NO_LAYOUT',\n}\n\nexport type InsightResult> = R&{\n warnings?: InsightWarning[],\n metricSavings?: {\n /* eslint-disable @typescript-eslint/naming-convention */\n FCP?: number,\n LCP?: number,\n TBT?: number,\n CLS?: number,\n INP?: number,\n /* eslint-enable @typescript-eslint/naming-convention */\n },\n};\n\n/**\n * Contains insights for a specific navigation.\n */\nexport type NavigationInsightData = {\n [I in keyof InsightRunnersType]: ReturnType|Error;\n};\n\n/**\n * Contains insights for a specific navigation.\n */\nexport type InsightResults = {\n [I in keyof InsightRunnersType]: ReturnType;\n};\n\n/**\n * Contains insights for the entire trace. Insights are grouped by `navigationId`.\n */\nexport type TraceInsightData = Map;\n\n/**\n * Represents the narrow set of dependencies defined by an insight's `deps()` function. `Meta` is always included regardless of `deps()`.\n */\nexport type RequiredData Array> =\n Handlers.Types.EnabledHandlerDataWithMeta[number]>>;\n"]} \ No newline at end of file +{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/insights/types.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAmC7B,MAAM,CAAN,IAAY,cAMX;AAND,WAAY,cAAc;IACxB,iCAAe,CAAA;IACf,mCAAiB,CAAA;IACjB,uEAAuE;IACvE,6DAA2C,CAAA;IAC3C,yCAAuB,CAAA;AACzB,CAAC,EANW,cAAc,KAAd,cAAc,QAMzB;AA4CD,MAAM,CAAC,MAAM,aAAa,GAAG,eAAe,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Handlers from '../handlers/handlers.js';\nimport type * as Lantern from '../lantern/lantern.js';\nimport type * as Types from '../types/types.js';\n\nimport type * as InsightsRunners from './InsightRunners.js';\n\n/**\n * Context for the portion of the trace an insight should look at.\n */\nexport type InsightSetContext = InsightSetContextWithoutNavigation|InsightSetContextWithNavigation;\n\nexport interface InsightSetContextWithoutNavigation {\n bounds: Types.Timing.TraceWindowMicroSeconds;\n frameId: string;\n navigation?: never;\n}\n\nexport interface InsightSetContextWithNavigation {\n bounds: Types.Timing.TraceWindowMicroSeconds;\n frameId: string;\n navigation: Types.Events.NavigationStart;\n navigationId: string;\n lantern?: LanternContext;\n}\n\nexport interface LanternContext {\n graph: Lantern.Graph.Node;\n simulator: Lantern.Simulation.Simulator;\n metrics: Record;\n}\n\nexport type InsightRunnersType = typeof InsightsRunners;\n\nexport enum InsightWarning {\n NO_FP = 'NO_FP',\n NO_LCP = 'NO_LCP',\n // No network request could be identified as the primary HTML document.\n NO_DOCUMENT_REQUEST = 'NO_DOCUMENT_REQUEST',\n NO_LAYOUT = 'NO_LAYOUT',\n}\n\nexport type InsightResult> = R&{\n warnings?: InsightWarning[],\n metricSavings?: {\n /* eslint-disable @typescript-eslint/naming-convention */\n FCP?: number,\n LCP?: number,\n TBT?: number,\n CLS?: number,\n INP?: number,\n /* eslint-enable @typescript-eslint/naming-convention */\n },\n};\n\n/**\n * Contains insights for a specific navigation. If a trace began after a navigation already started,\n * this could instead represent the duration from the beginning of the trace up to the first recorded\n * navigation (or the end of the trace).\n */\nexport type InsightSets = {\n id: string,\n label: string,\n frameId: string,\n bounds: Types.Timing.TraceWindowMicroSeconds,\n data: InsightResults,\n navigation?: Types.Events.NavigationStart,\n};\n\n/**\n * Contains insights for a specific navigation.\n */\nexport type InsightResults = {\n [I in keyof InsightRunnersType]: ReturnType;\n};\n\n/**\n * Contains insights for the entire trace. Insights are mostly grouped by `navigationId`, with one exception:\n *\n * If the analyzed trace started after the navigation, and has meaningful work with that span, there is no\n * navigation to map it to. In this case NO_NAVIGATION is used for the key.\n * TODO(crbug.com/366049346): Consider using a symbol. Wait until no-navigation insights are shown in the panel.\n */\nexport type TraceInsightSets = Map;\nexport const NO_NAVIGATION = 'NO_NAVIGATION';\n\n/**\n * Represents the narrow set of dependencies defined by an insight's `deps()` function. `Meta` is always included regardless of `deps()`.\n */\nexport type RequiredData Array> =\n Handlers.Types.EnabledHandlerDataWithMeta[number]>>;\n"]} \ No newline at end of file diff --git a/public/models/trace/insights/unittests-tsconfig.json b/public/models/trace/insights/unittests-tsconfig.json index 842b26adb..66eb89e60 100644 --- a/public/models/trace/insights/unittests-tsconfig.json +++ b/public/models/trace/insights/unittests-tsconfig.json @@ -40,6 +40,7 @@ "files": [ "../../../../../../../front_end/models/trace/insights/CumulativeLayoutShift.test.ts", "../../../../../../../front_end/models/trace/insights/DocumentLatency.test.ts", + "../../../../../../../front_end/models/trace/insights/FontDisplay.test.ts", "../../../../../../../front_end/models/trace/insights/InteractionToNextPaint.test.ts", "../../../../../../../front_end/models/trace/insights/LargestContentfulPaint.test.ts", "../../../../../../../front_end/models/trace/insights/RenderBlocking.test.ts", diff --git a/public/models/trace/lantern/core/NetworkAnalyzer.test.js b/public/models/trace/lantern/core/NetworkAnalyzer.test.js index fca650b3f..14fc590b5 100644 --- a/public/models/trace/lantern/core/NetworkAnalyzer.test.js +++ b/public/models/trace/lantern/core/NetworkAnalyzer.test.js @@ -3,13 +3,13 @@ // found in the LICENSE file. // @ts-nocheck TODO(crbug.com/348449529) import { TraceLoader } from '../../../../testing/TraceLoader.js'; -import * as TraceModel from '../../trace.js'; +import * as Trace from '../../trace.js'; import * as Lantern from '../lantern.js'; -import { runTraceEngine, toLanternTrace } from '../testing/testing.js'; +import { runTrace, toLanternTrace } from '../testing/testing.js'; const { NetworkAnalyzer } = Lantern.Core; async function createRequests(trace) { - const traceEngineData = await runTraceEngine(trace); - return TraceModel.LanternComputationData.createNetworkRequests(trace, traceEngineData); + const parsedTrace = await runTrace(trace); + return Trace.LanternComputationData.createNetworkRequests(trace, parsedTrace); } describe('NetworkAnalyzer', () => { let trace; diff --git a/public/models/trace/lantern/core/NetworkAnalyzer.test.js.map b/public/models/trace/lantern/core/NetworkAnalyzer.test.js.map index ac2b6bd7f..87355a6fc 100644 --- a/public/models/trace/lantern/core/NetworkAnalyzer.test.js.map +++ b/public/models/trace/lantern/core/NetworkAnalyzer.test.js.map @@ -1 +1 @@ -{"version":3,"file":"NetworkAnalyzer.test.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/core/NetworkAnalyzer.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// @ts-nocheck TODO(crbug.com/348449529)\n\nimport {TraceLoader} from '../../../../testing/TraceLoader.js';\nimport * as TraceModel from '../../trace.js';\nimport * as Lantern from '../lantern.js';\nimport {runTraceEngine, toLanternTrace} from '../testing/testing.js';\n\nconst {NetworkAnalyzer} = Lantern.Core;\n\nasync function createRequests(trace: Lantern.Types.Trace) {\n const traceEngineData = await runTraceEngine(trace);\n return TraceModel.LanternComputationData.createNetworkRequests(trace, traceEngineData);\n}\n\ndescribe('NetworkAnalyzer', () => {\n let trace: Lantern.Types.Trace;\n let traceWithRedirect: Lantern.Types.Trace;\n before(async function() {\n trace = toLanternTrace(await TraceLoader.rawEvents(this, 'lantern/paul/trace.json.gz'));\n traceWithRedirect = toLanternTrace(await TraceLoader.rawEvents(this, 'lantern/redirect/trace.json.gz'));\n });\n\n let recordId;\n\n function createRecord(opts) {\n const url = opts.url || 'https://example.com';\n if (opts.networkRequestTime) {\n opts.networkRequestTime *= 1000;\n }\n if (opts.networkEndTime) {\n opts.networkEndTime *= 1000;\n }\n return Object.assign(\n {\n url,\n requestId: recordId++,\n connectionId: 0,\n connectionReused: false,\n networkRequestTime: 10,\n networkEndTime: 10,\n transferSize: 0,\n protocol: opts.protocol || 'http/1.1',\n parsedURL: {scheme: url.match(/https?/)[0], securityOrigin: url.match(/.*\\.com/)[0]},\n timing: opts.timing || null,\n },\n opts,\n );\n }\n\n beforeEach(() => {\n recordId = 1;\n });\n\n function assertCloseEnough(valueA, valueB, threshold = 1) {\n const message = `${valueA} was not close enough to ${valueB}`;\n assert.ok(Math.abs(valueA - valueB) < threshold, message);\n }\n\n describe('#estimateIfConnectionWasReused', () => {\n it('should use built-in value when trustworthy', () => {\n const records = [\n {requestId: 1, connectionId: 1, connectionReused: false},\n {requestId: 2, connectionId: 1, connectionReused: true},\n {requestId: 3, connectionId: 2, connectionReused: false},\n {requestId: 4, connectionId: 3, connectionReused: false},\n {requestId: 5, connectionId: 2, connectionReused: true},\n ];\n\n const result = NetworkAnalyzer.estimateIfConnectionWasReused(records);\n const expected = new Map([[1, false], [2, true], [3, false], [4, false], [5, true]]);\n assert.deepStrictEqual(result, expected);\n });\n\n it('should estimate values when not trustworthy (duplicate IDs)', () => {\n const records = [\n createRecord({requestId: 1, networkRequestTime: 0, networkEndTime: 15}),\n createRecord({requestId: 2, networkRequestTime: 10, networkEndTime: 25}),\n createRecord({requestId: 3, networkRequestTime: 20, networkEndTime: 40}),\n createRecord({requestId: 4, networkRequestTime: 30, networkEndTime: 40}),\n ];\n\n const result = NetworkAnalyzer.estimateIfConnectionWasReused(records);\n const expected = new Map([[1, false], [2, false], [3, true], [4, true]]);\n assert.deepStrictEqual(result, expected);\n });\n\n it('should estimate values when not trustworthy (connectionReused nonsense)', () => {\n const records = [\n createRecord({\n requestId: 1,\n connectionId: 1,\n connectionReused: true,\n networkRequestTime: 0,\n networkEndTime: 15,\n }),\n createRecord({\n requestId: 2,\n connectionId: 1,\n connectionReused: true,\n networkRequestTime: 10,\n networkEndTime: 25,\n }),\n createRecord({\n requestId: 3,\n connectionId: 1,\n connectionReused: true,\n networkRequestTime: 20,\n networkEndTime: 40,\n }),\n createRecord({\n requestId: 4,\n connectionId: 2,\n connectionReused: false,\n networkRequestTime: 30,\n networkEndTime: 40,\n }),\n ];\n\n const result = NetworkAnalyzer.estimateIfConnectionWasReused(records);\n const expected = new Map([[1, false], [2, false], [3, true], [4, true]]);\n assert.deepStrictEqual(result, expected);\n });\n\n it('should estimate with earliest allowed reuse', () => {\n const records = [\n createRecord({requestId: 1, networkRequestTime: 0, networkEndTime: 40}),\n createRecord({requestId: 2, networkRequestTime: 10, networkEndTime: 15}),\n createRecord({requestId: 3, networkRequestTime: 20, networkEndTime: 30}),\n createRecord({requestId: 4, networkRequestTime: 35, networkEndTime: 40}),\n ];\n\n const result = NetworkAnalyzer.estimateIfConnectionWasReused(records);\n const expected = new Map([[1, false], [2, false], [3, true], [4, true]]);\n assert.deepStrictEqual(result, expected);\n });\n\n it('should work on a real trace', async () => {\n const requests = await createRequests(trace);\n const result = NetworkAnalyzer.estimateIfConnectionWasReused(requests);\n const distinctConnections = Array.from(result.values()).filter(item => !item).length;\n assert.strictEqual(result.size, 25);\n assert.strictEqual(distinctConnections, 9);\n });\n });\n\n describe('#estimateRTTByOrigin', () => {\n it('should infer from tcp timing when available', () => {\n const timing = {connectStart: 0, connectEnd: 99};\n const request = createRecord({networkRequestTime: 0, networkEndTime: 1, timing});\n const result = NetworkAnalyzer.estimateRTTByOrigin([request]);\n const expected = {min: 99, max: 99, avg: 99, median: 99};\n assert.deepStrictEqual(result.get('https://example.com'), expected);\n });\n\n it('should infer only one estimate if tcp and ssl start times are equal', () => {\n const timing = {connectStart: 0, connectEnd: 99, sslStart: 0, sslEnd: 99};\n const request = createRecord({networkRequestTime: 0, networkEndTime: 1, timing});\n const result = NetworkAnalyzer.estimateRTTByOrigin([request]);\n const expected = {min: 99, max: 99, avg: 99, median: 99};\n assert.deepStrictEqual(result.get('https://example.com'), expected);\n });\n\n it('should infer from tcp and ssl timing when available', () => {\n const timing = {connectStart: 0, connectEnd: 99, sslStart: 50, sslEnd: 99};\n const request = createRecord({networkRequestTime: 0, networkEndTime: 1, timing});\n const result = NetworkAnalyzer.estimateRTTByOrigin([request]);\n const expected = {min: 49, max: 50, avg: 49.5, median: 49.5};\n assert.deepStrictEqual(result.get('https://example.com'), expected);\n });\n\n it('should infer from connection timing when available for h3 (one estimate)', () => {\n const timing = {connectStart: 0, connectEnd: 99, sslStart: 1, sslEnd: 99};\n const request = createRecord({networkRequestTime: 0, networkEndTime: 1, timing, protocol: 'h3'});\n const result = NetworkAnalyzer.estimateRTTByOrigin([request]);\n const expected = {min: 99, max: 99, avg: 99, median: 99};\n assert.deepStrictEqual(result.get('https://example.com'), expected);\n });\n\n it('should infer from sendStart when available', () => {\n const timing = {sendStart: 150};\n // this request took 150ms before Chrome could send the request\n // i.e. DNS (maybe) + queuing (maybe) + TCP handshake took ~100ms\n // 150ms / 3 round trips ~= 50ms RTT\n const request = createRecord({networkRequestTime: 0, networkEndTime: 1, timing});\n const result = NetworkAnalyzer.estimateRTTByOrigin([request], {coarseEstimateMultiplier: 1});\n const expected = {min: 50, max: 50, avg: 50, median: 50};\n assert.deepStrictEqual(result.get('https://example.com'), expected);\n });\n\n it('should infer from download timing when available', () => {\n const timing = {receiveHeadersEnd: 100};\n // this request took 1000ms after the first byte was received to download the payload\n // i.e. it took at least one full additional roundtrip after first byte to download the rest\n // 1000ms / 1 round trip ~= 1000ms RTT\n const request = createRecord({networkRequestTime: 0, networkEndTime: 1.1, transferSize: 28 * 1024, timing});\n const result = NetworkAnalyzer.estimateRTTByOrigin([request], {\n coarseEstimateMultiplier: 1,\n useHeadersEndEstimates: false,\n });\n const expected = {min: 1000, max: 1000, avg: 1000, median: 1000};\n assert.deepStrictEqual(result.get('https://example.com'), expected);\n });\n\n it('should infer from TTFB when available', () => {\n const timing = {receiveHeadersEnd: 1000};\n const request = createRecord({networkRequestTime: 0, networkEndTime: 1, timing, resourceType: 'Other'});\n const result = NetworkAnalyzer.estimateRTTByOrigin([request], {\n coarseEstimateMultiplier: 1,\n });\n\n // this request's TTFB was 1000ms, it used SSL and was a fresh connection requiring a handshake\n // which needs ~4 RTs. We don't know its resource type so it'll be assumed that 40% of it was\n // server response time.\n // 600 ms / 4 = 150ms\n const expected = {min: 150, max: 150, avg: 150, median: 150};\n assert.deepStrictEqual(result.get('https://example.com'), expected);\n });\n\n it('should use coarse estimates on a per-origin basis', () => {\n const records = [\n createRecord({url: 'https://example.com', timing: {connectStart: 1, connectEnd: 100, sendStart: 150}}),\n createRecord({url: 'https://example2.com', timing: {sendStart: 150}}),\n ];\n const result = NetworkAnalyzer.estimateRTTByOrigin(records);\n assert.deepStrictEqual(result.get('https://example.com'), {min: 99, max: 99, avg: 99, median: 99});\n assert.deepStrictEqual(result.get('https://example2.com'), {min: 15, max: 15, avg: 15, median: 15});\n });\n\n it('should handle untrustworthy connection information', () => {\n const timing = {sendStart: 150};\n const recordA = createRecord({networkRequestTime: 0, networkEndTime: 1, timing, connectionReused: true});\n const recordB = createRecord({\n networkRequestTime: 0,\n networkEndTime: 1,\n timing,\n connectionId: 2,\n connectionReused: true,\n });\n const result = NetworkAnalyzer.estimateRTTByOrigin([recordA, recordB], {\n coarseEstimateMultiplier: 1,\n });\n const expected = {min: 50, max: 50, avg: 50, median: 50};\n assert.deepStrictEqual(result.get('https://example.com'), expected);\n });\n\n it('should work on a real trace', async () => {\n const requests = await createRequests(trace);\n const result = NetworkAnalyzer.estimateRTTByOrigin(requests);\n assertCloseEnough(result.get('https://www.paulirish.com').min, 10);\n assertCloseEnough(result.get('https://www.googletagmanager.com').min, 17);\n assertCloseEnough(result.get('https://www.google-analytics.com').min, 10);\n });\n\n it('should approximate well with either method', async () => {\n const requests = await createRequests(trace);\n const result = NetworkAnalyzer.estimateRTTByOrigin(requests).get(NetworkAnalyzer.summary);\n const resultApprox = NetworkAnalyzer\n .estimateRTTByOrigin(requests, {\n forceCoarseEstimates: true,\n })\n .get(NetworkAnalyzer.summary);\n assertCloseEnough(result.min, resultApprox.min, 20);\n assertCloseEnough(result.avg, resultApprox.avg, 30);\n assertCloseEnough(result.median, resultApprox.median, 30);\n });\n });\n\n describe('#estimateServerResponseTimeByOrigin', () => {\n it('should estimate server response time using ttfb times', () => {\n const timing = {sendEnd: 100, receiveHeadersEnd: 200};\n const request = createRecord({networkRequestTime: 0, networkEndTime: 1, timing});\n const rttByOrigin = new Map([[NetworkAnalyzer.summary, 0]]);\n const result = NetworkAnalyzer.estimateServerResponseTimeByOrigin([request], {rttByOrigin});\n const expected = {min: 100, max: 100, avg: 100, median: 100};\n assert.deepStrictEqual(result.get('https://example.com'), expected);\n });\n\n it('should subtract out rtt', () => {\n const timing = {sendEnd: 100, receiveHeadersEnd: 200};\n const request = createRecord({networkRequestTime: 0, networkEndTime: 1, timing});\n const rttByOrigin = new Map([[NetworkAnalyzer.summary, 50]]);\n const result = NetworkAnalyzer.estimateServerResponseTimeByOrigin([request], {rttByOrigin});\n const expected = {min: 50, max: 50, avg: 50, median: 50};\n assert.deepStrictEqual(result.get('https://example.com'), expected);\n });\n\n it('should compute rtts when not provided', () => {\n const timing = {connectStart: 5, connectEnd: 55, sendEnd: 100, receiveHeadersEnd: 200};\n const request = createRecord({networkRequestTime: 0, networkEndTime: 1, timing});\n const result = NetworkAnalyzer.estimateServerResponseTimeByOrigin([request]);\n const expected = {min: 50, max: 50, avg: 50, median: 50};\n assert.deepStrictEqual(result.get('https://example.com'), expected);\n });\n\n it('should work on a real trace', async () => {\n const requests = await createRequests(trace);\n const result = NetworkAnalyzer.estimateServerResponseTimeByOrigin(requests);\n assertCloseEnough(result.get('https://www.paulirish.com').avg, 35);\n assertCloseEnough(result.get('https://www.googletagmanager.com').avg, 8);\n assertCloseEnough(result.get('https://www.google-analytics.com').avg, 8);\n });\n\n it('should approximate well with either method', async () => {\n const requests = await createRequests(trace);\n const result = NetworkAnalyzer.estimateServerResponseTimeByOrigin(requests).get(\n NetworkAnalyzer.summary,\n );\n const resultApprox = NetworkAnalyzer\n .estimateServerResponseTimeByOrigin(requests, {\n forceCoarseEstimates: true,\n })\n .get(NetworkAnalyzer.summary);\n assertCloseEnough(result.min, resultApprox.min, 20);\n assertCloseEnough(result.avg, resultApprox.avg, 30);\n assertCloseEnough(result.median, resultApprox.median, 30);\n });\n });\n\n describe('#estimateThroughput', () => {\n const estimateThroughput = NetworkAnalyzer.estimateThroughput;\n\n function createThroughputRecord(responseHeadersEndTimeInS, networkEndTimeInS, extras) {\n return Object.assign(\n {\n responseHeadersEndTime: responseHeadersEndTimeInS * 1000,\n networkEndTime: networkEndTimeInS * 1000,\n transferSize: 1000,\n finished: true,\n failed: false,\n statusCode: 200,\n url: 'https://google.com/logo.png',\n parsedURL: {scheme: 'https'},\n },\n extras,\n );\n }\n\n it('should return Infinity for no/missing records', () => {\n assert.strictEqual(estimateThroughput([]), Infinity);\n assert.strictEqual(estimateThroughput([createThroughputRecord(0, 0, {finished: false})]), Infinity);\n });\n\n it('should compute correctly for a basic waterfall', () => {\n const result = estimateThroughput([\n createThroughputRecord(0, 1),\n createThroughputRecord(1, 2),\n createThroughputRecord(2, 6),\n ]);\n\n assert.strictEqual(result, 500 * 8);\n });\n\n it('should compute correctly for concurrent requests', () => {\n const result = estimateThroughput([\n createThroughputRecord(0, 1),\n createThroughputRecord(0.5, 1),\n ]);\n\n assert.strictEqual(result, 2000 * 8);\n });\n\n it('should compute correctly for gaps', () => {\n const result = estimateThroughput([\n createThroughputRecord(0, 1),\n createThroughputRecord(3, 4),\n ]);\n\n assert.strictEqual(result, 1000 * 8);\n });\n\n it('should compute correctly for partially overlapping requests', () => {\n const result = estimateThroughput([\n createThroughputRecord(0, 1),\n createThroughputRecord(0.5, 1.5),\n createThroughputRecord(1.25, 3),\n createThroughputRecord(1.4, 4),\n createThroughputRecord(5, 9),\n ]);\n\n assert.strictEqual(result, 625 * 8);\n });\n\n it('should exclude failed records', () => {\n const result = estimateThroughput([\n createThroughputRecord(0, 2),\n createThroughputRecord(3, 4, {failed: true}),\n ]);\n assert.strictEqual(result, 500 * 8);\n });\n\n it('should exclude cached records', () => {\n const result = estimateThroughput([\n createThroughputRecord(0, 2),\n createThroughputRecord(3, 4, {statusCode: 304}),\n ]);\n assert.strictEqual(result, 500 * 8);\n });\n\n it('should exclude unfinished records', () => {\n const result = estimateThroughput([\n createThroughputRecord(0, 2),\n createThroughputRecord(3, 4, {finished: false}),\n ]);\n assert.strictEqual(result, 500 * 8);\n });\n\n it('should exclude data URIs', () => {\n const result = estimateThroughput([\n createThroughputRecord(0, 2),\n createThroughputRecord(3, 4, {parsedURL: {scheme: 'data'}}),\n ]);\n assert.strictEqual(result, 500 * 8);\n });\n });\n\n describe('#computeRTTAndServerResponseTime', () => {\n it('should work', async () => {\n const requests = await createRequests(trace);\n const result = NetworkAnalyzer.computeRTTAndServerResponseTime(requests);\n\n expect(result.rtt).to.be.closeTo(0.082, 0.001);\n assert.deepStrictEqual([...result.additionalRttByOrigin.entries()], [\n [\n 'https://www.paulirish.com',\n 9.788999999999994,\n ],\n [\n 'https://www.googletagmanager.com',\n 17.21999999999999,\n ],\n [\n 'https://fonts.googleapis.com',\n 16.816000000000003,\n ],\n [\n 'https://fonts.gstatic.com',\n 1.6889999999999998,\n ],\n [\n 'https://www.google-analytics.com',\n 9.924999999999997,\n ],\n [\n 'https://paulirish.disqus.com',\n 9.000999999999998,\n ],\n [\n 'https://firebaseinstallations.googleapis.com',\n 0,\n ],\n [\n 'https://firebaseremoteconfig.googleapis.com',\n 0.1823,\n ],\n [\n '__SUMMARY__',\n 0,\n ],\n ]);\n });\n });\n\n describe('#findMainDocument', () => {\n it('should find the main document', async () => {\n const requests = await createRequests(trace);\n const mainDocument = NetworkAnalyzer.findResourceForUrl(requests, 'https://www.paulirish.com/');\n assert.strictEqual(mainDocument.url, 'https://www.paulirish.com/');\n });\n\n it('should find the main document if the URL includes a fragment', async () => {\n const requests = await createRequests(trace);\n const mainDocument = NetworkAnalyzer.findResourceForUrl(requests, 'https://www.paulirish.com/#info');\n assert.strictEqual(mainDocument.url, 'https://www.paulirish.com/');\n });\n });\n\n describe('#resolveRedirects', () => {\n it('should resolve to the same document when no redirect', async () => {\n const requests = await createRequests(trace);\n const mainDocument = NetworkAnalyzer.findResourceForUrl(requests, 'https://www.paulirish.com/');\n const finalDocument = NetworkAnalyzer.resolveRedirects(mainDocument);\n assert.strictEqual(mainDocument.url, finalDocument.url);\n assert.strictEqual(finalDocument.url, 'https://www.paulirish.com/');\n });\n\n it('should resolve to the final document with redirects', async () => {\n const requests = await createRequests(traceWithRedirect);\n const mainDocument = NetworkAnalyzer.findResourceForUrl(requests, 'http://www.vkontakte.ru/');\n const finalDocument = NetworkAnalyzer.resolveRedirects(mainDocument);\n assert.notEqual(mainDocument.url, finalDocument.url);\n assert.strictEqual(finalDocument.url, 'https://m.vk.com/');\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"NetworkAnalyzer.test.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/core/NetworkAnalyzer.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// @ts-nocheck TODO(crbug.com/348449529)\n\nimport {TraceLoader} from '../../../../testing/TraceLoader.js';\nimport * as Trace from '../../trace.js';\nimport * as Lantern from '../lantern.js';\nimport {runTrace, toLanternTrace} from '../testing/testing.js';\n\nconst {NetworkAnalyzer} = Lantern.Core;\n\nasync function createRequests(trace: Lantern.Types.Trace) {\n const parsedTrace = await runTrace(trace);\n return Trace.LanternComputationData.createNetworkRequests(trace, parsedTrace);\n}\n\ndescribe('NetworkAnalyzer', () => {\n let trace: Lantern.Types.Trace;\n let traceWithRedirect: Lantern.Types.Trace;\n before(async function() {\n trace = toLanternTrace(await TraceLoader.rawEvents(this, 'lantern/paul/trace.json.gz'));\n traceWithRedirect = toLanternTrace(await TraceLoader.rawEvents(this, 'lantern/redirect/trace.json.gz'));\n });\n\n let recordId;\n\n function createRecord(opts) {\n const url = opts.url || 'https://example.com';\n if (opts.networkRequestTime) {\n opts.networkRequestTime *= 1000;\n }\n if (opts.networkEndTime) {\n opts.networkEndTime *= 1000;\n }\n return Object.assign(\n {\n url,\n requestId: recordId++,\n connectionId: 0,\n connectionReused: false,\n networkRequestTime: 10,\n networkEndTime: 10,\n transferSize: 0,\n protocol: opts.protocol || 'http/1.1',\n parsedURL: {scheme: url.match(/https?/)[0], securityOrigin: url.match(/.*\\.com/)[0]},\n timing: opts.timing || null,\n },\n opts,\n );\n }\n\n beforeEach(() => {\n recordId = 1;\n });\n\n function assertCloseEnough(valueA, valueB, threshold = 1) {\n const message = `${valueA} was not close enough to ${valueB}`;\n assert.ok(Math.abs(valueA - valueB) < threshold, message);\n }\n\n describe('#estimateIfConnectionWasReused', () => {\n it('should use built-in value when trustworthy', () => {\n const records = [\n {requestId: 1, connectionId: 1, connectionReused: false},\n {requestId: 2, connectionId: 1, connectionReused: true},\n {requestId: 3, connectionId: 2, connectionReused: false},\n {requestId: 4, connectionId: 3, connectionReused: false},\n {requestId: 5, connectionId: 2, connectionReused: true},\n ];\n\n const result = NetworkAnalyzer.estimateIfConnectionWasReused(records);\n const expected = new Map([[1, false], [2, true], [3, false], [4, false], [5, true]]);\n assert.deepStrictEqual(result, expected);\n });\n\n it('should estimate values when not trustworthy (duplicate IDs)', () => {\n const records = [\n createRecord({requestId: 1, networkRequestTime: 0, networkEndTime: 15}),\n createRecord({requestId: 2, networkRequestTime: 10, networkEndTime: 25}),\n createRecord({requestId: 3, networkRequestTime: 20, networkEndTime: 40}),\n createRecord({requestId: 4, networkRequestTime: 30, networkEndTime: 40}),\n ];\n\n const result = NetworkAnalyzer.estimateIfConnectionWasReused(records);\n const expected = new Map([[1, false], [2, false], [3, true], [4, true]]);\n assert.deepStrictEqual(result, expected);\n });\n\n it('should estimate values when not trustworthy (connectionReused nonsense)', () => {\n const records = [\n createRecord({\n requestId: 1,\n connectionId: 1,\n connectionReused: true,\n networkRequestTime: 0,\n networkEndTime: 15,\n }),\n createRecord({\n requestId: 2,\n connectionId: 1,\n connectionReused: true,\n networkRequestTime: 10,\n networkEndTime: 25,\n }),\n createRecord({\n requestId: 3,\n connectionId: 1,\n connectionReused: true,\n networkRequestTime: 20,\n networkEndTime: 40,\n }),\n createRecord({\n requestId: 4,\n connectionId: 2,\n connectionReused: false,\n networkRequestTime: 30,\n networkEndTime: 40,\n }),\n ];\n\n const result = NetworkAnalyzer.estimateIfConnectionWasReused(records);\n const expected = new Map([[1, false], [2, false], [3, true], [4, true]]);\n assert.deepStrictEqual(result, expected);\n });\n\n it('should estimate with earliest allowed reuse', () => {\n const records = [\n createRecord({requestId: 1, networkRequestTime: 0, networkEndTime: 40}),\n createRecord({requestId: 2, networkRequestTime: 10, networkEndTime: 15}),\n createRecord({requestId: 3, networkRequestTime: 20, networkEndTime: 30}),\n createRecord({requestId: 4, networkRequestTime: 35, networkEndTime: 40}),\n ];\n\n const result = NetworkAnalyzer.estimateIfConnectionWasReused(records);\n const expected = new Map([[1, false], [2, false], [3, true], [4, true]]);\n assert.deepStrictEqual(result, expected);\n });\n\n it('should work on a real trace', async () => {\n const requests = await createRequests(trace);\n const result = NetworkAnalyzer.estimateIfConnectionWasReused(requests);\n const distinctConnections = Array.from(result.values()).filter(item => !item).length;\n assert.strictEqual(result.size, 25);\n assert.strictEqual(distinctConnections, 9);\n });\n });\n\n describe('#estimateRTTByOrigin', () => {\n it('should infer from tcp timing when available', () => {\n const timing = {connectStart: 0, connectEnd: 99};\n const request = createRecord({networkRequestTime: 0, networkEndTime: 1, timing});\n const result = NetworkAnalyzer.estimateRTTByOrigin([request]);\n const expected = {min: 99, max: 99, avg: 99, median: 99};\n assert.deepStrictEqual(result.get('https://example.com'), expected);\n });\n\n it('should infer only one estimate if tcp and ssl start times are equal', () => {\n const timing = {connectStart: 0, connectEnd: 99, sslStart: 0, sslEnd: 99};\n const request = createRecord({networkRequestTime: 0, networkEndTime: 1, timing});\n const result = NetworkAnalyzer.estimateRTTByOrigin([request]);\n const expected = {min: 99, max: 99, avg: 99, median: 99};\n assert.deepStrictEqual(result.get('https://example.com'), expected);\n });\n\n it('should infer from tcp and ssl timing when available', () => {\n const timing = {connectStart: 0, connectEnd: 99, sslStart: 50, sslEnd: 99};\n const request = createRecord({networkRequestTime: 0, networkEndTime: 1, timing});\n const result = NetworkAnalyzer.estimateRTTByOrigin([request]);\n const expected = {min: 49, max: 50, avg: 49.5, median: 49.5};\n assert.deepStrictEqual(result.get('https://example.com'), expected);\n });\n\n it('should infer from connection timing when available for h3 (one estimate)', () => {\n const timing = {connectStart: 0, connectEnd: 99, sslStart: 1, sslEnd: 99};\n const request = createRecord({networkRequestTime: 0, networkEndTime: 1, timing, protocol: 'h3'});\n const result = NetworkAnalyzer.estimateRTTByOrigin([request]);\n const expected = {min: 99, max: 99, avg: 99, median: 99};\n assert.deepStrictEqual(result.get('https://example.com'), expected);\n });\n\n it('should infer from sendStart when available', () => {\n const timing = {sendStart: 150};\n // this request took 150ms before Chrome could send the request\n // i.e. DNS (maybe) + queuing (maybe) + TCP handshake took ~100ms\n // 150ms / 3 round trips ~= 50ms RTT\n const request = createRecord({networkRequestTime: 0, networkEndTime: 1, timing});\n const result = NetworkAnalyzer.estimateRTTByOrigin([request], {coarseEstimateMultiplier: 1});\n const expected = {min: 50, max: 50, avg: 50, median: 50};\n assert.deepStrictEqual(result.get('https://example.com'), expected);\n });\n\n it('should infer from download timing when available', () => {\n const timing = {receiveHeadersEnd: 100};\n // this request took 1000ms after the first byte was received to download the payload\n // i.e. it took at least one full additional roundtrip after first byte to download the rest\n // 1000ms / 1 round trip ~= 1000ms RTT\n const request = createRecord({networkRequestTime: 0, networkEndTime: 1.1, transferSize: 28 * 1024, timing});\n const result = NetworkAnalyzer.estimateRTTByOrigin([request], {\n coarseEstimateMultiplier: 1,\n useHeadersEndEstimates: false,\n });\n const expected = {min: 1000, max: 1000, avg: 1000, median: 1000};\n assert.deepStrictEqual(result.get('https://example.com'), expected);\n });\n\n it('should infer from TTFB when available', () => {\n const timing = {receiveHeadersEnd: 1000};\n const request = createRecord({networkRequestTime: 0, networkEndTime: 1, timing, resourceType: 'Other'});\n const result = NetworkAnalyzer.estimateRTTByOrigin([request], {\n coarseEstimateMultiplier: 1,\n });\n\n // this request's TTFB was 1000ms, it used SSL and was a fresh connection requiring a handshake\n // which needs ~4 RTs. We don't know its resource type so it'll be assumed that 40% of it was\n // server response time.\n // 600 ms / 4 = 150ms\n const expected = {min: 150, max: 150, avg: 150, median: 150};\n assert.deepStrictEqual(result.get('https://example.com'), expected);\n });\n\n it('should use coarse estimates on a per-origin basis', () => {\n const records = [\n createRecord({url: 'https://example.com', timing: {connectStart: 1, connectEnd: 100, sendStart: 150}}),\n createRecord({url: 'https://example2.com', timing: {sendStart: 150}}),\n ];\n const result = NetworkAnalyzer.estimateRTTByOrigin(records);\n assert.deepStrictEqual(result.get('https://example.com'), {min: 99, max: 99, avg: 99, median: 99});\n assert.deepStrictEqual(result.get('https://example2.com'), {min: 15, max: 15, avg: 15, median: 15});\n });\n\n it('should handle untrustworthy connection information', () => {\n const timing = {sendStart: 150};\n const recordA = createRecord({networkRequestTime: 0, networkEndTime: 1, timing, connectionReused: true});\n const recordB = createRecord({\n networkRequestTime: 0,\n networkEndTime: 1,\n timing,\n connectionId: 2,\n connectionReused: true,\n });\n const result = NetworkAnalyzer.estimateRTTByOrigin([recordA, recordB], {\n coarseEstimateMultiplier: 1,\n });\n const expected = {min: 50, max: 50, avg: 50, median: 50};\n assert.deepStrictEqual(result.get('https://example.com'), expected);\n });\n\n it('should work on a real trace', async () => {\n const requests = await createRequests(trace);\n const result = NetworkAnalyzer.estimateRTTByOrigin(requests);\n assertCloseEnough(result.get('https://www.paulirish.com').min, 10);\n assertCloseEnough(result.get('https://www.googletagmanager.com').min, 17);\n assertCloseEnough(result.get('https://www.google-analytics.com').min, 10);\n });\n\n it('should approximate well with either method', async () => {\n const requests = await createRequests(trace);\n const result = NetworkAnalyzer.estimateRTTByOrigin(requests).get(NetworkAnalyzer.summary);\n const resultApprox = NetworkAnalyzer\n .estimateRTTByOrigin(requests, {\n forceCoarseEstimates: true,\n })\n .get(NetworkAnalyzer.summary);\n assertCloseEnough(result.min, resultApprox.min, 20);\n assertCloseEnough(result.avg, resultApprox.avg, 30);\n assertCloseEnough(result.median, resultApprox.median, 30);\n });\n });\n\n describe('#estimateServerResponseTimeByOrigin', () => {\n it('should estimate server response time using ttfb times', () => {\n const timing = {sendEnd: 100, receiveHeadersEnd: 200};\n const request = createRecord({networkRequestTime: 0, networkEndTime: 1, timing});\n const rttByOrigin = new Map([[NetworkAnalyzer.summary, 0]]);\n const result = NetworkAnalyzer.estimateServerResponseTimeByOrigin([request], {rttByOrigin});\n const expected = {min: 100, max: 100, avg: 100, median: 100};\n assert.deepStrictEqual(result.get('https://example.com'), expected);\n });\n\n it('should subtract out rtt', () => {\n const timing = {sendEnd: 100, receiveHeadersEnd: 200};\n const request = createRecord({networkRequestTime: 0, networkEndTime: 1, timing});\n const rttByOrigin = new Map([[NetworkAnalyzer.summary, 50]]);\n const result = NetworkAnalyzer.estimateServerResponseTimeByOrigin([request], {rttByOrigin});\n const expected = {min: 50, max: 50, avg: 50, median: 50};\n assert.deepStrictEqual(result.get('https://example.com'), expected);\n });\n\n it('should compute rtts when not provided', () => {\n const timing = {connectStart: 5, connectEnd: 55, sendEnd: 100, receiveHeadersEnd: 200};\n const request = createRecord({networkRequestTime: 0, networkEndTime: 1, timing});\n const result = NetworkAnalyzer.estimateServerResponseTimeByOrigin([request]);\n const expected = {min: 50, max: 50, avg: 50, median: 50};\n assert.deepStrictEqual(result.get('https://example.com'), expected);\n });\n\n it('should work on a real trace', async () => {\n const requests = await createRequests(trace);\n const result = NetworkAnalyzer.estimateServerResponseTimeByOrigin(requests);\n assertCloseEnough(result.get('https://www.paulirish.com').avg, 35);\n assertCloseEnough(result.get('https://www.googletagmanager.com').avg, 8);\n assertCloseEnough(result.get('https://www.google-analytics.com').avg, 8);\n });\n\n it('should approximate well with either method', async () => {\n const requests = await createRequests(trace);\n const result = NetworkAnalyzer.estimateServerResponseTimeByOrigin(requests).get(\n NetworkAnalyzer.summary,\n );\n const resultApprox = NetworkAnalyzer\n .estimateServerResponseTimeByOrigin(requests, {\n forceCoarseEstimates: true,\n })\n .get(NetworkAnalyzer.summary);\n assertCloseEnough(result.min, resultApprox.min, 20);\n assertCloseEnough(result.avg, resultApprox.avg, 30);\n assertCloseEnough(result.median, resultApprox.median, 30);\n });\n });\n\n describe('#estimateThroughput', () => {\n const estimateThroughput = NetworkAnalyzer.estimateThroughput;\n\n function createThroughputRecord(responseHeadersEndTimeInS, networkEndTimeInS, extras) {\n return Object.assign(\n {\n responseHeadersEndTime: responseHeadersEndTimeInS * 1000,\n networkEndTime: networkEndTimeInS * 1000,\n transferSize: 1000,\n finished: true,\n failed: false,\n statusCode: 200,\n url: 'https://google.com/logo.png',\n parsedURL: {scheme: 'https'},\n },\n extras,\n );\n }\n\n it('should return Infinity for no/missing records', () => {\n assert.strictEqual(estimateThroughput([]), Infinity);\n assert.strictEqual(estimateThroughput([createThroughputRecord(0, 0, {finished: false})]), Infinity);\n });\n\n it('should compute correctly for a basic waterfall', () => {\n const result = estimateThroughput([\n createThroughputRecord(0, 1),\n createThroughputRecord(1, 2),\n createThroughputRecord(2, 6),\n ]);\n\n assert.strictEqual(result, 500 * 8);\n });\n\n it('should compute correctly for concurrent requests', () => {\n const result = estimateThroughput([\n createThroughputRecord(0, 1),\n createThroughputRecord(0.5, 1),\n ]);\n\n assert.strictEqual(result, 2000 * 8);\n });\n\n it('should compute correctly for gaps', () => {\n const result = estimateThroughput([\n createThroughputRecord(0, 1),\n createThroughputRecord(3, 4),\n ]);\n\n assert.strictEqual(result, 1000 * 8);\n });\n\n it('should compute correctly for partially overlapping requests', () => {\n const result = estimateThroughput([\n createThroughputRecord(0, 1),\n createThroughputRecord(0.5, 1.5),\n createThroughputRecord(1.25, 3),\n createThroughputRecord(1.4, 4),\n createThroughputRecord(5, 9),\n ]);\n\n assert.strictEqual(result, 625 * 8);\n });\n\n it('should exclude failed records', () => {\n const result = estimateThroughput([\n createThroughputRecord(0, 2),\n createThroughputRecord(3, 4, {failed: true}),\n ]);\n assert.strictEqual(result, 500 * 8);\n });\n\n it('should exclude cached records', () => {\n const result = estimateThroughput([\n createThroughputRecord(0, 2),\n createThroughputRecord(3, 4, {statusCode: 304}),\n ]);\n assert.strictEqual(result, 500 * 8);\n });\n\n it('should exclude unfinished records', () => {\n const result = estimateThroughput([\n createThroughputRecord(0, 2),\n createThroughputRecord(3, 4, {finished: false}),\n ]);\n assert.strictEqual(result, 500 * 8);\n });\n\n it('should exclude data URIs', () => {\n const result = estimateThroughput([\n createThroughputRecord(0, 2),\n createThroughputRecord(3, 4, {parsedURL: {scheme: 'data'}}),\n ]);\n assert.strictEqual(result, 500 * 8);\n });\n });\n\n describe('#computeRTTAndServerResponseTime', () => {\n it('should work', async () => {\n const requests = await createRequests(trace);\n const result = NetworkAnalyzer.computeRTTAndServerResponseTime(requests);\n\n expect(result.rtt).to.be.closeTo(0.082, 0.001);\n assert.deepStrictEqual([...result.additionalRttByOrigin.entries()], [\n [\n 'https://www.paulirish.com',\n 9.788999999999994,\n ],\n [\n 'https://www.googletagmanager.com',\n 17.21999999999999,\n ],\n [\n 'https://fonts.googleapis.com',\n 16.816000000000003,\n ],\n [\n 'https://fonts.gstatic.com',\n 1.6889999999999998,\n ],\n [\n 'https://www.google-analytics.com',\n 9.924999999999997,\n ],\n [\n 'https://paulirish.disqus.com',\n 9.000999999999998,\n ],\n [\n 'https://firebaseinstallations.googleapis.com',\n 0,\n ],\n [\n 'https://firebaseremoteconfig.googleapis.com',\n 0.1823,\n ],\n [\n '__SUMMARY__',\n 0,\n ],\n ]);\n });\n });\n\n describe('#findMainDocument', () => {\n it('should find the main document', async () => {\n const requests = await createRequests(trace);\n const mainDocument = NetworkAnalyzer.findResourceForUrl(requests, 'https://www.paulirish.com/');\n assert.strictEqual(mainDocument.url, 'https://www.paulirish.com/');\n });\n\n it('should find the main document if the URL includes a fragment', async () => {\n const requests = await createRequests(trace);\n const mainDocument = NetworkAnalyzer.findResourceForUrl(requests, 'https://www.paulirish.com/#info');\n assert.strictEqual(mainDocument.url, 'https://www.paulirish.com/');\n });\n });\n\n describe('#resolveRedirects', () => {\n it('should resolve to the same document when no redirect', async () => {\n const requests = await createRequests(trace);\n const mainDocument = NetworkAnalyzer.findResourceForUrl(requests, 'https://www.paulirish.com/');\n const finalDocument = NetworkAnalyzer.resolveRedirects(mainDocument);\n assert.strictEqual(mainDocument.url, finalDocument.url);\n assert.strictEqual(finalDocument.url, 'https://www.paulirish.com/');\n });\n\n it('should resolve to the final document with redirects', async () => {\n const requests = await createRequests(traceWithRedirect);\n const mainDocument = NetworkAnalyzer.findResourceForUrl(requests, 'http://www.vkontakte.ru/');\n const finalDocument = NetworkAnalyzer.resolveRedirects(mainDocument);\n assert.notEqual(mainDocument.url, finalDocument.url);\n assert.strictEqual(finalDocument.url, 'https://m.vk.com/');\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/lantern/simulation/Simulator.test.js b/public/models/trace/lantern/simulation/Simulator.test.js index 9e8a7e4ce..a0c49b850 100644 --- a/public/models/trace/lantern/simulation/Simulator.test.js +++ b/public/models/trace/lantern/simulation/Simulator.test.js @@ -3,17 +3,17 @@ // found in the LICENSE file. // @ts-nocheck TODO(crbug.com/348449529) import { TraceLoader } from '../../../../testing/TraceLoader.js'; -import * as TraceModel from '../../trace.js'; +import * as Trace from '../../trace.js'; import * as Lantern from '../lantern.js'; -import { runTraceEngine, toLanternTrace } from '../testing/testing.js'; +import { runTrace, toLanternTrace } from '../testing/testing.js'; const { NetworkNode, CPUNode } = Lantern.Graph; const { Simulator, DNSCache } = Lantern.Simulation; let nextRequestId = 1; let nextTid = 1; async function createGraph(trace) { - const traceEngineData = await runTraceEngine(trace); - const requests = TraceModel.LanternComputationData.createNetworkRequests(trace, traceEngineData); - return TraceModel.LanternComputationData.createGraph(requests, trace, traceEngineData); + const parsedTrace = await runTrace(trace); + const requests = Trace.LanternComputationData.createNetworkRequests(trace, parsedTrace); + return Trace.LanternComputationData.createGraph(requests, trace, parsedTrace); } function request(opts) { const scheme = opts.scheme || 'http'; diff --git a/public/models/trace/lantern/simulation/Simulator.test.js.map b/public/models/trace/lantern/simulation/Simulator.test.js.map index b06c64c91..73deb052e 100644 --- a/public/models/trace/lantern/simulation/Simulator.test.js.map +++ b/public/models/trace/lantern/simulation/Simulator.test.js.map @@ -1 +1 @@ -{"version":3,"file":"Simulator.test.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/simulation/Simulator.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// @ts-nocheck TODO(crbug.com/348449529)\n\nimport {TraceLoader} from '../../../../testing/TraceLoader.js';\nimport * as TraceModel from '../../trace.js';\nimport * as Lantern from '../lantern.js';\nimport {runTraceEngine, toLanternTrace} from '../testing/testing.js';\n\nconst {NetworkNode, CPUNode} = Lantern.Graph;\nconst {Simulator, DNSCache} = Lantern.Simulation;\n\nlet nextRequestId = 1;\nlet nextTid = 1;\n\nasync function createGraph(trace: Lantern.Trace) {\n const traceEngineData = await runTraceEngine(trace);\n const requests = TraceModel.LanternComputationData.createNetworkRequests(trace, traceEngineData);\n return TraceModel.LanternComputationData.createGraph(requests, trace, traceEngineData);\n}\n\nfunction request(opts) {\n const scheme = opts.scheme || 'http';\n const url = `${scheme}://example.com`;\n const rendererStartTime = opts.startTime;\n const networkEndTime = opts.endTime;\n delete opts.startTime;\n delete opts.endTime;\n\n return Object.assign(\n {\n requestId: opts.requestId || nextRequestId++,\n url,\n transferSize: opts.transferSize || 1000,\n protocol: scheme,\n parsedURL: {scheme, host: 'example.com', securityOrigin: url},\n timing: opts.timing,\n rendererStartTime,\n networkEndTime,\n },\n opts);\n}\n\nfunction cpuTask({tid, ts, duration}) {\n tid = tid || nextTid++;\n ts = ts || 0;\n const dur = ((duration || 0) * 1000) / 5;\n return {tid, ts, dur};\n}\n\ndescribe('DependencyGraph/Simulator', () => {\n // Insulate the simulator tests from DNS multiplier changes\n let originalDNSMultiplier;\n let trace: Lantern.Trace;\n\n before(async function() {\n trace = toLanternTrace(await TraceLoader.rawEvents(this, 'lantern/progressive-app/trace.json.gz'));\n originalDNSMultiplier = DNSCache.rttMultiplier;\n DNSCache.rttMultiplier = 1;\n });\n\n after(() => {\n DNSCache.rttMultiplier = originalDNSMultiplier;\n });\n\n describe('.simulate', () => {\n const serverResponseTimeByOrigin = new Map([['http://example.com', 500]]);\n\n function assertNodeTiming(result, node, assertions) {\n const timing = result.nodeTimings.get(node);\n assert.ok(timing, 'missing node timing information');\n Object.keys(assertions).forEach(key => {\n assert.strictEqual(timing[key], assertions[key]);\n });\n }\n\n it('should simulate basic network graphs', () => {\n const rootNode = new NetworkNode(request({}));\n const simulator = new Simulator({serverResponseTimeByOrigin});\n const result = simulator.simulate(rootNode);\n // should be 3 RTTs and 500ms for the server response time\n assert.strictEqual(result.timeInMs, 450 + 500);\n assertNodeTiming(result, rootNode, {startTime: 0, endTime: 950});\n });\n\n it('should simulate basic mixed graphs', () => {\n const rootNode = new NetworkNode(request({}));\n const cpuNode = new CPUNode(cpuTask({duration: 200}));\n cpuNode.addDependency(rootNode);\n\n const simulator = new Simulator({\n serverResponseTimeByOrigin,\n cpuSlowdownMultiplier: 5,\n });\n const result = simulator.simulate(rootNode);\n // should be 3 RTTs and 500ms for the server response time + 200 CPU\n assert.strictEqual(result.timeInMs, 450 + 500 + 200);\n assertNodeTiming(result, rootNode, {startTime: 0, endTime: 950});\n assertNodeTiming(result, cpuNode, {startTime: 950, endTime: 1150});\n });\n\n it('should simulate basic network waterfall graphs', () => {\n const nodeA = new NetworkNode(request({startTime: 0, endTime: 1}));\n const nodeB = new NetworkNode(request({startTime: 0, endTime: 3}));\n const nodeC = new NetworkNode(request({startTime: 0, endTime: 5}));\n const nodeD = new NetworkNode(request({startTime: 0, endTime: 7}));\n\n nodeA.addDependent(nodeB);\n nodeB.addDependent(nodeC);\n nodeC.addDependent(nodeD);\n\n const simulator = new Simulator({serverResponseTimeByOrigin});\n const result = simulator.simulate(nodeA);\n // should be 950ms for A, 650ms each for B, C, D (no DNS and one-way connection)\n assert.strictEqual(result.timeInMs, 2900);\n assertNodeTiming(result, nodeA, {startTime: 0, endTime: 950});\n assertNodeTiming(result, nodeB, {startTime: 950, endTime: 1600});\n assertNodeTiming(result, nodeC, {startTime: 1600, endTime: 2250});\n assertNodeTiming(result, nodeD, {startTime: 2250, endTime: 2900});\n });\n\n it('should simulate cached network graphs', () => {\n const nodeA = new NetworkNode(request({startTime: 0, endTime: 1, fromDiskCache: true}));\n const nodeB = new NetworkNode(request({startTime: 0, endTime: 3, fromDiskCache: true}));\n nodeA.addDependent(nodeB);\n\n const simulator = new Simulator({serverResponseTimeByOrigin});\n const result = simulator.simulate(nodeA);\n // should be ~8ms each for A, B\n assert.strictEqual(result.timeInMs, 16);\n assertNodeTiming(result, nodeA, {startTime: 0, endTime: 8});\n assertNodeTiming(result, nodeB, {startTime: 8, endTime: 16});\n });\n\n it('should simulate data URL network graphs', () => {\n const url = 'data:image/jpeg;base64,foobar';\n const protocol = 'data';\n const parsedURL = {scheme: 'data', host: '', securityOrigin: 'null'};\n const nodeA = new NetworkNode(request({startTime: 0, endTime: 1, url, parsedURL, protocol}));\n const nodeB =\n new NetworkNode(request({startTime: 0, endTime: 3, url, parsedURL, protocol, resourceSize: 1024 * 1024}));\n nodeA.addDependent(nodeB);\n\n const simulator = new Simulator({serverResponseTimeByOrigin});\n const result = simulator.simulate(nodeA);\n\n // should be ~2ms for A (resourceSize 0), ~12ms for B (resourceSize 1MB)\n assert.strictEqual(result.timeInMs, 14);\n assertNodeTiming(result, nodeA, {startTime: 0, endTime: 2});\n assertNodeTiming(result, nodeB, {startTime: 2, endTime: 14});\n });\n\n it('should simulate basic CPU queue graphs', () => {\n const nodeA = new NetworkNode(request({}));\n const nodeB = new CPUNode(cpuTask({duration: 100}));\n const nodeC = new CPUNode(cpuTask({duration: 600}));\n const nodeD = new CPUNode(cpuTask({duration: 300}));\n\n nodeA.addDependent(nodeB);\n nodeA.addDependent(nodeC);\n nodeA.addDependent(nodeD);\n\n const simulator = new Simulator({\n serverResponseTimeByOrigin,\n cpuSlowdownMultiplier: 5,\n });\n const result = simulator.simulate(nodeA);\n // should be 800ms A, then 1000 ms total for B, C, D in serial\n assert.strictEqual(result.timeInMs, 1950);\n assertNodeTiming(result, nodeA, {startTime: 0, endTime: 950});\n assertNodeTiming(result, nodeB, {startTime: 950, endTime: 1050});\n assertNodeTiming(result, nodeC, {startTime: 1050, endTime: 1650});\n assertNodeTiming(result, nodeD, {startTime: 1650, endTime: 1950});\n });\n\n it('should simulate basic network waterfall graphs with CPU', () => {\n const nodeA = new NetworkNode(request({}));\n const nodeB = new NetworkNode(request({}));\n const nodeC = new NetworkNode(request({}));\n const nodeD = new NetworkNode(request({}));\n const nodeE = new CPUNode(cpuTask({duration: 1000}));\n const nodeF = new CPUNode(cpuTask({duration: 1000}));\n\n nodeA.addDependent(nodeB);\n nodeB.addDependent(nodeC);\n nodeB.addDependent(nodeE); // finishes 350 ms after C\n nodeC.addDependent(nodeD);\n nodeC.addDependent(nodeF); // finishes 700 ms after D\n\n const simulator = new Simulator({\n serverResponseTimeByOrigin,\n cpuSlowdownMultiplier: 5,\n });\n const result = simulator.simulate(nodeA);\n // should be 950ms for A, 650ms each for B, C, D, with F finishing 700 ms after D\n assert.strictEqual(result.timeInMs, 3600);\n });\n\n it('should simulate basic parallel requests', () => {\n const nodeA = new NetworkNode(request({}));\n const nodeB = new NetworkNode(request({}));\n const nodeC = new NetworkNode(request({transferSize: 15000}));\n const nodeD = new NetworkNode(request({}));\n\n nodeA.addDependent(nodeB);\n nodeA.addDependent(nodeC);\n nodeA.addDependent(nodeD);\n\n const simulator = new Simulator({serverResponseTimeByOrigin});\n const result = simulator.simulate(nodeA);\n // should be 950ms for A and 950ms for C (2 round trips of downloading, but no DNS)\n assert.strictEqual(result.timeInMs, 950 + 950);\n });\n\n it('should make connections in parallel', () => {\n const nodeA = new NetworkNode(request({startTime: 0, networkRequestTime: 0, endTime: 1}));\n const nodeB = new NetworkNode(request({startTime: 2, networkRequestTime: 2, endTime: 3}));\n const nodeC = new NetworkNode(request({startTime: 2, networkRequestTime: 2, endTime: 5}));\n const nodeD = new NetworkNode(request({startTime: 2, networkRequestTime: 2, endTime: 7}));\n\n nodeA.addDependent(nodeB);\n nodeA.addDependent(nodeC);\n nodeA.addDependent(nodeD);\n\n const simulator = new Simulator({serverResponseTimeByOrigin});\n const result = simulator.simulate(nodeA);\n // should be 950ms for A, 650ms for B reusing connection, 800ms for C and D in parallel.\n assert.strictEqual(result.timeInMs, 950 + 800);\n assertNodeTiming(result, nodeA, {startTime: 0, endTime: 950});\n assertNodeTiming(result, nodeB, {startTime: 950, endTime: 1600});\n assertNodeTiming(result, nodeC, {startTime: 950, endTime: 1750});\n assertNodeTiming(result, nodeD, {startTime: 950, endTime: 1750});\n });\n\n it('should adjust throughput based on number of requests', () => {\n const nodeA = new NetworkNode(request({}));\n const nodeB = new NetworkNode(request({}));\n const nodeC = new NetworkNode(request({transferSize: 14000}));\n const nodeD = new NetworkNode(request({}));\n\n nodeA.addDependent(nodeB);\n nodeA.addDependent(nodeC);\n nodeA.addDependent(nodeD);\n\n // 80 kbps while all 3 download at 150ms/RT = ~1460 bytes/RT\n // 240 kbps while the last one finishes at 150ms/RT = ~4380 bytes/RT\n // ~14000 bytes = 5 RTs\n // 1 RT 80 kbps b/c its shared\n // 1 RT 80 kbps b/c it needs to grow congestion window from being shared\n // 1 RT 160 kbps b/c TCP\n // 2 RT 240 kbps b/c throughput cap\n const simulator = new Simulator({serverResponseTimeByOrigin, throughput: 240000});\n const result = simulator.simulate(nodeA);\n // should be 950ms for A and 1400ms for C (5 round trips of downloading)\n assert.strictEqual(result.timeInMs, 950 + (150 + 750 + 500));\n });\n\n it('should start network requests in startTime order', () => {\n const rootNode = new NetworkNode(request({startTime: 0, endTime: 0.05, connectionId: 1}));\n const imageNodes = [\n new NetworkNode(request({startTime: 5})),\n new NetworkNode(request({startTime: 4})),\n new NetworkNode(request({startTime: 3})),\n new NetworkNode(request({startTime: 2})),\n new NetworkNode(request({startTime: 1})),\n ];\n\n for (const imageNode of imageNodes) {\n imageNode.request.connectionReused = true;\n imageNode.request.connectionId = 1;\n rootNode.addDependent(imageNode);\n }\n\n const simulator = new Simulator({serverResponseTimeByOrigin, maximumConcurrentRequests: 1});\n const result = simulator.simulate(rootNode);\n\n // should be 3 RTs + SRT for rootNode (950ms)\n // should be 1 RT + SRT for image nodes in observed order (650ms)\n assertNodeTiming(result, rootNode, {startTime: 0, endTime: 950});\n assertNodeTiming(result, imageNodes[4], {startTime: 950, endTime: 1600});\n assertNodeTiming(result, imageNodes[3], {startTime: 1600, endTime: 2250});\n assertNodeTiming(result, imageNodes[2], {startTime: 2250, endTime: 2900});\n assertNodeTiming(result, imageNodes[1], {startTime: 2900, endTime: 3550});\n assertNodeTiming(result, imageNodes[0], {startTime: 3550, endTime: 4200});\n });\n\n it('should start network requests in priority order to break startTime ties', () => {\n const rootNode = new NetworkNode(request({startTime: 0, endTime: 0.05, connectionId: 1}));\n const imageNodes = [\n new NetworkNode(request({startTime: 0.1, priority: 'VeryLow'})),\n new NetworkNode(request({startTime: 0.2, priority: 'Low'})),\n new NetworkNode(request({startTime: 0.3, priority: 'Medium'})),\n new NetworkNode(request({startTime: 0.4, priority: 'High'})),\n new NetworkNode(request({startTime: 0.5, priority: 'VeryHigh'})),\n ];\n\n for (const imageNode of imageNodes) {\n imageNode.request.connectionReused = true;\n imageNode.request.connectionId = 1;\n rootNode.addDependent(imageNode);\n }\n\n const simulator = new Simulator({serverResponseTimeByOrigin, maximumConcurrentRequests: 1});\n const result = simulator.simulate(rootNode);\n\n // should be 3 RTs + SRT for rootNode (950ms)\n // should be 1 RT + SRT for image nodes in priority order (650ms)\n assertNodeTiming(result, rootNode, {startTime: 0, endTime: 950});\n assertNodeTiming(result, imageNodes[4], {startTime: 950, endTime: 1600});\n assertNodeTiming(result, imageNodes[3], {startTime: 1600, endTime: 2250});\n assertNodeTiming(result, imageNodes[2], {startTime: 2250, endTime: 2900});\n assertNodeTiming(result, imageNodes[1], {startTime: 2900, endTime: 3550});\n assertNodeTiming(result, imageNodes[0], {startTime: 3550, endTime: 4200});\n });\n\n it('should simulate two graphs in a row', () => {\n const simulator = new Simulator({serverResponseTimeByOrigin});\n\n const nodeA = new NetworkNode(request({}));\n const nodeB = new NetworkNode(request({}));\n const nodeC = new NetworkNode(request({transferSize: 15000}));\n const nodeD = new NetworkNode(request({}));\n\n nodeA.addDependent(nodeB);\n nodeA.addDependent(nodeC);\n nodeA.addDependent(nodeD);\n\n const resultA = simulator.simulate(nodeA);\n // should be 950ms for A and 950ms for C (2 round trips of downloading, no DNS)\n assert.strictEqual(resultA.timeInMs, 950 + 950);\n\n const nodeE = new NetworkNode(request({}));\n const nodeF = new NetworkNode(request({}));\n const nodeG = new NetworkNode(request({}));\n\n nodeE.addDependent(nodeF);\n nodeE.addDependent(nodeG);\n\n const resultB = simulator.simulate(nodeE);\n // should be 950ms for E and 800ms for F/G\n assert.strictEqual(resultB.timeInMs, 950 + 800);\n });\n\n it('should maximize throughput with H2', () => {\n const simulator = new Simulator({serverResponseTimeByOrigin});\n const connectionDefaults = {protocol: 'h2', connectionId: 1};\n const nodeA = new NetworkNode(request({startTime: 0, endTime: 1, ...connectionDefaults}));\n const nodeB = new NetworkNode(request({startTime: 1, endTime: 2, ...connectionDefaults}));\n const nodeC = new NetworkNode(request({startTime: 2, endTime: 3, ...connectionDefaults}));\n const nodeD = new NetworkNode(request({startTime: 3, endTime: 4, ...connectionDefaults}));\n\n nodeA.addDependent(nodeB);\n nodeB.addDependent(nodeC);\n nodeB.addDependent(nodeD);\n\n // Run two simulations:\n // - The first with C & D in parallel.\n // - The second with C & D in series.\n // Under HTTP/2 simulation these should be equivalent, but definitely parallel\n // shouldn't be slower.\n const resultA = simulator.simulate(nodeA);\n nodeC.addDependent(nodeD);\n const resultB = simulator.simulate(nodeA);\n expect(resultA.timeInMs).to.be.lessThanOrEqual(resultB.timeInMs);\n });\n\n it('should throw (not hang) on graphs with cycles', () => {\n const rootNode = new NetworkNode(request({}));\n const depNode = new NetworkNode(request({}));\n rootNode.addDependency(depNode);\n depNode.addDependency(rootNode);\n\n const simulator = new Simulator({serverResponseTimeByOrigin});\n assert.throws(() => simulator.simulate(rootNode), /cycle/);\n });\n\n describe('on a real trace', function() {\n TraceLoader.setTestTimeout(this);\n\n it('should compute a timeInMs', async function() {\n const graph = await createGraph(trace);\n const simulator = new Simulator({serverResponseTimeByOrigin});\n const result = simulator.simulate(graph);\n expect(result.timeInMs).to.be.greaterThan(100);\n });\n\n it('should sort the task event times', async () => {\n const graph = await createGraph(trace);\n const simulator = new Simulator({serverResponseTimeByOrigin});\n const result = simulator.simulate(graph);\n const nodeTimings = Array.from(result.nodeTimings.entries());\n\n for (let i = 1; i < nodeTimings.length; i++) {\n const startTime = nodeTimings[i][1].startTime;\n const previousStartTime = nodeTimings[i - 1][1].startTime;\n expect(startTime).to.be.greaterThanOrEqual(previousStartTime);\n }\n });\n });\n });\n\n describe('.simulateTimespan', () => {\n it('calculates savings using throughput', () => {\n const simulator = new Simulator({throughput: 1000, observedThroughput: 2000});\n const wastedMs = simulator.computeWastedMsFromWastedBytes(500);\n expect(wastedMs).to.be.closeTo(4000, 0.1);\n });\n\n it('falls back to observed throughput if throughput is 0', () => {\n const simulator = new Simulator({throughput: 0, observedThroughput: 2000});\n const wastedMs = simulator.computeWastedMsFromWastedBytes(500);\n expect(wastedMs).to.be.closeTo(2000, 0.1);\n });\n\n it('returns 0 if throughput and observed throughput are 0', () => {\n const simulator = new Simulator({throughput: 0, observedThroughput: 0});\n const wastedMs = simulator.computeWastedMsFromWastedBytes(500);\n expect(wastedMs).to.equal(0);\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"Simulator.test.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/simulation/Simulator.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// @ts-nocheck TODO(crbug.com/348449529)\n\nimport {TraceLoader} from '../../../../testing/TraceLoader.js';\nimport * as Trace from '../../trace.js';\nimport * as Lantern from '../lantern.js';\nimport {runTrace, toLanternTrace} from '../testing/testing.js';\n\nconst {NetworkNode, CPUNode} = Lantern.Graph;\nconst {Simulator, DNSCache} = Lantern.Simulation;\n\nlet nextRequestId = 1;\nlet nextTid = 1;\n\nasync function createGraph(trace: Lantern.Trace) {\n const parsedTrace = await runTrace(trace);\n const requests = Trace.LanternComputationData.createNetworkRequests(trace, parsedTrace);\n return Trace.LanternComputationData.createGraph(requests, trace, parsedTrace);\n}\n\nfunction request(opts) {\n const scheme = opts.scheme || 'http';\n const url = `${scheme}://example.com`;\n const rendererStartTime = opts.startTime;\n const networkEndTime = opts.endTime;\n delete opts.startTime;\n delete opts.endTime;\n\n return Object.assign(\n {\n requestId: opts.requestId || nextRequestId++,\n url,\n transferSize: opts.transferSize || 1000,\n protocol: scheme,\n parsedURL: {scheme, host: 'example.com', securityOrigin: url},\n timing: opts.timing,\n rendererStartTime,\n networkEndTime,\n },\n opts);\n}\n\nfunction cpuTask({tid, ts, duration}) {\n tid = tid || nextTid++;\n ts = ts || 0;\n const dur = ((duration || 0) * 1000) / 5;\n return {tid, ts, dur};\n}\n\ndescribe('DependencyGraph/Simulator', () => {\n // Insulate the simulator tests from DNS multiplier changes\n let originalDNSMultiplier;\n let trace: Lantern.Trace;\n\n before(async function() {\n trace = toLanternTrace(await TraceLoader.rawEvents(this, 'lantern/progressive-app/trace.json.gz'));\n originalDNSMultiplier = DNSCache.rttMultiplier;\n DNSCache.rttMultiplier = 1;\n });\n\n after(() => {\n DNSCache.rttMultiplier = originalDNSMultiplier;\n });\n\n describe('.simulate', () => {\n const serverResponseTimeByOrigin = new Map([['http://example.com', 500]]);\n\n function assertNodeTiming(result, node, assertions) {\n const timing = result.nodeTimings.get(node);\n assert.ok(timing, 'missing node timing information');\n Object.keys(assertions).forEach(key => {\n assert.strictEqual(timing[key], assertions[key]);\n });\n }\n\n it('should simulate basic network graphs', () => {\n const rootNode = new NetworkNode(request({}));\n const simulator = new Simulator({serverResponseTimeByOrigin});\n const result = simulator.simulate(rootNode);\n // should be 3 RTTs and 500ms for the server response time\n assert.strictEqual(result.timeInMs, 450 + 500);\n assertNodeTiming(result, rootNode, {startTime: 0, endTime: 950});\n });\n\n it('should simulate basic mixed graphs', () => {\n const rootNode = new NetworkNode(request({}));\n const cpuNode = new CPUNode(cpuTask({duration: 200}));\n cpuNode.addDependency(rootNode);\n\n const simulator = new Simulator({\n serverResponseTimeByOrigin,\n cpuSlowdownMultiplier: 5,\n });\n const result = simulator.simulate(rootNode);\n // should be 3 RTTs and 500ms for the server response time + 200 CPU\n assert.strictEqual(result.timeInMs, 450 + 500 + 200);\n assertNodeTiming(result, rootNode, {startTime: 0, endTime: 950});\n assertNodeTiming(result, cpuNode, {startTime: 950, endTime: 1150});\n });\n\n it('should simulate basic network waterfall graphs', () => {\n const nodeA = new NetworkNode(request({startTime: 0, endTime: 1}));\n const nodeB = new NetworkNode(request({startTime: 0, endTime: 3}));\n const nodeC = new NetworkNode(request({startTime: 0, endTime: 5}));\n const nodeD = new NetworkNode(request({startTime: 0, endTime: 7}));\n\n nodeA.addDependent(nodeB);\n nodeB.addDependent(nodeC);\n nodeC.addDependent(nodeD);\n\n const simulator = new Simulator({serverResponseTimeByOrigin});\n const result = simulator.simulate(nodeA);\n // should be 950ms for A, 650ms each for B, C, D (no DNS and one-way connection)\n assert.strictEqual(result.timeInMs, 2900);\n assertNodeTiming(result, nodeA, {startTime: 0, endTime: 950});\n assertNodeTiming(result, nodeB, {startTime: 950, endTime: 1600});\n assertNodeTiming(result, nodeC, {startTime: 1600, endTime: 2250});\n assertNodeTiming(result, nodeD, {startTime: 2250, endTime: 2900});\n });\n\n it('should simulate cached network graphs', () => {\n const nodeA = new NetworkNode(request({startTime: 0, endTime: 1, fromDiskCache: true}));\n const nodeB = new NetworkNode(request({startTime: 0, endTime: 3, fromDiskCache: true}));\n nodeA.addDependent(nodeB);\n\n const simulator = new Simulator({serverResponseTimeByOrigin});\n const result = simulator.simulate(nodeA);\n // should be ~8ms each for A, B\n assert.strictEqual(result.timeInMs, 16);\n assertNodeTiming(result, nodeA, {startTime: 0, endTime: 8});\n assertNodeTiming(result, nodeB, {startTime: 8, endTime: 16});\n });\n\n it('should simulate data URL network graphs', () => {\n const url = 'data:image/jpeg;base64,foobar';\n const protocol = 'data';\n const parsedURL = {scheme: 'data', host: '', securityOrigin: 'null'};\n const nodeA = new NetworkNode(request({startTime: 0, endTime: 1, url, parsedURL, protocol}));\n const nodeB =\n new NetworkNode(request({startTime: 0, endTime: 3, url, parsedURL, protocol, resourceSize: 1024 * 1024}));\n nodeA.addDependent(nodeB);\n\n const simulator = new Simulator({serverResponseTimeByOrigin});\n const result = simulator.simulate(nodeA);\n\n // should be ~2ms for A (resourceSize 0), ~12ms for B (resourceSize 1MB)\n assert.strictEqual(result.timeInMs, 14);\n assertNodeTiming(result, nodeA, {startTime: 0, endTime: 2});\n assertNodeTiming(result, nodeB, {startTime: 2, endTime: 14});\n });\n\n it('should simulate basic CPU queue graphs', () => {\n const nodeA = new NetworkNode(request({}));\n const nodeB = new CPUNode(cpuTask({duration: 100}));\n const nodeC = new CPUNode(cpuTask({duration: 600}));\n const nodeD = new CPUNode(cpuTask({duration: 300}));\n\n nodeA.addDependent(nodeB);\n nodeA.addDependent(nodeC);\n nodeA.addDependent(nodeD);\n\n const simulator = new Simulator({\n serverResponseTimeByOrigin,\n cpuSlowdownMultiplier: 5,\n });\n const result = simulator.simulate(nodeA);\n // should be 800ms A, then 1000 ms total for B, C, D in serial\n assert.strictEqual(result.timeInMs, 1950);\n assertNodeTiming(result, nodeA, {startTime: 0, endTime: 950});\n assertNodeTiming(result, nodeB, {startTime: 950, endTime: 1050});\n assertNodeTiming(result, nodeC, {startTime: 1050, endTime: 1650});\n assertNodeTiming(result, nodeD, {startTime: 1650, endTime: 1950});\n });\n\n it('should simulate basic network waterfall graphs with CPU', () => {\n const nodeA = new NetworkNode(request({}));\n const nodeB = new NetworkNode(request({}));\n const nodeC = new NetworkNode(request({}));\n const nodeD = new NetworkNode(request({}));\n const nodeE = new CPUNode(cpuTask({duration: 1000}));\n const nodeF = new CPUNode(cpuTask({duration: 1000}));\n\n nodeA.addDependent(nodeB);\n nodeB.addDependent(nodeC);\n nodeB.addDependent(nodeE); // finishes 350 ms after C\n nodeC.addDependent(nodeD);\n nodeC.addDependent(nodeF); // finishes 700 ms after D\n\n const simulator = new Simulator({\n serverResponseTimeByOrigin,\n cpuSlowdownMultiplier: 5,\n });\n const result = simulator.simulate(nodeA);\n // should be 950ms for A, 650ms each for B, C, D, with F finishing 700 ms after D\n assert.strictEqual(result.timeInMs, 3600);\n });\n\n it('should simulate basic parallel requests', () => {\n const nodeA = new NetworkNode(request({}));\n const nodeB = new NetworkNode(request({}));\n const nodeC = new NetworkNode(request({transferSize: 15000}));\n const nodeD = new NetworkNode(request({}));\n\n nodeA.addDependent(nodeB);\n nodeA.addDependent(nodeC);\n nodeA.addDependent(nodeD);\n\n const simulator = new Simulator({serverResponseTimeByOrigin});\n const result = simulator.simulate(nodeA);\n // should be 950ms for A and 950ms for C (2 round trips of downloading, but no DNS)\n assert.strictEqual(result.timeInMs, 950 + 950);\n });\n\n it('should make connections in parallel', () => {\n const nodeA = new NetworkNode(request({startTime: 0, networkRequestTime: 0, endTime: 1}));\n const nodeB = new NetworkNode(request({startTime: 2, networkRequestTime: 2, endTime: 3}));\n const nodeC = new NetworkNode(request({startTime: 2, networkRequestTime: 2, endTime: 5}));\n const nodeD = new NetworkNode(request({startTime: 2, networkRequestTime: 2, endTime: 7}));\n\n nodeA.addDependent(nodeB);\n nodeA.addDependent(nodeC);\n nodeA.addDependent(nodeD);\n\n const simulator = new Simulator({serverResponseTimeByOrigin});\n const result = simulator.simulate(nodeA);\n // should be 950ms for A, 650ms for B reusing connection, 800ms for C and D in parallel.\n assert.strictEqual(result.timeInMs, 950 + 800);\n assertNodeTiming(result, nodeA, {startTime: 0, endTime: 950});\n assertNodeTiming(result, nodeB, {startTime: 950, endTime: 1600});\n assertNodeTiming(result, nodeC, {startTime: 950, endTime: 1750});\n assertNodeTiming(result, nodeD, {startTime: 950, endTime: 1750});\n });\n\n it('should adjust throughput based on number of requests', () => {\n const nodeA = new NetworkNode(request({}));\n const nodeB = new NetworkNode(request({}));\n const nodeC = new NetworkNode(request({transferSize: 14000}));\n const nodeD = new NetworkNode(request({}));\n\n nodeA.addDependent(nodeB);\n nodeA.addDependent(nodeC);\n nodeA.addDependent(nodeD);\n\n // 80 kbps while all 3 download at 150ms/RT = ~1460 bytes/RT\n // 240 kbps while the last one finishes at 150ms/RT = ~4380 bytes/RT\n // ~14000 bytes = 5 RTs\n // 1 RT 80 kbps b/c its shared\n // 1 RT 80 kbps b/c it needs to grow congestion window from being shared\n // 1 RT 160 kbps b/c TCP\n // 2 RT 240 kbps b/c throughput cap\n const simulator = new Simulator({serverResponseTimeByOrigin, throughput: 240000});\n const result = simulator.simulate(nodeA);\n // should be 950ms for A and 1400ms for C (5 round trips of downloading)\n assert.strictEqual(result.timeInMs, 950 + (150 + 750 + 500));\n });\n\n it('should start network requests in startTime order', () => {\n const rootNode = new NetworkNode(request({startTime: 0, endTime: 0.05, connectionId: 1}));\n const imageNodes = [\n new NetworkNode(request({startTime: 5})),\n new NetworkNode(request({startTime: 4})),\n new NetworkNode(request({startTime: 3})),\n new NetworkNode(request({startTime: 2})),\n new NetworkNode(request({startTime: 1})),\n ];\n\n for (const imageNode of imageNodes) {\n imageNode.request.connectionReused = true;\n imageNode.request.connectionId = 1;\n rootNode.addDependent(imageNode);\n }\n\n const simulator = new Simulator({serverResponseTimeByOrigin, maximumConcurrentRequests: 1});\n const result = simulator.simulate(rootNode);\n\n // should be 3 RTs + SRT for rootNode (950ms)\n // should be 1 RT + SRT for image nodes in observed order (650ms)\n assertNodeTiming(result, rootNode, {startTime: 0, endTime: 950});\n assertNodeTiming(result, imageNodes[4], {startTime: 950, endTime: 1600});\n assertNodeTiming(result, imageNodes[3], {startTime: 1600, endTime: 2250});\n assertNodeTiming(result, imageNodes[2], {startTime: 2250, endTime: 2900});\n assertNodeTiming(result, imageNodes[1], {startTime: 2900, endTime: 3550});\n assertNodeTiming(result, imageNodes[0], {startTime: 3550, endTime: 4200});\n });\n\n it('should start network requests in priority order to break startTime ties', () => {\n const rootNode = new NetworkNode(request({startTime: 0, endTime: 0.05, connectionId: 1}));\n const imageNodes = [\n new NetworkNode(request({startTime: 0.1, priority: 'VeryLow'})),\n new NetworkNode(request({startTime: 0.2, priority: 'Low'})),\n new NetworkNode(request({startTime: 0.3, priority: 'Medium'})),\n new NetworkNode(request({startTime: 0.4, priority: 'High'})),\n new NetworkNode(request({startTime: 0.5, priority: 'VeryHigh'})),\n ];\n\n for (const imageNode of imageNodes) {\n imageNode.request.connectionReused = true;\n imageNode.request.connectionId = 1;\n rootNode.addDependent(imageNode);\n }\n\n const simulator = new Simulator({serverResponseTimeByOrigin, maximumConcurrentRequests: 1});\n const result = simulator.simulate(rootNode);\n\n // should be 3 RTs + SRT for rootNode (950ms)\n // should be 1 RT + SRT for image nodes in priority order (650ms)\n assertNodeTiming(result, rootNode, {startTime: 0, endTime: 950});\n assertNodeTiming(result, imageNodes[4], {startTime: 950, endTime: 1600});\n assertNodeTiming(result, imageNodes[3], {startTime: 1600, endTime: 2250});\n assertNodeTiming(result, imageNodes[2], {startTime: 2250, endTime: 2900});\n assertNodeTiming(result, imageNodes[1], {startTime: 2900, endTime: 3550});\n assertNodeTiming(result, imageNodes[0], {startTime: 3550, endTime: 4200});\n });\n\n it('should simulate two graphs in a row', () => {\n const simulator = new Simulator({serverResponseTimeByOrigin});\n\n const nodeA = new NetworkNode(request({}));\n const nodeB = new NetworkNode(request({}));\n const nodeC = new NetworkNode(request({transferSize: 15000}));\n const nodeD = new NetworkNode(request({}));\n\n nodeA.addDependent(nodeB);\n nodeA.addDependent(nodeC);\n nodeA.addDependent(nodeD);\n\n const resultA = simulator.simulate(nodeA);\n // should be 950ms for A and 950ms for C (2 round trips of downloading, no DNS)\n assert.strictEqual(resultA.timeInMs, 950 + 950);\n\n const nodeE = new NetworkNode(request({}));\n const nodeF = new NetworkNode(request({}));\n const nodeG = new NetworkNode(request({}));\n\n nodeE.addDependent(nodeF);\n nodeE.addDependent(nodeG);\n\n const resultB = simulator.simulate(nodeE);\n // should be 950ms for E and 800ms for F/G\n assert.strictEqual(resultB.timeInMs, 950 + 800);\n });\n\n it('should maximize throughput with H2', () => {\n const simulator = new Simulator({serverResponseTimeByOrigin});\n const connectionDefaults = {protocol: 'h2', connectionId: 1};\n const nodeA = new NetworkNode(request({startTime: 0, endTime: 1, ...connectionDefaults}));\n const nodeB = new NetworkNode(request({startTime: 1, endTime: 2, ...connectionDefaults}));\n const nodeC = new NetworkNode(request({startTime: 2, endTime: 3, ...connectionDefaults}));\n const nodeD = new NetworkNode(request({startTime: 3, endTime: 4, ...connectionDefaults}));\n\n nodeA.addDependent(nodeB);\n nodeB.addDependent(nodeC);\n nodeB.addDependent(nodeD);\n\n // Run two simulations:\n // - The first with C & D in parallel.\n // - The second with C & D in series.\n // Under HTTP/2 simulation these should be equivalent, but definitely parallel\n // shouldn't be slower.\n const resultA = simulator.simulate(nodeA);\n nodeC.addDependent(nodeD);\n const resultB = simulator.simulate(nodeA);\n expect(resultA.timeInMs).to.be.lessThanOrEqual(resultB.timeInMs);\n });\n\n it('should throw (not hang) on graphs with cycles', () => {\n const rootNode = new NetworkNode(request({}));\n const depNode = new NetworkNode(request({}));\n rootNode.addDependency(depNode);\n depNode.addDependency(rootNode);\n\n const simulator = new Simulator({serverResponseTimeByOrigin});\n assert.throws(() => simulator.simulate(rootNode), /cycle/);\n });\n\n describe('on a real trace', function() {\n TraceLoader.setTestTimeout(this);\n\n it('should compute a timeInMs', async function() {\n const graph = await createGraph(trace);\n const simulator = new Simulator({serverResponseTimeByOrigin});\n const result = simulator.simulate(graph);\n expect(result.timeInMs).to.be.greaterThan(100);\n });\n\n it('should sort the task event times', async () => {\n const graph = await createGraph(trace);\n const simulator = new Simulator({serverResponseTimeByOrigin});\n const result = simulator.simulate(graph);\n const nodeTimings = Array.from(result.nodeTimings.entries());\n\n for (let i = 1; i < nodeTimings.length; i++) {\n const startTime = nodeTimings[i][1].startTime;\n const previousStartTime = nodeTimings[i - 1][1].startTime;\n expect(startTime).to.be.greaterThanOrEqual(previousStartTime);\n }\n });\n });\n });\n\n describe('.simulateTimespan', () => {\n it('calculates savings using throughput', () => {\n const simulator = new Simulator({throughput: 1000, observedThroughput: 2000});\n const wastedMs = simulator.computeWastedMsFromWastedBytes(500);\n expect(wastedMs).to.be.closeTo(4000, 0.1);\n });\n\n it('falls back to observed throughput if throughput is 0', () => {\n const simulator = new Simulator({throughput: 0, observedThroughput: 2000});\n const wastedMs = simulator.computeWastedMsFromWastedBytes(500);\n expect(wastedMs).to.be.closeTo(2000, 0.1);\n });\n\n it('returns 0 if throughput and observed throughput are 0', () => {\n const simulator = new Simulator({throughput: 0, observedThroughput: 0});\n const wastedMs = simulator.computeWastedMsFromWastedBytes(500);\n expect(wastedMs).to.equal(0);\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/lantern/testing/MetricTestUtils.d.ts b/public/models/trace/lantern/testing/MetricTestUtils.d.ts index 395735f83..1fe56bf6e 100644 --- a/public/models/trace/lantern/testing/MetricTestUtils.d.ts +++ b/public/models/trace/lantern/testing/MetricTestUtils.d.ts @@ -1,14 +1,14 @@ -import * as TraceModel from '../../trace.js'; +import * as Trace from '../../trace.js'; import * as Lantern from '../lantern.js'; -declare function toLanternTrace(traceEvents: readonly TraceModel.Types.TraceEvents.TraceEventData[]): Lantern.Types.Trace; -declare function runTraceEngine(trace: Lantern.Types.Trace): Promise>>; +declare function toLanternTrace(traceEvents: readonly Trace.Types.Events.Event[]): Lantern.Types.Trace; +declare function runTrace(trace: Lantern.Types.Trace): Promise>>; declare function getComputationDataFromFixture({ trace, settings, url }: { trace: Lantern.Types.Trace; settings?: Lantern.Types.Simulation.Settings; url?: Lantern.Types.Simulation.URL; }): Promise<{ - simulator: TraceModel.Lantern.Simulation.Simulator; - graph: TraceModel.Lantern.Graph.Node; - processedNavigation: TraceModel.Lantern.Types.Simulation.ProcessedNavigation; + simulator: Trace.Lantern.Simulation.Simulator; + graph: Trace.Lantern.Graph.Node; + processedNavigation: Trace.Lantern.Types.Simulation.ProcessedNavigation; }>; -export { toLanternTrace, runTraceEngine, getComputationDataFromFixture, }; +export { toLanternTrace, runTrace, getComputationDataFromFixture, }; diff --git a/public/models/trace/lantern/testing/MetricTestUtils.js b/public/models/trace/lantern/testing/MetricTestUtils.js index a5691711a..fb2172a33 100644 --- a/public/models/trace/lantern/testing/MetricTestUtils.js +++ b/public/models/trace/lantern/testing/MetricTestUtils.js @@ -1,39 +1,39 @@ // Copyright 2024 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 * as TraceModel from '../../trace.js'; +import * as Trace from '../../trace.js'; import * as Lantern from '../lantern.js'; function toLanternTrace(traceEvents) { return { traceEvents: traceEvents, }; } -async function runTraceEngine(trace) { - const processor = TraceModel.Processor.TraceProcessor.createWithAllHandlers(); +async function runTrace(trace) { + const processor = Trace.Processor.TraceProcessor.createWithAllHandlers(); await processor.parse(trace.traceEvents); - if (!processor.traceParsedData) { + if (!processor.parsedTrace) { throw new Error('No data'); } - return processor.traceParsedData; + return processor.parsedTrace; } async function getComputationDataFromFixture({ trace, settings, url }) { settings = settings ?? {}; if (!settings.throttlingMethod) { settings.throttlingMethod = 'simulate'; } - const traceEngineData = await runTraceEngine(trace); - const requests = TraceModel.LanternComputationData.createNetworkRequests(trace, traceEngineData); + const parsedTrace = await runTrace(trace); + const requests = Trace.LanternComputationData.createNetworkRequests(trace, parsedTrace); const networkAnalysis = Lantern.Core.NetworkAnalyzer.analyze(requests); - const frameId = traceEngineData.Meta.mainFrameId; - const navigationId = traceEngineData.Meta.mainFrameNavigations[0].args.data?.navigationId; + const frameId = parsedTrace.Meta.mainFrameId; + const navigationId = parsedTrace.Meta.mainFrameNavigations[0].args.data?.navigationId; if (!navigationId) { throw new Error('no navigation id found'); } return { simulator: Lantern.Simulation.Simulator.createSimulator({ ...settings, networkAnalysis }), - graph: TraceModel.LanternComputationData.createGraph(requests, trace, traceEngineData, url), - processedNavigation: TraceModel.LanternComputationData.createProcessedNavigation(traceEngineData, frameId, navigationId), + graph: Trace.LanternComputationData.createGraph(requests, trace, parsedTrace, url), + processedNavigation: Trace.LanternComputationData.createProcessedNavigation(parsedTrace, frameId, navigationId), }; } -export { toLanternTrace, runTraceEngine, getComputationDataFromFixture, }; +export { toLanternTrace, runTrace, getComputationDataFromFixture, }; //# sourceMappingURL=MetricTestUtils.js.map \ No newline at end of file diff --git a/public/models/trace/lantern/testing/MetricTestUtils.js.map b/public/models/trace/lantern/testing/MetricTestUtils.js.map index 83ca17833..0000471f6 100644 --- a/public/models/trace/lantern/testing/MetricTestUtils.js.map +++ b/public/models/trace/lantern/testing/MetricTestUtils.js.map @@ -1 +1 @@ -{"version":3,"file":"MetricTestUtils.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/testing/MetricTestUtils.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,UAAU,MAAM,gBAAgB,CAAC;AAC7C,OAAO,KAAK,OAAO,MAAM,eAAe,CAAC;AAEzC,SAAS,cAAc,CAAC,WAAmE;IACzF,OAAO;QACL,WAAW,EAAE,WAAoD;KAClE,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,cAAc,CAAC,KAA0B;IACtD,MAAM,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC,cAAc,CAAC,qBAAqB,EAAE,CAAC;IAC9E,MAAM,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,WAA4D,CAAC,CAAC;IAC1F,IAAI,CAAC,SAAS,CAAC,eAAe,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,SAAS,CAAC,eAAe,CAAC;AACnC,CAAC;AAED,KAAK,UAAU,6BAA6B,CAAC,EAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,EAIjE;IACC,QAAQ,GAAG,QAAQ,IAAI,EAAuC,CAAC;IAC/D,IAAI,CAAC,QAAQ,CAAC,gBAAgB,EAAE,CAAC;QAC/B,QAAQ,CAAC,gBAAgB,GAAG,UAAU,CAAC;IACzC,CAAC;IACD,MAAM,eAAe,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC;IACpD,MAAM,QAAQ,GAAG,UAAU,CAAC,sBAAsB,CAAC,qBAAqB,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;IACjG,MAAM,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACvE,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC;IACjD,MAAM,YAAY,GAAG,eAAe,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC;IAC1F,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC5C,CAAC;IAED,OAAO;QACL,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,eAAe,CAAC,EAAC,GAAG,QAAQ,EAAE,eAAe,EAAC,CAAC;QACvF,KAAK,EAAE,UAAU,CAAC,sBAAsB,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,EAAE,eAAe,EAAE,GAAG,CAAC;QAC3F,mBAAmB,EACf,UAAU,CAAC,sBAAsB,CAAC,yBAAyB,CAAC,eAAe,EAAE,OAAO,EAAE,YAAY,CAAC;KACxG,CAAC;AACJ,CAAC;AAED,OAAO,EACL,cAAc,EACd,cAAc,EACd,6BAA6B,GAC9B,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceModel from '../../trace.js';\nimport * as Lantern from '../lantern.js';\n\nfunction toLanternTrace(traceEvents: readonly TraceModel.Types.TraceEvents.TraceEventData[]): Lantern.Types.Trace {\n return {\n traceEvents: traceEvents as unknown as Lantern.Types.TraceEvent[],\n };\n}\n\nasync function runTraceEngine(trace: Lantern.Types.Trace) {\n const processor = TraceModel.Processor.TraceProcessor.createWithAllHandlers();\n await processor.parse(trace.traceEvents as TraceModel.Types.TraceEvents.TraceEventData[]);\n if (!processor.traceParsedData) {\n throw new Error('No data');\n }\n return processor.traceParsedData;\n}\n\nasync function getComputationDataFromFixture({trace, settings, url}: {\n trace: Lantern.Types.Trace,\n settings?: Lantern.Types.Simulation.Settings,\n url?: Lantern.Types.Simulation.URL,\n}) {\n settings = settings ?? {} as Lantern.Types.Simulation.Settings;\n if (!settings.throttlingMethod) {\n settings.throttlingMethod = 'simulate';\n }\n const traceEngineData = await runTraceEngine(trace);\n const requests = TraceModel.LanternComputationData.createNetworkRequests(trace, traceEngineData);\n const networkAnalysis = Lantern.Core.NetworkAnalyzer.analyze(requests);\n const frameId = traceEngineData.Meta.mainFrameId;\n const navigationId = traceEngineData.Meta.mainFrameNavigations[0].args.data?.navigationId;\n if (!navigationId) {\n throw new Error('no navigation id found');\n }\n\n return {\n simulator: Lantern.Simulation.Simulator.createSimulator({...settings, networkAnalysis}),\n graph: TraceModel.LanternComputationData.createGraph(requests, trace, traceEngineData, url),\n processedNavigation:\n TraceModel.LanternComputationData.createProcessedNavigation(traceEngineData, frameId, navigationId),\n };\n}\n\nexport {\n toLanternTrace,\n runTraceEngine,\n getComputationDataFromFixture,\n};\n"]} \ No newline at end of file +{"version":3,"file":"MetricTestUtils.js","sourceRoot":"","sources":["../../../../../../../../front_end/models/trace/lantern/testing/MetricTestUtils.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AACxC,OAAO,KAAK,OAAO,MAAM,eAAe,CAAC;AAEzC,SAAS,cAAc,CAAC,WAAgD;IACtE,OAAO;QACL,WAAW,EAAE,WAAoD;KAClE,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,QAAQ,CAAC,KAA0B;IAChD,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,qBAAqB,EAAE,CAAC;IACzE,MAAM,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,WAAyC,CAAC,CAAC;IACvE,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;IAC7B,CAAC;IACD,OAAO,SAAS,CAAC,WAAW,CAAC;AAC/B,CAAC;AAED,KAAK,UAAU,6BAA6B,CAAC,EAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,EAIjE;IACC,QAAQ,GAAG,QAAQ,IAAI,EAAuC,CAAC;IAC/D,IAAI,CAAC,QAAQ,CAAC,gBAAgB,EAAE,CAAC;QAC/B,QAAQ,CAAC,gBAAgB,GAAG,UAAU,CAAC;IACzC,CAAC;IACD,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,QAAQ,GAAG,KAAK,CAAC,sBAAsB,CAAC,qBAAqB,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;IACxF,MAAM,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACvE,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC;IAC7C,MAAM,YAAY,GAAG,WAAW,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC;IACtF,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;IAC5C,CAAC;IAED,OAAO;QACL,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,eAAe,CAAC,EAAC,GAAG,QAAQ,EAAE,eAAe,EAAC,CAAC;QACvF,KAAK,EAAE,KAAK,CAAC,sBAAsB,CAAC,WAAW,CAAC,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,CAAC;QAClF,mBAAmB,EAAE,KAAK,CAAC,sBAAsB,CAAC,yBAAyB,CAAC,WAAW,EAAE,OAAO,EAAE,YAAY,CAAC;KAChH,CAAC;AACJ,CAAC;AAED,OAAO,EACL,cAAc,EACd,QAAQ,EACR,6BAA6B,GAC9B,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../trace.js';\nimport * as Lantern from '../lantern.js';\n\nfunction toLanternTrace(traceEvents: readonly Trace.Types.Events.Event[]): Lantern.Types.Trace {\n return {\n traceEvents: traceEvents as unknown as Lantern.Types.TraceEvent[],\n };\n}\n\nasync function runTrace(trace: Lantern.Types.Trace) {\n const processor = Trace.Processor.TraceProcessor.createWithAllHandlers();\n await processor.parse(trace.traceEvents as Trace.Types.Events.Event[]);\n if (!processor.parsedTrace) {\n throw new Error('No data');\n }\n return processor.parsedTrace;\n}\n\nasync function getComputationDataFromFixture({trace, settings, url}: {\n trace: Lantern.Types.Trace,\n settings?: Lantern.Types.Simulation.Settings,\n url?: Lantern.Types.Simulation.URL,\n}) {\n settings = settings ?? {} as Lantern.Types.Simulation.Settings;\n if (!settings.throttlingMethod) {\n settings.throttlingMethod = 'simulate';\n }\n const parsedTrace = await runTrace(trace);\n const requests = Trace.LanternComputationData.createNetworkRequests(trace, parsedTrace);\n const networkAnalysis = Lantern.Core.NetworkAnalyzer.analyze(requests);\n const frameId = parsedTrace.Meta.mainFrameId;\n const navigationId = parsedTrace.Meta.mainFrameNavigations[0].args.data?.navigationId;\n if (!navigationId) {\n throw new Error('no navigation id found');\n }\n\n return {\n simulator: Lantern.Simulation.Simulator.createSimulator({...settings, networkAnalysis}),\n graph: Trace.LanternComputationData.createGraph(requests, trace, parsedTrace, url),\n processedNavigation: Trace.LanternComputationData.createProcessedNavigation(parsedTrace, frameId, navigationId),\n };\n}\n\nexport {\n toLanternTrace,\n runTrace,\n getComputationDataFromFixture,\n};\n"]} \ No newline at end of file diff --git a/public/models/trace/root-causes/LayoutShift.d.ts b/public/models/trace/root-causes/LayoutShift.d.ts index 022bd6059..ab01edef3 100644 --- a/public/models/trace/root-causes/LayoutShift.d.ts +++ b/public/models/trace/root-causes/LayoutShift.d.ts @@ -1,5 +1,5 @@ import type * as Protocol from '../../../generated/protocol.js'; -import { type TraceParseData } from '../handlers/types.js'; +import { type ParsedTrace } from '../handlers/types.js'; import * as Types from '../types/types.js'; import { type RootCauseProtocolInterface } from './RootCauses.js'; export type CSSDimensions = { @@ -16,7 +16,7 @@ export interface InjectedIframe { iframe: Protocol.DOM.Node; } export interface RootCauseRequest { - request: Types.TraceEvents.SyntheticNetworkRequest; + request: Types.Events.SyntheticNetworkRequest; initiator?: Protocol.Network.Initiator; } export interface FontChange extends RootCauseRequest { @@ -29,7 +29,7 @@ export interface LayoutShiftRootCausesData { iframes: InjectedIframe[]; fontChanges: FontChange[]; renderBlockingRequests: RenderBlockingRequest[]; - scriptStackTrace: Types.TraceEvents.TraceEventCallFrame[]; + scriptStackTrace: Types.Events.CallFrame[]; } interface Options { /** Checking iframe root causes can be an expensive operation, so it is disabled by default. */ @@ -46,18 +46,18 @@ export declare class LayoutShiftRootCauses { * events the first time that it's called. That then populates the cache for * each shift, so any subsequent calls are just a constant lookup. */ - rootCausesForEvent(modelData: TraceParseData, event: Types.TraceEvents.TraceEventLayoutShift): Promise | null>; + rootCausesForEvent(modelData: ParsedTrace, event: Types.Events.LayoutShift): Promise | null>; /** * Determines potential root causes for shifts */ - blameShifts(layoutShifts: Types.TraceEvents.TraceEventLayoutShift[], modelData: TraceParseData): Promise; + blameShifts(layoutShifts: Types.Events.LayoutShift[], modelData: ParsedTrace): Promise; /** * "LayoutInvalidations" are a set of trace events dispatched in Blink under the name * "layoutInvalidationTracking", which track invalidations on the "Layout"stage of the * rendering pipeline. This function utilizes this event to flag potential root causes * to layout shifts. */ - linkShiftsToLayoutInvalidations(layoutShifts: Types.TraceEvents.TraceEventLayoutShift[], modelData: TraceParseData): Promise; + linkShiftsToLayoutInvalidations(layoutShifts: Types.Events.LayoutShift[], modelData: ParsedTrace): Promise; /** * For every shift looks up the initiator of its corresponding Layout event. This initiator * is assigned by the RendererHandler and contains the stack trace of the point in a script @@ -66,23 +66,23 @@ export declare class LayoutShiftRootCauses { * Note that a Layout cannot always be linked to a script, in that case, we cannot add a * "script causing reflow" as a potential root cause to the corresponding shift. */ - linkShiftsToLayoutEvents(layoutShifts: Types.TraceEvents.TraceEventLayoutShift[], modelData: TraceParseData): void; + linkShiftsToLayoutEvents(layoutShifts: Types.Events.LayoutShift[], modelData: ParsedTrace): void; /** * Given a LayoutInvalidation trace event, determines if it was dispatched * because a media element without dimensions was resized. */ - getUnsizedMediaRootCause(layoutInvalidation: Types.TraceEvents.TraceEventLayoutInvalidationTracking, layoutInvalidationNodeId: Protocol.DOM.NodeId): Promise; + getUnsizedMediaRootCause(layoutInvalidation: Types.Events.LayoutInvalidationTracking, layoutInvalidationNodeId: Protocol.DOM.NodeId): Promise; /** * Given a LayoutInvalidation trace event, determines if it was dispatched * because a node, which is an ancestor to an iframe, was injected. */ - getIframeRootCause(layoutInvalidation: Types.TraceEvents.TraceEventLayoutInvalidationTracking, layoutInvalidationNodeId: Protocol.DOM.NodeId): Promise; + getIframeRootCause(layoutInvalidation: Types.Events.LayoutInvalidationTracking, layoutInvalidationNodeId: Protocol.DOM.NodeId): Promise; getNodeDetails(nodeId: Protocol.DOM.NodeId): Promise; /** * Given a layout invalidation event and a sorted array, returns the subset of requests that arrived within a * 500ms window before the layout invalidation. */ - requestsInInvalidationWindow(layoutInvalidation: Types.TraceEvents.TraceEventLayoutInvalidationTracking | Types.TraceEvents.TraceEventScheduleStyleInvalidationTracking, modelData: TraceParseData): RootCauseRequest[]; + requestsInInvalidationWindow(layoutInvalidation: Types.Events.LayoutInvalidationTracking | Types.Events.ScheduleStyleInvalidationTracking, modelData: ParsedTrace): RootCauseRequest[]; /** * Given a LayoutInvalidation trace event, determines if it was dispatched * because fonts were changed and if so returns the information of all network @@ -92,7 +92,7 @@ export declare class LayoutShiftRootCauses { * are not processed and the cached network requests for the prepaint is * returned instead. */ - getFontChangeRootCause(layoutInvalidation: Types.TraceEvents.TraceEventLayoutInvalidationTracking | Types.TraceEvents.TraceEventScheduleStyleInvalidationTracking, nextPrePaint: Types.TraceEvents.TraceEventPrePaint, modelData: TraceParseData): FontChange[] | null; + getFontChangeRootCause(layoutInvalidation: Types.Events.LayoutInvalidationTracking | Types.Events.ScheduleStyleInvalidationTracking, nextPrePaint: Types.Events.PrePaint, modelData: ParsedTrace): FontChange[] | null; /** * Given the requests that arrived within a 500ms window before the layout invalidation, returns the font * requests of them. @@ -105,7 +105,7 @@ export declare class LayoutShiftRootCauses { * that correspond to the same prepaint are not processed and the cached network requests for the prepaint is * returned instead. */ - getRenderBlockRootCause(layoutInvalidation: Types.TraceEvents.TraceEventLayoutInvalidationTracking | Types.TraceEvents.TraceEventScheduleStyleInvalidationTracking, nextPrePaint: Types.TraceEvents.TraceEventPrePaint, modelData: TraceParseData): RenderBlockingRequest[] | null; + getRenderBlockRootCause(layoutInvalidation: Types.Events.LayoutInvalidationTracking | Types.Events.ScheduleStyleInvalidationTracking, nextPrePaint: Types.Events.PrePaint, modelData: ParsedTrace): RenderBlockingRequest[] | null; /** * Returns a function that retrieves the active value of a given * CSS property within the matched styles of the param node. diff --git a/public/models/trace/root-causes/LayoutShift.js b/public/models/trace/root-causes/LayoutShift.js index a06782ac8..ea0404040 100644 --- a/public/models/trace/root-causes/LayoutShift.js +++ b/public/models/trace/root-causes/LayoutShift.js @@ -118,8 +118,7 @@ export class LayoutShiftRootCauses { const layoutInvalidationNodeId = nodeIdsByBackendIdMap.get(layoutInvalidation.args.data.nodeId); let unsizedMediaRootCause = null; let iframeRootCause = null; - if (layoutInvalidationNodeId !== undefined && - Types.TraceEvents.isTraceEventLayoutInvalidationTracking(layoutInvalidation)) { + if (layoutInvalidationNodeId !== undefined && Types.Events.isLayoutInvalidationTracking(layoutInvalidation)) { unsizedMediaRootCause = await this.getUnsizedMediaRootCause(layoutInvalidation, layoutInvalidationNodeId); iframeRootCause = await this.getIframeRootCause(layoutInvalidation, layoutInvalidationNodeId); } @@ -172,7 +171,7 @@ export class LayoutShiftRootCauses { const shiftsByPrePaint = getShiftsByPrePaintEvents(layoutShifts, prePaintEvents); const eventTriggersLayout = ({ name }) => { const knownName = name; - return knownName === "Layout" /* Types.TraceEvents.KnownEventName.LAYOUT */; + return knownName === "Layout" /* Types.Events.Name.LAYOUT */; }; const layoutEvents = modelData.Renderer.allTraceEntries.filter(eventTriggersLayout); for (const layout of layoutEvents) { @@ -217,7 +216,7 @@ export class LayoutShiftRootCauses { */ async getUnsizedMediaRootCause(layoutInvalidation, layoutInvalidationNodeId) { // Filter events to resizes only. - if (layoutInvalidation.args.data.reason !== "Size changed" /* Types.TraceEvents.LayoutInvalidationReason.SIZE_CHANGED */) { + if (layoutInvalidation.args.data.reason !== "Size changed" /* Types.Events.LayoutInvalidationReason.SIZE_CHANGED */) { return null; } const layoutInvalidationNode = await this.getNodeDetails(layoutInvalidationNodeId); @@ -245,8 +244,8 @@ export class LayoutShiftRootCauses { return null; } if (!layoutInvalidation.args.data.nodeName?.startsWith('IFRAME') && - layoutInvalidation.args.data.reason !== "Style changed" /* Types.TraceEvents.LayoutInvalidationReason.STYLE_CHANGED */ && - layoutInvalidation.args.data.reason !== "Added to layout" /* Types.TraceEvents.LayoutInvalidationReason.ADDED_TO_LAYOUT */) { + layoutInvalidation.args.data.reason !== "Style changed" /* Types.Events.LayoutInvalidationReason.STYLE_CHANGED */ && + layoutInvalidation.args.data.reason !== "Added to layout" /* Types.Events.LayoutInvalidationReason.ADDED_TO_LAYOUT */) { return null; } const layoutInvalidationNode = await this.getNodeDetails(layoutInvalidationNodeId); @@ -311,7 +310,7 @@ export class LayoutShiftRootCauses { * returned instead. */ getFontChangeRootCause(layoutInvalidation, nextPrePaint, modelData) { - if (layoutInvalidation.args.data.reason !== "Fonts changed" /* Types.TraceEvents.LayoutInvalidationReason.FONTS_CHANGED */) { + if (layoutInvalidation.args.data.reason !== "Fonts changed" /* Types.Events.LayoutInvalidationReason.FONTS_CHANGED */) { return null; } // Prevent computing the result of this function multiple times per PrePaint event. diff --git a/public/models/trace/root-causes/LayoutShift.js.map b/public/models/trace/root-causes/LayoutShift.js.map index 2118eb691..5acae1587 100644 --- a/public/models/trace/root-causes/LayoutShift.js.map +++ b/public/models/trace/root-causes/LayoutShift.js.map @@ -1 +1 @@ -{"version":3,"file":"LayoutShift.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/root-causes/LayoutShift.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport type * as Protocol from '../../../generated/protocol.js';\nimport {type TraceParseData} from '../handlers/types.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {type RootCauseProtocolInterface} from './RootCauses.js';\n\nexport type CSSDimensions = {\n width?: string,\n height?: string,\n aspectRatio?: string,\n};\n\nexport interface UnsizedMedia {\n node: Protocol.DOM.Node;\n authoredDimensions?: CSSDimensions;\n computedDimensions: CSSDimensions;\n}\n\nexport interface InjectedIframe {\n iframe: Protocol.DOM.Node;\n}\n\nexport interface RootCauseRequest {\n request: Types.TraceEvents.SyntheticNetworkRequest;\n initiator?: Protocol.Network.Initiator;\n}\n\nexport interface FontChange extends RootCauseRequest {\n fontFace: Protocol.CSS.FontFace;\n}\n\nexport interface RenderBlockingRequest extends RootCauseRequest {}\n\nexport interface LayoutShiftRootCausesData {\n unsizedMedia: UnsizedMedia[];\n iframes: InjectedIframe[];\n fontChanges: FontChange[];\n renderBlockingRequests: RenderBlockingRequest[];\n scriptStackTrace: Types.TraceEvents.TraceEventCallFrame[];\n}\n\nconst fontRequestsByPrePaint = new Map();\nconst renderBlocksByPrePaint = new Map();\n\nfunction setDefaultValue(\n map: Map,\n shift: Types.TraceEvents.TraceEventLayoutShift): void {\n Platform.MapUtilities.getWithDefault(map, shift, () => {\n return {\n unsizedMedia: [],\n iframes: [],\n fontChanges: [],\n renderBlockingRequests: [],\n scriptStackTrace: [],\n };\n });\n}\n\n// Important: we purposefully treat `potentially_blocking` as\n// non-render-blocking here because:\n// 1. An async script can run on the main thread at any point, including before\n// the page is loaded\n// 2. An async script will never block the parsing and rendering process of the\n// browser.\n// 3. Therefore, from a developer's point of view, there is nothing more they\n// can do if they've put `async` on, and within the context of Insights, we\n// shouldn't report an async script as render blocking.\n// In the future we may want to consider suggesting the use of `defer` over\n// `async`, as it doesn't have this concern, but for now we'll allow `async`\n// and not report it as an issue.\nconst NON_RENDER_BLOCKING_VALUES = new Set([\n 'non_blocking',\n 'potentially_blocking',\n]);\nfunction networkRequestIsRenderBlockingInFrame(\n event: Types.TraceEvents.SyntheticNetworkRequest, frameId: string): boolean {\n const isRenderBlocking = !NON_RENDER_BLOCKING_VALUES.has(event.args.data.renderBlocking);\n return isRenderBlocking && event.args.data.frame === frameId;\n}\n\ninterface Options {\n /** Checking iframe root causes can be an expensive operation, so it is disabled by default. */\n enableIframeRootCauses?: boolean;\n}\n\nexport class LayoutShiftRootCauses {\n #protocolInterface: RootCauseProtocolInterface;\n #rootCauseCacheMap = new Map();\n #nodeDetailsCache = new Map();\n #iframeRootCausesEnabled: boolean;\n\n constructor(protocolInterface: RootCauseProtocolInterface, options?: Options) {\n this.#protocolInterface = protocolInterface;\n this.#iframeRootCausesEnabled = options?.enableIframeRootCauses ?? false;\n }\n\n /**\n * Calculates the potential root causes for a given layout shift event. Once\n * calculated, this data is cached.\n * Note: because you need all layout shift data at once to calculate these\n * correctly, this function will parse the root causes for _all_ layout shift\n * events the first time that it's called. That then populates the cache for\n * each shift, so any subsequent calls are just a constant lookup.\n */\n async rootCausesForEvent(modelData: TraceParseData, event: Types.TraceEvents.TraceEventLayoutShift):\n Promise|null> {\n const cachedResult = this.#rootCauseCacheMap.get(event);\n if (cachedResult) {\n return cachedResult;\n }\n\n const allLayoutShifts = modelData.LayoutShifts.clusters.flatMap(cluster => cluster.events);\n // Make sure a value in the cache is set even for shifts that don't have a root cause,\n // so that we don't have to recompute when no root causes are found. In case a cause\n // for a shift is found, the default value is replaced.\n allLayoutShifts.forEach(shift => setDefaultValue(this.#rootCauseCacheMap, shift));\n\n // Populate the cache\n await this.blameShifts(\n allLayoutShifts,\n modelData,\n );\n\n const resultForEvent = this.#rootCauseCacheMap.get(event);\n if (!resultForEvent) {\n // No root causes available for this layout shift.\n return null;\n }\n return resultForEvent;\n }\n\n /**\n * Determines potential root causes for shifts\n */\n async blameShifts(\n layoutShifts: Types.TraceEvents.TraceEventLayoutShift[],\n modelData: TraceParseData,\n ): Promise {\n await this.linkShiftsToLayoutInvalidations(layoutShifts, modelData);\n this.linkShiftsToLayoutEvents(layoutShifts, modelData);\n }\n\n /**\n * \"LayoutInvalidations\" are a set of trace events dispatched in Blink under the name\n * \"layoutInvalidationTracking\", which track invalidations on the \"Layout\"stage of the\n * rendering pipeline. This function utilizes this event to flag potential root causes\n * to layout shifts.\n */\n async linkShiftsToLayoutInvalidations(\n layoutShifts: Types.TraceEvents.TraceEventLayoutShift[], modelData: TraceParseData): Promise {\n const {prePaintEvents, layoutInvalidationEvents, scheduleStyleInvalidationEvents, backendNodeIds} =\n modelData.LayoutShifts;\n\n // For the purposes of determining root causes of layout shifts, we\n // consider scheduleStyleInvalidationTracking and\n // LayoutInvalidationTracking events as events that could have been the\n // cause of the layout shift.\n const eventsForLayoutInvalidation: Array =\n [...layoutInvalidationEvents, ...scheduleStyleInvalidationEvents];\n\n const nodes = await this.#protocolInterface.pushNodesByBackendIdsToFrontend(backendNodeIds);\n const nodeIdsByBackendIdMap = new Map();\n for (let i = 0; i < backendNodeIds.length; i++) {\n nodeIdsByBackendIdMap.set(backendNodeIds[i], nodes[i]);\n }\n\n // Maps from PrePaint events to LayoutShifts that occured in each one.\n const shiftsByPrePaint = getShiftsByPrePaintEvents(layoutShifts, prePaintEvents);\n for (const layoutInvalidation of eventsForLayoutInvalidation) {\n // Get the first PrePaint event that happened after the current LayoutInvalidation event.\n const nextPrePaintIndex = Platform.ArrayUtilities.nearestIndexFromBeginning(\n prePaintEvents, prePaint => prePaint.ts > layoutInvalidation.ts);\n if (nextPrePaintIndex === null) {\n // No PrePaint event registered after this LayoutInvalidation. Continue.\n continue;\n }\n const nextPrePaint = prePaintEvents[nextPrePaintIndex];\n const subsequentShifts = shiftsByPrePaint.get(nextPrePaint);\n if (!subsequentShifts) {\n // The PrePaint after the current LayoutInvalidation doesn't contain shifts.\n continue;\n }\n const fontChangeRootCause = this.getFontChangeRootCause(layoutInvalidation, nextPrePaint, modelData);\n const renderBlockRootCause = this.getRenderBlockRootCause(layoutInvalidation, nextPrePaint, modelData);\n const layoutInvalidationNodeId = nodeIdsByBackendIdMap.get(layoutInvalidation.args.data.nodeId);\n let unsizedMediaRootCause: UnsizedMedia|null = null;\n let iframeRootCause: InjectedIframe|null = null;\n if (layoutInvalidationNodeId !== undefined &&\n Types.TraceEvents.isTraceEventLayoutInvalidationTracking(layoutInvalidation)) {\n unsizedMediaRootCause = await this.getUnsizedMediaRootCause(layoutInvalidation, layoutInvalidationNodeId);\n iframeRootCause = await this.getIframeRootCause(layoutInvalidation, layoutInvalidationNodeId);\n }\n\n if (!unsizedMediaRootCause && !iframeRootCause && !fontChangeRootCause && !renderBlockRootCause) {\n continue;\n }\n\n // Add found potential root causes to all the shifts in this PrePaint and populate the cache.\n for (const shift of subsequentShifts) {\n const rootCausesForShift = Platform.MapUtilities.getWithDefault(this.#rootCauseCacheMap, shift, () => {\n return {\n unsizedMedia: [],\n iframes: [],\n fontChanges: [],\n renderBlockingRequests: [],\n scriptStackTrace: [],\n };\n });\n if (unsizedMediaRootCause &&\n !rootCausesForShift.unsizedMedia.some(media => media.node.nodeId === unsizedMediaRootCause?.node.nodeId) &&\n shift.args.frame === layoutInvalidation.args.data.frame) {\n rootCausesForShift.unsizedMedia.push(unsizedMediaRootCause);\n }\n if (iframeRootCause &&\n !rootCausesForShift.iframes.some(\n injectedIframe => injectedIframe.iframe.nodeId === iframeRootCause?.iframe.nodeId)) {\n rootCausesForShift.iframes.push(iframeRootCause);\n }\n if (fontChangeRootCause) {\n // Unlike other root causes, we calculate fonts causing a shift only once,\n // which means we assign the built array instead of appending new objects\n // to it.\n rootCausesForShift.fontChanges = fontChangeRootCause;\n }\n if (renderBlockRootCause) {\n rootCausesForShift.renderBlockingRequests = renderBlockRootCause;\n }\n }\n }\n }\n\n /**\n * For every shift looks up the initiator of its corresponding Layout event. This initiator\n * is assigned by the RendererHandler and contains the stack trace of the point in a script\n * that caused a style recalculation or a relayout. This stack trace is added to the shift's\n * potential root causes.\n * Note that a Layout cannot always be linked to a script, in that case, we cannot add a\n * \"script causing reflow\" as a potential root cause to the corresponding shift.\n */\n linkShiftsToLayoutEvents(layoutShifts: Types.TraceEvents.TraceEventLayoutShift[], modelData: TraceParseData): void {\n const {prePaintEvents} = modelData.LayoutShifts;\n // Maps from PrePaint events to LayoutShifts that occured in each one.\n const shiftsByPrePaint = getShiftsByPrePaintEvents(layoutShifts, prePaintEvents);\n\n const eventTriggersLayout = ({name}: {name: string}): boolean => {\n const knownName = name as Types.TraceEvents.KnownEventName;\n return knownName === Types.TraceEvents.KnownEventName.LAYOUT;\n };\n const layoutEvents = modelData.Renderer.allTraceEntries.filter(eventTriggersLayout);\n for (const layout of layoutEvents) {\n // Get the first PrePaint event that happened after the current layout event.\n const nextPrePaintIndex = Platform.ArrayUtilities.nearestIndexFromBeginning(\n prePaintEvents, prePaint => prePaint.ts > layout.ts + (layout.dur || 0));\n if (nextPrePaintIndex === null) {\n // No PrePaint event registered after this LayoutInvalidation. Continue.\n continue;\n }\n const nextPrePaint = prePaintEvents[nextPrePaintIndex];\n const subsequentShifts = shiftsByPrePaint.get(nextPrePaint);\n if (!subsequentShifts) {\n // The PrePaint after the current LayoutInvalidation doesn't contain shifts.\n continue;\n }\n const layoutNode = modelData.Renderer.entryToNode.get(layout);\n const initiator = layoutNode ? modelData.Initiators.eventToInitiator.get(layoutNode.entry) : null;\n const stackTrace = initiator?.args?.data?.stackTrace;\n if (!stackTrace) {\n continue;\n }\n // Add found potential root causes to all the shifts in this PrePaint and populate the cache.\n for (const shift of subsequentShifts) {\n const rootCausesForShift = Platform.MapUtilities.getWithDefault(this.#rootCauseCacheMap, shift, () => {\n return {\n unsizedMedia: [],\n iframes: [],\n fontChanges: [],\n renderBlockingRequests: [],\n scriptStackTrace: [],\n };\n });\n if (rootCausesForShift.scriptStackTrace.length === 0) {\n rootCausesForShift.scriptStackTrace = stackTrace;\n }\n }\n }\n }\n\n /**\n * Given a LayoutInvalidation trace event, determines if it was dispatched\n * because a media element without dimensions was resized.\n */\n async getUnsizedMediaRootCause(\n layoutInvalidation: Types.TraceEvents.TraceEventLayoutInvalidationTracking,\n layoutInvalidationNodeId: Protocol.DOM.NodeId): Promise {\n // Filter events to resizes only.\n if (layoutInvalidation.args.data.reason !== Types.TraceEvents.LayoutInvalidationReason.SIZE_CHANGED) {\n return null;\n }\n\n const layoutInvalidationNode = await this.getNodeDetails(layoutInvalidationNodeId);\n if (!layoutInvalidationNode) {\n return null;\n }\n\n const computedStylesList = await this.#protocolInterface.getComputedStyleForNode(layoutInvalidationNode.nodeId);\n const computedStyles = new Map(computedStylesList.map(item => [item.name, item.value]));\n if (computedStyles && !(await nodeIsUnfixedMedia(layoutInvalidationNode, computedStyles))) {\n return null;\n }\n const authoredDimensions = await this.getNodeAuthoredDimensions(layoutInvalidationNode);\n if (dimensionsAreExplicit(authoredDimensions)) {\n return null;\n }\n const computedDimensions = computedStyles ? getNodeComputedDimensions(computedStyles) : {};\n\n return {node: layoutInvalidationNode, authoredDimensions, computedDimensions};\n }\n\n /**\n * Given a LayoutInvalidation trace event, determines if it was dispatched\n * because a node, which is an ancestor to an iframe, was injected.\n */\n async getIframeRootCause(\n layoutInvalidation: Types.TraceEvents.TraceEventLayoutInvalidationTracking,\n layoutInvalidationNodeId: Protocol.DOM.NodeId): Promise {\n if (!this.#iframeRootCausesEnabled) {\n return null;\n }\n\n if (!layoutInvalidation.args.data.nodeName?.startsWith('IFRAME') &&\n layoutInvalidation.args.data.reason !== Types.TraceEvents.LayoutInvalidationReason.STYLE_CHANGED &&\n layoutInvalidation.args.data.reason !== Types.TraceEvents.LayoutInvalidationReason.ADDED_TO_LAYOUT) {\n return null;\n }\n\n const layoutInvalidationNode = await this.getNodeDetails(layoutInvalidationNodeId);\n if (!layoutInvalidationNode) {\n return null;\n }\n\n const iframe = firstIframeInDOMTree(layoutInvalidationNode);\n if (!iframe) {\n return null;\n }\n return {iframe};\n }\n\n async getNodeDetails(nodeId: Protocol.DOM.NodeId): Promise {\n let nodeDetails = this.#nodeDetailsCache.get(nodeId);\n if (nodeDetails !== undefined) {\n return nodeDetails;\n }\n\n nodeDetails = await this.#protocolInterface.getNode(nodeId);\n this.#nodeDetailsCache.set(nodeId, nodeDetails);\n\n return nodeDetails;\n }\n\n /**\n * Given a layout invalidation event and a sorted array, returns the subset of requests that arrived within a\n * 500ms window before the layout invalidation.\n */\n requestsInInvalidationWindow(\n layoutInvalidation: Types.TraceEvents.TraceEventLayoutInvalidationTracking|\n Types.TraceEvents.TraceEventScheduleStyleInvalidationTracking,\n modelData: TraceParseData): RootCauseRequest[] {\n const requestsSortedByEndTime = modelData.NetworkRequests.byTime.sort((req1, req2) => {\n const req1EndTime = req1.ts + req1.dur;\n const req2EndTime = req2.ts + req2.dur;\n return req1EndTime - req2EndTime;\n });\n\n const lastRequestIndex = Platform.ArrayUtilities.nearestIndexFromEnd(\n requestsSortedByEndTime, request => request.ts + request.dur < layoutInvalidation.ts);\n if (lastRequestIndex === null) {\n return [];\n }\n\n const MAX_DELTA_FOR_FONT_REQUEST = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(0.5));\n\n const requestsInInvalidationWindow: RootCauseRequest[] = [];\n\n // Get all requests finished within the valid window.\n for (let i = lastRequestIndex; i > -1; i--) {\n const previousRequest = requestsSortedByEndTime[i];\n const previousRequestEndTime = previousRequest.ts + previousRequest.dur;\n if (layoutInvalidation.ts - previousRequestEndTime < MAX_DELTA_FOR_FONT_REQUEST) {\n const requestInInvalidationWindow: RootCauseRequest = {request: previousRequest};\n\n const initiator = this.#protocolInterface.getInitiatorForRequest(\n previousRequest.args.data.url as Platform.DevToolsPath.UrlString);\n requestInInvalidationWindow.initiator = initiator || undefined;\n requestsInInvalidationWindow.push(requestInInvalidationWindow);\n } else {\n // No more requests fit in the time window.\n break;\n }\n }\n return requestsInInvalidationWindow;\n }\n\n /**\n * Given a LayoutInvalidation trace event, determines if it was dispatched\n * because fonts were changed and if so returns the information of all network\n * request with which the fonts were possibly fetched, if any. The computed\n * network requests are cached for the corresponding prepaint event, meaning\n * that other LayoutInvalidation events that correspond to the same prepaint\n * are not processed and the cached network requests for the prepaint is\n * returned instead.\n */\n getFontChangeRootCause(\n layoutInvalidation: Types.TraceEvents.TraceEventLayoutInvalidationTracking|\n Types.TraceEvents.TraceEventScheduleStyleInvalidationTracking,\n nextPrePaint: Types.TraceEvents.TraceEventPrePaint, modelData: TraceParseData): FontChange[]|null {\n if (layoutInvalidation.args.data.reason !== Types.TraceEvents.LayoutInvalidationReason.FONTS_CHANGED) {\n return null;\n }\n // Prevent computing the result of this function multiple times per PrePaint event.\n const fontRequestsForPrepaint = fontRequestsByPrePaint.get(nextPrePaint);\n if (fontRequestsForPrepaint !== undefined) {\n return fontRequestsForPrepaint;\n }\n\n const fontRequestsInThisPrepaint =\n this.getFontRequestsInInvalidationWindow(this.requestsInInvalidationWindow(layoutInvalidation, modelData));\n fontRequestsByPrePaint.set(nextPrePaint, fontRequestsInThisPrepaint);\n return fontRequestsInThisPrepaint;\n }\n\n /**\n * Given the requests that arrived within a 500ms window before the layout invalidation, returns the font\n * requests of them.\n */\n getFontRequestsInInvalidationWindow(requestsInInvalidationWindow: RootCauseRequest[]): FontChange[] {\n const fontRequests: FontChange[] = [];\n\n // Get all requests finished within the valid window.\n for (let i = 0; i < requestsInInvalidationWindow.length; i++) {\n const fontRequest = requestsInInvalidationWindow[i] as FontChange;\n if (!fontRequest.request.args.data.mimeType.startsWith('font')) {\n continue;\n }\n\n const fontFace = this.#protocolInterface.fontFaceForSource(fontRequest.request.args.data.url);\n if (!fontFace || fontFace.fontDisplay === 'optional') {\n // Setting font-display to optional is part of what the developer\n // can do to avoid layout shifts due to FOIT/FOUT, as such we cannot\n // suggest any actionable insight here.\n continue;\n }\n fontRequest.fontFace = fontFace;\n fontRequests.push(fontRequest);\n }\n return fontRequests;\n }\n\n /**\n * Given a LayoutInvalidation trace event, determines if it arrived within a 500ms window before the layout\n * invalidation and if so returns the information of all network request, if any. The computed network\n * requests are cached for the corresponding prepaint event, meaning that other LayoutInvalidation events\n * that correspond to the same prepaint are not processed and the cached network requests for the prepaint is\n * returned instead.\n */\n getRenderBlockRootCause(\n layoutInvalidation: Types.TraceEvents.TraceEventLayoutInvalidationTracking|\n Types.TraceEvents.TraceEventScheduleStyleInvalidationTracking,\n nextPrePaint: Types.TraceEvents.TraceEventPrePaint, modelData: TraceParseData): RenderBlockingRequest[]|null {\n // Prevent computing the result of this function multiple times per PrePaint event.\n const renderBlocksInPrepaint = renderBlocksByPrePaint.get(nextPrePaint);\n if (renderBlocksInPrepaint !== undefined) {\n return renderBlocksInPrepaint;\n }\n\n const renderBlocksInThisPrepaint =\n getRenderBlockRequestsInInvalidationWindow(this.requestsInInvalidationWindow(layoutInvalidation, modelData));\n renderBlocksByPrePaint.set(nextPrePaint, renderBlocksInThisPrepaint);\n return renderBlocksInThisPrepaint;\n }\n\n /**\n * Returns a function that retrieves the active value of a given\n * CSS property within the matched styles of the param node.\n * The first occurence within the matched styles is returned and the\n * value is looked up in the following order, which follows CSS\n * specificity:\n * 1. Inline styles.\n * 2. CSS rules matching this node, from all applicable stylesheets.\n * 3. Attribute defined styles.\n */\n async nodeMatchedStylesPropertyGetter(node: Protocol.DOM.Node): Promise<((property: string) => string | null)> {\n const response = await this.#protocolInterface.getMatchedStylesForNode(node.nodeId);\n\n function cssPropertyValueGetter(cssProperty: string): string|null {\n let prop = response.inlineStyle?.cssProperties.find(prop => prop.name === cssProperty);\n if (prop) {\n return prop.value;\n }\n\n for (const {rule} of response.matchedCSSRules || []) {\n const prop = rule.style.cssProperties.find(prop => prop.name === cssProperty);\n if (prop) {\n return prop.value;\n }\n }\n\n prop = response.attributesStyle?.cssProperties.find(prop => prop.name === cssProperty);\n if (prop) {\n return prop.value;\n }\n\n return null;\n }\n return cssPropertyValueGetter;\n }\n\n /**\n * Returns the CSS dimensions set to the node from its matched styles.\n */\n async getNodeAuthoredDimensions(node: Protocol.DOM.Node): Promise {\n const authoredDimensions: CSSDimensions = {};\n\n const cssMatchedRulesGetter = await this.nodeMatchedStylesPropertyGetter(node);\n if (!cssMatchedRulesGetter) {\n return authoredDimensions;\n }\n\n const attributesFlat = node.attributes || [];\n const attributes = [];\n for (let i = 0; i < attributesFlat.length; i += 2) {\n attributes.push({name: attributesFlat[i], value: attributesFlat[i + 1]});\n }\n\n const htmlHeight = attributes.find(attr => attr.name === 'height' && htmlAttributeIsExplicit(attr));\n const htmlWidth = attributes.find(attr => attr.name === 'width' && htmlAttributeIsExplicit(attr));\n\n const cssExplicitAspectRatio = cssMatchedRulesGetter('aspect-ratio') || undefined;\n\n if (htmlHeight && htmlWidth && cssExplicitAspectRatio) {\n return {height: htmlHeight.value, width: htmlWidth.value, aspectRatio: cssExplicitAspectRatio};\n }\n\n const cssHeight = cssMatchedRulesGetter('height') || undefined;\n const cssWidth = cssMatchedRulesGetter('width') || undefined;\n return {height: cssHeight, width: cssWidth, aspectRatio: cssExplicitAspectRatio};\n }\n}\n\n/**\n * Given the requests that arrived within a 500ms window before the layout invalidation, returns the render\n * block requests of them.\n */\nfunction getRenderBlockRequestsInInvalidationWindow(requestsInInvalidationWindow: RootCauseRequest[]):\n RenderBlockingRequest[] {\n const renderBlockingRequests: RenderBlockingRequest[] = [];\n\n // Get all requests finished within the valid window.\n for (let i = 0; i < requestsInInvalidationWindow.length; i++) {\n const mainFrameId = requestsInInvalidationWindow[i].request.args.data.frame;\n if (!networkRequestIsRenderBlockingInFrame(requestsInInvalidationWindow[i].request, mainFrameId)) {\n continue;\n }\n renderBlockingRequests.push(requestsInInvalidationWindow[i] as RenderBlockingRequest);\n }\n return renderBlockingRequests;\n}\n\nfunction firstIframeInDOMTree(root: Protocol.DOM.Node): Protocol.DOM.Node|null {\n if (root.nodeName === 'IFRAME') {\n return root;\n }\n const children = root.children;\n if (!children) {\n return null;\n }\n for (const child of children) {\n const iFrameInChild = firstIframeInDOMTree(child);\n if (iFrameInChild) {\n return iFrameInChild;\n }\n }\n return null;\n}\n\nfunction cssPropertyIsExplicitlySet(propertyValue: string): boolean {\n return !['auto', 'initial', 'unset', 'inherit'].includes(propertyValue);\n}\n\nfunction htmlAttributeIsExplicit(attr: {value: string}): boolean {\n return parseInt(attr.value, 10) >= 0;\n}\n\nfunction computedStyleHasBackroundImage(computedStyle: Map): boolean {\n const CSS_URL_REGEX = /^url\\(\"([^\"]+)\"\\)$/;\n const backgroundImage = computedStyle.get('background-image');\n if (!backgroundImage) {\n return false;\n }\n return CSS_URL_REGEX.test(backgroundImage);\n}\n\nfunction computedStyleHasFixedPosition(computedStyle: Map): boolean {\n const position = computedStyle.get('position');\n if (!position) {\n return false;\n }\n return position === 'fixed' || position === 'absolute';\n}\n\nfunction getNodeComputedDimensions(computedStyle: Map): CSSDimensions {\n const computedDimensions: CSSDimensions = {};\n computedDimensions.height = computedStyle.get('height');\n computedDimensions.width = computedStyle.get('width');\n computedDimensions.aspectRatio = computedStyle.get('aspect-ratio');\n return computedDimensions;\n}\n\n/**\n * Determines if a node is a media element and is not fixed positioned\n * (i.e. \"position: fixed;\" or \"position: absolute;\")\n */\nasync function nodeIsUnfixedMedia(node: Protocol.DOM.Node, computedStyle: Map): Promise {\n const localName = node.localName;\n const isBackgroundImage = computedStyleHasBackroundImage(computedStyle);\n if (localName !== 'img' && localName !== 'video' && !isBackgroundImage) {\n // Not a media element.\n return false;\n }\n const isFixed = computedStyleHasFixedPosition(computedStyle);\n return !isFixed;\n}\n\n/**\n * Determines if a CSS dimensions object explicitly defines both width and height\n * (i.e. not set to auto, inherit, etc.)\n */\nfunction dimensionsAreExplicit(dimensions: CSSDimensions): boolean {\n const {height, width, aspectRatio} = dimensions;\n\n const explicitHeight = Boolean(height && cssPropertyIsExplicitlySet(height));\n const explicitWidth = Boolean(width && cssPropertyIsExplicitlySet(width));\n const explicitAspectRatio = Boolean(aspectRatio && cssPropertyIsExplicitlySet(aspectRatio));\n\n const explicitWithAR = (explicitHeight || explicitWidth) && explicitAspectRatio;\n return (explicitHeight && explicitWidth) || explicitWithAR;\n}\n\n/**\n * Given an array of layout shift and PrePaint events, returns a mapping from\n * PrePaint events to layout shifts dispatched within it.\n */\nfunction getShiftsByPrePaintEvents(\n layoutShifts: Types.TraceEvents.TraceEventLayoutShift[],\n prePaintEvents: Types.TraceEvents.TraceEventPrePaint[],\n ): Map {\n // Maps from PrePaint events to LayoutShifts that occured in each one.\n const shiftsByPrePaint = new Map();\n\n // Associate all shifts to their corresponding PrePaint.\n for (const prePaintEvent of prePaintEvents) {\n const firstShiftIndex =\n Platform.ArrayUtilities.nearestIndexFromBeginning(layoutShifts, shift => shift.ts >= prePaintEvent.ts);\n if (firstShiftIndex === null) {\n // No layout shifts registered after this PrePaint start. Continue.\n continue;\n }\n for (let i = firstShiftIndex; i < layoutShifts.length; i++) {\n const shift = layoutShifts[i];\n if (shift.ts >= prePaintEvent.ts && shift.ts <= prePaintEvent.ts + prePaintEvent.dur) {\n const shiftsInPrePaint = Platform.MapUtilities.getWithDefault(shiftsByPrePaint, prePaintEvent, () => []);\n shiftsInPrePaint.push(shift);\n }\n if (shift.ts > prePaintEvent.ts + prePaintEvent.dur) {\n // Reached the end of this PrePaint. Continue to the next one.\n break;\n }\n }\n }\n return shiftsByPrePaint;\n}\n"]} \ No newline at end of file +{"version":3,"file":"LayoutShift.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/root-causes/LayoutShift.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,QAAQ,MAAM,oCAAoC,CAAC;AAG/D,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAC;AACjD,OAAO,KAAK,KAAK,MAAM,mBAAmB,CAAC;AAuC3C,MAAM,sBAAsB,GAAG,IAAI,GAAG,EAA4C,CAAC;AACnF,MAAM,sBAAsB,GAAG,IAAI,GAAG,EAAuD,CAAC;AAE9F,SAAS,eAAe,CACpB,GAA6D,EAAE,KAA+B;IAChG,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE;QACpD,OAAO;YACL,YAAY,EAAE,EAAE;YAChB,OAAO,EAAE,EAAE;YACX,WAAW,EAAE,EAAE;YACf,sBAAsB,EAAE,EAAE;YAC1B,gBAAgB,EAAE,EAAE;SACrB,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,6DAA6D;AAC7D,oCAAoC;AACpC,+EAA+E;AAC/E,wBAAwB;AACxB,+EAA+E;AAC/E,cAAc;AACd,6EAA6E;AAC7E,8EAA8E;AAC9E,0DAA0D;AAC1D,2EAA2E;AAC3E,4EAA4E;AAC5E,iCAAiC;AACjC,MAAM,0BAA0B,GAAG,IAAI,GAAG,CAA8B;IACtE,cAAc;IACd,sBAAsB;CACvB,CAAC,CAAC;AACH,SAAS,qCAAqC,CAAC,KAA2C,EAAE,OAAe;IACzG,MAAM,gBAAgB,GAAG,CAAC,0BAA0B,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IACzF,OAAO,gBAAgB,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC;AAC/D,CAAC;AAOD,MAAM,OAAO,qBAAqB;IAChC,kBAAkB,CAA6B;IAC/C,kBAAkB,GAAG,IAAI,GAAG,EAAuD,CAAC;IACpF,iBAAiB,GAAG,IAAI,GAAG,EAA+C,CAAC;IAC3E,wBAAwB,CAAU;IAElC,YAAY,iBAA6C,EAAE,OAAiB;QAC1E,IAAI,CAAC,kBAAkB,GAAG,iBAAiB,CAAC;QAC5C,IAAI,CAAC,wBAAwB,GAAG,OAAO,EAAE,sBAAsB,IAAI,KAAK,CAAC;IAC3E,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,kBAAkB,CAAC,SAAsB,EAAE,KAA+B;QAE9E,MAAM,YAAY,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACxD,IAAI,YAAY,EAAE,CAAC;YACjB,OAAO,YAAY,CAAC;QACtB,CAAC;QAED,MAAM,eAAe,GAAG,SAAS,CAAC,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC3F,sFAAsF;QACtF,oFAAoF;QACpF,uDAAuD;QACvD,eAAe,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC,CAAC;QAElF,qBAAqB;QACrB,MAAM,IAAI,CAAC,WAAW,CAClB,eAAe,EACf,SAAS,CACZ,CAAC;QAEF,MAAM,cAAc,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC1D,IAAI,CAAC,cAAc,EAAE,CAAC;YACpB,kDAAkD;YAClD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,cAAc,CAAC;IACxB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW,CACb,YAAwC,EACxC,SAAsB;QAExB,MAAM,IAAI,CAAC,+BAA+B,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;QACpE,IAAI,CAAC,wBAAwB,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;IACzD,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,+BAA+B,CAAC,YAAwC,EAAE,SAAsB;QAEpG,MAAM,EAAC,cAAc,EAAE,wBAAwB,EAAE,+BAA+B,EAAE,cAAc,EAAC,GAC7F,SAAS,CAAC,YAAY,CAAC;QAE3B,mEAAmE;QACnE,iDAAiD;QACjD,uEAAuE;QACvE,6BAA6B;QAC7B,MAAM,2BAA2B,GAEzB,CAAC,GAAG,wBAAwB,EAAE,GAAG,+BAA+B,CAAC,CAAC;QAE1E,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,+BAA+B,CAAC,cAAc,CAAC,CAAC;QAC5F,MAAM,qBAAqB,GAAG,IAAI,GAAG,EAAmD,CAAC;QACzF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/C,qBAAqB,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACzD,CAAC;QAED,sEAAsE;QACtE,MAAM,gBAAgB,GAAG,yBAAyB,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;QACjF,KAAK,MAAM,kBAAkB,IAAI,2BAA2B,EAAE,CAAC;YAC7D,yFAAyF;YACzF,MAAM,iBAAiB,GAAG,QAAQ,CAAC,cAAc,CAAC,yBAAyB,CACvE,cAAc,EAAE,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAAC;YACrE,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;gBAC/B,wEAAwE;gBACxE,SAAS;YACX,CAAC;YACD,MAAM,YAAY,GAAG,cAAc,CAAC,iBAAiB,CAAC,CAAC;YACvD,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC5D,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACtB,4EAA4E;gBAC5E,SAAS;YACX,CAAC;YACD,MAAM,mBAAmB,GAAG,IAAI,CAAC,sBAAsB,CAAC,kBAAkB,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;YACrG,MAAM,oBAAoB,GAAG,IAAI,CAAC,uBAAuB,CAAC,kBAAkB,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;YACvG,MAAM,wBAAwB,GAAG,qBAAqB,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAChG,IAAI,qBAAqB,GAAsB,IAAI,CAAC;YACpD,IAAI,eAAe,GAAwB,IAAI,CAAC;YAChD,IAAI,wBAAwB,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,CAAC,4BAA4B,CAAC,kBAAkB,CAAC,EAAE,CAAC;gBAC5G,qBAAqB,GAAG,MAAM,IAAI,CAAC,wBAAwB,CAAC,kBAAkB,EAAE,wBAAwB,CAAC,CAAC;gBAC1G,eAAe,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,kBAAkB,EAAE,wBAAwB,CAAC,CAAC;YAChG,CAAC;YAED,IAAI,CAAC,qBAAqB,IAAI,CAAC,eAAe,IAAI,CAAC,mBAAmB,IAAI,CAAC,oBAAoB,EAAE,CAAC;gBAChG,SAAS;YACX,CAAC;YAED,6FAA6F;YAC7F,KAAK,MAAM,KAAK,IAAI,gBAAgB,EAAE,CAAC;gBACrC,MAAM,kBAAkB,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,IAAI,CAAC,kBAAkB,EAAE,KAAK,EAAE,GAAG,EAAE;oBACnG,OAAO;wBACL,YAAY,EAAE,EAAE;wBAChB,OAAO,EAAE,EAAE;wBACX,WAAW,EAAE,EAAE;wBACf,sBAAsB,EAAE,EAAE;wBAC1B,gBAAgB,EAAE,EAAE;qBACrB,CAAC;gBACJ,CAAC,CAAC,CAAC;gBACH,IAAI,qBAAqB;oBACrB,CAAC,kBAAkB,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,qBAAqB,EAAE,IAAI,CAAC,MAAM,CAAC;oBACxG,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;oBAC5D,kBAAkB,CAAC,YAAY,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;gBAC9D,CAAC;gBACD,IAAI,eAAe;oBACf,CAAC,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAC5B,cAAc,CAAC,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC,MAAM,KAAK,eAAe,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC3F,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;gBACnD,CAAC;gBACD,IAAI,mBAAmB,EAAE,CAAC;oBACxB,0EAA0E;oBAC1E,yEAAyE;oBACzE,SAAS;oBACT,kBAAkB,CAAC,WAAW,GAAG,mBAAmB,CAAC;gBACvD,CAAC;gBACD,IAAI,oBAAoB,EAAE,CAAC;oBACzB,kBAAkB,CAAC,sBAAsB,GAAG,oBAAoB,CAAC;gBACnE,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACH,wBAAwB,CAAC,YAAwC,EAAE,SAAsB;QACvF,MAAM,EAAC,cAAc,EAAC,GAAG,SAAS,CAAC,YAAY,CAAC;QAChD,sEAAsE;QACtE,MAAM,gBAAgB,GAAG,yBAAyB,CAAC,YAAY,EAAE,cAAc,CAAC,CAAC;QAEjF,MAAM,mBAAmB,GAAG,CAAC,EAAC,IAAI,EAAiB,EAAW,EAAE;YAC9D,MAAM,SAAS,GAAG,IAAyB,CAAC;YAC5C,OAAO,SAAS,4CAA6B,CAAC;QAChD,CAAC,CAAC;QACF,MAAM,YAAY,GAAG,SAAS,CAAC,QAAQ,CAAC,eAAe,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;QACpF,KAAK,MAAM,MAAM,IAAI,YAAY,EAAE,CAAC;YAClC,6EAA6E;YAC7E,MAAM,iBAAiB,GAAG,QAAQ,CAAC,cAAc,CAAC,yBAAyB,CACvE,cAAc,EAAE,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,GAAG,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YAC7E,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;gBAC/B,wEAAwE;gBACxE,SAAS;YACX,CAAC;YACD,MAAM,YAAY,GAAG,cAAc,CAAC,iBAAiB,CAAC,CAAC;YACvD,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC5D,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACtB,4EAA4E;gBAC5E,SAAS;YACX,CAAC;YACD,MAAM,UAAU,GAAG,SAAS,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAC9D,MAAM,SAAS,GAAG,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,UAAU,CAAC,gBAAgB,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAClG,MAAM,UAAU,GAAG,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC;YACrD,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,SAAS;YACX,CAAC;YACD,6FAA6F;YAC7F,KAAK,MAAM,KAAK,IAAI,gBAAgB,EAAE,CAAC;gBACrC,MAAM,kBAAkB,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,IAAI,CAAC,kBAAkB,EAAE,KAAK,EAAE,GAAG,EAAE;oBACnG,OAAO;wBACL,YAAY,EAAE,EAAE;wBAChB,OAAO,EAAE,EAAE;wBACX,WAAW,EAAE,EAAE;wBACf,sBAAsB,EAAE,EAAE;wBAC1B,gBAAgB,EAAE,EAAE;qBACrB,CAAC;gBACJ,CAAC,CAAC,CAAC;gBACH,IAAI,kBAAkB,CAAC,gBAAgB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBACrD,kBAAkB,CAAC,gBAAgB,GAAG,UAAU,CAAC;gBACnD,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,wBAAwB,CAC1B,kBAA2D,EAC3D,wBAA6C;QAC/C,iCAAiC;QACjC,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,4EAAuD,EAAE,CAAC;YAC/F,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,sBAAsB,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;QACnF,IAAI,CAAC,sBAAsB,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,kBAAkB,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,uBAAuB,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC;QAChH,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACxF,IAAI,cAAc,IAAI,CAAC,CAAC,MAAM,kBAAkB,CAAC,sBAAsB,EAAE,cAAc,CAAC,CAAC,EAAE,CAAC;YAC1F,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,kBAAkB,GAAG,MAAM,IAAI,CAAC,yBAAyB,CAAC,sBAAsB,CAAC,CAAC;QACxF,IAAI,qBAAqB,CAAC,kBAAkB,CAAC,EAAE,CAAC;YAC9C,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,kBAAkB,GAAG,cAAc,CAAC,CAAC,CAAC,yBAAyB,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAE3F,OAAO,EAAC,IAAI,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,kBAAkB,EAAC,CAAC;IAChF,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,kBAAkB,CACpB,kBAA2D,EAC3D,wBAA6C;QAC/C,IAAI,CAAC,IAAI,CAAC,wBAAwB,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,QAAQ,CAAC;YAC5D,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,8EAAwD;YAC3F,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,kFAA0D,EAAE,CAAC;YAClG,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,sBAAsB,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,wBAAwB,CAAC,CAAC;QACnF,IAAI,CAAC,sBAAsB,EAAE,CAAC;YAC5B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,MAAM,GAAG,oBAAoB,CAAC,sBAAsB,CAAC,CAAC;QAC5D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,EAAC,MAAM,EAAC,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,MAA2B;QAC9C,IAAI,WAAW,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACrD,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,OAAO,WAAW,CAAC;QACrB,CAAC;QAED,WAAW,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC5D,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAEhD,OAAO,WAAW,CAAC;IACrB,CAAC;IAED;;;OAGG;IACH,4BAA4B,CACxB,kBAA0G,EAC1G,SAAsB;QACxB,MAAM,uBAAuB,GAAG,SAAS,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE;YACnF,MAAM,WAAW,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC;YACvC,MAAM,WAAW,GAAG,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC;YACvC,OAAO,WAAW,GAAG,WAAW,CAAC;QACnC,CAAC,CAAC,CAAC;QAEH,MAAM,gBAAgB,GAAG,QAAQ,CAAC,cAAc,CAAC,mBAAmB,CAChE,uBAAuB,EAAE,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,GAAG,OAAO,CAAC,GAAG,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAAC;QAC1F,IAAI,gBAAgB,KAAK,IAAI,EAAE,CAAC;YAC9B,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,0BAA0B,GAAG,OAAO,CAAC,MAAM,CAAC,qBAAqB,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;QAEnG,MAAM,4BAA4B,GAAuB,EAAE,CAAC;QAE5D,qDAAqD;QACrD,KAAK,IAAI,CAAC,GAAG,gBAAgB,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3C,MAAM,eAAe,GAAG,uBAAuB,CAAC,CAAC,CAAC,CAAC;YACnD,MAAM,sBAAsB,GAAG,eAAe,CAAC,EAAE,GAAG,eAAe,CAAC,GAAG,CAAC;YACxE,IAAI,kBAAkB,CAAC,EAAE,GAAG,sBAAsB,GAAG,0BAA0B,EAAE,CAAC;gBAChF,MAAM,2BAA2B,GAAqB,EAAC,OAAO,EAAE,eAAe,EAAC,CAAC;gBAEjF,MAAM,SAAS,GAAG,IAAI,CAAC,kBAAkB,CAAC,sBAAsB,CAC5D,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,GAAsC,CAAC,CAAC;gBACtE,2BAA2B,CAAC,SAAS,GAAG,SAAS,IAAI,SAAS,CAAC;gBAC/D,4BAA4B,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;YACjE,CAAC;iBAAM,CAAC;gBACN,2CAA2C;gBAC3C,MAAM;YACR,CAAC;QACH,CAAC;QACD,OAAO,4BAA4B,CAAC;IACtC,CAAC;IAED;;;;;;;;OAQG;IACH,sBAAsB,CAClB,kBAA0G,EAC1G,YAAmC,EAAE,SAAsB;QAC7D,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,8EAAwD,EAAE,CAAC;YAChG,OAAO,IAAI,CAAC;QACd,CAAC;QACD,mFAAmF;QACnF,MAAM,uBAAuB,GAAG,sBAAsB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACzE,IAAI,uBAAuB,KAAK,SAAS,EAAE,CAAC;YAC1C,OAAO,uBAAuB,CAAC;QACjC,CAAC;QAED,MAAM,0BAA0B,GAC5B,IAAI,CAAC,mCAAmC,CAAC,IAAI,CAAC,4BAA4B,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAC,CAAC;QAC/G,sBAAsB,CAAC,GAAG,CAAC,YAAY,EAAE,0BAA0B,CAAC,CAAC;QACrE,OAAO,0BAA0B,CAAC;IACpC,CAAC;IAED;;;OAGG;IACH,mCAAmC,CAAC,4BAAgD;QAClF,MAAM,YAAY,GAAiB,EAAE,CAAC;QAEtC,qDAAqD;QACrD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,4BAA4B,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC7D,MAAM,WAAW,GAAG,4BAA4B,CAAC,CAAC,CAAe,CAAC;YAClE,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC/D,SAAS;YACX,CAAC;YAED,MAAM,QAAQ,GAAG,IAAI,CAAC,kBAAkB,CAAC,iBAAiB,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC9F,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;gBACrD,iEAAiE;gBACjE,oEAAoE;gBACpE,uCAAuC;gBACvC,SAAS;YACX,CAAC;YACD,WAAW,CAAC,QAAQ,GAAG,QAAQ,CAAC;YAChC,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACjC,CAAC;QACD,OAAO,YAAY,CAAC;IACtB,CAAC;IAED;;;;;;OAMG;IACH,uBAAuB,CACnB,kBAA0G,EAC1G,YAAmC,EAAE,SAAsB;QAC7D,mFAAmF;QACnF,MAAM,sBAAsB,GAAG,sBAAsB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;QACxE,IAAI,sBAAsB,KAAK,SAAS,EAAE,CAAC;YACzC,OAAO,sBAAsB,CAAC;QAChC,CAAC;QAED,MAAM,0BAA0B,GAC5B,0CAA0C,CAAC,IAAI,CAAC,4BAA4B,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAC,CAAC;QACjH,sBAAsB,CAAC,GAAG,CAAC,YAAY,EAAE,0BAA0B,CAAC,CAAC;QACrE,OAAO,0BAA0B,CAAC;IACpC,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,+BAA+B,CAAC,IAAuB;QAC3D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,uBAAuB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAEpF,SAAS,sBAAsB,CAAC,WAAmB;YACjD,IAAI,IAAI,GAAG,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;YACvF,IAAI,IAAI,EAAE,CAAC;gBACT,OAAO,IAAI,CAAC,KAAK,CAAC;YACpB,CAAC;YAED,KAAK,MAAM,EAAC,IAAI,EAAC,IAAI,QAAQ,CAAC,eAAe,IAAI,EAAE,EAAE,CAAC;gBACpD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;gBAC9E,IAAI,IAAI,EAAE,CAAC;oBACT,OAAO,IAAI,CAAC,KAAK,CAAC;gBACpB,CAAC;YACH,CAAC;YAED,IAAI,GAAG,QAAQ,CAAC,eAAe,EAAE,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;YACvF,IAAI,IAAI,EAAE,CAAC;gBACT,OAAO,IAAI,CAAC,KAAK,CAAC;YACpB,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,sBAAsB,CAAC;IAChC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,yBAAyB,CAAC,IAAuB;QACrD,MAAM,kBAAkB,GAAkB,EAAE,CAAC;QAE7C,MAAM,qBAAqB,GAAG,MAAM,IAAI,CAAC,+BAA+B,CAAC,IAAI,CAAC,CAAC;QAC/E,IAAI,CAAC,qBAAqB,EAAE,CAAC;YAC3B,OAAO,kBAAkB,CAAC;QAC5B,CAAC;QAED,MAAM,cAAc,GAAG,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC;QAC7C,MAAM,UAAU,GAAG,EAAE,CAAC;QACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YAClD,UAAU,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC,GAAG,CAAC,CAAC,EAAC,CAAC,CAAC;QAC3E,CAAC;QAED,MAAM,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,QAAQ,IAAI,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC;QACpG,MAAM,SAAS,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,OAAO,IAAI,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC;QAElG,MAAM,sBAAsB,GAAG,qBAAqB,CAAC,cAAc,CAAC,IAAI,SAAS,CAAC;QAElF,IAAI,UAAU,IAAI,SAAS,IAAI,sBAAsB,EAAE,CAAC;YACtD,OAAO,EAAC,MAAM,EAAE,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE,WAAW,EAAE,sBAAsB,EAAC,CAAC;QACjG,CAAC;QAED,MAAM,SAAS,GAAG,qBAAqB,CAAC,QAAQ,CAAC,IAAI,SAAS,CAAC;QAC/D,MAAM,QAAQ,GAAG,qBAAqB,CAAC,OAAO,CAAC,IAAI,SAAS,CAAC;QAC7D,OAAO,EAAC,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,sBAAsB,EAAC,CAAC;IACnF,CAAC;CACF;AAED;;;GAGG;AACH,SAAS,0CAA0C,CAAC,4BAAgD;IAElG,MAAM,sBAAsB,GAA4B,EAAE,CAAC;IAE3D,qDAAqD;IACrD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,4BAA4B,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7D,MAAM,WAAW,GAAG,4BAA4B,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QAC5E,IAAI,CAAC,qCAAqC,CAAC,4BAA4B,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,CAAC;YACjG,SAAS;QACX,CAAC;QACD,sBAAsB,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC,CAA0B,CAAC,CAAC;IACxF,CAAC;IACD,OAAO,sBAAsB,CAAC;AAChC,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAuB;IACnD,IAAI,IAAI,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;IAC/B,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IACD,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC7B,MAAM,aAAa,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;QAClD,IAAI,aAAa,EAAE,CAAC;YAClB,OAAO,aAAa,CAAC;QACvB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,0BAA0B,CAAC,aAAqB;IACvD,OAAO,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;AAC1E,CAAC;AAED,SAAS,uBAAuB,CAAC,IAAqB;IACpD,OAAO,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;AACvC,CAAC;AAED,SAAS,8BAA8B,CAAC,aAAkC;IACxE,MAAM,aAAa,GAAG,oBAAoB,CAAC;IAC3C,MAAM,eAAe,GAAG,aAAa,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAC9D,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;AAC7C,CAAC;AAED,SAAS,6BAA6B,CAAC,aAAkC;IACvE,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC/C,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,QAAQ,KAAK,OAAO,IAAI,QAAQ,KAAK,UAAU,CAAC;AACzD,CAAC;AAED,SAAS,yBAAyB,CAAC,aAAkC;IACnE,MAAM,kBAAkB,GAAkB,EAAE,CAAC;IAC7C,kBAAkB,CAAC,MAAM,GAAG,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IACxD,kBAAkB,CAAC,KAAK,GAAG,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACtD,kBAAkB,CAAC,WAAW,GAAG,aAAa,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IACnE,OAAO,kBAAkB,CAAC;AAC5B,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,kBAAkB,CAAC,IAAuB,EAAE,aAAkC;IAC3F,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;IACjC,MAAM,iBAAiB,GAAG,8BAA8B,CAAC,aAAa,CAAC,CAAC;IACxE,IAAI,SAAS,KAAK,KAAK,IAAI,SAAS,KAAK,OAAO,IAAI,CAAC,iBAAiB,EAAE,CAAC;QACvE,uBAAuB;QACvB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,OAAO,GAAG,6BAA6B,CAAC,aAAa,CAAC,CAAC;IAC7D,OAAO,CAAC,OAAO,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,SAAS,qBAAqB,CAAC,UAAyB;IACtD,MAAM,EAAC,MAAM,EAAE,KAAK,EAAE,WAAW,EAAC,GAAG,UAAU,CAAC;IAEhD,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,IAAI,0BAA0B,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7E,MAAM,aAAa,GAAG,OAAO,CAAC,KAAK,IAAI,0BAA0B,CAAC,KAAK,CAAC,CAAC,CAAC;IAC1E,MAAM,mBAAmB,GAAG,OAAO,CAAC,WAAW,IAAI,0BAA0B,CAAC,WAAW,CAAC,CAAC,CAAC;IAE5F,MAAM,cAAc,GAAG,CAAC,cAAc,IAAI,aAAa,CAAC,IAAI,mBAAmB,CAAC;IAChF,OAAO,CAAC,cAAc,IAAI,aAAa,CAAC,IAAI,cAAc,CAAC;AAC7D,CAAC;AAED;;;GAGG;AACH,SAAS,yBAAyB,CAC9B,YAAwC,EACxC,cAAuC;IAEzC,sEAAsE;IACtE,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAqD,CAAC;IAEtF,wDAAwD;IACxD,KAAK,MAAM,aAAa,IAAI,cAAc,EAAE,CAAC;QAC3C,MAAM,eAAe,GACjB,QAAQ,CAAC,cAAc,CAAC,yBAAyB,CAAC,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,IAAI,aAAa,CAAC,EAAE,CAAC,CAAC;QAC3G,IAAI,eAAe,KAAK,IAAI,EAAE,CAAC;YAC7B,mEAAmE;YACnE,SAAS;QACX,CAAC;QACD,KAAK,IAAI,CAAC,GAAG,eAAe,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC3D,MAAM,KAAK,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;YAC9B,IAAI,KAAK,CAAC,EAAE,IAAI,aAAa,CAAC,EAAE,IAAI,KAAK,CAAC,EAAE,IAAI,aAAa,CAAC,EAAE,GAAG,aAAa,CAAC,GAAG,EAAE,CAAC;gBACrF,MAAM,gBAAgB,GAAG,QAAQ,CAAC,YAAY,CAAC,cAAc,CAAC,gBAAgB,EAAE,aAAa,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;gBACzG,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC/B,CAAC;YACD,IAAI,KAAK,CAAC,EAAE,GAAG,aAAa,CAAC,EAAE,GAAG,aAAa,CAAC,GAAG,EAAE,CAAC;gBACpD,8DAA8D;gBAC9D,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,gBAAgB,CAAC;AAC1B,CAAC","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport type * as Protocol from '../../../generated/protocol.js';\nimport {type ParsedTrace} from '../handlers/types.js';\nimport * as Helpers from '../helpers/helpers.js';\nimport * as Types from '../types/types.js';\n\nimport {type RootCauseProtocolInterface} from './RootCauses.js';\n\nexport type CSSDimensions = {\n width?: string,\n height?: string,\n aspectRatio?: string,\n};\n\nexport interface UnsizedMedia {\n node: Protocol.DOM.Node;\n authoredDimensions?: CSSDimensions;\n computedDimensions: CSSDimensions;\n}\n\nexport interface InjectedIframe {\n iframe: Protocol.DOM.Node;\n}\n\nexport interface RootCauseRequest {\n request: Types.Events.SyntheticNetworkRequest;\n initiator?: Protocol.Network.Initiator;\n}\n\nexport interface FontChange extends RootCauseRequest {\n fontFace: Protocol.CSS.FontFace;\n}\n\nexport interface RenderBlockingRequest extends RootCauseRequest {}\n\nexport interface LayoutShiftRootCausesData {\n unsizedMedia: UnsizedMedia[];\n iframes: InjectedIframe[];\n fontChanges: FontChange[];\n renderBlockingRequests: RenderBlockingRequest[];\n scriptStackTrace: Types.Events.CallFrame[];\n}\n\nconst fontRequestsByPrePaint = new Map();\nconst renderBlocksByPrePaint = new Map();\n\nfunction setDefaultValue(\n map: Map, shift: Types.Events.LayoutShift): void {\n Platform.MapUtilities.getWithDefault(map, shift, () => {\n return {\n unsizedMedia: [],\n iframes: [],\n fontChanges: [],\n renderBlockingRequests: [],\n scriptStackTrace: [],\n };\n });\n}\n\n// Important: we purposefully treat `potentially_blocking` as\n// non-render-blocking here because:\n// 1. An async script can run on the main thread at any point, including before\n// the page is loaded\n// 2. An async script will never block the parsing and rendering process of the\n// browser.\n// 3. Therefore, from a developer's point of view, there is nothing more they\n// can do if they've put `async` on, and within the context of Insights, we\n// shouldn't report an async script as render blocking.\n// In the future we may want to consider suggesting the use of `defer` over\n// `async`, as it doesn't have this concern, but for now we'll allow `async`\n// and not report it as an issue.\nconst NON_RENDER_BLOCKING_VALUES = new Set([\n 'non_blocking',\n 'potentially_blocking',\n]);\nfunction networkRequestIsRenderBlockingInFrame(event: Types.Events.SyntheticNetworkRequest, frameId: string): boolean {\n const isRenderBlocking = !NON_RENDER_BLOCKING_VALUES.has(event.args.data.renderBlocking);\n return isRenderBlocking && event.args.data.frame === frameId;\n}\n\ninterface Options {\n /** Checking iframe root causes can be an expensive operation, so it is disabled by default. */\n enableIframeRootCauses?: boolean;\n}\n\nexport class LayoutShiftRootCauses {\n #protocolInterface: RootCauseProtocolInterface;\n #rootCauseCacheMap = new Map();\n #nodeDetailsCache = new Map();\n #iframeRootCausesEnabled: boolean;\n\n constructor(protocolInterface: RootCauseProtocolInterface, options?: Options) {\n this.#protocolInterface = protocolInterface;\n this.#iframeRootCausesEnabled = options?.enableIframeRootCauses ?? false;\n }\n\n /**\n * Calculates the potential root causes for a given layout shift event. Once\n * calculated, this data is cached.\n * Note: because you need all layout shift data at once to calculate these\n * correctly, this function will parse the root causes for _all_ layout shift\n * events the first time that it's called. That then populates the cache for\n * each shift, so any subsequent calls are just a constant lookup.\n */\n async rootCausesForEvent(modelData: ParsedTrace, event: Types.Events.LayoutShift):\n Promise|null> {\n const cachedResult = this.#rootCauseCacheMap.get(event);\n if (cachedResult) {\n return cachedResult;\n }\n\n const allLayoutShifts = modelData.LayoutShifts.clusters.flatMap(cluster => cluster.events);\n // Make sure a value in the cache is set even for shifts that don't have a root cause,\n // so that we don't have to recompute when no root causes are found. In case a cause\n // for a shift is found, the default value is replaced.\n allLayoutShifts.forEach(shift => setDefaultValue(this.#rootCauseCacheMap, shift));\n\n // Populate the cache\n await this.blameShifts(\n allLayoutShifts,\n modelData,\n );\n\n const resultForEvent = this.#rootCauseCacheMap.get(event);\n if (!resultForEvent) {\n // No root causes available for this layout shift.\n return null;\n }\n return resultForEvent;\n }\n\n /**\n * Determines potential root causes for shifts\n */\n async blameShifts(\n layoutShifts: Types.Events.LayoutShift[],\n modelData: ParsedTrace,\n ): Promise {\n await this.linkShiftsToLayoutInvalidations(layoutShifts, modelData);\n this.linkShiftsToLayoutEvents(layoutShifts, modelData);\n }\n\n /**\n * \"LayoutInvalidations\" are a set of trace events dispatched in Blink under the name\n * \"layoutInvalidationTracking\", which track invalidations on the \"Layout\"stage of the\n * rendering pipeline. This function utilizes this event to flag potential root causes\n * to layout shifts.\n */\n async linkShiftsToLayoutInvalidations(layoutShifts: Types.Events.LayoutShift[], modelData: ParsedTrace):\n Promise {\n const {prePaintEvents, layoutInvalidationEvents, scheduleStyleInvalidationEvents, backendNodeIds} =\n modelData.LayoutShifts;\n\n // For the purposes of determining root causes of layout shifts, we\n // consider scheduleStyleInvalidationTracking and\n // LayoutInvalidationTracking events as events that could have been the\n // cause of the layout shift.\n const eventsForLayoutInvalidation:\n Array =\n [...layoutInvalidationEvents, ...scheduleStyleInvalidationEvents];\n\n const nodes = await this.#protocolInterface.pushNodesByBackendIdsToFrontend(backendNodeIds);\n const nodeIdsByBackendIdMap = new Map();\n for (let i = 0; i < backendNodeIds.length; i++) {\n nodeIdsByBackendIdMap.set(backendNodeIds[i], nodes[i]);\n }\n\n // Maps from PrePaint events to LayoutShifts that occured in each one.\n const shiftsByPrePaint = getShiftsByPrePaintEvents(layoutShifts, prePaintEvents);\n for (const layoutInvalidation of eventsForLayoutInvalidation) {\n // Get the first PrePaint event that happened after the current LayoutInvalidation event.\n const nextPrePaintIndex = Platform.ArrayUtilities.nearestIndexFromBeginning(\n prePaintEvents, prePaint => prePaint.ts > layoutInvalidation.ts);\n if (nextPrePaintIndex === null) {\n // No PrePaint event registered after this LayoutInvalidation. Continue.\n continue;\n }\n const nextPrePaint = prePaintEvents[nextPrePaintIndex];\n const subsequentShifts = shiftsByPrePaint.get(nextPrePaint);\n if (!subsequentShifts) {\n // The PrePaint after the current LayoutInvalidation doesn't contain shifts.\n continue;\n }\n const fontChangeRootCause = this.getFontChangeRootCause(layoutInvalidation, nextPrePaint, modelData);\n const renderBlockRootCause = this.getRenderBlockRootCause(layoutInvalidation, nextPrePaint, modelData);\n const layoutInvalidationNodeId = nodeIdsByBackendIdMap.get(layoutInvalidation.args.data.nodeId);\n let unsizedMediaRootCause: UnsizedMedia|null = null;\n let iframeRootCause: InjectedIframe|null = null;\n if (layoutInvalidationNodeId !== undefined && Types.Events.isLayoutInvalidationTracking(layoutInvalidation)) {\n unsizedMediaRootCause = await this.getUnsizedMediaRootCause(layoutInvalidation, layoutInvalidationNodeId);\n iframeRootCause = await this.getIframeRootCause(layoutInvalidation, layoutInvalidationNodeId);\n }\n\n if (!unsizedMediaRootCause && !iframeRootCause && !fontChangeRootCause && !renderBlockRootCause) {\n continue;\n }\n\n // Add found potential root causes to all the shifts in this PrePaint and populate the cache.\n for (const shift of subsequentShifts) {\n const rootCausesForShift = Platform.MapUtilities.getWithDefault(this.#rootCauseCacheMap, shift, () => {\n return {\n unsizedMedia: [],\n iframes: [],\n fontChanges: [],\n renderBlockingRequests: [],\n scriptStackTrace: [],\n };\n });\n if (unsizedMediaRootCause &&\n !rootCausesForShift.unsizedMedia.some(media => media.node.nodeId === unsizedMediaRootCause?.node.nodeId) &&\n shift.args.frame === layoutInvalidation.args.data.frame) {\n rootCausesForShift.unsizedMedia.push(unsizedMediaRootCause);\n }\n if (iframeRootCause &&\n !rootCausesForShift.iframes.some(\n injectedIframe => injectedIframe.iframe.nodeId === iframeRootCause?.iframe.nodeId)) {\n rootCausesForShift.iframes.push(iframeRootCause);\n }\n if (fontChangeRootCause) {\n // Unlike other root causes, we calculate fonts causing a shift only once,\n // which means we assign the built array instead of appending new objects\n // to it.\n rootCausesForShift.fontChanges = fontChangeRootCause;\n }\n if (renderBlockRootCause) {\n rootCausesForShift.renderBlockingRequests = renderBlockRootCause;\n }\n }\n }\n }\n\n /**\n * For every shift looks up the initiator of its corresponding Layout event. This initiator\n * is assigned by the RendererHandler and contains the stack trace of the point in a script\n * that caused a style recalculation or a relayout. This stack trace is added to the shift's\n * potential root causes.\n * Note that a Layout cannot always be linked to a script, in that case, we cannot add a\n * \"script causing reflow\" as a potential root cause to the corresponding shift.\n */\n linkShiftsToLayoutEvents(layoutShifts: Types.Events.LayoutShift[], modelData: ParsedTrace): void {\n const {prePaintEvents} = modelData.LayoutShifts;\n // Maps from PrePaint events to LayoutShifts that occured in each one.\n const shiftsByPrePaint = getShiftsByPrePaintEvents(layoutShifts, prePaintEvents);\n\n const eventTriggersLayout = ({name}: {name: string}): boolean => {\n const knownName = name as Types.Events.Name;\n return knownName === Types.Events.Name.LAYOUT;\n };\n const layoutEvents = modelData.Renderer.allTraceEntries.filter(eventTriggersLayout);\n for (const layout of layoutEvents) {\n // Get the first PrePaint event that happened after the current layout event.\n const nextPrePaintIndex = Platform.ArrayUtilities.nearestIndexFromBeginning(\n prePaintEvents, prePaint => prePaint.ts > layout.ts + (layout.dur || 0));\n if (nextPrePaintIndex === null) {\n // No PrePaint event registered after this LayoutInvalidation. Continue.\n continue;\n }\n const nextPrePaint = prePaintEvents[nextPrePaintIndex];\n const subsequentShifts = shiftsByPrePaint.get(nextPrePaint);\n if (!subsequentShifts) {\n // The PrePaint after the current LayoutInvalidation doesn't contain shifts.\n continue;\n }\n const layoutNode = modelData.Renderer.entryToNode.get(layout);\n const initiator = layoutNode ? modelData.Initiators.eventToInitiator.get(layoutNode.entry) : null;\n const stackTrace = initiator?.args?.data?.stackTrace;\n if (!stackTrace) {\n continue;\n }\n // Add found potential root causes to all the shifts in this PrePaint and populate the cache.\n for (const shift of subsequentShifts) {\n const rootCausesForShift = Platform.MapUtilities.getWithDefault(this.#rootCauseCacheMap, shift, () => {\n return {\n unsizedMedia: [],\n iframes: [],\n fontChanges: [],\n renderBlockingRequests: [],\n scriptStackTrace: [],\n };\n });\n if (rootCausesForShift.scriptStackTrace.length === 0) {\n rootCausesForShift.scriptStackTrace = stackTrace;\n }\n }\n }\n }\n\n /**\n * Given a LayoutInvalidation trace event, determines if it was dispatched\n * because a media element without dimensions was resized.\n */\n async getUnsizedMediaRootCause(\n layoutInvalidation: Types.Events.LayoutInvalidationTracking,\n layoutInvalidationNodeId: Protocol.DOM.NodeId): Promise {\n // Filter events to resizes only.\n if (layoutInvalidation.args.data.reason !== Types.Events.LayoutInvalidationReason.SIZE_CHANGED) {\n return null;\n }\n\n const layoutInvalidationNode = await this.getNodeDetails(layoutInvalidationNodeId);\n if (!layoutInvalidationNode) {\n return null;\n }\n\n const computedStylesList = await this.#protocolInterface.getComputedStyleForNode(layoutInvalidationNode.nodeId);\n const computedStyles = new Map(computedStylesList.map(item => [item.name, item.value]));\n if (computedStyles && !(await nodeIsUnfixedMedia(layoutInvalidationNode, computedStyles))) {\n return null;\n }\n const authoredDimensions = await this.getNodeAuthoredDimensions(layoutInvalidationNode);\n if (dimensionsAreExplicit(authoredDimensions)) {\n return null;\n }\n const computedDimensions = computedStyles ? getNodeComputedDimensions(computedStyles) : {};\n\n return {node: layoutInvalidationNode, authoredDimensions, computedDimensions};\n }\n\n /**\n * Given a LayoutInvalidation trace event, determines if it was dispatched\n * because a node, which is an ancestor to an iframe, was injected.\n */\n async getIframeRootCause(\n layoutInvalidation: Types.Events.LayoutInvalidationTracking,\n layoutInvalidationNodeId: Protocol.DOM.NodeId): Promise {\n if (!this.#iframeRootCausesEnabled) {\n return null;\n }\n\n if (!layoutInvalidation.args.data.nodeName?.startsWith('IFRAME') &&\n layoutInvalidation.args.data.reason !== Types.Events.LayoutInvalidationReason.STYLE_CHANGED &&\n layoutInvalidation.args.data.reason !== Types.Events.LayoutInvalidationReason.ADDED_TO_LAYOUT) {\n return null;\n }\n\n const layoutInvalidationNode = await this.getNodeDetails(layoutInvalidationNodeId);\n if (!layoutInvalidationNode) {\n return null;\n }\n\n const iframe = firstIframeInDOMTree(layoutInvalidationNode);\n if (!iframe) {\n return null;\n }\n return {iframe};\n }\n\n async getNodeDetails(nodeId: Protocol.DOM.NodeId): Promise {\n let nodeDetails = this.#nodeDetailsCache.get(nodeId);\n if (nodeDetails !== undefined) {\n return nodeDetails;\n }\n\n nodeDetails = await this.#protocolInterface.getNode(nodeId);\n this.#nodeDetailsCache.set(nodeId, nodeDetails);\n\n return nodeDetails;\n }\n\n /**\n * Given a layout invalidation event and a sorted array, returns the subset of requests that arrived within a\n * 500ms window before the layout invalidation.\n */\n requestsInInvalidationWindow(\n layoutInvalidation: Types.Events.LayoutInvalidationTracking|Types.Events.ScheduleStyleInvalidationTracking,\n modelData: ParsedTrace): RootCauseRequest[] {\n const requestsSortedByEndTime = modelData.NetworkRequests.byTime.sort((req1, req2) => {\n const req1EndTime = req1.ts + req1.dur;\n const req2EndTime = req2.ts + req2.dur;\n return req1EndTime - req2EndTime;\n });\n\n const lastRequestIndex = Platform.ArrayUtilities.nearestIndexFromEnd(\n requestsSortedByEndTime, request => request.ts + request.dur < layoutInvalidation.ts);\n if (lastRequestIndex === null) {\n return [];\n }\n\n const MAX_DELTA_FOR_FONT_REQUEST = Helpers.Timing.secondsToMicroseconds(Types.Timing.Seconds(0.5));\n\n const requestsInInvalidationWindow: RootCauseRequest[] = [];\n\n // Get all requests finished within the valid window.\n for (let i = lastRequestIndex; i > -1; i--) {\n const previousRequest = requestsSortedByEndTime[i];\n const previousRequestEndTime = previousRequest.ts + previousRequest.dur;\n if (layoutInvalidation.ts - previousRequestEndTime < MAX_DELTA_FOR_FONT_REQUEST) {\n const requestInInvalidationWindow: RootCauseRequest = {request: previousRequest};\n\n const initiator = this.#protocolInterface.getInitiatorForRequest(\n previousRequest.args.data.url as Platform.DevToolsPath.UrlString);\n requestInInvalidationWindow.initiator = initiator || undefined;\n requestsInInvalidationWindow.push(requestInInvalidationWindow);\n } else {\n // No more requests fit in the time window.\n break;\n }\n }\n return requestsInInvalidationWindow;\n }\n\n /**\n * Given a LayoutInvalidation trace event, determines if it was dispatched\n * because fonts were changed and if so returns the information of all network\n * request with which the fonts were possibly fetched, if any. The computed\n * network requests are cached for the corresponding prepaint event, meaning\n * that other LayoutInvalidation events that correspond to the same prepaint\n * are not processed and the cached network requests for the prepaint is\n * returned instead.\n */\n getFontChangeRootCause(\n layoutInvalidation: Types.Events.LayoutInvalidationTracking|Types.Events.ScheduleStyleInvalidationTracking,\n nextPrePaint: Types.Events.PrePaint, modelData: ParsedTrace): FontChange[]|null {\n if (layoutInvalidation.args.data.reason !== Types.Events.LayoutInvalidationReason.FONTS_CHANGED) {\n return null;\n }\n // Prevent computing the result of this function multiple times per PrePaint event.\n const fontRequestsForPrepaint = fontRequestsByPrePaint.get(nextPrePaint);\n if (fontRequestsForPrepaint !== undefined) {\n return fontRequestsForPrepaint;\n }\n\n const fontRequestsInThisPrepaint =\n this.getFontRequestsInInvalidationWindow(this.requestsInInvalidationWindow(layoutInvalidation, modelData));\n fontRequestsByPrePaint.set(nextPrePaint, fontRequestsInThisPrepaint);\n return fontRequestsInThisPrepaint;\n }\n\n /**\n * Given the requests that arrived within a 500ms window before the layout invalidation, returns the font\n * requests of them.\n */\n getFontRequestsInInvalidationWindow(requestsInInvalidationWindow: RootCauseRequest[]): FontChange[] {\n const fontRequests: FontChange[] = [];\n\n // Get all requests finished within the valid window.\n for (let i = 0; i < requestsInInvalidationWindow.length; i++) {\n const fontRequest = requestsInInvalidationWindow[i] as FontChange;\n if (!fontRequest.request.args.data.mimeType.startsWith('font')) {\n continue;\n }\n\n const fontFace = this.#protocolInterface.fontFaceForSource(fontRequest.request.args.data.url);\n if (!fontFace || fontFace.fontDisplay === 'optional') {\n // Setting font-display to optional is part of what the developer\n // can do to avoid layout shifts due to FOIT/FOUT, as such we cannot\n // suggest any actionable insight here.\n continue;\n }\n fontRequest.fontFace = fontFace;\n fontRequests.push(fontRequest);\n }\n return fontRequests;\n }\n\n /**\n * Given a LayoutInvalidation trace event, determines if it arrived within a 500ms window before the layout\n * invalidation and if so returns the information of all network request, if any. The computed network\n * requests are cached for the corresponding prepaint event, meaning that other LayoutInvalidation events\n * that correspond to the same prepaint are not processed and the cached network requests for the prepaint is\n * returned instead.\n */\n getRenderBlockRootCause(\n layoutInvalidation: Types.Events.LayoutInvalidationTracking|Types.Events.ScheduleStyleInvalidationTracking,\n nextPrePaint: Types.Events.PrePaint, modelData: ParsedTrace): RenderBlockingRequest[]|null {\n // Prevent computing the result of this function multiple times per PrePaint event.\n const renderBlocksInPrepaint = renderBlocksByPrePaint.get(nextPrePaint);\n if (renderBlocksInPrepaint !== undefined) {\n return renderBlocksInPrepaint;\n }\n\n const renderBlocksInThisPrepaint =\n getRenderBlockRequestsInInvalidationWindow(this.requestsInInvalidationWindow(layoutInvalidation, modelData));\n renderBlocksByPrePaint.set(nextPrePaint, renderBlocksInThisPrepaint);\n return renderBlocksInThisPrepaint;\n }\n\n /**\n * Returns a function that retrieves the active value of a given\n * CSS property within the matched styles of the param node.\n * The first occurence within the matched styles is returned and the\n * value is looked up in the following order, which follows CSS\n * specificity:\n * 1. Inline styles.\n * 2. CSS rules matching this node, from all applicable stylesheets.\n * 3. Attribute defined styles.\n */\n async nodeMatchedStylesPropertyGetter(node: Protocol.DOM.Node): Promise<((property: string) => string | null)> {\n const response = await this.#protocolInterface.getMatchedStylesForNode(node.nodeId);\n\n function cssPropertyValueGetter(cssProperty: string): string|null {\n let prop = response.inlineStyle?.cssProperties.find(prop => prop.name === cssProperty);\n if (prop) {\n return prop.value;\n }\n\n for (const {rule} of response.matchedCSSRules || []) {\n const prop = rule.style.cssProperties.find(prop => prop.name === cssProperty);\n if (prop) {\n return prop.value;\n }\n }\n\n prop = response.attributesStyle?.cssProperties.find(prop => prop.name === cssProperty);\n if (prop) {\n return prop.value;\n }\n\n return null;\n }\n return cssPropertyValueGetter;\n }\n\n /**\n * Returns the CSS dimensions set to the node from its matched styles.\n */\n async getNodeAuthoredDimensions(node: Protocol.DOM.Node): Promise {\n const authoredDimensions: CSSDimensions = {};\n\n const cssMatchedRulesGetter = await this.nodeMatchedStylesPropertyGetter(node);\n if (!cssMatchedRulesGetter) {\n return authoredDimensions;\n }\n\n const attributesFlat = node.attributes || [];\n const attributes = [];\n for (let i = 0; i < attributesFlat.length; i += 2) {\n attributes.push({name: attributesFlat[i], value: attributesFlat[i + 1]});\n }\n\n const htmlHeight = attributes.find(attr => attr.name === 'height' && htmlAttributeIsExplicit(attr));\n const htmlWidth = attributes.find(attr => attr.name === 'width' && htmlAttributeIsExplicit(attr));\n\n const cssExplicitAspectRatio = cssMatchedRulesGetter('aspect-ratio') || undefined;\n\n if (htmlHeight && htmlWidth && cssExplicitAspectRatio) {\n return {height: htmlHeight.value, width: htmlWidth.value, aspectRatio: cssExplicitAspectRatio};\n }\n\n const cssHeight = cssMatchedRulesGetter('height') || undefined;\n const cssWidth = cssMatchedRulesGetter('width') || undefined;\n return {height: cssHeight, width: cssWidth, aspectRatio: cssExplicitAspectRatio};\n }\n}\n\n/**\n * Given the requests that arrived within a 500ms window before the layout invalidation, returns the render\n * block requests of them.\n */\nfunction getRenderBlockRequestsInInvalidationWindow(requestsInInvalidationWindow: RootCauseRequest[]):\n RenderBlockingRequest[] {\n const renderBlockingRequests: RenderBlockingRequest[] = [];\n\n // Get all requests finished within the valid window.\n for (let i = 0; i < requestsInInvalidationWindow.length; i++) {\n const mainFrameId = requestsInInvalidationWindow[i].request.args.data.frame;\n if (!networkRequestIsRenderBlockingInFrame(requestsInInvalidationWindow[i].request, mainFrameId)) {\n continue;\n }\n renderBlockingRequests.push(requestsInInvalidationWindow[i] as RenderBlockingRequest);\n }\n return renderBlockingRequests;\n}\n\nfunction firstIframeInDOMTree(root: Protocol.DOM.Node): Protocol.DOM.Node|null {\n if (root.nodeName === 'IFRAME') {\n return root;\n }\n const children = root.children;\n if (!children) {\n return null;\n }\n for (const child of children) {\n const iFrameInChild = firstIframeInDOMTree(child);\n if (iFrameInChild) {\n return iFrameInChild;\n }\n }\n return null;\n}\n\nfunction cssPropertyIsExplicitlySet(propertyValue: string): boolean {\n return !['auto', 'initial', 'unset', 'inherit'].includes(propertyValue);\n}\n\nfunction htmlAttributeIsExplicit(attr: {value: string}): boolean {\n return parseInt(attr.value, 10) >= 0;\n}\n\nfunction computedStyleHasBackroundImage(computedStyle: Map): boolean {\n const CSS_URL_REGEX = /^url\\(\"([^\"]+)\"\\)$/;\n const backgroundImage = computedStyle.get('background-image');\n if (!backgroundImage) {\n return false;\n }\n return CSS_URL_REGEX.test(backgroundImage);\n}\n\nfunction computedStyleHasFixedPosition(computedStyle: Map): boolean {\n const position = computedStyle.get('position');\n if (!position) {\n return false;\n }\n return position === 'fixed' || position === 'absolute';\n}\n\nfunction getNodeComputedDimensions(computedStyle: Map): CSSDimensions {\n const computedDimensions: CSSDimensions = {};\n computedDimensions.height = computedStyle.get('height');\n computedDimensions.width = computedStyle.get('width');\n computedDimensions.aspectRatio = computedStyle.get('aspect-ratio');\n return computedDimensions;\n}\n\n/**\n * Determines if a node is a media element and is not fixed positioned\n * (i.e. \"position: fixed;\" or \"position: absolute;\")\n */\nasync function nodeIsUnfixedMedia(node: Protocol.DOM.Node, computedStyle: Map): Promise {\n const localName = node.localName;\n const isBackgroundImage = computedStyleHasBackroundImage(computedStyle);\n if (localName !== 'img' && localName !== 'video' && !isBackgroundImage) {\n // Not a media element.\n return false;\n }\n const isFixed = computedStyleHasFixedPosition(computedStyle);\n return !isFixed;\n}\n\n/**\n * Determines if a CSS dimensions object explicitly defines both width and height\n * (i.e. not set to auto, inherit, etc.)\n */\nfunction dimensionsAreExplicit(dimensions: CSSDimensions): boolean {\n const {height, width, aspectRatio} = dimensions;\n\n const explicitHeight = Boolean(height && cssPropertyIsExplicitlySet(height));\n const explicitWidth = Boolean(width && cssPropertyIsExplicitlySet(width));\n const explicitAspectRatio = Boolean(aspectRatio && cssPropertyIsExplicitlySet(aspectRatio));\n\n const explicitWithAR = (explicitHeight || explicitWidth) && explicitAspectRatio;\n return (explicitHeight && explicitWidth) || explicitWithAR;\n}\n\n/**\n * Given an array of layout shift and PrePaint events, returns a mapping from\n * PrePaint events to layout shifts dispatched within it.\n */\nfunction getShiftsByPrePaintEvents(\n layoutShifts: Types.Events.LayoutShift[],\n prePaintEvents: Types.Events.PrePaint[],\n ): Map {\n // Maps from PrePaint events to LayoutShifts that occured in each one.\n const shiftsByPrePaint = new Map();\n\n // Associate all shifts to their corresponding PrePaint.\n for (const prePaintEvent of prePaintEvents) {\n const firstShiftIndex =\n Platform.ArrayUtilities.nearestIndexFromBeginning(layoutShifts, shift => shift.ts >= prePaintEvent.ts);\n if (firstShiftIndex === null) {\n // No layout shifts registered after this PrePaint start. Continue.\n continue;\n }\n for (let i = firstShiftIndex; i < layoutShifts.length; i++) {\n const shift = layoutShifts[i];\n if (shift.ts >= prePaintEvent.ts && shift.ts <= prePaintEvent.ts + prePaintEvent.dur) {\n const shiftsInPrePaint = Platform.MapUtilities.getWithDefault(shiftsByPrePaint, prePaintEvent, () => []);\n shiftsInPrePaint.push(shift);\n }\n if (shift.ts > prePaintEvent.ts + prePaintEvent.dur) {\n // Reached the end of this PrePaint. Continue to the next one.\n break;\n }\n }\n }\n return shiftsByPrePaint;\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/root-causes/LayoutShift.test.js b/public/models/trace/root-causes/LayoutShift.test.js index 4cd12a72b..f05327597 100644 --- a/public/models/trace/root-causes/LayoutShift.test.js +++ b/public/models/trace/root-causes/LayoutShift.test.js @@ -3,7 +3,7 @@ // found in the LICENSE file. import { describeWithMockConnection, } from '../../../testing/MockConnection.js'; import { getBaseTraceParseModelData } from '../../../testing/TraceHelpers.js'; -import * as TraceEngine from '../trace.js'; +import * as Trace from '../trace.js'; import * as RootCauses from './RootCauses.js'; function assertArrayHasNoNulls(inputArray) { inputArray.forEach((item, index) => { @@ -56,7 +56,8 @@ describeWithMockConnection('LayoutShift root causes', () => { beforeEach(() => { fontFaceMock = { fontFamily: 'Roboto', src: fontSource, fontDisplay: 'swap' }; // Layout shifts for which we want to extract potential root causes. - shifts = [{ ts: 10 }, { ts: 30 }, { ts: 50 }, { ts: 70 }, { ts: 90 }]; + shifts = + [{ ts: 10 }, { ts: 30 }, { ts: 50 }, { ts: 70 }, { ts: 90 }]; // Initialize the shifts. for (const shift of shifts) { shift.args = { @@ -66,14 +67,13 @@ describeWithMockConnection('LayoutShift root causes', () => { } const clusters = [{ events: shifts }]; // PrePaint events to which each layout shift belongs. - prePaintEvents = [{ ts: 5, dur: 30 }, { ts: 45, dur: 30 }, { ts: 85, dur: 10 }]; - resizeEvents = [{ ts: 0 }, { ts: 25 }, { ts: 80 }, { ts: 100 }]; - injectedIframeEvents = - [{ ts: 2 }, { ts: 81 }]; - fontChanges = - [{ ts: 3 }, { ts: 35 }]; - unknownLayoutInvalidation = - [{ ts: 4 }, { ts: 36 }]; + prePaintEvents = + [{ ts: 5, dur: 30 }, { ts: 45, dur: 30 }, { ts: 85, dur: 10 }]; + resizeEvents = + [{ ts: 0 }, { ts: 25 }, { ts: 80 }, { ts: 100 }]; + injectedIframeEvents = [{ ts: 2 }, { ts: 81 }]; + fontChanges = [{ ts: 3 }, { ts: 35 }]; + unknownLayoutInvalidation = [{ ts: 4 }, { ts: 36 }]; // |Resize|---|Iframe|---|Fonts-|---|--PrePaint 1--|----|Resize|---|Fonts-|-|---PrePaint 2---|---|Resize|---|Iframe|---|PrePaint 3| // ----------------------------------|LS 1|-|LS 2|----------------------------|LS 3|-|LS 4|-----------------------------|LS 5| // Initialize the LI events by adding a nodeId and setting a reason so that they @@ -82,7 +82,7 @@ describeWithMockConnection('LayoutShift root causes', () => { resizeEvents[i].args = { data: { nodeId: i + 1, - reason: "Size changed" /* TraceEngine.Types.TraceEvents.LayoutInvalidationReason.SIZE_CHANGED */, + reason: "Size changed" /* Trace.Types.Events.LayoutInvalidationReason.SIZE_CHANGED */, nodeName: 'IMG', frame: 'frame-id-123', }, @@ -92,7 +92,7 @@ describeWithMockConnection('LayoutShift root causes', () => { injectedIframeEvents[i].args = { data: { nodeId: i + 11, - reason: "Added to layout" /* TraceEngine.Types.TraceEvents.LayoutInvalidationReason.ADDED_TO_LAYOUT */, + reason: "Added to layout" /* Trace.Types.Events.LayoutInvalidationReason.ADDED_TO_LAYOUT */, nodeName: 'IFRAME', frame: 'frame-id-123', }, @@ -102,7 +102,7 @@ describeWithMockConnection('LayoutShift root causes', () => { fontChanges[i].args = { data: { nodeId: i + 21, - reason: "Fonts changed" /* TraceEngine.Types.TraceEvents.LayoutInvalidationReason.FONTS_CHANGED */, + reason: "Fonts changed" /* Trace.Types.Events.LayoutInvalidationReason.FONTS_CHANGED */, nodeName: 'DIV', frame: 'frame-id-123', }, @@ -112,7 +112,7 @@ describeWithMockConnection('LayoutShift root causes', () => { unknownLayoutInvalidation[i].args = { data: { nodeId: i + 31, - reason: "Unknown" /* TraceEngine.Types.TraceEvents.LayoutInvalidationReason.UNKNOWN */, + reason: "Unknown" /* Trace.Types.Events.LayoutInvalidationReason.UNKNOWN */, nodeName: 'DIV', frame: 'frame-id-123', }, @@ -125,7 +125,7 @@ describeWithMockConnection('LayoutShift root causes', () => { ...unknownLayoutInvalidation, ].sort((a, b) => a.ts - b.ts); for (const e of layoutInvalidationEvents) { - e.name = "LayoutInvalidationTracking" /* TraceEngine.Types.TraceEvents.KnownEventName.LAYOUT_INVALIDATION_TRACKING */; + e.name = "LayoutInvalidationTracking" /* Trace.Types.Events.Name.LAYOUT_INVALIDATION_TRACKING */; } // Map from fake BackendNodeId to fake Protocol.DOM.Node used by the handler to // resolve the nodeIds in the traces. @@ -344,7 +344,8 @@ describeWithMockConnection('LayoutShift root causes', () => { }); it('does not error when there are no layout shifts', async () => { // Layout shifts for which we want to associate LayoutInvalidation events as potential root causes. - shifts = [{ ts: 10 }, { ts: 30 }, { ts: 50 }, { ts: 70 }, { ts: 90 }]; + shifts = + [{ ts: 10 }, { ts: 30 }, { ts: 50 }, { ts: 70 }, { ts: 90 }]; // Initialize the shifts. for (const shift of shifts) { shift.args = { @@ -381,7 +382,7 @@ describeWithMockConnection('LayoutShift root causes', () => { it('ignores events that could not add or resize an iframe', async () => { injectedIframeEvents.forEach(e => { e.args.data.nodeName = 'DIV'; - e.args.data.reason = "Size changed" /* TraceEngine.Types.TraceEvents.LayoutInvalidationReason.SIZE_CHANGED */; + e.args.data.reason = "Size changed" /* Trace.Types.Events.LayoutInvalidationReason.SIZE_CHANGED */; }); const rootCauses = await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift))); assertArrayHasNoNulls(rootCauses); @@ -393,8 +394,8 @@ describeWithMockConnection('LayoutShift root causes', () => { // that correspond to font changes. const fontRequests = [ { - dur: TraceEngine.Types.Timing.MicroSeconds(2), - ts: TraceEngine.Types.Timing.MicroSeconds(0), + dur: Trace.Types.Timing.MicroSeconds(2), + ts: Trace.Types.Timing.MicroSeconds(0), args: { data: { url: fontSource, @@ -403,8 +404,8 @@ describeWithMockConnection('LayoutShift root causes', () => { }, }, { - dur: TraceEngine.Types.Timing.MicroSeconds(30), - ts: TraceEngine.Types.Timing.MicroSeconds(0), + dur: Trace.Types.Timing.MicroSeconds(30), + ts: Trace.Types.Timing.MicroSeconds(0), args: { data: { url: fontSource, @@ -431,8 +432,8 @@ describeWithMockConnection('LayoutShift root causes', () => { }); it('ignores requests for fonts whose font-display property is "optional"', async () => { const optionalFontRequests = [{ - dur: TraceEngine.Types.Timing.MicroSeconds(2), - ts: TraceEngine.Types.Timing.MicroSeconds(0), + dur: Trace.Types.Timing.MicroSeconds(2), + ts: Trace.Types.Timing.MicroSeconds(0), args: { data: { url: fontSource, @@ -455,8 +456,8 @@ describeWithMockConnection('LayoutShift root causes', () => { }); it('ignores requests for fonts that lie outside the fixed time window from ending at the "font change" layout invalidation event', async () => { const optionalFontRequests = [{ - dur: TraceEngine.Types.Timing.MicroSeconds(2), - ts: TraceEngine.Types.Timing.MicroSeconds(85), + dur: Trace.Types.Timing.MicroSeconds(2), + ts: Trace.Types.Timing.MicroSeconds(85), args: { data: { url: fontSource, @@ -481,8 +482,8 @@ describeWithMockConnection('LayoutShift root causes', () => { describe('Render blocking request', () => { const RenderBlockingRequest = [ { - dur: TraceEngine.Types.Timing.MicroSeconds(2), - ts: TraceEngine.Types.Timing.MicroSeconds(0), + dur: Trace.Types.Timing.MicroSeconds(2), + ts: Trace.Types.Timing.MicroSeconds(0), args: { data: { url: renderBlockSource, @@ -492,8 +493,8 @@ describeWithMockConnection('LayoutShift root causes', () => { }, }, { - dur: TraceEngine.Types.Timing.MicroSeconds(30), - ts: TraceEngine.Types.Timing.MicroSeconds(0), + dur: Trace.Types.Timing.MicroSeconds(30), + ts: Trace.Types.Timing.MicroSeconds(0), args: { data: { url: renderBlockSource, diff --git a/public/models/trace/root-causes/LayoutShift.test.js.map b/public/models/trace/root-causes/LayoutShift.test.js.map index eaaee9be1..995447c6a 100644 --- a/public/models/trace/root-causes/LayoutShift.test.js.map +++ b/public/models/trace/root-causes/LayoutShift.test.js.map @@ -1 +1 @@ -{"version":3,"file":"LayoutShift.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/root-causes/LayoutShift.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Protocol from '../../../generated/protocol.js';\nimport {\n describeWithMockConnection,\n} from '../../../testing/MockConnection.js';\nimport {getBaseTraceParseModelData} from '../../../testing/TraceHelpers.js';\nimport * as TraceEngine from '../trace.js';\n\nimport * as RootCauses from './RootCauses.js';\n\ntype TraceParseData = TraceEngine.Handlers.Types.TraceParseData;\ntype TraceParseDataMutable = TraceEngine.Handlers.Types.TraceParseDataMutable;\n\nfunction assertArrayHasNoNulls(inputArray: Array): asserts inputArray is T[] {\n inputArray.forEach((item, index) => {\n if (item === null) {\n assert.fail(`Found null at array index ${index}`);\n }\n });\n}\n\nfunction createMockStyle(cssProperties: {name: string, value: string}[]): Protocol.CSS.CSSStyle {\n return {cssProperties, shorthandEntries: []};\n}\n\nfunction createMockMatchedRules(cssProperties: {name: string, value: string}[]): Protocol.CSS.RuleMatch[] {\n return [{\n rule: {\n style: createMockStyle(cssProperties),\n selectorList: {selectors: [], text: ''},\n origin: Protocol.CSS.StyleSheetOrigin.Regular,\n },\n matchingSelectors: [],\n }];\n}\n\ndescribeWithMockConnection('LayoutShift root causes', () => {\n /*\n * This test has to do a lot of mocking and creating of fake data in order\n * to function. Normally in the perfomance panel tests we prefer to parse a\n * real trace and use that, but in this case because LayoutShift root causes\n * rely on having an actual DevTools instance open with access to the DOM,\n * we can't do that. So therefore we completely mock the set of data\n * required.\n */\n describe('assigns root causes to layout shifts', () => {\n let layoutShifts: RootCauses.LayoutShiftRootCauses;\n let prePaintEvents: TraceEngine.Types.TraceEvents.TraceEventPrePaint[];\n let resizeEvents: TraceEngine.Types.TraceEvents.TraceEventLayoutInvalidationTracking[];\n let injectedIframeEvents: TraceEngine.Types.TraceEvents.TraceEventLayoutInvalidationTracking[];\n let fontChanges: TraceEngine.Types.TraceEvents.TraceEventLayoutInvalidationTracking[];\n let unknownLayoutInvalidation: TraceEngine.Types.TraceEvents.TraceEventLayoutInvalidationTracking[];\n let domNodeByBackendIdMap: Map;\n let model: TraceParseData;\n let modelMut: TraceParseDataMutable;\n let resizeEventsNodeIds: number[];\n let iframesNodeIds: number[];\n let shifts: TraceEngine.Types.TraceEvents.SyntheticLayoutShift[];\n let matchedStylesMock: Omit;\n let protocolInterface: RootCauses.RootCauseProtocolInterface;\n let computedStylesMock: Protocol.CSS.CSSComputedStyleProperty[];\n let fontFaceMock: Protocol.CSS.FontFace;\n const fontSource = 'mock-source.woff';\n const renderBlockSource = 'mock-source.css';\n\n beforeEach(() => {\n fontFaceMock = {fontFamily: 'Roboto', src: fontSource, fontDisplay: 'swap'} as Protocol.CSS.FontFace;\n\n // Layout shifts for which we want to extract potential root causes.\n shifts = [{ts: 10}, {ts: 30}, {ts: 50}, {ts: 70}, {ts: 90}] as unknown as\n TraceEngine.Types.TraceEvents.SyntheticLayoutShift[];\n\n // Initialize the shifts.\n for (const shift of shifts) {\n shift.args = {\n frame: 'frame-id-123',\n };\n shift.name = 'LayoutShift';\n }\n\n const clusters = [{events: shifts}] as unknown as TraceEngine.Types.TraceEvents.SyntheticLayoutShiftCluster[];\n\n // PrePaint events to which each layout shift belongs.\n prePaintEvents = [{ts: 5, dur: 30}, {ts: 45, dur: 30}, {ts: 85, dur: 10}] as unknown as\n TraceEngine.Types.TraceEvents.TraceEventPrePaint[];\n\n resizeEvents = [{ts: 0}, {ts: 25}, {ts: 80}, {ts: 100}] as unknown as\n TraceEngine.Types.TraceEvents.TraceEventLayoutInvalidationTracking[];\n\n injectedIframeEvents =\n [{ts: 2}, {ts: 81}] as unknown as TraceEngine.Types.TraceEvents.TraceEventLayoutInvalidationTracking[];\n\n fontChanges =\n [{ts: 3}, {ts: 35}] as unknown as TraceEngine.Types.TraceEvents.TraceEventLayoutInvalidationTracking[];\n\n unknownLayoutInvalidation =\n [{ts: 4}, {ts: 36}] as unknown as TraceEngine.Types.TraceEvents.TraceEventLayoutInvalidationTracking[];\n\n // |Resize|---|Iframe|---|Fonts-|---|--PrePaint 1--|----|Resize|---|Fonts-|-|---PrePaint 2---|---|Resize|---|Iframe|---|PrePaint 3|\n // ----------------------------------|LS 1|-|LS 2|----------------------------|LS 3|-|LS 4|-----------------------------|LS 5|\n\n // Initialize the LI events by adding a nodeId and setting a reason so that they\n // aren't filtered out.\n for (let i = 0; i < resizeEvents.length; i++) {\n resizeEvents[i].args = {\n data: {\n nodeId: i + 1 as Protocol.DOM.BackendNodeId,\n reason: TraceEngine.Types.TraceEvents.LayoutInvalidationReason.SIZE_CHANGED,\n nodeName: 'IMG',\n frame: 'frame-id-123',\n },\n };\n }\n for (let i = 0; i < injectedIframeEvents.length; i++) {\n injectedIframeEvents[i].args = {\n data: {\n nodeId: i + 11 as Protocol.DOM.BackendNodeId,\n reason: TraceEngine.Types.TraceEvents.LayoutInvalidationReason.ADDED_TO_LAYOUT,\n nodeName: 'IFRAME',\n frame: 'frame-id-123',\n },\n };\n }\n for (let i = 0; i < fontChanges.length; i++) {\n fontChanges[i].args = {\n data: {\n nodeId: i + 21 as Protocol.DOM.BackendNodeId,\n reason: TraceEngine.Types.TraceEvents.LayoutInvalidationReason.FONTS_CHANGED,\n nodeName: 'DIV',\n frame: 'frame-id-123',\n },\n };\n }\n for (let i = 0; i < unknownLayoutInvalidation.length; i++) {\n unknownLayoutInvalidation[i].args = {\n data: {\n nodeId: i + 31 as Protocol.DOM.BackendNodeId,\n reason: TraceEngine.Types.TraceEvents.LayoutInvalidationReason.UNKNOWN,\n nodeName: 'DIV',\n frame: 'frame-id-123',\n },\n };\n }\n const layoutInvalidationEvents = [\n ...resizeEvents,\n ...injectedIframeEvents,\n ...fontChanges,\n ...unknownLayoutInvalidation,\n ].sort((a, b) => a.ts - b.ts);\n\n for (const e of layoutInvalidationEvents) {\n e.name = TraceEngine.Types.TraceEvents.KnownEventName.LAYOUT_INVALIDATION_TRACKING;\n }\n\n // Map from fake BackendNodeId to fake Protocol.DOM.Node used by the handler to\n // resolve the nodeIds in the traces.\n const domNodeByBackendIdMapEntries: [Protocol.DOM.BackendNodeId, Protocol.DOM.Node|null][] = [];\n const domNodeByIdMap = new Map();\n for (let i = 0 as Protocol.DOM.BackendNodeId; i < layoutInvalidationEvents.length; i++) {\n const backendNodeId = layoutInvalidationEvents[i].args.data.nodeId;\n const nodeId = i as unknown as Protocol.DOM.NodeId;\n const nodeName = layoutInvalidationEvents[i].args.data.nodeName || 'DIV';\n const fakeNode = {\n backendNodeId,\n nodeId,\n localName: nodeName.toLowerCase(),\n nodeName,\n attributes: [],\n nodeType: Node.ELEMENT_NODE,\n } as unknown as Protocol.DOM.Node;\n\n domNodeByBackendIdMapEntries.push([backendNodeId, fakeNode]);\n domNodeByIdMap.set(nodeId, fakeNode);\n }\n\n domNodeByBackendIdMap =\n new Map(domNodeByBackendIdMapEntries) as unknown as Map;\n\n model = getBaseTraceParseModelData();\n modelMut = model as unknown as TraceParseDataMutable;\n // Now fake out the relevant LayoutShift data\n modelMut.LayoutShifts.prePaintEvents = prePaintEvents;\n modelMut.LayoutShifts.layoutInvalidationEvents = layoutInvalidationEvents;\n modelMut.LayoutShifts.backendNodeIds = [...domNodeByBackendIdMap.keys()] as Protocol.DOM.BackendNodeId[];\n modelMut.LayoutShifts.clusters = clusters;\n modelMut.LayoutShifts.scheduleStyleInvalidationEvents = [];\n modelMut.Initiators = {\n eventToInitiator: new Map(),\n initiatorToEvents: new Map(),\n };\n\n resizeEventsNodeIds = resizeEvents.map(li => Number(li.args.data.nodeId));\n iframesNodeIds = injectedIframeEvents.map(li => Number(li.args.data.nodeId));\n\n computedStylesMock = [];\n matchedStylesMock = {};\n\n protocolInterface = {\n getInitiatorForRequest(_: string): Protocol.Network.Initiator |\n null {\n return null;\n },\n async pushNodesByBackendIdsToFrontend(backendNodeIds: Protocol.DOM.BackendNodeId[]):\n Promise {\n return backendNodeIds.map(id => {\n const node = domNodeByBackendIdMap.get(id);\n if (!node) {\n throw new Error('unexpected backend id');\n }\n return node.nodeId;\n });\n },\n async getNode(nodeId: Protocol.DOM.NodeId): Promise {\n const node = domNodeByIdMap.get(nodeId);\n if (!node) {\n throw new Error('unexpected id');\n }\n return node;\n },\n async getComputedStyleForNode(_: Protocol.DOM.NodeId): Promise {\n return computedStylesMock;\n },\n async getMatchedStylesForNode(_: Protocol.DOM.NodeId): Promise {\n return {\n ...matchedStylesMock,\n getError: () => undefined,\n };\n },\n fontFaceForSource(url: string): Protocol.CSS.FontFace |\n undefined {\n if (url === fontFaceMock.src) {\n return fontFaceMock;\n }\n return;\n },\n };\n\n layoutShifts = new RootCauses.LayoutShiftRootCauses(protocolInterface, {enableIframeRootCauses: true});\n });\n\n it('uses cached node details', async () => {\n // Use duplicate node ids for invalidation events that use `getNode`\n resizeEvents.forEach(e => {\n e.args.data.nodeId = 1 as Protocol.DOM.BackendNodeId;\n });\n injectedIframeEvents.forEach(e => {\n e.args.data.nodeId = 11 as Protocol.DOM.BackendNodeId;\n });\n\n const getNodeSpy = sinon.spy(protocolInterface, 'getNode');\n\n const rootCauses = await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift)));\n assertArrayHasNoNulls(rootCauses);\n\n assert.strictEqual(getNodeSpy.callCount, 2);\n });\n\n describe('Unsized media', () => {\n it('marks unsized media node in LayoutInvalidation events as a potential root cause to layout shifts correctly',\n async () => {\n const rootCauses = await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift)));\n assertArrayHasNoNulls(rootCauses);\n\n const shiftCausesNodeIds = rootCauses.map(cause => {\n return cause.unsizedMedia.map(media => Number(media.node.backendNodeId));\n });\n\n // Test the nodes from the LI events are assinged as the potential root causes to layout shifts correctly.\n assert.strictEqual(shiftCausesNodeIds[0].length, 1);\n assert.strictEqual(shiftCausesNodeIds[0][0], resizeEventsNodeIds[0]);\n\n assert.strictEqual(shiftCausesNodeIds[1].length, 1);\n assert.strictEqual(shiftCausesNodeIds[1][0], resizeEventsNodeIds[0]);\n\n assert.strictEqual(shiftCausesNodeIds[2].length, 1);\n assert.strictEqual(shiftCausesNodeIds[2][0], resizeEventsNodeIds[1]);\n\n assert.strictEqual(shiftCausesNodeIds[3].length, 1);\n assert.strictEqual(shiftCausesNodeIds[3][0], resizeEventsNodeIds[1]);\n\n assert.strictEqual(shiftCausesNodeIds[4].length, 1);\n assert.strictEqual(shiftCausesNodeIds[4][0], resizeEventsNodeIds[2]);\n });\n\n it('sets partially sized media\\'s authored dimensions properly, using inline styles.', async () => {\n // Set height using inline and matched CSS styles.\n matchedStylesMock = {\n attributesStyle: createMockStyle([]),\n inlineStyle: createMockStyle([{name: 'height', value: '20px'}]),\n matchedCSSRules: createMockMatchedRules([{name: 'height', value: '10px'}]),\n };\n const rootCause = await layoutShifts.rootCausesForEvent(model, shifts[0]);\n\n const authoredDimensions = rootCause?.unsizedMedia[0].authoredDimensions;\n if (!authoredDimensions) {\n assert.fail('Expected defined authored dimensions');\n return;\n }\n // Assert inline styles are preferred.\n assert.strictEqual(authoredDimensions.height, '20px');\n assert.isUndefined(authoredDimensions.width);\n assert.isUndefined(authoredDimensions.aspectRatio);\n });\n\n it('sets partially sized media\\'s authored dimensions properly, using matched CSS rules.', async () => {\n // Set height using matched CSS rules.\n matchedStylesMock = {\n attributesStyle: createMockStyle([{name: 'height', value: '10px'}]),\n inlineStyle: createMockStyle([]),\n matchedCSSRules: createMockMatchedRules([{name: 'height', value: '30px'}]),\n };\n\n const rootCause = await layoutShifts.rootCausesForEvent(model, shifts[1]);\n const authoredDimensions = rootCause?.unsizedMedia[0].authoredDimensions;\n if (!authoredDimensions) {\n assert.fail('Expected defined authored dimensions');\n return;\n }\n // Assert matched CSS rules styles are preferred.\n assert.strictEqual(authoredDimensions.height, '30px');\n });\n\n it('sets partially unsized media\\'s computed dimensions properly.', async () => {\n const height = '10px';\n const width = '20px';\n computedStylesMock = [\n {name: 'height', value: height},\n {name: 'width', value: width},\n ];\n\n const rootCause = await layoutShifts.rootCausesForEvent(model, shifts[1]);\n const computedDimensions = rootCause?.unsizedMedia[0].computedDimensions;\n if (!computedDimensions) {\n assert.fail('Expected defined computed dimensions');\n return;\n }\n // Assert correct computed styles are set.\n assert.strictEqual(computedDimensions.height, height);\n assert.strictEqual(computedDimensions.width, width);\n });\n\n async function assertAmountOfBlamedLayoutInvalidations(amount: number) {\n const allShiftsRootCauses =\n await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift)));\n\n const nodesFromLayoutInvalidations = new Set();\n for (const currentShiftRootCauses of allShiftsRootCauses) {\n if (currentShiftRootCauses === null) {\n continue;\n }\n for (const media of currentShiftRootCauses.unsizedMedia) {\n nodesFromLayoutInvalidations.add(media.node.backendNodeId);\n }\n }\n\n assert.strictEqual(nodesFromLayoutInvalidations.size, amount);\n }\n it('ignores media with inline height and width', async () => {\n matchedStylesMock = {\n attributesStyle: createMockStyle([{name: 'height', value: '10px'}, {name: 'width', value: '10px'}]),\n inlineStyle: createMockStyle([]),\n matchedCSSRules: createMockMatchedRules([]),\n };\n await assertAmountOfBlamedLayoutInvalidations(0);\n });\n it('ignores media with CSS height and width', async () => {\n matchedStylesMock = {\n attributesStyle: createMockStyle([]),\n inlineStyle: createMockStyle([]),\n matchedCSSRules: createMockMatchedRules([{name: 'height', value: '10px'}, {name: 'width', value: '10px'}]),\n };\n await assertAmountOfBlamedLayoutInvalidations(0);\n });\n it('ignores media with height and aspect ratio', async () => {\n matchedStylesMock = {\n attributesStyle: createMockStyle([{name: 'height', value: '10px'}, {name: 'aspect-ratio', value: '1'}]),\n inlineStyle: createMockStyle([]),\n matchedCSSRules: createMockMatchedRules([]),\n };\n await assertAmountOfBlamedLayoutInvalidations(0);\n });\n\n it('ignores media with explicit height and width', async () => {\n matchedStylesMock = {\n attributesStyle: createMockStyle([{name: 'height', value: '10px'}]),\n inlineStyle: createMockStyle([{name: 'width', value: '10px'}]),\n matchedCSSRules: createMockMatchedRules([]),\n };\n await assertAmountOfBlamedLayoutInvalidations(0);\n });\n\n it('ignores media with fixed position as potential root causes of layout shifts', async () => {\n computedStylesMock = [{name: 'position', value: 'fixed'}];\n await assertAmountOfBlamedLayoutInvalidations(0);\n });\n\n it('does not ignore media with only height or width explicitly set as potential root causes of layout shifts',\n async () => {\n matchedStylesMock = {\n attributesStyle: createMockStyle([{name: 'height', value: '10px'}]),\n inlineStyle: createMockStyle([]),\n matchedCSSRules: createMockMatchedRules([]),\n };\n await assertAmountOfBlamedLayoutInvalidations(3);\n });\n\n it('does not error when there are no layout shifts', async () => {\n // Layout shifts for which we want to associate LayoutInvalidation events as potential root causes.\n shifts = [{ts: 10}, {ts: 30}, {ts: 50}, {ts: 70}, {ts: 90}] as unknown as\n TraceEngine.Types.TraceEvents.SyntheticLayoutShift[];\n\n // Initialize the shifts.\n for (const shift of shifts) {\n shift.args = {\n frame: 'frame-id-123',\n };\n shift.name = 'LayoutShift';\n }\n\n const clusters = [{events: shifts}] as unknown as TraceEngine.Types.TraceEvents.SyntheticLayoutShiftCluster[];\n modelMut.LayoutShifts.clusters = clusters;\n\n assert.doesNotThrow(async () => {\n await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift)));\n });\n });\n });\n\n describe('Injected iframes', () => {\n it('marks injected iframes in LayoutInvalidation events as a potential root cause to layout shifts correctly',\n async () => {\n const rootCauses = await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift)));\n assertArrayHasNoNulls(rootCauses);\n const shiftCausesNodeIds = rootCauses.map(cause => {\n return cause.iframes.map(node => Number(node.iframe.backendNodeId));\n });\n\n // Test the nodes from the LI events are assinged as the potential root causes to layout shifts correctly.\n assert.strictEqual(shiftCausesNodeIds[0].length, 1);\n assert.strictEqual(shiftCausesNodeIds[0][0], iframesNodeIds[0]);\n\n assert.strictEqual(shiftCausesNodeIds[4].length, 1);\n assert.strictEqual(shiftCausesNodeIds[4][0], iframesNodeIds[1]);\n });\n\n it('ignores injected iframes if disabled', async () => {\n layoutShifts = new RootCauses.LayoutShiftRootCauses(protocolInterface, {enableIframeRootCauses: false});\n const rootCauses = await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift)));\n assertArrayHasNoNulls(rootCauses);\n assert(rootCauses.every(cause => cause.iframes.length === 0), 'contained iframe root causes');\n });\n\n it('ignores events that could not add or resize an iframe', async () => {\n injectedIframeEvents.forEach(e => {\n e.args.data.nodeName = 'DIV';\n e.args.data.reason = TraceEngine.Types.TraceEvents.LayoutInvalidationReason.SIZE_CHANGED;\n });\n\n const rootCauses = await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift)));\n assertArrayHasNoNulls(rootCauses);\n assert(rootCauses.every(cause => cause.iframes.length === 0), 'contained iframe root causes');\n });\n });\n\n describe('Font changes', () => {\n // Mock two font network request that finished right before the mocked layout invalidation events\n // that correspond to font changes.\n const fontRequests = [\n {\n dur: TraceEngine.Types.Timing.MicroSeconds(2),\n ts: TraceEngine.Types.Timing.MicroSeconds(0),\n args: {\n data: {\n url: fontSource,\n mimeType: 'font/woff2',\n },\n },\n },\n {\n dur: TraceEngine.Types.Timing.MicroSeconds(30),\n ts: TraceEngine.Types.Timing.MicroSeconds(0),\n args: {\n data: {\n url: fontSource,\n mimeType: 'font/woff2',\n },\n },\n },\n ] as unknown as TraceEngine.Types.TraceEvents.SyntheticNetworkRequest[];\n\n it('marks fonts changes in LayoutInvalidation events as a potential root cause to layout shifts correctly',\n async () => {\n modelMut.NetworkRequests.byTime = fontRequests;\n\n const rootCauses = await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift)));\n assertArrayHasNoNulls(rootCauses);\n const shiftCausesNodeIds = rootCauses.map(cause => {\n return cause.fontChanges;\n });\n\n // Test the font requests are marked as potential layout shift root causes\n // in the correct order.\n assert.deepEqual(shiftCausesNodeIds[0][0]?.request, fontRequests[0]);\n assert.deepEqual(shiftCausesNodeIds[1][0]?.request, fontRequests[0]);\n assert.deepEqual(shiftCausesNodeIds[2][0]?.request, fontRequests[1]);\n assert.deepEqual(shiftCausesNodeIds[3][0]?.request, fontRequests[1]);\n assert.deepEqual(shiftCausesNodeIds[2][1]?.request, fontRequests[0]);\n assert.deepEqual(shiftCausesNodeIds[3][1]?.request, fontRequests[0]);\n });\n\n it('ignores requests for fonts whose font-display property is \"optional\"', async () => {\n const optionalFontRequests = [{\n dur: TraceEngine.Types.Timing.MicroSeconds(2),\n ts: TraceEngine.Types.Timing.MicroSeconds(0),\n args: {\n data: {\n url: fontSource,\n mimeType: 'font/woff2',\n },\n },\n }] as unknown as TraceEngine.Types.TraceEvents.SyntheticNetworkRequest[];\n modelMut.NetworkRequests.byTime = optionalFontRequests;\n fontFaceMock = {fontFamily: 'Roboto', src: fontSource, fontDisplay: 'optional'} as Protocol.CSS.FontFace;\n const rootCauses = await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift)));\n assertArrayHasNoNulls(rootCauses);\n const shiftCausesNodeIds = rootCauses.map(cause => {\n return cause.fontChanges;\n });\n\n // Test no font request is marked as potential layout shift root causes\n assert.strictEqual(shiftCausesNodeIds[0].length, 0);\n assert.strictEqual(shiftCausesNodeIds[1].length, 0);\n assert.strictEqual(shiftCausesNodeIds[2].length, 0);\n assert.strictEqual(shiftCausesNodeIds[3].length, 0);\n });\n it('ignores requests for fonts that lie outside the fixed time window from ending at the \"font change\" layout invalidation event',\n async () => {\n const optionalFontRequests = [{\n dur: TraceEngine.Types.Timing.MicroSeconds(2),\n ts: TraceEngine.Types.Timing.MicroSeconds(85),\n args: {\n data: {\n url: fontSource,\n mimeType: 'font/woff2',\n },\n },\n }] as unknown as TraceEngine.Types.TraceEvents.SyntheticNetworkRequest[];\n modelMut.NetworkRequests.byTime = optionalFontRequests;\n fontFaceMock = {fontFamily: 'Roboto', src: fontSource, fontDisplay: 'swap'} as Protocol.CSS.FontFace;\n const rootCauses = await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift)));\n assertArrayHasNoNulls(rootCauses);\n const shiftCausesNodeIds = rootCauses.map(cause => {\n return cause.fontChanges;\n });\n\n // Test no font request is marked as potential layout shift root causes\n assert.strictEqual(shiftCausesNodeIds[0].length, 0);\n assert.strictEqual(shiftCausesNodeIds[1].length, 0);\n assert.strictEqual(shiftCausesNodeIds[2].length, 0);\n assert.strictEqual(shiftCausesNodeIds[3].length, 0);\n });\n });\n\n describe('Render blocking request', () => {\n const RenderBlockingRequest = [\n {\n dur: TraceEngine.Types.Timing.MicroSeconds(2),\n ts: TraceEngine.Types.Timing.MicroSeconds(0),\n args: {\n data: {\n url: renderBlockSource,\n mimeType: 'text/plain',\n renderBlocking: 'blocking',\n },\n },\n },\n {\n dur: TraceEngine.Types.Timing.MicroSeconds(30),\n ts: TraceEngine.Types.Timing.MicroSeconds(0),\n args: {\n data: {\n url: renderBlockSource,\n mimeType: 'text/css',\n renderBlocking: 'non_blocking',\n },\n },\n },\n ] as TraceEngine.Types.TraceEvents.SyntheticNetworkRequest[];\n\n it('marks render blocks in LayoutInvalidation events as a potential root cause to layout shifts correctly',\n async () => {\n modelMut.NetworkRequests.byTime = RenderBlockingRequest;\n\n const rootCauses = await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift)));\n assertArrayHasNoNulls(rootCauses);\n const shiftCausesNodeIds = rootCauses.map(cause => {\n return cause.renderBlockingRequests;\n });\n\n // Test the rendering block requests are marked as potential layout shift root causes\n // in the correct order.\n assert.deepEqual(shiftCausesNodeIds[2][0]?.request, RenderBlockingRequest[0]);\n assert.deepEqual(shiftCausesNodeIds[3][0]?.request, RenderBlockingRequest[0]);\n assert.deepEqual(shiftCausesNodeIds[4][0]?.request, RenderBlockingRequest[0]);\n });\n });\n\n describe('Scripts causing relayout/style recalc', () => {\n it('adds a Layout initiator\\'s stack trace to the corresponding layout shift root causes.', async () => {\n const mockStackTrace = [\n {\n scriptId: 0,\n functionName: 'foo',\n columnNumber: 10,\n lineNumber: 1,\n url: 'Main.js',\n },\n {\n scriptId: 2,\n functionName: 'bar',\n columnNumber: 10,\n lineNumber: 20,\n url: 'Main.js',\n },\n ];\n\n // Mock a Layout event, which corresponds to the last shift.\n // a stack trace.\n modelMut.Renderer.allTraceEntries = [{\n name: 'Layout',\n ts: 82,\n } as unknown as TraceEngine.Types.TraceEvents.TraceEventData];\n\n const node = {\n entry: model.Renderer.allTraceEntries[0],\n } as TraceEngine.Helpers.TreeHelpers.TraceEntryNode;\n model.Renderer.entryToNode.set(model.Renderer.allTraceEntries[0], node);\n // Fake out the initiator detection and link the Layout event with a fake InvalidateLayout event.\n model.Initiators.eventToInitiator.set(model.Renderer.allTraceEntries[0], {\n name: 'InvalidateLayout',\n args: {\n data: {\n stackTrace: mockStackTrace,\n },\n },\n } as TraceEngine.Types.TraceEvents.TraceEventData);\n\n // Verify the Layout initiator's stack trace is added to the last shift.\n const rootCauses = await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift)));\n assertArrayHasNoNulls(rootCauses);\n const rootCauseStackTraces = rootCauses.map(cause => {\n return cause.scriptStackTrace;\n });\n const stackTracesForLastShift = rootCauseStackTraces.at(-1);\n if (!stackTracesForLastShift) {\n assert.fail('No stack traces found for layout shift');\n return;\n }\n assert.strictEqual(stackTracesForLastShift, mockStackTrace);\n });\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"LayoutShift.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/root-causes/LayoutShift.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Protocol from '../../../generated/protocol.js';\nimport {\n describeWithMockConnection,\n} from '../../../testing/MockConnection.js';\nimport {getBaseTraceParseModelData} from '../../../testing/TraceHelpers.js';\nimport * as Trace from '../trace.js';\n\nimport * as RootCauses from './RootCauses.js';\n\ntype ParsedTrace = Trace.Handlers.Types.ParsedTrace;\ntype ParsedTraceMutable = Trace.Handlers.Types.ParsedTraceMutable;\n\nfunction assertArrayHasNoNulls(inputArray: Array): asserts inputArray is T[] {\n inputArray.forEach((item, index) => {\n if (item === null) {\n assert.fail(`Found null at array index ${index}`);\n }\n });\n}\n\nfunction createMockStyle(cssProperties: {name: string, value: string}[]): Protocol.CSS.CSSStyle {\n return {cssProperties, shorthandEntries: []};\n}\n\nfunction createMockMatchedRules(cssProperties: {name: string, value: string}[]): Protocol.CSS.RuleMatch[] {\n return [{\n rule: {\n style: createMockStyle(cssProperties),\n selectorList: {selectors: [], text: ''},\n origin: Protocol.CSS.StyleSheetOrigin.Regular,\n },\n matchingSelectors: [],\n }];\n}\n\ndescribeWithMockConnection('LayoutShift root causes', () => {\n /*\n * This test has to do a lot of mocking and creating of fake data in order\n * to function. Normally in the perfomance panel tests we prefer to parse a\n * real trace and use that, but in this case because LayoutShift root causes\n * rely on having an actual DevTools instance open with access to the DOM,\n * we can't do that. So therefore we completely mock the set of data\n * required.\n */\n describe('assigns root causes to layout shifts', () => {\n let layoutShifts: RootCauses.LayoutShiftRootCauses;\n let prePaintEvents: Trace.Types.Events.PrePaint[];\n let resizeEvents: Trace.Types.Events.LayoutInvalidationTracking[];\n let injectedIframeEvents: Trace.Types.Events.LayoutInvalidationTracking[];\n let fontChanges: Trace.Types.Events.LayoutInvalidationTracking[];\n let unknownLayoutInvalidation: Trace.Types.Events.LayoutInvalidationTracking[];\n let domNodeByBackendIdMap: Map;\n let model: ParsedTrace;\n let modelMut: ParsedTraceMutable;\n let resizeEventsNodeIds: number[];\n let iframesNodeIds: number[];\n let shifts: Trace.Types.Events.SyntheticLayoutShift[];\n let matchedStylesMock: Omit;\n let protocolInterface: RootCauses.RootCauseProtocolInterface;\n let computedStylesMock: Protocol.CSS.CSSComputedStyleProperty[];\n let fontFaceMock: Protocol.CSS.FontFace;\n const fontSource = 'mock-source.woff';\n const renderBlockSource = 'mock-source.css';\n\n beforeEach(() => {\n fontFaceMock = {fontFamily: 'Roboto', src: fontSource, fontDisplay: 'swap'} as Protocol.CSS.FontFace;\n\n // Layout shifts for which we want to extract potential root causes.\n shifts =\n [{ts: 10}, {ts: 30}, {ts: 50}, {ts: 70}, {ts: 90}] as unknown as Trace.Types.Events.SyntheticLayoutShift[];\n\n // Initialize the shifts.\n for (const shift of shifts) {\n shift.args = {\n frame: 'frame-id-123',\n };\n shift.name = 'LayoutShift';\n }\n\n const clusters = [{events: shifts}] as unknown as Trace.Types.Events.SyntheticLayoutShiftCluster[];\n\n // PrePaint events to which each layout shift belongs.\n prePaintEvents =\n [{ts: 5, dur: 30}, {ts: 45, dur: 30}, {ts: 85, dur: 10}] as unknown as Trace.Types.Events.PrePaint[];\n\n resizeEvents =\n [{ts: 0}, {ts: 25}, {ts: 80}, {ts: 100}] as unknown as Trace.Types.Events.LayoutInvalidationTracking[];\n\n injectedIframeEvents = [{ts: 2}, {ts: 81}] as unknown as Trace.Types.Events.LayoutInvalidationTracking[];\n\n fontChanges = [{ts: 3}, {ts: 35}] as unknown as Trace.Types.Events.LayoutInvalidationTracking[];\n\n unknownLayoutInvalidation = [{ts: 4}, {ts: 36}] as unknown as Trace.Types.Events.LayoutInvalidationTracking[];\n\n // |Resize|---|Iframe|---|Fonts-|---|--PrePaint 1--|----|Resize|---|Fonts-|-|---PrePaint 2---|---|Resize|---|Iframe|---|PrePaint 3|\n // ----------------------------------|LS 1|-|LS 2|----------------------------|LS 3|-|LS 4|-----------------------------|LS 5|\n\n // Initialize the LI events by adding a nodeId and setting a reason so that they\n // aren't filtered out.\n for (let i = 0; i < resizeEvents.length; i++) {\n resizeEvents[i].args = {\n data: {\n nodeId: i + 1 as Protocol.DOM.BackendNodeId,\n reason: Trace.Types.Events.LayoutInvalidationReason.SIZE_CHANGED,\n nodeName: 'IMG',\n frame: 'frame-id-123',\n },\n };\n }\n for (let i = 0; i < injectedIframeEvents.length; i++) {\n injectedIframeEvents[i].args = {\n data: {\n nodeId: i + 11 as Protocol.DOM.BackendNodeId,\n reason: Trace.Types.Events.LayoutInvalidationReason.ADDED_TO_LAYOUT,\n nodeName: 'IFRAME',\n frame: 'frame-id-123',\n },\n };\n }\n for (let i = 0; i < fontChanges.length; i++) {\n fontChanges[i].args = {\n data: {\n nodeId: i + 21 as Protocol.DOM.BackendNodeId,\n reason: Trace.Types.Events.LayoutInvalidationReason.FONTS_CHANGED,\n nodeName: 'DIV',\n frame: 'frame-id-123',\n },\n };\n }\n for (let i = 0; i < unknownLayoutInvalidation.length; i++) {\n unknownLayoutInvalidation[i].args = {\n data: {\n nodeId: i + 31 as Protocol.DOM.BackendNodeId,\n reason: Trace.Types.Events.LayoutInvalidationReason.UNKNOWN,\n nodeName: 'DIV',\n frame: 'frame-id-123',\n },\n };\n }\n const layoutInvalidationEvents = [\n ...resizeEvents,\n ...injectedIframeEvents,\n ...fontChanges,\n ...unknownLayoutInvalidation,\n ].sort((a, b) => a.ts - b.ts);\n\n for (const e of layoutInvalidationEvents) {\n e.name = Trace.Types.Events.Name.LAYOUT_INVALIDATION_TRACKING;\n }\n\n // Map from fake BackendNodeId to fake Protocol.DOM.Node used by the handler to\n // resolve the nodeIds in the traces.\n const domNodeByBackendIdMapEntries: [Protocol.DOM.BackendNodeId, Protocol.DOM.Node|null][] = [];\n const domNodeByIdMap = new Map();\n for (let i = 0 as Protocol.DOM.BackendNodeId; i < layoutInvalidationEvents.length; i++) {\n const backendNodeId = layoutInvalidationEvents[i].args.data.nodeId;\n const nodeId = i as unknown as Protocol.DOM.NodeId;\n const nodeName = layoutInvalidationEvents[i].args.data.nodeName || 'DIV';\n const fakeNode = {\n backendNodeId,\n nodeId,\n localName: nodeName.toLowerCase(),\n nodeName,\n attributes: [],\n nodeType: Node.ELEMENT_NODE,\n } as unknown as Protocol.DOM.Node;\n\n domNodeByBackendIdMapEntries.push([backendNodeId, fakeNode]);\n domNodeByIdMap.set(nodeId, fakeNode);\n }\n\n domNodeByBackendIdMap =\n new Map(domNodeByBackendIdMapEntries) as unknown as Map;\n\n model = getBaseTraceParseModelData();\n modelMut = model as unknown as ParsedTraceMutable;\n // Now fake out the relevant LayoutShift data\n modelMut.LayoutShifts.prePaintEvents = prePaintEvents;\n modelMut.LayoutShifts.layoutInvalidationEvents = layoutInvalidationEvents;\n modelMut.LayoutShifts.backendNodeIds = [...domNodeByBackendIdMap.keys()] as Protocol.DOM.BackendNodeId[];\n modelMut.LayoutShifts.clusters = clusters;\n modelMut.LayoutShifts.scheduleStyleInvalidationEvents = [];\n modelMut.Initiators = {\n eventToInitiator: new Map(),\n initiatorToEvents: new Map(),\n };\n\n resizeEventsNodeIds = resizeEvents.map(li => Number(li.args.data.nodeId));\n iframesNodeIds = injectedIframeEvents.map(li => Number(li.args.data.nodeId));\n\n computedStylesMock = [];\n matchedStylesMock = {};\n\n protocolInterface = {\n getInitiatorForRequest(_: string): Protocol.Network.Initiator |\n null {\n return null;\n },\n async pushNodesByBackendIdsToFrontend(backendNodeIds: Protocol.DOM.BackendNodeId[]):\n Promise {\n return backendNodeIds.map(id => {\n const node = domNodeByBackendIdMap.get(id);\n if (!node) {\n throw new Error('unexpected backend id');\n }\n return node.nodeId;\n });\n },\n async getNode(nodeId: Protocol.DOM.NodeId): Promise {\n const node = domNodeByIdMap.get(nodeId);\n if (!node) {\n throw new Error('unexpected id');\n }\n return node;\n },\n async getComputedStyleForNode(_: Protocol.DOM.NodeId): Promise {\n return computedStylesMock;\n },\n async getMatchedStylesForNode(_: Protocol.DOM.NodeId): Promise {\n return {\n ...matchedStylesMock,\n getError: () => undefined,\n };\n },\n fontFaceForSource(url: string): Protocol.CSS.FontFace |\n undefined {\n if (url === fontFaceMock.src) {\n return fontFaceMock;\n }\n return;\n },\n };\n\n layoutShifts = new RootCauses.LayoutShiftRootCauses(protocolInterface, {enableIframeRootCauses: true});\n });\n\n it('uses cached node details', async () => {\n // Use duplicate node ids for invalidation events that use `getNode`\n resizeEvents.forEach(e => {\n e.args.data.nodeId = 1 as Protocol.DOM.BackendNodeId;\n });\n injectedIframeEvents.forEach(e => {\n e.args.data.nodeId = 11 as Protocol.DOM.BackendNodeId;\n });\n\n const getNodeSpy = sinon.spy(protocolInterface, 'getNode');\n\n const rootCauses = await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift)));\n assertArrayHasNoNulls(rootCauses);\n\n assert.strictEqual(getNodeSpy.callCount, 2);\n });\n\n describe('Unsized media', () => {\n it('marks unsized media node in LayoutInvalidation events as a potential root cause to layout shifts correctly',\n async () => {\n const rootCauses = await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift)));\n assertArrayHasNoNulls(rootCauses);\n\n const shiftCausesNodeIds = rootCauses.map(cause => {\n return cause.unsizedMedia.map(media => Number(media.node.backendNodeId));\n });\n\n // Test the nodes from the LI events are assinged as the potential root causes to layout shifts correctly.\n assert.strictEqual(shiftCausesNodeIds[0].length, 1);\n assert.strictEqual(shiftCausesNodeIds[0][0], resizeEventsNodeIds[0]);\n\n assert.strictEqual(shiftCausesNodeIds[1].length, 1);\n assert.strictEqual(shiftCausesNodeIds[1][0], resizeEventsNodeIds[0]);\n\n assert.strictEqual(shiftCausesNodeIds[2].length, 1);\n assert.strictEqual(shiftCausesNodeIds[2][0], resizeEventsNodeIds[1]);\n\n assert.strictEqual(shiftCausesNodeIds[3].length, 1);\n assert.strictEqual(shiftCausesNodeIds[3][0], resizeEventsNodeIds[1]);\n\n assert.strictEqual(shiftCausesNodeIds[4].length, 1);\n assert.strictEqual(shiftCausesNodeIds[4][0], resizeEventsNodeIds[2]);\n });\n\n it('sets partially sized media\\'s authored dimensions properly, using inline styles.', async () => {\n // Set height using inline and matched CSS styles.\n matchedStylesMock = {\n attributesStyle: createMockStyle([]),\n inlineStyle: createMockStyle([{name: 'height', value: '20px'}]),\n matchedCSSRules: createMockMatchedRules([{name: 'height', value: '10px'}]),\n };\n const rootCause = await layoutShifts.rootCausesForEvent(model, shifts[0]);\n\n const authoredDimensions = rootCause?.unsizedMedia[0].authoredDimensions;\n if (!authoredDimensions) {\n assert.fail('Expected defined authored dimensions');\n return;\n }\n // Assert inline styles are preferred.\n assert.strictEqual(authoredDimensions.height, '20px');\n assert.isUndefined(authoredDimensions.width);\n assert.isUndefined(authoredDimensions.aspectRatio);\n });\n\n it('sets partially sized media\\'s authored dimensions properly, using matched CSS rules.', async () => {\n // Set height using matched CSS rules.\n matchedStylesMock = {\n attributesStyle: createMockStyle([{name: 'height', value: '10px'}]),\n inlineStyle: createMockStyle([]),\n matchedCSSRules: createMockMatchedRules([{name: 'height', value: '30px'}]),\n };\n\n const rootCause = await layoutShifts.rootCausesForEvent(model, shifts[1]);\n const authoredDimensions = rootCause?.unsizedMedia[0].authoredDimensions;\n if (!authoredDimensions) {\n assert.fail('Expected defined authored dimensions');\n return;\n }\n // Assert matched CSS rules styles are preferred.\n assert.strictEqual(authoredDimensions.height, '30px');\n });\n\n it('sets partially unsized media\\'s computed dimensions properly.', async () => {\n const height = '10px';\n const width = '20px';\n computedStylesMock = [\n {name: 'height', value: height},\n {name: 'width', value: width},\n ];\n\n const rootCause = await layoutShifts.rootCausesForEvent(model, shifts[1]);\n const computedDimensions = rootCause?.unsizedMedia[0].computedDimensions;\n if (!computedDimensions) {\n assert.fail('Expected defined computed dimensions');\n return;\n }\n // Assert correct computed styles are set.\n assert.strictEqual(computedDimensions.height, height);\n assert.strictEqual(computedDimensions.width, width);\n });\n\n async function assertAmountOfBlamedLayoutInvalidations(amount: number) {\n const allShiftsRootCauses =\n await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift)));\n\n const nodesFromLayoutInvalidations = new Set();\n for (const currentShiftRootCauses of allShiftsRootCauses) {\n if (currentShiftRootCauses === null) {\n continue;\n }\n for (const media of currentShiftRootCauses.unsizedMedia) {\n nodesFromLayoutInvalidations.add(media.node.backendNodeId);\n }\n }\n\n assert.strictEqual(nodesFromLayoutInvalidations.size, amount);\n }\n it('ignores media with inline height and width', async () => {\n matchedStylesMock = {\n attributesStyle: createMockStyle([{name: 'height', value: '10px'}, {name: 'width', value: '10px'}]),\n inlineStyle: createMockStyle([]),\n matchedCSSRules: createMockMatchedRules([]),\n };\n await assertAmountOfBlamedLayoutInvalidations(0);\n });\n it('ignores media with CSS height and width', async () => {\n matchedStylesMock = {\n attributesStyle: createMockStyle([]),\n inlineStyle: createMockStyle([]),\n matchedCSSRules: createMockMatchedRules([{name: 'height', value: '10px'}, {name: 'width', value: '10px'}]),\n };\n await assertAmountOfBlamedLayoutInvalidations(0);\n });\n it('ignores media with height and aspect ratio', async () => {\n matchedStylesMock = {\n attributesStyle: createMockStyle([{name: 'height', value: '10px'}, {name: 'aspect-ratio', value: '1'}]),\n inlineStyle: createMockStyle([]),\n matchedCSSRules: createMockMatchedRules([]),\n };\n await assertAmountOfBlamedLayoutInvalidations(0);\n });\n\n it('ignores media with explicit height and width', async () => {\n matchedStylesMock = {\n attributesStyle: createMockStyle([{name: 'height', value: '10px'}]),\n inlineStyle: createMockStyle([{name: 'width', value: '10px'}]),\n matchedCSSRules: createMockMatchedRules([]),\n };\n await assertAmountOfBlamedLayoutInvalidations(0);\n });\n\n it('ignores media with fixed position as potential root causes of layout shifts', async () => {\n computedStylesMock = [{name: 'position', value: 'fixed'}];\n await assertAmountOfBlamedLayoutInvalidations(0);\n });\n\n it('does not ignore media with only height or width explicitly set as potential root causes of layout shifts',\n async () => {\n matchedStylesMock = {\n attributesStyle: createMockStyle([{name: 'height', value: '10px'}]),\n inlineStyle: createMockStyle([]),\n matchedCSSRules: createMockMatchedRules([]),\n };\n await assertAmountOfBlamedLayoutInvalidations(3);\n });\n\n it('does not error when there are no layout shifts', async () => {\n // Layout shifts for which we want to associate LayoutInvalidation events as potential root causes.\n shifts =\n [{ts: 10}, {ts: 30}, {ts: 50}, {ts: 70}, {ts: 90}] as unknown as Trace.Types.Events.SyntheticLayoutShift[];\n\n // Initialize the shifts.\n for (const shift of shifts) {\n shift.args = {\n frame: 'frame-id-123',\n };\n shift.name = 'LayoutShift';\n }\n\n const clusters = [{events: shifts}] as unknown as Trace.Types.Events.SyntheticLayoutShiftCluster[];\n modelMut.LayoutShifts.clusters = clusters;\n\n assert.doesNotThrow(async () => {\n await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift)));\n });\n });\n });\n\n describe('Injected iframes', () => {\n it('marks injected iframes in LayoutInvalidation events as a potential root cause to layout shifts correctly',\n async () => {\n const rootCauses = await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift)));\n assertArrayHasNoNulls(rootCauses);\n const shiftCausesNodeIds = rootCauses.map(cause => {\n return cause.iframes.map(node => Number(node.iframe.backendNodeId));\n });\n\n // Test the nodes from the LI events are assinged as the potential root causes to layout shifts correctly.\n assert.strictEqual(shiftCausesNodeIds[0].length, 1);\n assert.strictEqual(shiftCausesNodeIds[0][0], iframesNodeIds[0]);\n\n assert.strictEqual(shiftCausesNodeIds[4].length, 1);\n assert.strictEqual(shiftCausesNodeIds[4][0], iframesNodeIds[1]);\n });\n\n it('ignores injected iframes if disabled', async () => {\n layoutShifts = new RootCauses.LayoutShiftRootCauses(protocolInterface, {enableIframeRootCauses: false});\n const rootCauses = await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift)));\n assertArrayHasNoNulls(rootCauses);\n assert(rootCauses.every(cause => cause.iframes.length === 0), 'contained iframe root causes');\n });\n\n it('ignores events that could not add or resize an iframe', async () => {\n injectedIframeEvents.forEach(e => {\n e.args.data.nodeName = 'DIV';\n e.args.data.reason = Trace.Types.Events.LayoutInvalidationReason.SIZE_CHANGED;\n });\n\n const rootCauses = await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift)));\n assertArrayHasNoNulls(rootCauses);\n assert(rootCauses.every(cause => cause.iframes.length === 0), 'contained iframe root causes');\n });\n });\n\n describe('Font changes', () => {\n // Mock two font network request that finished right before the mocked layout invalidation events\n // that correspond to font changes.\n const fontRequests = [\n {\n dur: Trace.Types.Timing.MicroSeconds(2),\n ts: Trace.Types.Timing.MicroSeconds(0),\n args: {\n data: {\n url: fontSource,\n mimeType: 'font/woff2',\n },\n },\n },\n {\n dur: Trace.Types.Timing.MicroSeconds(30),\n ts: Trace.Types.Timing.MicroSeconds(0),\n args: {\n data: {\n url: fontSource,\n mimeType: 'font/woff2',\n },\n },\n },\n ] as unknown as Trace.Types.Events.SyntheticNetworkRequest[];\n\n it('marks fonts changes in LayoutInvalidation events as a potential root cause to layout shifts correctly',\n async () => {\n modelMut.NetworkRequests.byTime = fontRequests;\n\n const rootCauses = await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift)));\n assertArrayHasNoNulls(rootCauses);\n const shiftCausesNodeIds = rootCauses.map(cause => {\n return cause.fontChanges;\n });\n\n // Test the font requests are marked as potential layout shift root causes\n // in the correct order.\n assert.deepEqual(shiftCausesNodeIds[0][0]?.request, fontRequests[0]);\n assert.deepEqual(shiftCausesNodeIds[1][0]?.request, fontRequests[0]);\n assert.deepEqual(shiftCausesNodeIds[2][0]?.request, fontRequests[1]);\n assert.deepEqual(shiftCausesNodeIds[3][0]?.request, fontRequests[1]);\n assert.deepEqual(shiftCausesNodeIds[2][1]?.request, fontRequests[0]);\n assert.deepEqual(shiftCausesNodeIds[3][1]?.request, fontRequests[0]);\n });\n\n it('ignores requests for fonts whose font-display property is \"optional\"', async () => {\n const optionalFontRequests = [{\n dur: Trace.Types.Timing.MicroSeconds(2),\n ts: Trace.Types.Timing.MicroSeconds(0),\n args: {\n data: {\n url: fontSource,\n mimeType: 'font/woff2',\n },\n },\n }] as unknown as Trace.Types.Events.SyntheticNetworkRequest[];\n modelMut.NetworkRequests.byTime = optionalFontRequests;\n fontFaceMock = {fontFamily: 'Roboto', src: fontSource, fontDisplay: 'optional'} as Protocol.CSS.FontFace;\n const rootCauses = await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift)));\n assertArrayHasNoNulls(rootCauses);\n const shiftCausesNodeIds = rootCauses.map(cause => {\n return cause.fontChanges;\n });\n\n // Test no font request is marked as potential layout shift root causes\n assert.strictEqual(shiftCausesNodeIds[0].length, 0);\n assert.strictEqual(shiftCausesNodeIds[1].length, 0);\n assert.strictEqual(shiftCausesNodeIds[2].length, 0);\n assert.strictEqual(shiftCausesNodeIds[3].length, 0);\n });\n it('ignores requests for fonts that lie outside the fixed time window from ending at the \"font change\" layout invalidation event',\n async () => {\n const optionalFontRequests = [{\n dur: Trace.Types.Timing.MicroSeconds(2),\n ts: Trace.Types.Timing.MicroSeconds(85),\n args: {\n data: {\n url: fontSource,\n mimeType: 'font/woff2',\n },\n },\n }] as unknown as Trace.Types.Events.SyntheticNetworkRequest[];\n modelMut.NetworkRequests.byTime = optionalFontRequests;\n fontFaceMock = {fontFamily: 'Roboto', src: fontSource, fontDisplay: 'swap'} as Protocol.CSS.FontFace;\n const rootCauses = await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift)));\n assertArrayHasNoNulls(rootCauses);\n const shiftCausesNodeIds = rootCauses.map(cause => {\n return cause.fontChanges;\n });\n\n // Test no font request is marked as potential layout shift root causes\n assert.strictEqual(shiftCausesNodeIds[0].length, 0);\n assert.strictEqual(shiftCausesNodeIds[1].length, 0);\n assert.strictEqual(shiftCausesNodeIds[2].length, 0);\n assert.strictEqual(shiftCausesNodeIds[3].length, 0);\n });\n });\n\n describe('Render blocking request', () => {\n const RenderBlockingRequest = [\n {\n dur: Trace.Types.Timing.MicroSeconds(2),\n ts: Trace.Types.Timing.MicroSeconds(0),\n args: {\n data: {\n url: renderBlockSource,\n mimeType: 'text/plain',\n renderBlocking: 'blocking',\n },\n },\n },\n {\n dur: Trace.Types.Timing.MicroSeconds(30),\n ts: Trace.Types.Timing.MicroSeconds(0),\n args: {\n data: {\n url: renderBlockSource,\n mimeType: 'text/css',\n renderBlocking: 'non_blocking',\n },\n },\n },\n ] as Trace.Types.Events.SyntheticNetworkRequest[];\n\n it('marks render blocks in LayoutInvalidation events as a potential root cause to layout shifts correctly',\n async () => {\n modelMut.NetworkRequests.byTime = RenderBlockingRequest;\n\n const rootCauses = await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift)));\n assertArrayHasNoNulls(rootCauses);\n const shiftCausesNodeIds = rootCauses.map(cause => {\n return cause.renderBlockingRequests;\n });\n\n // Test the rendering block requests are marked as potential layout shift root causes\n // in the correct order.\n assert.deepEqual(shiftCausesNodeIds[2][0]?.request, RenderBlockingRequest[0]);\n assert.deepEqual(shiftCausesNodeIds[3][0]?.request, RenderBlockingRequest[0]);\n assert.deepEqual(shiftCausesNodeIds[4][0]?.request, RenderBlockingRequest[0]);\n });\n });\n\n describe('Scripts causing relayout/style recalc', () => {\n it('adds a Layout initiator\\'s stack trace to the corresponding layout shift root causes.', async () => {\n const mockStackTrace = [\n {\n scriptId: 0,\n functionName: 'foo',\n columnNumber: 10,\n lineNumber: 1,\n url: 'Main.js',\n },\n {\n scriptId: 2,\n functionName: 'bar',\n columnNumber: 10,\n lineNumber: 20,\n url: 'Main.js',\n },\n ];\n\n // Mock a Layout event, which corresponds to the last shift.\n // a stack trace.\n modelMut.Renderer.allTraceEntries = [{\n name: 'Layout',\n ts: 82,\n } as unknown as Trace.Types.Events.Event];\n\n const node = {\n entry: model.Renderer.allTraceEntries[0],\n } as Trace.Helpers.TreeHelpers.TraceEntryNode;\n model.Renderer.entryToNode.set(model.Renderer.allTraceEntries[0], node);\n // Fake out the initiator detection and link the Layout event with a fake InvalidateLayout event.\n model.Initiators.eventToInitiator.set(model.Renderer.allTraceEntries[0], {\n name: 'InvalidateLayout',\n args: {\n data: {\n stackTrace: mockStackTrace,\n },\n },\n } as Trace.Types.Events.Event);\n\n // Verify the Layout initiator's stack trace is added to the last shift.\n const rootCauses = await Promise.all(shifts.map(shift => layoutShifts.rootCausesForEvent(model, shift)));\n assertArrayHasNoNulls(rootCauses);\n const rootCauseStackTraces = rootCauses.map(cause => {\n return cause.scriptStackTrace;\n });\n const stackTracesForLastShift = rootCauseStackTraces.at(-1);\n if (!stackTracesForLastShift) {\n assert.fail('No stack traces found for layout shift');\n return;\n }\n assert.strictEqual(stackTracesForLastShift, mockStackTrace);\n });\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/types/Extensions.d.ts b/public/models/trace/types/Extensions.d.ts index 76e0bfb78..abaa6a174 100644 --- a/public/models/trace/types/Extensions.d.ts +++ b/public/models/trace/types/Extensions.d.ts @@ -1,4 +1,4 @@ -import { type Phase, type SyntheticBasedEvent, type TraceEventArgs, type TraceEventData } from './TraceEvents.js'; +import { type Args, type Event, type Phase, type SyntheticBased } from './TraceEvents.js'; export type ExtensionEntryType = 'track-entry' | 'marker'; declare const extensionPalette: readonly ["primary", "primary-light", "primary-dark", "secondary", "secondary-light", "secondary-dark", "tertiary", "tertiary-light", "tertiary-dark", "error"]; export type ExtensionColorFromPalette = typeof extensionPalette[number]; @@ -20,14 +20,14 @@ export interface ExtensionMarkerPayload extends ExtensionDataPayloadBase { /** * Synthetic events created for extension tracks. */ -export interface SyntheticExtensionTrackEntry extends SyntheticBasedEvent { - args: TraceEventArgs & ExtensionTrackEntryPayload; +export interface SyntheticExtensionTrackEntry extends SyntheticBased { + args: Args & ExtensionTrackEntryPayload; } /** * Synthetic events created for extension marks. */ -export interface SyntheticExtensionMarker extends SyntheticBasedEvent { - args: TraceEventArgs & ExtensionMarkerPayload; +export interface SyntheticExtensionMarker extends SyntheticBased { + args: Args & ExtensionMarkerPayload; } export type SyntheticExtensionEntry = SyntheticExtensionTrackEntry | SyntheticExtensionMarker; export declare function isExtensionPayloadMarker(payload: { @@ -41,7 +41,7 @@ export declare function isValidExtensionPayload(payload: { track?: string; dataType?: string; }): payload is ExtensionDataPayload; -export declare function isSyntheticExtensionEntry(entry: TraceEventData): entry is SyntheticExtensionEntry; +export declare function isSyntheticExtensionEntry(entry: Event): entry is SyntheticExtensionEntry; export interface ExtensionTrackData { name: string; isTrackGroup: boolean; diff --git a/public/models/trace/types/Extensions.js.map b/public/models/trace/types/Extensions.js.map index 897dee1d1..0b1461aa9 100644 --- a/public/models/trace/types/Extensions.js.map +++ b/public/models/trace/types/Extensions.js.map @@ -1 +1 @@ -{"version":3,"file":"Extensions.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/types/Extensions.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAW7B,MAAM,gBAAgB,GAAG;IACvB,SAAS;IACT,eAAe;IACf,cAAc;IACd,WAAW;IACX,iBAAiB;IACjB,gBAAgB;IAChB,UAAU;IACV,gBAAgB;IAChB,eAAe;IACf,OAAO;CACC,CAAC;AAIX,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,OAAQ,gBAAsC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACjE,CAAC;AA8CD,MAAM,UAAU,wBAAwB,CAAC,OAA4B;IACnE,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,OAA4C;IAEvF,MAAM,QAAQ,GAAG,OAAO,IAAI,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9D,MAAM,cAAc,GAAG,OAAO,CAAC,QAAQ,KAAK,aAAa,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC;IAC5F,OAAO,cAAc,IAAI,QAAQ,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAA4C;IAClF,OAAO,wBAAwB,CAAC,OAAO,CAAC,IAAI,4BAA4B,CAAC,OAAO,CAAC,CAAC;AACpF,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,KAAqB;IAC7D,OAAO,KAAK,CAAC,GAAG,KAAK,oBAAoB,CAAC;AAC5C,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {\n type Phase,\n type SyntheticBasedEvent,\n type TraceEventArgs,\n type TraceEventData,\n} from './TraceEvents.js';\n\nexport type ExtensionEntryType = 'track-entry'|'marker';\n\nconst extensionPalette = [\n 'primary',\n 'primary-light',\n 'primary-dark',\n 'secondary',\n 'secondary-light',\n 'secondary-dark',\n 'tertiary',\n 'tertiary-light',\n 'tertiary-dark',\n 'error',\n] as const;\n\nexport type ExtensionColorFromPalette = typeof extensionPalette[number];\n\nexport function colorIsValid(color: string): boolean {\n return (extensionPalette as readonly string[]).includes(color);\n}\n\nexport interface ExtensionDataPayloadBase {\n color?: ExtensionColorFromPalette;\n properties?: [string, string][];\n tooltipText?: string;\n}\n\nexport type ExtensionDataPayload = ExtensionTrackEntryPayload|ExtensionMarkerPayload;\n\nexport interface ExtensionTrackEntryPayload extends ExtensionDataPayloadBase {\n // Typed as possibly undefined since when no data type is provided\n // the entry is defaulted to a track entry\n dataType?: 'track-entry';\n // The name of the track the entry will be displayed in.\n // Entries intended to be displayed in the same track must contain the\n // same value in this property.\n // If undefined, measurement is added to the Timings track\n track: string;\n // The track group an entry’s track belongs to.\n // Entries intended to be displayed in the same track must contain the\n // same value in this property as well as the same value in the track\n // property.\n trackGroup?: string;\n}\n\nexport interface ExtensionMarkerPayload extends ExtensionDataPayloadBase {\n dataType: 'marker';\n}\n\n/**\n * Synthetic events created for extension tracks.\n */\nexport interface SyntheticExtensionTrackEntry extends SyntheticBasedEvent {\n args: TraceEventArgs&ExtensionTrackEntryPayload;\n}\n\n/**\n * Synthetic events created for extension marks.\n */\nexport interface SyntheticExtensionMarker extends SyntheticBasedEvent {\n args: TraceEventArgs&ExtensionMarkerPayload;\n}\n\nexport type SyntheticExtensionEntry = SyntheticExtensionTrackEntry|SyntheticExtensionMarker;\n\nexport function isExtensionPayloadMarker(payload: {dataType?: string}): payload is ExtensionMarkerPayload {\n return payload.dataType === 'marker';\n}\n\nexport function isExtensionPayloadTrackEntry(payload: {track?: string, dataType?: string}):\n payload is ExtensionTrackEntryPayload {\n const hasTrack = 'track' in payload && Boolean(payload.track);\n const validEntryType = payload.dataType === 'track-entry' || payload.dataType === undefined;\n return validEntryType && hasTrack;\n}\n\nexport function isValidExtensionPayload(payload: {track?: string, dataType?: string}): payload is ExtensionDataPayload {\n return isExtensionPayloadMarker(payload) || isExtensionPayloadTrackEntry(payload);\n}\n\nexport function isSyntheticExtensionEntry(entry: TraceEventData): entry is SyntheticExtensionEntry {\n return entry.cat === 'devtools.extension';\n}\n\nexport interface ExtensionTrackData {\n // Name of the top level track. If it's a track group then this value\n // has the name of the group, otherwise it has the name of the track.\n name: string;\n isTrackGroup: boolean;\n // If this contains the data of a track group, this property contains\n // the entries of each of the tracks in the the group. If this is a\n // standalone track, then this contains that track's entries only.\n entriesByTrack: {\n [x: string]: SyntheticExtensionTrackEntry[],\n };\n}\n"]} \ No newline at end of file +{"version":3,"file":"Extensions.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/types/Extensions.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAW7B,MAAM,gBAAgB,GAAG;IACvB,SAAS;IACT,eAAe;IACf,cAAc;IACd,WAAW;IACX,iBAAiB;IACjB,gBAAgB;IAChB,UAAU;IACV,gBAAgB;IAChB,eAAe;IACf,OAAO;CACC,CAAC;AAIX,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,OAAQ,gBAAsC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AACjE,CAAC;AA8CD,MAAM,UAAU,wBAAwB,CAAC,OAA4B;IACnE,OAAO,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,OAA4C;IAEvF,MAAM,QAAQ,GAAG,OAAO,IAAI,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC9D,MAAM,cAAc,GAAG,OAAO,CAAC,QAAQ,KAAK,aAAa,IAAI,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC;IAC5F,OAAO,cAAc,IAAI,QAAQ,CAAC;AACpC,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAA4C;IAClF,OAAO,wBAAwB,CAAC,OAAO,CAAC,IAAI,4BAA4B,CAAC,OAAO,CAAC,CAAC;AACpF,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,KAAY;IACpD,OAAO,KAAK,CAAC,GAAG,KAAK,oBAAoB,CAAC;AAC5C,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {\n type Args,\n type Event,\n type Phase,\n type SyntheticBased,\n} from './TraceEvents.js';\n\nexport type ExtensionEntryType = 'track-entry'|'marker';\n\nconst extensionPalette = [\n 'primary',\n 'primary-light',\n 'primary-dark',\n 'secondary',\n 'secondary-light',\n 'secondary-dark',\n 'tertiary',\n 'tertiary-light',\n 'tertiary-dark',\n 'error',\n] as const;\n\nexport type ExtensionColorFromPalette = typeof extensionPalette[number];\n\nexport function colorIsValid(color: string): boolean {\n return (extensionPalette as readonly string[]).includes(color);\n}\n\nexport interface ExtensionDataPayloadBase {\n color?: ExtensionColorFromPalette;\n properties?: [string, string][];\n tooltipText?: string;\n}\n\nexport type ExtensionDataPayload = ExtensionTrackEntryPayload|ExtensionMarkerPayload;\n\nexport interface ExtensionTrackEntryPayload extends ExtensionDataPayloadBase {\n // Typed as possibly undefined since when no data type is provided\n // the entry is defaulted to a track entry\n dataType?: 'track-entry';\n // The name of the track the entry will be displayed in.\n // Entries intended to be displayed in the same track must contain the\n // same value in this property.\n // If undefined, measurement is added to the Timings track\n track: string;\n // The track group an entry’s track belongs to.\n // Entries intended to be displayed in the same track must contain the\n // same value in this property as well as the same value in the track\n // property.\n trackGroup?: string;\n}\n\nexport interface ExtensionMarkerPayload extends ExtensionDataPayloadBase {\n dataType: 'marker';\n}\n\n/**\n * Synthetic events created for extension tracks.\n */\nexport interface SyntheticExtensionTrackEntry extends SyntheticBased {\n args: Args&ExtensionTrackEntryPayload;\n}\n\n/**\n * Synthetic events created for extension marks.\n */\nexport interface SyntheticExtensionMarker extends SyntheticBased {\n args: Args&ExtensionMarkerPayload;\n}\n\nexport type SyntheticExtensionEntry = SyntheticExtensionTrackEntry|SyntheticExtensionMarker;\n\nexport function isExtensionPayloadMarker(payload: {dataType?: string}): payload is ExtensionMarkerPayload {\n return payload.dataType === 'marker';\n}\n\nexport function isExtensionPayloadTrackEntry(payload: {track?: string, dataType?: string}):\n payload is ExtensionTrackEntryPayload {\n const hasTrack = 'track' in payload && Boolean(payload.track);\n const validEntryType = payload.dataType === 'track-entry' || payload.dataType === undefined;\n return validEntryType && hasTrack;\n}\n\nexport function isValidExtensionPayload(payload: {track?: string, dataType?: string}): payload is ExtensionDataPayload {\n return isExtensionPayloadMarker(payload) || isExtensionPayloadTrackEntry(payload);\n}\n\nexport function isSyntheticExtensionEntry(entry: Event): entry is SyntheticExtensionEntry {\n return entry.cat === 'devtools.extension';\n}\n\nexport interface ExtensionTrackData {\n // Name of the top level track. If it's a track group then this value\n // has the name of the group, otherwise it has the name of the track.\n name: string;\n isTrackGroup: boolean;\n // If this contains the data of a track group, this property contains\n // the entries of each of the tracks in the the group. If this is a\n // standalone track, then this contains that track's entries only.\n entriesByTrack: {\n [x: string]: SyntheticExtensionTrackEntry[],\n };\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/types/File.d.ts b/public/models/trace/types/File.d.ts index f789f6654..f035b1344 100644 --- a/public/models/trace/types/File.d.ts +++ b/public/models/trace/types/File.d.ts @@ -1,8 +1,8 @@ import type * as Protocol from '../../../generated/protocol.js'; import { type TraceWindowMicroSeconds } from './Timing.js'; -import { type LegacyTimelineFrame, type ProcessID, type SampleIndex, type ThreadID, type TraceEventData } from './TraceEvents.js'; +import { type Event, type LegacyTimelineFrame, type ProcessID, type SampleIndex, type ThreadID } from './TraceEvents.js'; export type TraceFile = { - traceEvents: readonly TraceEventData[]; + traceEvents: readonly Event[]; metadata: MetaData; }; export interface Breadcrumb { @@ -34,7 +34,7 @@ export interface SerializedAnnotations { */ export interface EntryLabelAnnotation { type: 'ENTRY_LABEL'; - entry: TraceEventData | LegacyTimelineFrame; + entry: Event | LegacyTimelineFrame; label: string; } /** @@ -50,14 +50,14 @@ export interface TimeRangeAnnotation { */ export interface EntriesLinkAnnotation { type: 'ENTRIES_LINK'; - entryFrom: TraceEventData; - entryTo?: TraceEventData; + entryFrom: Event; + entryTo?: Event; } /** * Represents an object that is saved in the file when a user creates a label for an entry in the timeline. */ export interface EntryLabelAnnotationSerialized { - entry: TraceEventSerializableKey; + entry: SerializableKey; label: string; } /** @@ -71,8 +71,8 @@ export interface TimeRangeAnnotationSerialized { * Represents an object that is saved in the file when a user creates a link between entries in the timeline. */ export interface EntriesLinkAnnotationSerialized { - entryFrom: TraceEventSerializableKey; - entryTo: TraceEventSerializableKey; + entryFrom: SerializableKey; + entryTo: SerializableKey; } /** * `Annotation` are the user-created annotations that are saved into the metadata. @@ -89,7 +89,7 @@ export type RawEventKey = `${EventKeyType.RAW_EVENT}-${number}`; export type SyntheticEventKey = `${EventKeyType.SYNTHETIC_EVENT}-${number}`; export type ProfileCallKey = `${EventKeyType.PROFILE_CALL}-${ProcessID}-${ThreadID}-${SampleIndex}-${Protocol.integer}`; export type LegacyTimelineFrameKey = `${EventKeyType.LEGACY_TIMELINE_FRAME}-${number}`; -export type TraceEventSerializableKey = RawEventKey | ProfileCallKey | SyntheticEventKey | LegacyTimelineFrameKey; +export type SerializableKey = RawEventKey | ProfileCallKey | SyntheticEventKey | LegacyTimelineFrameKey; export type RawEventKeyValues = { type: EventKeyType.RAW_EVENT; rawIndex: number; @@ -109,11 +109,11 @@ export type LegacyTimelineFrameKeyValues = { type: EventKeyType.LEGACY_TIMELINE_FRAME; rawIndex: number; }; -export type TraceEventSerializableKeyValues = RawEventKeyValues | ProfileCallKeyValues | SyntheticEventKeyValues | LegacyTimelineFrameKeyValues; +export type SerializableKeyValues = RawEventKeyValues | ProfileCallKeyValues | SyntheticEventKeyValues | LegacyTimelineFrameKeyValues; export interface Modifications { entriesModifications: { - hiddenEntries: TraceEventSerializableKey[]; - expandableEntries: TraceEventSerializableKey[]; + hiddenEntries: SerializableKey[]; + expandableEntries: SerializableKey[]; }; initialBreadcrumb: Breadcrumb; annotations: SerializedAnnotations; @@ -133,5 +133,5 @@ export interface MetaData { modifications?: Modifications; enhancedTraceVersion?: number; } -export type Contents = TraceFile | TraceEventData[]; -export declare function traceEventKeyToValues(key: TraceEventSerializableKey): TraceEventSerializableKeyValues; +export type Contents = TraceFile | Event[]; +export declare function traceEventKeyToValues(key: SerializableKey): SerializableKeyValues; diff --git a/public/models/trace/types/File.js.map b/public/models/trace/types/File.js.map index e6dec3cab..2196a40f4 100644 --- a/public/models/trace/types/File.js.map +++ b/public/models/trace/types/File.js.map @@ -1 +1 @@ -{"version":3,"file":"File.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/types/File.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport type * as Protocol from '../../../generated/protocol.js';\n\nimport {type TraceWindowMicroSeconds} from './Timing.js';\nimport {\n type LegacyTimelineFrame,\n type ProcessID,\n type SampleIndex,\n type ThreadID,\n type TraceEventData,\n} from './TraceEvents.js';\n\nexport type TraceFile = {\n traceEvents: readonly TraceEventData[],\n metadata: MetaData,\n};\n\nexport interface Breadcrumb {\n window: TraceWindowMicroSeconds;\n child: Breadcrumb|null;\n}\n\nexport const enum DataOrigin {\n CPU_PROFILE = 'CPUProfile',\n TRACE_EVENTS = 'TraceEvents',\n}\n\nexport const enum EventKeyType {\n RAW_EVENT = 'r',\n SYNTHETIC_EVENT = 's',\n PROFILE_CALL = 'p',\n LEGACY_TIMELINE_FRAME = 'l',\n}\n\n/**\n * Represents an object that is saved in the file when user created annotations in the timeline.\n *\n * Expected to add more annotations.\n */\nexport interface SerializedAnnotations {\n entryLabels: EntryLabelAnnotationSerialized[];\n labelledTimeRanges: TimeRangeAnnotationSerialized[];\n linksBetweenEntries: EntriesLinkAnnotationSerialized[];\n}\n\n/**\n * Represents an object that is used to store the Entry Label annotation that is created when a user creates a label for an entry in the timeline.\n */\nexport interface EntryLabelAnnotation {\n type: 'ENTRY_LABEL';\n entry: TraceEventData|LegacyTimelineFrame;\n label: string;\n}\n\n/**\n * Represents an object that is used to store the Labelled Time Range Annotation that is created when a user creates a Time Range Selection in the timeline.\n */\nexport interface TimeRangeAnnotation {\n type: 'TIME_RANGE';\n label: string;\n bounds: TraceWindowMicroSeconds;\n}\n\n/**\n * Represents an object that is used to store the Entries link Annotation.\n */\nexport interface EntriesLinkAnnotation {\n type: 'ENTRIES_LINK';\n entryFrom: TraceEventData;\n entryTo?: TraceEventData;\n}\n\n/**\n * Represents an object that is saved in the file when a user creates a label for an entry in the timeline.\n */\nexport interface EntryLabelAnnotationSerialized {\n entry: TraceEventSerializableKey;\n label: string;\n}\n\n/**\n * Represents an object that is saved in the file when a user creates a time range with a label in the timeline.\n */\nexport interface TimeRangeAnnotationSerialized {\n bounds: TraceWindowMicroSeconds;\n label: string;\n}\n\n/**\n * Represents an object that is saved in the file when a user creates a link between entries in the timeline.\n */\nexport interface EntriesLinkAnnotationSerialized {\n entryFrom: TraceEventSerializableKey;\n entryTo: TraceEventSerializableKey;\n}\n\n/**\n * `Annotation` are the user-created annotations that are saved into the metadata.\n * Those annotations are rendered on the timeline by `Overlays.ts`\n *\n * TODO: Implement other OverlayAnnotations (annotated time ranges, links between entries).\n * TODO: Save/load overlay annotations to/from the trace file.\n */\nexport type Annotation = EntryLabelAnnotation|TimeRangeAnnotation|EntriesLinkAnnotation;\n\nexport function isTimeRangeAnnotation(annotation: Annotation): annotation is TimeRangeAnnotation {\n return annotation.type === 'TIME_RANGE';\n}\n\nexport function isEntryLabelAnnotation(annotation: Annotation): annotation is EntryLabelAnnotation {\n return annotation.type === 'ENTRY_LABEL';\n}\n\nexport function isEntriesLinkAnnotation(annotation: Annotation): annotation is EntriesLinkAnnotation {\n return annotation.type === 'ENTRIES_LINK';\n}\n\n// Serializable keys are created for trace events to be able to save\n// references to timeline events in a trace file. These keys enable\n// user modifications that can be saved. See go/cpq:event-data-json for\n// more details on the key format.\nexport type RawEventKey = `${EventKeyType.RAW_EVENT}-${number}`;\nexport type SyntheticEventKey = `${EventKeyType.SYNTHETIC_EVENT}-${number}`;\nexport type ProfileCallKey = `${EventKeyType.PROFILE_CALL}-${ProcessID}-${ThreadID}-${SampleIndex}-${Protocol.integer}`;\nexport type LegacyTimelineFrameKey = `${EventKeyType.LEGACY_TIMELINE_FRAME}-${number}`;\nexport type TraceEventSerializableKey = RawEventKey|ProfileCallKey|SyntheticEventKey|LegacyTimelineFrameKey;\n\n// Serializable keys values objects contain data that maps the keys to original Trace Events\nexport type RawEventKeyValues = {\n type: EventKeyType.RAW_EVENT,\n rawIndex: number,\n};\n\nexport type SyntheticEventKeyValues = {\n type: EventKeyType.SYNTHETIC_EVENT,\n rawIndex: number,\n};\n\nexport type ProfileCallKeyValues = {\n type: EventKeyType.PROFILE_CALL,\n processID: ProcessID,\n threadID: ThreadID,\n sampleIndex: SampleIndex,\n protocol: Protocol.integer,\n};\n\nexport type LegacyTimelineFrameKeyValues = {\n type: EventKeyType.LEGACY_TIMELINE_FRAME,\n rawIndex: number,\n};\n\nexport type TraceEventSerializableKeyValues =\n RawEventKeyValues|ProfileCallKeyValues|SyntheticEventKeyValues|LegacyTimelineFrameKeyValues;\n\nexport interface Modifications {\n entriesModifications: {\n // Entries hidden by the user\n hiddenEntries: TraceEventSerializableKey[],\n // Entries that parent a hiddenEntry\n expandableEntries: TraceEventSerializableKey[],\n };\n initialBreadcrumb: Breadcrumb;\n annotations: SerializedAnnotations;\n}\n\n/**\n * Trace metadata that we persist to the file. This will allow us to\n * store specifics for the trace, e.g., which tracks should be visible\n * on load.\n */\nexport interface MetaData {\n source?: 'DevTools';\n startTime?: string;\n networkThrottling?: string;\n cpuThrottling?: number;\n hardwareConcurrency?: number;\n dataOrigin?: DataOrigin;\n modifications?: Modifications;\n enhancedTraceVersion?: number;\n}\n\nexport type Contents = TraceFile|TraceEventData[];\n\nexport function traceEventKeyToValues(key: TraceEventSerializableKey): TraceEventSerializableKeyValues {\n const parts = key.split('-');\n const type = parts[0];\n\n switch (type) {\n case EventKeyType.PROFILE_CALL:\n if (parts.length !== 5 ||\n !(parts.every((part, i) => i === 0 || typeof part === 'number' || !isNaN(parseInt(part, 10))))) {\n throw new Error(`Invalid ProfileCallKey: ${key}`);\n }\n return {\n type: parts[0],\n processID: parseInt(parts[1], 10),\n threadID: parseInt(parts[2], 10),\n sampleIndex: parseInt(parts[3], 10),\n protocol: parseInt(parts[4], 10),\n } as ProfileCallKeyValues;\n case EventKeyType.RAW_EVENT:\n if (parts.length !== 2 || !(typeof parts[1] === 'number' || !isNaN(parseInt(parts[1], 10)))) {\n throw new Error(`Invalid RawEvent Key: ${key}`);\n }\n return {\n type: parts[0],\n rawIndex: parseInt(parts[1], 10),\n } as RawEventKeyValues;\n case EventKeyType.SYNTHETIC_EVENT:\n if (parts.length !== 2 || !(typeof parts[1] === 'number' || !isNaN(parseInt(parts[1], 10)))) {\n throw new Error(`Invalid SyntheticEvent Key: ${key}`);\n }\n return {\n type: parts[0],\n rawIndex: parseInt(parts[1], 10),\n } as SyntheticEventKeyValues;\n case EventKeyType.LEGACY_TIMELINE_FRAME: {\n if (parts.length !== 2 || Number.isNaN(parseInt(parts[1], 10))) {\n throw new Error(`Invalid LegacyTimelineFrame Key: ${key}`);\n }\n return {\n type,\n rawIndex: parseInt(parts[1], 10),\n };\n }\n\n default:\n throw new Error(`Unknown trace event key: ${key}`);\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"File.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/types/File.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport type * as Protocol from '../../../generated/protocol.js';\n\nimport {type TraceWindowMicroSeconds} from './Timing.js';\nimport {\n type Event,\n type LegacyTimelineFrame,\n type ProcessID,\n type SampleIndex,\n type ThreadID,\n} from './TraceEvents.js';\n\nexport type TraceFile = {\n traceEvents: readonly Event[],\n metadata: MetaData,\n};\n\nexport interface Breadcrumb {\n window: TraceWindowMicroSeconds;\n child: Breadcrumb|null;\n}\n\nexport const enum DataOrigin {\n CPU_PROFILE = 'CPUProfile',\n TRACE_EVENTS = 'TraceEvents',\n}\n\nexport const enum EventKeyType {\n RAW_EVENT = 'r',\n SYNTHETIC_EVENT = 's',\n PROFILE_CALL = 'p',\n LEGACY_TIMELINE_FRAME = 'l',\n}\n\n/**\n * Represents an object that is saved in the file when user created annotations in the timeline.\n *\n * Expected to add more annotations.\n */\nexport interface SerializedAnnotations {\n entryLabels: EntryLabelAnnotationSerialized[];\n labelledTimeRanges: TimeRangeAnnotationSerialized[];\n linksBetweenEntries: EntriesLinkAnnotationSerialized[];\n}\n\n/**\n * Represents an object that is used to store the Entry Label annotation that is created when a user creates a label for an entry in the timeline.\n */\nexport interface EntryLabelAnnotation {\n type: 'ENTRY_LABEL';\n entry: Event|LegacyTimelineFrame;\n label: string;\n}\n\n/**\n * Represents an object that is used to store the Labelled Time Range Annotation that is created when a user creates a Time Range Selection in the timeline.\n */\nexport interface TimeRangeAnnotation {\n type: 'TIME_RANGE';\n label: string;\n bounds: TraceWindowMicroSeconds;\n}\n\n/**\n * Represents an object that is used to store the Entries link Annotation.\n */\nexport interface EntriesLinkAnnotation {\n type: 'ENTRIES_LINK';\n entryFrom: Event;\n entryTo?: Event;\n}\n\n/**\n * Represents an object that is saved in the file when a user creates a label for an entry in the timeline.\n */\nexport interface EntryLabelAnnotationSerialized {\n entry: SerializableKey;\n label: string;\n}\n\n/**\n * Represents an object that is saved in the file when a user creates a time range with a label in the timeline.\n */\nexport interface TimeRangeAnnotationSerialized {\n bounds: TraceWindowMicroSeconds;\n label: string;\n}\n\n/**\n * Represents an object that is saved in the file when a user creates a link between entries in the timeline.\n */\nexport interface EntriesLinkAnnotationSerialized {\n entryFrom: SerializableKey;\n entryTo: SerializableKey;\n}\n\n/**\n * `Annotation` are the user-created annotations that are saved into the metadata.\n * Those annotations are rendered on the timeline by `Overlays.ts`\n *\n * TODO: Implement other OverlayAnnotations (annotated time ranges, links between entries).\n * TODO: Save/load overlay annotations to/from the trace file.\n */\nexport type Annotation = EntryLabelAnnotation|TimeRangeAnnotation|EntriesLinkAnnotation;\n\nexport function isTimeRangeAnnotation(annotation: Annotation): annotation is TimeRangeAnnotation {\n return annotation.type === 'TIME_RANGE';\n}\n\nexport function isEntryLabelAnnotation(annotation: Annotation): annotation is EntryLabelAnnotation {\n return annotation.type === 'ENTRY_LABEL';\n}\n\nexport function isEntriesLinkAnnotation(annotation: Annotation): annotation is EntriesLinkAnnotation {\n return annotation.type === 'ENTRIES_LINK';\n}\n\n// Serializable keys are created for trace events to be able to save\n// references to timeline events in a trace file. These keys enable\n// user modifications that can be saved. See go/cpq:event-data-json for\n// more details on the key format.\nexport type RawEventKey = `${EventKeyType.RAW_EVENT}-${number}`;\nexport type SyntheticEventKey = `${EventKeyType.SYNTHETIC_EVENT}-${number}`;\nexport type ProfileCallKey = `${EventKeyType.PROFILE_CALL}-${ProcessID}-${ThreadID}-${SampleIndex}-${Protocol.integer}`;\nexport type LegacyTimelineFrameKey = `${EventKeyType.LEGACY_TIMELINE_FRAME}-${number}`;\nexport type SerializableKey = RawEventKey|ProfileCallKey|SyntheticEventKey|LegacyTimelineFrameKey;\n\n// Serializable keys values objects contain data that maps the keys to original Trace Events\nexport type RawEventKeyValues = {\n type: EventKeyType.RAW_EVENT,\n rawIndex: number,\n};\n\nexport type SyntheticEventKeyValues = {\n type: EventKeyType.SYNTHETIC_EVENT,\n rawIndex: number,\n};\n\nexport type ProfileCallKeyValues = {\n type: EventKeyType.PROFILE_CALL,\n processID: ProcessID,\n threadID: ThreadID,\n sampleIndex: SampleIndex,\n protocol: Protocol.integer,\n};\n\nexport type LegacyTimelineFrameKeyValues = {\n type: EventKeyType.LEGACY_TIMELINE_FRAME,\n rawIndex: number,\n};\n\nexport type SerializableKeyValues =\n RawEventKeyValues|ProfileCallKeyValues|SyntheticEventKeyValues|LegacyTimelineFrameKeyValues;\n\nexport interface Modifications {\n entriesModifications: {\n // Entries hidden by the user\n hiddenEntries: SerializableKey[],\n // Entries that parent a hiddenEntry\n expandableEntries: SerializableKey[],\n };\n initialBreadcrumb: Breadcrumb;\n annotations: SerializedAnnotations;\n}\n\n/**\n * Trace metadata that we persist to the file. This will allow us to\n * store specifics for the trace, e.g., which tracks should be visible\n * on load.\n */\nexport interface MetaData {\n source?: 'DevTools';\n startTime?: string;\n networkThrottling?: string;\n cpuThrottling?: number;\n hardwareConcurrency?: number;\n dataOrigin?: DataOrigin;\n modifications?: Modifications;\n enhancedTraceVersion?: number;\n}\n\nexport type Contents = TraceFile|Event[];\n\nexport function traceEventKeyToValues(key: SerializableKey): SerializableKeyValues {\n const parts = key.split('-');\n const type = parts[0];\n\n switch (type) {\n case EventKeyType.PROFILE_CALL:\n if (parts.length !== 5 ||\n !(parts.every((part, i) => i === 0 || typeof part === 'number' || !isNaN(parseInt(part, 10))))) {\n throw new Error(`Invalid ProfileCallKey: ${key}`);\n }\n return {\n type: parts[0],\n processID: parseInt(parts[1], 10),\n threadID: parseInt(parts[2], 10),\n sampleIndex: parseInt(parts[3], 10),\n protocol: parseInt(parts[4], 10),\n } as ProfileCallKeyValues;\n case EventKeyType.RAW_EVENT:\n if (parts.length !== 2 || !(typeof parts[1] === 'number' || !isNaN(parseInt(parts[1], 10)))) {\n throw new Error(`Invalid RawEvent Key: ${key}`);\n }\n return {\n type: parts[0],\n rawIndex: parseInt(parts[1], 10),\n } as RawEventKeyValues;\n case EventKeyType.SYNTHETIC_EVENT:\n if (parts.length !== 2 || !(typeof parts[1] === 'number' || !isNaN(parseInt(parts[1], 10)))) {\n throw new Error(`Invalid SyntheticEvent Key: ${key}`);\n }\n return {\n type: parts[0],\n rawIndex: parseInt(parts[1], 10),\n } as SyntheticEventKeyValues;\n case EventKeyType.LEGACY_TIMELINE_FRAME: {\n if (parts.length !== 2 || Number.isNaN(parseInt(parts[1], 10))) {\n throw new Error(`Invalid LegacyTimelineFrame Key: ${key}`);\n }\n return {\n type,\n rawIndex: parseInt(parts[1], 10),\n };\n }\n\n default:\n throw new Error(`Unknown trace event key: ${key}`);\n }\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/types/File.test.js b/public/models/trace/types/File.test.js index 69a30265a..abd9fb6f0 100644 --- a/public/models/trace/types/File.test.js +++ b/public/models/trace/types/File.test.js @@ -1,30 +1,30 @@ // Copyright 2024 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 * as TraceEngine from '../trace.js'; -describe('TraceEngine file types', () => { +import * as Trace from '../trace.js'; +describe('Trace file types', () => { describe('traceEventKeyToValues', () => { it('converts the values for a LegacyTimelineFrame', async () => { - const result = TraceEngine.Types.File.traceEventKeyToValues('l-101'); - assert.deepEqual(result, { type: "l" /* TraceEngine.Types.File.EventKeyType.LEGACY_TIMELINE_FRAME */, rawIndex: 101 }); + const result = Trace.Types.File.traceEventKeyToValues('l-101'); + assert.deepEqual(result, { type: "l" /* Trace.Types.File.EventKeyType.LEGACY_TIMELINE_FRAME */, rawIndex: 101 }); }); it('converts the values for a raw event', async () => { - const result = TraceEngine.Types.File.traceEventKeyToValues('r-101'); - assert.deepEqual(result, { type: "r" /* TraceEngine.Types.File.EventKeyType.RAW_EVENT */, rawIndex: 101 }); + const result = Trace.Types.File.traceEventKeyToValues('r-101'); + assert.deepEqual(result, { type: "r" /* Trace.Types.File.EventKeyType.RAW_EVENT */, rawIndex: 101 }); }); it('converts the values for a synthetic event', async () => { - const result = TraceEngine.Types.File.traceEventKeyToValues('s-101'); - assert.deepEqual(result, { type: "s" /* TraceEngine.Types.File.EventKeyType.SYNTHETIC_EVENT */, rawIndex: 101 }); + const result = Trace.Types.File.traceEventKeyToValues('s-101'); + assert.deepEqual(result, { type: "s" /* Trace.Types.File.EventKeyType.SYNTHETIC_EVENT */, rawIndex: 101 }); }); it('converts the values for a profile call event', async () => { - const pid = TraceEngine.Types.TraceEvents.ProcessID(1); - const tid = TraceEngine.Types.TraceEvents.ThreadID(2); - const sampleIndex = TraceEngine.Types.TraceEvents.SampleIndex(3); + const pid = Trace.Types.Events.ProcessID(1); + const tid = Trace.Types.Events.ThreadID(2); + const sampleIndex = Trace.Types.Events.SampleIndex(3); const nodeId = 4; const key = ['p', pid, tid, sampleIndex, nodeId].join('-'); - const result = TraceEngine.Types.File.traceEventKeyToValues(key); + const result = Trace.Types.File.traceEventKeyToValues(key); assert.deepEqual(result, { - type: "p" /* TraceEngine.Types.File.EventKeyType.PROFILE_CALL */, + type: "p" /* Trace.Types.File.EventKeyType.PROFILE_CALL */, processID: pid, threadID: tid, sampleIndex, diff --git a/public/models/trace/types/File.test.js.map b/public/models/trace/types/File.test.js.map index 78a543728..aae1da71c 100644 --- a/public/models/trace/types/File.test.js.map +++ b/public/models/trace/types/File.test.js.map @@ -1 +1 @@ -{"version":3,"file":"File.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/types/File.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAG7B,OAAO,KAAK,WAAW,MAAM,aAAa,CAAC;AAE3C,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;QACrC,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;YAC7D,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC;YACrE,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,EAAC,IAAI,qEAA2D,EAAE,QAAQ,EAAE,GAAG,EAAC,CAAC,CAAC;QAC7G,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;YACnD,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC;YACrE,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,EAAC,IAAI,yDAA+C,EAAE,QAAQ,EAAE,GAAG,EAAC,CAAC,CAAC;QACjG,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;YACzD,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC;YACrE,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,EAAC,IAAI,+DAAqD,EAAE,QAAQ,EAAE,GAAG,EAAC,CAAC,CAAC;QACvG,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;YAC5D,MAAM,GAAG,GAAG,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YACvD,MAAM,GAAG,GAAG,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YACtD,MAAM,WAAW,GAAG,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;YACjE,MAAM,MAAM,GAAG,CAAqB,CAAC;YAErC,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAqD,CAAC;YAC/G,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC;YACjE,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE;gBACvB,IAAI,4DAAkD;gBACtD,SAAS,EAAE,GAAG;gBACd,QAAQ,EAAE,GAAG;gBACb,WAAW;gBACX,QAAQ,EAAE,MAAM;aACjB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Protocol from '../../../generated/protocol.js';\nimport * as TraceEngine from '../trace.js';\n\ndescribe('TraceEngine file types', () => {\n describe('traceEventKeyToValues', () => {\n it('converts the values for a LegacyTimelineFrame', async () => {\n const result = TraceEngine.Types.File.traceEventKeyToValues('l-101');\n assert.deepEqual(result, {type: TraceEngine.Types.File.EventKeyType.LEGACY_TIMELINE_FRAME, rawIndex: 101});\n });\n\n it('converts the values for a raw event', async () => {\n const result = TraceEngine.Types.File.traceEventKeyToValues('r-101');\n assert.deepEqual(result, {type: TraceEngine.Types.File.EventKeyType.RAW_EVENT, rawIndex: 101});\n });\n\n it('converts the values for a synthetic event', async () => {\n const result = TraceEngine.Types.File.traceEventKeyToValues('s-101');\n assert.deepEqual(result, {type: TraceEngine.Types.File.EventKeyType.SYNTHETIC_EVENT, rawIndex: 101});\n });\n\n it('converts the values for a profile call event', async () => {\n const pid = TraceEngine.Types.TraceEvents.ProcessID(1);\n const tid = TraceEngine.Types.TraceEvents.ThreadID(2);\n const sampleIndex = TraceEngine.Types.TraceEvents.SampleIndex(3);\n const nodeId = 4 as Protocol.integer;\n\n const key = ['p', pid, tid, sampleIndex, nodeId].join('-') as TraceEngine.Types.File.TraceEventSerializableKey;\n const result = TraceEngine.Types.File.traceEventKeyToValues(key);\n assert.deepEqual(result, {\n type: TraceEngine.Types.File.EventKeyType.PROFILE_CALL,\n processID: pid,\n threadID: tid,\n sampleIndex,\n protocol: nodeId,\n });\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"File.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/types/File.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAG7B,OAAO,KAAK,KAAK,MAAM,aAAa,CAAC;AAErC,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;QACrC,EAAE,CAAC,+CAA+C,EAAE,KAAK,IAAI,EAAE;YAC7D,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC;YAC/D,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,EAAC,IAAI,+DAAqD,EAAE,QAAQ,EAAE,GAAG,EAAC,CAAC,CAAC;QACvG,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;YACnD,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC;YAC/D,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,EAAC,IAAI,mDAAyC,EAAE,QAAQ,EAAE,GAAG,EAAC,CAAC,CAAC;QAC3F,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;YACzD,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC;YAC/D,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE,EAAC,IAAI,yDAA+C,EAAE,QAAQ,EAAE,GAAG,EAAC,CAAC,CAAC;QACjG,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8CAA8C,EAAE,KAAK,IAAI,EAAE;YAC5D,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YAC5C,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC3C,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;YACtD,MAAM,MAAM,GAAG,CAAqB,CAAC;YAErC,MAAM,GAAG,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAqC,CAAC;YAC/F,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,CAAC;YAC3D,MAAM,CAAC,SAAS,CAAC,MAAM,EAAE;gBACvB,IAAI,sDAA4C;gBAChD,SAAS,EAAE,GAAG;gBACd,QAAQ,EAAE,GAAG;gBACb,WAAW;gBACX,QAAQ,EAAE,MAAM;aACjB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Protocol from '../../../generated/protocol.js';\nimport * as Trace from '../trace.js';\n\ndescribe('Trace file types', () => {\n describe('traceEventKeyToValues', () => {\n it('converts the values for a LegacyTimelineFrame', async () => {\n const result = Trace.Types.File.traceEventKeyToValues('l-101');\n assert.deepEqual(result, {type: Trace.Types.File.EventKeyType.LEGACY_TIMELINE_FRAME, rawIndex: 101});\n });\n\n it('converts the values for a raw event', async () => {\n const result = Trace.Types.File.traceEventKeyToValues('r-101');\n assert.deepEqual(result, {type: Trace.Types.File.EventKeyType.RAW_EVENT, rawIndex: 101});\n });\n\n it('converts the values for a synthetic event', async () => {\n const result = Trace.Types.File.traceEventKeyToValues('s-101');\n assert.deepEqual(result, {type: Trace.Types.File.EventKeyType.SYNTHETIC_EVENT, rawIndex: 101});\n });\n\n it('converts the values for a profile call event', async () => {\n const pid = Trace.Types.Events.ProcessID(1);\n const tid = Trace.Types.Events.ThreadID(2);\n const sampleIndex = Trace.Types.Events.SampleIndex(3);\n const nodeId = 4 as Protocol.integer;\n\n const key = ['p', pid, tid, sampleIndex, nodeId].join('-') as Trace.Types.File.SerializableKey;\n const result = Trace.Types.File.traceEventKeyToValues(key);\n assert.deepEqual(result, {\n type: Trace.Types.File.EventKeyType.PROFILE_CALL,\n processID: pid,\n threadID: tid,\n sampleIndex,\n protocol: nodeId,\n });\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/types/TraceEvents.d.ts b/public/models/trace/types/TraceEvents.d.ts index c11141abf..a77d090e0 100644 --- a/public/models/trace/types/TraceEvents.d.ts +++ b/public/models/trace/types/TraceEvents.d.ts @@ -27,15 +27,15 @@ export declare const enum Phase { CLOCK_SYNC = "c" } export declare function isNestableAsyncPhase(phase: Phase): boolean; -export declare function isAsyncPhase(phase: Phase): boolean; +export declare function isPhaseAsync(phase: Phase): boolean; export declare function isFlowPhase(phase: Phase): boolean; -export declare const enum TraceEventScope { +export declare const enum Scope { THREAD = "t", PROCESS = "p", GLOBAL = "g" } -export interface TraceEventData { - args?: TraceEventArgs; +export interface Event { + args?: Args; cat: string; name: string; ph: Phase; @@ -46,17 +46,17 @@ export interface TraceEventData { tdur?: MicroSeconds; dur?: MicroSeconds; } -export interface TraceEventArgs { - data?: TraceEventArgsData; - stackTrace?: TraceEventCallFrame[]; +export interface Args { + data?: ArgsData; + stackTrace?: CallFrame[]; } -export interface TraceEventArgsData { - stackTrace?: TraceEventCallFrame[]; +export interface ArgsData { + stackTrace?: CallFrame[]; url?: string; navigationId?: string; frame?: string; } -export interface TraceEventCallFrame { +export interface CallFrame { codeType?: string; functionName: string; scriptId: number | string; @@ -64,7 +64,7 @@ export interface TraceEventCallFrame { lineNumber: number; url: string; } -export declare function objectIsTraceEventCallFrame(object: {}): object is TraceEventCallFrame; +export declare function objectIsCallFrame(object: {}): object is CallFrame; export interface TraceFrame { frame: string; name: string; @@ -74,62 +74,62 @@ export interface TraceFrame { isOutermostMainFrame?: boolean; isInPrimaryMainFrame?: boolean; } -export interface TraceEventSample extends TraceEventData { +export interface Sample extends Event { ph: Phase.SAMPLE; } /** * A fake trace event created to support CDP.Profiler.Profiles in the * trace engine. */ -export interface SyntheticCpuProfile extends TraceEventInstant, SyntheticBasedEvent { +export interface SyntheticCpuProfile extends Instant, SyntheticBased { name: 'CpuProfile'; - args: TraceEventArgs & { - data: TraceEventArgsData & { + args: Args & { + data: ArgsData & { cpuProfile: Protocol.Profiler.Profile; }; }; } -export interface TraceEventProfile extends TraceEventSample { +export interface Profile extends Sample { name: 'Profile'; id: ProfileID; - args: TraceEventArgs & { - data: TraceEventArgsData & { + args: Args & { + data: ArgsData & { startTime: MicroSeconds; }; }; } -export interface TraceEventProfileChunk extends TraceEventSample { +export interface ProfileChunk extends Sample { name: 'ProfileChunk'; id: ProfileID; - args: TraceEventArgs & { - data?: TraceEventArgsData & { - cpuProfile?: TraceEventPartialProfile; + args: Args & { + data?: ArgsData & { + cpuProfile?: PartialProfile; timeDeltas?: MicroSeconds[]; lines?: MicroSeconds[]; }; }; } -export interface TraceEventPartialProfile { - nodes?: TraceEventPartialNode[]; +export interface PartialProfile { + nodes?: PartialNode[]; samples: CallFrameID[]; } -export interface TraceEventPartialNode { - callFrame: TraceEventCallFrame; +export interface PartialNode { + callFrame: CallFrame; id: CallFrameID; parent?: CallFrameID; } -export interface TraceEventComplete extends TraceEventData { +export interface Complete extends Event { ph: Phase.COMPLETE; dur: MicroSeconds; } -export interface TraceEventRunTask extends TraceEventComplete { - name: KnownEventName.RUN_TASK; +export interface RunTask extends Complete { + name: Name.RUN_TASK; } -export declare function isTraceEventRunTask(event: TraceEventData): event is TraceEventRunTask; -export interface TraceEventFireIdleCallback extends TraceEventComplete { - name: KnownEventName.FIRE_IDLE_CALLBACK; - args: TraceEventArgs & { - data: TraceEventArgsData & { +export declare function isRunTask(event: Event): event is RunTask; +export interface FireIdleCallback extends Complete { + name: Name.FIRE_IDLE_CALLBACK; + args: Args & { + data: ArgsData & { allottedMilliseconds: MilliSeconds; frame: string; id: number; @@ -137,33 +137,33 @@ export interface TraceEventFireIdleCallback extends TraceEventComplete { }; }; } -export interface TraceEventSchedulePostMessage extends TraceEventInstant { - name: KnownEventName.SCHEDULE_POST_MESSAGE; - args: TraceEventArgs & { - data: TraceEventArgsData & { +export interface SchedulePostMessage extends Instant { + name: Name.SCHEDULE_POST_MESSAGE; + args: Args & { + data: ArgsData & { traceId: string; }; }; } -export interface TraceEventHandlePostMessage extends TraceEventComplete { - name: KnownEventName.HANDLE_POST_MESSAGE; - args: TraceEventArgs & { - data: TraceEventArgsData & { +export interface HandlePostMessage extends Complete { + name: Name.HANDLE_POST_MESSAGE; + args: Args & { + data: ArgsData & { traceId: string; }; }; } -export interface TraceEventDispatch extends TraceEventComplete { +export interface Dispatch extends Complete { name: 'EventDispatch'; - args: TraceEventArgs & { - data: TraceEventArgsData & { + args: Args & { + data: ArgsData & { type: string; }; }; } -export interface TraceEventParseHTML extends TraceEventComplete { +export interface ParseHTML extends Complete { name: 'ParseHTML'; - args: TraceEventArgs & { + args: Args & { beginData: { frame: string; startLine: number; @@ -174,10 +174,10 @@ export interface TraceEventParseHTML extends TraceEventComplete { }; }; } -export interface TraceEventBegin extends TraceEventData { +export interface Begin extends Event { ph: Phase.BEGIN; } -export interface TraceEventEnd extends TraceEventData { +export interface End extends Event { ph: Phase.END; } /** @@ -187,14 +187,14 @@ export interface TraceEventEnd extends TraceEventData { * complete event that comprises the data of both from the beginning in * the RendererHandler. */ -export type SyntheticCompleteEvent = TraceEventComplete; -export interface TraceEventEventTiming extends TraceEventData { +export type SyntheticComplete = Complete; +export interface EventTiming extends Event { ph: Phase.ASYNC_NESTABLE_START | Phase.ASYNC_NESTABLE_END; - name: KnownEventName.EVENT_TIMING; + name: Name.EVENT_TIMING; id: string; - args: TraceEventArgs & { + args: Args & { frame: string; - data?: TraceEventArgsData & { + data?: ArgsData & { cancelable: boolean; duration: MilliSeconds; processingEnd: MilliSeconds; @@ -205,16 +205,16 @@ export interface TraceEventEventTiming extends TraceEventData { }; }; } -export interface TraceEventEventTimingBegin extends TraceEventEventTiming { +export interface EventTimingBegin extends EventTiming { ph: Phase.ASYNC_NESTABLE_START; } -export interface TraceEventEventTimingEnd extends TraceEventEventTiming { +export interface EventTimingEnd extends EventTiming { ph: Phase.ASYNC_NESTABLE_END; } -export interface TraceEventGPUTask extends TraceEventComplete { +export interface GPUTask extends Complete { name: 'GPUTask'; - args: TraceEventArgs & { - data?: TraceEventArgsData & { + args: Args & { + data?: ArgsData & { renderer_pid: ProcessID; used_bytes: number; }; @@ -249,10 +249,10 @@ interface SyntheticArgsData { totalTime: MicroSeconds; waiting: MicroSeconds; } -export interface SyntheticNetworkRequest extends TraceEventComplete, SyntheticBasedEvent { - rawSourceEvent: TraceEventResourceSendRequest; - args: TraceEventArgs & { - data: TraceEventArgsData & { +export interface SyntheticNetworkRequest extends Complete, SyntheticBased { + rawSourceEvent: ResourceSendRequest; + args: Args & { + data: ArgsData & { syntheticData: SyntheticArgsData; /** Size of the resource after decompression (if applicable). */ decodedBodyLength: number; @@ -295,7 +295,7 @@ export interface SyntheticNetworkRequest extends TraceEventComplete, SyntheticBa connectionReused: boolean; initiator?: Initiator; requestMethod?: string; - timing?: TraceEventResourceReceiveResponseTimingData; + timing?: ResourceReceiveResponseTimingData; syntheticServerTimings?: SyntheticServerTiming[]; }; }; @@ -309,57 +309,57 @@ export interface SyntheticNetworkRequest extends TraceEventComplete, SyntheticBa pid: ProcessID; tid: ThreadID; } -export interface SyntheticWebSocketConnectionEvent extends TraceEventComplete, SyntheticBasedEvent { - rawSourceEvent: TraceEventData; - args: TraceEventArgs & { - data: TraceEventArgsData & { +export interface SyntheticWebSocketConnection extends Complete, SyntheticBased { + rawSourceEvent: Event; + args: Args & { + data: ArgsData & { identifier: number; priority: Protocol.Network.ResourcePriority; url: string; }; }; cat: string; - name: 'SyntheticWebSocketConnectionEvent'; + name: 'SyntheticWebSocketConnection'; ph: Phase.COMPLETE; dur: MicroSeconds; ts: MicroSeconds; pid: ProcessID; tid: ThreadID; - s: TraceEventScope; + s: Scope; } export declare const enum AuctionWorkletType { BIDDER = "bidder", SELLER = "seller", UNKNOWN = "unknown" } -export interface SyntheticAuctionWorkletEvent extends TraceEventInstant, SyntheticBasedEvent { - rawSourceEvent: TraceEventData; - name: 'SyntheticAuctionWorkletEvent'; +export interface SyntheticAuctionWorklet extends Instant, SyntheticBased { + rawSourceEvent: Event; + name: 'SyntheticAuctionWorklet'; pid: ProcessID; host: string; target: string; type: AuctionWorkletType; - args: TraceEventArgs & { - data: TraceEventArgsData & { - utilityThread: TraceEventThreadName; - v8HelperThread: TraceEventThreadName; + args: Args & { + data: ArgsData & { + utilityThread: ThreadName; + v8HelperThread: ThreadName; } & ({ - runningInProcessEvent: TraceEventAuctionWorkletRunningInProcess; - doneWithProcessEvent: TraceEventAuctionWorkletDoneWithProcess; + runningInProcessEvent: AuctionWorkletRunningInProcess; + doneWithProcessEvent: AuctionWorkletDoneWithProcess; } | { - runningInProcessEvent?: TraceEventAuctionWorkletRunningInProcess; - doneWithProcessEvent: TraceEventAuctionWorkletDoneWithProcess; + runningInProcessEvent?: AuctionWorkletRunningInProcess; + doneWithProcessEvent: AuctionWorkletDoneWithProcess; } | { - doneWithProcessEvent?: TraceEventAuctionWorkletDoneWithProcess; - runningInProcessEvent: TraceEventAuctionWorkletRunningInProcess; + doneWithProcessEvent?: AuctionWorkletDoneWithProcess; + runningInProcessEvent: AuctionWorkletRunningInProcess; }); }; } -export interface TraceEventAuctionWorkletRunningInProcess extends TraceEventData { +export interface AuctionWorkletRunningInProcess extends Event { name: 'AuctionWorkletRunningInProcess'; ph: Phase.INSTANT; - args: TraceEventArgs & { - data: TraceEventArgsData & { + args: Args & { + data: ArgsData & { host: string; pid: ProcessID; target: string; @@ -367,11 +367,11 @@ export interface TraceEventAuctionWorkletRunningInProcess extends TraceEventData }; }; } -export interface TraceEventAuctionWorkletDoneWithProcess extends TraceEventData { +export interface AuctionWorkletDoneWithProcess extends Event { name: 'AuctionWorkletDoneWithProcess'; ph: Phase.INSTANT; - args: TraceEventArgs & { - data: TraceEventArgsData & { + args: Args & { + data: ArgsData & { host: string; pid: ProcessID; target: string; @@ -379,39 +379,39 @@ export interface TraceEventAuctionWorkletDoneWithProcess extends TraceEventData }; }; } -export declare function isTraceEventAuctionWorkletRunningInProcess(event: TraceEventData): event is TraceEventAuctionWorkletRunningInProcess; -export declare function isTraceEventAuctionWorkletDoneWithProcess(event: TraceEventData): event is TraceEventAuctionWorkletDoneWithProcess; -export interface TraceEventScreenshot extends TraceEventData { +export declare function isAuctionWorkletRunningInProcess(event: Event): event is AuctionWorkletRunningInProcess; +export declare function isAuctionWorkletDoneWithProcess(event: Event): event is AuctionWorkletDoneWithProcess; +export interface Screenshot extends Event { /** * @deprecated This value is incorrect. Use ScreenshotHandler.getPresentationTimestamp() */ ts: MicroSeconds; /** The id is the frame sequence number in hex */ id: string; - args: TraceEventArgs & { + args: Args & { snapshot: string; }; - name: KnownEventName.SCREENSHOT; + name: Name.SCREENSHOT; cat: 'disabled-by-default-devtools.screenshot'; ph: Phase.OBJECT_SNAPSHOT; } -export declare function isTraceEventScreenshot(event: TraceEventData): event is TraceEventScreenshot; -export interface SyntheticScreenshot extends TraceEventData, SyntheticBasedEvent { - rawSourceEvent: TraceEventScreenshot; +export declare function isScreenshot(event: Event): event is Screenshot; +export interface SyntheticScreenshot extends Event, SyntheticBased { + rawSourceEvent: Screenshot; /** This is the correct presentation timestamp. */ ts: MicroSeconds; - args: TraceEventArgs & { + args: Args & { dataUri: string; }; - name: KnownEventName.SCREENSHOT; + name: Name.SCREENSHOT; cat: 'disabled-by-default-devtools.screenshot'; ph: Phase.OBJECT_SNAPSHOT; } -export interface TraceEventAnimation extends TraceEventData { - args: TraceEventArgs & { - data: TraceEventArgsData & { +export interface Animation extends Event { + args: Args & { + data: ArgsData & { nodeName?: string; - nodeId?: number; + nodeId?: Protocol.DOM.BackendNodeId; displayName?: string; id?: string; name?: string; @@ -426,29 +426,29 @@ export interface TraceEventAnimation extends TraceEventData { }; ph: Phase.ASYNC_NESTABLE_START | Phase.ASYNC_NESTABLE_END | Phase.ASYNC_NESTABLE_INSTANT; } -export interface TraceEventMetadata extends TraceEventData { +export interface Metadata extends Event { ph: Phase.METADATA; - args: TraceEventArgs & { + args: Args & { name?: string; uptime?: string; }; } -export interface TraceEventThreadName extends TraceEventMetadata { - name: KnownEventName.THREAD_NAME; - args: TraceEventArgs & { +export interface ThreadName extends Metadata { + name: Name.THREAD_NAME; + args: Args & { name?: string; }; } -export interface TraceEventProcessName extends TraceEventMetadata { +export interface ProcessName extends Metadata { name: 'process_name'; } -export interface TraceEventMark extends TraceEventData { +export interface Mark extends Event { ph: Phase.MARK; } -export interface TraceEventNavigationStart extends TraceEventMark { +export interface NavigationStart extends Mark { name: 'navigationStart'; - args: TraceEventArgs & { - data?: TraceEventArgsData & { + args: Args & { + data?: ArgsData & { documentLoaderURL: string; isLoadingMainFrame: boolean; isOutermostMainFrame?: boolean; @@ -461,36 +461,36 @@ export interface TraceEventNavigationStart extends TraceEventMark { frame: string; }; } -export interface TraceEventFirstContentfulPaint extends TraceEventMark { - name: KnownEventName.MARK_FCP; - args: TraceEventArgs & { +export interface FirstContentfulPaint extends Mark { + name: Name.MARK_FCP; + args: Args & { frame: string; - data?: TraceEventArgsData & { + data?: ArgsData & { navigationId: string; }; }; } -export interface TraceEventFirstPaint extends TraceEventMark { +export interface FirstPaint extends Mark { name: 'firstPaint'; - args: TraceEventArgs & { + args: Args & { frame: string; - data?: TraceEventArgsData & { + data?: ArgsData & { navigationId: string; }; }; } -export type PageLoadEvent = TraceEventFirstContentfulPaint | TraceEventMarkDOMContent | TraceEventInteractiveTime | TraceEventLargestContentfulPaintCandidate | TraceEventLayoutShift | TraceEventFirstPaint | TraceEventMarkLoad | TraceEventNavigationStart; +export type PageLoadEvent = FirstContentfulPaint | MarkDOMContent | InteractiveTime | LargestContentfulPaintCandidate | LayoutShift | FirstPaint | MarkLoad | NavigationStart; export declare const MarkerName: readonly ["MarkDOMContent", "MarkLoad", "firstPaint", "firstContentfulPaint", "largestContentfulPaint::Candidate"]; -export interface MarkerEvent extends TraceEventData { +export interface MarkerEvent extends Event { name: typeof MarkerName[number]; } -export declare function isTraceEventMarkerEvent(event: TraceEventData): event is MarkerEvent; -export declare function eventIsPageLoadEvent(event: TraceEventData): event is PageLoadEvent; -export interface TraceEventLargestContentfulPaintCandidate extends TraceEventMark { - name: KnownEventName.MARK_LCP_CANDIDATE; - args: TraceEventArgs & { +export declare function isMarkerEvent(event: Event): event is MarkerEvent; +export declare function eventIsPageLoadEvent(event: Event): event is PageLoadEvent; +export interface LargestContentfulPaintCandidate extends Mark { + name: Name.MARK_LCP_CANDIDATE; + args: Args & { frame: string; - data?: TraceEventArgsData & { + data?: ArgsData & { candidateIndex: number; isOutermostMainFrame: boolean; isMainFrame: boolean; @@ -501,44 +501,44 @@ export interface TraceEventLargestContentfulPaintCandidate extends TraceEventMar }; }; } -export interface TraceEventLargestImagePaintCandidate extends TraceEventMark { +export interface LargestImagePaintCandidate extends Mark { name: 'LargestImagePaint::Candidate'; - args: TraceEventArgs & { + args: Args & { frame: string; - data?: TraceEventArgsData & { + data?: ArgsData & { candidateIndex: number; imageUrl: string; DOMNodeId: Protocol.DOM.BackendNodeId; }; }; } -export interface TraceEventLargestTextPaintCandidate extends TraceEventMark { +export interface LargestTextPaintCandidate extends Mark { name: 'LargestTextPaint::Candidate'; - args: TraceEventArgs & { + args: Args & { frame: string; - data?: TraceEventArgsData & { + data?: ArgsData & { candidateIndex: number; DOMNodeId: Protocol.DOM.BackendNodeId; }; }; } -export interface TraceEventInteractiveTime extends TraceEventMark { +export interface InteractiveTime extends Mark { name: 'InteractiveTime'; - args: TraceEventArgs & { + args: Args & { args: { total_blocking_time_ms: number; }; frame: string; }; } -export interface TraceEventInstant extends TraceEventData { +export interface Instant extends Event { ph: Phase.INSTANT; - s: TraceEventScope; + s: Scope; } -export interface TraceEventUpdateCounters extends TraceEventInstant { +export interface UpdateCounters extends Instant { name: 'UpdateCounters'; - args: TraceEventArgs & { - data: TraceEventArgsData & { + args: Args & { + data: ArgsData & { documents: number; jsEventListeners: number; jsHeapSizeUsed: number; @@ -547,21 +547,21 @@ export interface TraceEventUpdateCounters extends TraceEventInstant { }; }; } -export type TraceEventRendererEvent = TraceEventInstant | TraceEventComplete; -export interface TraceEventTracingStartedInBrowser extends TraceEventInstant { - name: KnownEventName.TRACING_STARTED_IN_BROWSER; - args: TraceEventArgs & { - data?: TraceEventArgsData & { +export type RendererEvent = Instant | Complete; +export interface TracingStartedInBrowser extends Instant { + name: Name.TRACING_STARTED_IN_BROWSER; + args: Args & { + data?: ArgsData & { frameTreeNodeId: number; frames?: TraceFrame[]; persistentIds: boolean; }; }; } -export interface TraceEventTracingSessionIdForWorker extends TraceEventInstant { +export interface TracingSessionIdForWorker extends Instant { name: 'TracingSessionIdForWorker'; - args: TraceEventArgs & { - data?: TraceEventArgsData & { + args: Args & { + data?: ArgsData & { url: string; workerId: WorkerId; workerThreadId: ThreadID; @@ -569,25 +569,25 @@ export interface TraceEventTracingSessionIdForWorker extends TraceEventInstant { }; }; } -export declare function isTraceEventTracingSessionIdForWorker(event: TraceEventData): event is TraceEventTracingSessionIdForWorker; -export interface TraceEventFrameCommittedInBrowser extends TraceEventInstant { +export declare function isTracingSessionIdForWorker(event: Event): event is TracingSessionIdForWorker; +export interface FrameCommittedInBrowser extends Instant { name: 'FrameCommittedInBrowser'; - args: TraceEventArgs & { - data?: TraceEventArgsData & TraceFrame; + args: Args & { + data?: ArgsData & TraceFrame; }; } -export interface TraceEventMainFrameViewport extends TraceEventInstant { +export interface MainFrameViewport extends Instant { name: 'PaintTimingVisualizer::Viewport'; args: { - data: TraceEventArgsData & { + data: ArgsData & { viewport_rect: number[]; }; }; } -export interface TraceEventCommitLoad extends TraceEventInstant { +export interface CommitLoad extends Instant { name: 'CommitLoad'; - args: TraceEventArgs & { - data?: TraceEventArgsData & { + args: Args & { + data?: ArgsData & { frame: string; isMainFrame: boolean; name: string; @@ -598,10 +598,10 @@ export interface TraceEventCommitLoad extends TraceEventInstant { }; }; } -export interface TraceEventMarkDOMContent extends TraceEventInstant { +export interface MarkDOMContent extends Instant { name: 'MarkDOMContent'; - args: TraceEventArgs & { - data?: TraceEventArgsData & { + args: Args & { + data?: ArgsData & { frame: string; isMainFrame: boolean; isOutermostMainFrame?: boolean; @@ -609,10 +609,10 @@ export interface TraceEventMarkDOMContent extends TraceEventInstant { }; }; } -export interface TraceEventMarkLoad extends TraceEventInstant { +export interface MarkLoad extends Instant { name: 'MarkLoad'; - args: TraceEventArgs & { - data?: TraceEventArgsData & { + args: Args & { + data?: ArgsData & { frame: string; isMainFrame: boolean; page: string; @@ -620,7 +620,7 @@ export interface TraceEventMarkLoad extends TraceEventInstant { }; }; } -export interface TraceEventAsync extends TraceEventData { +export interface Async extends Event { ph: Phase.ASYNC_NESTABLE_START | Phase.ASYNC_NESTABLE_INSTANT | Phase.ASYNC_NESTABLE_END | Phase.ASYNC_STEP_INTO | Phase.ASYNC_BEGIN | Phase.ASYNC_END | Phase.ASYNC_STEP_PAST; } export type TraceRect = [number, number, number, number]; @@ -629,7 +629,7 @@ export type TraceImpactedNode = { node_id: Protocol.DOM.BackendNodeId; old_rect: TraceRect; }; -type LayoutShiftData = TraceEventArgsData & { +type LayoutShiftData = ArgsData & { cumulative_score: number; frame_max_distance: number; had_recent_input: boolean; @@ -641,10 +641,10 @@ type LayoutShiftData = TraceEventArgsData & { weighted_score_delta: number; navigationId?: string; }; -export interface TraceEventLayoutShift extends TraceEventInstant { +export interface LayoutShift extends Instant { name: 'LayoutShift'; normalized?: boolean; - args: TraceEventArgs & { + args: Args & { frame: string; data?: LayoutShiftData; }; @@ -659,13 +659,13 @@ export interface LayoutShiftParsedData { cumulativeWeightedScoreInWindow: number; sessionWindowData: LayoutShiftSessionWindowData; } -export interface SyntheticLayoutShift extends TraceEventLayoutShift, SyntheticBasedEvent { +export interface SyntheticLayoutShift extends LayoutShift, SyntheticBased { name: 'LayoutShift'; - rawSourceEvent: TraceEventLayoutShift; - args: TraceEventArgs & { + rawSourceEvent: LayoutShift; + args: Args & { frame: string; data?: LayoutShiftData & { - rawEvent: TraceEventLayoutShift; + rawEvent: LayoutShift; }; }; parsedData: LayoutShiftParsedData; @@ -685,7 +685,7 @@ export interface SyntheticLayoutShiftCluster { bad?: TraceWindowMicroSeconds; }; navigationId?: string; - worstShiftEvent?: TraceEventData; + worstShiftEvent?: Event; ts: MicroSeconds; dur?: MicroSeconds; cat: ''; @@ -702,10 +702,10 @@ export interface Initiator { lineNumber?: number; url?: string; } -export interface TraceEventResourceSendRequest extends TraceEventInstant { +export interface ResourceSendRequest extends Instant { name: 'ResourceSendRequest'; - args: TraceEventArgs & { - data: TraceEventArgsData & { + args: Args & { + data: ArgsData & { frame: string; requestId: string; url: string; @@ -719,27 +719,27 @@ export interface TraceEventResourceSendRequest extends TraceEventInstant { }; }; } -export interface TraceEventResourceChangePriority extends TraceEventInstant { +export interface ResourceChangePriority extends Instant { name: 'ResourceChangePriority'; - args: TraceEventArgs & { - data: TraceEventArgsData & { + args: Args & { + data: ArgsData & { requestId: string; priority: Protocol.Network.ResourcePriority; }; }; } -export interface TraceEventResourceWillSendRequest extends TraceEventInstant { +export interface ResourceWillSendRequest extends Instant { name: 'ResourceWillSendRequest'; - args: TraceEventArgs & { - data: TraceEventArgsData & { + args: Args & { + data: ArgsData & { requestId: string; }; }; } -export interface TraceEventResourceFinish extends TraceEventInstant { +export interface ResourceFinish extends Instant { name: 'ResourceFinish'; - args: TraceEventArgs & { - data: TraceEventArgsData & { + args: Args & { + data: ArgsData & { decodedBodyLength: number; didFail: boolean; encodedDataLength: number; @@ -748,17 +748,17 @@ export interface TraceEventResourceFinish extends TraceEventInstant { }; }; } -export interface TraceEventResourceReceivedData extends TraceEventInstant { +export interface ResourceReceivedData extends Instant { name: 'ResourceReceivedData'; - args: TraceEventArgs & { - data: TraceEventArgsData & { + args: Args & { + data: ArgsData & { encodedDataLength: number; frame: string; requestId: string; }; }; } -interface TraceEventResourceReceiveResponseTimingData { +interface ResourceReceiveResponseTimingData { connectEnd: MilliSeconds; connectStart: MilliSeconds; dnsEnd: MilliSeconds; @@ -777,10 +777,10 @@ interface TraceEventResourceReceiveResponseTimingData { workerReady: MilliSeconds; workerStart: MilliSeconds; } -export interface TraceEventResourceReceiveResponse extends TraceEventInstant { +export interface ResourceReceiveResponse extends Instant { name: 'ResourceReceiveResponse'; - args: TraceEventArgs & { - data: TraceEventArgsData & { + args: Args & { + data: ArgsData & { /** * This is the protocol used to resolve the request. * @@ -797,7 +797,7 @@ export interface TraceEventResourceReceiveResponse extends TraceEventInstant { requestId: string; responseTime: MilliSeconds; statusCode: number; - timing?: TraceEventResourceReceiveResponseTimingData; + timing?: ResourceReceiveResponseTimingData; connectionId: number; connectionReused: boolean; headers?: Array<{ @@ -807,10 +807,10 @@ export interface TraceEventResourceReceiveResponse extends TraceEventInstant { }; }; } -export interface TraceEventResourceMarkAsCached extends TraceEventInstant { +export interface ResourceMarkAsCached extends Instant { name: 'ResourceMarkAsCached'; - args: TraceEventArgs & { - data: TraceEventArgsData & { + args: Args & { + data: ArgsData & { requestId: string; }; }; @@ -825,10 +825,10 @@ export declare const enum LayoutInvalidationReason { FONTS_CHANGED = "Fonts changed", UNKNOWN = "Unknown" } -export interface TraceEventLayoutInvalidationTracking extends TraceEventInstant { - name: KnownEventName.LAYOUT_INVALIDATION_TRACKING; - args: TraceEventArgs & { - data: TraceEventArgsData & { +export interface LayoutInvalidationTracking extends Instant { + name: Name.LAYOUT_INVALIDATION_TRACKING; + args: Args & { + data: ArgsData & { frame: string; nodeId: Protocol.DOM.BackendNodeId; reason: LayoutInvalidationReason; @@ -836,10 +836,10 @@ export interface TraceEventLayoutInvalidationTracking extends TraceEventInstant }; }; } -export interface TraceEventScheduleStyleInvalidationTracking extends TraceEventInstant { - name: KnownEventName.SCHEDULE_STYLE_INVALIDATION_TRACKING; - args: TraceEventArgs & { - data: TraceEventArgsData & { +export interface ScheduleStyleInvalidationTracking extends Instant { + name: Name.SCHEDULE_STYLE_INVALIDATION_TRACKING; + args: Args & { + data: ArgsData & { frame: string; nodeId: Protocol.DOM.BackendNodeId; invalidationSet?: string; @@ -849,18 +849,18 @@ export interface TraceEventScheduleStyleInvalidationTracking extends TraceEventI changedAttribute?: string; changedId?: string; nodeName?: string; - stackTrace?: TraceEventCallFrame[]; + stackTrace?: CallFrame[]; }; }; } -export declare function isTraceEventScheduleStyleInvalidationTracking(event: TraceEventData): event is TraceEventScheduleStyleInvalidationTracking; +export declare function isScheduleStyleInvalidationTracking(event: Event): event is ScheduleStyleInvalidationTracking; export declare const enum StyleRecalcInvalidationReason { ANIMATION = "Animation" } -export interface TraceEventStyleRecalcInvalidationTracking extends TraceEventInstant { - name: KnownEventName.STYLE_RECALC_INVALIDATION_TRACKING; - args: TraceEventArgs & { - data: TraceEventArgsData & { +export interface StyleRecalcInvalidationTracking extends Instant { + name: Name.STYLE_RECALC_INVALIDATION_TRACKING; + args: Args & { + data: ArgsData & { frame: string; nodeId: Protocol.DOM.BackendNodeId; reason: StyleRecalcInvalidationReason; @@ -870,11 +870,11 @@ export interface TraceEventStyleRecalcInvalidationTracking extends TraceEventIns }; }; } -export declare function isTraceEventStyleRecalcInvalidationTracking(event: TraceEventData): event is TraceEventStyleRecalcInvalidationTracking; -export interface TraceEventStyleInvalidatorInvalidationTracking extends TraceEventInstant { - name: KnownEventName.STYLE_INVALIDATOR_INVALIDATION_TRACKING; - args: TraceEventArgs & { - data: TraceEventArgsData & { +export declare function isStyleRecalcInvalidationTracking(event: Event): event is StyleRecalcInvalidationTracking; +export interface StyleInvalidatorInvalidationTracking extends Instant { + name: Name.STYLE_INVALIDATOR_INVALIDATION_TRACKING; + args: Args & { + data: ArgsData & { frame: string; nodeId: Protocol.DOM.BackendNodeId; reason: string; @@ -888,47 +888,47 @@ export interface TraceEventStyleInvalidatorInvalidationTracking extends TraceEve }; }; } -export declare function isTraceEventStyleInvalidatorInvalidationTracking(event: TraceEventData): event is TraceEventStyleInvalidatorInvalidationTracking; -export interface TraceEventBeginCommitCompositorFrame extends TraceEventInstant { - name: KnownEventName.BEGIN_COMMIT_COMPOSITOR_FRAME; - args: TraceEventArgs & { +export declare function isStyleInvalidatorInvalidationTracking(event: Event): event is StyleInvalidatorInvalidationTracking; +export interface BeginCommitCompositorFrame extends Instant { + name: Name.BEGIN_COMMIT_COMPOSITOR_FRAME; + args: Args & { frame: string; is_mobile_optimized: boolean; }; } -export declare function isTraceEventBeginCommitCompositorFrame(event: TraceEventData): event is TraceEventBeginCommitCompositorFrame; -export interface TraceEventParseMetaViewport extends TraceEventInstant { - name: KnownEventName.PARSE_META_VIEWPORT; - args: TraceEventArgs & { +export declare function isBeginCommitCompositorFrame(event: Event): event is BeginCommitCompositorFrame; +export interface ParseMetaViewport extends Instant { + name: Name.PARSE_META_VIEWPORT; + args: Args & { data: { - frame: string; node_id: Protocol.DOM.BackendNodeId; content: string; + frame?: string; }; }; } -export declare function isTraceEventParseMetaViewport(event: TraceEventData): event is TraceEventParseMetaViewport; -export interface TraceEventScheduleStyleRecalculation extends TraceEventInstant { - name: KnownEventName.SCHEDULE_STYLE_RECALCULATION; - args: TraceEventArgs & { +export declare function isParseMetaViewport(event: Event): event is ParseMetaViewport; +export interface ScheduleStyleRecalculation extends Instant { + name: Name.SCHEDULE_STYLE_RECALCULATION; + args: Args & { data: { frame: string; }; }; } -export declare function isTraceEventScheduleStyleRecalculation(event: TraceEventData): event is TraceEventScheduleStyleRecalculation; -export interface TraceEventRenderFrameImplCreateChildFrame extends TraceEventData { - name: KnownEventName.RENDER_FRAME_IMPL_CREATE_CHILD_FRAME; - args: TraceEventArgs & { +export declare function isScheduleStyleRecalculation(event: Event): event is ScheduleStyleRecalculation; +export interface RenderFrameImplCreateChildFrame extends Event { + name: Name.RENDER_FRAME_IMPL_CREATE_CHILD_FRAME; + args: Args & { child_frame_token: string; frame_token: string; }; } -export declare function isTraceEventRenderFrameImplCreateChildFrame(event: TraceEventData): event is TraceEventRenderFrameImplCreateChildFrame; -export interface TraceEventPrePaint extends TraceEventComplete { +export declare function isRenderFrameImplCreateChildFrame(event: Event): event is RenderFrameImplCreateChildFrame; +export interface PrePaint extends Complete { name: 'PrePaint'; } -export interface TraceEventPairableAsync extends TraceEventData { +export interface PairableAsync extends Event { ph: Phase.ASYNC_NESTABLE_START | Phase.ASYNC_NESTABLE_END | Phase.ASYNC_NESTABLE_INSTANT; id2?: { local?: string; @@ -936,16 +936,16 @@ export interface TraceEventPairableAsync extends TraceEventData { }; id?: string; } -export interface TraceEventPairableAsyncBegin extends TraceEventPairableAsync { +export interface PairableAsyncBegin extends PairableAsync { ph: Phase.ASYNC_NESTABLE_START; } -export interface TraceEventPairableAsyncInstant extends TraceEventPairableAsync { +export interface PairableAsyncInstant extends PairableAsync { ph: Phase.ASYNC_NESTABLE_INSTANT; } -export interface TraceEventPairableAsyncEnd extends TraceEventPairableAsync { +export interface PairableAsyncEnd extends PairableAsync { ph: Phase.ASYNC_NESTABLE_END; } -export interface TraceEventUserTiming extends TraceEventData { +export interface UserTiming extends Event { id2?: { local?: string; global?: string; @@ -953,99 +953,57 @@ export interface TraceEventUserTiming extends TraceEventData { id?: string; cat: 'blink.user_timing'; } -export interface TraceEventDomLoading extends TraceEventUserTiming { - name: KnownEventName.DOM_LOADING; - args: TraceEventArgs & { +export interface DomLoading extends UserTiming { + name: Name.DOM_LOADING; + args: Args & { frame?: string; }; } -export type TraceEventPairableUserTiming = TraceEventUserTiming & TraceEventPairableAsync; -export interface TraceEventPerformanceMeasureBegin extends TraceEventPairableUserTiming { - args: TraceEventArgs & { +export interface BeginRemoteFontLoad extends UserTiming { + name: Name.BEGIN_REMOTE_FONT_LOAD; + args: Args & { + display: string; + id: number; + }; +} +export type PairableUserTiming = UserTiming & PairableAsync; +export interface PerformanceMeasureBegin extends PairableUserTiming { + args: Args & { detail?: string; - stackTrace?: TraceEventCallFrame[]; + stackTrace?: CallFrame[]; }; ph: Phase.ASYNC_NESTABLE_START; } -export type TraceEventPerformanceMeasureEnd = TraceEventPairableUserTiming & TraceEventPairableAsyncEnd; -export type TraceEventPerformanceMeasure = TraceEventPerformanceMeasureBegin | TraceEventPerformanceMeasureEnd; -export interface TraceEventPerformanceMark extends TraceEventUserTiming { - args: TraceEventArgs & { - data?: TraceEventArgsData & { +export type PerformanceMeasureEnd = PairableUserTiming & PairableAsyncEnd; +export type PerformanceMeasure = PerformanceMeasureBegin | PerformanceMeasureEnd; +export interface PerformanceMark extends UserTiming { + args: Args & { + data?: ArgsData & { detail?: string; - stackTrace?: TraceEventCallFrame[]; + stackTrace?: CallFrame[]; }; }; ph: Phase.INSTANT | Phase.MARK | Phase.ASYNC_NESTABLE_INSTANT; } -export interface TraceEventConsoleTimeBegin extends TraceEventPairableAsyncBegin { +export interface ConsoleTimeBegin extends PairableAsyncBegin { cat: 'blink.console'; } -export interface TraceEventConsoleTimeEnd extends TraceEventPairableAsyncEnd { +export interface ConsoleTimeEnd extends PairableAsyncEnd { cat: 'blink.console'; } -export type TraceEventConsoleTime = TraceEventConsoleTimeBegin | TraceEventConsoleTimeEnd; -export interface TraceEventTimeStamp extends TraceEventData { +export type ConsoleTime = ConsoleTimeBegin | ConsoleTimeEnd; +export interface TimeStamp extends Event { cat: 'devtools.timeline'; name: 'TimeStamp'; ph: Phase.INSTANT; id: string; - args: TraceEventArgs & { - data: TraceEventArgsData & { + args: Args & { + data: ArgsData & { frame: string; message: string; }; }; } -export interface TraceEventTargetRundown extends TraceEventData { - cat: 'disabled-by-default-devtools.target-rundown'; - args: TraceEventArgs & { - data: TraceEventArgsData & { - frame: string; - frameType: string; - url: string; - isolate: string; - v8context: string; - origin: string; - scriptId: number; - isDefault?: boolean; - contextType?: string; - }; - }; -} -export declare function isTraceEventTargetRundown(traceEventData: TraceEventData): traceEventData is TraceEventTargetRundown; -export interface TraceEventScriptRundown extends TraceEventData { - cat: 'disabled-by-default-devtools.v8-source-rundown'; - args: TraceEventArgs & { - data: TraceEventArgsData & { - isolate: string; - executionContextId: number; - scriptId: number; - startLine: number; - startColumn: number; - endLine: number; - endColumn: number; - url: string; - hash: string; - isModule: boolean; - hasSourceUrl: boolean; - sourceMapUrl?: string; - }; - }; -} -export declare function isTraceEventScriptRundown(traceEventData: TraceEventData): traceEventData is TraceEventScriptRundown; -export interface TraceEventScriptRundownSource extends TraceEventData { - cat: 'disabled-by-default-devtools.v8-source-rundown-sources'; - args: TraceEventArgs & { - data: TraceEventArgsData & { - isolate: string; - scriptId: number; - length?: number; - sourceText?: string; - }; - }; -} -export declare function isTraceEventScriptRundownSource(traceEventData: TraceEventData): traceEventData is TraceEventScriptRundownSource; /** ChromeFrameReporter args for PipelineReporter event. Matching proto: https://source.chromium.org/chromium/chromium/src/+/main:third_party/perfetto/protos/perfetto/trace/track_event/chrome_frame_reporter.proto */ @@ -1124,24 +1082,24 @@ declare const enum FrameType { FORKED = "FORKED", BACKFILL = "BACKFILL" } -export interface TraceEventPipelineReporter extends TraceEventData { +export interface PipelineReporter extends Event { id2?: { local?: string; }; ph: Phase.ASYNC_NESTABLE_START | Phase.ASYNC_NESTABLE_END; - args: TraceEventArgs & { + args: Args & { chrome_frame_reporter: ChromeFrameReporter; }; } -export declare function isTraceEventPipelineReporter(event: TraceEventData): event is TraceEventPipelineReporter; -export interface SyntheticBasedEvent extends TraceEventData { +export declare function isPipelineReporter(event: Event): event is PipelineReporter; +export interface SyntheticBased extends Event { ph: Ph; - rawSourceEvent: TraceEventData; + rawSourceEvent: Event; _tag: 'SyntheticEntryTag'; } -export declare function isSyntheticBasedEvent(event: TraceEventData): event is SyntheticBasedEvent; -export interface SyntheticEventPair extends SyntheticBasedEvent { - rawSourceEvent: TraceEventData; +export declare function isSyntheticBased(event: Event): event is SyntheticBased; +export interface SyntheticEventPair extends SyntheticBased { + rawSourceEvent: Event; name: T['name']; cat: T['cat']; id?: string; @@ -1150,19 +1108,19 @@ export interface SyntheticEventPair; + beginEvent: T & PairableAsyncBegin; + endEvent: T & PairableAsyncEnd; + instantEvents?: Array; }; }; } -export type SyntheticPipelineReporterPair = SyntheticEventPair; -export type SyntheticUserTimingPair = SyntheticEventPair; -export type SyntheticConsoleTimingPair = SyntheticEventPair; -export type SyntheticAnimationPair = SyntheticEventPair; -export interface SyntheticInteractionPair extends SyntheticEventPair { +export type SyntheticPipelineReporterPair = SyntheticEventPair; +export type SyntheticUserTimingPair = SyntheticEventPair; +export type SyntheticConsoleTimingPair = SyntheticEventPair; +export type SyntheticAnimationPair = SyntheticEventPair; +export interface SyntheticInteractionPair extends SyntheticEventPair { interactionId: number; type: string; ts: MicroSeconds; @@ -1185,7 +1143,7 @@ export interface SyntheticInteractionPair extends SyntheticEventPair extends SyntheticBasedEvent { - rawSourceEvent: TraceEventResourceSendRequest; +export interface SyntheticServerTiming extends SyntheticBased { + rawSourceEvent: ResourceSendRequest; cat: 'devtools.server-timing'; - args: TraceEventArgs & { - data: TraceEventArgsData & { + args: Args & { + data: ArgsData & { desc?: string; origin: string; }; @@ -1213,88 +1171,88 @@ export interface SyntheticServerTiming extends /** * A JS Sample reflects a single sample from the V8 CPU Profile */ -export interface SyntheticJSSample extends TraceEventData { - name: KnownEventName.JS_SAMPLE; - args: TraceEventArgs & { - data: TraceEventArgsData & { +export interface SyntheticJSSample extends Event { + name: Name.JS_SAMPLE; + args: Args & { + data: ArgsData & { stackTrace: Protocol.Runtime.CallFrame[]; }; }; ph: Phase.INSTANT; } -export declare function isSyntheticInteractionEvent(event: TraceEventData): event is SyntheticInteractionPair; -export interface TraceEventDrawFrame extends TraceEventInstant { - name: KnownEventName.DRAW_FRAME; - args: TraceEventArgs & { +export declare function isSyntheticInteraction(event: Event): event is SyntheticInteractionPair; +export interface DrawFrame extends Instant { + name: Name.DRAW_FRAME; + args: Args & { layerTreeId: number; frameSeqId: number; }; } -export declare function isTraceEventDrawFrame(event: TraceEventData): event is TraceEventDrawFrame; -export interface TraceEventLegacyDrawFrameBegin extends TraceEventAsync { - name: KnownEventName.DRAW_FRAME; +export declare function isDrawFrame(event: Event): event is DrawFrame; +export interface LegacyDrawFrameBegin extends Async { + name: Name.DRAW_FRAME; ph: Phase.ASYNC_NESTABLE_START; - args: TraceEventArgs & { + args: Args & { layerTreeId: number; frameSeqId: number; }; } -export declare function isLegacyTraceEventDrawFrameBegin(event: TraceEventData): event is TraceEventLegacyDrawFrameBegin; -export interface TraceEventBeginFrame extends TraceEventInstant { - name: KnownEventName.BEGIN_FRAME; - args: TraceEventArgs & { +export declare function isLegacyTraceEventDrawFrameBegin(event: Event): event is LegacyDrawFrameBegin; +export interface BeginFrame extends Instant { + name: Name.BEGIN_FRAME; + args: Args & { layerTreeId: number; frameSeqId: number; }; } -export declare function isTraceEventBeginFrame(event: TraceEventData): event is TraceEventBeginFrame; -export interface TraceEventDroppedFrame extends TraceEventInstant { - name: KnownEventName.DROPPED_FRAME; - args: TraceEventArgs & { +export declare function isBeginFrame(event: Event): event is BeginFrame; +export interface DroppedFrame extends Instant { + name: Name.DROPPED_FRAME; + args: Args & { layerTreeId: number; frameSeqId: number; hasPartialUpdate?: boolean; }; } -export declare function isTraceEventDroppedFrame(event: TraceEventData): event is TraceEventDroppedFrame; -export interface TraceEventRequestMainThreadFrame extends TraceEventInstant { - name: KnownEventName.REQUEST_MAIN_THREAD_FRAME; - args: TraceEventArgs & { +export declare function isDroppedFrame(event: Event): event is DroppedFrame; +export interface RequestMainThreadFrame extends Instant { + name: Name.REQUEST_MAIN_THREAD_FRAME; + args: Args & { layerTreeId: number; }; } -export declare function isTraceEventRequestMainThreadFrame(event: TraceEventData): event is TraceEventRequestMainThreadFrame; -export interface TraceEventBeginMainThreadFrame extends TraceEventInstant { - name: KnownEventName.BEGIN_MAIN_THREAD_FRAME; - args: TraceEventArgs & { +export declare function isRequestMainThreadFrame(event: Event): event is RequestMainThreadFrame; +export interface BeginMainThreadFrame extends Instant { + name: Name.BEGIN_MAIN_THREAD_FRAME; + args: Args & { layerTreeId: number; - data: TraceEventArgsData & { + data: ArgsData & { frameId?: number; }; }; } -export declare function isTraceEventBeginMainThreadFrame(event: TraceEventData): event is TraceEventBeginMainThreadFrame; -export interface TraceEventNeedsBeginFrameChanged extends TraceEventInstant { - name: KnownEventName.NEEDS_BEGIN_FRAME_CHANGED; - args: TraceEventArgs & { +export declare function isBeginMainThreadFrame(event: Event): event is BeginMainThreadFrame; +export interface NeedsBeginFrameChanged extends Instant { + name: Name.NEEDS_BEGIN_FRAME_CHANGED; + args: Args & { layerTreeId: number; - data: TraceEventArgsData & { + data: ArgsData & { needsBeginFrame: number; }; }; } -export declare function isTraceEventNeedsBeginFrameChanged(event: TraceEventData): event is TraceEventNeedsBeginFrameChanged; -export interface TraceEventCommit extends TraceEventInstant { - name: KnownEventName.COMMIT; - args: TraceEventArgs & { +export declare function isNeedsBeginFrameChanged(event: Event): event is NeedsBeginFrameChanged; +export interface Commit extends Instant { + name: Name.COMMIT; + args: Args & { layerTreeId: number; frameSeqId: number; }; } -export declare function isTraceEventCommit(event: TraceEventData): event is TraceEventCommit; -export interface TraceEventRasterTask extends TraceEventComplete { - name: KnownEventName.RASTER_TASK; - args: TraceEventArgs & { +export declare function isCommit(event: Event): event is Commit; +export interface RasterTask extends Complete { + name: Name.RASTER_TASK; + args: Args & { tileData?: { layerId: number; sourceFrameNumber: number; @@ -1305,45 +1263,45 @@ export interface TraceEventRasterTask extends TraceEventComplete { }; }; } -export declare function isTraceEventRasterTask(event: TraceEventData): event is TraceEventRasterTask; -export interface TraceEventCompositeLayers extends TraceEventInstant { - name: KnownEventName.COMPOSITE_LAYERS; - args: TraceEventArgs & { +export declare function isRasterTask(event: Event): event is RasterTask; +export interface CompositeLayers extends Instant { + name: Name.COMPOSITE_LAYERS; + args: Args & { layerTreeId: number; }; } -export declare function isTraceEventCompositeLayers(event: TraceEventData): event is TraceEventCompositeLayers; -export interface TraceEventActivateLayerTree extends TraceEventInstant { - name: KnownEventName.ACTIVATE_LAYER_TREE; - args: TraceEventArgs & { +export declare function isCompositeLayers(event: Event): event is CompositeLayers; +export interface ActivateLayerTree extends Instant { + name: Name.ACTIVATE_LAYER_TREE; + args: Args & { layerTreeId: number; frameId: number; }; } -export declare function isTraceEventActivateLayerTree(event: TraceEventData): event is TraceEventActivateLayerTree; -export type InvalidationTrackingEvent = TraceEventScheduleStyleInvalidationTracking | TraceEventStyleRecalcInvalidationTracking | TraceEventStyleInvalidatorInvalidationTracking | TraceEventLayoutInvalidationTracking; -export declare function isTraceEventInvalidationTracking(event: TraceEventData): event is InvalidationTrackingEvent; -export interface TraceEventDrawLazyPixelRef extends TraceEventInstant { - name: KnownEventName.DRAW_LAZY_PIXEL_REF; - args?: TraceEventArgs & { +export declare function isActivateLayerTree(event: Event): event is ActivateLayerTree; +export type InvalidationTrackingEvent = ScheduleStyleInvalidationTracking | StyleRecalcInvalidationTracking | StyleInvalidatorInvalidationTracking | LayoutInvalidationTracking; +export declare function isInvalidationTracking(event: Event): event is InvalidationTrackingEvent; +export interface DrawLazyPixelRef extends Instant { + name: Name.DRAW_LAZY_PIXEL_REF; + args?: Args & { LazyPixelRef: number; }; } -export declare function isTraceEventDrawLazyPixelRef(event: TraceEventData): event is TraceEventDrawLazyPixelRef; -export interface TraceEventDecodeLazyPixelRef extends TraceEventInstant { - name: KnownEventName.DECODE_LAZY_PIXEL_REF; - args?: TraceEventArgs & { +export declare function isDrawLazyPixelRef(event: Event): event is DrawLazyPixelRef; +export interface DecodeLazyPixelRef extends Instant { + name: Name.DECODE_LAZY_PIXEL_REF; + args?: Args & { LazyPixelRef: number; }; } -export declare function isTraceEventDecodeLazyPixelRef(event: TraceEventData): event is TraceEventDecodeLazyPixelRef; -export interface TraceEventDecodeImage extends TraceEventComplete { - name: KnownEventName.DECODE_IMAGE; - args: TraceEventArgs & { +export declare function isDecodeLazyPixelRef(event: Event): event is DecodeLazyPixelRef; +export interface DecodeImage extends Complete { + name: Name.DECODE_IMAGE; + args: Args & { imageType: string; }; } -export declare function isTraceEventDecodeImage(event: TraceEventData): event is TraceEventDecodeImage; +export declare function isDecodeImage(event: Event): event is DecodeImage; export interface SelectorTiming { 'elapsed (us)': number; 'fast_reject_count': number; @@ -1364,27 +1322,27 @@ export declare enum SelectorTimingsKey { export interface SelectorStats { selector_timings: SelectorTiming[]; } -export interface TraceEventSelectorStats extends TraceEventComplete { - name: KnownEventName.SELECTOR_STATS; - args: TraceEventArgs & { +export interface SelectorStats extends Complete { + name: Name.SELECTOR_STATS; + args: Args & { selector_stats?: SelectorStats; }; } -export declare function isTraceEventSelectorStats(event: TraceEventData): event is TraceEventSelectorStats; -export interface TraceEventUpdateLayoutTree extends TraceEventComplete { - name: KnownEventName.UPDATE_LAYOUT_TREE; - args: TraceEventArgs & { +export declare function isSelectorStats(event: Event): event is SelectorStats; +export interface UpdateLayoutTree extends Complete { + name: Name.UPDATE_LAYOUT_TREE; + args: Args & { elementCount: number; beginData?: { frame: string; - stackTrace?: TraceEventCallFrame[]; + stackTrace?: CallFrame[]; }; }; } -export declare function isTraceEventUpdateLayoutTree(event: TraceEventData): event is TraceEventUpdateLayoutTree; -export interface TraceEventLayout extends TraceEventComplete { - name: KnownEventName.LAYOUT; - args: TraceEventArgs & { +export declare function isUpdateLayoutTree(event: Event): event is UpdateLayoutTree; +export interface Layout extends Complete { + name: Name.LAYOUT; + args: Args & { beginData: { frame: string; dirtyObjects: number; @@ -1400,17 +1358,17 @@ export interface TraceEventLayout extends TraceEventComplete { }; }; } -export declare function isTraceEventLayout(event: TraceEventData): event is TraceEventLayout; -export interface TraceEventInvalidateLayout extends TraceEventInstant { - name: KnownEventName.INVALIDATE_LAYOUT; - args: TraceEventArgs & { +export declare function isLayout(event: Event): event is Layout; +export interface InvalidateLayout extends Instant { + name: Name.INVALIDATE_LAYOUT; + args: Args & { data: { frame: string; nodeId: Protocol.DOM.BackendNodeId; }; }; } -export declare function isTraceEventInvalidateLayout(event: TraceEventData): event is TraceEventInvalidateLayout; +export declare function isInvalidateLayout(event: Event): event is InvalidateLayout; declare class ProfileIdTag { #private; } @@ -1441,73 +1399,74 @@ declare class WorkerIdTag { } export type WorkerId = string & WorkerIdTag; export declare function WorkerId(value: string): WorkerId; -export declare function isTraceEventComplete(event: TraceEventData): event is TraceEventComplete; -export declare function isTraceEventBegin(event: TraceEventData): event is TraceEventBegin; -export declare function isTraceEventEnd(event: TraceEventData): event is TraceEventEnd; -export declare function isTraceEventDispatch(event: TraceEventData): event is TraceEventDispatch; -export declare function isTraceEventInstant(event: TraceEventData): event is TraceEventInstant; -export declare function isTraceEventRendererEvent(event: TraceEventData): event is TraceEventRendererEvent; -export declare function isTraceEventFireIdleCallback(event: TraceEventData): event is TraceEventFireIdleCallback; -export declare function isTraceEventSchedulePostMessage(event: TraceEventData): event is TraceEventSchedulePostMessage; -export declare function isTraceEventHandlePostMessage(event: TraceEventData): event is TraceEventHandlePostMessage; -export declare function isTraceEventUpdateCounters(event: TraceEventData): event is TraceEventUpdateCounters; -export declare function isThreadName(traceEventData: TraceEventData): traceEventData is TraceEventThreadName; -export declare function isProcessName(traceEventData: TraceEventData): traceEventData is TraceEventProcessName; -export declare function isTraceEventTracingStartedInBrowser(traceEventData: TraceEventData): traceEventData is TraceEventTracingStartedInBrowser; -export declare function isTraceEventFrameCommittedInBrowser(traceEventData: TraceEventData): traceEventData is TraceEventFrameCommittedInBrowser; -export declare function isTraceEventCommitLoad(traceEventData: TraceEventData): traceEventData is TraceEventCommitLoad; -export declare function isTraceEventNavigationStart(traceEventData: TraceEventData): traceEventData is TraceEventNavigationStart; -export declare function isTraceEventAnimation(traceEventData: TraceEventData): traceEventData is TraceEventAnimation; -export declare function isTraceEventLayoutShift(traceEventData: TraceEventData): traceEventData is TraceEventLayoutShift; -export declare function isTraceEventLayoutInvalidationTracking(traceEventData: TraceEventData): traceEventData is TraceEventLayoutInvalidationTracking; -export declare function isTraceEventFirstContentfulPaint(traceEventData: TraceEventData): traceEventData is TraceEventFirstContentfulPaint; -export declare function isTraceEventLargestContentfulPaintCandidate(traceEventData: TraceEventData): traceEventData is TraceEventLargestContentfulPaintCandidate; -export declare function isTraceEventLargestImagePaintCandidate(traceEventData: TraceEventData): traceEventData is TraceEventLargestImagePaintCandidate; -export declare function isTraceEventLargestTextPaintCandidate(traceEventData: TraceEventData): traceEventData is TraceEventLargestTextPaintCandidate; -export declare function isTraceEventMarkLoad(traceEventData: TraceEventData): traceEventData is TraceEventMarkLoad; -export declare function isTraceEventFirstPaint(traceEventData: TraceEventData): traceEventData is TraceEventFirstPaint; -export declare function isTraceEventMarkDOMContent(traceEventData: TraceEventData): traceEventData is TraceEventMarkDOMContent; -export declare function isTraceEventInteractiveTime(traceEventData: TraceEventData): traceEventData is TraceEventInteractiveTime; -export declare function isTraceEventEventTiming(traceEventData: TraceEventData): traceEventData is TraceEventEventTiming; -export declare function isTraceEventEventTimingEnd(traceEventData: TraceEventData): traceEventData is TraceEventEventTimingEnd; -export declare function isTraceEventEventTimingStart(traceEventData: TraceEventData): traceEventData is TraceEventEventTimingBegin; -export declare function isTraceEventGPUTask(traceEventData: TraceEventData): traceEventData is TraceEventGPUTask; -export declare function isTraceEventProfile(traceEventData: TraceEventData): traceEventData is TraceEventProfile; -export declare function isSyntheticCpuProfile(traceEventData: TraceEventData): traceEventData is SyntheticCpuProfile; -export declare function isTraceEventProfileChunk(traceEventData: TraceEventData): traceEventData is TraceEventProfileChunk; -export declare function isTraceEventResourceChangePriority(traceEventData: TraceEventData): traceEventData is TraceEventResourceChangePriority; -export declare function isTraceEventResourceSendRequest(traceEventData: TraceEventData): traceEventData is TraceEventResourceSendRequest; -export declare function isTraceEventResourceReceiveResponse(traceEventData: TraceEventData): traceEventData is TraceEventResourceReceiveResponse; -export declare function isTraceEventResourceMarkAsCached(traceEventData: TraceEventData): traceEventData is TraceEventResourceMarkAsCached; -export declare function isTraceEventResourceFinish(traceEventData: TraceEventData): traceEventData is TraceEventResourceFinish; -export declare function isTraceEventResourceWillSendRequest(traceEventData: TraceEventData): traceEventData is TraceEventResourceWillSendRequest; -export declare function isTraceEventResourceReceivedData(traceEventData: TraceEventData): traceEventData is TraceEventResourceReceivedData; -export declare function isSyntheticNetworkRequestEvent(traceEventData: TraceEventData): traceEventData is SyntheticNetworkRequest; -export declare function isSyntheticWebSocketConnectionEvent(traceEventData: TraceEventData): traceEventData is SyntheticWebSocketConnectionEvent; -export declare function isNetworkTrackEntry(traceEventData: TraceEventData): traceEventData is SyntheticWebSocketConnectionEvent | SyntheticNetworkRequest; -export declare function isTraceEventPrePaint(traceEventData: TraceEventData): traceEventData is TraceEventPrePaint; -export declare function isTraceEventNavigationStartWithURL(event: TraceEventData): event is TraceEventNavigationStart; -export declare function isTraceEventMainFrameViewport(traceEventData: TraceEventData): traceEventData is TraceEventMainFrameViewport; -export declare function isSyntheticUserTiming(traceEventData: TraceEventData): traceEventData is SyntheticUserTimingPair; -export declare function isSyntheticConsoleTiming(traceEventData: TraceEventData): traceEventData is SyntheticConsoleTimingPair; -export declare function isTraceEventUserTiming(traceEventData: TraceEventData): traceEventData is TraceEventUserTiming; -export declare function isTraceEventDomLoading(traceEventData: TraceEventData): traceEventData is TraceEventDomLoading; -export declare function isTraceEventPerformanceMeasure(traceEventData: TraceEventData): traceEventData is TraceEventPerformanceMeasure; -export declare function isTraceEventPerformanceMark(traceEventData: TraceEventData): traceEventData is TraceEventPerformanceMark; -export declare function isTraceEventConsoleTime(traceEventData: TraceEventData): traceEventData is TraceEventConsoleTime; -export declare function isTraceEventTimeStamp(traceEventData: TraceEventData): traceEventData is TraceEventTimeStamp; -export declare function isTraceEventParseHTML(traceEventData: TraceEventData): traceEventData is TraceEventParseHTML; -export interface TraceEventAsync extends TraceEventData { +export declare function isComplete(event: Event): event is Complete; +export declare function isBegin(event: Event): event is Begin; +export declare function isEnd(event: Event): event is End; +export declare function isDispatch(event: Event): event is Dispatch; +export declare function isInstant(event: Event): event is Instant; +export declare function isRendererEvent(event: Event): event is RendererEvent; +export declare function isFireIdleCallback(event: Event): event is FireIdleCallback; +export declare function isSchedulePostMessage(event: Event): event is SchedulePostMessage; +export declare function isHandlePostMessage(event: Event): event is HandlePostMessage; +export declare function isUpdateCounters(event: Event): event is UpdateCounters; +export declare function isThreadName(event: Event): event is ThreadName; +export declare function isProcessName(event: Event): event is ProcessName; +export declare function isTracingStartedInBrowser(event: Event): event is TracingStartedInBrowser; +export declare function isFrameCommittedInBrowser(event: Event): event is FrameCommittedInBrowser; +export declare function isCommitLoad(event: Event): event is CommitLoad; +export declare function isNavigationStart(event: Event): event is NavigationStart; +export declare function isAnimation(event: Event): event is Animation; +export declare function isSyntheticAnimation(event: Event): event is SyntheticAnimationPair; +export declare function isLayoutShift(event: Event): event is LayoutShift; +export declare function isLayoutInvalidationTracking(event: Event): event is LayoutInvalidationTracking; +export declare function isFirstContentfulPaint(event: Event): event is FirstContentfulPaint; +export declare function isLargestContentfulPaintCandidate(event: Event): event is LargestContentfulPaintCandidate; +export declare function isLargestImagePaintCandidate(event: Event): event is LargestImagePaintCandidate; +export declare function isLargestTextPaintCandidate(event: Event): event is LargestTextPaintCandidate; +export declare function isMarkLoad(event: Event): event is MarkLoad; +export declare function isFirstPaint(event: Event): event is FirstPaint; +export declare function isMarkDOMContent(event: Event): event is MarkDOMContent; +export declare function isInteractiveTime(event: Event): event is InteractiveTime; +export declare function isEventTiming(event: Event): event is EventTiming; +export declare function isEventTimingEnd(event: Event): event is EventTimingEnd; +export declare function isEventTimingStart(event: Event): event is EventTimingBegin; +export declare function isGPUTask(event: Event): event is GPUTask; +export declare function isProfile(event: Event): event is Profile; +export declare function isSyntheticCpuProfile(event: Event): event is SyntheticCpuProfile; +export declare function isProfileChunk(event: Event): event is ProfileChunk; +export declare function isResourceChangePriority(event: Event): event is ResourceChangePriority; +export declare function isResourceSendRequest(event: Event): event is ResourceSendRequest; +export declare function isResourceReceiveResponse(event: Event): event is ResourceReceiveResponse; +export declare function isResourceMarkAsCached(event: Event): event is ResourceMarkAsCached; +export declare function isResourceFinish(event: Event): event is ResourceFinish; +export declare function isResourceWillSendRequest(event: Event): event is ResourceWillSendRequest; +export declare function isResourceReceivedData(event: Event): event is ResourceReceivedData; +export declare function isSyntheticNetworkRequest(event: Event): event is SyntheticNetworkRequest; +export declare function isSyntheticWebSocketConnection(event: Event): event is SyntheticWebSocketConnection; +export declare function isNetworkTrackEntry(event: Event): event is SyntheticWebSocketConnection | SyntheticNetworkRequest; +export declare function isPrePaint(event: Event): event is PrePaint; +export declare function isNavigationStartWithURL(event: Event): event is NavigationStart; +export declare function isMainFrameViewport(event: Event): event is MainFrameViewport; +export declare function isSyntheticUserTiming(event: Event): event is SyntheticUserTimingPair; +export declare function isSyntheticConsoleTiming(event: Event): event is SyntheticConsoleTimingPair; +export declare function isUserTiming(event: Event): event is UserTiming; +export declare function isDomLoading(event: Event): event is DomLoading; +export declare function isBeginRemoteFontLoad(event: Event): event is BeginRemoteFontLoad; +export declare function isPerformanceMeasure(event: Event): event is PerformanceMeasure; +export declare function isPerformanceMark(event: Event): event is PerformanceMark; +export declare function isConsoleTime(event: Event): event is ConsoleTime; +export declare function isTimeStamp(event: Event): event is TimeStamp; +export declare function isParseHTML(event: Event): event is ParseHTML; +export interface Async extends Event { ph: Phase.ASYNC_NESTABLE_START | Phase.ASYNC_NESTABLE_INSTANT | Phase.ASYNC_NESTABLE_END | Phase.ASYNC_STEP_INTO | Phase.ASYNC_BEGIN | Phase.ASYNC_END | Phase.ASYNC_STEP_PAST; } -export declare function isTraceEventAsyncPhase(traceEventData: TraceEventData): boolean; -export declare function isSyntheticLayoutShift(traceEventData: TraceEventData): traceEventData is SyntheticLayoutShift; -export declare function isSyntheticLayoutShiftCluster(traceEventData: TraceEventData): traceEventData is SyntheticLayoutShiftCluster; -export declare function isProfileCall(event: TraceEventData): event is SyntheticProfileCall; -export interface TraceEventPaint extends TraceEventComplete { - name: KnownEventName.PAINT; - args: TraceEventArgs & { - data: TraceEventArgsData & { +export declare function isSyntheticLayoutShift(event: Event): event is SyntheticLayoutShift; +export declare function isSyntheticLayoutShiftCluster(event: Event): event is SyntheticLayoutShiftCluster; +export declare function isProfileCall(event: Event): event is SyntheticProfileCall; +export interface Paint extends Complete { + name: Name.PAINT; + args: Args & { + data: ArgsData & { clip: number[]; frame: string; layerId: number; @@ -1515,11 +1474,11 @@ export interface TraceEventPaint extends TraceEventComplete { }; }; } -export declare function isTraceEventPaint(event: TraceEventData): event is TraceEventPaint; -export interface TraceEventPaintImage extends TraceEventComplete { - name: KnownEventName.PAINT_IMAGE; - args: TraceEventArgs & { - data: TraceEventData & { +export declare function isPaint(event: Event): event is Paint; +export interface PaintImage extends Complete { + name: Name.PAINT_IMAGE; + args: Args & { + data: Event & { height: number; width: number; x: number; @@ -1531,42 +1490,42 @@ export interface TraceEventPaintImage extends TraceEventComplete { }; }; } -export declare function isTraceEventPaintImage(event: TraceEventData): event is TraceEventPaintImage; -export interface TraceEventScrollLayer extends TraceEventComplete { - name: KnownEventName.SCROLL_LAYER; - args: TraceEventArgs & { - data: TraceEventData & { +export declare function isPaintImage(event: Event): event is PaintImage; +export interface ScrollLayer extends Complete { + name: Name.SCROLL_LAYER; + args: Args & { + data: Event & { frame: string; nodeId?: Protocol.DOM.BackendNodeId; }; }; } -export declare function isTraceEventScrollLayer(event: TraceEventData): event is TraceEventScrollLayer; -export interface TraceEventSetLayerTreeId extends TraceEventInstant { - name: KnownEventName.SET_LAYER_TREE_ID; - args: TraceEventArgs & { - data: TraceEventArgsData & { +export declare function isScrollLayer(event: Event): event is ScrollLayer; +export interface SetLayerTreeId extends Instant { + name: Name.SET_LAYER_TREE_ID; + args: Args & { + data: ArgsData & { frame: string; layerTreeId: number; }; }; } -export declare function isTraceEventSetLayerId(event: TraceEventData): event is TraceEventSetLayerTreeId; -export interface TraceEventUpdateLayer extends TraceEventComplete { - name: KnownEventName.UPDATE_LAYER; - args: TraceEventArgs & { +export declare function isSetLayerId(event: Event): event is SetLayerTreeId; +export interface UpdateLayer extends Complete { + name: Name.UPDATE_LAYER; + args: Args & { layerId: number; layerTreeId: number; }; } -export declare function isTraceEventUpdateLayer(event: TraceEventData): event is TraceEventUpdateLayer; -export interface TraceEventDisplayItemListSnapshot extends TraceEventData { - name: KnownEventName.DISPLAY_ITEM_LIST_SNAPSHOT; +export declare function isUpdateLayer(event: Event): event is UpdateLayer; +export interface DisplayItemListSnapshot extends Event { + name: Name.DISPLAY_ITEM_LIST_SNAPSHOT; ph: Phase.OBJECT_SNAPSHOT; id2: { local?: string; }; - args: TraceEventArgs & { + args: Args & { snapshot: { skp64: string; params?: { @@ -1575,12 +1534,12 @@ export interface TraceEventDisplayItemListSnapshot extends TraceEventData { }; }; } -export declare function isTraceEventDisplayListItemListSnapshot(event: TraceEventData): event is TraceEventDisplayItemListSnapshot; -export interface TraceEventLayerTreeHostImplSnapshot extends TraceEventData { - name: KnownEventName.LAYER_TREE_HOST_IMPL_SNAPSHOT; +export declare function isDisplayListItemListSnapshot(event: Event): event is DisplayItemListSnapshot; +export interface LayerTreeHostImplSnapshot extends Event { + name: Name.LAYER_TREE_HOST_IMPL_SNAPSHOT; ph: Phase.OBJECT_SNAPSHOT; id: string; - args: TraceEventArgs & { + args: Args & { snapshot: { active_tiles: Array<{ id: string; @@ -1599,7 +1558,7 @@ export interface TraceEventLayerTreeHostImplSnapshot extends TraceEventData { }; }; } -export declare function isTraceEventLayerTreeHostImplSnapshot(event: TraceEventData): event is TraceEventLayerTreeHostImplSnapshot; +export declare function isLayerTreeHostImplSnapshot(event: Event): event is LayerTreeHostImplSnapshot; export interface TraceLayer { bounds: { height: number; @@ -1627,80 +1586,80 @@ export interface TracingLayerTile { gpu_memory_usage: number; content_rect: number[]; } -export interface TraceEventFireAnimationFrame extends TraceEventComplete { - name: KnownEventName.FIRE_ANIMATION_FRAME; - args: TraceEventArgs & { +export interface FireAnimationFrame extends Complete { + name: Name.FIRE_ANIMATION_FRAME; + args: Args & { data: { frame: string; id: number; }; }; } -export declare function isTraceEventFireAnimationFrame(event: TraceEventData): event is TraceEventFireAnimationFrame; -export interface TraceEventRequestAnimationFrame extends TraceEventInstant { - name: KnownEventName.REQUEST_ANIMATION_FRAME; - args: TraceEventArgs & { +export declare function isFireAnimationFrame(event: Event): event is FireAnimationFrame; +export interface RequestAnimationFrame extends Instant { + name: Name.REQUEST_ANIMATION_FRAME; + args: Args & { data: { frame: string; id: number; - stackTrace?: TraceEventCallFrame; + stackTrace?: CallFrame; }; }; } -export declare function isTraceEventRequestAnimationFrame(event: TraceEventData): event is TraceEventRequestAnimationFrame; -export interface TraceEventTimerInstall extends TraceEventInstant { - name: KnownEventName.TIMER_INSTALL; - args: TraceEventArgs & { +export declare function isRequestAnimationFrame(event: Event): event is RequestAnimationFrame; +export interface TimerInstall extends Instant { + name: Name.TIMER_INSTALL; + args: Args & { data: { frame: string; singleShot: boolean; - stackTrace?: TraceEventCallFrame; + stackTrace?: CallFrame; timeout: number; timerId: number; }; }; } -export declare function isTraceEventTimerInstall(event: TraceEventData): event is TraceEventTimerInstall; -export interface TraceEventTimerFire extends TraceEventComplete { - name: KnownEventName.TIMER_FIRE; - args: TraceEventArgs & { +export declare function isTimerInstall(event: Event): event is TimerInstall; +export interface TimerFire extends Complete { + name: Name.TIMER_FIRE; + args: Args & { data: { frame: string; timerId: number; }; }; } -export declare function isTraceEventTimerFire(event: TraceEventData): event is TraceEventTimerFire; -export interface TraceEventRequestIdleCallback extends TraceEventInstant { - name: KnownEventName.REQUEST_IDLE_CALLBACK; - args: TraceEventArgs & { +export declare function isTimerFire(event: Event): event is TimerFire; +export interface RequestIdleCallback extends Instant { + name: Name.REQUEST_IDLE_CALLBACK; + args: Args & { data: { frame: string; id: number; timeout: number; - stackTrace?: TraceEventCallFrame; + stackTrace?: CallFrame; }; }; } -export declare function isTraceEventRequestIdleCallback(event: TraceEventData): event is TraceEventRequestIdleCallback; -export interface TraceEventWebSocketCreate extends TraceEventInstant { - name: KnownEventName.WEB_SOCKET_CREATE; - args: TraceEventArgs & { +export declare function isRequestIdleCallback(event: Event): event is RequestIdleCallback; +export interface WebSocketCreate extends Instant { + name: Name.WEB_SOCKET_CREATE; + args: Args & { data: { identifier: number; url: string; frame?: string; workerId?: string; websocketProtocol?: string; - stackTrace?: TraceEventCallFrame; + stackTrace?: CallFrame; }; }; } -export declare function isTraceEventWebSocketCreate(event: TraceEventData): event is TraceEventWebSocketCreate; -export interface TraceEventWebSocketInfo extends TraceEventInstant { - name: KnownEventName.WEB_SOCKET_DESTROY | KnownEventName.WEB_SOCKET_RECEIVE_HANDSHAKE | KnownEventName.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST; - args: TraceEventArgs & { - data: TraceEventArgsData & { +export declare function isWebSocketCreate(event: Event): event is WebSocketCreate; +export interface WebSocketInfo extends Instant { + name: Name.WEB_SOCKET_DESTROY | Name.WEB_SOCKET_RECEIVE_HANDSHAKE | Name.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST; + args: Args & { + data: ArgsData & { identifier: number; url: string; frame?: string; @@ -1708,10 +1667,10 @@ export interface TraceEventWebSocketInfo extends TraceEventInstant { }; }; } -export interface TraceEventWebSocketTransfer extends TraceEventInstant { - name: KnownEventName.WEB_SOCKET_SEND | KnownEventName.WEB_SOCKET_RECEIVE; - args: TraceEventArgs & { - data: TraceEventArgsData & { +export interface WebSocketTransfer extends Instant { + name: Name.WEB_SOCKET_SEND | Name.WEB_SOCKET_RECEIVE; + args: Args & { + data: ArgsData & { identifier: number; url: string; frame?: string; @@ -1720,12 +1679,12 @@ export interface TraceEventWebSocketTransfer extends TraceEventInstant { }; }; } -export declare function isTraceEventWebSocketInfo(traceEventData: TraceEventData): traceEventData is TraceEventWebSocketInfo; -export declare function isTraceEventWebSocketTransfer(traceEventData: TraceEventData): traceEventData is TraceEventWebSocketTransfer; -export interface TraceEventWebSocketSend extends TraceEventInstant { - name: KnownEventName.WEB_SOCKET_SEND; - args: TraceEventArgs & { - data: TraceEventArgsData & { +export declare function isWebSocketInfo(event: Event): event is WebSocketInfo; +export declare function isWebSocketTransfer(event: Event): event is WebSocketTransfer; +export interface WebSocketSend extends Instant { + name: Name.WEB_SOCKET_SEND; + args: Args & { + data: ArgsData & { identifier: number; url: string; frame?: string; @@ -1734,11 +1693,11 @@ export interface TraceEventWebSocketSend extends TraceEventInstant { }; }; } -export declare function isTraceEventWebSocketSend(event: TraceEventData): event is TraceEventWebSocketSend; -export interface TraceEventWebSocketReceive extends TraceEventInstant { - name: KnownEventName.WEB_SOCKET_RECEIVE; - args: TraceEventArgs & { - data: TraceEventArgsData & { +export declare function isWebSocketSend(event: Event): event is WebSocketSend; +export interface WebSocketReceive extends Instant { + name: Name.WEB_SOCKET_RECEIVE; + args: Args & { + data: ArgsData & { identifier: number; url: string; frame?: string; @@ -1747,44 +1706,44 @@ export interface TraceEventWebSocketReceive extends TraceEventInstant { }; }; } -export declare function isTraceEventWebSocketReceive(event: TraceEventData): event is TraceEventWebSocketReceive; -export interface TraceEventWebSocketSendHandshakeRequest extends TraceEventInstant { - name: KnownEventName.WEB_SOCKET_SEND_HANDSHAKE_REQUEST; - args: TraceEventArgs & { +export declare function isWebSocketReceive(event: Event): event is WebSocketReceive; +export interface WebSocketSendHandshakeRequest extends Instant { + name: Name.WEB_SOCKET_SEND_HANDSHAKE_REQUEST; + args: Args & { data: { frame: string; identifier: number; }; }; } -export declare function isTraceEventWebSocketSendHandshakeRequest(event: TraceEventData): event is TraceEventWebSocketSendHandshakeRequest; -export interface TraceEventWebSocketReceiveHandshakeResponse extends TraceEventInstant { - name: KnownEventName.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST; - args: TraceEventArgs & { +export declare function isWebSocketSendHandshakeRequest(event: Event): event is WebSocketSendHandshakeRequest; +export interface WebSocketReceiveHandshakeResponse extends Instant { + name: Name.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST; + args: Args & { data: { frame: string; identifier: number; }; }; } -export declare function isTraceEventWebSocketReceiveHandshakeResponse(event: TraceEventData): event is TraceEventWebSocketReceiveHandshakeResponse; -export interface TraceEventWebSocketDestroy extends TraceEventInstant { - name: KnownEventName.WEB_SOCKET_DESTROY; - args: TraceEventArgs & { +export declare function isWebSocketReceiveHandshakeResponse(event: Event): event is WebSocketReceiveHandshakeResponse; +export interface WebSocketDestroy extends Instant { + name: Name.WEB_SOCKET_DESTROY; + args: Args & { data: { frame: string; identifier: number; }; }; } -export declare function isTraceEventWebSocketDestroy(event: TraceEventData): event is TraceEventWebSocketDestroy; -export type WebSocketTraceEvent = TraceEventWebSocketCreate | TraceEventWebSocketInfo | TraceEventWebSocketTransfer; -export declare function isWebSocketTraceEvent(event: TraceEventData): event is WebSocketTraceEvent; -export type WebSocketEvent = WebSocketTraceEvent | SyntheticWebSocketConnectionEvent; -export declare function isWebSocketEvent(event: TraceEventData): event is WebSocketTraceEvent | SyntheticWebSocketConnectionEvent; -export interface TraceEventV8Compile extends TraceEventComplete { - name: KnownEventName.COMPILE; - args: TraceEventArgs & { +export declare function isWebSocketDestroy(event: Event): event is WebSocketDestroy; +export type WebSocketTraceEvent = WebSocketCreate | WebSocketInfo | WebSocketTransfer; +export declare function isWebSocketTraceEvent(event: Event): event is WebSocketTraceEvent; +export type WebSocketEvent = WebSocketTraceEvent | SyntheticWebSocketConnection; +export declare function isWebSocketEvent(event: Event): event is WebSocketTraceEvent | SyntheticWebSocketConnection; +export interface V8Compile extends Complete { + name: Name.COMPILE; + args: Args & { data?: { url?: string; columnNumber?: number; @@ -1799,10 +1758,10 @@ export interface TraceEventV8Compile extends TraceEventComplete { fileName?: string; }; } -export declare function isTraceEventV8Compile(event: TraceEventData): event is TraceEventV8Compile; -export interface TraceEventFunctionCall extends TraceEventComplete { - name: KnownEventName.FUNCTION_CALL; - args: TraceEventArgs & { +export declare function isV8Compile(event: Event): event is V8Compile; +export interface FunctionCall extends Complete { + name: Name.FUNCTION_CALL; + args: Args & { data?: { frame?: string; columnNumber?: number; @@ -1813,21 +1772,21 @@ export interface TraceEventFunctionCall extends TraceEventComplete { }; }; } -export declare function isTraceEventFunctionCall(event: TraceEventData): event is TraceEventFunctionCall; -export declare function isSyntheticServerTiming(event: TraceEventData): event is SyntheticServerTiming; +export declare function isFunctionCall(event: Event): event is FunctionCall; +export declare function isSyntheticServerTiming(event: Event): event is SyntheticServerTiming; /** * Generally, before JS is executed, a trace event is dispatched that * parents the JS calls. These we call "invocation" events. This * function determines if an event is one of such. */ -export declare function isJSInvocationEvent(event: TraceEventData): boolean; +export declare function isJSInvocationEvent(event: Event): boolean; /** * This is an exhaustive list of events we track in the Performance * panel. Note not all of them are necessarliry shown in the flame * chart, some of them we only use for parsing. * TODO(crbug.com/1428024): Complete this enum. */ -export declare const enum KnownEventName { +export declare const enum Name { THREAD_NAME = "thread_name", PROGRAM = "Program", RUN_TASK = "RunTask", @@ -1981,7 +1940,8 @@ export declare const enum KnownEventName { SCHEDULE_POST_MESSAGE = "SchedulePostMessage", HANDLE_POST_MESSAGE = "HandlePostMessage", RENDER_FRAME_IMPL_CREATE_CHILD_FRAME = "RenderFrameImpl::createChildFrame", - DOM_LOADING = "domLoading" + DOM_LOADING = "domLoading", + BEGIN_REMOTE_FONT_LOAD = "BeginRemoteFontLoad" } export declare const Categories: { readonly Console: "blink.console"; @@ -2002,7 +1962,7 @@ export declare const Categories: { * instances of frames in trace/types/*.ts which is unable to import from * handlers. */ -export interface LegacyTimelineFrame extends TraceEventData { +export interface LegacyTimelineFrame extends Event { startTime: MicroSeconds; startTimeOffset: MicroSeconds; endTime: MicroSeconds; @@ -2016,14 +1976,14 @@ export interface LegacyTimelineFrame extends TraceEventData { readonly seqId: number; index: number; } -export declare function isLegacyTimelineFrame(data: TraceEventData): data is LegacyTimelineFrame; +export declare function isLegacyTimelineFrame(data: Event): data is LegacyTimelineFrame; export interface LegacyFrameLayerTreeData { - entry: TraceEventLayerTreeHostImplSnapshot; + entry: LayerTreeHostImplSnapshot; paints: LegacyLayerPaintEvent[]; } export interface LegacyLayerPaintEvent { layerId(): number; - event(): TraceEventPaint; + event(): Paint; picture(): LegacyLayerPaintEventPicture | null; } export interface LegacyLayerPaintEventPicture { diff --git a/public/models/trace/types/TraceEvents.js b/public/models/trace/types/TraceEvents.js index 06190babd..8575d92bd 100644 --- a/public/models/trace/types/TraceEvents.js +++ b/public/models/trace/types/TraceEvents.js @@ -5,166 +5,133 @@ export function isNestableAsyncPhase(phase) { return phase === "b" /* Phase.ASYNC_NESTABLE_START */ || phase === "e" /* Phase.ASYNC_NESTABLE_END */ || phase === "n" /* Phase.ASYNC_NESTABLE_INSTANT */; } -export function isAsyncPhase(phase) { +export function isPhaseAsync(phase) { return isNestableAsyncPhase(phase) || phase === "S" /* Phase.ASYNC_BEGIN */ || phase === "T" /* Phase.ASYNC_STEP_INTO */ || phase === "F" /* Phase.ASYNC_END */ || phase === "p" /* Phase.ASYNC_STEP_PAST */; } export function isFlowPhase(phase) { return phase === "s" /* Phase.FLOW_START */ || phase === "t" /* Phase.FLOW_STEP */ || phase === "f" /* Phase.FLOW_END */; } -export function objectIsTraceEventCallFrame(object) { +export function objectIsCallFrame(object) { return ('functionName' in object && typeof object.functionName === 'string') && ('scriptId' in object && (typeof object.scriptId === 'string' || typeof object.scriptId === 'number')) && ('columnNumber' in object && typeof object.columnNumber === 'number') && ('lineNumber' in object && typeof object.lineNumber === 'number') && ('url' in object && typeof object.url === 'string'); } -export function isTraceEventRunTask(event) { - return event.name === "RunTask" /* KnownEventName.RUN_TASK */; +export function isRunTask(event) { + return event.name === "RunTask" /* Name.RUN_TASK */; } -export function isTraceEventAuctionWorkletRunningInProcess(event) { +export function isAuctionWorkletRunningInProcess(event) { return event.name === 'AuctionWorkletRunningInProcess'; } -export function isTraceEventAuctionWorkletDoneWithProcess(event) { +export function isAuctionWorkletDoneWithProcess(event) { return event.name === 'AuctionWorkletDoneWithProcess'; } -export function isTraceEventScreenshot(event) { - return event.name === "Screenshot" /* KnownEventName.SCREENSHOT */; +export function isScreenshot(event) { + return event.name === "Screenshot" /* Name.SCREENSHOT */; } const markerTypeGuards = [ - isTraceEventMarkDOMContent, - isTraceEventMarkLoad, - isTraceEventFirstPaint, - isTraceEventFirstContentfulPaint, - isTraceEventLargestContentfulPaintCandidate, - isTraceEventNavigationStart, + isMarkDOMContent, + isMarkLoad, + isFirstPaint, + isFirstContentfulPaint, + isLargestContentfulPaintCandidate, + isNavigationStart, ]; export const MarkerName = ['MarkDOMContent', 'MarkLoad', 'firstPaint', 'firstContentfulPaint', 'largestContentfulPaint::Candidate']; -export function isTraceEventMarkerEvent(event) { +export function isMarkerEvent(event) { return markerTypeGuards.some(fn => fn(event)); } const pageLoadEventTypeGuards = [ ...markerTypeGuards, - isTraceEventInteractiveTime, + isInteractiveTime, ]; export function eventIsPageLoadEvent(event) { return pageLoadEventTypeGuards.some(fn => fn(event)); } -export function isTraceEventTracingSessionIdForWorker(event) { +export function isTracingSessionIdForWorker(event) { return event.name === 'TracingSessionIdForWorker'; } -export function isTraceEventScheduleStyleInvalidationTracking(event) { - return event.name === "ScheduleStyleInvalidationTracking" /* KnownEventName.SCHEDULE_STYLE_INVALIDATION_TRACKING */; +export function isScheduleStyleInvalidationTracking(event) { + return event.name === "ScheduleStyleInvalidationTracking" /* Name.SCHEDULE_STYLE_INVALIDATION_TRACKING */; } -export function isTraceEventStyleRecalcInvalidationTracking(event) { - return event.name === "StyleRecalcInvalidationTracking" /* KnownEventName.STYLE_RECALC_INVALIDATION_TRACKING */; +export function isStyleRecalcInvalidationTracking(event) { + return event.name === "StyleRecalcInvalidationTracking" /* Name.STYLE_RECALC_INVALIDATION_TRACKING */; } -export function isTraceEventStyleInvalidatorInvalidationTracking(event) { - return event.name === "StyleInvalidatorInvalidationTracking" /* KnownEventName.STYLE_INVALIDATOR_INVALIDATION_TRACKING */; +export function isStyleInvalidatorInvalidationTracking(event) { + return event.name === "StyleInvalidatorInvalidationTracking" /* Name.STYLE_INVALIDATOR_INVALIDATION_TRACKING */; } -export function isTraceEventBeginCommitCompositorFrame(event) { - return event.name === "BeginCommitCompositorFrame" /* KnownEventName.BEGIN_COMMIT_COMPOSITOR_FRAME */; +export function isBeginCommitCompositorFrame(event) { + return event.name === "BeginCommitCompositorFrame" /* Name.BEGIN_COMMIT_COMPOSITOR_FRAME */; } -export function isTraceEventParseMetaViewport(event) { - return event.name === "ParseMetaViewport" /* KnownEventName.PARSE_META_VIEWPORT */; +export function isParseMetaViewport(event) { + return event.name === "ParseMetaViewport" /* Name.PARSE_META_VIEWPORT */; } -export function isTraceEventScheduleStyleRecalculation(event) { - return event.name === "ScheduleStyleRecalculation" /* KnownEventName.SCHEDULE_STYLE_RECALCULATION */; +export function isScheduleStyleRecalculation(event) { + return event.name === "ScheduleStyleRecalculation" /* Name.SCHEDULE_STYLE_RECALCULATION */; } -export function isTraceEventRenderFrameImplCreateChildFrame(event) { - return event.name === "RenderFrameImpl::createChildFrame" /* KnownEventName.RENDER_FRAME_IMPL_CREATE_CHILD_FRAME */; +export function isRenderFrameImplCreateChildFrame(event) { + return event.name === "RenderFrameImpl::createChildFrame" /* Name.RENDER_FRAME_IMPL_CREATE_CHILD_FRAME */; } -export function isTraceEventTargetRundown(traceEventData) { - if (traceEventData.cat !== 'disabled-by-default-devtools.target-rundown') { - return false; - } - const data = traceEventData.args?.data; - if (!data) { - return false; - } - return 'frame' in data && 'frameType' in data && 'url' in data && 'isolate' in data && 'v8context' in data && - 'scriptId' in data; +export function isPipelineReporter(event) { + return event.name === "PipelineReporter" /* Name.PIPELINE_REPORTER */; } -export function isTraceEventScriptRundown(traceEventData) { - if (traceEventData.cat !== 'disabled-by-default-devtools.v8-source-rundown') { - return false; - } - const data = traceEventData.args?.data; - if (!data) { - return false; - } - return 'isolate' in data && 'executionContextId' in data && 'scriptId' in data && 'startLine' in data && - 'startColumn' in data && 'endLine' in data && 'endColumn' in data && 'hash' in data && 'isModule' in data && - 'hasSourceUrl' in data; -} -export function isTraceEventScriptRundownSource(traceEventData) { - if (traceEventData.cat !== 'disabled-by-default-devtools.v8-source-rundown-sources') { - return false; - } - const data = traceEventData.args?.data; - if (!data) { - return false; - } - return 'isolate' in data && 'scriptId' in data && 'sourceText' in data; -} -export function isTraceEventPipelineReporter(event) { - return event.name === "PipelineReporter" /* KnownEventName.PIPELINE_REPORTER */; -} -export function isSyntheticBasedEvent(event) { +export function isSyntheticBased(event) { return 'rawSourceEvent' in event; } -export function isSyntheticInteractionEvent(event) { +export function isSyntheticInteraction(event) { return Boolean('interactionId' in event && event.args?.data && 'beginEvent' in event.args.data && 'endEvent' in event.args.data); } -export function isTraceEventDrawFrame(event) { +export function isDrawFrame(event) { // The extra check for INSTANT here is because in the past DrawFrame events had an ASYNC_NESTABLE_START and ASYNC_NESTABLE_END pair. We don't want to support those old events, so we have to check we are dealing with an instant event. - return event.name === "DrawFrame" /* KnownEventName.DRAW_FRAME */ && event.ph === "I" /* Phase.INSTANT */; + return event.name === "DrawFrame" /* Name.DRAW_FRAME */ && event.ph === "I" /* Phase.INSTANT */; } export function isLegacyTraceEventDrawFrameBegin(event) { - return event.name === "DrawFrame" /* KnownEventName.DRAW_FRAME */ && event.ph === "b" /* Phase.ASYNC_NESTABLE_START */; + return event.name === "DrawFrame" /* Name.DRAW_FRAME */ && event.ph === "b" /* Phase.ASYNC_NESTABLE_START */; } -export function isTraceEventBeginFrame(event) { +export function isBeginFrame(event) { // Old traces did not have frameSeqId; but we do not want to support these. - return Boolean(event.name === "BeginFrame" /* KnownEventName.BEGIN_FRAME */ && event.args && 'frameSeqId' in event.args); + return Boolean(event.name === "BeginFrame" /* Name.BEGIN_FRAME */ && event.args && 'frameSeqId' in event.args); } -export function isTraceEventDroppedFrame(event) { +export function isDroppedFrame(event) { // Old traces did not have frameSeqId; but we do not want to support these. - return Boolean(event.name === "DroppedFrame" /* KnownEventName.DROPPED_FRAME */ && event.args && 'frameSeqId' in event.args); + return Boolean(event.name === "DroppedFrame" /* Name.DROPPED_FRAME */ && event.args && 'frameSeqId' in event.args); } -export function isTraceEventRequestMainThreadFrame(event) { - return event.name === "RequestMainThreadFrame" /* KnownEventName.REQUEST_MAIN_THREAD_FRAME */; +export function isRequestMainThreadFrame(event) { + return event.name === "RequestMainThreadFrame" /* Name.REQUEST_MAIN_THREAD_FRAME */; } -export function isTraceEventBeginMainThreadFrame(event) { - return event.name === "BeginMainThreadFrame" /* KnownEventName.BEGIN_MAIN_THREAD_FRAME */; +export function isBeginMainThreadFrame(event) { + return event.name === "BeginMainThreadFrame" /* Name.BEGIN_MAIN_THREAD_FRAME */; } -export function isTraceEventNeedsBeginFrameChanged(event) { - return event.name === "NeedsBeginFrameChanged" /* KnownEventName.NEEDS_BEGIN_FRAME_CHANGED */; +export function isNeedsBeginFrameChanged(event) { + return event.name === "NeedsBeginFrameChanged" /* Name.NEEDS_BEGIN_FRAME_CHANGED */; } -export function isTraceEventCommit(event) { +export function isCommit(event) { // Old traces did not have frameSeqId; but we do not want to support these. - return Boolean(event.name === "Commit" /* KnownEventName.COMMIT */ && event.args && 'frameSeqId' in event.args); + return Boolean(event.name === "Commit" /* Name.COMMIT */ && event.args && 'frameSeqId' in event.args); } -export function isTraceEventRasterTask(event) { - return event.name === "RasterTask" /* KnownEventName.RASTER_TASK */; +export function isRasterTask(event) { + return event.name === "RasterTask" /* Name.RASTER_TASK */; } -export function isTraceEventCompositeLayers(event) { - return event.name === "CompositeLayers" /* KnownEventName.COMPOSITE_LAYERS */; +export function isCompositeLayers(event) { + return event.name === "CompositeLayers" /* Name.COMPOSITE_LAYERS */; } -export function isTraceEventActivateLayerTree(event) { - return event.name === "ActivateLayerTree" /* KnownEventName.ACTIVATE_LAYER_TREE */; +export function isActivateLayerTree(event) { + return event.name === "ActivateLayerTree" /* Name.ACTIVATE_LAYER_TREE */; } -export function isTraceEventInvalidationTracking(event) { - return isTraceEventScheduleStyleInvalidationTracking(event) || isTraceEventStyleRecalcInvalidationTracking(event) || - isTraceEventStyleInvalidatorInvalidationTracking(event) || isTraceEventLayoutInvalidationTracking(event); +export function isInvalidationTracking(event) { + return isScheduleStyleInvalidationTracking(event) || isStyleRecalcInvalidationTracking(event) || + isStyleInvalidatorInvalidationTracking(event) || isLayoutInvalidationTracking(event); } -export function isTraceEventDrawLazyPixelRef(event) { - return event.name === "Draw LazyPixelRef" /* KnownEventName.DRAW_LAZY_PIXEL_REF */; +export function isDrawLazyPixelRef(event) { + return event.name === "Draw LazyPixelRef" /* Name.DRAW_LAZY_PIXEL_REF */; } -export function isTraceEventDecodeLazyPixelRef(event) { - return event.name === "Decode LazyPixelRef" /* KnownEventName.DECODE_LAZY_PIXEL_REF */; +export function isDecodeLazyPixelRef(event) { + return event.name === "Decode LazyPixelRef" /* Name.DECODE_LAZY_PIXEL_REF */; } -export function isTraceEventDecodeImage(event) { - return event.name === "Decode Image" /* KnownEventName.DECODE_IMAGE */; +export function isDecodeImage(event) { + return event.name === "Decode Image" /* Name.DECODE_IMAGE */; } export var SelectorTimingsKey; (function (SelectorTimingsKey) { @@ -176,17 +143,17 @@ export var SelectorTimingsKey; SelectorTimingsKey["Selector"] = "selector"; SelectorTimingsKey["StyleSheetId"] = "style_sheet_id"; })(SelectorTimingsKey || (SelectorTimingsKey = {})); -export function isTraceEventSelectorStats(event) { - return event.name === "SelectorStats" /* KnownEventName.SELECTOR_STATS */; +export function isSelectorStats(event) { + return event.name === "SelectorStats" /* Name.SELECTOR_STATS */; } -export function isTraceEventUpdateLayoutTree(event) { - return event.name === "UpdateLayoutTree" /* KnownEventName.UPDATE_LAYOUT_TREE */; +export function isUpdateLayoutTree(event) { + return event.name === "UpdateLayoutTree" /* Name.UPDATE_LAYOUT_TREE */; } -export function isTraceEventLayout(event) { - return event.name === "Layout" /* KnownEventName.LAYOUT */; +export function isLayout(event) { + return event.name === "Layout" /* Name.LAYOUT */; } -export function isTraceEventInvalidateLayout(event) { - return event.name === "InvalidateLayout" /* KnownEventName.INVALIDATE_LAYOUT */; +export function isInvalidateLayout(event) { + return event.name === "InvalidateLayout" /* Name.INVALIDATE_LAYOUT */; } class ProfileIdTag { #profileIdTag; @@ -230,289 +197,286 @@ class WorkerIdTag { export function WorkerId(value) { return value; } -export function isTraceEventComplete(event) { +export function isComplete(event) { return event.ph === "X" /* Phase.COMPLETE */; } -export function isTraceEventBegin(event) { +export function isBegin(event) { return event.ph === "B" /* Phase.BEGIN */; } -export function isTraceEventEnd(event) { +export function isEnd(event) { return event.ph === "E" /* Phase.END */; } -export function isTraceEventDispatch(event) { +export function isDispatch(event) { return event.name === 'EventDispatch'; } -export function isTraceEventInstant(event) { +export function isInstant(event) { return event.ph === "I" /* Phase.INSTANT */; } -export function isTraceEventRendererEvent(event) { - return isTraceEventInstant(event) || isTraceEventComplete(event); +export function isRendererEvent(event) { + return isInstant(event) || isComplete(event); } -export function isTraceEventFireIdleCallback(event) { +export function isFireIdleCallback(event) { return event.name === 'FireIdleCallback'; } -export function isTraceEventSchedulePostMessage(event) { - return event.name === "SchedulePostMessage" /* KnownEventName.SCHEDULE_POST_MESSAGE */; +export function isSchedulePostMessage(event) { + return event.name === "SchedulePostMessage" /* Name.SCHEDULE_POST_MESSAGE */; } -export function isTraceEventHandlePostMessage(event) { - return event.name === "HandlePostMessage" /* KnownEventName.HANDLE_POST_MESSAGE */; +export function isHandlePostMessage(event) { + return event.name === "HandlePostMessage" /* Name.HANDLE_POST_MESSAGE */; } -export function isTraceEventUpdateCounters(event) { +export function isUpdateCounters(event) { return event.name === 'UpdateCounters'; } -export function isThreadName(traceEventData) { - return traceEventData.name === "thread_name" /* KnownEventName.THREAD_NAME */; +export function isThreadName(event) { + return event.name === "thread_name" /* Name.THREAD_NAME */; } -export function isProcessName(traceEventData) { - return traceEventData.name === 'process_name'; +export function isProcessName(event) { + return event.name === 'process_name'; } -export function isTraceEventTracingStartedInBrowser(traceEventData) { - return traceEventData.name === "TracingStartedInBrowser" /* KnownEventName.TRACING_STARTED_IN_BROWSER */; +export function isTracingStartedInBrowser(event) { + return event.name === "TracingStartedInBrowser" /* Name.TRACING_STARTED_IN_BROWSER */; } -export function isTraceEventFrameCommittedInBrowser(traceEventData) { - return traceEventData.name === 'FrameCommittedInBrowser'; +export function isFrameCommittedInBrowser(event) { + return event.name === 'FrameCommittedInBrowser'; } -export function isTraceEventCommitLoad(traceEventData) { - return traceEventData.name === 'CommitLoad'; +export function isCommitLoad(event) { + return event.name === 'CommitLoad'; } -export function isTraceEventNavigationStart(traceEventData) { - return traceEventData.name === 'navigationStart'; +export function isNavigationStart(event) { + return event.name === 'navigationStart'; } -export function isTraceEventAnimation(traceEventData) { +export function isAnimation(event) { // We've found some rare traces with an Animtation trace event from a different category: https://crbug.com/1472375#comment7 - return traceEventData.name === 'Animation' && traceEventData.cat.includes('devtools.timeline'); + return event.name === 'Animation' && event.cat.includes('devtools.timeline'); +} +export function isSyntheticAnimation(event) { + if (event.name !== 'Animation' || !event.cat.includes('devtools.timeline')) { + return false; + } + const data = event.args?.data; + if (!data) { + return false; + } + return 'beginEvent' in data && 'endEvent' in data; } -export function isTraceEventLayoutShift(traceEventData) { - return traceEventData.name === 'LayoutShift'; +export function isLayoutShift(event) { + return event.name === 'LayoutShift'; } -export function isTraceEventLayoutInvalidationTracking(traceEventData) { - return traceEventData.name === "LayoutInvalidationTracking" /* KnownEventName.LAYOUT_INVALIDATION_TRACKING */; +export function isLayoutInvalidationTracking(event) { + return event.name === "LayoutInvalidationTracking" /* Name.LAYOUT_INVALIDATION_TRACKING */; } -export function isTraceEventFirstContentfulPaint(traceEventData) { - return traceEventData.name === 'firstContentfulPaint'; +export function isFirstContentfulPaint(event) { + return event.name === 'firstContentfulPaint'; } -export function isTraceEventLargestContentfulPaintCandidate(traceEventData) { - return traceEventData.name === "largestContentfulPaint::Candidate" /* KnownEventName.MARK_LCP_CANDIDATE */; +export function isLargestContentfulPaintCandidate(event) { + return event.name === "largestContentfulPaint::Candidate" /* Name.MARK_LCP_CANDIDATE */; } -export function isTraceEventLargestImagePaintCandidate(traceEventData) { - return traceEventData.name === 'LargestImagePaint::Candidate'; +export function isLargestImagePaintCandidate(event) { + return event.name === 'LargestImagePaint::Candidate'; } -export function isTraceEventLargestTextPaintCandidate(traceEventData) { - return traceEventData.name === 'LargestTextPaint::Candidate'; +export function isLargestTextPaintCandidate(event) { + return event.name === 'LargestTextPaint::Candidate'; } -export function isTraceEventMarkLoad(traceEventData) { - return traceEventData.name === 'MarkLoad'; +export function isMarkLoad(event) { + return event.name === 'MarkLoad'; } -export function isTraceEventFirstPaint(traceEventData) { - return traceEventData.name === 'firstPaint'; +export function isFirstPaint(event) { + return event.name === 'firstPaint'; } -export function isTraceEventMarkDOMContent(traceEventData) { - return traceEventData.name === 'MarkDOMContent'; +export function isMarkDOMContent(event) { + return event.name === 'MarkDOMContent'; } -export function isTraceEventInteractiveTime(traceEventData) { - return traceEventData.name === 'InteractiveTime'; +export function isInteractiveTime(event) { + return event.name === 'InteractiveTime'; } -export function isTraceEventEventTiming(traceEventData) { - return traceEventData.name === "EventTiming" /* KnownEventName.EVENT_TIMING */; +export function isEventTiming(event) { + return event.name === "EventTiming" /* Name.EVENT_TIMING */; } -export function isTraceEventEventTimingEnd(traceEventData) { - return isTraceEventEventTiming(traceEventData) && traceEventData.ph === "e" /* Phase.ASYNC_NESTABLE_END */; +export function isEventTimingEnd(event) { + return isEventTiming(event) && event.ph === "e" /* Phase.ASYNC_NESTABLE_END */; } -export function isTraceEventEventTimingStart(traceEventData) { - return isTraceEventEventTiming(traceEventData) && traceEventData.ph === "b" /* Phase.ASYNC_NESTABLE_START */; +export function isEventTimingStart(event) { + return isEventTiming(event) && event.ph === "b" /* Phase.ASYNC_NESTABLE_START */; } -export function isTraceEventGPUTask(traceEventData) { - return traceEventData.name === 'GPUTask'; +export function isGPUTask(event) { + return event.name === 'GPUTask'; } -export function isTraceEventProfile(traceEventData) { - return traceEventData.name === 'Profile'; +export function isProfile(event) { + return event.name === 'Profile'; } -export function isSyntheticCpuProfile(traceEventData) { - return traceEventData.name === 'CpuProfile'; +export function isSyntheticCpuProfile(event) { + return event.name === 'CpuProfile'; } -export function isTraceEventProfileChunk(traceEventData) { - return traceEventData.name === 'ProfileChunk'; +export function isProfileChunk(event) { + return event.name === 'ProfileChunk'; } -export function isTraceEventResourceChangePriority(traceEventData) { - return traceEventData.name === 'ResourceChangePriority'; +export function isResourceChangePriority(event) { + return event.name === 'ResourceChangePriority'; } -export function isTraceEventResourceSendRequest(traceEventData) { - return traceEventData.name === 'ResourceSendRequest'; +export function isResourceSendRequest(event) { + return event.name === 'ResourceSendRequest'; } -export function isTraceEventResourceReceiveResponse(traceEventData) { - return traceEventData.name === 'ResourceReceiveResponse'; +export function isResourceReceiveResponse(event) { + return event.name === 'ResourceReceiveResponse'; } -export function isTraceEventResourceMarkAsCached(traceEventData) { - return traceEventData.name === 'ResourceMarkAsCached'; +export function isResourceMarkAsCached(event) { + return event.name === 'ResourceMarkAsCached'; } -export function isTraceEventResourceFinish(traceEventData) { - return traceEventData.name === 'ResourceFinish'; +export function isResourceFinish(event) { + return event.name === 'ResourceFinish'; } -export function isTraceEventResourceWillSendRequest(traceEventData) { - return traceEventData.name === 'ResourceWillSendRequest'; +export function isResourceWillSendRequest(event) { + return event.name === 'ResourceWillSendRequest'; } -export function isTraceEventResourceReceivedData(traceEventData) { - return traceEventData.name === 'ResourceReceivedData'; +export function isResourceReceivedData(event) { + return event.name === 'ResourceReceivedData'; } -export function isSyntheticNetworkRequestEvent(traceEventData) { - return traceEventData.name === 'SyntheticNetworkRequest'; +export function isSyntheticNetworkRequest(event) { + return event.name === 'SyntheticNetworkRequest'; } -export function isSyntheticWebSocketConnectionEvent(traceEventData) { - return traceEventData.name === 'SyntheticWebSocketConnectionEvent'; +export function isSyntheticWebSocketConnection(event) { + return event.name === 'SyntheticWebSocketConnection'; } -export function isNetworkTrackEntry(traceEventData) { - return isSyntheticNetworkRequestEvent(traceEventData) || isSyntheticWebSocketConnectionEvent(traceEventData) || - isWebSocketTraceEvent(traceEventData); +export function isNetworkTrackEntry(event) { + return isSyntheticNetworkRequest(event) || isSyntheticWebSocketConnection(event) || isWebSocketTraceEvent(event); } -export function isTraceEventPrePaint(traceEventData) { - return traceEventData.name === 'PrePaint'; +export function isPrePaint(event) { + return event.name === 'PrePaint'; } -export function isTraceEventNavigationStartWithURL(event) { - return Boolean(isTraceEventNavigationStart(event) && event.args.data && event.args.data.documentLoaderURL !== ''); +export function isNavigationStartWithURL(event) { + return Boolean(isNavigationStart(event) && event.args.data && event.args.data.documentLoaderURL !== ''); } -export function isTraceEventMainFrameViewport(traceEventData) { - return traceEventData.name === 'PaintTimingVisualizer::Viewport'; +export function isMainFrameViewport(event) { + return event.name === 'PaintTimingVisualizer::Viewport'; } -export function isSyntheticUserTiming(traceEventData) { - if (traceEventData.cat !== 'blink.user_timing') { +export function isSyntheticUserTiming(event) { + if (event.cat !== 'blink.user_timing') { return false; } - const data = traceEventData.args?.data; + const data = event.args?.data; if (!data) { return false; } return 'beginEvent' in data && 'endEvent' in data; } -export function isSyntheticConsoleTiming(traceEventData) { - if (traceEventData.cat !== 'blink.console') { +export function isSyntheticConsoleTiming(event) { + if (event.cat !== 'blink.console') { return false; } - const data = traceEventData.args?.data; + const data = event.args?.data; if (!data) { return false; } return 'beginEvent' in data && 'endEvent' in data; } -export function isTraceEventUserTiming(traceEventData) { - return traceEventData.cat === 'blink.user_timing'; +export function isUserTiming(event) { + return event.cat === 'blink.user_timing'; } -export function isTraceEventDomLoading(traceEventData) { - return traceEventData.name === "domLoading" /* KnownEventName.DOM_LOADING */; +export function isDomLoading(event) { + return event.name === "domLoading" /* Name.DOM_LOADING */; } -export function isTraceEventPerformanceMeasure(traceEventData) { - return isTraceEventUserTiming(traceEventData) && isTraceEventAsyncPhase(traceEventData); +export function isBeginRemoteFontLoad(event) { + return event.name === "BeginRemoteFontLoad" /* Name.BEGIN_REMOTE_FONT_LOAD */; } -export function isTraceEventPerformanceMark(traceEventData) { - return isTraceEventUserTiming(traceEventData) && - (traceEventData.ph === "R" /* Phase.MARK */ || traceEventData.ph === "I" /* Phase.INSTANT */); +export function isPerformanceMeasure(event) { + return isUserTiming(event) && isPhaseAsync(event.ph); } -export function isTraceEventConsoleTime(traceEventData) { - return traceEventData.cat === 'blink.console' && isTraceEventAsyncPhase(traceEventData); +export function isPerformanceMark(event) { + return isUserTiming(event) && (event.ph === "R" /* Phase.MARK */ || event.ph === "I" /* Phase.INSTANT */); } -export function isTraceEventTimeStamp(traceEventData) { - return traceEventData.ph === "I" /* Phase.INSTANT */ && traceEventData.name === 'TimeStamp'; +export function isConsoleTime(event) { + return event.cat === 'blink.console' && isPhaseAsync(event.ph); } -export function isTraceEventParseHTML(traceEventData) { - return traceEventData.name === 'ParseHTML'; +export function isTimeStamp(event) { + return event.ph === "I" /* Phase.INSTANT */ && event.name === 'TimeStamp'; } -const asyncPhases = new Set([ - "b" /* Phase.ASYNC_NESTABLE_START */, - "n" /* Phase.ASYNC_NESTABLE_INSTANT */, - "e" /* Phase.ASYNC_NESTABLE_END */, - "T" /* Phase.ASYNC_STEP_INTO */, - "S" /* Phase.ASYNC_BEGIN */, - "F" /* Phase.ASYNC_END */, - "p" /* Phase.ASYNC_STEP_PAST */, -]); -export function isTraceEventAsyncPhase(traceEventData) { - return asyncPhases.has(traceEventData.ph); +export function isParseHTML(event) { + return event.name === 'ParseHTML'; } -export function isSyntheticLayoutShift(traceEventData) { - if (!isTraceEventLayoutShift(traceEventData) || !traceEventData.args.data) { +export function isSyntheticLayoutShift(event) { + if (!isLayoutShift(event) || !event.args.data) { return false; } - return 'rawEvent' in traceEventData.args.data; + return 'rawEvent' in event.args.data; } -export function isSyntheticLayoutShiftCluster(traceEventData) { - return traceEventData.name === "SyntheticLayoutShiftCluster" /* KnownEventName.SYNTHETIC_LAYOUT_SHIFT_CLUSTER */; +export function isSyntheticLayoutShiftCluster(event) { + return event.name === "SyntheticLayoutShiftCluster" /* Name.SYNTHETIC_LAYOUT_SHIFT_CLUSTER */; } export function isProfileCall(event) { return 'callFrame' in event; } -export function isTraceEventPaint(event) { - return event.name === "Paint" /* KnownEventName.PAINT */; +export function isPaint(event) { + return event.name === "Paint" /* Name.PAINT */; } -export function isTraceEventPaintImage(event) { - return event.name === "PaintImage" /* KnownEventName.PAINT_IMAGE */; +export function isPaintImage(event) { + return event.name === "PaintImage" /* Name.PAINT_IMAGE */; } -export function isTraceEventScrollLayer(event) { - return event.name === "ScrollLayer" /* KnownEventName.SCROLL_LAYER */; +export function isScrollLayer(event) { + return event.name === "ScrollLayer" /* Name.SCROLL_LAYER */; } -export function isTraceEventSetLayerId(event) { - return event.name === "SetLayerTreeId" /* KnownEventName.SET_LAYER_TREE_ID */; +export function isSetLayerId(event) { + return event.name === "SetLayerTreeId" /* Name.SET_LAYER_TREE_ID */; } -export function isTraceEventUpdateLayer(event) { - return event.name === "UpdateLayer" /* KnownEventName.UPDATE_LAYER */; +export function isUpdateLayer(event) { + return event.name === "UpdateLayer" /* Name.UPDATE_LAYER */; } -export function isTraceEventDisplayListItemListSnapshot(event) { - return event.name === "cc::DisplayItemList" /* KnownEventName.DISPLAY_ITEM_LIST_SNAPSHOT */; +export function isDisplayListItemListSnapshot(event) { + return event.name === "cc::DisplayItemList" /* Name.DISPLAY_ITEM_LIST_SNAPSHOT */; } -export function isTraceEventLayerTreeHostImplSnapshot(event) { - return event.name === "cc::LayerTreeHostImpl" /* KnownEventName.LAYER_TREE_HOST_IMPL_SNAPSHOT */; +export function isLayerTreeHostImplSnapshot(event) { + return event.name === "cc::LayerTreeHostImpl" /* Name.LAYER_TREE_HOST_IMPL_SNAPSHOT */; } -export function isTraceEventFireAnimationFrame(event) { - return event.name === "FireAnimationFrame" /* KnownEventName.FIRE_ANIMATION_FRAME */; +export function isFireAnimationFrame(event) { + return event.name === "FireAnimationFrame" /* Name.FIRE_ANIMATION_FRAME */; } -export function isTraceEventRequestAnimationFrame(event) { - return event.name === "RequestAnimationFrame" /* KnownEventName.REQUEST_ANIMATION_FRAME */; +export function isRequestAnimationFrame(event) { + return event.name === "RequestAnimationFrame" /* Name.REQUEST_ANIMATION_FRAME */; } -export function isTraceEventTimerInstall(event) { - return event.name === "TimerInstall" /* KnownEventName.TIMER_INSTALL */; +export function isTimerInstall(event) { + return event.name === "TimerInstall" /* Name.TIMER_INSTALL */; } -export function isTraceEventTimerFire(event) { - return event.name === "TimerFire" /* KnownEventName.TIMER_FIRE */; +export function isTimerFire(event) { + return event.name === "TimerFire" /* Name.TIMER_FIRE */; } -export function isTraceEventRequestIdleCallback(event) { - return event.name === "RequestIdleCallback" /* KnownEventName.REQUEST_IDLE_CALLBACK */; +export function isRequestIdleCallback(event) { + return event.name === "RequestIdleCallback" /* Name.REQUEST_IDLE_CALLBACK */; } -export function isTraceEventWebSocketCreate(event) { - return event.name === "WebSocketCreate" /* KnownEventName.WEB_SOCKET_CREATE */; +export function isWebSocketCreate(event) { + return event.name === "WebSocketCreate" /* Name.WEB_SOCKET_CREATE */; } -export function isTraceEventWebSocketInfo(traceEventData) { - return traceEventData.name === "WebSocketSendHandshakeRequest" /* KnownEventName.WEB_SOCKET_SEND_HANDSHAKE_REQUEST */ || - traceEventData.name === "WebSocketReceiveHandshakeResponse" /* KnownEventName.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST */ || - traceEventData.name === "WebSocketDestroy" /* KnownEventName.WEB_SOCKET_DESTROY */; +export function isWebSocketInfo(event) { + return event.name === "WebSocketSendHandshakeRequest" /* Name.WEB_SOCKET_SEND_HANDSHAKE_REQUEST */ || + event.name === "WebSocketReceiveHandshakeResponse" /* Name.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST */ || event.name === "WebSocketDestroy" /* Name.WEB_SOCKET_DESTROY */; } -export function isTraceEventWebSocketTransfer(traceEventData) { - return traceEventData.name === "WebSocketSend" /* KnownEventName.WEB_SOCKET_SEND */ || - traceEventData.name === "WebSocketReceive" /* KnownEventName.WEB_SOCKET_RECEIVE */; +export function isWebSocketTransfer(event) { + return event.name === "WebSocketSend" /* Name.WEB_SOCKET_SEND */ || event.name === "WebSocketReceive" /* Name.WEB_SOCKET_RECEIVE */; } -export function isTraceEventWebSocketSend(event) { - return event.name === "WebSocketSend" /* KnownEventName.WEB_SOCKET_SEND */; +export function isWebSocketSend(event) { + return event.name === "WebSocketSend" /* Name.WEB_SOCKET_SEND */; } -export function isTraceEventWebSocketReceive(event) { - return event.name === "WebSocketReceive" /* KnownEventName.WEB_SOCKET_RECEIVE */; +export function isWebSocketReceive(event) { + return event.name === "WebSocketReceive" /* Name.WEB_SOCKET_RECEIVE */; } -export function isTraceEventWebSocketSendHandshakeRequest(event) { - return event.name === "WebSocketSendHandshakeRequest" /* KnownEventName.WEB_SOCKET_SEND_HANDSHAKE_REQUEST */; +export function isWebSocketSendHandshakeRequest(event) { + return event.name === "WebSocketSendHandshakeRequest" /* Name.WEB_SOCKET_SEND_HANDSHAKE_REQUEST */; } -export function isTraceEventWebSocketReceiveHandshakeResponse(event) { - return event.name === "WebSocketReceiveHandshakeResponse" /* KnownEventName.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST */; +export function isWebSocketReceiveHandshakeResponse(event) { + return event.name === "WebSocketReceiveHandshakeResponse" /* Name.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST */; } -export function isTraceEventWebSocketDestroy(event) { - return event.name === "WebSocketDestroy" /* KnownEventName.WEB_SOCKET_DESTROY */; +export function isWebSocketDestroy(event) { + return event.name === "WebSocketDestroy" /* Name.WEB_SOCKET_DESTROY */; } export function isWebSocketTraceEvent(event) { - return isTraceEventWebSocketCreate(event) || isTraceEventWebSocketInfo(event) || isTraceEventWebSocketTransfer(event); + return isWebSocketCreate(event) || isWebSocketInfo(event) || isWebSocketTransfer(event); } export function isWebSocketEvent(event) { - return isWebSocketTraceEvent(event) || isSyntheticWebSocketConnectionEvent(event); + return isWebSocketTraceEvent(event) || isSyntheticWebSocketConnection(event); } -export function isTraceEventV8Compile(event) { - return event.name === "v8.compile" /* KnownEventName.COMPILE */; +export function isV8Compile(event) { + return event.name === "v8.compile" /* Name.COMPILE */; } -export function isTraceEventFunctionCall(event) { - return event.name === "FunctionCall" /* KnownEventName.FUNCTION_CALL */; +export function isFunctionCall(event) { + return event.name === "FunctionCall" /* Name.FUNCTION_CALL */; } export function isSyntheticServerTiming(event) { return event.cat === 'devtools.server-timing'; @@ -524,12 +488,12 @@ export function isSyntheticServerTiming(event) { */ export function isJSInvocationEvent(event) { switch (event.name) { - case "RunMicrotasks" /* KnownEventName.RUN_MICROTASKS */: - case "FunctionCall" /* KnownEventName.FUNCTION_CALL */: - case "EvaluateScript" /* KnownEventName.EVALUATE_SCRIPT */: - case "v8.evaluateModule" /* KnownEventName.EVALUATE_MODULE */: - case "EventDispatch" /* KnownEventName.EVENT_DISPATCH */: - case "V8.Execute" /* KnownEventName.V8_EXECUTE */: + case "RunMicrotasks" /* Name.RUN_MICROTASKS */: + case "FunctionCall" /* Name.FUNCTION_CALL */: + case "EvaluateScript" /* Name.EVALUATE_SCRIPT */: + case "v8.evaluateModule" /* Name.EVALUATE_MODULE */: + case "EventDispatch" /* Name.EVENT_DISPATCH */: + case "V8.Execute" /* Name.V8_EXECUTE */: return true; } // Also consider any new v8 trace events. (eg 'V8.RunMicrotasks' and 'v8.run') diff --git a/public/models/trace/types/TraceEvents.js.map b/public/models/trace/types/TraceEvents.js.map index 7651ddcf3..c3ecf30cc 100644 --- a/public/models/trace/types/TraceEvents.js.map +++ b/public/models/trace/types/TraceEvents.js.map @@ -1 +1 @@ -{"version":3,"file":"TraceEvents.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/types/TraceEvents.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/* eslint-disable no-unused-private-class-members */\nimport type * as Protocol from '../../../generated/protocol.js';\n\nimport {type MicroSeconds, type MilliSeconds, type Seconds, type TraceWindowMicroSeconds} from './Timing.js';\n\n// Trace Events.\nexport const enum Phase {\n // Standard\n BEGIN = 'B',\n END = 'E',\n COMPLETE = 'X',\n INSTANT = 'I',\n COUNTER = 'C',\n\n // Async\n ASYNC_NESTABLE_START = 'b',\n ASYNC_NESTABLE_INSTANT = 'n',\n ASYNC_NESTABLE_END = 'e',\n ASYNC_STEP_INTO = 'T',\n ASYNC_BEGIN = 'S',\n ASYNC_END = 'F',\n ASYNC_STEP_PAST = 'p',\n\n // Flow\n FLOW_START = 's',\n FLOW_STEP = 't',\n FLOW_END = 'f',\n\n // Sample\n SAMPLE = 'P',\n\n // Object\n OBJECT_CREATED = 'N',\n OBJECT_SNAPSHOT = 'O',\n OBJECT_DESTROYED = 'D',\n\n // Metadata\n METADATA = 'M',\n\n // Memory Dump\n MEMORY_DUMP_GLOBAL = 'V',\n MEMORY_DUMP_PROCESS = 'v',\n\n // Mark\n MARK = 'R',\n\n // Clock sync\n CLOCK_SYNC = 'c',\n}\n\nexport function isNestableAsyncPhase(phase: Phase): boolean {\n return phase === Phase.ASYNC_NESTABLE_START || phase === Phase.ASYNC_NESTABLE_END ||\n phase === Phase.ASYNC_NESTABLE_INSTANT;\n}\n\nexport function isAsyncPhase(phase: Phase): boolean {\n return isNestableAsyncPhase(phase) || phase === Phase.ASYNC_BEGIN || phase === Phase.ASYNC_STEP_INTO ||\n phase === Phase.ASYNC_END || phase === Phase.ASYNC_STEP_PAST;\n}\n\nexport function isFlowPhase(phase: Phase): boolean {\n return phase === Phase.FLOW_START || phase === Phase.FLOW_STEP || phase === Phase.FLOW_END;\n}\n\nexport const enum TraceEventScope {\n THREAD = 't',\n PROCESS = 'p',\n GLOBAL = 'g',\n}\n\nexport interface TraceEventData {\n args?: TraceEventArgs;\n cat: string;\n name: string;\n ph: Phase;\n pid: ProcessID;\n tid: ThreadID;\n tts?: MicroSeconds;\n ts: MicroSeconds;\n tdur?: MicroSeconds;\n dur?: MicroSeconds;\n}\n\nexport interface TraceEventArgs {\n data?: TraceEventArgsData;\n stackTrace?: TraceEventCallFrame[];\n}\n\nexport interface TraceEventArgsData {\n stackTrace?: TraceEventCallFrame[];\n url?: string;\n navigationId?: string;\n frame?: string;\n}\n\nexport interface TraceEventCallFrame {\n codeType?: string;\n functionName: string;\n // Trace events are inconsistent here sadly :(\n scriptId: number|string;\n columnNumber: number;\n lineNumber: number;\n url: string;\n}\n\nexport function objectIsTraceEventCallFrame(object: {}): object is TraceEventCallFrame {\n return ('functionName' in object && typeof object.functionName === 'string') &&\n ('scriptId' in object && (typeof object.scriptId === 'string' || typeof object.scriptId === 'number')) &&\n ('columnNumber' in object && typeof object.columnNumber === 'number') &&\n ('lineNumber' in object && typeof object.lineNumber === 'number') &&\n ('url' in object && typeof object.url === 'string');\n}\n\nexport interface TraceFrame {\n frame: string;\n name: string;\n processId: ProcessID;\n url: string;\n parent?: string;\n // Added to Chromium in April 2024:\n // crrev.com/c/5424783\n isOutermostMainFrame?: boolean;\n // Added to Chromium in June 2024:\n // crrev.com/c/5595033\n isInPrimaryMainFrame?: boolean;\n}\n\n// Sample events.\n\nexport interface TraceEventSample extends TraceEventData {\n ph: Phase.SAMPLE;\n}\n\n/**\n * A fake trace event created to support CDP.Profiler.Profiles in the\n * trace engine.\n */\nexport interface SyntheticCpuProfile extends TraceEventInstant, SyntheticBasedEvent {\n name: 'CpuProfile';\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n cpuProfile: Protocol.Profiler.Profile,\n },\n };\n}\n\nexport interface TraceEventProfile extends TraceEventSample {\n name: 'Profile';\n id: ProfileID;\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n startTime: MicroSeconds,\n },\n };\n}\n\nexport interface TraceEventProfileChunk extends TraceEventSample {\n name: 'ProfileChunk';\n id: ProfileID;\n args: TraceEventArgs&{\n // `data` is only missing in \"fake\" traces\n data?: TraceEventArgsData & {\n cpuProfile?: TraceEventPartialProfile,\n timeDeltas?: MicroSeconds[],\n lines?: MicroSeconds[],\n },\n };\n}\n\nexport interface TraceEventPartialProfile {\n nodes?: TraceEventPartialNode[];\n samples: CallFrameID[];\n}\n\nexport interface TraceEventPartialNode {\n callFrame: TraceEventCallFrame;\n id: CallFrameID;\n parent?: CallFrameID;\n}\n\n// Complete events.\n\nexport interface TraceEventComplete extends TraceEventData {\n ph: Phase.COMPLETE;\n dur: MicroSeconds;\n}\n\nexport interface TraceEventRunTask extends TraceEventComplete {\n name: KnownEventName.RUN_TASK;\n}\nexport function isTraceEventRunTask(event: TraceEventData): event is TraceEventRunTask {\n return event.name === KnownEventName.RUN_TASK;\n}\n\nexport interface TraceEventFireIdleCallback extends TraceEventComplete {\n name: KnownEventName.FIRE_IDLE_CALLBACK;\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n allottedMilliseconds: MilliSeconds,\n frame: string,\n id: number,\n timedOut: boolean,\n },\n };\n}\n\nexport interface TraceEventSchedulePostMessage extends TraceEventInstant {\n name: KnownEventName.SCHEDULE_POST_MESSAGE;\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n traceId: string,\n },\n };\n}\n\nexport interface TraceEventHandlePostMessage extends TraceEventComplete {\n name: KnownEventName.HANDLE_POST_MESSAGE;\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n traceId: string,\n },\n };\n}\n\nexport interface TraceEventDispatch extends TraceEventComplete {\n name: 'EventDispatch';\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n type: string,\n },\n };\n}\n\nexport interface TraceEventParseHTML extends TraceEventComplete {\n name: 'ParseHTML';\n args: TraceEventArgs&{\n beginData: {\n frame: string,\n startLine: number,\n url: string,\n },\n endData?: {\n endLine: number,\n },\n };\n}\n\nexport interface TraceEventBegin extends TraceEventData {\n ph: Phase.BEGIN;\n}\n\nexport interface TraceEventEnd extends TraceEventData {\n ph: Phase.END;\n}\n\n/**\n * This denotes a complete event created from a pair of begin and end\n * events. For practicality, instead of always having to look for the\n * end event corresponding to a begin event, we create a synthetic\n * complete event that comprises the data of both from the beginning in\n * the RendererHandler.\n */\nexport type SyntheticCompleteEvent = TraceEventComplete;\n\nexport interface TraceEventEventTiming extends TraceEventData {\n ph: Phase.ASYNC_NESTABLE_START|Phase.ASYNC_NESTABLE_END;\n name: KnownEventName.EVENT_TIMING;\n id: string;\n args: TraceEventArgs&{\n frame: string,\n data?: TraceEventArgsData&{\n cancelable: boolean,\n duration: MilliSeconds,\n processingEnd: MilliSeconds,\n processingStart: MilliSeconds,\n timeStamp: MilliSeconds,\n interactionId?: number, type: string,\n },\n };\n}\n\nexport interface TraceEventEventTimingBegin extends TraceEventEventTiming {\n ph: Phase.ASYNC_NESTABLE_START;\n}\nexport interface TraceEventEventTimingEnd extends TraceEventEventTiming {\n ph: Phase.ASYNC_NESTABLE_END;\n}\n\nexport interface TraceEventGPUTask extends TraceEventComplete {\n name: 'GPUTask';\n args: TraceEventArgs&{\n data?: TraceEventArgsData & {\n /* eslint-disable @typescript-eslint/naming-convention */\n renderer_pid: ProcessID,\n used_bytes: number,\n /* eslint-enable @typescript-eslint/naming-convention */\n },\n };\n}\n\nexport interface SyntheticNetworkRedirect {\n url: string;\n priority: string;\n requestMethod?: string;\n ts: MicroSeconds;\n dur: MicroSeconds;\n}\n\n// TraceEventProcessedArgsData is used to store the processed data of a network\n// request. Which is used to distinguish from the date we extract from the\n// trace event directly.\ninterface SyntheticArgsData {\n dnsLookup: MicroSeconds;\n download: MicroSeconds;\n downloadStart: MicroSeconds;\n finishTime: MicroSeconds;\n initialConnection: MicroSeconds;\n isDiskCached: boolean;\n isHttps: boolean;\n isMemoryCached: boolean;\n isPushedResource: boolean;\n networkDuration: MicroSeconds;\n processingDuration: MicroSeconds;\n proxyNegotiation: MicroSeconds;\n queueing: MicroSeconds;\n redirectionDuration: MicroSeconds;\n requestSent: MicroSeconds;\n sendStartTime: MicroSeconds;\n ssl: MicroSeconds;\n stalled: MicroSeconds;\n totalTime: MicroSeconds;\n waiting: MicroSeconds;\n}\n\nexport interface SyntheticNetworkRequest extends TraceEventComplete, SyntheticBasedEvent {\n rawSourceEvent: TraceEventResourceSendRequest;\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n syntheticData: SyntheticArgsData,\n // All fields below are from TraceEventsForNetworkRequest,\n // Required fields\n /** Size of the resource after decompression (if applicable). */\n decodedBodyLength: number,\n /**\n * Size of the resource over the network. Includes size of headers and\n * anything else in the HTTP response packet.\n */\n encodedDataLength: number,\n frame: string,\n fromServiceWorker: boolean,\n isLinkPreload: boolean,\n mimeType: string,\n priority: Protocol.Network.ResourcePriority,\n initialPriority: Protocol.Network.ResourcePriority,\n /**\n * This is the protocol used to resolve the request.\n *\n * Note, this is not the same as URL.protocol.\n *\n * Example values (not exhaustive): http/0.9, http/1.0, http/1.1, http, h2, h3-Q050, data, blob\n */\n protocol: string,\n redirects: SyntheticNetworkRedirect[],\n renderBlocking: RenderBlocking,\n requestId: string,\n requestingFrameUrl: string,\n statusCode: number,\n resourceType: Protocol.Network.ResourceType,\n responseHeaders: Array<{name: string, value: string}>,\n fetchPriorityHint: FetchPriorityHint,\n url: string,\n /** True only if got a 'resourceFinish' event indicating a failure. */\n failed: boolean,\n /** True only if got a 'resourceFinish' event. */\n finished: boolean,\n connectionId: number,\n connectionReused: boolean,\n // Optional fields\n initiator?: Initiator,\n requestMethod?: string,\n timing?: TraceEventResourceReceiveResponseTimingData,\n syntheticServerTimings?: SyntheticServerTiming[],\n },\n };\n cat: 'loading';\n name: 'SyntheticNetworkRequest';\n ph: Phase.COMPLETE;\n dur: MicroSeconds;\n tdur: MicroSeconds;\n ts: MicroSeconds;\n tts: MicroSeconds;\n pid: ProcessID;\n tid: ThreadID;\n}\n\nexport interface SyntheticWebSocketConnectionEvent extends TraceEventComplete, SyntheticBasedEvent {\n rawSourceEvent: TraceEventData;\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n identifier: number,\n priority: Protocol.Network.ResourcePriority,\n url: string,\n },\n };\n cat: string;\n name: 'SyntheticWebSocketConnectionEvent';\n ph: Phase.COMPLETE;\n dur: MicroSeconds;\n ts: MicroSeconds;\n pid: ProcessID;\n tid: ThreadID;\n s: TraceEventScope;\n}\n\nexport const enum AuctionWorkletType {\n BIDDER = 'bidder',\n SELLER = 'seller',\n // Not expected to be used, but here as a fallback in case new types get\n // added and we have yet to update the trace engine.\n UNKNOWN = 'unknown',\n}\n\nexport interface SyntheticAuctionWorkletEvent extends TraceEventInstant, SyntheticBasedEvent {\n rawSourceEvent: TraceEventData;\n name: 'SyntheticAuctionWorkletEvent';\n // The PID that the AuctionWorklet is running in.\n pid: ProcessID;\n // URL\n host: string;\n // An ID used to pair up runningInProcessEvents with doneWithProcessEvents\n target: string;\n type: AuctionWorkletType;\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n // There are two threads for a worklet that we care about, so we gather\n // the thread_name events so we can know the PID and TID for them (and\n // hence display the right events in the track for each thread)\n utilityThread: TraceEventThreadName,\n v8HelperThread: TraceEventThreadName,\n } &\n (\n // This type looks odd, but this is because these events could either have:\n // 1. Just the DoneWithProcess event\n // 2. Just the RunningInProcess event\n // 3. Both events\n // But crucially it cannot have both events missing, hence listing all the\n // allowed cases.\n // Clang is disabled as the combination of nested types and optional\n // properties cause it to weirdly indent some of the properties and make it\n // very unreadable.\n // clang-format off\n {\n runningInProcessEvent: TraceEventAuctionWorkletRunningInProcess,\n doneWithProcessEvent: TraceEventAuctionWorkletDoneWithProcess,\n } |\n {\n runningInProcessEvent?: TraceEventAuctionWorkletRunningInProcess,\n doneWithProcessEvent: TraceEventAuctionWorkletDoneWithProcess,\n } |\n {\n doneWithProcessEvent?: TraceEventAuctionWorkletDoneWithProcess,\n runningInProcessEvent: TraceEventAuctionWorkletRunningInProcess,\n\n }),\n // clang-format on\n };\n}\nexport interface TraceEventAuctionWorkletRunningInProcess extends TraceEventData {\n name: 'AuctionWorkletRunningInProcess';\n ph: Phase.INSTANT;\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n host: string,\n pid: ProcessID,\n target: string,\n type: AuctionWorkletType,\n },\n };\n}\nexport interface TraceEventAuctionWorkletDoneWithProcess extends TraceEventData {\n name: 'AuctionWorkletDoneWithProcess';\n ph: Phase.INSTANT;\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n host: string,\n pid: ProcessID,\n target: string,\n type: AuctionWorkletType,\n },\n };\n}\n\nexport function isTraceEventAuctionWorkletRunningInProcess(event: TraceEventData):\n event is TraceEventAuctionWorkletRunningInProcess {\n return event.name === 'AuctionWorkletRunningInProcess';\n}\nexport function isTraceEventAuctionWorkletDoneWithProcess(event: TraceEventData):\n event is TraceEventAuctionWorkletDoneWithProcess {\n return event.name === 'AuctionWorkletDoneWithProcess';\n}\n\n// Snapshot events.\n\nexport interface TraceEventScreenshot extends TraceEventData {\n /**\n * @deprecated This value is incorrect. Use ScreenshotHandler.getPresentationTimestamp()\n */\n ts: MicroSeconds;\n /** The id is the frame sequence number in hex */\n id: string;\n args: TraceEventArgs&{\n snapshot: string,\n };\n name: KnownEventName.SCREENSHOT;\n cat: 'disabled-by-default-devtools.screenshot';\n ph: Phase.OBJECT_SNAPSHOT;\n}\nexport function isTraceEventScreenshot(event: TraceEventData): event is TraceEventScreenshot {\n return event.name === KnownEventName.SCREENSHOT;\n}\n\nexport interface SyntheticScreenshot extends TraceEventData, SyntheticBasedEvent {\n rawSourceEvent: TraceEventScreenshot;\n /** This is the correct presentation timestamp. */\n ts: MicroSeconds;\n args: TraceEventArgs&{\n dataUri: string,\n };\n name: KnownEventName.SCREENSHOT;\n cat: 'disabled-by-default-devtools.screenshot';\n ph: Phase.OBJECT_SNAPSHOT;\n}\n\n// Animation events.\n\nexport interface TraceEventAnimation extends TraceEventData {\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n nodeName?: string,\n nodeId?: number,\n displayName?: string,\n id?: string,\n name?: string,\n state?: string,\n compositeFailed?: number,\n unsupportedProperties?: string[],\n },\n };\n name: 'Animation';\n id2?: {\n local?: string,\n };\n ph: Phase.ASYNC_NESTABLE_START|Phase.ASYNC_NESTABLE_END|Phase.ASYNC_NESTABLE_INSTANT;\n}\n\n// Metadata events.\n\nexport interface TraceEventMetadata extends TraceEventData {\n ph: Phase.METADATA;\n args: TraceEventArgs&{\n name?: string,\n uptime?: string,\n };\n}\n\nexport interface TraceEventThreadName extends TraceEventMetadata {\n name: KnownEventName.THREAD_NAME;\n args: TraceEventArgs&{\n name?: string,\n };\n}\n\nexport interface TraceEventProcessName extends TraceEventMetadata {\n name: 'process_name';\n}\n\n// Mark events.\n\nexport interface TraceEventMark extends TraceEventData {\n ph: Phase.MARK;\n}\n\nexport interface TraceEventNavigationStart extends TraceEventMark {\n name: 'navigationStart';\n args: TraceEventArgs&{\n data?: TraceEventArgsData & {\n documentLoaderURL: string,\n isLoadingMainFrame: boolean,\n // isOutermostMainFrame was introduced in crrev.com/c/3625434 and exists\n // because of Fenced Frames\n // [github.com/WICG/fenced-frame/tree/master/explainer].\n // Fenced frames introduce a situation where isLoadingMainFrame could be\n // true for a navigation, but that navigation be within an embedded \"main\n // frame\", and therefore it wouldn't be on the top level main frame.\n // In situations where we need to distinguish that, we can rely on\n // isOutermostMainFrame, which will only be true for navigations on the\n // top level main frame.\n\n // This flag is optional as it was introduced in May 2022; so users\n // reasonably may import traces from before that date that do not have\n // this field present.\n isOutermostMainFrame?: boolean, navigationId: string,\n /**\n * @deprecated use documentLoaderURL for navigation events URLs\n */\n url?: string,\n },\n frame: string,\n };\n}\n\nexport interface TraceEventFirstContentfulPaint extends TraceEventMark {\n name: KnownEventName.MARK_FCP;\n args: TraceEventArgs&{\n frame: string,\n data?: TraceEventArgsData&{\n navigationId: string,\n },\n };\n}\n\nexport interface TraceEventFirstPaint extends TraceEventMark {\n name: 'firstPaint';\n args: TraceEventArgs&{\n frame: string,\n data?: TraceEventArgsData&{\n navigationId: string,\n },\n };\n}\n\nexport type PageLoadEvent = TraceEventFirstContentfulPaint|TraceEventMarkDOMContent|TraceEventInteractiveTime|\n TraceEventLargestContentfulPaintCandidate|TraceEventLayoutShift|TraceEventFirstPaint|TraceEventMarkLoad|\n TraceEventNavigationStart;\n\nconst markerTypeGuards = [\n isTraceEventMarkDOMContent,\n isTraceEventMarkLoad,\n isTraceEventFirstPaint,\n isTraceEventFirstContentfulPaint,\n isTraceEventLargestContentfulPaintCandidate,\n isTraceEventNavigationStart,\n];\n\nexport const MarkerName =\n ['MarkDOMContent', 'MarkLoad', 'firstPaint', 'firstContentfulPaint', 'largestContentfulPaint::Candidate'] as const;\n\nexport interface MarkerEvent extends TraceEventData {\n name: typeof MarkerName[number];\n}\n\nexport function isTraceEventMarkerEvent(event: TraceEventData): event is MarkerEvent {\n return markerTypeGuards.some(fn => fn(event));\n}\n\nconst pageLoadEventTypeGuards = [\n ...markerTypeGuards,\n isTraceEventInteractiveTime,\n];\n\nexport function eventIsPageLoadEvent(event: TraceEventData): event is PageLoadEvent {\n return pageLoadEventTypeGuards.some(fn => fn(event));\n}\n\nexport interface TraceEventLargestContentfulPaintCandidate extends TraceEventMark {\n name: KnownEventName.MARK_LCP_CANDIDATE;\n args: TraceEventArgs&{\n frame: string,\n data?: TraceEventArgsData&{\n candidateIndex: number,\n isOutermostMainFrame: boolean,\n isMainFrame: boolean,\n navigationId: string,\n nodeId: Protocol.DOM.BackendNodeId,\n loadingAttr: string,\n type?: string,\n },\n };\n}\nexport interface TraceEventLargestImagePaintCandidate extends TraceEventMark {\n name: 'LargestImagePaint::Candidate';\n args: TraceEventArgs&{\n frame: string,\n data?: TraceEventArgsData&{\n candidateIndex: number,\n imageUrl: string,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n DOMNodeId: Protocol.DOM.BackendNodeId,\n },\n };\n}\nexport interface TraceEventLargestTextPaintCandidate extends TraceEventMark {\n name: 'LargestTextPaint::Candidate';\n args: TraceEventArgs&{\n frame: string,\n data?: TraceEventArgsData&{\n candidateIndex: number,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n DOMNodeId: Protocol.DOM.BackendNodeId,\n },\n };\n}\n\nexport interface TraceEventInteractiveTime extends TraceEventMark {\n name: 'InteractiveTime';\n args: TraceEventArgs&{\n args: {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n total_blocking_time_ms: number,\n },\n frame: string,\n };\n}\n\n// Instant events.\n\nexport interface TraceEventInstant extends TraceEventData {\n ph: Phase.INSTANT;\n s: TraceEventScope;\n}\n\nexport interface TraceEventUpdateCounters extends TraceEventInstant {\n name: 'UpdateCounters';\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n documents: number,\n jsEventListeners: number,\n jsHeapSizeUsed: number,\n nodes: number,\n gpuMemoryLimitKB?: number,\n },\n };\n}\n\nexport type TraceEventRendererEvent = TraceEventInstant|TraceEventComplete;\n\nexport interface TraceEventTracingStartedInBrowser extends TraceEventInstant {\n name: KnownEventName.TRACING_STARTED_IN_BROWSER;\n args: TraceEventArgs&{\n data?: TraceEventArgsData & {\n frameTreeNodeId: number,\n // Frames can only missing in \"fake\" traces\n frames?: TraceFrame[], persistentIds: boolean,\n },\n };\n}\n\nexport interface TraceEventTracingSessionIdForWorker extends TraceEventInstant {\n name: 'TracingSessionIdForWorker';\n args: TraceEventArgs&{\n data?: TraceEventArgsData & {\n url: string,\n workerId: WorkerId,\n workerThreadId: ThreadID,\n frame: string,\n },\n };\n}\nexport function isTraceEventTracingSessionIdForWorker(event: TraceEventData):\n event is TraceEventTracingSessionIdForWorker {\n return event.name === 'TracingSessionIdForWorker';\n}\n\nexport interface TraceEventFrameCommittedInBrowser extends TraceEventInstant {\n name: 'FrameCommittedInBrowser';\n args: TraceEventArgs&{\n data?: TraceEventArgsData & TraceFrame,\n };\n}\n\nexport interface TraceEventMainFrameViewport extends TraceEventInstant {\n name: 'PaintTimingVisualizer::Viewport';\n args: {\n data: TraceEventArgsData&{\n // eslint-disable-next-line @typescript-eslint/naming-convention\n viewport_rect: number[],\n },\n };\n}\n\nexport interface TraceEventCommitLoad extends TraceEventInstant {\n name: 'CommitLoad';\n args: TraceEventArgs&{\n data?: TraceEventArgsData & {\n frame: string,\n isMainFrame: boolean,\n name: string,\n nodeId: number,\n page: string,\n parent: string,\n url: string,\n },\n };\n}\n\nexport interface TraceEventMarkDOMContent extends TraceEventInstant {\n name: 'MarkDOMContent';\n args: TraceEventArgs&{\n data?: TraceEventArgsData & {\n frame: string,\n isMainFrame: boolean,\n isOutermostMainFrame?: boolean, page: string,\n },\n };\n}\n\nexport interface TraceEventMarkLoad extends TraceEventInstant {\n name: 'MarkLoad';\n args: TraceEventArgs&{\n data?: TraceEventArgsData & {\n frame: string,\n isMainFrame: boolean,\n page: string,\n isOutermostMainFrame?: boolean,\n },\n };\n}\n\nexport interface TraceEventAsync extends TraceEventData {\n ph: Phase.ASYNC_NESTABLE_START|Phase.ASYNC_NESTABLE_INSTANT|Phase.ASYNC_NESTABLE_END|Phase.ASYNC_STEP_INTO|\n Phase.ASYNC_BEGIN|Phase.ASYNC_END|Phase.ASYNC_STEP_PAST;\n}\n\nexport type TraceRect = [number, number, number, number];\nexport type TraceImpactedNode = {\n // These keys come from the trace data, so we have to use underscores.\n /* eslint-disable @typescript-eslint/naming-convention */\n new_rect: TraceRect,\n node_id: Protocol.DOM.BackendNodeId,\n old_rect: TraceRect,\n /* eslint-enable @typescript-eslint/naming-convention */\n};\n\ntype LayoutShiftData = TraceEventArgsData&{\n // These keys come from the trace data, so we have to use underscores.\n /* eslint-disable @typescript-eslint/naming-convention */\n cumulative_score: number,\n frame_max_distance: number,\n had_recent_input: boolean,\n impacted_nodes: TraceImpactedNode[] | undefined,\n is_main_frame: boolean,\n overall_max_distance: number,\n region_rects: TraceRect[],\n score: number,\n weighted_score_delta: number,\n navigationId?: string,\n /* eslint-enable @typescript-eslint/naming-convention */\n};\n// These keys come from the trace data, so we have to use underscores.\nexport interface TraceEventLayoutShift extends TraceEventInstant {\n name: 'LayoutShift';\n normalized?: boolean;\n args: TraceEventArgs&{\n frame: string,\n data?: LayoutShiftData,\n };\n}\n\ninterface LayoutShiftSessionWindowData {\n // The sum of the weighted score of all the shifts\n // that belong to a session window.\n cumulativeWindowScore: number;\n // A consecutive generated in the frontend to\n // to identify a session window.\n id: number;\n}\nexport interface LayoutShiftParsedData {\n screenshotSource?: string;\n timeFromNavigation?: MicroSeconds;\n // The sum of the weighted scores of the shifts that\n // belong to a session window up until this shift\n // (inclusive).\n cumulativeWeightedScoreInWindow: number;\n sessionWindowData: LayoutShiftSessionWindowData;\n}\nexport interface SyntheticLayoutShift extends TraceEventLayoutShift, SyntheticBasedEvent {\n name: 'LayoutShift';\n rawSourceEvent: TraceEventLayoutShift;\n args: TraceEventArgs&{\n frame: string,\n data?: LayoutShiftData&{\n rawEvent: TraceEventLayoutShift,\n },\n };\n parsedData: LayoutShiftParsedData;\n}\n\n/**\n * This is a synthetic Layout shift cluster. Not based on a raw event as there's no concept\n * of this as a trace event.\n */\nexport interface SyntheticLayoutShiftCluster {\n name: 'SyntheticLayoutShiftCluster';\n clusterWindow: TraceWindowMicroSeconds;\n clusterCumulativeScore: number;\n events: SyntheticLayoutShift[];\n // For convenience we split apart the cluster into good, NI, and bad windows.\n // Since a cluster may remain in the good window, we mark NI and bad as being\n // possibly null.\n scoreWindows: {\n good: TraceWindowMicroSeconds,\n needsImprovement?: TraceWindowMicroSeconds,\n bad?: TraceWindowMicroSeconds,\n };\n // The last navigation that happened before this cluster.\n navigationId?: string;\n worstShiftEvent?: TraceEventData;\n // This is the start of the cluster: the start of the first layout shift of the cluster.\n ts: MicroSeconds;\n // The duration of the cluster. This should include up until the end of the last\n // layout shift in this cluster.\n dur?: MicroSeconds;\n cat: '';\n ph: Phase.COMPLETE;\n pid: ProcessID;\n tid: ThreadID;\n}\n\nexport type FetchPriorityHint = 'low'|'high'|'auto';\nexport type RenderBlocking = 'blocking'|'non_blocking'|'in_body_parser_blocking'|'potentially_blocking';\n\nexport interface Initiator {\n type: Protocol.Network.InitiatorType;\n fetchType: string;\n columnNumber?: number;\n lineNumber?: number;\n url?: string;\n}\n\nexport interface TraceEventResourceSendRequest extends TraceEventInstant {\n name: 'ResourceSendRequest';\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n frame: string,\n requestId: string,\n url: string,\n priority: Protocol.Network.ResourcePriority,\n resourceType: Protocol.Network.ResourceType,\n fetchPriorityHint: FetchPriorityHint,\n // TODO(crbug.com/1457985): change requestMethod to enum when confirm in the backend code.\n requestMethod?: string,\n renderBlocking?: RenderBlocking,\n initiator?: Initiator,\n isLinkPreload?: boolean,\n },\n };\n}\n\nexport interface TraceEventResourceChangePriority extends TraceEventInstant {\n name: 'ResourceChangePriority';\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n requestId: string,\n priority: Protocol.Network.ResourcePriority,\n },\n };\n}\n\nexport interface TraceEventResourceWillSendRequest extends TraceEventInstant {\n name: 'ResourceWillSendRequest';\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n requestId: string,\n },\n };\n}\n\nexport interface TraceEventResourceFinish extends TraceEventInstant {\n name: 'ResourceFinish';\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n decodedBodyLength: number,\n didFail: boolean,\n encodedDataLength: number,\n finishTime: Seconds,\n requestId: string,\n },\n };\n}\n\nexport interface TraceEventResourceReceivedData extends TraceEventInstant {\n name: 'ResourceReceivedData';\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n encodedDataLength: number,\n frame: string,\n requestId: string,\n },\n };\n}\n\ninterface TraceEventResourceReceiveResponseTimingData {\n connectEnd: MilliSeconds;\n connectStart: MilliSeconds;\n dnsEnd: MilliSeconds;\n dnsStart: MilliSeconds;\n proxyEnd: MilliSeconds;\n proxyStart: MilliSeconds;\n pushEnd: MilliSeconds;\n pushStart: MilliSeconds;\n receiveHeadersEnd: MilliSeconds;\n receiveHeadersStart: MilliSeconds;\n requestTime: Seconds;\n sendEnd: MilliSeconds;\n sendStart: MilliSeconds;\n sslEnd: MilliSeconds;\n sslStart: MilliSeconds;\n workerReady: MilliSeconds;\n workerStart: MilliSeconds;\n}\n\nexport interface TraceEventResourceReceiveResponse extends TraceEventInstant {\n name: 'ResourceReceiveResponse';\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n /**\n * This is the protocol used to resolve the request.\n *\n * Note, this is not the same as URL.protocol.\n *\n * Example values (not exhaustive): http/0.9, http/1.0, http/1.1, http, h2, h3-Q050, data, blob\n */\n protocol: string,\n encodedDataLength: number,\n frame: string,\n fromCache: boolean,\n fromServiceWorker: boolean,\n mimeType: string,\n requestId: string,\n responseTime: MilliSeconds,\n statusCode: number,\n // Some cached events don't have this field\n timing?: TraceEventResourceReceiveResponseTimingData, connectionId: number, connectionReused: boolean,\n headers?: Array<{name: string, value: string}>,\n },\n };\n}\n\nexport interface TraceEventResourceMarkAsCached extends TraceEventInstant {\n name: 'ResourceMarkAsCached';\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n requestId: string,\n },\n };\n}\n\nexport const enum LayoutInvalidationReason {\n SIZE_CHANGED = 'Size changed',\n ATTRIBUTE = 'Attribute',\n ADDED_TO_LAYOUT = 'Added to layout',\n SCROLLBAR_CHANGED = 'Scrollbar changed',\n REMOVED_FROM_LAYOUT = 'Removed from layout',\n STYLE_CHANGED = 'Style changed',\n FONTS_CHANGED = 'Fonts changed',\n UNKNOWN = 'Unknown',\n}\n\nexport interface TraceEventLayoutInvalidationTracking extends TraceEventInstant {\n name: KnownEventName.LAYOUT_INVALIDATION_TRACKING;\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n frame: string,\n nodeId: Protocol.DOM.BackendNodeId,\n reason: LayoutInvalidationReason,\n nodeName?: string,\n },\n };\n}\n\nexport interface TraceEventScheduleStyleInvalidationTracking extends TraceEventInstant {\n name: KnownEventName.SCHEDULE_STYLE_INVALIDATION_TRACKING;\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n frame: string,\n nodeId: Protocol.DOM.BackendNodeId,\n invalidationSet?: string,\n invalidatedSelectorId?: string,\n reason?: LayoutInvalidationReason,\n changedClass?: string,\n changedAttribute?: string,\n changedId?: string,\n nodeName?: string,\n stackTrace?: TraceEventCallFrame[],\n },\n };\n}\nexport function isTraceEventScheduleStyleInvalidationTracking(event: TraceEventData):\n event is TraceEventScheduleStyleInvalidationTracking {\n return event.name === KnownEventName.SCHEDULE_STYLE_INVALIDATION_TRACKING;\n}\n\nexport const enum StyleRecalcInvalidationReason {\n ANIMATION = 'Animation',\n}\n\nexport interface TraceEventStyleRecalcInvalidationTracking extends TraceEventInstant {\n name: KnownEventName.STYLE_RECALC_INVALIDATION_TRACKING;\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n frame: string,\n nodeId: Protocol.DOM.BackendNodeId,\n reason: StyleRecalcInvalidationReason,\n subtree: boolean,\n nodeName?: string,\n extraData?: string,\n },\n };\n}\n\nexport function isTraceEventStyleRecalcInvalidationTracking(event: TraceEventData):\n event is TraceEventStyleRecalcInvalidationTracking {\n return event.name === KnownEventName.STYLE_RECALC_INVALIDATION_TRACKING;\n}\nexport interface TraceEventStyleInvalidatorInvalidationTracking extends TraceEventInstant {\n name: KnownEventName.STYLE_INVALIDATOR_INVALIDATION_TRACKING;\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n frame: string,\n nodeId: Protocol.DOM.BackendNodeId,\n reason: string,\n invalidationList: Array<{classes?: string[], id: string}>,\n subtree: boolean,\n nodeName?: string,\n extraData?: string,\n },\n };\n}\nexport function isTraceEventStyleInvalidatorInvalidationTracking(event: TraceEventData):\n event is TraceEventStyleInvalidatorInvalidationTracking {\n return event.name === KnownEventName.STYLE_INVALIDATOR_INVALIDATION_TRACKING;\n}\n\nexport interface TraceEventBeginCommitCompositorFrame extends TraceEventInstant {\n name: KnownEventName.BEGIN_COMMIT_COMPOSITOR_FRAME;\n args: TraceEventArgs&{\n frame: string,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n is_mobile_optimized: boolean,\n };\n}\nexport function isTraceEventBeginCommitCompositorFrame(event: TraceEventData):\n event is TraceEventBeginCommitCompositorFrame {\n return event.name === KnownEventName.BEGIN_COMMIT_COMPOSITOR_FRAME;\n}\n\nexport interface TraceEventParseMetaViewport extends TraceEventInstant {\n name: KnownEventName.PARSE_META_VIEWPORT;\n args: TraceEventArgs&{\n data: {\n frame: string,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n node_id: Protocol.DOM.BackendNodeId,\n content: string,\n },\n };\n}\nexport function isTraceEventParseMetaViewport(event: TraceEventData): event is TraceEventParseMetaViewport {\n return event.name === KnownEventName.PARSE_META_VIEWPORT;\n}\n\nexport interface TraceEventScheduleStyleRecalculation extends TraceEventInstant {\n name: KnownEventName.SCHEDULE_STYLE_RECALCULATION;\n args: TraceEventArgs&{\n data: {\n frame: string,\n },\n };\n}\nexport function isTraceEventScheduleStyleRecalculation(event: TraceEventData):\n event is TraceEventScheduleStyleRecalculation {\n return event.name === KnownEventName.SCHEDULE_STYLE_RECALCULATION;\n}\n\nexport interface TraceEventRenderFrameImplCreateChildFrame extends TraceEventData {\n name: KnownEventName.RENDER_FRAME_IMPL_CREATE_CHILD_FRAME;\n /* eslint-disable @typescript-eslint/naming-convention */\n args: TraceEventArgs&{\n child_frame_token: string,\n frame_token: string,\n };\n}\nexport function isTraceEventRenderFrameImplCreateChildFrame(event: TraceEventData):\n event is TraceEventRenderFrameImplCreateChildFrame {\n return event.name === KnownEventName.RENDER_FRAME_IMPL_CREATE_CHILD_FRAME;\n}\n\nexport interface TraceEventPrePaint extends TraceEventComplete {\n name: 'PrePaint';\n}\n\nexport interface TraceEventPairableAsync extends TraceEventData {\n ph: Phase.ASYNC_NESTABLE_START|Phase.ASYNC_NESTABLE_END|Phase.ASYNC_NESTABLE_INSTANT;\n // The id2 field gives flexibility to explicitly specify if an event\n // id is global among processes or process local. However not all\n // events use it, so both kind of ids need to be marked as optional.\n id2?: {local?: string, global?: string};\n id?: string;\n}\nexport interface TraceEventPairableAsyncBegin extends TraceEventPairableAsync {\n ph: Phase.ASYNC_NESTABLE_START;\n}\n\nexport interface TraceEventPairableAsyncInstant extends TraceEventPairableAsync {\n ph: Phase.ASYNC_NESTABLE_INSTANT;\n}\n\nexport interface TraceEventPairableAsyncEnd extends TraceEventPairableAsync {\n ph: Phase.ASYNC_NESTABLE_END;\n}\n\nexport interface TraceEventUserTiming extends TraceEventData {\n id2?: {local?: string, global?: string};\n id?: string;\n cat: 'blink.user_timing';\n // Note that the timestamp for user timing trace events is set to the\n // start time passed by the user at the call site of the timing (based\n // on the UserTiming spec).\n // https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/timing/performance_user_timing.cc;l=236;drc=494419358caf690316f160a1f27d9e771a14c033\n}\n\nexport interface TraceEventDomLoading extends TraceEventUserTiming {\n name: KnownEventName.DOM_LOADING;\n args: TraceEventArgs&{\n frame?: string,\n };\n}\n\nexport type TraceEventPairableUserTiming = TraceEventUserTiming&TraceEventPairableAsync;\n\nexport interface TraceEventPerformanceMeasureBegin extends TraceEventPairableUserTiming {\n args: TraceEventArgs&{\n detail?: string,\n stackTrace?: TraceEventCallFrame[],\n };\n ph: Phase.ASYNC_NESTABLE_START;\n}\n\nexport type TraceEventPerformanceMeasureEnd = TraceEventPairableUserTiming&TraceEventPairableAsyncEnd;\nexport type TraceEventPerformanceMeasure = TraceEventPerformanceMeasureBegin|TraceEventPerformanceMeasureEnd;\n\nexport interface TraceEventPerformanceMark extends TraceEventUserTiming {\n args: TraceEventArgs&{\n data?: TraceEventArgsData & {\n detail?: string,\n stackTrace?: TraceEventCallFrame[],\n },\n };\n ph: Phase.INSTANT|Phase.MARK|Phase.ASYNC_NESTABLE_INSTANT;\n}\n\nexport interface TraceEventConsoleTimeBegin extends TraceEventPairableAsyncBegin {\n cat: 'blink.console';\n}\n\nexport interface TraceEventConsoleTimeEnd extends TraceEventPairableAsyncEnd {\n cat: 'blink.console';\n}\n\nexport type TraceEventConsoleTime = TraceEventConsoleTimeBegin|TraceEventConsoleTimeEnd;\n\nexport interface TraceEventTimeStamp extends TraceEventData {\n cat: 'devtools.timeline';\n name: 'TimeStamp';\n ph: Phase.INSTANT;\n id: string;\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n frame: string,\n message: string,\n },\n };\n}\n\nexport interface TraceEventTargetRundown extends TraceEventData {\n cat: 'disabled-by-default-devtools.target-rundown';\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n frame: string,\n frameType: string,\n url: string,\n isolate: string,\n v8context: string,\n origin: string,\n scriptId: number,\n isDefault?: boolean,\n contextType?: string,\n },\n };\n}\n\nexport function isTraceEventTargetRundown(traceEventData: TraceEventData): traceEventData is TraceEventTargetRundown {\n if (traceEventData.cat !== 'disabled-by-default-devtools.target-rundown') {\n return false;\n }\n const data = traceEventData.args?.data;\n if (!data) {\n return false;\n }\n return 'frame' in data && 'frameType' in data && 'url' in data && 'isolate' in data && 'v8context' in data &&\n 'scriptId' in data;\n}\n\nexport interface TraceEventScriptRundown extends TraceEventData {\n cat: 'disabled-by-default-devtools.v8-source-rundown';\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n isolate: string,\n executionContextId: number,\n scriptId: number,\n startLine: number,\n startColumn: number,\n endLine: number,\n endColumn: number,\n url: string,\n hash: string,\n isModule: boolean,\n hasSourceUrl: boolean,\n sourceMapUrl?: string,\n },\n };\n}\n\nexport function isTraceEventScriptRundown(traceEventData: TraceEventData): traceEventData is TraceEventScriptRundown {\n if (traceEventData.cat !== 'disabled-by-default-devtools.v8-source-rundown') {\n return false;\n }\n const data = traceEventData.args?.data;\n if (!data) {\n return false;\n }\n return 'isolate' in data && 'executionContextId' in data && 'scriptId' in data && 'startLine' in data &&\n 'startColumn' in data && 'endLine' in data && 'endColumn' in data && 'hash' in data && 'isModule' in data &&\n 'hasSourceUrl' in data;\n}\n\nexport interface TraceEventScriptRundownSource extends TraceEventData {\n cat: 'disabled-by-default-devtools.v8-source-rundown-sources';\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n isolate: string,\n scriptId: number,\n length?: number,\n sourceText?: string,\n },\n };\n}\n\nexport function isTraceEventScriptRundownSource(traceEventData: TraceEventData):\n traceEventData is TraceEventScriptRundownSource {\n if (traceEventData.cat !== 'disabled-by-default-devtools.v8-source-rundown-sources') {\n return false;\n }\n const data = traceEventData.args?.data;\n if (!data) {\n return false;\n }\n return 'isolate' in data && 'scriptId' in data && 'sourceText' in data;\n}\n\n/** ChromeFrameReporter args for PipelineReporter event.\n Matching proto: https://source.chromium.org/chromium/chromium/src/+/main:third_party/perfetto/protos/perfetto/trace/track_event/chrome_frame_reporter.proto\n */\n/* eslint-disable @typescript-eslint/naming-convention */\ninterface ChromeFrameReporter {\n state: State;\n enum: FrameDropReason;\n /** The reason is set only if |state| is not |STATE_UPDATED_ALL|. */\n reason: FrameDropReason;\n frame_source: number;\n /** Identifies a BeginFrameArgs (along with the source_id).\n See comments in components/viz/common/frame_sinks/begin_frame_args.h. */\n frame_sequence: number;\n /** If this is a droped frame (i.e. if |state| is set to |STATE_DROPPED| or\n |STATE_PRESENTED_PARTIAL|), then indicates whether this frame impacts smoothness. */\n affects_smoothness: boolean;\n /** The type of active scroll. */\n scroll_state: ScrollState;\n /** If any main thread animation is active during this frame. */\n has_main_animation: boolean;\n /** If any compositor thread animation is active during this frame. */\n has_compositor_animation: boolean;\n /** If any touch-driven UX (not scroll) is active during this frame. */\n has_smooth_input_main: boolean;\n /** Whether the frame contained any missing content (i.e. whether there was\n checkerboarding in the frame). */\n has_missing_content: boolean;\n /** The id of layer_tree_host that the frame has been produced for. */\n layer_tree_host_id: number;\n /** If total latency of PipelineReporter exceeds a certain limit. */\n has_high_latency: boolean;\n /** Indicate if the frame is \"FORKED\" (i.e. a PipelineReporter event starts at\n the same frame sequence as another PipelineReporter) or \"BACKFILL\"\n (i.e. dropped frames when there are no partial compositor updates). */\n frame_type: FrameType;\n /** The breakdown stage of PipelineReporter that is most likely accountable for\n high latency. */\n high_latency_contribution_stage: string[];\n}\nconst enum State {\n /** The frame did not have any updates to present. **/\n STATE_NO_UPDATE_DESIRED = 'STATE_NO_UPDATE_DESIRED',\n /** The frame presented all the desired updates (i.e. any updates requested\n from both the compositor thread and main-threads were handled). **/\n STATE_PRESENTED_ALL = 'STATE_PRESENTED_ALL',\n /** The frame was presented with some updates, but also missed some updates\n (e.g. missed updates from the main-thread, but included updates from the\n compositor thread). **/\n STATE_PRESENTED_PARTIAL = 'STATE_PRESENTED_PARTIAL',\n /** The frame was dropped, i.e. some updates were desired for the frame, but\n was not presented. **/\n STATE_DROPPED = 'STATE_DROPPED',\n}\n\nconst enum FrameDropReason {\n REASON_UNSPECIFIED = 'REASON_UNSPECIFIED',\n /** Frame was dropped by the display-compositor.\n The display-compositor may drop a frame some times (e.g. the frame missed\n the deadline, or was blocked on surface-sync, etc.) **/\n REASON_DISPLAY_COMPOSITOR = 'REASON_DISPLAY_COMPOSITOR',\n /** Frame was dropped because of the main-thread.\n The main-thread may cause a frame to be dropped, e.g. if the main-thread\n is running expensive javascript, or doing a lot of layout updates, etc. **/\n REASON_MAIN_THREAD = 'REASON_MAIN_THREAD',\n /** Frame was dropped by the client compositor.\n The client compositor can drop some frames too (e.g. attempting to\n recover latency, missing the deadline, etc.). **/\n REASON_CLIENT_COMPOSITOR = 'REASON_CLIENT_COMPOSITOR',\n}\n\nconst enum ScrollState {\n SCROLL_NONE = 'SCROLL_NONE',\n SCROLL_MAIN_THREAD = 'SCROLL_MAIN_THREAD',\n SCROLL_COMPOSITOR_THREAD = 'SCROLL_COMPOSITOR_THREAD',\n\n /** Used when it can't be determined whether a scroll is in progress or not. */\n SCROLL_UNKNOWN = 'SCROLL_UNKNOWN',\n}\nconst enum FrameType {\n FORKED = 'FORKED',\n BACKFILL = 'BACKFILL',\n}\n\nexport interface TraceEventPipelineReporter extends TraceEventData {\n id2?: {\n local?: string,\n };\n ph: Phase.ASYNC_NESTABLE_START|Phase.ASYNC_NESTABLE_END;\n args: TraceEventArgs&{\n chrome_frame_reporter: ChromeFrameReporter,\n };\n}\n\nexport function isTraceEventPipelineReporter(event: TraceEventData): event is TraceEventPipelineReporter {\n return event.name === KnownEventName.PIPELINE_REPORTER;\n}\n\n// A type used for synthetic events created based on a raw trace event.\n// A branded type is used to ensure not all events can be typed as\n// SyntheticBasedEvent and prevent places different to the\n// SyntheticEventsManager from creating synthetic events. This is\n// because synthetic events need to be registered in order to resolve\n// serialized event keys into event objects, so we ensure events are\n// registered at the time they are created by the SyntheticEventsManager.\nexport interface SyntheticBasedEvent extends TraceEventData {\n ph: Ph;\n rawSourceEvent: TraceEventData;\n _tag: 'SyntheticEntryTag';\n}\n\nexport function isSyntheticBasedEvent(event: TraceEventData): event is SyntheticBasedEvent {\n return 'rawSourceEvent' in event;\n}\n\n// Nestable async events with a duration are made up of two distinct\n// events: the begin, and the end. We need both of them to be able to\n// display the right information, so we create these synthetic events.\nexport interface SyntheticEventPair extends\n SyntheticBasedEvent {\n rawSourceEvent: TraceEventData;\n name: T['name'];\n cat: T['cat'];\n id?: string;\n id2?: {local?: string, global?: string};\n\n dur: MicroSeconds;\n args: TraceEventArgs&{\n data: {\n beginEvent: T & TraceEventPairableAsyncBegin,\n endEvent: T&TraceEventPairableAsyncEnd,\n instantEvents?: Array,\n },\n };\n}\n\nexport type SyntheticPipelineReporterPair = SyntheticEventPair;\n\nexport type SyntheticUserTimingPair = SyntheticEventPair;\n\nexport type SyntheticConsoleTimingPair = SyntheticEventPair;\n\nexport type SyntheticAnimationPair = SyntheticEventPair;\n\nexport interface SyntheticInteractionPair extends SyntheticEventPair {\n // InteractionID and type are available within the beginEvent's data, but we\n // put them on the top level for ease of access.\n interactionId: number;\n type: string;\n // This is equivalent to startEvent.ts;\n ts: MicroSeconds;\n // This duration can be calculated via endEvent.ts - startEvent.ts, but we do\n // that and put it here to make it easier. This also makes these events\n // consistent with real events that have a dur field.\n dur: MicroSeconds;\n // These values are provided in the startEvent's args.data field as\n // millisecond values, but during the handler phase we parse these into\n // microseconds and put them on the top level for easy access.\n processingStart: MicroSeconds;\n processingEnd: MicroSeconds;\n // These 3 values represent the breakdown of the parts of an interaction:\n // 1. inputDelay: time from the user clicking to the input being handled\n inputDelay: MicroSeconds;\n // 2. mainThreadHandling: time spent processing the event handler\n mainThreadHandling: MicroSeconds;\n // 3. presentationDelay: delay between the event being processed and the frame being rendered\n presentationDelay: MicroSeconds;\n}\n\n/**\n * A profile call created in the frontend from samples disguised as a\n * trace event.\n *\n * We store the sampleIndex, profileId and nodeId so that we can easily link\n * back a Synthetic Trace Entry to an indivdual Sample trace event within a\n * Profile.\n *\n * Because a sample contains a set of call frames representing the stack at the\n * point in time that the sample was created, we also have to store the ID of\n * the Node that points to the function call that this profile call represents.\n */\nexport interface SyntheticProfileCall extends TraceEventData {\n callFrame: Protocol.Runtime.CallFrame;\n nodeId: Protocol.integer;\n sampleIndex: number;\n profileId: ProfileID;\n}\n\n/**\n * A synthetic event created from the Server-Timing header of network\n * request. In order to create these synthetic events, the corresponding\n * metric (timing) in the header must contain a \"start\" param, which\n * corresponds to the timestamp of the metric in the server. The\n * ServerTimingsHandler implements a heuristic to estimate the offset\n * between the client clock and the server clock so that the server\n * timestamp can be translated to the tracing clock.\n */\nexport interface SyntheticServerTiming extends SyntheticBasedEvent {\n rawSourceEvent: TraceEventResourceSendRequest;\n cat: 'devtools.server-timing';\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n desc?: string, origin: string,\n },\n };\n}\n\n/**\n * A JS Sample reflects a single sample from the V8 CPU Profile\n */\nexport interface SyntheticJSSample extends TraceEventData {\n name: KnownEventName.JS_SAMPLE;\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n stackTrace: Protocol.Runtime.CallFrame[],\n },\n };\n ph: Phase.INSTANT;\n}\n\nexport function isSyntheticInteractionEvent(event: TraceEventData): event is SyntheticInteractionPair {\n return Boolean(\n 'interactionId' in event && event.args?.data && 'beginEvent' in event.args.data && 'endEvent' in event.args.data);\n}\n\n// Events relating to frames.\n\nexport interface TraceEventDrawFrame extends TraceEventInstant {\n name: KnownEventName.DRAW_FRAME;\n args: TraceEventArgs&{\n layerTreeId: number,\n frameSeqId: number,\n };\n}\n\nexport function isTraceEventDrawFrame(event: TraceEventData): event is TraceEventDrawFrame {\n // The extra check for INSTANT here is because in the past DrawFrame events had an ASYNC_NESTABLE_START and ASYNC_NESTABLE_END pair. We don't want to support those old events, so we have to check we are dealing with an instant event.\n return event.name === KnownEventName.DRAW_FRAME && event.ph === Phase.INSTANT;\n}\nexport interface TraceEventLegacyDrawFrameBegin extends TraceEventAsync {\n name: KnownEventName.DRAW_FRAME;\n ph: Phase.ASYNC_NESTABLE_START;\n args: TraceEventArgs&{\n layerTreeId: number,\n frameSeqId: number,\n };\n}\nexport function isLegacyTraceEventDrawFrameBegin(event: TraceEventData): event is TraceEventLegacyDrawFrameBegin {\n return event.name === KnownEventName.DRAW_FRAME && event.ph === Phase.ASYNC_NESTABLE_START;\n}\n\nexport interface TraceEventBeginFrame extends TraceEventInstant {\n name: KnownEventName.BEGIN_FRAME;\n args: TraceEventArgs&{\n layerTreeId: number,\n frameSeqId: number,\n };\n}\nexport function isTraceEventBeginFrame(event: TraceEventData): event is TraceEventBeginFrame {\n // Old traces did not have frameSeqId; but we do not want to support these.\n return Boolean(event.name === KnownEventName.BEGIN_FRAME && event.args && 'frameSeqId' in event.args);\n}\n\nexport interface TraceEventDroppedFrame extends TraceEventInstant {\n name: KnownEventName.DROPPED_FRAME;\n args: TraceEventArgs&{\n layerTreeId: number,\n frameSeqId: number,\n hasPartialUpdate?: boolean,\n };\n}\nexport function isTraceEventDroppedFrame(event: TraceEventData): event is TraceEventDroppedFrame {\n // Old traces did not have frameSeqId; but we do not want to support these.\n return Boolean(event.name === KnownEventName.DROPPED_FRAME && event.args && 'frameSeqId' in event.args);\n}\n\nexport interface TraceEventRequestMainThreadFrame extends TraceEventInstant {\n name: KnownEventName.REQUEST_MAIN_THREAD_FRAME;\n args: TraceEventArgs&{\n layerTreeId: number,\n };\n}\nexport function isTraceEventRequestMainThreadFrame(event: TraceEventData): event is TraceEventRequestMainThreadFrame {\n return event.name === KnownEventName.REQUEST_MAIN_THREAD_FRAME;\n}\n\nexport interface TraceEventBeginMainThreadFrame extends TraceEventInstant {\n name: KnownEventName.BEGIN_MAIN_THREAD_FRAME;\n args: TraceEventArgs&{\n layerTreeId: number,\n data: TraceEventArgsData&{\n frameId?: number,\n },\n };\n}\nexport function isTraceEventBeginMainThreadFrame(event: TraceEventData): event is TraceEventBeginMainThreadFrame {\n return event.name === KnownEventName.BEGIN_MAIN_THREAD_FRAME;\n}\n\nexport interface TraceEventNeedsBeginFrameChanged extends TraceEventInstant {\n name: KnownEventName.NEEDS_BEGIN_FRAME_CHANGED;\n args: TraceEventArgs&{\n layerTreeId: number,\n data: TraceEventArgsData&{\n needsBeginFrame: number,\n },\n };\n}\nexport function isTraceEventNeedsBeginFrameChanged(event: TraceEventData): event is TraceEventNeedsBeginFrameChanged {\n return event.name === KnownEventName.NEEDS_BEGIN_FRAME_CHANGED;\n}\n\nexport interface TraceEventCommit extends TraceEventInstant {\n name: KnownEventName.COMMIT;\n args: TraceEventArgs&{\n layerTreeId: number,\n frameSeqId: number,\n };\n}\nexport function isTraceEventCommit(event: TraceEventData): event is TraceEventCommit {\n // Old traces did not have frameSeqId; but we do not want to support these.\n return Boolean(event.name === KnownEventName.COMMIT && event.args && 'frameSeqId' in event.args);\n}\n\nexport interface TraceEventRasterTask extends TraceEventComplete {\n name: KnownEventName.RASTER_TASK;\n args: TraceEventArgs&{\n tileData?: {\n layerId: number,\n sourceFrameNumber: number,\n tileId: {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n id_ref: string,\n },\n tileResolution: string,\n },\n };\n}\nexport function isTraceEventRasterTask(event: TraceEventData): event is TraceEventRasterTask {\n return event.name === KnownEventName.RASTER_TASK;\n}\n\n// CompositeLayers has been replaced by \"Commit\", but we support both to not break old traces being imported.\nexport interface TraceEventCompositeLayers extends TraceEventInstant {\n name: KnownEventName.COMPOSITE_LAYERS;\n args: TraceEventArgs&{\n layerTreeId: number,\n };\n}\nexport function isTraceEventCompositeLayers(event: TraceEventData): event is TraceEventCompositeLayers {\n return event.name === KnownEventName.COMPOSITE_LAYERS;\n}\n\nexport interface TraceEventActivateLayerTree extends TraceEventInstant {\n name: KnownEventName.ACTIVATE_LAYER_TREE;\n args: TraceEventArgs&{\n layerTreeId: number,\n frameId: number,\n };\n}\nexport function isTraceEventActivateLayerTree(event: TraceEventData): event is TraceEventActivateLayerTree {\n return event.name === KnownEventName.ACTIVATE_LAYER_TREE;\n}\n\nexport type InvalidationTrackingEvent =\n TraceEventScheduleStyleInvalidationTracking|TraceEventStyleRecalcInvalidationTracking|\n TraceEventStyleInvalidatorInvalidationTracking|TraceEventLayoutInvalidationTracking;\n\nexport function isTraceEventInvalidationTracking(event: TraceEventData): event is InvalidationTrackingEvent {\n return isTraceEventScheduleStyleInvalidationTracking(event) || isTraceEventStyleRecalcInvalidationTracking(event) ||\n isTraceEventStyleInvalidatorInvalidationTracking(event) || isTraceEventLayoutInvalidationTracking(event);\n}\n\nexport interface TraceEventDrawLazyPixelRef extends TraceEventInstant {\n name: KnownEventName.DRAW_LAZY_PIXEL_REF;\n args?: TraceEventArgs&{\n // eslint-disable-next-line @typescript-eslint/naming-convention\n LazyPixelRef: number,\n };\n}\nexport function isTraceEventDrawLazyPixelRef(event: TraceEventData): event is TraceEventDrawLazyPixelRef {\n return event.name === KnownEventName.DRAW_LAZY_PIXEL_REF;\n}\n\nexport interface TraceEventDecodeLazyPixelRef extends TraceEventInstant {\n name: KnownEventName.DECODE_LAZY_PIXEL_REF;\n args?: TraceEventArgs&{\n // eslint-disable-next-line @typescript-eslint/naming-convention\n LazyPixelRef: number,\n };\n}\nexport function isTraceEventDecodeLazyPixelRef(event: TraceEventData): event is TraceEventDecodeLazyPixelRef {\n return event.name === KnownEventName.DECODE_LAZY_PIXEL_REF;\n}\n\nexport interface TraceEventDecodeImage extends TraceEventComplete {\n name: KnownEventName.DECODE_IMAGE;\n args: TraceEventArgs&{\n imageType: string,\n };\n}\nexport function isTraceEventDecodeImage(event: TraceEventData): event is TraceEventDecodeImage {\n return event.name === KnownEventName.DECODE_IMAGE;\n}\n\nexport interface SelectorTiming {\n 'elapsed (us)': number;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n 'fast_reject_count': number;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n 'match_attempts': number;\n 'selector': string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n 'style_sheet_id': string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n 'match_count': number;\n}\n\nexport enum SelectorTimingsKey {\n Elapsed = 'elapsed (us)',\n RejectPercentage = 'reject_percentage',\n FastRejectCount = 'fast_reject_count',\n MatchAttempts = 'match_attempts',\n MatchCount = 'match_count',\n Selector = 'selector',\n StyleSheetId = 'style_sheet_id',\n}\n\nexport interface SelectorStats {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n selector_timings: SelectorTiming[];\n}\n\nexport interface TraceEventSelectorStats extends TraceEventComplete {\n name: KnownEventName.SELECTOR_STATS;\n args: TraceEventArgs&{\n // eslint-disable-next-line @typescript-eslint/naming-convention\n selector_stats?: SelectorStats,\n };\n}\n\nexport function isTraceEventSelectorStats(event: TraceEventData): event is TraceEventSelectorStats {\n return event.name === KnownEventName.SELECTOR_STATS;\n}\n\nexport interface TraceEventUpdateLayoutTree extends TraceEventComplete {\n name: KnownEventName.UPDATE_LAYOUT_TREE;\n args: TraceEventArgs&{\n elementCount: number,\n beginData?: {\n frame: string,\n stackTrace?: TraceEventCallFrame[],\n },\n };\n}\nexport function isTraceEventUpdateLayoutTree(event: TraceEventData): event is TraceEventUpdateLayoutTree {\n return event.name === KnownEventName.UPDATE_LAYOUT_TREE;\n}\n\nexport interface TraceEventLayout extends TraceEventComplete {\n name: KnownEventName.LAYOUT;\n args: TraceEventArgs&{\n beginData: {\n frame: string,\n dirtyObjects: number,\n partialLayout: boolean,\n totalObjects: number,\n },\n // endData is not reliably populated.\n // Why? TBD. https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/frame/local_frame_view.cc;l=847-851;drc=8b6aaad8027390ce6b32d82d57328e93f34bb8e5\n endData?: {\n layoutRoots: Array<{\n depth: number,\n nodeId: Protocol.DOM.BackendNodeId,\n quads: number[][],\n }>,\n },\n };\n}\nexport function isTraceEventLayout(event: TraceEventData): event is TraceEventLayout {\n return event.name === KnownEventName.LAYOUT;\n}\nexport interface TraceEventInvalidateLayout extends TraceEventInstant {\n name: KnownEventName.INVALIDATE_LAYOUT;\n args: TraceEventArgs&{\n data: {\n frame: string,\n nodeId: Protocol.DOM.BackendNodeId,\n },\n };\n}\nexport function isTraceEventInvalidateLayout(event: TraceEventData): event is TraceEventInvalidateLayout {\n return event.name === KnownEventName.INVALIDATE_LAYOUT;\n}\n\nclass ProfileIdTag {\n readonly #profileIdTag: (symbol|undefined);\n}\nexport type ProfileID = string&ProfileIdTag;\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport function ProfileID(value: string): ProfileID {\n return value as ProfileID;\n}\n\nclass CallFrameIdTag {\n readonly #callFrameIdTag: (symbol|undefined);\n}\nexport type CallFrameID = number&CallFrameIdTag;\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport function CallFrameID(value: number): CallFrameID {\n return value as CallFrameID;\n}\n\nclass SampleIndexTag {\n readonly #sampleIndexTag: (symbol|undefined);\n}\nexport type SampleIndex = number&SampleIndexTag;\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport function SampleIndex(value: number): SampleIndex {\n return value as SampleIndex;\n}\n\nclass ProcessIdTag {\n readonly #processIdTag: (symbol|undefined);\n}\nexport type ProcessID = number&ProcessIdTag;\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport function ProcessID(value: number): ProcessID {\n return value as ProcessID;\n}\n\nclass ThreadIdTag {\n readonly #threadIdTag: (symbol|undefined);\n}\nexport type ThreadID = number&ThreadIdTag;\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport function ThreadID(value: number): ThreadID {\n return value as ThreadID;\n}\n\nclass WorkerIdTag {\n readonly #workerIdTag: (symbol|undefined);\n}\nexport type WorkerId = string&WorkerIdTag;\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport function WorkerId(value: string): WorkerId {\n return value as WorkerId;\n}\n\nexport function isTraceEventComplete(event: TraceEventData): event is TraceEventComplete {\n return event.ph === Phase.COMPLETE;\n}\n\nexport function isTraceEventBegin(event: TraceEventData): event is TraceEventBegin {\n return event.ph === Phase.BEGIN;\n}\n\nexport function isTraceEventEnd(event: TraceEventData): event is TraceEventEnd {\n return event.ph === Phase.END;\n}\n\nexport function isTraceEventDispatch(event: TraceEventData): event is TraceEventDispatch {\n return event.name === 'EventDispatch';\n}\n\nexport function isTraceEventInstant(event: TraceEventData): event is TraceEventInstant {\n return event.ph === Phase.INSTANT;\n}\n\nexport function isTraceEventRendererEvent(event: TraceEventData): event is TraceEventRendererEvent {\n return isTraceEventInstant(event) || isTraceEventComplete(event);\n}\n\nexport function isTraceEventFireIdleCallback(event: TraceEventData): event is TraceEventFireIdleCallback {\n return event.name === 'FireIdleCallback';\n}\n\nexport function isTraceEventSchedulePostMessage(event: TraceEventData): event is TraceEventSchedulePostMessage {\n return event.name === KnownEventName.SCHEDULE_POST_MESSAGE;\n}\n\nexport function isTraceEventHandlePostMessage(event: TraceEventData): event is TraceEventHandlePostMessage {\n return event.name === KnownEventName.HANDLE_POST_MESSAGE;\n}\n\nexport function isTraceEventUpdateCounters(event: TraceEventData): event is TraceEventUpdateCounters {\n return event.name === 'UpdateCounters';\n}\n\nexport function isThreadName(\n traceEventData: TraceEventData,\n ): traceEventData is TraceEventThreadName {\n return traceEventData.name === KnownEventName.THREAD_NAME;\n}\n\nexport function isProcessName(\n traceEventData: TraceEventData,\n ): traceEventData is TraceEventProcessName {\n return traceEventData.name === 'process_name';\n}\n\nexport function isTraceEventTracingStartedInBrowser(\n traceEventData: TraceEventData,\n ): traceEventData is TraceEventTracingStartedInBrowser {\n return traceEventData.name === KnownEventName.TRACING_STARTED_IN_BROWSER;\n}\n\nexport function isTraceEventFrameCommittedInBrowser(\n traceEventData: TraceEventData,\n ): traceEventData is TraceEventFrameCommittedInBrowser {\n return traceEventData.name === 'FrameCommittedInBrowser';\n}\n\nexport function isTraceEventCommitLoad(\n traceEventData: TraceEventData,\n ): traceEventData is TraceEventCommitLoad {\n return traceEventData.name === 'CommitLoad';\n}\n\nexport function isTraceEventNavigationStart(\n traceEventData: TraceEventData,\n ): traceEventData is TraceEventNavigationStart {\n return traceEventData.name === 'navigationStart';\n}\n\nexport function isTraceEventAnimation(\n traceEventData: TraceEventData,\n ): traceEventData is TraceEventAnimation {\n // We've found some rare traces with an Animtation trace event from a different category: https://crbug.com/1472375#comment7\n return traceEventData.name === 'Animation' && traceEventData.cat.includes('devtools.timeline');\n}\n\nexport function isTraceEventLayoutShift(\n traceEventData: TraceEventData,\n ): traceEventData is TraceEventLayoutShift {\n return traceEventData.name === 'LayoutShift';\n}\n\nexport function isTraceEventLayoutInvalidationTracking(\n traceEventData: TraceEventData,\n ): traceEventData is TraceEventLayoutInvalidationTracking {\n return traceEventData.name === KnownEventName.LAYOUT_INVALIDATION_TRACKING;\n}\n\nexport function isTraceEventFirstContentfulPaint(traceEventData: TraceEventData):\n traceEventData is TraceEventFirstContentfulPaint {\n return traceEventData.name === 'firstContentfulPaint';\n}\n\nexport function isTraceEventLargestContentfulPaintCandidate(traceEventData: TraceEventData):\n traceEventData is TraceEventLargestContentfulPaintCandidate {\n return traceEventData.name === KnownEventName.MARK_LCP_CANDIDATE;\n}\nexport function isTraceEventLargestImagePaintCandidate(traceEventData: TraceEventData):\n traceEventData is TraceEventLargestImagePaintCandidate {\n return traceEventData.name === 'LargestImagePaint::Candidate';\n}\nexport function isTraceEventLargestTextPaintCandidate(traceEventData: TraceEventData):\n traceEventData is TraceEventLargestTextPaintCandidate {\n return traceEventData.name === 'LargestTextPaint::Candidate';\n}\n\nexport function isTraceEventMarkLoad(traceEventData: TraceEventData): traceEventData is TraceEventMarkLoad {\n return traceEventData.name === 'MarkLoad';\n}\n\nexport function isTraceEventFirstPaint(traceEventData: TraceEventData): traceEventData is TraceEventFirstPaint {\n return traceEventData.name === 'firstPaint';\n}\n\nexport function isTraceEventMarkDOMContent(traceEventData: TraceEventData): traceEventData is TraceEventMarkDOMContent {\n return traceEventData.name === 'MarkDOMContent';\n}\n\nexport function isTraceEventInteractiveTime(traceEventData: TraceEventData):\n traceEventData is TraceEventInteractiveTime {\n return traceEventData.name === 'InteractiveTime';\n}\n\nexport function isTraceEventEventTiming(traceEventData: TraceEventData): traceEventData is TraceEventEventTiming {\n return traceEventData.name === KnownEventName.EVENT_TIMING;\n}\n\nexport function isTraceEventEventTimingEnd(traceEventData: TraceEventData): traceEventData is TraceEventEventTimingEnd {\n return isTraceEventEventTiming(traceEventData) && traceEventData.ph === Phase.ASYNC_NESTABLE_END;\n}\nexport function isTraceEventEventTimingStart(traceEventData: TraceEventData):\n traceEventData is TraceEventEventTimingBegin {\n return isTraceEventEventTiming(traceEventData) && traceEventData.ph === Phase.ASYNC_NESTABLE_START;\n}\n\nexport function isTraceEventGPUTask(traceEventData: TraceEventData): traceEventData is TraceEventGPUTask {\n return traceEventData.name === 'GPUTask';\n}\n\nexport function isTraceEventProfile(traceEventData: TraceEventData): traceEventData is TraceEventProfile {\n return traceEventData.name === 'Profile';\n}\n\nexport function isSyntheticCpuProfile(traceEventData: TraceEventData): traceEventData is SyntheticCpuProfile {\n return traceEventData.name === 'CpuProfile';\n}\n\nexport function isTraceEventProfileChunk(traceEventData: TraceEventData): traceEventData is TraceEventProfileChunk {\n return traceEventData.name === 'ProfileChunk';\n}\n\nexport function isTraceEventResourceChangePriority(\n traceEventData: TraceEventData,\n ): traceEventData is TraceEventResourceChangePriority {\n return traceEventData.name === 'ResourceChangePriority';\n}\n\nexport function isTraceEventResourceSendRequest(\n traceEventData: TraceEventData,\n ): traceEventData is TraceEventResourceSendRequest {\n return traceEventData.name === 'ResourceSendRequest';\n}\n\nexport function isTraceEventResourceReceiveResponse(\n traceEventData: TraceEventData,\n ): traceEventData is TraceEventResourceReceiveResponse {\n return traceEventData.name === 'ResourceReceiveResponse';\n}\n\nexport function isTraceEventResourceMarkAsCached(\n traceEventData: TraceEventData,\n ): traceEventData is TraceEventResourceMarkAsCached {\n return traceEventData.name === 'ResourceMarkAsCached';\n}\n\nexport function isTraceEventResourceFinish(\n traceEventData: TraceEventData,\n ): traceEventData is TraceEventResourceFinish {\n return traceEventData.name === 'ResourceFinish';\n}\n\nexport function isTraceEventResourceWillSendRequest(\n traceEventData: TraceEventData,\n ): traceEventData is TraceEventResourceWillSendRequest {\n return traceEventData.name === 'ResourceWillSendRequest';\n}\n\nexport function isTraceEventResourceReceivedData(\n traceEventData: TraceEventData,\n ): traceEventData is TraceEventResourceReceivedData {\n return traceEventData.name === 'ResourceReceivedData';\n}\n\nexport function isSyntheticNetworkRequestEvent(\n traceEventData: TraceEventData,\n ): traceEventData is SyntheticNetworkRequest {\n return traceEventData.name === 'SyntheticNetworkRequest';\n}\n\nexport function isSyntheticWebSocketConnectionEvent(\n traceEventData: TraceEventData,\n ): traceEventData is SyntheticWebSocketConnectionEvent {\n return traceEventData.name === 'SyntheticWebSocketConnectionEvent';\n}\n\nexport function isNetworkTrackEntry(traceEventData: TraceEventData):\n traceEventData is SyntheticWebSocketConnectionEvent|SyntheticNetworkRequest {\n return isSyntheticNetworkRequestEvent(traceEventData) || isSyntheticWebSocketConnectionEvent(traceEventData) ||\n isWebSocketTraceEvent(traceEventData);\n}\n\nexport function isTraceEventPrePaint(\n traceEventData: TraceEventData,\n ): traceEventData is TraceEventPrePaint {\n return traceEventData.name === 'PrePaint';\n}\n\nexport function isTraceEventNavigationStartWithURL(event: TraceEventData): event is TraceEventNavigationStart {\n return Boolean(isTraceEventNavigationStart(event) && event.args.data && event.args.data.documentLoaderURL !== '');\n}\n\nexport function isTraceEventMainFrameViewport(\n traceEventData: TraceEventData,\n ): traceEventData is TraceEventMainFrameViewport {\n return traceEventData.name === 'PaintTimingVisualizer::Viewport';\n}\n\nexport function isSyntheticUserTiming(traceEventData: TraceEventData): traceEventData is SyntheticUserTimingPair {\n if (traceEventData.cat !== 'blink.user_timing') {\n return false;\n }\n const data = traceEventData.args?.data;\n if (!data) {\n return false;\n }\n return 'beginEvent' in data && 'endEvent' in data;\n}\n\nexport function isSyntheticConsoleTiming(traceEventData: TraceEventData): traceEventData is SyntheticConsoleTimingPair {\n if (traceEventData.cat !== 'blink.console') {\n return false;\n }\n const data = traceEventData.args?.data;\n if (!data) {\n return false;\n }\n return 'beginEvent' in data && 'endEvent' in data;\n}\n\nexport function isTraceEventUserTiming(traceEventData: TraceEventData): traceEventData is TraceEventUserTiming {\n return traceEventData.cat === 'blink.user_timing';\n}\n\nexport function isTraceEventDomLoading(traceEventData: TraceEventData): traceEventData is TraceEventDomLoading {\n return traceEventData.name === KnownEventName.DOM_LOADING;\n}\n\nexport function isTraceEventPerformanceMeasure(traceEventData: TraceEventData):\n traceEventData is TraceEventPerformanceMeasure {\n return isTraceEventUserTiming(traceEventData) && isTraceEventAsyncPhase(traceEventData);\n}\n\nexport function isTraceEventPerformanceMark(traceEventData: TraceEventData):\n traceEventData is TraceEventPerformanceMark {\n return isTraceEventUserTiming(traceEventData) &&\n (traceEventData.ph === Phase.MARK || traceEventData.ph === Phase.INSTANT);\n}\n\nexport function isTraceEventConsoleTime(traceEventData: TraceEventData): traceEventData is TraceEventConsoleTime {\n return traceEventData.cat === 'blink.console' && isTraceEventAsyncPhase(traceEventData);\n}\n\nexport function isTraceEventTimeStamp(traceEventData: TraceEventData): traceEventData is TraceEventTimeStamp {\n return traceEventData.ph === Phase.INSTANT && traceEventData.name === 'TimeStamp';\n}\n\nexport function isTraceEventParseHTML(traceEventData: TraceEventData): traceEventData is TraceEventParseHTML {\n return traceEventData.name === 'ParseHTML';\n}\n\nexport interface TraceEventAsync extends TraceEventData {\n ph: Phase.ASYNC_NESTABLE_START|Phase.ASYNC_NESTABLE_INSTANT|Phase.ASYNC_NESTABLE_END|Phase.ASYNC_STEP_INTO|\n Phase.ASYNC_BEGIN|Phase.ASYNC_END|Phase.ASYNC_STEP_PAST;\n}\n\nconst asyncPhases = new Set([\n Phase.ASYNC_NESTABLE_START,\n Phase.ASYNC_NESTABLE_INSTANT,\n Phase.ASYNC_NESTABLE_END,\n Phase.ASYNC_STEP_INTO,\n Phase.ASYNC_BEGIN,\n Phase.ASYNC_END,\n Phase.ASYNC_STEP_PAST,\n]);\n\nexport function isTraceEventAsyncPhase(traceEventData: TraceEventData): boolean {\n return asyncPhases.has(traceEventData.ph);\n}\n\nexport function isSyntheticLayoutShift(traceEventData: TraceEventData): traceEventData is SyntheticLayoutShift {\n if (!isTraceEventLayoutShift(traceEventData) || !traceEventData.args.data) {\n return false;\n }\n return 'rawEvent' in traceEventData.args.data;\n}\n\nexport function isSyntheticLayoutShiftCluster(traceEventData: TraceEventData):\n traceEventData is SyntheticLayoutShiftCluster {\n return traceEventData.name === KnownEventName.SYNTHETIC_LAYOUT_SHIFT_CLUSTER;\n}\n\nexport function isProfileCall(event: TraceEventData): event is SyntheticProfileCall {\n return 'callFrame' in event;\n}\n\nexport interface TraceEventPaint extends TraceEventComplete {\n name: KnownEventName.PAINT;\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n clip: number[],\n frame: string,\n layerId: number,\n // With CompositeAfterPaint enabled, paint events are no longer\n // associated with a Node, and nodeId will not be present.\n nodeId?: Protocol.DOM.BackendNodeId,\n },\n };\n}\n\nexport function isTraceEventPaint(event: TraceEventData): event is TraceEventPaint {\n return event.name === KnownEventName.PAINT;\n}\n\nexport interface TraceEventPaintImage extends TraceEventComplete {\n name: KnownEventName.PAINT_IMAGE;\n args: TraceEventArgs&{\n data: TraceEventData & {\n height: number,\n width: number,\n x: number,\n y: number,\n url?: string, srcHeight: number, srcWidth: number,\n nodeId?: Protocol.DOM.BackendNodeId,\n },\n };\n}\nexport function isTraceEventPaintImage(event: TraceEventData): event is TraceEventPaintImage {\n return event.name === KnownEventName.PAINT_IMAGE;\n}\n\nexport interface TraceEventScrollLayer extends TraceEventComplete {\n name: KnownEventName.SCROLL_LAYER;\n args: TraceEventArgs&{\n data: TraceEventData & {\n frame: string,\n nodeId?: Protocol.DOM.BackendNodeId,\n },\n };\n}\nexport function isTraceEventScrollLayer(event: TraceEventData): event is TraceEventScrollLayer {\n return event.name === KnownEventName.SCROLL_LAYER;\n}\n\nexport interface TraceEventSetLayerTreeId extends TraceEventInstant {\n name: KnownEventName.SET_LAYER_TREE_ID;\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n frame: string,\n layerTreeId: number,\n },\n };\n}\nexport function isTraceEventSetLayerId(event: TraceEventData): event is TraceEventSetLayerTreeId {\n return event.name === KnownEventName.SET_LAYER_TREE_ID;\n}\nexport interface TraceEventUpdateLayer extends TraceEventComplete {\n name: KnownEventName.UPDATE_LAYER;\n args: TraceEventArgs&{\n layerId: number,\n layerTreeId: number,\n };\n}\nexport function isTraceEventUpdateLayer(event: TraceEventData): event is TraceEventUpdateLayer {\n return event.name === KnownEventName.UPDATE_LAYER;\n}\n\nexport interface TraceEventDisplayItemListSnapshot extends TraceEventData {\n name: KnownEventName.DISPLAY_ITEM_LIST_SNAPSHOT;\n ph: Phase.OBJECT_SNAPSHOT;\n id2: {\n local?: string,\n };\n args: TraceEventArgs&{\n snapshot: {\n skp64: string,\n params?: {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n layer_rect: [number, number, number, number],\n },\n },\n };\n}\nexport function isTraceEventDisplayListItemListSnapshot(event: TraceEventData):\n event is TraceEventDisplayItemListSnapshot {\n return event.name === KnownEventName.DISPLAY_ITEM_LIST_SNAPSHOT;\n}\n\nexport interface TraceEventLayerTreeHostImplSnapshot extends TraceEventData {\n name: KnownEventName.LAYER_TREE_HOST_IMPL_SNAPSHOT;\n ph: Phase.OBJECT_SNAPSHOT;\n id: string;\n args: TraceEventArgs&{\n snapshot: {\n /* eslint-disable @typescript-eslint/naming-convention */\n active_tiles: Array<{\n id: string,\n layer_id: string,\n gpu_memory_usage: number,\n content_rect: number[],\n }>,\n device_viewport_size: {\n width: number,\n height: number,\n },\n active_tree: {\n root_layer: TraceLayer,\n layers: TraceLayer[],\n },\n /* eslint-enable @typescript-eslint/naming-convention */\n },\n };\n}\n\nexport function isTraceEventLayerTreeHostImplSnapshot(event: TraceEventData):\n event is TraceEventLayerTreeHostImplSnapshot {\n return event.name === KnownEventName.LAYER_TREE_HOST_IMPL_SNAPSHOT;\n}\n/* eslint-disable @typescript-eslint/naming-convention */\nexport interface TraceLayer {\n bounds: {height: number, width: number};\n children: TraceLayer[];\n layer_id: number;\n position: number[];\n scroll_offset: number[];\n layer_quad: number[];\n draws_content: number;\n gpu_memory_usage: number;\n transform: number[];\n owner_node: Protocol.DOM.BackendNodeId;\n compositing_reasons: string[];\n compositing_reason_ids: string[];\n non_fast_scrollable_region: number[];\n touch_event_handler_region: number[];\n wheel_event_handler_region: number[];\n scroll_event_handler_region: number[];\n}\n\nexport interface TracingLayerTile {\n id: string;\n layer_id: string;\n gpu_memory_usage: number;\n content_rect: number[];\n}\n/* eslint-enable @typescript-eslint/naming-convention */\n\nexport interface TraceEventFireAnimationFrame extends TraceEventComplete {\n name: KnownEventName.FIRE_ANIMATION_FRAME;\n args: TraceEventArgs&{\n data: {\n frame: string,\n id: number,\n },\n };\n}\nexport function isTraceEventFireAnimationFrame(event: TraceEventData): event is TraceEventFireAnimationFrame {\n return event.name === KnownEventName.FIRE_ANIMATION_FRAME;\n}\n\nexport interface TraceEventRequestAnimationFrame extends TraceEventInstant {\n name: KnownEventName.REQUEST_ANIMATION_FRAME;\n args: TraceEventArgs&{\n data: {\n frame: string,\n id: number,\n stackTrace?: TraceEventCallFrame,\n },\n };\n}\nexport function isTraceEventRequestAnimationFrame(event: TraceEventData): event is TraceEventRequestAnimationFrame {\n return event.name === KnownEventName.REQUEST_ANIMATION_FRAME;\n}\n\nexport interface TraceEventTimerInstall extends TraceEventInstant {\n name: KnownEventName.TIMER_INSTALL;\n args: TraceEventArgs&{\n data: {\n frame: string,\n singleShot: boolean,\n stackTrace?: TraceEventCallFrame, timeout: number, timerId: number,\n },\n };\n}\nexport function isTraceEventTimerInstall(event: TraceEventData): event is TraceEventTimerInstall {\n return event.name === KnownEventName.TIMER_INSTALL;\n}\n\nexport interface TraceEventTimerFire extends TraceEventComplete {\n name: KnownEventName.TIMER_FIRE;\n args: TraceEventArgs&{\n data: {\n frame: string,\n timerId: number,\n },\n };\n}\nexport function isTraceEventTimerFire(event: TraceEventData): event is TraceEventTimerFire {\n return event.name === KnownEventName.TIMER_FIRE;\n}\n\nexport interface TraceEventRequestIdleCallback extends TraceEventInstant {\n name: KnownEventName.REQUEST_IDLE_CALLBACK;\n args: TraceEventArgs&{\n data: {\n frame: string,\n id: number,\n timeout: number,\n stackTrace?: TraceEventCallFrame,\n },\n\n };\n}\nexport function isTraceEventRequestIdleCallback(event: TraceEventData): event is TraceEventRequestIdleCallback {\n return event.name === KnownEventName.REQUEST_IDLE_CALLBACK;\n}\n\nexport interface TraceEventWebSocketCreate extends TraceEventInstant {\n name: KnownEventName.WEB_SOCKET_CREATE;\n args: TraceEventArgs&{\n data: {\n identifier: number,\n url: string,\n frame?: string,\n workerId?: string,\n websocketProtocol?: string,\n stackTrace?: TraceEventCallFrame,\n },\n };\n}\nexport function isTraceEventWebSocketCreate(event: TraceEventData): event is TraceEventWebSocketCreate {\n return event.name === KnownEventName.WEB_SOCKET_CREATE;\n}\n\nexport interface TraceEventWebSocketInfo extends TraceEventInstant {\n name: KnownEventName.WEB_SOCKET_DESTROY|KnownEventName.WEB_SOCKET_RECEIVE_HANDSHAKE|\n KnownEventName.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST;\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n identifier: number,\n url: string,\n frame?: string,\n workerId?: string,\n },\n };\n}\nexport interface TraceEventWebSocketTransfer extends TraceEventInstant {\n name: KnownEventName.WEB_SOCKET_SEND|KnownEventName.WEB_SOCKET_RECEIVE;\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n identifier: number,\n url: string,\n frame?: string,\n workerId?: string, dataLength: number,\n },\n };\n}\nexport function isTraceEventWebSocketInfo(traceEventData: TraceEventData): traceEventData is TraceEventWebSocketInfo {\n return traceEventData.name === KnownEventName.WEB_SOCKET_SEND_HANDSHAKE_REQUEST ||\n traceEventData.name === KnownEventName.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST ||\n traceEventData.name === KnownEventName.WEB_SOCKET_DESTROY;\n}\n\nexport function isTraceEventWebSocketTransfer(traceEventData: TraceEventData):\n traceEventData is TraceEventWebSocketTransfer {\n return traceEventData.name === KnownEventName.WEB_SOCKET_SEND ||\n traceEventData.name === KnownEventName.WEB_SOCKET_RECEIVE;\n}\n\nexport interface TraceEventWebSocketSend extends TraceEventInstant {\n name: KnownEventName.WEB_SOCKET_SEND;\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n identifier: number,\n url: string,\n frame?: string,\n workerId?: string, dataLength: number,\n },\n };\n}\n\nexport function isTraceEventWebSocketSend(event: TraceEventData): event is TraceEventWebSocketSend {\n return event.name === KnownEventName.WEB_SOCKET_SEND;\n}\n\nexport interface TraceEventWebSocketReceive extends TraceEventInstant {\n name: KnownEventName.WEB_SOCKET_RECEIVE;\n args: TraceEventArgs&{\n data: TraceEventArgsData & {\n identifier: number,\n url: string,\n frame?: string,\n workerId?: string, dataLength: number,\n },\n };\n}\nexport function isTraceEventWebSocketReceive(event: TraceEventData): event is TraceEventWebSocketReceive {\n return event.name === KnownEventName.WEB_SOCKET_RECEIVE;\n}\n\nexport interface TraceEventWebSocketSendHandshakeRequest extends TraceEventInstant {\n name: KnownEventName.WEB_SOCKET_SEND_HANDSHAKE_REQUEST;\n args: TraceEventArgs&{\n data: {\n frame: string,\n identifier: number,\n },\n };\n}\nexport function isTraceEventWebSocketSendHandshakeRequest(event: TraceEventData):\n event is TraceEventWebSocketSendHandshakeRequest {\n return event.name === KnownEventName.WEB_SOCKET_SEND_HANDSHAKE_REQUEST;\n}\n\nexport interface TraceEventWebSocketReceiveHandshakeResponse extends TraceEventInstant {\n name: KnownEventName.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST;\n args: TraceEventArgs&{\n data: {\n frame: string,\n identifier: number,\n },\n };\n}\nexport function isTraceEventWebSocketReceiveHandshakeResponse(event: TraceEventData):\n event is TraceEventWebSocketReceiveHandshakeResponse {\n return event.name === KnownEventName.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST;\n}\n\nexport interface TraceEventWebSocketDestroy extends TraceEventInstant {\n name: KnownEventName.WEB_SOCKET_DESTROY;\n args: TraceEventArgs&{\n data: {\n frame: string,\n identifier: number,\n },\n };\n}\nexport function isTraceEventWebSocketDestroy(event: TraceEventData): event is TraceEventWebSocketDestroy {\n return event.name === KnownEventName.WEB_SOCKET_DESTROY;\n}\n\nexport type WebSocketTraceEvent = TraceEventWebSocketCreate|TraceEventWebSocketInfo|TraceEventWebSocketTransfer;\nexport function isWebSocketTraceEvent(event: TraceEventData): event is WebSocketTraceEvent {\n return isTraceEventWebSocketCreate(event) || isTraceEventWebSocketInfo(event) || isTraceEventWebSocketTransfer(event);\n}\n\nexport type WebSocketEvent = WebSocketTraceEvent|SyntheticWebSocketConnectionEvent;\nexport function isWebSocketEvent(event: TraceEventData): event is WebSocketTraceEvent|\n SyntheticWebSocketConnectionEvent {\n return isWebSocketTraceEvent(event) || isSyntheticWebSocketConnectionEvent(event);\n}\n\nexport interface TraceEventV8Compile extends TraceEventComplete {\n name: KnownEventName.COMPILE;\n args: TraceEventArgs&{\n data?: {\n url?: string,\n columnNumber?: number,\n consumedCacheSize?: number,\n cacheRejected?: boolean,\n cacheKind?: 'full'|'normal',\n lineNumber?: number,\n notStreamedReason?: string,\n streamed?: boolean,\n eager?: boolean,\n },\n fileName?: string,\n };\n}\nexport function isTraceEventV8Compile(event: TraceEventData): event is TraceEventV8Compile {\n return event.name === KnownEventName.COMPILE;\n}\n\nexport interface TraceEventFunctionCall extends TraceEventComplete {\n name: KnownEventName.FUNCTION_CALL;\n args: TraceEventArgs&{\n data?: {\n frame?: string,\n columnNumber?: number,\n lineNumber?: number,\n functionName?: string,\n scriptId?: number,\n url?: string,\n },\n };\n}\nexport function isTraceEventFunctionCall(event: TraceEventData): event is TraceEventFunctionCall {\n return event.name === KnownEventName.FUNCTION_CALL;\n}\n\nexport function isSyntheticServerTiming(event: TraceEventData): event is SyntheticServerTiming {\n return event.cat === 'devtools.server-timing';\n}\n\n/**\n * Generally, before JS is executed, a trace event is dispatched that\n * parents the JS calls. These we call \"invocation\" events. This\n * function determines if an event is one of such.\n */\nexport function isJSInvocationEvent(event: TraceEventData): boolean {\n switch (event.name) {\n case KnownEventName.RUN_MICROTASKS:\n case KnownEventName.FUNCTION_CALL:\n case KnownEventName.EVALUATE_SCRIPT:\n case KnownEventName.EVALUATE_MODULE:\n case KnownEventName.EVENT_DISPATCH:\n case KnownEventName.V8_EXECUTE:\n return true;\n }\n // Also consider any new v8 trace events. (eg 'V8.RunMicrotasks' and 'v8.run')\n if (event.name.startsWith('v8') || event.name.startsWith('V8')) {\n return true;\n }\n return false;\n}\n\n/**\n * This is an exhaustive list of events we track in the Performance\n * panel. Note not all of them are necessarliry shown in the flame\n * chart, some of them we only use for parsing.\n * TODO(crbug.com/1428024): Complete this enum.\n */\nexport const enum KnownEventName {\n /* Metadata */\n THREAD_NAME = 'thread_name',\n\n /* Task */\n PROGRAM = 'Program',\n RUN_TASK = 'RunTask',\n ASYNC_TASK = 'AsyncTask',\n RUN_MICROTASKS = 'RunMicrotasks',\n\n /* Load */\n XHR_LOAD = 'XHRLoad',\n XHR_READY_STATE_CHANGED = 'XHRReadyStateChange',\n /* Parse */\n PARSE_HTML = 'ParseHTML',\n PARSE_CSS = 'ParseAuthorStyleSheet',\n /* V8 */\n COMPILE_CODE = 'V8.CompileCode',\n COMPILE_MODULE = 'V8.CompileModule',\n // Although V8 emits the V8.CompileScript event, the event that actually\n // contains the useful information about the script (URL, etc), is contained\n // in the v8.compile event.\n // Yes, it is all lowercase compared to all the rest of the V8... events,\n // that is not a typo :)\n COMPILE = 'v8.compile',\n COMPILE_SCRIPT = 'V8.CompileScript',\n OPTIMIZE = 'V8.OptimizeCode',\n WASM_STREAM_FROM_RESPONSE_CALLBACK = 'v8.wasm.streamFromResponseCallback',\n WASM_COMPILED_MODULE = 'v8.wasm.compiledModule',\n WASM_CACHED_MODULE = 'v8.wasm.cachedModule',\n WASM_MODULE_CACHE_HIT = 'v8.wasm.moduleCacheHit',\n WASM_MODULE_CACHE_INVALID = 'v8.wasm.moduleCacheInvalid',\n /* Js */\n PROFILE_CALL = 'ProfileCall',\n EVALUATE_SCRIPT = 'EvaluateScript',\n FUNCTION_CALL = 'FunctionCall',\n EVENT_DISPATCH = 'EventDispatch',\n EVALUATE_MODULE = 'v8.evaluateModule',\n REQUEST_MAIN_THREAD_FRAME = 'RequestMainThreadFrame',\n REQUEST_ANIMATION_FRAME = 'RequestAnimationFrame',\n CANCEL_ANIMATION_FRAME = 'CancelAnimationFrame',\n FIRE_ANIMATION_FRAME = 'FireAnimationFrame',\n REQUEST_IDLE_CALLBACK = 'RequestIdleCallback',\n CANCEL_IDLE_CALLBACK = 'CancelIdleCallback',\n FIRE_IDLE_CALLBACK = 'FireIdleCallback',\n TIMER_INSTALL = 'TimerInstall',\n TIMER_REMOVE = 'TimerRemove',\n TIMER_FIRE = 'TimerFire',\n WEB_SOCKET_CREATE = 'WebSocketCreate',\n WEB_SOCKET_SEND_HANDSHAKE = 'WebSocketSendHandshakeRequest',\n WEB_SOCKET_RECEIVE_HANDSHAKE = 'WebSocketReceiveHandshakeResponse',\n WEB_SOCKET_DESTROY = 'WebSocketDestroy',\n WEB_SOCKET_SEND = 'WebSocketSend',\n WEB_SOCKET_RECEIVE = 'WebSocketReceive',\n CRYPTO_DO_ENCRYPT = 'DoEncrypt',\n CRYPTO_DO_ENCRYPT_REPLY = 'DoEncryptReply',\n CRYPTO_DO_DECRYPT = 'DoDecrypt',\n CRYPTO_DO_DECRYPT_REPLY = 'DoDecryptReply',\n CRYPTO_DO_DIGEST = 'DoDigest',\n CRYPTO_DO_DIGEST_REPLY = 'DoDigestReply',\n CRYPTO_DO_SIGN = 'DoSign',\n CRYPTO_DO_SIGN_REPLY = 'DoSignReply',\n CRYPTO_DO_VERIFY = 'DoVerify',\n CRYPTO_DO_VERIFY_REPLY = 'DoVerifyReply',\n V8_EXECUTE = 'V8.Execute',\n\n /* Gc */\n GC = 'GCEvent',\n DOMGC = 'BlinkGC.AtomicPhase',\n MAJOR_GC = 'MajorGC',\n MINOR_GC = 'MinorGC',\n GC_COLLECT_GARBARGE = 'BlinkGC.AtomicPhase',\n CPPGC_SWEEP = 'CppGC.IncrementalSweep',\n\n /* Layout */\n SCHEDULE_STYLE_RECALCULATION = 'ScheduleStyleRecalculation',\n LAYOUT = 'Layout',\n UPDATE_LAYOUT_TREE = 'UpdateLayoutTree',\n INVALIDATE_LAYOUT = 'InvalidateLayout',\n LAYOUT_INVALIDATION_TRACKING = 'LayoutInvalidationTracking',\n COMPUTE_INTERSECTION = 'ComputeIntersections',\n HIT_TEST = 'HitTest',\n PRE_PAINT = 'PrePaint',\n LAYERIZE = 'Layerize',\n LAYOUT_SHIFT = 'LayoutShift',\n SYNTHETIC_LAYOUT_SHIFT_CLUSTER = 'SyntheticLayoutShiftCluster',\n UPDATE_LAYER_TREE = 'UpdateLayerTree',\n SCHEDULE_STYLE_INVALIDATION_TRACKING = 'ScheduleStyleInvalidationTracking',\n STYLE_RECALC_INVALIDATION_TRACKING = 'StyleRecalcInvalidationTracking',\n STYLE_INVALIDATOR_INVALIDATION_TRACKING = 'StyleInvalidatorInvalidationTracking',\n SELECTOR_STATS = 'SelectorStats',\n BEGIN_COMMIT_COMPOSITOR_FRAME = 'BeginCommitCompositorFrame',\n PARSE_META_VIEWPORT = 'ParseMetaViewport',\n\n /* Paint */\n SCROLL_LAYER = 'ScrollLayer',\n UPDATE_LAYER = 'UpdateLayer',\n PAINT_SETUP = 'PaintSetup',\n PAINT = 'Paint',\n PAINT_IMAGE = 'PaintImage',\n COMMIT = 'Commit',\n COMPOSITE_LAYERS = 'CompositeLayers',\n RASTER_TASK = 'RasterTask',\n IMAGE_DECODE_TASK = 'ImageDecodeTask',\n IMAGE_UPLOAD_TASK = 'ImageUploadTask',\n DECODE_IMAGE = 'Decode Image',\n DRAW_LAZY_PIXEL_REF = 'Draw LazyPixelRef',\n DECODE_LAZY_PIXEL_REF = 'Decode LazyPixelRef',\n GPU_TASK = 'GPUTask',\n RASTERIZE = 'Rasterize',\n EVENT_TIMING = 'EventTiming',\n\n /* Compile */\n OPTIMIZE_CODE = 'V8.OptimizeCode',\n CACHE_SCRIPT = 'v8.produceCache',\n CACHE_MODULE = 'v8.produceModuleCache',\n // V8Sample events are coming from tracing and contain raw stacks with function addresses.\n // After being processed with help of JitCodeAdded and JitCodeMoved events they\n // get translated into function infos and stored as stacks in JSSample events.\n V8_SAMPLE = 'V8Sample',\n JIT_CODE_ADDED = 'JitCodeAdded',\n JIT_CODE_MOVED = 'JitCodeMoved',\n STREAMING_COMPILE_SCRIPT = 'v8.parseOnBackground',\n STREAMING_COMPILE_SCRIPT_WAITING = 'v8.parseOnBackgroundWaiting',\n STREAMING_COMPILE_SCRIPT_PARSING = 'v8.parseOnBackgroundParsing',\n BACKGROUND_DESERIALIZE = 'v8.deserializeOnBackground',\n FINALIZE_DESERIALIZATION = 'V8.FinalizeDeserialization',\n\n /* Markers */\n COMMIT_LOAD = 'CommitLoad',\n MARK_LOAD = 'MarkLoad',\n MARK_DOM_CONTENT = 'MarkDOMContent',\n MARK_FIRST_PAINT = 'firstPaint',\n MARK_FCP = 'firstContentfulPaint',\n MARK_LCP_CANDIDATE = 'largestContentfulPaint::Candidate',\n MARK_LCP_INVALIDATE = 'largestContentfulPaint::Invalidate',\n NAVIGATION_START = 'navigationStart',\n TIME_STAMP = 'TimeStamp',\n CONSOLE_TIME = 'ConsoleTime',\n USER_TIMING = 'UserTiming',\n INTERACTIVE_TIME = 'InteractiveTime',\n\n /* Frames */\n BEGIN_FRAME = 'BeginFrame',\n NEEDS_BEGIN_FRAME_CHANGED = 'NeedsBeginFrameChanged',\n BEGIN_MAIN_THREAD_FRAME = 'BeginMainThreadFrame',\n ACTIVATE_LAYER_TREE = 'ActivateLayerTree',\n DRAW_FRAME = 'DrawFrame',\n DROPPED_FRAME = 'DroppedFrame',\n FRAME_STARTED_LOADING = 'FrameStartedLoading',\n PIPELINE_REPORTER = 'PipelineReporter',\n SCREENSHOT = 'Screenshot',\n\n /* Network request events */\n RESOURCE_WILL_SEND_REQUEST = 'ResourceWillSendRequest',\n RESOURCE_SEND_REQUEST = 'ResourceSendRequest',\n RESOURCE_RECEIVE_RESPONSE = 'ResourceReceiveResponse',\n RESOURCE_RECEIVE_DATA = 'ResourceReceivedData',\n RESOURCE_FINISH = 'ResourceFinish',\n RESOURCE_MARK_AS_CACHED = 'ResourceMarkAsCached',\n\n /* Web sockets */\n WEB_SOCKET_SEND_HANDSHAKE_REQUEST = 'WebSocketSendHandshakeRequest',\n WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST = 'WebSocketReceiveHandshakeResponse',\n\n /* CPU Profiling */\n PROFILE = 'Profile',\n START_PROFILING = 'CpuProfiler::StartProfiling',\n PROFILE_CHUNK = 'ProfileChunk',\n UPDATE_COUNTERS = 'UpdateCounters',\n\n JS_SAMPLE = 'JSSample',\n\n /* Other */\n ANIMATION = 'Animation',\n PARSE_AUTHOR_STYLE_SHEET = 'ParseAuthorStyleSheet',\n EMBEDDER_CALLBACK = 'EmbedderCallback',\n SET_LAYER_TREE_ID = 'SetLayerTreeId',\n TRACING_STARTED_IN_PAGE = 'TracingStartedInPage',\n TRACING_STARTED_IN_BROWSER = 'TracingStartedInBrowser',\n TRACING_SESSION_ID_FOR_WORKER = 'TracingSessionIdForWorker',\n LAZY_PIXEL_REF = 'LazyPixelRef',\n LAYER_TREE_HOST_IMPL_SNAPSHOT = 'cc::LayerTreeHostImpl',\n PICTURE_SNAPSHOT = 'cc::Picture',\n DISPLAY_ITEM_LIST_SNAPSHOT = 'cc::DisplayItemList',\n INPUT_LATENCY_MOUSE_MOVE = 'InputLatency::MouseMove',\n INPUT_LATENCY_MOUSE_WHEEL = 'InputLatency::MouseWheel',\n IMPL_SIDE_FLING = 'InputHandlerProxy::HandleGestureFling::started',\n\n SCHEDULE_POST_MESSAGE = 'SchedulePostMessage',\n HANDLE_POST_MESSAGE = 'HandlePostMessage',\n\n RENDER_FRAME_IMPL_CREATE_CHILD_FRAME = 'RenderFrameImpl::createChildFrame',\n\n DOM_LOADING = 'domLoading',\n}\n\n// NOT AN EXHAUSTIVE LIST: just some categories we use and refer\n// to in multiple places.\nexport const Categories = {\n Console: 'blink.console',\n UserTiming: 'blink.user_timing',\n Loading: 'loading',\n} as const;\n\n/**\n * The frames implementation in handlers/FramesHandler is considered \"legacy\"\n * in that it is based on the old TimelineModel implementation rather than\n * following the pattern of the other handlers. This will change in time as we\n * migrate the frames track to use AnimationFrame events, but for now we\n * maintain it because the effort required to migrate was large.\n * Consequently, the types we use through the codebase to refer to these frames\n * usually use ModelHandlers.FramesHandler.TimelineFrame, but in\n * trace/types/*.ts we cannot refer to types defined in the Handlers. To avoid a\n * circular dependency, we define these interfaces here which are implemented by\n * the classes in FramesHandler.ts, but they can also be used to refer to\n * instances of frames in trace/types/*.ts which is unable to import from\n * handlers.\n */\nexport interface LegacyTimelineFrame extends TraceEventData {\n startTime: MicroSeconds;\n startTimeOffset: MicroSeconds;\n endTime: MicroSeconds;\n duration: MicroSeconds;\n idle: boolean;\n dropped: boolean;\n isPartial: boolean;\n layerTree: LegacyFrameLayerTreeData|null;\n paints: LegacyLayerPaintEvent[];\n mainFrameId?: number;\n readonly seqId: number;\n index: number;\n}\n\nexport function isLegacyTimelineFrame(data: TraceEventData): data is LegacyTimelineFrame {\n return 'idle' in data && typeof data.idle === 'boolean';\n}\n\nexport interface LegacyFrameLayerTreeData {\n entry: TraceEventLayerTreeHostImplSnapshot;\n paints: LegacyLayerPaintEvent[];\n}\n\nexport interface LegacyLayerPaintEvent {\n layerId(): number;\n event(): TraceEventPaint;\n picture(): LegacyLayerPaintEventPicture|null;\n}\n\nexport interface LegacyLayerPaintEventPicture {\n rect: Array;\n serializedPicture: string;\n}\n"]} \ No newline at end of file +{"version":3,"file":"TraceEvents.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/types/TraceEvents.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/* eslint-disable no-unused-private-class-members */\nimport type * as Protocol from '../../../generated/protocol.js';\n\nimport {type MicroSeconds, type MilliSeconds, type Seconds, type TraceWindowMicroSeconds} from './Timing.js';\n\n// Trace Events.\nexport const enum Phase {\n // Standard\n BEGIN = 'B',\n END = 'E',\n COMPLETE = 'X',\n INSTANT = 'I',\n COUNTER = 'C',\n\n // Async\n ASYNC_NESTABLE_START = 'b',\n ASYNC_NESTABLE_INSTANT = 'n',\n ASYNC_NESTABLE_END = 'e',\n ASYNC_STEP_INTO = 'T',\n ASYNC_BEGIN = 'S',\n ASYNC_END = 'F',\n ASYNC_STEP_PAST = 'p',\n\n // Flow\n FLOW_START = 's',\n FLOW_STEP = 't',\n FLOW_END = 'f',\n\n // Sample\n SAMPLE = 'P',\n\n // Object\n OBJECT_CREATED = 'N',\n OBJECT_SNAPSHOT = 'O',\n OBJECT_DESTROYED = 'D',\n\n // Metadata\n METADATA = 'M',\n\n // Memory Dump\n MEMORY_DUMP_GLOBAL = 'V',\n MEMORY_DUMP_PROCESS = 'v',\n\n // Mark\n MARK = 'R',\n\n // Clock sync\n CLOCK_SYNC = 'c',\n}\n\nexport function isNestableAsyncPhase(phase: Phase): boolean {\n return phase === Phase.ASYNC_NESTABLE_START || phase === Phase.ASYNC_NESTABLE_END ||\n phase === Phase.ASYNC_NESTABLE_INSTANT;\n}\n\nexport function isPhaseAsync(phase: Phase): boolean {\n return isNestableAsyncPhase(phase) || phase === Phase.ASYNC_BEGIN || phase === Phase.ASYNC_STEP_INTO ||\n phase === Phase.ASYNC_END || phase === Phase.ASYNC_STEP_PAST;\n}\n\nexport function isFlowPhase(phase: Phase): boolean {\n return phase === Phase.FLOW_START || phase === Phase.FLOW_STEP || phase === Phase.FLOW_END;\n}\n\nexport const enum Scope {\n THREAD = 't',\n PROCESS = 'p',\n GLOBAL = 'g',\n}\n\nexport interface Event {\n args?: Args;\n cat: string;\n name: string;\n ph: Phase;\n pid: ProcessID;\n tid: ThreadID;\n tts?: MicroSeconds;\n ts: MicroSeconds;\n tdur?: MicroSeconds;\n dur?: MicroSeconds;\n}\n\nexport interface Args {\n data?: ArgsData;\n stackTrace?: CallFrame[];\n}\n\nexport interface ArgsData {\n stackTrace?: CallFrame[];\n url?: string;\n navigationId?: string;\n frame?: string;\n}\n\nexport interface CallFrame {\n codeType?: string;\n functionName: string;\n // Trace events are inconsistent here sadly :(\n scriptId: number|string;\n columnNumber: number;\n lineNumber: number;\n url: string;\n}\n\nexport function objectIsCallFrame(object: {}): object is CallFrame {\n return ('functionName' in object && typeof object.functionName === 'string') &&\n ('scriptId' in object && (typeof object.scriptId === 'string' || typeof object.scriptId === 'number')) &&\n ('columnNumber' in object && typeof object.columnNumber === 'number') &&\n ('lineNumber' in object && typeof object.lineNumber === 'number') &&\n ('url' in object && typeof object.url === 'string');\n}\n\nexport interface TraceFrame {\n frame: string;\n name: string;\n processId: ProcessID;\n url: string;\n parent?: string;\n // Added to Chromium in April 2024:\n // crrev.com/c/5424783\n isOutermostMainFrame?: boolean;\n // Added to Chromium in June 2024:\n // crrev.com/c/5595033\n isInPrimaryMainFrame?: boolean;\n}\n\n// Sample events.\n\nexport interface Sample extends Event {\n ph: Phase.SAMPLE;\n}\n\n/**\n * A fake trace event created to support CDP.Profiler.Profiles in the\n * trace engine.\n */\nexport interface SyntheticCpuProfile extends Instant, SyntheticBased {\n name: 'CpuProfile';\n args: Args&{\n data: ArgsData & {\n cpuProfile: Protocol.Profiler.Profile,\n },\n };\n}\n\nexport interface Profile extends Sample {\n name: 'Profile';\n id: ProfileID;\n args: Args&{\n data: ArgsData & {\n startTime: MicroSeconds,\n },\n };\n}\n\nexport interface ProfileChunk extends Sample {\n name: 'ProfileChunk';\n id: ProfileID;\n args: Args&{\n // `data` is only missing in \"fake\" traces\n data?: ArgsData & {\n cpuProfile?: PartialProfile,\n timeDeltas?: MicroSeconds[],\n lines?: MicroSeconds[],\n },\n };\n}\n\nexport interface PartialProfile {\n nodes?: PartialNode[];\n samples: CallFrameID[];\n}\n\nexport interface PartialNode {\n callFrame: CallFrame;\n id: CallFrameID;\n parent?: CallFrameID;\n}\n\n// Complete events.\n\nexport interface Complete extends Event {\n ph: Phase.COMPLETE;\n dur: MicroSeconds;\n}\n\nexport interface RunTask extends Complete {\n name: Name.RUN_TASK;\n}\nexport function isRunTask(event: Event): event is RunTask {\n return event.name === Name.RUN_TASK;\n}\n\nexport interface FireIdleCallback extends Complete {\n name: Name.FIRE_IDLE_CALLBACK;\n args: Args&{\n data: ArgsData & {\n allottedMilliseconds: MilliSeconds,\n frame: string,\n id: number,\n timedOut: boolean,\n },\n };\n}\n\nexport interface SchedulePostMessage extends Instant {\n name: Name.SCHEDULE_POST_MESSAGE;\n args: Args&{\n data: ArgsData & {\n traceId: string,\n },\n };\n}\n\nexport interface HandlePostMessage extends Complete {\n name: Name.HANDLE_POST_MESSAGE;\n args: Args&{\n data: ArgsData & {\n traceId: string,\n },\n };\n}\n\nexport interface Dispatch extends Complete {\n name: 'EventDispatch';\n args: Args&{\n data: ArgsData & {\n type: string,\n },\n };\n}\n\nexport interface ParseHTML extends Complete {\n name: 'ParseHTML';\n args: Args&{\n beginData: {\n frame: string,\n startLine: number,\n url: string,\n },\n endData?: {\n endLine: number,\n },\n };\n}\n\nexport interface Begin extends Event {\n ph: Phase.BEGIN;\n}\n\nexport interface End extends Event {\n ph: Phase.END;\n}\n\n/**\n * This denotes a complete event created from a pair of begin and end\n * events. For practicality, instead of always having to look for the\n * end event corresponding to a begin event, we create a synthetic\n * complete event that comprises the data of both from the beginning in\n * the RendererHandler.\n */\nexport type SyntheticComplete = Complete;\n\nexport interface EventTiming extends Event {\n ph: Phase.ASYNC_NESTABLE_START|Phase.ASYNC_NESTABLE_END;\n name: Name.EVENT_TIMING;\n id: string;\n args: Args&{\n frame: string,\n data?: ArgsData&{\n cancelable: boolean,\n duration: MilliSeconds,\n processingEnd: MilliSeconds,\n processingStart: MilliSeconds,\n timeStamp: MilliSeconds,\n interactionId?: number, type: string,\n },\n };\n}\n\nexport interface EventTimingBegin extends EventTiming {\n ph: Phase.ASYNC_NESTABLE_START;\n}\nexport interface EventTimingEnd extends EventTiming {\n ph: Phase.ASYNC_NESTABLE_END;\n}\n\nexport interface GPUTask extends Complete {\n name: 'GPUTask';\n args: Args&{\n data?: ArgsData & {\n /* eslint-disable @typescript-eslint/naming-convention */\n renderer_pid: ProcessID,\n used_bytes: number,\n /* eslint-enable @typescript-eslint/naming-convention */\n },\n };\n}\n\nexport interface SyntheticNetworkRedirect {\n url: string;\n priority: string;\n requestMethod?: string;\n ts: MicroSeconds;\n dur: MicroSeconds;\n}\n\n// ProcessedArgsData is used to store the processed data of a network\n// request. Which is used to distinguish from the date we extract from the\n// trace event directly.\ninterface SyntheticArgsData {\n dnsLookup: MicroSeconds;\n download: MicroSeconds;\n downloadStart: MicroSeconds;\n finishTime: MicroSeconds;\n initialConnection: MicroSeconds;\n isDiskCached: boolean;\n isHttps: boolean;\n isMemoryCached: boolean;\n isPushedResource: boolean;\n networkDuration: MicroSeconds;\n processingDuration: MicroSeconds;\n proxyNegotiation: MicroSeconds;\n queueing: MicroSeconds;\n redirectionDuration: MicroSeconds;\n requestSent: MicroSeconds;\n sendStartTime: MicroSeconds;\n ssl: MicroSeconds;\n stalled: MicroSeconds;\n totalTime: MicroSeconds;\n waiting: MicroSeconds;\n}\n\nexport interface SyntheticNetworkRequest extends Complete, SyntheticBased {\n rawSourceEvent: ResourceSendRequest;\n args: Args&{\n data: ArgsData & {\n syntheticData: SyntheticArgsData,\n // All fields below are from TraceEventsForNetworkRequest,\n // Required fields\n /** Size of the resource after decompression (if applicable). */\n decodedBodyLength: number,\n /**\n * Size of the resource over the network. Includes size of headers and\n * anything else in the HTTP response packet.\n */\n encodedDataLength: number,\n frame: string,\n fromServiceWorker: boolean,\n isLinkPreload: boolean,\n mimeType: string,\n priority: Protocol.Network.ResourcePriority,\n initialPriority: Protocol.Network.ResourcePriority,\n /**\n * This is the protocol used to resolve the request.\n *\n * Note, this is not the same as URL.protocol.\n *\n * Example values (not exhaustive): http/0.9, http/1.0, http/1.1, http, h2, h3-Q050, data, blob\n */\n protocol: string,\n redirects: SyntheticNetworkRedirect[],\n renderBlocking: RenderBlocking,\n requestId: string,\n requestingFrameUrl: string,\n statusCode: number,\n resourceType: Protocol.Network.ResourceType,\n responseHeaders: Array<{name: string, value: string}>,\n fetchPriorityHint: FetchPriorityHint,\n url: string,\n /** True only if got a 'resourceFinish' event indicating a failure. */\n failed: boolean,\n /** True only if got a 'resourceFinish' event. */\n finished: boolean,\n connectionId: number,\n connectionReused: boolean,\n // Optional fields\n initiator?: Initiator,\n requestMethod?: string,\n timing?: ResourceReceiveResponseTimingData,\n syntheticServerTimings?: SyntheticServerTiming[],\n },\n };\n cat: 'loading';\n name: 'SyntheticNetworkRequest';\n ph: Phase.COMPLETE;\n dur: MicroSeconds;\n tdur: MicroSeconds;\n ts: MicroSeconds;\n tts: MicroSeconds;\n pid: ProcessID;\n tid: ThreadID;\n}\n\nexport interface SyntheticWebSocketConnection extends Complete, SyntheticBased {\n rawSourceEvent: Event;\n args: Args&{\n data: ArgsData & {\n identifier: number,\n priority: Protocol.Network.ResourcePriority,\n url: string,\n },\n };\n cat: string;\n name: 'SyntheticWebSocketConnection';\n ph: Phase.COMPLETE;\n dur: MicroSeconds;\n ts: MicroSeconds;\n pid: ProcessID;\n tid: ThreadID;\n s: Scope;\n}\n\nexport const enum AuctionWorkletType {\n BIDDER = 'bidder',\n SELLER = 'seller',\n // Not expected to be used, but here as a fallback in case new types get\n // added and we have yet to update the trace engine.\n UNKNOWN = 'unknown',\n}\n\nexport interface SyntheticAuctionWorklet extends Instant, SyntheticBased {\n rawSourceEvent: Event;\n name: 'SyntheticAuctionWorklet';\n // The PID that the AuctionWorklet is running in.\n pid: ProcessID;\n // URL\n host: string;\n // An ID used to pair up runningInProcessEvents with doneWithProcessEvents\n target: string;\n type: AuctionWorkletType;\n args: Args&{\n data:\n ArgsData & {\n // There are two threads for a worklet that we care about, so we gather\n // the thread_name events so we can know the PID and TID for them (and\n // hence display the right events in the track for each thread)\n utilityThread: ThreadName,\n v8HelperThread: ThreadName,\n } &\n (\n // This type looks odd, but this is because these events could either have:\n // 1. Just the DoneWithProcess event\n // 2. Just the RunningInProcess event\n // 3. Both events\n // But crucially it cannot have both events missing, hence listing all the\n // allowed cases.\n // Clang is disabled as the combination of nested types and optional\n // properties cause it to weirdly indent some of the properties and make it\n // very unreadable.\n // clang-format off\n {\n runningInProcessEvent: AuctionWorkletRunningInProcess,\n doneWithProcessEvent: AuctionWorkletDoneWithProcess,\n } |\n {\n runningInProcessEvent?: AuctionWorkletRunningInProcess,\n doneWithProcessEvent: AuctionWorkletDoneWithProcess,\n } |\n {\n doneWithProcessEvent?: AuctionWorkletDoneWithProcess,\n runningInProcessEvent: AuctionWorkletRunningInProcess,\n\n }),\n // clang-format on\n };\n}\nexport interface AuctionWorkletRunningInProcess extends Event {\n name: 'AuctionWorkletRunningInProcess';\n ph: Phase.INSTANT;\n args: Args&{\n data: ArgsData & {\n host: string,\n pid: ProcessID,\n target: string,\n type: AuctionWorkletType,\n },\n };\n}\nexport interface AuctionWorkletDoneWithProcess extends Event {\n name: 'AuctionWorkletDoneWithProcess';\n ph: Phase.INSTANT;\n args: Args&{\n data: ArgsData & {\n host: string,\n pid: ProcessID,\n target: string,\n type: AuctionWorkletType,\n },\n };\n}\n\nexport function isAuctionWorkletRunningInProcess(event: Event): event is AuctionWorkletRunningInProcess {\n return event.name === 'AuctionWorkletRunningInProcess';\n}\nexport function isAuctionWorkletDoneWithProcess(event: Event): event is AuctionWorkletDoneWithProcess {\n return event.name === 'AuctionWorkletDoneWithProcess';\n}\n\n// Snapshot events.\n\nexport interface Screenshot extends Event {\n /**\n * @deprecated This value is incorrect. Use ScreenshotHandler.getPresentationTimestamp()\n */\n ts: MicroSeconds;\n /** The id is the frame sequence number in hex */\n id: string;\n args: Args&{\n snapshot: string,\n };\n name: Name.SCREENSHOT;\n cat: 'disabled-by-default-devtools.screenshot';\n ph: Phase.OBJECT_SNAPSHOT;\n}\nexport function isScreenshot(event: Event): event is Screenshot {\n return event.name === Name.SCREENSHOT;\n}\n\nexport interface SyntheticScreenshot extends Event, SyntheticBased {\n rawSourceEvent: Screenshot;\n /** This is the correct presentation timestamp. */\n ts: MicroSeconds;\n args: Args&{\n dataUri: string,\n };\n name: Name.SCREENSHOT;\n cat: 'disabled-by-default-devtools.screenshot';\n ph: Phase.OBJECT_SNAPSHOT;\n}\n\n// Animation events.\n\nexport interface Animation extends Event {\n args: Args&{\n data: ArgsData & {\n nodeName?: string,\n nodeId?: Protocol.DOM.BackendNodeId,\n displayName?: string,\n id?: string,\n name?: string,\n state?: string,\n compositeFailed?: number,\n unsupportedProperties?: string[],\n },\n };\n name: 'Animation';\n id2?: {\n local?: string,\n };\n ph: Phase.ASYNC_NESTABLE_START|Phase.ASYNC_NESTABLE_END|Phase.ASYNC_NESTABLE_INSTANT;\n}\n\n// Metadata events.\n\nexport interface Metadata extends Event {\n ph: Phase.METADATA;\n args: Args&{\n name?: string,\n uptime?: string,\n };\n}\n\nexport interface ThreadName extends Metadata {\n name: Name.THREAD_NAME;\n args: Args&{\n name?: string,\n };\n}\n\nexport interface ProcessName extends Metadata {\n name: 'process_name';\n}\n\n// Mark events.\n\nexport interface Mark extends Event {\n ph: Phase.MARK;\n}\n\nexport interface NavigationStart extends Mark {\n name: 'navigationStart';\n args: Args&{\n data?: ArgsData & {\n documentLoaderURL: string,\n isLoadingMainFrame: boolean,\n // isOutermostMainFrame was introduced in crrev.com/c/3625434 and exists\n // because of Fenced Frames\n // [github.com/WICG/fenced-frame/tree/master/explainer].\n // Fenced frames introduce a situation where isLoadingMainFrame could be\n // true for a navigation, but that navigation be within an embedded \"main\n // frame\", and therefore it wouldn't be on the top level main frame.\n // In situations where we need to distinguish that, we can rely on\n // isOutermostMainFrame, which will only be true for navigations on the\n // top level main frame.\n\n // This flag is optional as it was introduced in May 2022; so users\n // reasonably may import traces from before that date that do not have\n // this field present.\n isOutermostMainFrame?: boolean, navigationId: string,\n /**\n * @deprecated use documentLoaderURL for navigation events URLs\n */\n url?: string,\n },\n frame: string,\n };\n}\n\nexport interface FirstContentfulPaint extends Mark {\n name: Name.MARK_FCP;\n args: Args&{\n frame: string,\n data?: ArgsData&{\n navigationId: string,\n },\n };\n}\n\nexport interface FirstPaint extends Mark {\n name: 'firstPaint';\n args: Args&{\n frame: string,\n data?: ArgsData&{\n navigationId: string,\n },\n };\n}\n\nexport type PageLoadEvent = FirstContentfulPaint|MarkDOMContent|InteractiveTime|LargestContentfulPaintCandidate|\n LayoutShift|FirstPaint|MarkLoad|NavigationStart;\n\nconst markerTypeGuards = [\n isMarkDOMContent,\n isMarkLoad,\n isFirstPaint,\n isFirstContentfulPaint,\n isLargestContentfulPaintCandidate,\n isNavigationStart,\n];\n\nexport const MarkerName =\n ['MarkDOMContent', 'MarkLoad', 'firstPaint', 'firstContentfulPaint', 'largestContentfulPaint::Candidate'] as const;\n\nexport interface MarkerEvent extends Event {\n name: typeof MarkerName[number];\n}\n\nexport function isMarkerEvent(event: Event): event is MarkerEvent {\n return markerTypeGuards.some(fn => fn(event));\n}\n\nconst pageLoadEventTypeGuards = [\n ...markerTypeGuards,\n isInteractiveTime,\n];\n\nexport function eventIsPageLoadEvent(event: Event): event is PageLoadEvent {\n return pageLoadEventTypeGuards.some(fn => fn(event));\n}\n\nexport interface LargestContentfulPaintCandidate extends Mark {\n name: Name.MARK_LCP_CANDIDATE;\n args: Args&{\n frame: string,\n data?: ArgsData&{\n candidateIndex: number,\n isOutermostMainFrame: boolean,\n isMainFrame: boolean,\n navigationId: string,\n nodeId: Protocol.DOM.BackendNodeId,\n loadingAttr: string,\n type?: string,\n },\n };\n}\nexport interface LargestImagePaintCandidate extends Mark {\n name: 'LargestImagePaint::Candidate';\n args: Args&{\n frame: string,\n data?: ArgsData&{\n candidateIndex: number,\n imageUrl: string,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n DOMNodeId: Protocol.DOM.BackendNodeId,\n },\n };\n}\nexport interface LargestTextPaintCandidate extends Mark {\n name: 'LargestTextPaint::Candidate';\n args: Args&{\n frame: string,\n data?: ArgsData&{\n candidateIndex: number,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n DOMNodeId: Protocol.DOM.BackendNodeId,\n },\n };\n}\n\nexport interface InteractiveTime extends Mark {\n name: 'InteractiveTime';\n args: Args&{\n args: {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n total_blocking_time_ms: number,\n },\n frame: string,\n };\n}\n\n// Instant events.\n\nexport interface Instant extends Event {\n ph: Phase.INSTANT;\n s: Scope;\n}\n\nexport interface UpdateCounters extends Instant {\n name: 'UpdateCounters';\n args: Args&{\n data: ArgsData & {\n documents: number,\n jsEventListeners: number,\n jsHeapSizeUsed: number,\n nodes: number,\n gpuMemoryLimitKB?: number,\n },\n };\n}\n\nexport type RendererEvent = Instant|Complete;\n\nexport interface TracingStartedInBrowser extends Instant {\n name: Name.TRACING_STARTED_IN_BROWSER;\n args: Args&{\n data?: ArgsData & {\n frameTreeNodeId: number,\n // Frames can only missing in \"fake\" traces\n frames?: TraceFrame[], persistentIds: boolean,\n },\n };\n}\n\nexport interface TracingSessionIdForWorker extends Instant {\n name: 'TracingSessionIdForWorker';\n args: Args&{\n data?: ArgsData & {\n url: string,\n workerId: WorkerId,\n workerThreadId: ThreadID,\n frame: string,\n },\n };\n}\nexport function isTracingSessionIdForWorker(event: Event): event is TracingSessionIdForWorker {\n return event.name === 'TracingSessionIdForWorker';\n}\n\nexport interface FrameCommittedInBrowser extends Instant {\n name: 'FrameCommittedInBrowser';\n args: Args&{\n data?: ArgsData & TraceFrame,\n };\n}\n\nexport interface MainFrameViewport extends Instant {\n name: 'PaintTimingVisualizer::Viewport';\n args: {\n data: ArgsData&{\n // eslint-disable-next-line @typescript-eslint/naming-convention\n viewport_rect: number[],\n },\n };\n}\n\nexport interface CommitLoad extends Instant {\n name: 'CommitLoad';\n args: Args&{\n data?: ArgsData & {\n frame: string,\n isMainFrame: boolean,\n name: string,\n nodeId: number,\n page: string,\n parent: string,\n url: string,\n },\n };\n}\n\nexport interface MarkDOMContent extends Instant {\n name: 'MarkDOMContent';\n args: Args&{\n data?: ArgsData & {\n frame: string,\n isMainFrame: boolean,\n isOutermostMainFrame?: boolean, page: string,\n },\n };\n}\n\nexport interface MarkLoad extends Instant {\n name: 'MarkLoad';\n args: Args&{\n data?: ArgsData & {\n frame: string,\n isMainFrame: boolean,\n page: string,\n isOutermostMainFrame?: boolean,\n },\n };\n}\n\nexport interface Async extends Event {\n ph: Phase.ASYNC_NESTABLE_START|Phase.ASYNC_NESTABLE_INSTANT|Phase.ASYNC_NESTABLE_END|Phase.ASYNC_STEP_INTO|\n Phase.ASYNC_BEGIN|Phase.ASYNC_END|Phase.ASYNC_STEP_PAST;\n}\n\nexport type TraceRect = [number, number, number, number];\nexport type TraceImpactedNode = {\n // These keys come from the trace data, so we have to use underscores.\n /* eslint-disable @typescript-eslint/naming-convention */\n new_rect: TraceRect,\n node_id: Protocol.DOM.BackendNodeId,\n old_rect: TraceRect,\n /* eslint-enable @typescript-eslint/naming-convention */\n};\n\ntype LayoutShiftData = ArgsData&{\n // These keys come from the trace data, so we have to use underscores.\n /* eslint-disable @typescript-eslint/naming-convention */\n cumulative_score: number,\n frame_max_distance: number,\n had_recent_input: boolean,\n impacted_nodes: TraceImpactedNode[] | undefined,\n is_main_frame: boolean,\n overall_max_distance: number,\n region_rects: TraceRect[],\n score: number,\n weighted_score_delta: number,\n navigationId?: string,\n /* eslint-enable @typescript-eslint/naming-convention */\n};\n// These keys come from the trace data, so we have to use underscores.\nexport interface LayoutShift extends Instant {\n name: 'LayoutShift';\n normalized?: boolean;\n args: Args&{\n frame: string,\n data?: LayoutShiftData,\n };\n}\n\ninterface LayoutShiftSessionWindowData {\n // The sum of the weighted score of all the shifts\n // that belong to a session window.\n cumulativeWindowScore: number;\n // A consecutive generated in the frontend to\n // to identify a session window.\n id: number;\n}\nexport interface LayoutShiftParsedData {\n screenshotSource?: string;\n timeFromNavigation?: MicroSeconds;\n // The sum of the weighted scores of the shifts that\n // belong to a session window up until this shift\n // (inclusive).\n cumulativeWeightedScoreInWindow: number;\n sessionWindowData: LayoutShiftSessionWindowData;\n}\nexport interface SyntheticLayoutShift extends LayoutShift, SyntheticBased {\n name: 'LayoutShift';\n rawSourceEvent: LayoutShift;\n args: Args&{\n frame: string,\n data?: LayoutShiftData&{\n rawEvent: LayoutShift,\n },\n };\n parsedData: LayoutShiftParsedData;\n}\n\n/**\n * This is a synthetic Layout shift cluster. Not based on a raw event as there's no concept\n * of this as a trace event.\n */\nexport interface SyntheticLayoutShiftCluster {\n name: 'SyntheticLayoutShiftCluster';\n clusterWindow: TraceWindowMicroSeconds;\n clusterCumulativeScore: number;\n events: SyntheticLayoutShift[];\n // For convenience we split apart the cluster into good, NI, and bad windows.\n // Since a cluster may remain in the good window, we mark NI and bad as being\n // possibly null.\n scoreWindows: {\n good: TraceWindowMicroSeconds,\n needsImprovement?: TraceWindowMicroSeconds,\n bad?: TraceWindowMicroSeconds,\n };\n // The last navigation that happened before this cluster.\n navigationId?: string;\n worstShiftEvent?: Event;\n // This is the start of the cluster: the start of the first layout shift of the cluster.\n ts: MicroSeconds;\n // The duration of the cluster. This should include up until the end of the last\n // layout shift in this cluster.\n dur?: MicroSeconds;\n cat: '';\n ph: Phase.COMPLETE;\n pid: ProcessID;\n tid: ThreadID;\n}\n\nexport type FetchPriorityHint = 'low'|'high'|'auto';\nexport type RenderBlocking = 'blocking'|'non_blocking'|'in_body_parser_blocking'|'potentially_blocking';\n\nexport interface Initiator {\n type: Protocol.Network.InitiatorType;\n fetchType: string;\n columnNumber?: number;\n lineNumber?: number;\n url?: string;\n}\n\nexport interface ResourceSendRequest extends Instant {\n name: 'ResourceSendRequest';\n args: Args&{\n data: ArgsData & {\n frame: string,\n requestId: string,\n url: string,\n priority: Protocol.Network.ResourcePriority,\n resourceType: Protocol.Network.ResourceType,\n fetchPriorityHint: FetchPriorityHint,\n // TODO(crbug.com/1457985): change requestMethod to enum when confirm in the backend code.\n requestMethod?: string,\n renderBlocking?: RenderBlocking,\n initiator?: Initiator,\n isLinkPreload?: boolean,\n },\n };\n}\n\nexport interface ResourceChangePriority extends Instant {\n name: 'ResourceChangePriority';\n args: Args&{\n data: ArgsData & {\n requestId: string,\n priority: Protocol.Network.ResourcePriority,\n },\n };\n}\n\nexport interface ResourceWillSendRequest extends Instant {\n name: 'ResourceWillSendRequest';\n args: Args&{\n data: ArgsData & {\n requestId: string,\n },\n };\n}\n\nexport interface ResourceFinish extends Instant {\n name: 'ResourceFinish';\n args: Args&{\n data: ArgsData & {\n decodedBodyLength: number,\n didFail: boolean,\n encodedDataLength: number,\n finishTime: Seconds,\n requestId: string,\n },\n };\n}\n\nexport interface ResourceReceivedData extends Instant {\n name: 'ResourceReceivedData';\n args: Args&{\n data: ArgsData & {\n encodedDataLength: number,\n frame: string,\n requestId: string,\n },\n };\n}\n\ninterface ResourceReceiveResponseTimingData {\n connectEnd: MilliSeconds;\n connectStart: MilliSeconds;\n dnsEnd: MilliSeconds;\n dnsStart: MilliSeconds;\n proxyEnd: MilliSeconds;\n proxyStart: MilliSeconds;\n pushEnd: MilliSeconds;\n pushStart: MilliSeconds;\n receiveHeadersEnd: MilliSeconds;\n receiveHeadersStart: MilliSeconds;\n requestTime: Seconds;\n sendEnd: MilliSeconds;\n sendStart: MilliSeconds;\n sslEnd: MilliSeconds;\n sslStart: MilliSeconds;\n workerReady: MilliSeconds;\n workerStart: MilliSeconds;\n}\n\nexport interface ResourceReceiveResponse extends Instant {\n name: 'ResourceReceiveResponse';\n args: Args&{\n data: ArgsData & {\n /**\n * This is the protocol used to resolve the request.\n *\n * Note, this is not the same as URL.protocol.\n *\n * Example values (not exhaustive): http/0.9, http/1.0, http/1.1, http, h2, h3-Q050, data, blob\n */\n protocol: string,\n encodedDataLength: number,\n frame: string,\n fromCache: boolean,\n fromServiceWorker: boolean,\n mimeType: string,\n requestId: string,\n responseTime: MilliSeconds,\n statusCode: number,\n // Some cached events don't have this field\n timing?: ResourceReceiveResponseTimingData, connectionId: number, connectionReused: boolean,\n headers?: Array<{name: string, value: string}>,\n },\n };\n}\n\nexport interface ResourceMarkAsCached extends Instant {\n name: 'ResourceMarkAsCached';\n args: Args&{\n data: ArgsData & {\n requestId: string,\n },\n };\n}\n\nexport const enum LayoutInvalidationReason {\n SIZE_CHANGED = 'Size changed',\n ATTRIBUTE = 'Attribute',\n ADDED_TO_LAYOUT = 'Added to layout',\n SCROLLBAR_CHANGED = 'Scrollbar changed',\n REMOVED_FROM_LAYOUT = 'Removed from layout',\n STYLE_CHANGED = 'Style changed',\n FONTS_CHANGED = 'Fonts changed',\n UNKNOWN = 'Unknown',\n}\n\nexport interface LayoutInvalidationTracking extends Instant {\n name: Name.LAYOUT_INVALIDATION_TRACKING;\n args: Args&{\n data: ArgsData & {\n frame: string,\n nodeId: Protocol.DOM.BackendNodeId,\n reason: LayoutInvalidationReason,\n nodeName?: string,\n },\n };\n}\n\nexport interface ScheduleStyleInvalidationTracking extends Instant {\n name: Name.SCHEDULE_STYLE_INVALIDATION_TRACKING;\n args: Args&{\n data: ArgsData & {\n frame: string,\n nodeId: Protocol.DOM.BackendNodeId,\n invalidationSet?: string,\n invalidatedSelectorId?: string,\n reason?: LayoutInvalidationReason,\n changedClass?: string,\n changedAttribute?: string,\n changedId?: string,\n nodeName?: string,\n stackTrace?: CallFrame[],\n },\n };\n}\nexport function isScheduleStyleInvalidationTracking(event: Event): event is ScheduleStyleInvalidationTracking {\n return event.name === Name.SCHEDULE_STYLE_INVALIDATION_TRACKING;\n}\n\nexport const enum StyleRecalcInvalidationReason {\n ANIMATION = 'Animation',\n}\n\nexport interface StyleRecalcInvalidationTracking extends Instant {\n name: Name.STYLE_RECALC_INVALIDATION_TRACKING;\n args: Args&{\n data: ArgsData & {\n frame: string,\n nodeId: Protocol.DOM.BackendNodeId,\n reason: StyleRecalcInvalidationReason,\n subtree: boolean,\n nodeName?: string,\n extraData?: string,\n },\n };\n}\n\nexport function isStyleRecalcInvalidationTracking(event: Event): event is StyleRecalcInvalidationTracking {\n return event.name === Name.STYLE_RECALC_INVALIDATION_TRACKING;\n}\nexport interface StyleInvalidatorInvalidationTracking extends Instant {\n name: Name.STYLE_INVALIDATOR_INVALIDATION_TRACKING;\n args: Args&{\n data: ArgsData & {\n frame: string,\n nodeId: Protocol.DOM.BackendNodeId,\n reason: string,\n invalidationList: Array<{classes?: string[], id: string}>,\n subtree: boolean,\n nodeName?: string,\n extraData?: string,\n },\n };\n}\nexport function isStyleInvalidatorInvalidationTracking(event: Event): event is StyleInvalidatorInvalidationTracking {\n return event.name === Name.STYLE_INVALIDATOR_INVALIDATION_TRACKING;\n}\n\nexport interface BeginCommitCompositorFrame extends Instant {\n name: Name.BEGIN_COMMIT_COMPOSITOR_FRAME;\n args: Args&{\n frame: string,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n is_mobile_optimized: boolean,\n };\n}\nexport function isBeginCommitCompositorFrame(event: Event): event is BeginCommitCompositorFrame {\n return event.name === Name.BEGIN_COMMIT_COMPOSITOR_FRAME;\n}\n\nexport interface ParseMetaViewport extends Instant {\n name: Name.PARSE_META_VIEWPORT;\n args: Args&{\n data: {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n node_id: Protocol.DOM.BackendNodeId,\n content: string,\n frame?: string,\n },\n };\n}\nexport function isParseMetaViewport(event: Event): event is ParseMetaViewport {\n return event.name === Name.PARSE_META_VIEWPORT;\n}\n\nexport interface ScheduleStyleRecalculation extends Instant {\n name: Name.SCHEDULE_STYLE_RECALCULATION;\n args: Args&{\n data: {\n frame: string,\n },\n };\n}\nexport function isScheduleStyleRecalculation(event: Event): event is ScheduleStyleRecalculation {\n return event.name === Name.SCHEDULE_STYLE_RECALCULATION;\n}\n\nexport interface RenderFrameImplCreateChildFrame extends Event {\n name: Name.RENDER_FRAME_IMPL_CREATE_CHILD_FRAME;\n /* eslint-disable @typescript-eslint/naming-convention */\n args: Args&{\n child_frame_token: string,\n frame_token: string,\n };\n}\nexport function isRenderFrameImplCreateChildFrame(event: Event): event is RenderFrameImplCreateChildFrame {\n return event.name === Name.RENDER_FRAME_IMPL_CREATE_CHILD_FRAME;\n}\n\nexport interface PrePaint extends Complete {\n name: 'PrePaint';\n}\n\nexport interface PairableAsync extends Event {\n ph: Phase.ASYNC_NESTABLE_START|Phase.ASYNC_NESTABLE_END|Phase.ASYNC_NESTABLE_INSTANT;\n // The id2 field gives flexibility to explicitly specify if an event\n // id is global among processes or process local. However not all\n // events use it, so both kind of ids need to be marked as optional.\n id2?: {local?: string, global?: string};\n id?: string;\n}\nexport interface PairableAsyncBegin extends PairableAsync {\n ph: Phase.ASYNC_NESTABLE_START;\n}\n\nexport interface PairableAsyncInstant extends PairableAsync {\n ph: Phase.ASYNC_NESTABLE_INSTANT;\n}\n\nexport interface PairableAsyncEnd extends PairableAsync {\n ph: Phase.ASYNC_NESTABLE_END;\n}\n\nexport interface UserTiming extends Event {\n id2?: {local?: string, global?: string};\n id?: string;\n cat: 'blink.user_timing';\n // Note that the timestamp for user timing trace events is set to the\n // start time passed by the user at the call site of the timing (based\n // on the UserTiming spec).\n // https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/timing/performance_user_timing.cc;l=236;drc=494419358caf690316f160a1f27d9e771a14c033\n}\n\nexport interface DomLoading extends UserTiming {\n name: Name.DOM_LOADING;\n args: Args&{\n frame?: string,\n };\n}\n\nexport interface BeginRemoteFontLoad extends UserTiming {\n name: Name.BEGIN_REMOTE_FONT_LOAD;\n args: Args&{\n display: string,\n id: number,\n };\n}\n\nexport type PairableUserTiming = UserTiming&PairableAsync;\n\nexport interface PerformanceMeasureBegin extends PairableUserTiming {\n args: Args&{\n detail?: string,\n stackTrace?: CallFrame[],\n };\n ph: Phase.ASYNC_NESTABLE_START;\n}\n\nexport type PerformanceMeasureEnd = PairableUserTiming&PairableAsyncEnd;\nexport type PerformanceMeasure = PerformanceMeasureBegin|PerformanceMeasureEnd;\n\nexport interface PerformanceMark extends UserTiming {\n args: Args&{\n data?: ArgsData & {\n detail?: string,\n stackTrace?: CallFrame[],\n },\n };\n ph: Phase.INSTANT|Phase.MARK|Phase.ASYNC_NESTABLE_INSTANT;\n}\n\nexport interface ConsoleTimeBegin extends PairableAsyncBegin {\n cat: 'blink.console';\n}\n\nexport interface ConsoleTimeEnd extends PairableAsyncEnd {\n cat: 'blink.console';\n}\n\nexport type ConsoleTime = ConsoleTimeBegin|ConsoleTimeEnd;\n\nexport interface TimeStamp extends Event {\n cat: 'devtools.timeline';\n name: 'TimeStamp';\n ph: Phase.INSTANT;\n id: string;\n args: Args&{\n data: ArgsData & {\n frame: string,\n message: string,\n },\n };\n}\n\n/** ChromeFrameReporter args for PipelineReporter event.\n Matching proto: https://source.chromium.org/chromium/chromium/src/+/main:third_party/perfetto/protos/perfetto/trace/track_event/chrome_frame_reporter.proto\n */\n/* eslint-disable @typescript-eslint/naming-convention */\ninterface ChromeFrameReporter {\n state: State;\n enum: FrameDropReason;\n /** The reason is set only if |state| is not |STATE_UPDATED_ALL|. */\n reason: FrameDropReason;\n frame_source: number;\n /** Identifies a BeginFrameArgs (along with the source_id).\n See comments in components/viz/common/frame_sinks/begin_frame_args.h. */\n frame_sequence: number;\n /** If this is a droped frame (i.e. if |state| is set to |STATE_DROPPED| or\n |STATE_PRESENTED_PARTIAL|), then indicates whether this frame impacts smoothness. */\n affects_smoothness: boolean;\n /** The type of active scroll. */\n scroll_state: ScrollState;\n /** If any main thread animation is active during this frame. */\n has_main_animation: boolean;\n /** If any compositor thread animation is active during this frame. */\n has_compositor_animation: boolean;\n /** If any touch-driven UX (not scroll) is active during this frame. */\n has_smooth_input_main: boolean;\n /** Whether the frame contained any missing content (i.e. whether there was\n checkerboarding in the frame). */\n has_missing_content: boolean;\n /** The id of layer_tree_host that the frame has been produced for. */\n layer_tree_host_id: number;\n /** If total latency of PipelineReporter exceeds a certain limit. */\n has_high_latency: boolean;\n /** Indicate if the frame is \"FORKED\" (i.e. a PipelineReporter event starts at\n the same frame sequence as another PipelineReporter) or \"BACKFILL\"\n (i.e. dropped frames when there are no partial compositor updates). */\n frame_type: FrameType;\n /** The breakdown stage of PipelineReporter that is most likely accountable for\n high latency. */\n high_latency_contribution_stage: string[];\n}\nconst enum State {\n /** The frame did not have any updates to present. **/\n STATE_NO_UPDATE_DESIRED = 'STATE_NO_UPDATE_DESIRED',\n /** The frame presented all the desired updates (i.e. any updates requested\n from both the compositor thread and main-threads were handled). **/\n STATE_PRESENTED_ALL = 'STATE_PRESENTED_ALL',\n /** The frame was presented with some updates, but also missed some updates\n (e.g. missed updates from the main-thread, but included updates from the\n compositor thread). **/\n STATE_PRESENTED_PARTIAL = 'STATE_PRESENTED_PARTIAL',\n /** The frame was dropped, i.e. some updates were desired for the frame, but\n was not presented. **/\n STATE_DROPPED = 'STATE_DROPPED',\n}\n\nconst enum FrameDropReason {\n REASON_UNSPECIFIED = 'REASON_UNSPECIFIED',\n /** Frame was dropped by the display-compositor.\n The display-compositor may drop a frame some times (e.g. the frame missed\n the deadline, or was blocked on surface-sync, etc.) **/\n REASON_DISPLAY_COMPOSITOR = 'REASON_DISPLAY_COMPOSITOR',\n /** Frame was dropped because of the main-thread.\n The main-thread may cause a frame to be dropped, e.g. if the main-thread\n is running expensive javascript, or doing a lot of layout updates, etc. **/\n REASON_MAIN_THREAD = 'REASON_MAIN_THREAD',\n /** Frame was dropped by the client compositor.\n The client compositor can drop some frames too (e.g. attempting to\n recover latency, missing the deadline, etc.). **/\n REASON_CLIENT_COMPOSITOR = 'REASON_CLIENT_COMPOSITOR',\n}\n\nconst enum ScrollState {\n SCROLL_NONE = 'SCROLL_NONE',\n SCROLL_MAIN_THREAD = 'SCROLL_MAIN_THREAD',\n SCROLL_COMPOSITOR_THREAD = 'SCROLL_COMPOSITOR_THREAD',\n\n /** Used when it can't be determined whether a scroll is in progress or not. */\n SCROLL_UNKNOWN = 'SCROLL_UNKNOWN',\n}\nconst enum FrameType {\n FORKED = 'FORKED',\n BACKFILL = 'BACKFILL',\n}\n\nexport interface PipelineReporter extends Event {\n id2?: {\n local?: string,\n };\n ph: Phase.ASYNC_NESTABLE_START|Phase.ASYNC_NESTABLE_END;\n args: Args&{\n chrome_frame_reporter: ChromeFrameReporter,\n };\n}\n\nexport function isPipelineReporter(event: Event): event is PipelineReporter {\n return event.name === Name.PIPELINE_REPORTER;\n}\n\n// A type used for synthetic events created based on a raw trace event.\n// A branded type is used to ensure not all events can be typed as\n// SyntheticBased and prevent places different to the\n// SyntheticEventsManager from creating synthetic events. This is\n// because synthetic events need to be registered in order to resolve\n// serialized event keys into event objects, so we ensure events are\n// registered at the time they are created by the SyntheticEventsManager.\nexport interface SyntheticBased extends Event {\n ph: Ph;\n rawSourceEvent: Event;\n _tag: 'SyntheticEntryTag';\n}\n\nexport function isSyntheticBased(event: Event): event is SyntheticBased {\n return 'rawSourceEvent' in event;\n}\n\n// Nestable async events with a duration are made up of two distinct\n// events: the begin, and the end. We need both of them to be able to\n// display the right information, so we create these synthetic events.\nexport interface SyntheticEventPair extends SyntheticBased {\n rawSourceEvent: Event;\n name: T['name'];\n cat: T['cat'];\n id?: string;\n id2?: {local?: string, global?: string};\n\n dur: MicroSeconds;\n args: Args&{\n data: {\n beginEvent: T & PairableAsyncBegin,\n endEvent: T&PairableAsyncEnd,\n instantEvents?: Array,\n },\n };\n}\n\nexport type SyntheticPipelineReporterPair = SyntheticEventPair;\n\nexport type SyntheticUserTimingPair = SyntheticEventPair;\n\nexport type SyntheticConsoleTimingPair = SyntheticEventPair;\n\nexport type SyntheticAnimationPair = SyntheticEventPair;\n\nexport interface SyntheticInteractionPair extends SyntheticEventPair {\n // InteractionID and type are available within the beginEvent's data, but we\n // put them on the top level for ease of access.\n interactionId: number;\n type: string;\n // This is equivalent to startEvent.ts;\n ts: MicroSeconds;\n // This duration can be calculated via endEvent.ts - startEvent.ts, but we do\n // that and put it here to make it easier. This also makes these events\n // consistent with real events that have a dur field.\n dur: MicroSeconds;\n // These values are provided in the startEvent's args.data field as\n // millisecond values, but during the handler phase we parse these into\n // microseconds and put them on the top level for easy access.\n processingStart: MicroSeconds;\n processingEnd: MicroSeconds;\n // These 3 values represent the breakdown of the parts of an interaction:\n // 1. inputDelay: time from the user clicking to the input being handled\n inputDelay: MicroSeconds;\n // 2. mainThreadHandling: time spent processing the event handler\n mainThreadHandling: MicroSeconds;\n // 3. presentationDelay: delay between the event being processed and the frame being rendered\n presentationDelay: MicroSeconds;\n}\n\n/**\n * A profile call created in the frontend from samples disguised as a\n * trace event.\n *\n * We store the sampleIndex, profileId and nodeId so that we can easily link\n * back a Synthetic Trace Entry to an indivdual Sample trace event within a\n * Profile.\n *\n * Because a sample contains a set of call frames representing the stack at the\n * point in time that the sample was created, we also have to store the ID of\n * the Node that points to the function call that this profile call represents.\n */\nexport interface SyntheticProfileCall extends Event {\n callFrame: Protocol.Runtime.CallFrame;\n nodeId: Protocol.integer;\n sampleIndex: number;\n profileId: ProfileID;\n}\n\n/**\n * A synthetic event created from the Server-Timing header of network\n * request. In order to create these synthetic events, the corresponding\n * metric (timing) in the header must contain a \"start\" param, which\n * corresponds to the timestamp of the metric in the server. The\n * ServerTimingsHandler implements a heuristic to estimate the offset\n * between the client clock and the server clock so that the server\n * timestamp can be translated to the tracing clock.\n */\nexport interface SyntheticServerTiming extends SyntheticBased {\n rawSourceEvent: ResourceSendRequest;\n cat: 'devtools.server-timing';\n args: Args&{\n data: ArgsData & {\n desc?: string, origin: string,\n },\n };\n}\n\n/**\n * A JS Sample reflects a single sample from the V8 CPU Profile\n */\nexport interface SyntheticJSSample extends Event {\n name: Name.JS_SAMPLE;\n args: Args&{\n data: ArgsData & {\n stackTrace: Protocol.Runtime.CallFrame[],\n },\n };\n ph: Phase.INSTANT;\n}\n\nexport function isSyntheticInteraction(event: Event): event is SyntheticInteractionPair {\n return Boolean(\n 'interactionId' in event && event.args?.data && 'beginEvent' in event.args.data && 'endEvent' in event.args.data);\n}\n\n// Events relating to frames.\n\nexport interface DrawFrame extends Instant {\n name: Name.DRAW_FRAME;\n args: Args&{\n layerTreeId: number,\n frameSeqId: number,\n };\n}\n\nexport function isDrawFrame(event: Event): event is DrawFrame {\n // The extra check for INSTANT here is because in the past DrawFrame events had an ASYNC_NESTABLE_START and ASYNC_NESTABLE_END pair. We don't want to support those old events, so we have to check we are dealing with an instant event.\n return event.name === Name.DRAW_FRAME && event.ph === Phase.INSTANT;\n}\nexport interface LegacyDrawFrameBegin extends Async {\n name: Name.DRAW_FRAME;\n ph: Phase.ASYNC_NESTABLE_START;\n args: Args&{\n layerTreeId: number,\n frameSeqId: number,\n };\n}\nexport function isLegacyTraceEventDrawFrameBegin(event: Event): event is LegacyDrawFrameBegin {\n return event.name === Name.DRAW_FRAME && event.ph === Phase.ASYNC_NESTABLE_START;\n}\n\nexport interface BeginFrame extends Instant {\n name: Name.BEGIN_FRAME;\n args: Args&{\n layerTreeId: number,\n frameSeqId: number,\n };\n}\nexport function isBeginFrame(event: Event): event is BeginFrame {\n // Old traces did not have frameSeqId; but we do not want to support these.\n return Boolean(event.name === Name.BEGIN_FRAME && event.args && 'frameSeqId' in event.args);\n}\n\nexport interface DroppedFrame extends Instant {\n name: Name.DROPPED_FRAME;\n args: Args&{\n layerTreeId: number,\n frameSeqId: number,\n hasPartialUpdate?: boolean,\n };\n}\nexport function isDroppedFrame(event: Event): event is DroppedFrame {\n // Old traces did not have frameSeqId; but we do not want to support these.\n return Boolean(event.name === Name.DROPPED_FRAME && event.args && 'frameSeqId' in event.args);\n}\n\nexport interface RequestMainThreadFrame extends Instant {\n name: Name.REQUEST_MAIN_THREAD_FRAME;\n args: Args&{\n layerTreeId: number,\n };\n}\nexport function isRequestMainThreadFrame(event: Event): event is RequestMainThreadFrame {\n return event.name === Name.REQUEST_MAIN_THREAD_FRAME;\n}\n\nexport interface BeginMainThreadFrame extends Instant {\n name: Name.BEGIN_MAIN_THREAD_FRAME;\n args: Args&{\n layerTreeId: number,\n data: ArgsData&{\n frameId?: number,\n },\n };\n}\nexport function isBeginMainThreadFrame(event: Event): event is BeginMainThreadFrame {\n return event.name === Name.BEGIN_MAIN_THREAD_FRAME;\n}\n\nexport interface NeedsBeginFrameChanged extends Instant {\n name: Name.NEEDS_BEGIN_FRAME_CHANGED;\n args: Args&{\n layerTreeId: number,\n data: ArgsData&{\n needsBeginFrame: number,\n },\n };\n}\nexport function isNeedsBeginFrameChanged(event: Event): event is NeedsBeginFrameChanged {\n return event.name === Name.NEEDS_BEGIN_FRAME_CHANGED;\n}\n\nexport interface Commit extends Instant {\n name: Name.COMMIT;\n args: Args&{\n layerTreeId: number,\n frameSeqId: number,\n };\n}\nexport function isCommit(event: Event): event is Commit {\n // Old traces did not have frameSeqId; but we do not want to support these.\n return Boolean(event.name === Name.COMMIT && event.args && 'frameSeqId' in event.args);\n}\n\nexport interface RasterTask extends Complete {\n name: Name.RASTER_TASK;\n args: Args&{\n tileData?: {\n layerId: number,\n sourceFrameNumber: number,\n tileId: {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n id_ref: string,\n },\n tileResolution: string,\n },\n };\n}\nexport function isRasterTask(event: Event): event is RasterTask {\n return event.name === Name.RASTER_TASK;\n}\n\n// CompositeLayers has been replaced by \"Commit\", but we support both to not break old traces being imported.\nexport interface CompositeLayers extends Instant {\n name: Name.COMPOSITE_LAYERS;\n args: Args&{\n layerTreeId: number,\n };\n}\nexport function isCompositeLayers(event: Event): event is CompositeLayers {\n return event.name === Name.COMPOSITE_LAYERS;\n}\n\nexport interface ActivateLayerTree extends Instant {\n name: Name.ACTIVATE_LAYER_TREE;\n args: Args&{\n layerTreeId: number,\n frameId: number,\n };\n}\nexport function isActivateLayerTree(event: Event): event is ActivateLayerTree {\n return event.name === Name.ACTIVATE_LAYER_TREE;\n}\n\nexport type InvalidationTrackingEvent = ScheduleStyleInvalidationTracking|StyleRecalcInvalidationTracking|\n StyleInvalidatorInvalidationTracking|LayoutInvalidationTracking;\n\nexport function isInvalidationTracking(event: Event): event is InvalidationTrackingEvent {\n return isScheduleStyleInvalidationTracking(event) || isStyleRecalcInvalidationTracking(event) ||\n isStyleInvalidatorInvalidationTracking(event) || isLayoutInvalidationTracking(event);\n}\n\nexport interface DrawLazyPixelRef extends Instant {\n name: Name.DRAW_LAZY_PIXEL_REF;\n args?: Args&{\n // eslint-disable-next-line @typescript-eslint/naming-convention\n LazyPixelRef: number,\n };\n}\nexport function isDrawLazyPixelRef(event: Event): event is DrawLazyPixelRef {\n return event.name === Name.DRAW_LAZY_PIXEL_REF;\n}\n\nexport interface DecodeLazyPixelRef extends Instant {\n name: Name.DECODE_LAZY_PIXEL_REF;\n args?: Args&{\n // eslint-disable-next-line @typescript-eslint/naming-convention\n LazyPixelRef: number,\n };\n}\nexport function isDecodeLazyPixelRef(event: Event): event is DecodeLazyPixelRef {\n return event.name === Name.DECODE_LAZY_PIXEL_REF;\n}\n\nexport interface DecodeImage extends Complete {\n name: Name.DECODE_IMAGE;\n args: Args&{\n imageType: string,\n };\n}\nexport function isDecodeImage(event: Event): event is DecodeImage {\n return event.name === Name.DECODE_IMAGE;\n}\n\nexport interface SelectorTiming {\n 'elapsed (us)': number;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n 'fast_reject_count': number;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n 'match_attempts': number;\n 'selector': string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n 'style_sheet_id': string;\n // eslint-disable-next-line @typescript-eslint/naming-convention\n 'match_count': number;\n}\n\nexport enum SelectorTimingsKey {\n Elapsed = 'elapsed (us)',\n RejectPercentage = 'reject_percentage',\n FastRejectCount = 'fast_reject_count',\n MatchAttempts = 'match_attempts',\n MatchCount = 'match_count',\n Selector = 'selector',\n StyleSheetId = 'style_sheet_id',\n}\n\nexport interface SelectorStats {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n selector_timings: SelectorTiming[];\n}\n\nexport interface SelectorStats extends Complete {\n name: Name.SELECTOR_STATS;\n args: Args&{\n // eslint-disable-next-line @typescript-eslint/naming-convention\n selector_stats?: SelectorStats,\n };\n}\n\nexport function isSelectorStats(event: Event): event is SelectorStats {\n return event.name === Name.SELECTOR_STATS;\n}\n\nexport interface UpdateLayoutTree extends Complete {\n name: Name.UPDATE_LAYOUT_TREE;\n args: Args&{\n elementCount: number,\n beginData?: {\n frame: string,\n stackTrace?: CallFrame[],\n },\n };\n}\nexport function isUpdateLayoutTree(event: Event): event is UpdateLayoutTree {\n return event.name === Name.UPDATE_LAYOUT_TREE;\n}\n\nexport interface Layout extends Complete {\n name: Name.LAYOUT;\n args: Args&{\n beginData: {\n frame: string,\n dirtyObjects: number,\n partialLayout: boolean,\n totalObjects: number,\n },\n // endData is not reliably populated.\n // Why? TBD. https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/frame/local_frame_view.cc;l=847-851;drc=8b6aaad8027390ce6b32d82d57328e93f34bb8e5\n endData?: {\n layoutRoots: Array<{\n depth: number,\n nodeId: Protocol.DOM.BackendNodeId,\n quads: number[][],\n }>,\n },\n };\n}\nexport function isLayout(event: Event): event is Layout {\n return event.name === Name.LAYOUT;\n}\nexport interface InvalidateLayout extends Instant {\n name: Name.INVALIDATE_LAYOUT;\n args: Args&{\n data: {\n frame: string,\n nodeId: Protocol.DOM.BackendNodeId,\n },\n };\n}\nexport function isInvalidateLayout(event: Event): event is InvalidateLayout {\n return event.name === Name.INVALIDATE_LAYOUT;\n}\n\nclass ProfileIdTag {\n readonly #profileIdTag: (symbol|undefined);\n}\nexport type ProfileID = string&ProfileIdTag;\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport function ProfileID(value: string): ProfileID {\n return value as ProfileID;\n}\n\nclass CallFrameIdTag {\n readonly #callFrameIdTag: (symbol|undefined);\n}\nexport type CallFrameID = number&CallFrameIdTag;\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport function CallFrameID(value: number): CallFrameID {\n return value as CallFrameID;\n}\n\nclass SampleIndexTag {\n readonly #sampleIndexTag: (symbol|undefined);\n}\nexport type SampleIndex = number&SampleIndexTag;\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport function SampleIndex(value: number): SampleIndex {\n return value as SampleIndex;\n}\n\nclass ProcessIdTag {\n readonly #processIdTag: (symbol|undefined);\n}\nexport type ProcessID = number&ProcessIdTag;\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport function ProcessID(value: number): ProcessID {\n return value as ProcessID;\n}\n\nclass ThreadIdTag {\n readonly #threadIdTag: (symbol|undefined);\n}\nexport type ThreadID = number&ThreadIdTag;\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport function ThreadID(value: number): ThreadID {\n return value as ThreadID;\n}\n\nclass WorkerIdTag {\n readonly #workerIdTag: (symbol|undefined);\n}\nexport type WorkerId = string&WorkerIdTag;\n// eslint-disable-next-line @typescript-eslint/naming-convention\nexport function WorkerId(value: string): WorkerId {\n return value as WorkerId;\n}\n\nexport function isComplete(event: Event): event is Complete {\n return event.ph === Phase.COMPLETE;\n}\n\nexport function isBegin(event: Event): event is Begin {\n return event.ph === Phase.BEGIN;\n}\n\nexport function isEnd(event: Event): event is End {\n return event.ph === Phase.END;\n}\n\nexport function isDispatch(event: Event): event is Dispatch {\n return event.name === 'EventDispatch';\n}\n\nexport function isInstant(event: Event): event is Instant {\n return event.ph === Phase.INSTANT;\n}\n\nexport function isRendererEvent(event: Event): event is RendererEvent {\n return isInstant(event) || isComplete(event);\n}\n\nexport function isFireIdleCallback(event: Event): event is FireIdleCallback {\n return event.name === 'FireIdleCallback';\n}\n\nexport function isSchedulePostMessage(event: Event): event is SchedulePostMessage {\n return event.name === Name.SCHEDULE_POST_MESSAGE;\n}\n\nexport function isHandlePostMessage(event: Event): event is HandlePostMessage {\n return event.name === Name.HANDLE_POST_MESSAGE;\n}\n\nexport function isUpdateCounters(event: Event): event is UpdateCounters {\n return event.name === 'UpdateCounters';\n}\n\nexport function isThreadName(\n event: Event,\n ): event is ThreadName {\n return event.name === Name.THREAD_NAME;\n}\n\nexport function isProcessName(\n event: Event,\n ): event is ProcessName {\n return event.name === 'process_name';\n}\n\nexport function isTracingStartedInBrowser(\n event: Event,\n ): event is TracingStartedInBrowser {\n return event.name === Name.TRACING_STARTED_IN_BROWSER;\n}\n\nexport function isFrameCommittedInBrowser(\n event: Event,\n ): event is FrameCommittedInBrowser {\n return event.name === 'FrameCommittedInBrowser';\n}\n\nexport function isCommitLoad(\n event: Event,\n ): event is CommitLoad {\n return event.name === 'CommitLoad';\n}\n\nexport function isNavigationStart(\n event: Event,\n ): event is NavigationStart {\n return event.name === 'navigationStart';\n}\n\nexport function isAnimation(\n event: Event,\n ): event is Animation {\n // We've found some rare traces with an Animtation trace event from a different category: https://crbug.com/1472375#comment7\n return event.name === 'Animation' && event.cat.includes('devtools.timeline');\n}\n\nexport function isSyntheticAnimation(event: Event): event is SyntheticAnimationPair {\n if (event.name !== 'Animation' || !event.cat.includes('devtools.timeline')) {\n return false;\n }\n const data = event.args?.data;\n if (!data) {\n return false;\n }\n return 'beginEvent' in data && 'endEvent' in data;\n}\n\nexport function isLayoutShift(\n event: Event,\n ): event is LayoutShift {\n return event.name === 'LayoutShift';\n}\n\nexport function isLayoutInvalidationTracking(\n event: Event,\n ): event is LayoutInvalidationTracking {\n return event.name === Name.LAYOUT_INVALIDATION_TRACKING;\n}\n\nexport function isFirstContentfulPaint(event: Event): event is FirstContentfulPaint {\n return event.name === 'firstContentfulPaint';\n}\n\nexport function isLargestContentfulPaintCandidate(event: Event): event is LargestContentfulPaintCandidate {\n return event.name === Name.MARK_LCP_CANDIDATE;\n}\nexport function isLargestImagePaintCandidate(event: Event): event is LargestImagePaintCandidate {\n return event.name === 'LargestImagePaint::Candidate';\n}\nexport function isLargestTextPaintCandidate(event: Event): event is LargestTextPaintCandidate {\n return event.name === 'LargestTextPaint::Candidate';\n}\n\nexport function isMarkLoad(event: Event): event is MarkLoad {\n return event.name === 'MarkLoad';\n}\n\nexport function isFirstPaint(event: Event): event is FirstPaint {\n return event.name === 'firstPaint';\n}\n\nexport function isMarkDOMContent(event: Event): event is MarkDOMContent {\n return event.name === 'MarkDOMContent';\n}\n\nexport function isInteractiveTime(event: Event): event is InteractiveTime {\n return event.name === 'InteractiveTime';\n}\n\nexport function isEventTiming(event: Event): event is EventTiming {\n return event.name === Name.EVENT_TIMING;\n}\n\nexport function isEventTimingEnd(event: Event): event is EventTimingEnd {\n return isEventTiming(event) && event.ph === Phase.ASYNC_NESTABLE_END;\n}\nexport function isEventTimingStart(event: Event): event is EventTimingBegin {\n return isEventTiming(event) && event.ph === Phase.ASYNC_NESTABLE_START;\n}\n\nexport function isGPUTask(event: Event): event is GPUTask {\n return event.name === 'GPUTask';\n}\n\nexport function isProfile(event: Event): event is Profile {\n return event.name === 'Profile';\n}\n\nexport function isSyntheticCpuProfile(event: Event): event is SyntheticCpuProfile {\n return event.name === 'CpuProfile';\n}\n\nexport function isProfileChunk(event: Event): event is ProfileChunk {\n return event.name === 'ProfileChunk';\n}\n\nexport function isResourceChangePriority(\n event: Event,\n ): event is ResourceChangePriority {\n return event.name === 'ResourceChangePriority';\n}\n\nexport function isResourceSendRequest(\n event: Event,\n ): event is ResourceSendRequest {\n return event.name === 'ResourceSendRequest';\n}\n\nexport function isResourceReceiveResponse(\n event: Event,\n ): event is ResourceReceiveResponse {\n return event.name === 'ResourceReceiveResponse';\n}\n\nexport function isResourceMarkAsCached(\n event: Event,\n ): event is ResourceMarkAsCached {\n return event.name === 'ResourceMarkAsCached';\n}\n\nexport function isResourceFinish(\n event: Event,\n ): event is ResourceFinish {\n return event.name === 'ResourceFinish';\n}\n\nexport function isResourceWillSendRequest(\n event: Event,\n ): event is ResourceWillSendRequest {\n return event.name === 'ResourceWillSendRequest';\n}\n\nexport function isResourceReceivedData(\n event: Event,\n ): event is ResourceReceivedData {\n return event.name === 'ResourceReceivedData';\n}\n\nexport function isSyntheticNetworkRequest(\n event: Event,\n ): event is SyntheticNetworkRequest {\n return event.name === 'SyntheticNetworkRequest';\n}\n\nexport function isSyntheticWebSocketConnection(\n event: Event,\n ): event is SyntheticWebSocketConnection {\n return event.name === 'SyntheticWebSocketConnection';\n}\n\nexport function isNetworkTrackEntry(event: Event): event is SyntheticWebSocketConnection|SyntheticNetworkRequest {\n return isSyntheticNetworkRequest(event) || isSyntheticWebSocketConnection(event) || isWebSocketTraceEvent(event);\n}\n\nexport function isPrePaint(\n event: Event,\n ): event is PrePaint {\n return event.name === 'PrePaint';\n}\n\nexport function isNavigationStartWithURL(event: Event): event is NavigationStart {\n return Boolean(isNavigationStart(event) && event.args.data && event.args.data.documentLoaderURL !== '');\n}\n\nexport function isMainFrameViewport(\n event: Event,\n ): event is MainFrameViewport {\n return event.name === 'PaintTimingVisualizer::Viewport';\n}\n\nexport function isSyntheticUserTiming(event: Event): event is SyntheticUserTimingPair {\n if (event.cat !== 'blink.user_timing') {\n return false;\n }\n const data = event.args?.data;\n if (!data) {\n return false;\n }\n return 'beginEvent' in data && 'endEvent' in data;\n}\n\nexport function isSyntheticConsoleTiming(event: Event): event is SyntheticConsoleTimingPair {\n if (event.cat !== 'blink.console') {\n return false;\n }\n const data = event.args?.data;\n if (!data) {\n return false;\n }\n return 'beginEvent' in data && 'endEvent' in data;\n}\n\nexport function isUserTiming(event: Event): event is UserTiming {\n return event.cat === 'blink.user_timing';\n}\n\nexport function isDomLoading(event: Event): event is DomLoading {\n return event.name === Name.DOM_LOADING;\n}\n\nexport function isBeginRemoteFontLoad(event: Event): event is BeginRemoteFontLoad {\n return event.name === Name.BEGIN_REMOTE_FONT_LOAD;\n}\n\nexport function isPerformanceMeasure(event: Event): event is PerformanceMeasure {\n return isUserTiming(event) && isPhaseAsync(event.ph);\n}\n\nexport function isPerformanceMark(event: Event): event is PerformanceMark {\n return isUserTiming(event) && (event.ph === Phase.MARK || event.ph === Phase.INSTANT);\n}\n\nexport function isConsoleTime(event: Event): event is ConsoleTime {\n return event.cat === 'blink.console' && isPhaseAsync(event.ph);\n}\n\nexport function isTimeStamp(event: Event): event is TimeStamp {\n return event.ph === Phase.INSTANT && event.name === 'TimeStamp';\n}\n\nexport function isParseHTML(event: Event): event is ParseHTML {\n return event.name === 'ParseHTML';\n}\n\nexport interface Async extends Event {\n ph: Phase.ASYNC_NESTABLE_START|Phase.ASYNC_NESTABLE_INSTANT|Phase.ASYNC_NESTABLE_END|Phase.ASYNC_STEP_INTO|\n Phase.ASYNC_BEGIN|Phase.ASYNC_END|Phase.ASYNC_STEP_PAST;\n}\n\nexport function isSyntheticLayoutShift(event: Event): event is SyntheticLayoutShift {\n if (!isLayoutShift(event) || !event.args.data) {\n return false;\n }\n return 'rawEvent' in event.args.data;\n}\n\nexport function isSyntheticLayoutShiftCluster(event: Event): event is SyntheticLayoutShiftCluster {\n return event.name === Name.SYNTHETIC_LAYOUT_SHIFT_CLUSTER;\n}\n\nexport function isProfileCall(event: Event): event is SyntheticProfileCall {\n return 'callFrame' in event;\n}\n\nexport interface Paint extends Complete {\n name: Name.PAINT;\n args: Args&{\n data: ArgsData & {\n clip: number[],\n frame: string,\n layerId: number,\n // With CompositeAfterPaint enabled, paint events are no longer\n // associated with a Node, and nodeId will not be present.\n nodeId?: Protocol.DOM.BackendNodeId,\n },\n };\n}\n\nexport function isPaint(event: Event): event is Paint {\n return event.name === Name.PAINT;\n}\n\nexport interface PaintImage extends Complete {\n name: Name.PAINT_IMAGE;\n args: Args&{\n data: Event & {\n height: number,\n width: number,\n x: number,\n y: number,\n url?: string, srcHeight: number, srcWidth: number,\n nodeId?: Protocol.DOM.BackendNodeId,\n },\n };\n}\nexport function isPaintImage(event: Event): event is PaintImage {\n return event.name === Name.PAINT_IMAGE;\n}\n\nexport interface ScrollLayer extends Complete {\n name: Name.SCROLL_LAYER;\n args: Args&{\n data: Event & {\n frame: string,\n nodeId?: Protocol.DOM.BackendNodeId,\n },\n };\n}\nexport function isScrollLayer(event: Event): event is ScrollLayer {\n return event.name === Name.SCROLL_LAYER;\n}\n\nexport interface SetLayerTreeId extends Instant {\n name: Name.SET_LAYER_TREE_ID;\n args: Args&{\n data: ArgsData & {\n frame: string,\n layerTreeId: number,\n },\n };\n}\nexport function isSetLayerId(event: Event): event is SetLayerTreeId {\n return event.name === Name.SET_LAYER_TREE_ID;\n}\nexport interface UpdateLayer extends Complete {\n name: Name.UPDATE_LAYER;\n args: Args&{\n layerId: number,\n layerTreeId: number,\n };\n}\nexport function isUpdateLayer(event: Event): event is UpdateLayer {\n return event.name === Name.UPDATE_LAYER;\n}\n\nexport interface DisplayItemListSnapshot extends Event {\n name: Name.DISPLAY_ITEM_LIST_SNAPSHOT;\n ph: Phase.OBJECT_SNAPSHOT;\n id2: {\n local?: string,\n };\n args: Args&{\n snapshot: {\n skp64: string,\n params?: {\n // eslint-disable-next-line @typescript-eslint/naming-convention\n layer_rect: [number, number, number, number],\n },\n },\n };\n}\nexport function isDisplayListItemListSnapshot(event: Event): event is DisplayItemListSnapshot {\n return event.name === Name.DISPLAY_ITEM_LIST_SNAPSHOT;\n}\n\nexport interface LayerTreeHostImplSnapshot extends Event {\n name: Name.LAYER_TREE_HOST_IMPL_SNAPSHOT;\n ph: Phase.OBJECT_SNAPSHOT;\n id: string;\n args: Args&{\n snapshot: {\n /* eslint-disable @typescript-eslint/naming-convention */\n active_tiles: Array<{\n id: string,\n layer_id: string,\n gpu_memory_usage: number,\n content_rect: number[],\n }>,\n device_viewport_size: {\n width: number,\n height: number,\n },\n active_tree: {\n root_layer: TraceLayer,\n layers: TraceLayer[],\n },\n /* eslint-enable @typescript-eslint/naming-convention */\n },\n };\n}\n\nexport function isLayerTreeHostImplSnapshot(event: Event): event is LayerTreeHostImplSnapshot {\n return event.name === Name.LAYER_TREE_HOST_IMPL_SNAPSHOT;\n}\n/* eslint-disable @typescript-eslint/naming-convention */\nexport interface TraceLayer {\n bounds: {height: number, width: number};\n children: TraceLayer[];\n layer_id: number;\n position: number[];\n scroll_offset: number[];\n layer_quad: number[];\n draws_content: number;\n gpu_memory_usage: number;\n transform: number[];\n owner_node: Protocol.DOM.BackendNodeId;\n compositing_reasons: string[];\n compositing_reason_ids: string[];\n non_fast_scrollable_region: number[];\n touch_event_handler_region: number[];\n wheel_event_handler_region: number[];\n scroll_event_handler_region: number[];\n}\n\nexport interface TracingLayerTile {\n id: string;\n layer_id: string;\n gpu_memory_usage: number;\n content_rect: number[];\n}\n/* eslint-enable @typescript-eslint/naming-convention */\n\nexport interface FireAnimationFrame extends Complete {\n name: Name.FIRE_ANIMATION_FRAME;\n args: Args&{\n data: {\n frame: string,\n id: number,\n },\n };\n}\nexport function isFireAnimationFrame(event: Event): event is FireAnimationFrame {\n return event.name === Name.FIRE_ANIMATION_FRAME;\n}\n\nexport interface RequestAnimationFrame extends Instant {\n name: Name.REQUEST_ANIMATION_FRAME;\n args: Args&{\n data: {\n frame: string,\n id: number,\n stackTrace?: CallFrame,\n },\n };\n}\nexport function isRequestAnimationFrame(event: Event): event is RequestAnimationFrame {\n return event.name === Name.REQUEST_ANIMATION_FRAME;\n}\n\nexport interface TimerInstall extends Instant {\n name: Name.TIMER_INSTALL;\n args: Args&{\n data: {\n frame: string,\n singleShot: boolean,\n stackTrace?: CallFrame, timeout: number, timerId: number,\n },\n };\n}\nexport function isTimerInstall(event: Event): event is TimerInstall {\n return event.name === Name.TIMER_INSTALL;\n}\n\nexport interface TimerFire extends Complete {\n name: Name.TIMER_FIRE;\n args: Args&{\n data: {\n frame: string,\n timerId: number,\n },\n };\n}\nexport function isTimerFire(event: Event): event is TimerFire {\n return event.name === Name.TIMER_FIRE;\n}\n\nexport interface RequestIdleCallback extends Instant {\n name: Name.REQUEST_IDLE_CALLBACK;\n args: Args&{\n data: {\n frame: string,\n id: number,\n timeout: number,\n stackTrace?: CallFrame,\n },\n\n };\n}\nexport function isRequestIdleCallback(event: Event): event is RequestIdleCallback {\n return event.name === Name.REQUEST_IDLE_CALLBACK;\n}\n\nexport interface WebSocketCreate extends Instant {\n name: Name.WEB_SOCKET_CREATE;\n args: Args&{\n data: {\n identifier: number,\n url: string,\n frame?: string,\n workerId?: string,\n websocketProtocol?: string,\n stackTrace?: CallFrame,\n },\n };\n}\nexport function isWebSocketCreate(event: Event): event is WebSocketCreate {\n return event.name === Name.WEB_SOCKET_CREATE;\n}\n\nexport interface WebSocketInfo extends Instant {\n name: Name.WEB_SOCKET_DESTROY|Name.WEB_SOCKET_RECEIVE_HANDSHAKE|Name.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST;\n args: Args&{\n data: ArgsData & {\n identifier: number,\n url: string,\n frame?: string,\n workerId?: string,\n },\n };\n}\nexport interface WebSocketTransfer extends Instant {\n name: Name.WEB_SOCKET_SEND|Name.WEB_SOCKET_RECEIVE;\n args: Args&{\n data: ArgsData & {\n identifier: number,\n url: string,\n frame?: string,\n workerId?: string, dataLength: number,\n },\n };\n}\nexport function isWebSocketInfo(event: Event): event is WebSocketInfo {\n return event.name === Name.WEB_SOCKET_SEND_HANDSHAKE_REQUEST ||\n event.name === Name.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST || event.name === Name.WEB_SOCKET_DESTROY;\n}\n\nexport function isWebSocketTransfer(event: Event): event is WebSocketTransfer {\n return event.name === Name.WEB_SOCKET_SEND || event.name === Name.WEB_SOCKET_RECEIVE;\n}\n\nexport interface WebSocketSend extends Instant {\n name: Name.WEB_SOCKET_SEND;\n args: Args&{\n data: ArgsData & {\n identifier: number,\n url: string,\n frame?: string,\n workerId?: string, dataLength: number,\n },\n };\n}\n\nexport function isWebSocketSend(event: Event): event is WebSocketSend {\n return event.name === Name.WEB_SOCKET_SEND;\n}\n\nexport interface WebSocketReceive extends Instant {\n name: Name.WEB_SOCKET_RECEIVE;\n args: Args&{\n data: ArgsData & {\n identifier: number,\n url: string,\n frame?: string,\n workerId?: string, dataLength: number,\n },\n };\n}\nexport function isWebSocketReceive(event: Event): event is WebSocketReceive {\n return event.name === Name.WEB_SOCKET_RECEIVE;\n}\n\nexport interface WebSocketSendHandshakeRequest extends Instant {\n name: Name.WEB_SOCKET_SEND_HANDSHAKE_REQUEST;\n args: Args&{\n data: {\n frame: string,\n identifier: number,\n },\n };\n}\nexport function isWebSocketSendHandshakeRequest(event: Event): event is WebSocketSendHandshakeRequest {\n return event.name === Name.WEB_SOCKET_SEND_HANDSHAKE_REQUEST;\n}\n\nexport interface WebSocketReceiveHandshakeResponse extends Instant {\n name: Name.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST;\n args: Args&{\n data: {\n frame: string,\n identifier: number,\n },\n };\n}\nexport function isWebSocketReceiveHandshakeResponse(event: Event): event is WebSocketReceiveHandshakeResponse {\n return event.name === Name.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST;\n}\n\nexport interface WebSocketDestroy extends Instant {\n name: Name.WEB_SOCKET_DESTROY;\n args: Args&{\n data: {\n frame: string,\n identifier: number,\n },\n };\n}\nexport function isWebSocketDestroy(event: Event): event is WebSocketDestroy {\n return event.name === Name.WEB_SOCKET_DESTROY;\n}\n\nexport type WebSocketTraceEvent = WebSocketCreate|WebSocketInfo|WebSocketTransfer;\nexport function isWebSocketTraceEvent(event: Event): event is WebSocketTraceEvent {\n return isWebSocketCreate(event) || isWebSocketInfo(event) || isWebSocketTransfer(event);\n}\n\nexport type WebSocketEvent = WebSocketTraceEvent|SyntheticWebSocketConnection;\nexport function isWebSocketEvent(event: Event): event is WebSocketTraceEvent|SyntheticWebSocketConnection {\n return isWebSocketTraceEvent(event) || isSyntheticWebSocketConnection(event);\n}\n\nexport interface V8Compile extends Complete {\n name: Name.COMPILE;\n args: Args&{\n data?: {\n url?: string,\n columnNumber?: number,\n consumedCacheSize?: number,\n cacheRejected?: boolean,\n cacheKind?: 'full'|'normal',\n lineNumber?: number,\n notStreamedReason?: string,\n streamed?: boolean,\n eager?: boolean,\n },\n fileName?: string,\n };\n}\nexport function isV8Compile(event: Event): event is V8Compile {\n return event.name === Name.COMPILE;\n}\n\nexport interface FunctionCall extends Complete {\n name: Name.FUNCTION_CALL;\n args: Args&{\n data?: {\n frame?: string,\n columnNumber?: number,\n lineNumber?: number,\n functionName?: string,\n scriptId?: number,\n url?: string,\n },\n };\n}\nexport function isFunctionCall(event: Event): event is FunctionCall {\n return event.name === Name.FUNCTION_CALL;\n}\n\nexport function isSyntheticServerTiming(event: Event): event is SyntheticServerTiming {\n return event.cat === 'devtools.server-timing';\n}\n\n/**\n * Generally, before JS is executed, a trace event is dispatched that\n * parents the JS calls. These we call \"invocation\" events. This\n * function determines if an event is one of such.\n */\nexport function isJSInvocationEvent(event: Event): boolean {\n switch (event.name) {\n case Name.RUN_MICROTASKS:\n case Name.FUNCTION_CALL:\n case Name.EVALUATE_SCRIPT:\n case Name.EVALUATE_MODULE:\n case Name.EVENT_DISPATCH:\n case Name.V8_EXECUTE:\n return true;\n }\n // Also consider any new v8 trace events. (eg 'V8.RunMicrotasks' and 'v8.run')\n if (event.name.startsWith('v8') || event.name.startsWith('V8')) {\n return true;\n }\n return false;\n}\n\n/**\n * This is an exhaustive list of events we track in the Performance\n * panel. Note not all of them are necessarliry shown in the flame\n * chart, some of them we only use for parsing.\n * TODO(crbug.com/1428024): Complete this enum.\n */\nexport const enum Name {\n /* Metadata */\n THREAD_NAME = 'thread_name',\n\n /* Task */\n PROGRAM = 'Program',\n RUN_TASK = 'RunTask',\n ASYNC_TASK = 'AsyncTask',\n RUN_MICROTASKS = 'RunMicrotasks',\n\n /* Load */\n XHR_LOAD = 'XHRLoad',\n XHR_READY_STATE_CHANGED = 'XHRReadyStateChange',\n /* Parse */\n PARSE_HTML = 'ParseHTML',\n PARSE_CSS = 'ParseAuthorStyleSheet',\n /* V8 */\n COMPILE_CODE = 'V8.CompileCode',\n COMPILE_MODULE = 'V8.CompileModule',\n // Although V8 emits the V8.CompileScript event, the event that actually\n // contains the useful information about the script (URL, etc), is contained\n // in the v8.compile event.\n // Yes, it is all lowercase compared to all the rest of the V8... events,\n // that is not a typo :)\n COMPILE = 'v8.compile',\n COMPILE_SCRIPT = 'V8.CompileScript',\n OPTIMIZE = 'V8.OptimizeCode',\n WASM_STREAM_FROM_RESPONSE_CALLBACK = 'v8.wasm.streamFromResponseCallback',\n WASM_COMPILED_MODULE = 'v8.wasm.compiledModule',\n WASM_CACHED_MODULE = 'v8.wasm.cachedModule',\n WASM_MODULE_CACHE_HIT = 'v8.wasm.moduleCacheHit',\n WASM_MODULE_CACHE_INVALID = 'v8.wasm.moduleCacheInvalid',\n /* Js */\n PROFILE_CALL = 'ProfileCall',\n EVALUATE_SCRIPT = 'EvaluateScript',\n FUNCTION_CALL = 'FunctionCall',\n EVENT_DISPATCH = 'EventDispatch',\n EVALUATE_MODULE = 'v8.evaluateModule',\n REQUEST_MAIN_THREAD_FRAME = 'RequestMainThreadFrame',\n REQUEST_ANIMATION_FRAME = 'RequestAnimationFrame',\n CANCEL_ANIMATION_FRAME = 'CancelAnimationFrame',\n FIRE_ANIMATION_FRAME = 'FireAnimationFrame',\n REQUEST_IDLE_CALLBACK = 'RequestIdleCallback',\n CANCEL_IDLE_CALLBACK = 'CancelIdleCallback',\n FIRE_IDLE_CALLBACK = 'FireIdleCallback',\n TIMER_INSTALL = 'TimerInstall',\n TIMER_REMOVE = 'TimerRemove',\n TIMER_FIRE = 'TimerFire',\n WEB_SOCKET_CREATE = 'WebSocketCreate',\n WEB_SOCKET_SEND_HANDSHAKE = 'WebSocketSendHandshakeRequest',\n WEB_SOCKET_RECEIVE_HANDSHAKE = 'WebSocketReceiveHandshakeResponse',\n WEB_SOCKET_DESTROY = 'WebSocketDestroy',\n WEB_SOCKET_SEND = 'WebSocketSend',\n WEB_SOCKET_RECEIVE = 'WebSocketReceive',\n CRYPTO_DO_ENCRYPT = 'DoEncrypt',\n CRYPTO_DO_ENCRYPT_REPLY = 'DoEncryptReply',\n CRYPTO_DO_DECRYPT = 'DoDecrypt',\n CRYPTO_DO_DECRYPT_REPLY = 'DoDecryptReply',\n CRYPTO_DO_DIGEST = 'DoDigest',\n CRYPTO_DO_DIGEST_REPLY = 'DoDigestReply',\n CRYPTO_DO_SIGN = 'DoSign',\n CRYPTO_DO_SIGN_REPLY = 'DoSignReply',\n CRYPTO_DO_VERIFY = 'DoVerify',\n CRYPTO_DO_VERIFY_REPLY = 'DoVerifyReply',\n V8_EXECUTE = 'V8.Execute',\n\n /* Gc */\n GC = 'GCEvent',\n DOMGC = 'BlinkGC.AtomicPhase',\n MAJOR_GC = 'MajorGC',\n MINOR_GC = 'MinorGC',\n GC_COLLECT_GARBARGE = 'BlinkGC.AtomicPhase',\n CPPGC_SWEEP = 'CppGC.IncrementalSweep',\n\n /* Layout */\n SCHEDULE_STYLE_RECALCULATION = 'ScheduleStyleRecalculation',\n LAYOUT = 'Layout',\n UPDATE_LAYOUT_TREE = 'UpdateLayoutTree',\n INVALIDATE_LAYOUT = 'InvalidateLayout',\n LAYOUT_INVALIDATION_TRACKING = 'LayoutInvalidationTracking',\n COMPUTE_INTERSECTION = 'ComputeIntersections',\n HIT_TEST = 'HitTest',\n PRE_PAINT = 'PrePaint',\n LAYERIZE = 'Layerize',\n LAYOUT_SHIFT = 'LayoutShift',\n SYNTHETIC_LAYOUT_SHIFT_CLUSTER = 'SyntheticLayoutShiftCluster',\n UPDATE_LAYER_TREE = 'UpdateLayerTree',\n SCHEDULE_STYLE_INVALIDATION_TRACKING = 'ScheduleStyleInvalidationTracking',\n STYLE_RECALC_INVALIDATION_TRACKING = 'StyleRecalcInvalidationTracking',\n STYLE_INVALIDATOR_INVALIDATION_TRACKING = 'StyleInvalidatorInvalidationTracking',\n SELECTOR_STATS = 'SelectorStats',\n BEGIN_COMMIT_COMPOSITOR_FRAME = 'BeginCommitCompositorFrame',\n PARSE_META_VIEWPORT = 'ParseMetaViewport',\n\n /* Paint */\n SCROLL_LAYER = 'ScrollLayer',\n UPDATE_LAYER = 'UpdateLayer',\n PAINT_SETUP = 'PaintSetup',\n PAINT = 'Paint',\n PAINT_IMAGE = 'PaintImage',\n COMMIT = 'Commit',\n COMPOSITE_LAYERS = 'CompositeLayers',\n RASTER_TASK = 'RasterTask',\n IMAGE_DECODE_TASK = 'ImageDecodeTask',\n IMAGE_UPLOAD_TASK = 'ImageUploadTask',\n DECODE_IMAGE = 'Decode Image',\n DRAW_LAZY_PIXEL_REF = 'Draw LazyPixelRef',\n DECODE_LAZY_PIXEL_REF = 'Decode LazyPixelRef',\n GPU_TASK = 'GPUTask',\n RASTERIZE = 'Rasterize',\n EVENT_TIMING = 'EventTiming',\n\n /* Compile */\n OPTIMIZE_CODE = 'V8.OptimizeCode',\n CACHE_SCRIPT = 'v8.produceCache',\n CACHE_MODULE = 'v8.produceModuleCache',\n // V8Sample events are coming from tracing and contain raw stacks with function addresses.\n // After being processed with help of JitCodeAdded and JitCodeMoved events they\n // get translated into function infos and stored as stacks in JSSample events.\n V8_SAMPLE = 'V8Sample',\n JIT_CODE_ADDED = 'JitCodeAdded',\n JIT_CODE_MOVED = 'JitCodeMoved',\n STREAMING_COMPILE_SCRIPT = 'v8.parseOnBackground',\n STREAMING_COMPILE_SCRIPT_WAITING = 'v8.parseOnBackgroundWaiting',\n STREAMING_COMPILE_SCRIPT_PARSING = 'v8.parseOnBackgroundParsing',\n BACKGROUND_DESERIALIZE = 'v8.deserializeOnBackground',\n FINALIZE_DESERIALIZATION = 'V8.FinalizeDeserialization',\n\n /* Markers */\n COMMIT_LOAD = 'CommitLoad',\n MARK_LOAD = 'MarkLoad',\n MARK_DOM_CONTENT = 'MarkDOMContent',\n MARK_FIRST_PAINT = 'firstPaint',\n MARK_FCP = 'firstContentfulPaint',\n MARK_LCP_CANDIDATE = 'largestContentfulPaint::Candidate',\n MARK_LCP_INVALIDATE = 'largestContentfulPaint::Invalidate',\n NAVIGATION_START = 'navigationStart',\n TIME_STAMP = 'TimeStamp',\n CONSOLE_TIME = 'ConsoleTime',\n USER_TIMING = 'UserTiming',\n INTERACTIVE_TIME = 'InteractiveTime',\n\n /* Frames */\n BEGIN_FRAME = 'BeginFrame',\n NEEDS_BEGIN_FRAME_CHANGED = 'NeedsBeginFrameChanged',\n BEGIN_MAIN_THREAD_FRAME = 'BeginMainThreadFrame',\n ACTIVATE_LAYER_TREE = 'ActivateLayerTree',\n DRAW_FRAME = 'DrawFrame',\n DROPPED_FRAME = 'DroppedFrame',\n FRAME_STARTED_LOADING = 'FrameStartedLoading',\n PIPELINE_REPORTER = 'PipelineReporter',\n SCREENSHOT = 'Screenshot',\n\n /* Network request events */\n RESOURCE_WILL_SEND_REQUEST = 'ResourceWillSendRequest',\n RESOURCE_SEND_REQUEST = 'ResourceSendRequest',\n RESOURCE_RECEIVE_RESPONSE = 'ResourceReceiveResponse',\n RESOURCE_RECEIVE_DATA = 'ResourceReceivedData',\n RESOURCE_FINISH = 'ResourceFinish',\n RESOURCE_MARK_AS_CACHED = 'ResourceMarkAsCached',\n\n /* Web sockets */\n WEB_SOCKET_SEND_HANDSHAKE_REQUEST = 'WebSocketSendHandshakeRequest',\n WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST = 'WebSocketReceiveHandshakeResponse',\n\n /* CPU Profiling */\n PROFILE = 'Profile',\n START_PROFILING = 'CpuProfiler::StartProfiling',\n PROFILE_CHUNK = 'ProfileChunk',\n UPDATE_COUNTERS = 'UpdateCounters',\n\n JS_SAMPLE = 'JSSample',\n\n /* Other */\n ANIMATION = 'Animation',\n PARSE_AUTHOR_STYLE_SHEET = 'ParseAuthorStyleSheet',\n EMBEDDER_CALLBACK = 'EmbedderCallback',\n SET_LAYER_TREE_ID = 'SetLayerTreeId',\n TRACING_STARTED_IN_PAGE = 'TracingStartedInPage',\n TRACING_STARTED_IN_BROWSER = 'TracingStartedInBrowser',\n TRACING_SESSION_ID_FOR_WORKER = 'TracingSessionIdForWorker',\n LAZY_PIXEL_REF = 'LazyPixelRef',\n LAYER_TREE_HOST_IMPL_SNAPSHOT = 'cc::LayerTreeHostImpl',\n PICTURE_SNAPSHOT = 'cc::Picture',\n DISPLAY_ITEM_LIST_SNAPSHOT = 'cc::DisplayItemList',\n INPUT_LATENCY_MOUSE_MOVE = 'InputLatency::MouseMove',\n INPUT_LATENCY_MOUSE_WHEEL = 'InputLatency::MouseWheel',\n IMPL_SIDE_FLING = 'InputHandlerProxy::HandleGestureFling::started',\n\n SCHEDULE_POST_MESSAGE = 'SchedulePostMessage',\n HANDLE_POST_MESSAGE = 'HandlePostMessage',\n\n RENDER_FRAME_IMPL_CREATE_CHILD_FRAME = 'RenderFrameImpl::createChildFrame',\n\n DOM_LOADING = 'domLoading',\n BEGIN_REMOTE_FONT_LOAD = 'BeginRemoteFontLoad',\n}\n\n// NOT AN EXHAUSTIVE LIST: just some categories we use and refer\n// to in multiple places.\nexport const Categories = {\n Console: 'blink.console',\n UserTiming: 'blink.user_timing',\n Loading: 'loading',\n} as const;\n\n/**\n * The frames implementation in handlers/FramesHandler is considered \"legacy\"\n * in that it is based on the old TimelineModel implementation rather than\n * following the pattern of the other handlers. This will change in time as we\n * migrate the frames track to use AnimationFrame events, but for now we\n * maintain it because the effort required to migrate was large.\n * Consequently, the types we use through the codebase to refer to these frames\n * usually use ModelHandlers.FramesHandler.TimelineFrame, but in\n * trace/types/*.ts we cannot refer to types defined in the Handlers. To avoid a\n * circular dependency, we define these interfaces here which are implemented by\n * the classes in FramesHandler.ts, but they can also be used to refer to\n * instances of frames in trace/types/*.ts which is unable to import from\n * handlers.\n */\nexport interface LegacyTimelineFrame extends Event {\n startTime: MicroSeconds;\n startTimeOffset: MicroSeconds;\n endTime: MicroSeconds;\n duration: MicroSeconds;\n idle: boolean;\n dropped: boolean;\n isPartial: boolean;\n layerTree: LegacyFrameLayerTreeData|null;\n paints: LegacyLayerPaintEvent[];\n mainFrameId?: number;\n readonly seqId: number;\n index: number;\n}\n\nexport function isLegacyTimelineFrame(data: Event): data is LegacyTimelineFrame {\n return 'idle' in data && typeof data.idle === 'boolean';\n}\n\nexport interface LegacyFrameLayerTreeData {\n entry: LayerTreeHostImplSnapshot;\n paints: LegacyLayerPaintEvent[];\n}\n\nexport interface LegacyLayerPaintEvent {\n layerId(): number;\n event(): Paint;\n picture(): LegacyLayerPaintEventPicture|null;\n}\n\nexport interface LegacyLayerPaintEventPicture {\n rect: Array;\n serializedPicture: string;\n}\n"]} \ No newline at end of file diff --git a/public/models/trace/types/TraceEvents.test.js b/public/models/trace/types/TraceEvents.test.js index 8bd3dd19b..1acfcdde8 100644 --- a/public/models/trace/types/TraceEvents.test.js +++ b/public/models/trace/types/TraceEvents.test.js @@ -3,9 +3,9 @@ // found in the LICENSE file. import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; -import * as TraceEngine from '../trace.js'; +import * as Trace from '../trace.js'; describeWithEnvironment('TraceEvent types', function () { - const { Phase, isNestableAsyncPhase, isAsyncPhase, isFlowPhase } = TraceEngine.Types.TraceEvents; + const { Phase, isNestableAsyncPhase, isPhaseAsync, isFlowPhase } = Trace.Types.Events; it('is able to determine if a phase is a nestable async phase', function () { assert.isTrue(isNestableAsyncPhase("b" /* Phase.ASYNC_NESTABLE_START */)); assert.isTrue(isNestableAsyncPhase("e" /* Phase.ASYNC_NESTABLE_END */)); @@ -17,18 +17,18 @@ describeWithEnvironment('TraceEvent types', function () { assert.isFalse(isNestableAsyncPhase("S" /* Phase.ASYNC_BEGIN */)); }); it('is able to determine if a phase is an async phase', function () { - assert.isTrue(isAsyncPhase("b" /* Phase.ASYNC_NESTABLE_START */)); - assert.isTrue(isAsyncPhase("e" /* Phase.ASYNC_NESTABLE_END */)); - assert.isTrue(isAsyncPhase("n" /* Phase.ASYNC_NESTABLE_INSTANT */)); - assert.isTrue(isAsyncPhase("S" /* Phase.ASYNC_BEGIN */)); - assert.isTrue(isAsyncPhase("T" /* Phase.ASYNC_STEP_INTO */)); - assert.isTrue(isAsyncPhase("p" /* Phase.ASYNC_STEP_PAST */)); - assert.isTrue(isAsyncPhase("F" /* Phase.ASYNC_END */)); + assert.isTrue(isPhaseAsync("b" /* Phase.ASYNC_NESTABLE_START */)); + assert.isTrue(isPhaseAsync("e" /* Phase.ASYNC_NESTABLE_END */)); + assert.isTrue(isPhaseAsync("n" /* Phase.ASYNC_NESTABLE_INSTANT */)); + assert.isTrue(isPhaseAsync("S" /* Phase.ASYNC_BEGIN */)); + assert.isTrue(isPhaseAsync("T" /* Phase.ASYNC_STEP_INTO */)); + assert.isTrue(isPhaseAsync("p" /* Phase.ASYNC_STEP_PAST */)); + assert.isTrue(isPhaseAsync("F" /* Phase.ASYNC_END */)); }); it('is able to determine if a phase is not an async phase', function () { - assert.isFalse(isAsyncPhase("B" /* Phase.BEGIN */)); - assert.isFalse(isAsyncPhase("M" /* Phase.METADATA */)); - assert.isFalse(isAsyncPhase("N" /* Phase.OBJECT_CREATED */)); + assert.isFalse(isPhaseAsync("B" /* Phase.BEGIN */)); + assert.isFalse(isPhaseAsync("M" /* Phase.METADATA */)); + assert.isFalse(isPhaseAsync("N" /* Phase.OBJECT_CREATED */)); }); it('is able to determine if a phase is a flow phase', function () { assert.isTrue(isFlowPhase("s" /* Phase.FLOW_START */)); @@ -41,39 +41,39 @@ describeWithEnvironment('TraceEvent types', function () { assert.isFalse(isFlowPhase("B" /* Phase.BEGIN */)); }); it('is able to determine that an event is a synthetic user timing event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'timings-track.json.gz'); - const timingEvent = traceData.UserTimings.performanceMeasures[0]; - assert.isTrue(TraceEngine.Types.TraceEvents.isSyntheticUserTiming(timingEvent)); - const consoleEvent = traceData.UserTimings.consoleTimings[0]; - assert.isFalse(TraceEngine.Types.TraceEvents.isSyntheticUserTiming(consoleEvent)); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'timings-track.json.gz'); + const timingEvent = parsedTrace.UserTimings.performanceMeasures[0]; + assert.isTrue(Trace.Types.Events.isSyntheticUserTiming(timingEvent)); + const consoleEvent = parsedTrace.UserTimings.consoleTimings[0]; + assert.isFalse(Trace.Types.Events.isSyntheticUserTiming(consoleEvent)); }); it('is able to determine that an event is a synthetic console event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'timings-track.json.gz'); - const consoleEvent = traceData.UserTimings.consoleTimings[0]; - assert.isTrue(TraceEngine.Types.TraceEvents.isSyntheticConsoleTiming(consoleEvent)); - const timingEvent = traceData.UserTimings.performanceMeasures[0]; - assert.isFalse(TraceEngine.Types.TraceEvents.isSyntheticConsoleTiming(timingEvent)); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'timings-track.json.gz'); + const consoleEvent = parsedTrace.UserTimings.consoleTimings[0]; + assert.isTrue(Trace.Types.Events.isSyntheticConsoleTiming(consoleEvent)); + const timingEvent = parsedTrace.UserTimings.performanceMeasures[0]; + assert.isFalse(Trace.Types.Events.isSyntheticConsoleTiming(timingEvent)); }); it('is able to detemrine that an event is a synthetic network request event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'lcp-images.json.gz'); - const networkEvent = traceData.NetworkRequests.byTime[0]; - assert.isTrue(TraceEngine.Types.TraceEvents.isSyntheticNetworkRequestEvent(networkEvent)); - const otherEvent = traceData.Renderer.allTraceEntries[0]; - assert.isFalse(TraceEngine.Types.TraceEvents.isSyntheticNetworkRequestEvent(otherEvent)); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'lcp-images.json.gz'); + const networkEvent = parsedTrace.NetworkRequests.byTime[0]; + assert.isTrue(Trace.Types.Events.isSyntheticNetworkRequest(networkEvent)); + const otherEvent = parsedTrace.Renderer.allTraceEntries[0]; + assert.isFalse(Trace.Types.Events.isSyntheticNetworkRequest(otherEvent)); }); it('is able to determine that an event is a synthetic layout shift event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'cls-single-frame.json.gz'); - const syntheticLayoutShift = traceData.LayoutShifts.clusters[0].events[0]; - assert.isTrue(TraceEngine.Types.TraceEvents.isSyntheticLayoutShift(syntheticLayoutShift)); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'cls-single-frame.json.gz'); + const syntheticLayoutShift = parsedTrace.LayoutShifts.clusters[0].events[0]; + assert.isTrue(Trace.Types.Events.isSyntheticLayoutShift(syntheticLayoutShift)); }); it('is able to identify that an event is a legacy timeline frame', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); - const frame = traceData.Frames.frames.at(0); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); + const frame = parsedTrace.Frames.frames.at(0); assert.isOk(frame); - assert.isTrue(TraceEngine.Types.TraceEvents.isLegacyTimelineFrame(frame)); - const networkEvent = traceData.NetworkRequests.byTime.at(0); + assert.isTrue(Trace.Types.Events.isLegacyTimelineFrame(frame)); + const networkEvent = parsedTrace.NetworkRequests.byTime.at(0); assert.isOk(networkEvent); - assert.isFalse(TraceEngine.Types.TraceEvents.isLegacyTimelineFrame(networkEvent)); + assert.isFalse(Trace.Types.Events.isLegacyTimelineFrame(networkEvent)); }); }); //# sourceMappingURL=TraceEvents.test.js.map \ No newline at end of file diff --git a/public/models/trace/types/TraceEvents.test.js.map b/public/models/trace/types/TraceEvents.test.js.map index ecdd3e3b7..1eb22feab 100644 --- a/public/models/trace/types/TraceEvents.test.js.map +++ b/public/models/trace/types/TraceEvents.test.js.map @@ -1 +1 @@ -{"version":3,"file":"TraceEvents.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/types/TraceEvents.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as TraceEngine from '../trace.js';\n\ndescribeWithEnvironment('TraceEvent types', function() {\n const {Phase, isNestableAsyncPhase, isAsyncPhase, isFlowPhase} = TraceEngine.Types.TraceEvents;\n it('is able to determine if a phase is a nestable async phase', function() {\n assert.isTrue(isNestableAsyncPhase(Phase.ASYNC_NESTABLE_START));\n assert.isTrue(isNestableAsyncPhase(Phase.ASYNC_NESTABLE_END));\n assert.isTrue(isNestableAsyncPhase(Phase.ASYNC_NESTABLE_INSTANT));\n });\n\n it('is able to determine if a phase is not a nestable async phase', function() {\n assert.isFalse(isNestableAsyncPhase(Phase.BEGIN));\n assert.isFalse(isNestableAsyncPhase(Phase.END));\n assert.isFalse(isNestableAsyncPhase(Phase.ASYNC_BEGIN));\n });\n\n it('is able to determine if a phase is an async phase', function() {\n assert.isTrue(isAsyncPhase(Phase.ASYNC_NESTABLE_START));\n assert.isTrue(isAsyncPhase(Phase.ASYNC_NESTABLE_END));\n assert.isTrue(isAsyncPhase(Phase.ASYNC_NESTABLE_INSTANT));\n assert.isTrue(isAsyncPhase(Phase.ASYNC_BEGIN));\n assert.isTrue(isAsyncPhase(Phase.ASYNC_STEP_INTO));\n assert.isTrue(isAsyncPhase(Phase.ASYNC_STEP_PAST));\n assert.isTrue(isAsyncPhase(Phase.ASYNC_END));\n });\n\n it('is able to determine if a phase is not an async phase', function() {\n assert.isFalse(isAsyncPhase(Phase.BEGIN));\n assert.isFalse(isAsyncPhase(Phase.METADATA));\n assert.isFalse(isAsyncPhase(Phase.OBJECT_CREATED));\n });\n\n it('is able to determine if a phase is a flow phase', function() {\n assert.isTrue(isFlowPhase(Phase.FLOW_START));\n assert.isTrue(isFlowPhase(Phase.FLOW_STEP));\n assert.isTrue(isFlowPhase(Phase.FLOW_END));\n });\n\n it('is able to determine if a phase is not a flow phase', function() {\n assert.isFalse(isFlowPhase(Phase.ASYNC_STEP_INTO));\n assert.isFalse(isFlowPhase(Phase.ASYNC_NESTABLE_START));\n assert.isFalse(isFlowPhase(Phase.BEGIN));\n });\n\n it('is able to determine that an event is a synthetic user timing event', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'timings-track.json.gz');\n const timingEvent = traceData.UserTimings.performanceMeasures[0];\n assert.isTrue(TraceEngine.Types.TraceEvents.isSyntheticUserTiming(timingEvent));\n const consoleEvent = traceData.UserTimings.consoleTimings[0];\n assert.isFalse(TraceEngine.Types.TraceEvents.isSyntheticUserTiming(consoleEvent));\n });\n\n it('is able to determine that an event is a synthetic console event', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'timings-track.json.gz');\n const consoleEvent = traceData.UserTimings.consoleTimings[0];\n assert.isTrue(TraceEngine.Types.TraceEvents.isSyntheticConsoleTiming(consoleEvent));\n const timingEvent = traceData.UserTimings.performanceMeasures[0];\n assert.isFalse(TraceEngine.Types.TraceEvents.isSyntheticConsoleTiming(timingEvent));\n });\n\n it('is able to detemrine that an event is a synthetic network request event', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'lcp-images.json.gz');\n const networkEvent = traceData.NetworkRequests.byTime[0];\n assert.isTrue(TraceEngine.Types.TraceEvents.isSyntheticNetworkRequestEvent(networkEvent));\n const otherEvent = traceData.Renderer.allTraceEntries[0];\n assert.isFalse(TraceEngine.Types.TraceEvents.isSyntheticNetworkRequestEvent(otherEvent));\n });\n\n it('is able to determine that an event is a synthetic layout shift event', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'cls-single-frame.json.gz');\n const syntheticLayoutShift = traceData.LayoutShifts.clusters[0].events[0];\n assert.isTrue(TraceEngine.Types.TraceEvents.isSyntheticLayoutShift(syntheticLayoutShift));\n });\n\n it('is able to identify that an event is a legacy timeline frame', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n const frame = traceData.Frames.frames.at(0);\n assert.isOk(frame);\n assert.isTrue(TraceEngine.Types.TraceEvents.isLegacyTimelineFrame(frame));\n\n const networkEvent = traceData.NetworkRequests.byTime.at(0);\n assert.isOk(networkEvent);\n assert.isFalse(TraceEngine.Types.TraceEvents.isLegacyTimelineFrame(networkEvent));\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"TraceEvents.test.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/types/TraceEvents.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as Trace from '../trace.js';\n\ndescribeWithEnvironment('TraceEvent types', function() {\n const {Phase, isNestableAsyncPhase, isPhaseAsync, isFlowPhase} = Trace.Types.Events;\n it('is able to determine if a phase is a nestable async phase', function() {\n assert.isTrue(isNestableAsyncPhase(Phase.ASYNC_NESTABLE_START));\n assert.isTrue(isNestableAsyncPhase(Phase.ASYNC_NESTABLE_END));\n assert.isTrue(isNestableAsyncPhase(Phase.ASYNC_NESTABLE_INSTANT));\n });\n\n it('is able to determine if a phase is not a nestable async phase', function() {\n assert.isFalse(isNestableAsyncPhase(Phase.BEGIN));\n assert.isFalse(isNestableAsyncPhase(Phase.END));\n assert.isFalse(isNestableAsyncPhase(Phase.ASYNC_BEGIN));\n });\n\n it('is able to determine if a phase is an async phase', function() {\n assert.isTrue(isPhaseAsync(Phase.ASYNC_NESTABLE_START));\n assert.isTrue(isPhaseAsync(Phase.ASYNC_NESTABLE_END));\n assert.isTrue(isPhaseAsync(Phase.ASYNC_NESTABLE_INSTANT));\n assert.isTrue(isPhaseAsync(Phase.ASYNC_BEGIN));\n assert.isTrue(isPhaseAsync(Phase.ASYNC_STEP_INTO));\n assert.isTrue(isPhaseAsync(Phase.ASYNC_STEP_PAST));\n assert.isTrue(isPhaseAsync(Phase.ASYNC_END));\n });\n\n it('is able to determine if a phase is not an async phase', function() {\n assert.isFalse(isPhaseAsync(Phase.BEGIN));\n assert.isFalse(isPhaseAsync(Phase.METADATA));\n assert.isFalse(isPhaseAsync(Phase.OBJECT_CREATED));\n });\n\n it('is able to determine if a phase is a flow phase', function() {\n assert.isTrue(isFlowPhase(Phase.FLOW_START));\n assert.isTrue(isFlowPhase(Phase.FLOW_STEP));\n assert.isTrue(isFlowPhase(Phase.FLOW_END));\n });\n\n it('is able to determine if a phase is not a flow phase', function() {\n assert.isFalse(isFlowPhase(Phase.ASYNC_STEP_INTO));\n assert.isFalse(isFlowPhase(Phase.ASYNC_NESTABLE_START));\n assert.isFalse(isFlowPhase(Phase.BEGIN));\n });\n\n it('is able to determine that an event is a synthetic user timing event', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'timings-track.json.gz');\n const timingEvent = parsedTrace.UserTimings.performanceMeasures[0];\n assert.isTrue(Trace.Types.Events.isSyntheticUserTiming(timingEvent));\n const consoleEvent = parsedTrace.UserTimings.consoleTimings[0];\n assert.isFalse(Trace.Types.Events.isSyntheticUserTiming(consoleEvent));\n });\n\n it('is able to determine that an event is a synthetic console event', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'timings-track.json.gz');\n const consoleEvent = parsedTrace.UserTimings.consoleTimings[0];\n assert.isTrue(Trace.Types.Events.isSyntheticConsoleTiming(consoleEvent));\n const timingEvent = parsedTrace.UserTimings.performanceMeasures[0];\n assert.isFalse(Trace.Types.Events.isSyntheticConsoleTiming(timingEvent));\n });\n\n it('is able to detemrine that an event is a synthetic network request event', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'lcp-images.json.gz');\n const networkEvent = parsedTrace.NetworkRequests.byTime[0];\n assert.isTrue(Trace.Types.Events.isSyntheticNetworkRequest(networkEvent));\n const otherEvent = parsedTrace.Renderer.allTraceEntries[0];\n assert.isFalse(Trace.Types.Events.isSyntheticNetworkRequest(otherEvent));\n });\n\n it('is able to determine that an event is a synthetic layout shift event', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'cls-single-frame.json.gz');\n const syntheticLayoutShift = parsedTrace.LayoutShifts.clusters[0].events[0];\n assert.isTrue(Trace.Types.Events.isSyntheticLayoutShift(syntheticLayoutShift));\n });\n\n it('is able to identify that an event is a legacy timeline frame', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n const frame = parsedTrace.Frames.frames.at(0);\n assert.isOk(frame);\n assert.isTrue(Trace.Types.Events.isLegacyTimelineFrame(frame));\n\n const networkEvent = parsedTrace.NetworkRequests.byTime.at(0);\n assert.isOk(networkEvent);\n assert.isFalse(Trace.Types.Events.isLegacyTimelineFrame(networkEvent));\n });\n});\n"]} \ No newline at end of file diff --git a/public/models/trace/types/types.d.ts b/public/models/trace/types/types.d.ts index 0e089546e..df3862184 100644 --- a/public/models/trace/types/types.d.ts +++ b/public/models/trace/types/types.d.ts @@ -2,4 +2,4 @@ export * as Configuration from './Configuration.js'; export * as Extensions from './Extensions.js'; export * as File from './File.js'; export * as Timing from './Timing.js'; -export * as TraceEvents from './TraceEvents.js'; +export * as Events from './TraceEvents.js'; diff --git a/public/models/trace/types/types.js b/public/models/trace/types/types.js index 6d33dfbef..0c8a5b793 100644 --- a/public/models/trace/types/types.js +++ b/public/models/trace/types/types.js @@ -5,5 +5,5 @@ export * as Configuration from './Configuration.js'; export * as Extensions from './Extensions.js'; export * as File from './File.js'; export * as Timing from './Timing.js'; -export * as TraceEvents from './TraceEvents.js'; +export * as Events from './TraceEvents.js'; //# sourceMappingURL=types.js.map \ No newline at end of file diff --git a/public/models/trace/types/types.js.map b/public/models/trace/types/types.js.map index 477f6b531..70894a350 100644 --- a/public/models/trace/types/types.js.map +++ b/public/models/trace/types/types.js.map @@ -1 +1 @@ -{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/types/types.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,aAAa,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nexport * as Configuration from './Configuration.js';\nexport * as Extensions from './Extensions.js';\nexport * as File from './File.js';\nexport * as Timing from './Timing.js';\nexport * as TraceEvents from './TraceEvents.js';\n"]} \ No newline at end of file +{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../../../../front_end/models/trace/types/types.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,aAAa,MAAM,oBAAoB,CAAC;AACpD,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,MAAM,MAAM,kBAAkB,CAAC","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nexport * as Configuration from './Configuration.js';\nexport * as Extensions from './Extensions.js';\nexport * as File from './File.js';\nexport * as Timing from './Timing.js';\nexport * as Events from './TraceEvents.js';\n"]} \ No newline at end of file diff --git a/public/panels/application/ApplicationPanelSidebar.d.ts b/public/panels/application/ApplicationPanelSidebar.d.ts index ea5ae761b..7a042f0f0 100644 --- a/public/panels/application/ApplicationPanelSidebar.d.ts +++ b/public/panels/application/ApplicationPanelSidebar.d.ts @@ -7,6 +7,7 @@ import { ApplicationPanelTreeElement, ExpandableApplicationPanelTreeElement } fr import { BackgroundServiceModel } from './BackgroundServiceModel.js'; import { BounceTrackingMitigationsTreeElement } from './BounceTrackingMitigationsTreeElement.js'; import { type DOMStorage } from './DOMStorageModel.js'; +import { type ExtensionStorage } from './ExtensionStorageModel.js'; import { type Database as IndexedDBModelDatabase, type DatabaseId, type Index, IndexedDBModel, type ObjectStore } from './IndexedDBModel.js'; import { InterestGroupTreeElement } from './InterestGroupTreeElement.js'; import type * as PreloadingHelper from './preloading/helper/helper.js'; @@ -35,6 +36,7 @@ export declare class ApplicationPanelSidebar extends UI.Widget.VBox implements S serviceWorkersTreeElement: ServiceWorkersTreeElement; localStorageListTreeElement: ExpandableApplicationPanelTreeElement; sessionStorageListTreeElement: ExpandableApplicationPanelTreeElement; + extensionStorageListTreeElement: ExpandableApplicationPanelTreeElement | undefined; indexedDBListTreeElement: IndexedDBTreeElement; interestGroupTreeElement: InterestGroupTreeElement; cookieListTreeElement: ExpandableApplicationPanelTreeElement; @@ -54,6 +56,7 @@ export declare class ApplicationPanelSidebar extends UI.Widget.VBox implements S preloadingSummaryTreeElement: PreloadingSummaryTreeElement | undefined; private readonly resourcesSection; private domStorageTreeElements; + private extensionStorageTreeElements; private sharedStorageTreeElements; private domains; private target?; @@ -67,6 +70,8 @@ export declare class ApplicationPanelSidebar extends UI.Widget.VBox implements S private initialize; private domStorageModelAdded; private domStorageModelRemoved; + private extensionStorageModelAdded; + private extensionStorageModelRemoved; private indexedDBModelAdded; private indexedDBModelRemoved; private interestGroupModelAdded; @@ -85,6 +90,10 @@ export declare class ApplicationPanelSidebar extends UI.Widget.VBox implements S private addDOMStorage; private domStorageRemoved; private removeDOMStorage; + private extensionStorageAdded; + private addExtensionStorage; + private extensionStorageRemoved; + private removeExtensionStorage; private sharedStorageAdded; private addSharedStorage; private sharedStorageRemoved; @@ -222,6 +231,14 @@ export declare class DOMStorageTreeElement extends ApplicationPanelTreeElement { onattach(): void; private handleContextMenuEvent; } +export declare class ExtensionStorageTreeElement extends ApplicationPanelTreeElement { + private readonly extensionStorage; + constructor(storagePanel: ResourcesPanel, extensionStorage: ExtensionStorage); + get itemURL(): Platform.DevToolsPath.UrlString; + onselect(selectedByUser?: boolean): boolean; + onattach(): void; + private handleContextMenuEvent; +} export declare class CookieTreeElement extends ApplicationPanelTreeElement { private readonly target; private readonly cookieDomainInternal; diff --git a/public/panels/application/ApplicationPanelSidebar.js b/public/panels/application/ApplicationPanelSidebar.js index 348070936..1f17d70f4 100644 --- a/public/panels/application/ApplicationPanelSidebar.js +++ b/public/panels/application/ApplicationPanelSidebar.js @@ -34,6 +34,7 @@ import * as Common from '../../core/common/common.js'; import * as Host from '../../core/host/host.js'; import * as i18n from '../../core/i18n/i18n.js'; import * as Platform from '../../core/platform/platform.js'; +import * as Root from '../../core/root/root.js'; import * as SDK from '../../core/sdk/sdk.js'; import * as IssuesManager from '../../models/issues_manager/issues_manager.js'; import * as IconButton from '../../ui/components/icon_button/icon_button.js'; @@ -48,6 +49,7 @@ import { BackgroundServiceView } from './BackgroundServiceView.js'; import { BounceTrackingMitigationsTreeElement } from './BounceTrackingMitigationsTreeElement.js'; import * as ApplicationComponents from './components/components.js'; import { DOMStorageModel } from './DOMStorageModel.js'; +import { ExtensionStorageModel, } from './ExtensionStorageModel.js'; import { Events as IndexedDBModelEvents, IndexedDBModel, } from './IndexedDBModel.js'; import { IDBDatabaseView, IDBDataView } from './IndexedDBViews.js'; import { InterestGroupStorageModel } from './InterestGroupStorageModel.js'; @@ -81,6 +83,10 @@ const UIStrings = { *@description Text in Application Panel Sidebar of the Application panel */ sessionStorage: 'Session storage', + /** + *@description Text in Application Panel Sidebar of the Application panel + */ + extensionStorage: 'Extension storage', /** *@description Text for web cookies */ @@ -203,6 +209,7 @@ export class ApplicationPanelSidebar extends UI.Widget.VBox { serviceWorkersTreeElement; localStorageListTreeElement; sessionStorageListTreeElement; + extensionStorageListTreeElement; indexedDBListTreeElement; interestGroupTreeElement; cookieListTreeElement; @@ -222,6 +229,7 @@ export class ApplicationPanelSidebar extends UI.Widget.VBox { preloadingSummaryTreeElement; resourcesSection; domStorageTreeElements; + extensionStorageTreeElements; sharedStorageTreeElements; domains; // Holds main frame target. @@ -265,6 +273,14 @@ export class ApplicationPanelSidebar extends UI.Widget.VBox { const sessionStorageIcon = IconButton.Icon.create('table'); this.sessionStorageListTreeElement.setLeadingIcons([sessionStorageIcon]); storageTreeElement.appendChild(this.sessionStorageListTreeElement); + if (Root.Runtime.experiments.isEnabled("extension-storage-viewer" /* Root.Runtime.ExperimentName.EXTENSION_STORAGE_VIEWER */)) { + this.extensionStorageListTreeElement = + new ExpandableApplicationPanelTreeElement(panel, i18nString(UIStrings.extensionStorage), 'extension-storage'); + this.extensionStorageListTreeElement.setLink('https://developer.chrome.com/docs/extensions/reference/api/storage/?utm_source=devtools'); + const extensionStorageIcon = IconButton.Icon.create('table'); + this.extensionStorageListTreeElement.setLeadingIcons([extensionStorageIcon]); + storageTreeElement.appendChild(this.extensionStorageListTreeElement); + } this.indexedDBListTreeElement = new IndexedDBTreeElement(panel); this.indexedDBListTreeElement.setLink('https://developer.chrome.com/docs/devtools/storage/indexeddb/?utm_source=devtools'); storageTreeElement.appendChild(this.indexedDBListTreeElement); @@ -317,6 +333,7 @@ export class ApplicationPanelSidebar extends UI.Widget.VBox { const resourcesTreeElement = this.addSidebarSection(resourcesSectionTitle, 'frames'); this.resourcesSection = new ResourcesSection(panel, resourcesTreeElement); this.domStorageTreeElements = new Map(); + this.extensionStorageTreeElements = new Map(); this.sharedStorageTreeElements = new Map(); this.domains = {}; this.sidebarTree.contentElement.addEventListener('mousemove', this.onmousemove.bind(this), false); @@ -331,6 +348,12 @@ export class ApplicationPanelSidebar extends UI.Widget.VBox { modelAdded: (model) => this.domStorageModelAdded(model), modelRemoved: (model) => this.domStorageModelRemoved(model), }, { scoped: true }); + if (Root.Runtime.experiments.isEnabled("extension-storage-viewer" /* Root.Runtime.ExperimentName.EXTENSION_STORAGE_VIEWER */)) { + SDK.TargetManager.TargetManager.instance().observeModels(ExtensionStorageModel, { + modelAdded: (model) => this.extensionStorageModelAdded(model), + modelRemoved: (model) => this.extensionStorageModelRemoved(model), + }, { scoped: true }); + } SDK.TargetManager.TargetManager.instance().observeModels(IndexedDBModel, { modelAdded: (model) => this.indexedDBModelAdded(model), modelRemoved: (model) => this.indexedDBModelRemoved(model), @@ -436,6 +459,17 @@ export class ApplicationPanelSidebar extends UI.Widget.VBox { model.removeEventListener("DOMStorageAdded" /* DOMStorageModelEvents.DOM_STORAGE_ADDED */, this.domStorageAdded, this); model.removeEventListener("DOMStorageRemoved" /* DOMStorageModelEvents.DOM_STORAGE_REMOVED */, this.domStorageRemoved, this); } + extensionStorageModelAdded(model) { + model.enable(); + model.storages().forEach(this.addExtensionStorage.bind(this)); + model.addEventListener("ExtensionStorageAdded" /* ExtensionStorageModelEvents.EXTENSION_STORAGE_ADDED */, this.extensionStorageAdded, this); + model.addEventListener("ExtensionStorageRemoved" /* ExtensionStorageModelEvents.EXTENSION_STORAGE_REMOVED */, this.extensionStorageRemoved, this); + } + extensionStorageModelRemoved(model) { + model.storages().forEach(this.removeExtensionStorage.bind(this)); + model.removeEventListener("ExtensionStorageAdded" /* ExtensionStorageModelEvents.EXTENSION_STORAGE_ADDED */, this.extensionStorageAdded, this); + model.removeEventListener("ExtensionStorageRemoved" /* ExtensionStorageModelEvents.EXTENSION_STORAGE_REMOVED */, this.extensionStorageRemoved, this); + } indexedDBModelAdded(model) { model.enable(); this.indexedDBListTreeElement.addIndexedDBForModel(model); @@ -580,6 +614,41 @@ export class ApplicationPanelSidebar extends UI.Widget.VBox { } this.domStorageTreeElements.delete(domStorage); } + extensionStorageAdded(event) { + const extensionStorage = event.data; + this.addExtensionStorage(extensionStorage); + } + addExtensionStorage(extensionStorage) { + console.assert(Boolean(this.extensionStorageListTreeElement)); + console.assert(!this.extensionStorageTreeElements.get(extensionStorage)); + const extensionStorageTreeElement = new ExtensionStorageTreeElement(this.panel, extensionStorage); + this.extensionStorageTreeElements.set(extensionStorage, extensionStorageTreeElement); + this.extensionStorageListTreeElement?.appendChild(extensionStorageTreeElement, comparator); + function comparator(a, b) { + const aTitle = a.titleAsText().toLocaleLowerCase(); + const bTitle = b.titleAsText().toLocaleUpperCase(); + return aTitle.localeCompare(bTitle); + } + } + extensionStorageRemoved(event) { + const extensionStorage = event.data; + this.removeExtensionStorage(extensionStorage); + } + removeExtensionStorage(extensionStorage) { + const treeElement = this.extensionStorageTreeElements.get(extensionStorage); + if (!treeElement) { + return; + } + const wasSelected = treeElement.selected; + const parentListTreeElement = treeElement.parent; + if (parentListTreeElement) { + parentListTreeElement.removeChild(treeElement); + if (wasSelected) { + parentListTreeElement.select(); + } + } + this.extensionStorageTreeElements.delete(extensionStorage); + } async sharedStorageAdded(event) { await this.addSharedStorage(event.data); } @@ -1283,6 +1352,34 @@ export class DOMStorageTreeElement extends ApplicationPanelTreeElement { void contextMenu.show(); } } +export class ExtensionStorageTreeElement extends ApplicationPanelTreeElement { + extensionStorage; + constructor(storagePanel, extensionStorage) { + super(storagePanel, extensionStorage.name + ` (${extensionStorage.storageArea})`, false, 'extension-storage-for-domain'); + this.extensionStorage = extensionStorage; + const icon = IconButton.Icon.create('table'); + this.setLeadingIcons([icon]); + } + get itemURL() { + return 'storage://' + this.extensionStorage.extensionId + '/' + this.extensionStorage.storageArea; + } + onselect(selectedByUser) { + super.onselect(selectedByUser); + Host.userMetrics.panelShown('dom-storage'); + // TODO(crbug.com/40963428): Call this.resourcesPanel to show extension + // storage view + return false; + } + onattach() { + super.onattach(); + this.listItemElement.addEventListener('contextmenu', this.handleContextMenuEvent.bind(this), true); + } + handleContextMenuEvent(event) { + const contextMenu = new UI.ContextMenu.ContextMenu(event); + contextMenu.defaultSection().appendItem(i18nString(UIStrings.clear), () => this.extensionStorage.clear(), { jslogContext: 'clear' }); + void contextMenu.show(); + } +} export class CookieTreeElement extends ApplicationPanelTreeElement { target; cookieDomainInternal; diff --git a/public/panels/application/ApplicationPanelSidebar.js.map b/public/panels/application/ApplicationPanelSidebar.js.map index e0b1a5ea2..847e229cd 100644 --- a/public/panels/application/ApplicationPanelSidebar.js.map +++ b/public/panels/application/ApplicationPanelSidebar.js.map @@ -1 +1 @@ -{"version":3,"file":"ApplicationPanelSidebar.js","sourceRoot":"","sources":["../../../../../../front_end/panels/application/ApplicationPanelSidebar.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2021 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/*\n * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved.\n * Copyright (C) 2009 Joseph Pecoraro\n * Copyright (C) 2013 Samsung Electronics. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. Neither the name of Apple Computer, Inc. (\"Apple\") nor the names of\n * its contributors may be used to endorse or promote products derived\n * from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport * as Common from '../../core/common/common.js';\nimport * as Host from '../../core/host/host.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as Protocol from '../../generated/protocol.js';\nimport * as IssuesManager from '../../models/issues_manager/issues_manager.js';\nimport * as IconButton from '../../ui/components/icon_button/icon_button.js';\nimport * as LegacyWrapper from '../../ui/components/legacy_wrapper/legacy_wrapper.js';\nimport * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport {ApplicationPanelTreeElement, ExpandableApplicationPanelTreeElement} from './ApplicationPanelTreeElement.js';\nimport {AppManifestView, Events as AppManifestViewEvents} from './AppManifestView.js';\nimport {BackForwardCacheTreeElement} from './BackForwardCacheTreeElement.js';\nimport {BackgroundServiceModel} from './BackgroundServiceModel.js';\nimport {BackgroundServiceView} from './BackgroundServiceView.js';\nimport {BounceTrackingMitigationsTreeElement} from './BounceTrackingMitigationsTreeElement.js';\nimport * as ApplicationComponents from './components/components.js';\nimport {type DOMStorage, DOMStorageModel, Events as DOMStorageModelEvents} from './DOMStorageModel.js';\nimport {\n type Database as IndexedDBModelDatabase,\n type DatabaseId,\n Events as IndexedDBModelEvents,\n type Index,\n IndexedDBModel,\n type ObjectStore,\n} from './IndexedDBModel.js';\nimport {IDBDatabaseView, IDBDataView} from './IndexedDBViews.js';\nimport {Events as InterestGroupModelEvents, InterestGroupStorageModel} from './InterestGroupStorageModel.js';\nimport {InterestGroupTreeElement} from './InterestGroupTreeElement.js';\nimport {OpenedWindowDetailsView, WorkerDetailsView} from './OpenedWindowDetailsView.js';\nimport type * as PreloadingHelper from './preloading/helper/helper.js';\nimport {\n PreloadingSummaryTreeElement,\n} from './PreloadingTreeElement.js';\nimport {ReportingApiTreeElement} from './ReportingApiTreeElement.js';\nimport {type ResourcesPanel} from './ResourcesPanel.js';\nimport resourcesSidebarStyles from './resourcesSidebar.css.js';\nimport {ServiceWorkerCacheTreeElement} from './ServiceWorkerCacheTreeElement.js';\nimport {ServiceWorkersView} from './ServiceWorkersView.js';\nimport {SharedStorageListTreeElement} from './SharedStorageListTreeElement.js';\nimport {\n Events as SharedStorageModelEvents,\n type SharedStorageForOrigin,\n SharedStorageModel,\n} from './SharedStorageModel.js';\nimport {SharedStorageTreeElement} from './SharedStorageTreeElement.js';\nimport {StorageBucketsTreeParentElement} from './StorageBucketsTreeElement.js';\nimport {StorageView} from './StorageView.js';\nimport {TrustTokensTreeElement} from './TrustTokensTreeElement.js';\n\nconst UIStrings = {\n /**\n *@description Text in Application Panel Sidebar of the Application panel\n */\n application: 'Application',\n /**\n *@description Text in Application Panel Sidebar of the Application panel\n */\n storage: 'Storage',\n /**\n *@description Text in Application Panel Sidebar of the Application panel\n */\n localStorage: 'Local storage',\n /**\n *@description Text in Application Panel Sidebar of the Application panel\n */\n sessionStorage: 'Session storage',\n /**\n *@description Text for web cookies\n */\n cookies: 'Cookies',\n /**\n *@description Text in Application Panel Sidebar of the Application panel\n */\n backgroundServices: 'Background services',\n /**\n *@description Text for rendering frames\n */\n frames: 'Frames',\n /**\n *@description Text that appears on a button for the manifest resource type filter.\n */\n manifest: 'Manifest',\n /**\n *@description Text in App Manifest View of the Application panel\n */\n noManifestDetected: 'No manifest detected',\n /**\n *@description Text in App Manifest View of the Application panel\n */\n appManifest: 'App Manifest',\n /**\n *@description Text in Application Panel Sidebar of the Application panel\n */\n indexeddb: 'IndexedDB',\n /**\n *@description A context menu item in the Application Panel Sidebar of the Application panel\n */\n refreshIndexeddb: 'Refresh IndexedDB',\n /**\n *@description Tooltip in Application Panel Sidebar of the Application panel\n *@example {1.0} PH1\n */\n versionSEmpty: 'Version: {PH1} (empty)',\n /**\n *@description Tooltip in Application Panel Sidebar of the Application panel\n *@example {1.0} PH1\n */\n versionS: 'Version: {PH1}',\n /**\n *@description Text to clear content\n */\n clear: 'Clear',\n /**\n *@description Text in Application Panel Sidebar of the Application panel\n *@example {\"key path\"} PH1\n */\n keyPathS: 'Key path: {PH1}',\n /**\n *@description Text in Application Panel Sidebar of the Application panel\n */\n localFiles: 'Local Files',\n /**\n *@description Tooltip in Application Panel Sidebar of the Application panel\n *@example {https://example.com} PH1\n */\n cookiesUsedByFramesFromS: 'Cookies used by frames from {PH1}',\n /**\n *@description Text in Frames View of the Application panel\n */\n openedWindows: 'Opened Windows',\n /**\n *@description Label for plural of worker type: web workers\n */\n webWorkers: 'Web Workers',\n /**\n *@description Label in frame tree for unavailable document\n */\n documentNotAvailable: 'Document not available',\n /**\n *@description Description of content of unavailable document in Application panel\n */\n theContentOfThisDocumentHasBeen:\n 'The content of this document has been generated dynamically via \\'document.write()\\'.',\n /**\n *@description Text in Frames View of the Application panel\n */\n windowWithoutTitle: 'Window without title',\n /**\n *@description Default name for worker\n */\n worker: 'worker',\n /**\n * @description Aria text for screen reader to announce they can scroll to top of manifest if invoked\n */\n onInvokeManifestAlert: 'Manifest: Invoke to scroll to the top of manifest',\n /**\n * @description Aria text for screen reader to announce they can scroll to a section if invoked\n * @example {\"Identity\"} PH1\n */\n beforeInvokeAlert: '{PH1}: Invoke to scroll to this section in manifest',\n /**\n * @description Alert message for screen reader to announce which subsection is being scrolled to\n * @example {\"Identity\"} PH1\n */\n onInvokeAlert: 'Scrolled to {PH1}',\n /**\n * @description Application sidebar panel\n */\n applicationSidebarPanel: 'Application panel sidebar',\n /**\n *@description Tooltip in Application Panel Sidebar of the Application panel\n *@example {https://example.com} PH1\n */\n thirdPartyPhaseout: 'Cookies from {PH1} may have been blocked due to third-party cookie phaseout.',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/application/ApplicationPanelSidebar.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nfunction assertNotMainTarget(targetId: Protocol.Target.TargetID|'main'): asserts targetId is Protocol.Target.TargetID {\n if (targetId === 'main') {\n throw new Error('Unexpected main target id');\n }\n}\n\nexport namespace SharedStorageTreeElementDispatcher {\n export const enum Events {\n SHARED_STORAGE_TREE_ELEMENT_ADDED = 'SharedStorageTreeElementAdded',\n }\n\n export interface SharedStorageTreeElementAddedEvent {\n origin: string;\n }\n\n export type EventTypes = {\n [Events.SHARED_STORAGE_TREE_ELEMENT_ADDED]: SharedStorageTreeElementAddedEvent,\n };\n}\n\nexport class ApplicationPanelSidebar extends UI.Widget.VBox implements SDK.TargetManager.Observer {\n panel: ResourcesPanel;\n private readonly sidebarTree: UI.TreeOutline.TreeOutlineInShadow;\n private readonly applicationTreeElement: UI.TreeOutline.TreeElement;\n serviceWorkersTreeElement: ServiceWorkersTreeElement;\n localStorageListTreeElement: ExpandableApplicationPanelTreeElement;\n sessionStorageListTreeElement: ExpandableApplicationPanelTreeElement;\n indexedDBListTreeElement: IndexedDBTreeElement;\n interestGroupTreeElement: InterestGroupTreeElement;\n cookieListTreeElement: ExpandableApplicationPanelTreeElement;\n trustTokensTreeElement: TrustTokensTreeElement;\n cacheStorageListTreeElement: ServiceWorkerCacheTreeElement;\n sharedStorageListTreeElement: SharedStorageListTreeElement;\n storageBucketsTreeElement: StorageBucketsTreeParentElement|undefined;\n private backForwardCacheListTreeElement?: BackForwardCacheTreeElement;\n backgroundFetchTreeElement: BackgroundServiceTreeElement;\n backgroundSyncTreeElement: BackgroundServiceTreeElement;\n bounceTrackingMitigationsTreeElement: BounceTrackingMitigationsTreeElement;\n notificationsTreeElement: BackgroundServiceTreeElement;\n paymentHandlerTreeElement: BackgroundServiceTreeElement;\n periodicBackgroundSyncTreeElement: BackgroundServiceTreeElement;\n pushMessagingTreeElement: BackgroundServiceTreeElement;\n reportingApiTreeElement: ReportingApiTreeElement;\n preloadingSummaryTreeElement: PreloadingSummaryTreeElement|undefined;\n private readonly resourcesSection: ResourcesSection;\n private domStorageTreeElements: Map;\n private sharedStorageTreeElements: Map;\n private domains: {\n [x: string]: boolean,\n };\n // Holds main frame target.\n private target?: SDK.Target.Target;\n private previousHoveredElement?: FrameTreeElement;\n readonly sharedStorageTreeElementDispatcher:\n Common.ObjectWrapper.ObjectWrapper;\n\n constructor(panel: ResourcesPanel) {\n super();\n\n this.panel = panel;\n\n this.sidebarTree = new UI.TreeOutline.TreeOutlineInShadow(UI.TreeOutline.TreeVariant.NAVIGATION_TREE);\n this.sidebarTree.element.classList.add('resources-sidebar');\n this.sidebarTree.hideOverflow();\n\n this.sidebarTree.element.classList.add('filter-all');\n // Listener needs to have been set up before the elements are added\n this.sidebarTree.addEventListener(UI.TreeOutline.Events.ElementAttached, this.treeElementAdded, this);\n\n this.contentElement.appendChild(this.sidebarTree.element);\n\n const applicationSectionTitle = i18nString(UIStrings.application);\n this.applicationTreeElement = this.addSidebarSection(applicationSectionTitle, 'application');\n const applicationPanelSidebar = this.applicationTreeElement.treeOutline?.contentElement;\n if (applicationPanelSidebar) {\n applicationPanelSidebar.ariaLabel = i18nString(UIStrings.applicationSidebarPanel);\n }\n const manifestTreeElement = new AppManifestTreeElement(panel);\n this.applicationTreeElement.appendChild(manifestTreeElement);\n manifestTreeElement.generateChildren();\n this.serviceWorkersTreeElement = new ServiceWorkersTreeElement(panel);\n this.applicationTreeElement.appendChild(this.serviceWorkersTreeElement);\n const clearStorageTreeElement = new ClearStorageTreeElement(panel);\n this.applicationTreeElement.appendChild(clearStorageTreeElement);\n\n const storageSectionTitle = i18nString(UIStrings.storage);\n const storageTreeElement = this.addSidebarSection(storageSectionTitle, 'storage');\n this.localStorageListTreeElement =\n new ExpandableApplicationPanelTreeElement(panel, i18nString(UIStrings.localStorage), 'local-storage');\n this.localStorageListTreeElement.setLink(\n 'https://developer.chrome.com/docs/devtools/storage/localstorage/?utm_source=devtools' as\n Platform.DevToolsPath.UrlString);\n const localStorageIcon = IconButton.Icon.create('table');\n this.localStorageListTreeElement.setLeadingIcons([localStorageIcon]);\n\n storageTreeElement.appendChild(this.localStorageListTreeElement);\n this.sessionStorageListTreeElement =\n new ExpandableApplicationPanelTreeElement(panel, i18nString(UIStrings.sessionStorage), 'session-storage');\n this.sessionStorageListTreeElement.setLink(\n 'https://developer.chrome.com/docs/devtools/storage/sessionstorage/?utm_source=devtools' as\n Platform.DevToolsPath.UrlString);\n const sessionStorageIcon = IconButton.Icon.create('table');\n this.sessionStorageListTreeElement.setLeadingIcons([sessionStorageIcon]);\n\n storageTreeElement.appendChild(this.sessionStorageListTreeElement);\n this.indexedDBListTreeElement = new IndexedDBTreeElement(panel);\n this.indexedDBListTreeElement.setLink(\n 'https://developer.chrome.com/docs/devtools/storage/indexeddb/?utm_source=devtools' as\n Platform.DevToolsPath.UrlString);\n storageTreeElement.appendChild(this.indexedDBListTreeElement);\n\n this.cookieListTreeElement =\n new ExpandableApplicationPanelTreeElement(panel, i18nString(UIStrings.cookies), 'cookies');\n this.cookieListTreeElement.setLink(\n 'https://developer.chrome.com/docs/devtools/storage/cookies/?utm_source=devtools' as\n Platform.DevToolsPath.UrlString);\n const cookieIcon = IconButton.Icon.create('cookie');\n this.cookieListTreeElement.setLeadingIcons([cookieIcon]);\n storageTreeElement.appendChild(this.cookieListTreeElement);\n\n this.trustTokensTreeElement = new TrustTokensTreeElement(panel);\n storageTreeElement.appendChild(this.trustTokensTreeElement);\n\n this.interestGroupTreeElement = new InterestGroupTreeElement(panel);\n storageTreeElement.appendChild(this.interestGroupTreeElement);\n\n this.sharedStorageListTreeElement = new SharedStorageListTreeElement(panel);\n storageTreeElement.appendChild(this.sharedStorageListTreeElement);\n\n this.cacheStorageListTreeElement = new ServiceWorkerCacheTreeElement(panel);\n storageTreeElement.appendChild(this.cacheStorageListTreeElement);\n\n this.storageBucketsTreeElement = new StorageBucketsTreeParentElement(panel);\n storageTreeElement.appendChild(this.storageBucketsTreeElement);\n\n const backgroundServiceSectionTitle = i18nString(UIStrings.backgroundServices);\n const backgroundServiceTreeElement = this.addSidebarSection(backgroundServiceSectionTitle, 'background-services');\n\n this.backForwardCacheListTreeElement = new BackForwardCacheTreeElement(panel);\n backgroundServiceTreeElement.appendChild(this.backForwardCacheListTreeElement);\n this.backgroundFetchTreeElement =\n new BackgroundServiceTreeElement(panel, Protocol.BackgroundService.ServiceName.BackgroundFetch);\n backgroundServiceTreeElement.appendChild(this.backgroundFetchTreeElement);\n this.backgroundSyncTreeElement =\n new BackgroundServiceTreeElement(panel, Protocol.BackgroundService.ServiceName.BackgroundSync);\n backgroundServiceTreeElement.appendChild(this.backgroundSyncTreeElement);\n\n this.bounceTrackingMitigationsTreeElement = new BounceTrackingMitigationsTreeElement(panel);\n backgroundServiceTreeElement.appendChild(this.bounceTrackingMitigationsTreeElement);\n\n this.notificationsTreeElement =\n new BackgroundServiceTreeElement(panel, Protocol.BackgroundService.ServiceName.Notifications);\n backgroundServiceTreeElement.appendChild(this.notificationsTreeElement);\n this.paymentHandlerTreeElement =\n new BackgroundServiceTreeElement(panel, Protocol.BackgroundService.ServiceName.PaymentHandler);\n backgroundServiceTreeElement.appendChild(this.paymentHandlerTreeElement);\n this.periodicBackgroundSyncTreeElement =\n new BackgroundServiceTreeElement(panel, Protocol.BackgroundService.ServiceName.PeriodicBackgroundSync);\n backgroundServiceTreeElement.appendChild(this.periodicBackgroundSyncTreeElement);\n\n this.preloadingSummaryTreeElement = new PreloadingSummaryTreeElement(panel);\n backgroundServiceTreeElement.appendChild(this.preloadingSummaryTreeElement);\n this.preloadingSummaryTreeElement.constructChildren(panel);\n\n this.pushMessagingTreeElement =\n new BackgroundServiceTreeElement(panel, Protocol.BackgroundService.ServiceName.PushMessaging);\n backgroundServiceTreeElement.appendChild(this.pushMessagingTreeElement);\n this.reportingApiTreeElement = new ReportingApiTreeElement(panel);\n backgroundServiceTreeElement.appendChild(this.reportingApiTreeElement);\n\n const resourcesSectionTitle = i18nString(UIStrings.frames);\n const resourcesTreeElement = this.addSidebarSection(resourcesSectionTitle, 'frames');\n this.resourcesSection = new ResourcesSection(panel, resourcesTreeElement);\n\n this.domStorageTreeElements = new Map();\n this.sharedStorageTreeElements = new Map();\n this.domains = {};\n\n this.sidebarTree.contentElement.addEventListener('mousemove', this.onmousemove.bind(this), false);\n this.sidebarTree.contentElement.addEventListener('mouseleave', this.onmouseleave.bind(this), false);\n\n SDK.TargetManager.TargetManager.instance().observeTargets(this, {scoped: true});\n SDK.TargetManager.TargetManager.instance().addModelListener(\n SDK.ResourceTreeModel.ResourceTreeModel, SDK.ResourceTreeModel.Events.FrameNavigated, this.frameNavigated, this,\n {scoped: true});\n\n const selection = this.panel.lastSelectedItemPath();\n if (!selection.length) {\n manifestTreeElement.select();\n }\n\n SDK.TargetManager.TargetManager.instance().observeModels(\n DOMStorageModel, {\n modelAdded: (model: DOMStorageModel) => this.domStorageModelAdded(model),\n modelRemoved: (model: DOMStorageModel) => this.domStorageModelRemoved(model),\n },\n {scoped: true});\n SDK.TargetManager.TargetManager.instance().observeModels(\n IndexedDBModel, {\n modelAdded: (model: IndexedDBModel) => this.indexedDBModelAdded(model),\n modelRemoved: (model: IndexedDBModel) => this.indexedDBModelRemoved(model),\n },\n {scoped: true});\n SDK.TargetManager.TargetManager.instance().observeModels(\n InterestGroupStorageModel, {\n modelAdded: (model: InterestGroupStorageModel) => this.interestGroupModelAdded(model),\n modelRemoved: (model: InterestGroupStorageModel) => this.interestGroupModelRemoved(model),\n },\n {scoped: true});\n SDK.TargetManager.TargetManager.instance().observeModels(\n SharedStorageModel, {\n modelAdded: (model: SharedStorageModel) => this.sharedStorageModelAdded(model).catch(err => {\n console.error(err);\n }),\n modelRemoved: (model: SharedStorageModel) => this.sharedStorageModelRemoved(model),\n },\n {scoped: true});\n SDK.TargetManager.TargetManager.instance().observeModels(\n SDK.StorageBucketsModel.StorageBucketsModel, {\n modelAdded: (model: SDK.StorageBucketsModel.StorageBucketsModel) => this.storageBucketsModelAdded(model),\n modelRemoved: (model: SDK.StorageBucketsModel.StorageBucketsModel) => this.storageBucketsModelRemoved(model),\n },\n {scoped: true});\n\n this.sharedStorageTreeElementDispatcher =\n new Common.ObjectWrapper.ObjectWrapper();\n\n // Work-around for crbug.com/1152713: Something is wrong with custom scrollbars and size containment.\n // @ts-ignore\n this.contentElement.style.contain = 'layout style';\n }\n\n private addSidebarSection(title: string, jslogContext: string): UI.TreeOutline.TreeElement {\n const treeElement = new UI.TreeOutline.TreeElement(title, true, jslogContext);\n treeElement.listItemElement.classList.add('storage-group-list-item');\n treeElement.setCollapsible(false);\n treeElement.selectable = false;\n this.sidebarTree.appendChild(treeElement);\n UI.ARIAUtils.markAsHeading(treeElement.listItemElement, 3);\n UI.ARIAUtils.setLabel(treeElement.childrenListElement, title);\n return treeElement;\n }\n\n targetAdded(target: SDK.Target.Target): void {\n if (target !== target.outermostTarget()) {\n return;\n }\n\n this.target = target;\n\n const interestGroupModel = target.model(InterestGroupStorageModel);\n if (interestGroupModel) {\n interestGroupModel.addEventListener(\n InterestGroupModelEvents.INTEREST_GROUP_ACCESS, this.interestGroupAccess, this);\n }\n\n const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel);\n if (!resourceTreeModel) {\n return;\n }\n\n if (resourceTreeModel.cachedResourcesLoaded()) {\n this.initialize();\n }\n\n resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.CachedResourcesLoaded, this.initialize, this);\n resourceTreeModel.addEventListener(\n SDK.ResourceTreeModel.Events.WillLoadCachedResources, this.resetWithFrames, this);\n }\n\n targetRemoved(target: SDK.Target.Target): void {\n if (target !== this.target) {\n return;\n }\n delete this.target;\n\n const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel);\n if (resourceTreeModel) {\n resourceTreeModel.removeEventListener(SDK.ResourceTreeModel.Events.CachedResourcesLoaded, this.initialize, this);\n resourceTreeModel.removeEventListener(\n SDK.ResourceTreeModel.Events.WillLoadCachedResources, this.resetWithFrames, this);\n }\n\n const interestGroupModel = target.model(InterestGroupStorageModel);\n if (interestGroupModel) {\n interestGroupModel.removeEventListener(\n InterestGroupModelEvents.INTEREST_GROUP_ACCESS, this.interestGroupAccess, this);\n }\n\n this.resetWithFrames();\n }\n\n override focus(): void {\n this.sidebarTree.focus();\n }\n\n private initialize(): void {\n for (const frame of SDK.ResourceTreeModel.ResourceTreeModel.frames()) {\n this.addCookieDocument(frame);\n }\n const interestGroupModel = this.target && this.target.model(InterestGroupStorageModel);\n if (interestGroupModel) {\n interestGroupModel.enable();\n }\n\n this.cacheStorageListTreeElement.initialize();\n const backgroundServiceModel = this.target && this.target.model(BackgroundServiceModel) || null;\n this.backgroundFetchTreeElement && this.backgroundFetchTreeElement.initialize(backgroundServiceModel);\n this.backgroundSyncTreeElement && this.backgroundSyncTreeElement.initialize(backgroundServiceModel);\n this.notificationsTreeElement.initialize(backgroundServiceModel);\n this.paymentHandlerTreeElement.initialize(backgroundServiceModel);\n this.periodicBackgroundSyncTreeElement.initialize(backgroundServiceModel);\n this.pushMessagingTreeElement.initialize(backgroundServiceModel);\n this.storageBucketsTreeElement?.initialize();\n\n const preloadingModel = this.target?.model(SDK.PreloadingModel.PreloadingModel);\n if (preloadingModel) {\n this.preloadingSummaryTreeElement?.initialize(preloadingModel);\n }\n }\n\n private domStorageModelAdded(model: DOMStorageModel): void {\n model.enable();\n model.storages().forEach(this.addDOMStorage.bind(this));\n model.addEventListener(DOMStorageModelEvents.DOM_STORAGE_ADDED, this.domStorageAdded, this);\n model.addEventListener(DOMStorageModelEvents.DOM_STORAGE_REMOVED, this.domStorageRemoved, this);\n }\n\n private domStorageModelRemoved(model: DOMStorageModel): void {\n model.storages().forEach(this.removeDOMStorage.bind(this));\n model.removeEventListener(DOMStorageModelEvents.DOM_STORAGE_ADDED, this.domStorageAdded, this);\n model.removeEventListener(DOMStorageModelEvents.DOM_STORAGE_REMOVED, this.domStorageRemoved, this);\n }\n\n private indexedDBModelAdded(model: IndexedDBModel): void {\n model.enable();\n this.indexedDBListTreeElement.addIndexedDBForModel(model);\n }\n\n private indexedDBModelRemoved(model: IndexedDBModel): void {\n this.indexedDBListTreeElement.removeIndexedDBForModel(model);\n }\n\n private interestGroupModelAdded(model: InterestGroupStorageModel): void {\n model.enable();\n model.addEventListener(InterestGroupModelEvents.INTEREST_GROUP_ACCESS, this.interestGroupAccess, this);\n }\n\n private interestGroupModelRemoved(model: InterestGroupStorageModel): void {\n model.disable();\n model.removeEventListener(InterestGroupModelEvents.INTEREST_GROUP_ACCESS, this.interestGroupAccess, this);\n }\n\n private async sharedStorageModelAdded(model: SharedStorageModel): Promise {\n await model.enable();\n for (const storage of model.storages()) {\n await this.addSharedStorage(storage);\n }\n model.addEventListener(SharedStorageModelEvents.SHARED_STORAGE_ADDED, this.sharedStorageAdded, this);\n model.addEventListener(SharedStorageModelEvents.SHARED_STORAGE_REMOVED, this.sharedStorageRemoved, this);\n model.addEventListener(SharedStorageModelEvents.SHARED_STORAGE_ACCESS, this.sharedStorageAccess, this);\n }\n\n private sharedStorageModelRemoved(model: SharedStorageModel): void {\n model.disable();\n for (const storage of model.storages()) {\n this.removeSharedStorage(storage);\n }\n model.removeEventListener(SharedStorageModelEvents.SHARED_STORAGE_ADDED, this.sharedStorageAdded, this);\n model.removeEventListener(SharedStorageModelEvents.SHARED_STORAGE_REMOVED, this.sharedStorageRemoved, this);\n model.removeEventListener(SharedStorageModelEvents.SHARED_STORAGE_ACCESS, this.sharedStorageAccess, this);\n }\n\n private storageBucketsModelAdded(model: SDK.StorageBucketsModel.StorageBucketsModel): void {\n model.enable();\n }\n\n private storageBucketsModelRemoved(model: SDK.StorageBucketsModel.StorageBucketsModel): void {\n this.storageBucketsTreeElement?.removeBucketsForModel(model);\n }\n\n private resetWithFrames(): void {\n this.resourcesSection.reset();\n this.reset();\n }\n\n private treeElementAdded(event: Common.EventTarget.EventTargetEvent): void {\n // On tree item selection its itemURL and those of its parents are persisted.\n // On reload/navigation we check for matches starting from the root on the\n // path to the current element. Matching nodes are expanded until we hit a\n // mismatch. This way we ensure that the longest matching path starting from\n // the root is expanded, even if we cannot match the whole path.\n const selection = this.panel.lastSelectedItemPath();\n if (!selection.length) {\n return;\n }\n const element = event.data;\n const elementPath = [element as UI.TreeOutline.TreeElement | ApplicationPanelTreeElement];\n for (let parent = element.parent as UI.TreeOutline.TreeElement | ApplicationPanelTreeElement | null;\n parent && 'itemURL' in parent && parent.itemURL; parent = parent.parent) {\n elementPath.push(parent as ApplicationPanelTreeElement);\n }\n\n let i = selection.length - 1;\n let j = elementPath.length - 1;\n while (i >= 0 && j >= 0 && selection[i] === (elementPath[j] as ApplicationPanelTreeElement).itemURL) {\n if (!elementPath[j].expanded) {\n if (i > 0) {\n elementPath[j].expand();\n }\n if (!elementPath[j].selected) {\n elementPath[j].select();\n }\n }\n i--;\n j--;\n }\n }\n\n private reset(): void {\n this.domains = {};\n this.cookieListTreeElement.removeChildren();\n this.interestGroupTreeElement.clearEvents();\n }\n\n private frameNavigated(event: Common.EventTarget.EventTargetEvent): void {\n const frame = event.data;\n\n if (frame.isOutermostFrame()) {\n this.reset();\n }\n this.addCookieDocument(frame);\n }\n\n private interestGroupAccess(event: Common.EventTarget.EventTargetEvent):\n void {\n this.interestGroupTreeElement.addEvent(event.data);\n }\n\n private addCookieDocument(frame: SDK.ResourceTreeModel.ResourceTreeFrame): void {\n // In case the current frame was unreachable, show its cookies\n // instead of the error interstitials because they might help to\n // debug why the frame was unreachable.\n const urlToParse = frame.unreachableUrl() || frame.url;\n const parsedURL = Common.ParsedURL.ParsedURL.fromString(urlToParse);\n if (!parsedURL || (parsedURL.scheme !== 'http' && parsedURL.scheme !== 'https' && parsedURL.scheme !== 'file')) {\n return;\n }\n\n const domain = parsedURL.securityOrigin();\n if (!this.domains[domain]) {\n this.domains[domain] = true;\n const cookieDomainTreeElement = new CookieTreeElement(this.panel, frame, parsedURL);\n this.cookieListTreeElement.appendChild(cookieDomainTreeElement);\n }\n }\n\n private domStorageAdded(event: Common.EventTarget.EventTargetEvent): void {\n const domStorage = (event.data as DOMStorage);\n this.addDOMStorage(domStorage);\n }\n\n private addDOMStorage(domStorage: DOMStorage): void {\n console.assert(!this.domStorageTreeElements.get(domStorage));\n console.assert(Boolean(domStorage.storageKey));\n\n const domStorageTreeElement = new DOMStorageTreeElement(this.panel, domStorage);\n this.domStorageTreeElements.set(domStorage, domStorageTreeElement);\n if (domStorage.isLocalStorage) {\n this.localStorageListTreeElement.appendChild(domStorageTreeElement, comparator);\n } else {\n this.sessionStorageListTreeElement.appendChild(domStorageTreeElement, comparator);\n }\n\n function comparator(a: UI.TreeOutline.TreeElement, b: UI.TreeOutline.TreeElement): number {\n const aTitle = a.titleAsText().toLocaleLowerCase();\n const bTitle = b.titleAsText().toLocaleUpperCase();\n return aTitle.localeCompare(bTitle);\n }\n }\n\n private domStorageRemoved(event: Common.EventTarget.EventTargetEvent): void {\n const domStorage = (event.data as DOMStorage);\n this.removeDOMStorage(domStorage);\n }\n\n private removeDOMStorage(domStorage: DOMStorage): void {\n const treeElement = this.domStorageTreeElements.get(domStorage);\n if (!treeElement) {\n return;\n }\n const wasSelected = treeElement.selected;\n const parentListTreeElement = treeElement.parent;\n if (parentListTreeElement) {\n parentListTreeElement.removeChild(treeElement);\n if (wasSelected) {\n parentListTreeElement.select();\n }\n }\n this.domStorageTreeElements.delete(domStorage);\n }\n\n private async sharedStorageAdded(event: Common.EventTarget.EventTargetEvent): Promise {\n await this.addSharedStorage(event.data);\n }\n\n private async addSharedStorage(sharedStorage: SharedStorageForOrigin): Promise {\n const sharedStorageTreeElement = await SharedStorageTreeElement.createElement(this.panel, sharedStorage);\n\n // A tree element for `sharedStorage.securityOrigin` may have been added while we were waiting for `sharedStorageTreeElement` to be created.\n if (this.sharedStorageTreeElements.has(sharedStorage.securityOrigin)) {\n return;\n }\n this.sharedStorageTreeElements.set(sharedStorage.securityOrigin, sharedStorageTreeElement);\n this.sharedStorageListTreeElement.appendChild(sharedStorageTreeElement);\n this.sharedStorageTreeElementDispatcher.dispatchEventToListeners(\n SharedStorageTreeElementDispatcher.Events.SHARED_STORAGE_TREE_ELEMENT_ADDED,\n {origin: sharedStorage.securityOrigin});\n }\n\n private sharedStorageRemoved(event: Common.EventTarget.EventTargetEvent): void {\n this.removeSharedStorage(event.data);\n }\n\n private removeSharedStorage(sharedStorage: SharedStorageForOrigin): void {\n const treeElement = this.sharedStorageTreeElements.get(sharedStorage.securityOrigin);\n if (!treeElement) {\n return;\n }\n const wasSelected = treeElement.selected;\n const parentListTreeElement = treeElement.parent;\n if (parentListTreeElement) {\n parentListTreeElement.removeChild(treeElement);\n parentListTreeElement.setExpandable(parentListTreeElement.childCount() > 0);\n if (wasSelected) {\n parentListTreeElement.select();\n }\n }\n this.sharedStorageTreeElements.delete(sharedStorage.securityOrigin);\n }\n\n private sharedStorageAccess(event: Common.EventTarget.EventTargetEvent):\n void {\n this.sharedStorageListTreeElement.addEvent(event.data);\n }\n\n async showResource(resource: SDK.Resource.Resource, line?: number, column?: number): Promise {\n await this.resourcesSection.revealResource(resource, line, column);\n }\n\n showFrame(frame: SDK.ResourceTreeModel.ResourceTreeFrame): void {\n this.resourcesSection.revealAndSelectFrame(frame);\n }\n\n showFileSystem(view: UI.Widget.Widget): void {\n this.innerShowView(view);\n }\n\n private innerShowView(view: UI.Widget.Widget): void {\n this.panel.showView(view);\n }\n\n showPreloadingRuleSetView(revealInfo: PreloadingHelper.PreloadingForward.RuleSetView): void {\n if (this.preloadingSummaryTreeElement) {\n this.preloadingSummaryTreeElement.expandAndRevealRuleSet(revealInfo);\n }\n }\n\n showPreloadingAttemptViewWithFilter(filter: PreloadingHelper.PreloadingForward.AttemptViewWithFilter): void {\n if (this.preloadingSummaryTreeElement) {\n this.preloadingSummaryTreeElement.expandAndRevealAttempts(filter);\n }\n }\n\n private onmousemove(event: MouseEvent): void {\n const nodeUnderMouse = (event.target as Node);\n if (!nodeUnderMouse) {\n return;\n }\n\n const listNode = UI.UIUtils.enclosingNodeOrSelfWithNodeName(nodeUnderMouse, 'li');\n if (!listNode) {\n return;\n }\n\n const element = UI.TreeOutline.TreeElement.getTreeElementBylistItemNode(listNode);\n if (this.previousHoveredElement === element) {\n return;\n }\n\n if (this.previousHoveredElement) {\n this.previousHoveredElement.hovered = false;\n delete this.previousHoveredElement;\n }\n\n if (element instanceof FrameTreeElement) {\n this.previousHoveredElement = element;\n element.hovered = true;\n }\n }\n\n private onmouseleave(_event: MouseEvent): void {\n if (this.previousHoveredElement) {\n this.previousHoveredElement.hovered = false;\n delete this.previousHoveredElement;\n }\n }\n override wasShown(): void {\n super.wasShown();\n this.sidebarTree.registerCSSFiles([resourcesSidebarStyles]);\n }\n}\n\nexport class BackgroundServiceTreeElement extends ApplicationPanelTreeElement {\n private serviceName: Protocol.BackgroundService.ServiceName;\n private view: BackgroundServiceView|null;\n private model: BackgroundServiceModel|null;\n private selectedInternal: boolean;\n\n constructor(storagePanel: ResourcesPanel, serviceName: Protocol.BackgroundService.ServiceName) {\n super(\n storagePanel, BackgroundServiceView.getUIString(serviceName), false,\n Platform.StringUtilities.toKebabCase(serviceName));\n\n this.serviceName = serviceName;\n\n /* Whether the element has been selected. */\n this.selectedInternal = false;\n\n this.view = null;\n\n this.model = null;\n\n const backgroundServiceIcon = IconButton.Icon.create(this.getIconType());\n this.setLeadingIcons([backgroundServiceIcon]);\n }\n\n private getIconType(): string {\n switch (this.serviceName) {\n case Protocol.BackgroundService.ServiceName.BackgroundFetch:\n return 'arrow-up-down';\n case Protocol.BackgroundService.ServiceName.BackgroundSync:\n return 'sync';\n case Protocol.BackgroundService.ServiceName.PushMessaging:\n return 'cloud';\n case Protocol.BackgroundService.ServiceName.Notifications:\n return 'bell';\n case Protocol.BackgroundService.ServiceName.PaymentHandler:\n return 'credit-card';\n case Protocol.BackgroundService.ServiceName.PeriodicBackgroundSync:\n return 'watch';\n default:\n console.error(`Service ${this.serviceName} does not have a dedicated icon`);\n return 'table';\n }\n }\n\n initialize(model: BackgroundServiceModel|null): void {\n this.model = model;\n // Show the view if the model was initialized after selection.\n if (this.selectedInternal && !this.view) {\n this.onselect(false);\n }\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return `background-service://${this.serviceName}` as Platform.DevToolsPath.UrlString;\n }\n\n override get selectable(): boolean {\n if (!this.model) {\n return false;\n }\n return super.selectable;\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n this.selectedInternal = true;\n\n if (!this.model) {\n return false;\n }\n\n if (!this.view) {\n this.view = new BackgroundServiceView(this.serviceName, this.model);\n }\n this.showView(this.view);\n UI.Context.Context.instance().setFlavor(BackgroundServiceView, this.view);\n Host.userMetrics.panelShown('background_service_' + this.serviceName);\n return false;\n }\n}\n\nexport class ServiceWorkersTreeElement extends ApplicationPanelTreeElement {\n private view?: ServiceWorkersView;\n\n constructor(storagePanel: ResourcesPanel) {\n super(storagePanel, i18n.i18n.lockedString('Service workers'), false, 'service-workers');\n const icon = IconButton.Icon.create('gears');\n this.setLeadingIcons([icon]);\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return 'service-workers://' as Platform.DevToolsPath.UrlString;\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n if (!this.view) {\n this.view = new ServiceWorkersView();\n }\n this.showView(this.view);\n Host.userMetrics.panelShown('service-workers');\n return false;\n }\n}\n\nexport class AppManifestTreeElement extends ApplicationPanelTreeElement {\n private view: AppManifestView;\n constructor(storagePanel: ResourcesPanel) {\n super(storagePanel, i18nString(UIStrings.manifest), true, 'manifest');\n const icon = IconButton.Icon.create('document');\n this.setLeadingIcons([icon]);\n self.onInvokeElement(this.listItemElement, this.onInvoke.bind(this));\n const emptyView = new UI.EmptyWidget.EmptyWidget(i18nString(UIStrings.noManifestDetected));\n // TODO(crbug.com/1156978): Replace UI.ReportView.ReportView with ReportView.ts web component.\n const reportView = new UI.ReportView.ReportView(i18nString(UIStrings.appManifest));\n this.view = new AppManifestView(emptyView, reportView, new Common.Throttler.Throttler(1000));\n UI.ARIAUtils.setLabel(this.listItemElement, i18nString(UIStrings.onInvokeManifestAlert));\n const handleExpansion = (hasManifest: boolean): void => {\n this.setExpandable(hasManifest);\n };\n this.view.addEventListener(AppManifestViewEvents.MANIFEST_DETECTED, event => handleExpansion(event.data));\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return 'manifest://' as Platform.DevToolsPath.UrlString;\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n this.showView(this.view);\n Host.userMetrics.panelShown('app-manifest');\n return false;\n }\n\n generateChildren(): void {\n const staticSections = this.view.getStaticSections();\n for (const section of staticSections) {\n const sectionElement = section.getTitleElement();\n const childTitle = section.title();\n const sectionFieldElement = section.getFieldElement();\n const child = new ManifestChildTreeElement(\n this.resourcesPanel, sectionElement, childTitle, sectionFieldElement, section.jslogContext || '');\n this.appendChild(child);\n }\n }\n\n onInvoke(): void {\n this.view.getManifestElement().scrollIntoView();\n UI.ARIAUtils.alert(i18nString(UIStrings.onInvokeAlert, {PH1: this.listItemElement.title}));\n }\n\n showManifestView(): void {\n this.showView(this.view);\n }\n}\n\nexport class ManifestChildTreeElement extends ApplicationPanelTreeElement {\n #sectionElement: Element;\n #sectionFieldElement: HTMLElement;\n constructor(\n storagePanel: ResourcesPanel, element: Element, childTitle: string, fieldElement: HTMLElement,\n jslogContext: string) {\n super(storagePanel, childTitle, false, jslogContext);\n const icon = IconButton.Icon.create('document');\n this.setLeadingIcons([icon]);\n this.#sectionElement = element;\n this.#sectionFieldElement = fieldElement;\n self.onInvokeElement(this.listItemElement, this.onInvoke.bind(this));\n this.listItemElement.addEventListener('keydown', this.onInvokeElementKeydown.bind(this));\n UI.ARIAUtils.setLabel(\n this.listItemElement, i18nString(UIStrings.beforeInvokeAlert, {PH1: this.listItemElement.title}));\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return 'manifest://' + this.title as Platform.DevToolsPath.UrlString;\n }\n\n onInvoke(): void {\n (this.parent as AppManifestTreeElement)?.showManifestView();\n this.#sectionElement.scrollIntoView();\n UI.ARIAUtils.alert(i18nString(UIStrings.onInvokeAlert, {PH1: this.listItemElement.title}));\n Host.userMetrics.manifestSectionSelected(this.listItemElement.title);\n }\n // direct focus to the corresponding element\n onInvokeElementKeydown(event: KeyboardEvent): void {\n if (event.key !== 'Tab' || event.shiftKey) {\n return;\n }\n const checkBoxElement = this.#sectionFieldElement.querySelector('.mask-checkbox');\n let focusableElement: HTMLElement|null = this.#sectionFieldElement.querySelector('[tabindex=\"0\"]');\n if (checkBoxElement && checkBoxElement.shadowRoot) {\n focusableElement = checkBoxElement.shadowRoot.querySelector('input') || null;\n } else if (!focusableElement) {\n // special case for protocol handler section since it is a custom Element and has different structure than the others\n focusableElement = this.#sectionFieldElement.querySelector('devtools-protocol-handlers-view')\n ?.shadowRoot?.querySelector('[tabindex=\"0\"]') ||\n null;\n }\n if (focusableElement) {\n focusableElement?.focus();\n event.consume(true);\n }\n }\n}\n\nexport class ClearStorageTreeElement extends ApplicationPanelTreeElement {\n private view?: StorageView;\n constructor(storagePanel: ResourcesPanel) {\n super(storagePanel, i18nString(UIStrings.storage), false, 'storage');\n const icon = IconButton.Icon.create('database');\n this.setLeadingIcons([icon]);\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return 'clear-storage://' as Platform.DevToolsPath.UrlString;\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n if (!this.view) {\n this.view = new StorageView();\n }\n this.showView(this.view);\n Host.userMetrics.panelShown(Host.UserMetrics.PanelCodes[Host.UserMetrics.PanelCodes.storage]);\n return false;\n }\n}\n\nexport class IndexedDBTreeElement extends ExpandableApplicationPanelTreeElement {\n private idbDatabaseTreeElements: IDBDatabaseTreeElement[];\n private storageBucket?: Protocol.Storage.StorageBucket;\n constructor(storagePanel: ResourcesPanel, storageBucket?: Protocol.Storage.StorageBucket) {\n super(storagePanel, i18nString(UIStrings.indexeddb), 'indexed-db');\n const icon = IconButton.Icon.create('database');\n this.setLeadingIcons([icon]);\n this.idbDatabaseTreeElements = [];\n this.storageBucket = storageBucket;\n this.initialize();\n }\n\n private initialize(): void {\n SDK.TargetManager.TargetManager.instance().addModelListener(\n IndexedDBModel, IndexedDBModelEvents.DatabaseAdded, this.indexedDBAdded, this, {scoped: true});\n SDK.TargetManager.TargetManager.instance().addModelListener(\n IndexedDBModel, IndexedDBModelEvents.DatabaseRemoved, this.indexedDBRemoved, this, {scoped: true});\n SDK.TargetManager.TargetManager.instance().addModelListener(\n IndexedDBModel, IndexedDBModelEvents.DatabaseLoaded, this.indexedDBLoaded, this, {scoped: true});\n SDK.TargetManager.TargetManager.instance().addModelListener(\n IndexedDBModel, IndexedDBModelEvents.IndexedDBContentUpdated, this.indexedDBContentUpdated, this,\n {scoped: true});\n // TODO(szuend): Replace with a Set once two web tests no longer directly access this private\n // variable (indexeddb/live-update-indexeddb-content.js, indexeddb/delete-entry.js).\n this.idbDatabaseTreeElements = [];\n\n for (const indexedDBModel of SDK.TargetManager.TargetManager.instance().models(IndexedDBModel, {scoped: true})) {\n const databases = indexedDBModel.databases();\n for (let j = 0; j < databases.length; ++j) {\n this.addIndexedDB(indexedDBModel, databases[j]);\n }\n }\n }\n\n addIndexedDBForModel(model: IndexedDBModel): void {\n for (const databaseId of model.databases()) {\n this.addIndexedDB(model, databaseId);\n }\n }\n\n removeIndexedDBForModel(model: IndexedDBModel): void {\n const idbDatabaseTreeElements = this.idbDatabaseTreeElements.filter(element => element.model === model);\n for (const idbDatabaseTreeElement of idbDatabaseTreeElements) {\n this.removeIDBDatabaseTreeElement(idbDatabaseTreeElement);\n }\n }\n\n override onattach(): void {\n super.onattach();\n this.listItemElement.addEventListener('contextmenu', this.handleContextMenuEvent.bind(this), true);\n }\n\n private handleContextMenuEvent(event: MouseEvent): void {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.refreshIndexeddb), this.refreshIndexedDB.bind(this), {jslogContext: 'refresh-indexeddb'});\n void contextMenu.show();\n }\n\n refreshIndexedDB(): void {\n for (const indexedDBModel of SDK.TargetManager.TargetManager.instance().models(IndexedDBModel, {scoped: true})) {\n void indexedDBModel.refreshDatabaseNames();\n }\n }\n\n private databaseInTree(databaseId: DatabaseId): boolean {\n if (this.storageBucket) {\n return databaseId.inBucket(this.storageBucket);\n }\n return true;\n }\n\n private indexedDBAdded({\n data: {databaseId, model},\n }: Common.EventTarget.EventTargetEvent<{databaseId: DatabaseId, model: IndexedDBModel}>): void {\n this.addIndexedDB(model, databaseId);\n }\n\n private addIndexedDB(model: IndexedDBModel, databaseId: DatabaseId): void {\n if (!this.databaseInTree(databaseId)) {\n return;\n }\n const idbDatabaseTreeElement = new IDBDatabaseTreeElement(this.resourcesPanel, model, databaseId);\n this.idbDatabaseTreeElements.push(idbDatabaseTreeElement);\n this.appendChild(idbDatabaseTreeElement);\n model.refreshDatabase(databaseId);\n }\n\n private indexedDBRemoved({\n data: {databaseId, model},\n }: Common.EventTarget.EventTargetEvent<{databaseId: DatabaseId, model: IndexedDBModel}>): void {\n const idbDatabaseTreeElement = this.idbDatabaseTreeElement(model, databaseId);\n if (!idbDatabaseTreeElement) {\n return;\n }\n this.removeIDBDatabaseTreeElement(idbDatabaseTreeElement);\n }\n\n private removeIDBDatabaseTreeElement(idbDatabaseTreeElement: IDBDatabaseTreeElement): void {\n idbDatabaseTreeElement.clear();\n this.removeChild(idbDatabaseTreeElement);\n Platform.ArrayUtilities.removeElement(this.idbDatabaseTreeElements, idbDatabaseTreeElement);\n this.setExpandable(this.childCount() > 0);\n }\n\n private indexedDBLoaded(\n {data: {database, model, entriesUpdated}}: Common.EventTarget\n .EventTargetEvent<{database: IndexedDBModelDatabase, model: IndexedDBModel, entriesUpdated: boolean}>): void {\n const idbDatabaseTreeElement = this.idbDatabaseTreeElement(model, database.databaseId);\n if (!idbDatabaseTreeElement) {\n return;\n }\n idbDatabaseTreeElement.update(database, entriesUpdated);\n this.indexedDBLoadedForTest();\n }\n\n private indexedDBLoadedForTest(): void {\n // For sniffing in tests.\n }\n\n private indexedDBContentUpdated({\n data: {databaseId, objectStoreName, model},\n }: Common.EventTarget.EventTargetEvent<{databaseId: DatabaseId, objectStoreName: string, model: IndexedDBModel}>):\n void {\n const idbDatabaseTreeElement = this.idbDatabaseTreeElement(model, databaseId);\n if (!idbDatabaseTreeElement) {\n return;\n }\n idbDatabaseTreeElement.indexedDBContentUpdated(objectStoreName);\n }\n\n private idbDatabaseTreeElement(model: IndexedDBModel, databaseId: DatabaseId): IDBDatabaseTreeElement|null {\n return this.idbDatabaseTreeElements.find(x => x.databaseId.equals(databaseId) && x.model === model) || null;\n }\n}\n\nexport class IDBDatabaseTreeElement extends ApplicationPanelTreeElement {\n model: IndexedDBModel;\n databaseId: DatabaseId;\n private readonly idbObjectStoreTreeElements: Map;\n private database?: IndexedDBModelDatabase;\n private view?: LegacyWrapper.LegacyWrapper.LegacyWrapper;\n\n constructor(storagePanel: ResourcesPanel, model: IndexedDBModel, databaseId: DatabaseId) {\n super(storagePanel, databaseId.name, false, 'indexed-db-database');\n this.model = model;\n this.databaseId = databaseId;\n this.idbObjectStoreTreeElements = new Map();\n const icon = IconButton.Icon.create('database');\n this.setLeadingIcons([icon]);\n this.model.addEventListener(IndexedDBModelEvents.DatabaseNamesRefreshed, this.refreshIndexedDB, this);\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return 'indexedDB://' + this.databaseId.storageBucket.storageKey + '/' +\n (this.databaseId.storageBucket.name ?? '') + '/' + this.databaseId.name as Platform.DevToolsPath.UrlString;\n }\n\n override onattach(): void {\n super.onattach();\n this.listItemElement.addEventListener('contextmenu', this.handleContextMenuEvent.bind(this), true);\n }\n\n private handleContextMenuEvent(event: MouseEvent): void {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.refreshIndexeddb), this.refreshIndexedDB.bind(this), {jslogContext: 'refresh-indexeddb'});\n void contextMenu.show();\n }\n\n private refreshIndexedDB(): void {\n this.model.refreshDatabase(this.databaseId);\n }\n\n indexedDBContentUpdated(objectStoreName: string): void {\n const treeElement = this.idbObjectStoreTreeElements.get(objectStoreName);\n if (treeElement) {\n treeElement.markNeedsRefresh();\n }\n }\n\n update(database: IndexedDBModelDatabase, entriesUpdated: boolean): void {\n this.database = database;\n const objectStoreNames = new Set();\n for (const objectStoreName of [...this.database.objectStores.keys()].sort()) {\n const objectStore = this.database.objectStores.get(objectStoreName);\n if (!objectStore) {\n continue;\n }\n objectStoreNames.add(objectStore.name);\n let treeElement = this.idbObjectStoreTreeElements.get(objectStore.name);\n if (!treeElement) {\n treeElement = new IDBObjectStoreTreeElement(this.resourcesPanel, this.model, this.databaseId, objectStore);\n this.idbObjectStoreTreeElements.set(objectStore.name, treeElement);\n this.appendChild(treeElement);\n }\n treeElement.update(objectStore, entriesUpdated);\n }\n for (const objectStoreName of this.idbObjectStoreTreeElements.keys()) {\n if (!objectStoreNames.has(objectStoreName)) {\n this.objectStoreRemoved(objectStoreName);\n }\n }\n\n if (this.view) {\n this.view.getComponent().update(database);\n }\n\n this.updateTooltip();\n }\n\n private updateTooltip(): void {\n const version = this.database ? this.database.version : '-';\n if (Object.keys(this.idbObjectStoreTreeElements).length === 0) {\n this.tooltip = i18nString(UIStrings.versionSEmpty, {PH1: version});\n } else {\n this.tooltip = i18nString(UIStrings.versionS, {PH1: version});\n }\n }\n\n override get selectable(): boolean {\n if (!this.database) {\n return false;\n }\n return super.selectable;\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n if (!this.database) {\n return false;\n }\n if (!this.view) {\n this.view = LegacyWrapper.LegacyWrapper.legacyWrapper(\n UI.Widget.VBox, new IDBDatabaseView(this.model, this.database), 'indexeddb-data');\n }\n\n this.showView(this.view);\n Host.userMetrics.panelShown('indexed-db');\n return false;\n }\n\n private objectStoreRemoved(objectStoreName: string): void {\n const objectStoreTreeElement = this.idbObjectStoreTreeElements.get(objectStoreName);\n if (objectStoreTreeElement) {\n objectStoreTreeElement.clear();\n this.removeChild(objectStoreTreeElement);\n }\n this.idbObjectStoreTreeElements.delete(objectStoreName);\n this.updateTooltip();\n }\n\n clear(): void {\n for (const objectStoreName of this.idbObjectStoreTreeElements.keys()) {\n this.objectStoreRemoved(objectStoreName);\n }\n }\n}\n\nexport class IDBObjectStoreTreeElement extends ApplicationPanelTreeElement {\n private model: IndexedDBModel;\n private databaseId: DatabaseId;\n private readonly idbIndexTreeElements: Map;\n private objectStore: ObjectStore;\n private view: IDBDataView|null;\n\n constructor(storagePanel: ResourcesPanel, model: IndexedDBModel, databaseId: DatabaseId, objectStore: ObjectStore) {\n super(storagePanel, objectStore.name, false, 'indexed-db-object-store');\n this.model = model;\n this.databaseId = databaseId;\n this.idbIndexTreeElements = new Map();\n this.objectStore = objectStore;\n this.view = null;\n const icon = IconButton.Icon.create('table');\n this.setLeadingIcons([icon]);\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return 'indexedDB://' + this.databaseId.storageBucket.storageKey + '/' +\n (this.databaseId.storageBucket.name ?? '') + '/' + this.databaseId.name + '/' +\n this.objectStore.name as Platform.DevToolsPath.UrlString;\n }\n\n override onattach(): void {\n super.onattach();\n this.listItemElement.addEventListener('contextmenu', this.handleContextMenuEvent.bind(this), true);\n }\n\n markNeedsRefresh(): void {\n if (this.view) {\n this.view.markNeedsRefresh();\n }\n for (const treeElement of this.idbIndexTreeElements.values()) {\n treeElement.markNeedsRefresh();\n }\n }\n\n private handleContextMenuEvent(event: MouseEvent): void {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.clear), this.clearObjectStore.bind(this), {jslogContext: 'clear'});\n void contextMenu.show();\n }\n\n private refreshObjectStore(): void {\n if (this.view) {\n this.view.refreshData();\n }\n for (const treeElement of this.idbIndexTreeElements.values()) {\n treeElement.refreshIndex();\n }\n }\n\n private async clearObjectStore(): Promise {\n await this.model.clearObjectStore(this.databaseId, this.objectStore.name);\n this.update(this.objectStore, true);\n }\n\n update(objectStore: ObjectStore, entriesUpdated: boolean): void {\n this.objectStore = objectStore;\n\n const indexNames = new Set();\n for (const index of this.objectStore.indexes.values()) {\n indexNames.add(index.name);\n let treeElement = this.idbIndexTreeElements.get(index.name);\n if (!treeElement) {\n treeElement = new IDBIndexTreeElement(\n this.resourcesPanel, this.model, this.databaseId, this.objectStore, index,\n this.refreshObjectStore.bind(this));\n this.idbIndexTreeElements.set(index.name, treeElement);\n this.appendChild(treeElement);\n }\n treeElement.update(this.objectStore, index, entriesUpdated);\n }\n for (const indexName of this.idbIndexTreeElements.keys()) {\n if (!indexNames.has(indexName)) {\n this.indexRemoved(indexName);\n }\n }\n for (const [indexName, treeElement] of this.idbIndexTreeElements.entries()) {\n if (!indexNames.has(indexName)) {\n this.removeChild((treeElement as IDBIndexTreeElement));\n this.idbIndexTreeElements.delete((indexName as string));\n }\n }\n\n if (this.childCount()) {\n this.expand();\n }\n\n if (this.view && entriesUpdated) {\n this.view.update(this.objectStore, null);\n }\n\n this.updateTooltip();\n }\n\n private updateTooltip(): void {\n const keyPathString = this.objectStore.keyPathString;\n let tooltipString = keyPathString !== null ? i18nString(UIStrings.keyPathS, {PH1: keyPathString}) : '';\n if (this.objectStore.autoIncrement) {\n tooltipString += '\\n' + i18n.i18n.lockedString('autoIncrement');\n }\n this.tooltip = tooltipString;\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n if (!this.view) {\n this.view =\n new IDBDataView(this.model, this.databaseId, this.objectStore, null, this.refreshObjectStore.bind(this));\n }\n\n this.showView(this.view);\n Host.userMetrics.panelShown('indexed-db');\n return false;\n }\n\n private indexRemoved(indexName: string): void {\n const indexTreeElement = this.idbIndexTreeElements.get(indexName);\n if (indexTreeElement) {\n indexTreeElement.clear();\n this.removeChild(indexTreeElement);\n }\n this.idbIndexTreeElements.delete(indexName);\n }\n\n clear(): void {\n for (const indexName of this.idbIndexTreeElements.keys()) {\n this.indexRemoved(indexName);\n }\n if (this.view) {\n this.view.clear();\n }\n }\n}\n\nexport class IDBIndexTreeElement extends ApplicationPanelTreeElement {\n private model: IndexedDBModel;\n private databaseId: DatabaseId;\n private objectStore: ObjectStore;\n private index: Index;\n private refreshObjectStore: () => void;\n private view?: IDBDataView;\n\n constructor(\n storagePanel: ResourcesPanel, model: IndexedDBModel, databaseId: DatabaseId, objectStore: ObjectStore,\n index: Index, refreshObjectStore: () => void) {\n super(storagePanel, index.name, false, 'indexed-db');\n this.model = model;\n this.databaseId = databaseId;\n this.objectStore = objectStore;\n this.index = index;\n this.refreshObjectStore = refreshObjectStore;\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return 'indexedDB://' + this.databaseId.storageBucket.storageKey + '/' +\n (this.databaseId.storageBucket.name ?? '') + '/' + this.databaseId.name + '/' + this.objectStore.name + '/' +\n this.index.name as Platform.DevToolsPath.UrlString;\n }\n\n markNeedsRefresh(): void {\n if (this.view) {\n this.view.markNeedsRefresh();\n }\n }\n\n refreshIndex(): void {\n if (this.view) {\n this.view.refreshData();\n }\n }\n\n update(objectStore: ObjectStore, index: Index, entriesUpdated: boolean): void {\n this.objectStore = objectStore;\n this.index = index;\n\n if (this.view && entriesUpdated) {\n this.view.update(this.objectStore, this.index);\n }\n\n this.updateTooltip();\n }\n\n private updateTooltip(): void {\n const tooltipLines = [];\n const keyPathString = this.index.keyPathString;\n tooltipLines.push(i18nString(UIStrings.keyPathS, {PH1: keyPathString}));\n if (this.index.unique) {\n tooltipLines.push(i18n.i18n.lockedString('unique'));\n }\n if (this.index.multiEntry) {\n tooltipLines.push(i18n.i18n.lockedString('multiEntry'));\n }\n this.tooltip = tooltipLines.join('\\n');\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n if (!this.view) {\n this.view = new IDBDataView(this.model, this.databaseId, this.objectStore, this.index, this.refreshObjectStore);\n }\n\n this.showView(this.view);\n Host.userMetrics.panelShown('indexed-db');\n return false;\n }\n\n clear(): void {\n if (this.view) {\n this.view.clear();\n }\n }\n}\n\nexport class DOMStorageTreeElement extends ApplicationPanelTreeElement {\n private readonly domStorage: DOMStorage;\n constructor(storagePanel: ResourcesPanel, domStorage: DOMStorage) {\n super(\n storagePanel,\n domStorage.storageKey ? SDK.StorageKeyManager.parseStorageKey(domStorage.storageKey).origin :\n i18nString(UIStrings.localFiles),\n false, domStorage.isLocalStorage ? 'local-storage-for-domain' : 'session-storage-for-domain');\n this.domStorage = domStorage;\n const icon = IconButton.Icon.create('table');\n this.setLeadingIcons([icon]);\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return 'storage://' + this.domStorage.storageKey + '/' + (this.domStorage.isLocalStorage ? 'local' : 'session') as\n Platform.DevToolsPath.UrlString;\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n Host.userMetrics.panelShown('dom-storage');\n this.resourcesPanel.showDOMStorage(this.domStorage);\n return false;\n }\n\n override onattach(): void {\n super.onattach();\n this.listItemElement.addEventListener('contextmenu', this.handleContextMenuEvent.bind(this), true);\n }\n\n private handleContextMenuEvent(event: MouseEvent): void {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.clear), () => this.domStorage.clear(), {jslogContext: 'clear'});\n void contextMenu.show();\n }\n}\n\nexport class CookieTreeElement extends ApplicationPanelTreeElement {\n private readonly target: SDK.Target.Target;\n private readonly cookieDomainInternal: string;\n\n constructor(\n storagePanel: ResourcesPanel, frame: SDK.ResourceTreeModel.ResourceTreeFrame,\n cookieUrl: Common.ParsedURL.ParsedURL) {\n super(storagePanel, cookieUrl.securityOrigin() || i18nString(UIStrings.localFiles), false, 'cookies-for-frame');\n this.target = frame.resourceTreeModel().target();\n this.cookieDomainInternal = cookieUrl.securityOrigin();\n this.tooltip = i18nString(UIStrings.cookiesUsedByFramesFromS, {PH1: this.cookieDomainInternal});\n const icon = IconButton.Icon.create('cookie');\n // Note that we cannot use `cookieDomainInternal` here since it contains scheme.\n if (IssuesManager.RelatedIssue.hasThirdPartyPhaseoutCookieIssueForDomain(cookieUrl.domain())) {\n icon.name = 'warning-filled';\n icon.classList.add('warn-icon');\n this.tooltip = i18nString(UIStrings.thirdPartyPhaseout, {PH1: this.cookieDomainInternal});\n }\n this.setLeadingIcons([icon]);\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return 'cookies://' + this.cookieDomainInternal as Platform.DevToolsPath.UrlString;\n }\n\n cookieDomain(): string {\n return this.cookieDomainInternal;\n }\n\n override onattach(): void {\n super.onattach();\n this.listItemElement.addEventListener('contextmenu', this.handleContextMenuEvent.bind(this), true);\n }\n\n private handleContextMenuEvent(event: Event): void {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.clear), () => this.resourcesPanel.clearCookies(this.target, this.cookieDomainInternal),\n {jslogContext: 'clear'});\n void contextMenu.show();\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n this.resourcesPanel.showCookies(this.target, this.cookieDomainInternal);\n Host.userMetrics.panelShown(Host.UserMetrics.PanelCodes[Host.UserMetrics.PanelCodes.cookies]);\n return false;\n }\n}\n\nexport class StorageCategoryView extends UI.Widget.VBox {\n private emptyWidget: UI.EmptyWidget.EmptyWidget;\n private linkElement: HTMLElement|null;\n\n constructor() {\n super();\n\n this.element.classList.add('storage-view');\n this.emptyWidget = new UI.EmptyWidget.EmptyWidget('');\n this.linkElement = null;\n this.emptyWidget.show(this.element);\n }\n\n setText(text: string): void {\n this.emptyWidget.text = text;\n }\n\n setLink(link: Platform.DevToolsPath.UrlString|null): void {\n if (link && !this.linkElement) {\n this.linkElement = this.emptyWidget.appendLink(link);\n }\n if (!link && this.linkElement) {\n this.linkElement.classList.add('hidden');\n }\n if (link && this.linkElement) {\n this.linkElement.setAttribute('href', link);\n this.linkElement.classList.remove('hidden');\n }\n }\n}\n\nexport class ResourcesSection implements SDK.TargetManager.Observer {\n panel: ResourcesPanel;\n private readonly treeElement: UI.TreeOutline.TreeElement;\n private treeElementForFrameId: Map;\n private treeElementForTargetId: Map;\n\n constructor(storagePanel: ResourcesPanel, treeElement: UI.TreeOutline.TreeElement) {\n this.panel = storagePanel;\n this.treeElement = treeElement;\n UI.ARIAUtils.setLabel(this.treeElement.listItemNode, 'Resources Section');\n this.treeElementForFrameId = new Map();\n this.treeElementForTargetId = new Map();\n\n const frameManager = SDK.FrameManager.FrameManager.instance();\n frameManager.addEventListener(\n SDK.FrameManager.Events.FRAME_ADDED_TO_TARGET, event => this.frameAdded(event.data.frame), this);\n frameManager.addEventListener(\n SDK.FrameManager.Events.FRAME_REMOVED, event => this.frameDetached(event.data.frameId), this);\n frameManager.addEventListener(\n SDK.FrameManager.Events.FRAME_NAVIGATED, event => this.frameNavigated(event.data.frame), this);\n frameManager.addEventListener(\n SDK.FrameManager.Events.RESOURCE_ADDED, event => this.resourceAdded(event.data.resource), this);\n\n SDK.TargetManager.TargetManager.instance().addModelListener(\n SDK.ChildTargetManager.ChildTargetManager, SDK.ChildTargetManager.Events.TARGET_CREATED, this.windowOpened,\n this, {scoped: true});\n SDK.TargetManager.TargetManager.instance().addModelListener(\n SDK.ChildTargetManager.ChildTargetManager, SDK.ChildTargetManager.Events.TARGET_INFO_CHANGED,\n this.windowChanged, this, {scoped: true});\n SDK.TargetManager.TargetManager.instance().addModelListener(\n SDK.ChildTargetManager.ChildTargetManager, SDK.ChildTargetManager.Events.TARGET_DESTROYED, this.windowDestroyed,\n this, {scoped: true});\n\n SDK.TargetManager.TargetManager.instance().observeTargets(this, {scoped: true});\n }\n\n private initialize(): void {\n const frameManager = SDK.FrameManager.FrameManager.instance();\n for (const frame of frameManager.getAllFrames()) {\n if (!this.treeElementForFrameId.get(frame.id)) {\n this.addFrameAndParents(frame);\n }\n const childTargetManager = frame.resourceTreeModel().target().model(SDK.ChildTargetManager.ChildTargetManager);\n if (childTargetManager) {\n for (const targetInfo of childTargetManager.targetInfos()) {\n this.windowOpened({data: targetInfo});\n }\n }\n }\n }\n\n targetAdded(target: SDK.Target.Target): void {\n if (target.type() === SDK.Target.Type.Worker || target.type() === SDK.Target.Type.ServiceWorker) {\n void this.workerAdded(target);\n }\n if (target.type() === SDK.Target.Type.FRAME && target === target.outermostTarget()) {\n // Process existing frames, e.g. after prerendering activation or\n // switching between outermost targets.\n this.initialize();\n }\n }\n\n private async workerAdded(target: SDK.Target.Target): Promise {\n const parentTarget = target.parentTarget();\n if (!parentTarget) {\n return;\n }\n const parentTargetId = parentTarget.id();\n const frameTreeElement = this.treeElementForTargetId.get(parentTargetId);\n const targetId = target.id();\n assertNotMainTarget(targetId);\n const {targetInfo} = await parentTarget.targetAgent().invoke_getTargetInfo({targetId});\n if (frameTreeElement && targetInfo) {\n frameTreeElement.workerCreated(targetInfo);\n }\n }\n\n targetRemoved(_target: SDK.Target.Target): void {\n }\n\n private addFrameAndParents(frame: SDK.ResourceTreeModel.ResourceTreeFrame): void {\n const parentFrame = frame.parentFrame();\n if (parentFrame && !this.treeElementForFrameId.get(parentFrame.id)) {\n this.addFrameAndParents(parentFrame);\n }\n this.frameAdded(frame);\n }\n\n private expandFrame(frame: SDK.ResourceTreeModel.ResourceTreeFrame|null): boolean {\n if (!frame) {\n return false;\n }\n let treeElement = this.treeElementForFrameId.get(frame.id);\n if (!treeElement && !this.expandFrame(frame.parentFrame())) {\n return false;\n }\n treeElement = this.treeElementForFrameId.get(frame.id);\n if (!treeElement) {\n return false;\n }\n treeElement.expand();\n return true;\n }\n\n async revealResource(resource: SDK.Resource.Resource, line?: number, column?: number): Promise {\n if (!this.expandFrame(resource.frame())) {\n return;\n }\n const resourceTreeElement = FrameResourceTreeElement.forResource(resource);\n if (resourceTreeElement) {\n await resourceTreeElement.revealResource(line, column);\n }\n }\n\n revealAndSelectFrame(frame: SDK.ResourceTreeModel.ResourceTreeFrame): void {\n const frameTreeElement = this.treeElementForFrameId.get(frame.id);\n frameTreeElement?.reveal();\n frameTreeElement?.select();\n }\n\n private frameAdded(frame: SDK.ResourceTreeModel.ResourceTreeFrame): void {\n if (!SDK.TargetManager.TargetManager.instance().isInScope(frame.resourceTreeModel())) {\n return;\n }\n const parentFrame = frame.parentFrame();\n const parentTreeElement = parentFrame ? this.treeElementForFrameId.get(parentFrame.id) : this.treeElement;\n if (!parentTreeElement) {\n return;\n }\n\n const existingElement = this.treeElementForFrameId.get(frame.id);\n if (existingElement) {\n this.treeElementForFrameId.delete(frame.id);\n if (existingElement.parent) {\n existingElement.parent.removeChild(existingElement);\n }\n }\n\n const frameTreeElement = new FrameTreeElement(this, frame);\n this.treeElementForFrameId.set(frame.id, frameTreeElement);\n const targetId = frame.resourceTreeModel().target().id();\n if (!this.treeElementForTargetId.get(targetId)) {\n this.treeElementForTargetId.set(targetId, frameTreeElement);\n }\n parentTreeElement.appendChild(frameTreeElement);\n\n for (const resource of frame.resources()) {\n this.resourceAdded(resource);\n }\n }\n\n private frameDetached(frameId: Protocol.Page.FrameId): void {\n const frameTreeElement = this.treeElementForFrameId.get(frameId);\n if (!frameTreeElement) {\n return;\n }\n\n this.treeElementForFrameId.delete(frameId);\n if (frameTreeElement.parent) {\n frameTreeElement.parent.removeChild(frameTreeElement);\n }\n }\n\n private frameNavigated(frame: SDK.ResourceTreeModel.ResourceTreeFrame): void {\n if (!SDK.TargetManager.TargetManager.instance().isInScope(frame.resourceTreeModel())) {\n return;\n }\n const frameTreeElement = this.treeElementForFrameId.get(frame.id);\n if (frameTreeElement) {\n void frameTreeElement.frameNavigated(frame);\n }\n }\n\n private resourceAdded(resource: SDK.Resource.Resource): void {\n const frame = resource.frame();\n if (!frame) {\n return;\n }\n if (!SDK.TargetManager.TargetManager.instance().isInScope(frame.resourceTreeModel())) {\n return;\n }\n const frameTreeElement = this.treeElementForFrameId.get(frame.id);\n if (!frameTreeElement) {\n // This is a frame's main resource, it will be retained\n // and re-added by the resource manager;\n return;\n }\n frameTreeElement.appendResource(resource);\n }\n\n private windowOpened(event: Common.EventTarget.EventTargetEvent): void {\n const targetInfo = event.data;\n // Events for DevTools windows are ignored because they do not have an openerId\n if (targetInfo.openerId && targetInfo.type === 'page') {\n const frameTreeElement = this.treeElementForFrameId.get(targetInfo.openerId);\n if (frameTreeElement) {\n this.treeElementForTargetId.set(targetInfo.targetId, frameTreeElement);\n frameTreeElement.windowOpened(targetInfo);\n }\n }\n }\n\n private windowDestroyed(event: Common.EventTarget.EventTargetEvent): void {\n const targetId = event.data;\n const frameTreeElement = this.treeElementForTargetId.get(targetId);\n if (frameTreeElement) {\n frameTreeElement.windowDestroyed(targetId);\n this.treeElementForTargetId.delete(targetId);\n }\n }\n\n private windowChanged(event: Common.EventTarget.EventTargetEvent): void {\n const targetInfo = event.data;\n // Events for DevTools windows are ignored because they do not have an openerId\n if (targetInfo.openerId && targetInfo.type === 'page') {\n const frameTreeElement = this.treeElementForFrameId.get(targetInfo.openerId);\n if (frameTreeElement) {\n frameTreeElement.windowChanged(targetInfo);\n }\n }\n }\n\n reset(): void {\n this.treeElement.removeChildren();\n this.treeElementForFrameId.clear();\n this.treeElementForTargetId.clear();\n }\n}\n\nexport class FrameTreeElement extends ApplicationPanelTreeElement {\n private section: ResourcesSection;\n private frame: SDK.ResourceTreeModel.ResourceTreeFrame;\n private frameId: string;\n private readonly categoryElements: Map;\n private readonly treeElementForResource: Map;\n private treeElementForWindow: Map;\n private treeElementForWorker: Map;\n private view: LegacyWrapper.LegacyWrapper\n .LegacyWrapper|null;\n\n constructor(section: ResourcesSection, frame: SDK.ResourceTreeModel.ResourceTreeFrame) {\n super(section.panel, '', false, 'frame');\n this.section = section;\n this.frame = frame;\n this.frameId = frame.id;\n this.categoryElements = new Map();\n this.treeElementForResource = new Map();\n this.treeElementForWindow = new Map();\n this.treeElementForWorker = new Map();\n void this.frameNavigated(frame);\n this.view = null;\n }\n\n getIconTypeForFrame(frame: SDK.ResourceTreeModel.ResourceTreeFrame): 'frame-crossed'|'frame'|'iframe-crossed'|\n 'iframe' {\n if (frame.isOutermostFrame()) {\n return frame.unreachableUrl() ? 'frame-crossed' : 'frame';\n }\n return frame.unreachableUrl() ? 'iframe-crossed' : 'iframe';\n }\n\n async frameNavigated(frame: SDK.ResourceTreeModel.ResourceTreeFrame): Promise {\n const icon = IconButton.Icon.create(this.getIconTypeForFrame(frame));\n if (frame.unreachableUrl()) {\n icon.classList.add('red-icon');\n }\n this.setLeadingIcons([icon]);\n this.invalidateChildren();\n\n this.frameId = frame.id;\n if (this.title !== frame.displayName()) {\n this.title = frame.displayName();\n UI.ARIAUtils.setLabel(this.listItemElement, this.title);\n if (this.parent) {\n const parent = this.parent;\n // Insert frame at new position to preserve correct alphabetical order\n parent.removeChild(this);\n parent.appendChild(this);\n }\n }\n this.categoryElements.clear();\n this.treeElementForResource.clear();\n this.treeElementForWorker.clear();\n\n if (this.selected) {\n this.view = LegacyWrapper.LegacyWrapper.legacyWrapper(\n UI.Widget.Widget, new ApplicationComponents.FrameDetailsView.FrameDetailsReportView(this.frame));\n this.showView(this.view);\n } else {\n this.view = null;\n }\n\n // Service Workers' parent is always the outermost frame. We need to reconstruct\n // the service worker tree elements after those navigations which allow\n // the service workers to stay alive.\n if (frame.isOutermostFrame()) {\n const targets = SDK.TargetManager.TargetManager.instance().targets();\n for (const target of targets) {\n if (target.type() === SDK.Target.Type.ServiceWorker &&\n SDK.TargetManager.TargetManager.instance().isInScope(target)) {\n const targetId = target.id();\n assertNotMainTarget(targetId);\n const agent = frame.resourceTreeModel().target().targetAgent();\n const targetInfo = (await agent.invoke_getTargetInfo({targetId})).targetInfo;\n this.workerCreated(targetInfo);\n }\n }\n }\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n // This is used to persist over reloads/navigation which frame was selected.\n // A frame's title can change on DevTools refresh, so we resort to using\n // the URL instead (even though it is not guaranteed to be unique).\n if (this.frame.isOutermostFrame()) {\n return 'frame://' as Platform.DevToolsPath.UrlString;\n }\n return 'frame://' + encodeURI(this.frame.url) as Platform.DevToolsPath.UrlString;\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n if (!this.view) {\n this.view = LegacyWrapper.LegacyWrapper.legacyWrapper(\n UI.Widget.Widget, new ApplicationComponents.FrameDetailsView.FrameDetailsReportView(this.frame));\n }\n Host.userMetrics.panelShown('frame-details');\n this.showView(this.view);\n\n this.listItemElement.classList.remove('hovered');\n SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight();\n return false;\n }\n\n set hovered(hovered: boolean) {\n if (hovered) {\n this.listItemElement.classList.add('hovered');\n void this.frame.highlight();\n } else {\n this.listItemElement.classList.remove('hovered');\n SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight();\n }\n }\n\n appendResource(resource: SDK.Resource.Resource): void {\n const statusCode = resource.statusCode();\n if (statusCode >= 301 && statusCode <= 303) {\n return;\n }\n\n const resourceType = resource.resourceType();\n const categoryName = resourceType.name();\n let categoryElement =\n resourceType === Common.ResourceType.resourceTypes.Document ? this : this.categoryElements.get(categoryName);\n if (!categoryElement) {\n categoryElement = new ExpandableApplicationPanelTreeElement(\n this.section.panel, resource.resourceType().category().title(), categoryName, categoryName === 'Frames');\n this.categoryElements.set(resourceType.name(), categoryElement);\n this.appendChild(categoryElement, FrameTreeElement.presentationOrderCompare);\n }\n const resourceTreeElement = new FrameResourceTreeElement(this.section.panel, resource);\n categoryElement.appendChild(resourceTreeElement, FrameTreeElement.presentationOrderCompare);\n this.treeElementForResource.set(resource.url, resourceTreeElement);\n }\n\n windowOpened(targetInfo: Protocol.Target.TargetInfo): void {\n const categoryKey = 'opened-windows';\n let categoryElement = this.categoryElements.get(categoryKey);\n if (!categoryElement) {\n categoryElement = new ExpandableApplicationPanelTreeElement(\n this.section.panel, i18nString(UIStrings.openedWindows), categoryKey);\n this.categoryElements.set(categoryKey, categoryElement);\n this.appendChild(categoryElement, FrameTreeElement.presentationOrderCompare);\n }\n if (!this.treeElementForWindow.get(targetInfo.targetId)) {\n const windowTreeElement = new FrameWindowTreeElement(this.section.panel, targetInfo);\n categoryElement.appendChild(windowTreeElement);\n this.treeElementForWindow.set(targetInfo.targetId, windowTreeElement);\n }\n }\n\n workerCreated(targetInfo: Protocol.Target.TargetInfo): void {\n const categoryKey = targetInfo.type === 'service_worker' ? 'service-workers' : 'web-workers';\n const categoryName = targetInfo.type === 'service_worker' ? i18n.i18n.lockedString('Service workers') :\n i18nString(UIStrings.webWorkers);\n let categoryElement = this.categoryElements.get(categoryKey);\n if (!categoryElement) {\n categoryElement = new ExpandableApplicationPanelTreeElement(this.section.panel, categoryName, categoryKey);\n this.categoryElements.set(categoryKey, categoryElement);\n this.appendChild(categoryElement, FrameTreeElement.presentationOrderCompare);\n }\n if (!this.treeElementForWorker.get(targetInfo.targetId)) {\n const workerTreeElement = new WorkerTreeElement(this.section.panel, targetInfo);\n categoryElement.appendChild(workerTreeElement);\n this.treeElementForWorker.set(targetInfo.targetId, workerTreeElement);\n }\n }\n\n windowChanged(targetInfo: Protocol.Target.TargetInfo): void {\n const windowTreeElement = this.treeElementForWindow.get(targetInfo.targetId);\n if (!windowTreeElement) {\n return;\n }\n if (windowTreeElement.title !== targetInfo.title) {\n windowTreeElement.title = targetInfo.title;\n }\n windowTreeElement.update(targetInfo);\n }\n\n windowDestroyed(targetId: Protocol.Target.TargetID): void {\n const windowTreeElement = this.treeElementForWindow.get(targetId);\n if (windowTreeElement) {\n windowTreeElement.windowClosed();\n }\n }\n\n override appendChild(\n treeElement: UI.TreeOutline.TreeElement,\n comparator: ((arg0: UI.TreeOutline.TreeElement, arg1: UI.TreeOutline.TreeElement) => number)|\n undefined = FrameTreeElement.presentationOrderCompare): void {\n super.appendChild(treeElement, comparator);\n }\n\n /**\n * Order elements by type (first frames, then resources, last Document resources)\n * and then each of these groups in the alphabetical order.\n */\n private static presentationOrderCompare(\n treeElement1: UI.TreeOutline.TreeElement, treeElement2: UI.TreeOutline.TreeElement): number {\n function typeWeight(treeElement: UI.TreeOutline.TreeElement): number {\n if (treeElement instanceof ExpandableApplicationPanelTreeElement) {\n return 2;\n }\n if (treeElement instanceof FrameTreeElement) {\n return 1;\n }\n return 3;\n }\n\n const typeWeight1 = typeWeight(treeElement1);\n const typeWeight2 = typeWeight(treeElement2);\n return typeWeight1 - typeWeight2 || treeElement1.titleAsText().localeCompare(treeElement2.titleAsText());\n }\n}\n\nconst resourceToFrameResourceTreeElement = new WeakMap();\n\nexport class FrameResourceTreeElement extends ApplicationPanelTreeElement {\n private readonly panel: ResourcesPanel;\n private resource: SDK.Resource.Resource;\n private previewPromise: Promise|null;\n\n constructor(storagePanel: ResourcesPanel, resource: SDK.Resource.Resource) {\n super(\n storagePanel, resource.isGenerated ? i18nString(UIStrings.documentNotAvailable) : resource.displayName, false,\n 'frame-resource');\n this.panel = storagePanel;\n this.resource = resource;\n this.previewPromise = null;\n this.tooltip = resource.url;\n resourceToFrameResourceTreeElement.set(this.resource, this);\n\n const icon = IconButton.Icon.create('document', 'navigator-file-tree-item');\n icon.classList.add('navigator-' + resource.resourceType().name() + '-tree-item');\n this.setLeadingIcons([icon]);\n }\n\n static forResource(resource: SDK.Resource.Resource): FrameResourceTreeElement|undefined {\n return resourceToFrameResourceTreeElement.get(resource);\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return this.resource.url;\n }\n\n private preparePreview(): Promise {\n if (this.previewPromise) {\n return this.previewPromise;\n }\n const viewPromise = SourceFrame.PreviewFactory.PreviewFactory.createPreview(this.resource, this.resource.mimeType);\n this.previewPromise = viewPromise.then(view => {\n if (view) {\n return view;\n }\n return new UI.EmptyWidget.EmptyWidget(this.resource.url);\n });\n return this.previewPromise;\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n if (this.resource.isGenerated) {\n this.panel.showCategoryView(i18nString(UIStrings.theContentOfThisDocumentHasBeen), null);\n } else {\n void this.panel.scheduleShowView(this.preparePreview());\n }\n Host.userMetrics.panelShown('frame-resource');\n return false;\n }\n\n override ondblclick(_event: Event): boolean {\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(this.resource.url);\n return false;\n }\n\n override onattach(): void {\n super.onattach();\n this.listItemElement.draggable = true;\n this.listItemElement.addEventListener('dragstart', this.ondragstart.bind(this), false);\n this.listItemElement.addEventListener('contextmenu', this.handleContextMenuEvent.bind(this), true);\n }\n\n private ondragstart(event: DragEvent): boolean {\n if (!event.dataTransfer) {\n return false;\n }\n event.dataTransfer.setData('text/plain', this.resource.content || '');\n event.dataTransfer.effectAllowed = 'copy';\n return true;\n }\n\n private handleContextMenuEvent(event: MouseEvent): void {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n contextMenu.appendApplicableItems(this.resource);\n void contextMenu.show();\n }\n\n async revealResource(lineNumber?: number, columnNumber?: number): Promise {\n this.revealAndSelect(true);\n const view = await this.panel.scheduleShowView(this.preparePreview());\n if (!(view instanceof SourceFrame.ResourceSourceFrame.ResourceSourceFrame) || typeof lineNumber !== 'number') {\n return;\n }\n view.revealPosition({lineNumber, columnNumber}, true);\n }\n}\n\nclass FrameWindowTreeElement extends ApplicationPanelTreeElement {\n private targetInfo: Protocol.Target.TargetInfo;\n private isWindowClosed: boolean;\n private view: OpenedWindowDetailsView|null;\n\n constructor(storagePanel: ResourcesPanel, targetInfo: Protocol.Target.TargetInfo) {\n super(storagePanel, targetInfo.title || i18nString(UIStrings.windowWithoutTitle), false, 'window');\n this.targetInfo = targetInfo;\n this.isWindowClosed = false;\n this.view = null;\n this.updateIcon(targetInfo.canAccessOpener);\n }\n\n updateIcon(canAccessOpener: boolean): void {\n const iconType = canAccessOpener ? 'popup' : 'frame';\n const icon = IconButton.Icon.create(iconType);\n this.setLeadingIcons([icon]);\n }\n\n update(targetInfo: Protocol.Target.TargetInfo): void {\n if (targetInfo.canAccessOpener !== this.targetInfo.canAccessOpener) {\n this.updateIcon(targetInfo.canAccessOpener);\n }\n this.targetInfo = targetInfo;\n if (this.view) {\n this.view.setTargetInfo(targetInfo);\n this.view.update();\n }\n }\n\n windowClosed(): void {\n this.listItemElement.classList.add('window-closed');\n this.isWindowClosed = true;\n if (this.view) {\n this.view.setIsWindowClosed(true);\n this.view.update();\n }\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n if (!this.view) {\n this.view = new OpenedWindowDetailsView(this.targetInfo, this.isWindowClosed);\n } else {\n this.view.update();\n }\n this.showView(this.view);\n Host.userMetrics.panelShown('frame-window');\n return false;\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return this.targetInfo.url as Platform.DevToolsPath.UrlString;\n }\n}\n\nclass WorkerTreeElement extends ApplicationPanelTreeElement {\n private targetInfo: Protocol.Target.TargetInfo;\n private view: WorkerDetailsView|null;\n\n constructor(storagePanel: ResourcesPanel, targetInfo: Protocol.Target.TargetInfo) {\n super(storagePanel, targetInfo.title || targetInfo.url || i18nString(UIStrings.worker), false, 'worker');\n this.targetInfo = targetInfo;\n this.view = null;\n const icon = IconButton.Icon.create('gears', 'navigator-file-tree-item');\n this.setLeadingIcons([icon]);\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n if (!this.view) {\n this.view = new WorkerDetailsView(this.targetInfo);\n } else {\n this.view.update();\n }\n this.showView(this.view);\n Host.userMetrics.panelShown('frame-worker');\n return false;\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return this.targetInfo.url as Platform.DevToolsPath.UrlString;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"ApplicationPanelSidebar.js","sourceRoot":"","sources":["../../../../../../front_end/panels/application/ApplicationPanelSidebar.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2021 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/*\n * Copyright (C) 2007, 2008, 2010 Apple Inc. All rights reserved.\n * Copyright (C) 2009 Joseph Pecoraro\n * Copyright (C) 2013 Samsung Electronics. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. Neither the name of Apple Computer, Inc. (\"Apple\") nor the names of\n * its contributors may be used to endorse or promote products derived\n * from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport * as Common from '../../core/common/common.js';\nimport * as Host from '../../core/host/host.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as Root from '../../core/root/root.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as Protocol from '../../generated/protocol.js';\nimport * as IssuesManager from '../../models/issues_manager/issues_manager.js';\nimport * as IconButton from '../../ui/components/icon_button/icon_button.js';\nimport * as LegacyWrapper from '../../ui/components/legacy_wrapper/legacy_wrapper.js';\nimport * as SourceFrame from '../../ui/legacy/components/source_frame/source_frame.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport {ApplicationPanelTreeElement, ExpandableApplicationPanelTreeElement} from './ApplicationPanelTreeElement.js';\nimport {AppManifestView, Events as AppManifestViewEvents} from './AppManifestView.js';\nimport {BackForwardCacheTreeElement} from './BackForwardCacheTreeElement.js';\nimport {BackgroundServiceModel} from './BackgroundServiceModel.js';\nimport {BackgroundServiceView} from './BackgroundServiceView.js';\nimport {BounceTrackingMitigationsTreeElement} from './BounceTrackingMitigationsTreeElement.js';\nimport * as ApplicationComponents from './components/components.js';\nimport {type DOMStorage, DOMStorageModel, Events as DOMStorageModelEvents} from './DOMStorageModel.js';\nimport {\n Events as ExtensionStorageModelEvents,\n type ExtensionStorage,\n ExtensionStorageModel,\n} from './ExtensionStorageModel.js';\nimport {\n type Database as IndexedDBModelDatabase,\n type DatabaseId,\n Events as IndexedDBModelEvents,\n type Index,\n IndexedDBModel,\n type ObjectStore,\n} from './IndexedDBModel.js';\nimport {IDBDatabaseView, IDBDataView} from './IndexedDBViews.js';\nimport {Events as InterestGroupModelEvents, InterestGroupStorageModel} from './InterestGroupStorageModel.js';\nimport {InterestGroupTreeElement} from './InterestGroupTreeElement.js';\nimport {OpenedWindowDetailsView, WorkerDetailsView} from './OpenedWindowDetailsView.js';\nimport type * as PreloadingHelper from './preloading/helper/helper.js';\nimport {\n PreloadingSummaryTreeElement,\n} from './PreloadingTreeElement.js';\nimport {ReportingApiTreeElement} from './ReportingApiTreeElement.js';\nimport {type ResourcesPanel} from './ResourcesPanel.js';\nimport resourcesSidebarStyles from './resourcesSidebar.css.js';\nimport {ServiceWorkerCacheTreeElement} from './ServiceWorkerCacheTreeElement.js';\nimport {ServiceWorkersView} from './ServiceWorkersView.js';\nimport {SharedStorageListTreeElement} from './SharedStorageListTreeElement.js';\nimport {\n Events as SharedStorageModelEvents,\n type SharedStorageForOrigin,\n SharedStorageModel,\n} from './SharedStorageModel.js';\nimport {SharedStorageTreeElement} from './SharedStorageTreeElement.js';\nimport {StorageBucketsTreeParentElement} from './StorageBucketsTreeElement.js';\nimport {StorageView} from './StorageView.js';\nimport {TrustTokensTreeElement} from './TrustTokensTreeElement.js';\n\nconst UIStrings = {\n /**\n *@description Text in Application Panel Sidebar of the Application panel\n */\n application: 'Application',\n /**\n *@description Text in Application Panel Sidebar of the Application panel\n */\n storage: 'Storage',\n /**\n *@description Text in Application Panel Sidebar of the Application panel\n */\n localStorage: 'Local storage',\n /**\n *@description Text in Application Panel Sidebar of the Application panel\n */\n sessionStorage: 'Session storage',\n /**\n *@description Text in Application Panel Sidebar of the Application panel\n */\n extensionStorage: 'Extension storage',\n /**\n *@description Text for web cookies\n */\n cookies: 'Cookies',\n /**\n *@description Text in Application Panel Sidebar of the Application panel\n */\n backgroundServices: 'Background services',\n /**\n *@description Text for rendering frames\n */\n frames: 'Frames',\n /**\n *@description Text that appears on a button for the manifest resource type filter.\n */\n manifest: 'Manifest',\n /**\n *@description Text in App Manifest View of the Application panel\n */\n noManifestDetected: 'No manifest detected',\n /**\n *@description Text in App Manifest View of the Application panel\n */\n appManifest: 'App Manifest',\n /**\n *@description Text in Application Panel Sidebar of the Application panel\n */\n indexeddb: 'IndexedDB',\n /**\n *@description A context menu item in the Application Panel Sidebar of the Application panel\n */\n refreshIndexeddb: 'Refresh IndexedDB',\n /**\n *@description Tooltip in Application Panel Sidebar of the Application panel\n *@example {1.0} PH1\n */\n versionSEmpty: 'Version: {PH1} (empty)',\n /**\n *@description Tooltip in Application Panel Sidebar of the Application panel\n *@example {1.0} PH1\n */\n versionS: 'Version: {PH1}',\n /**\n *@description Text to clear content\n */\n clear: 'Clear',\n /**\n *@description Text in Application Panel Sidebar of the Application panel\n *@example {\"key path\"} PH1\n */\n keyPathS: 'Key path: {PH1}',\n /**\n *@description Text in Application Panel Sidebar of the Application panel\n */\n localFiles: 'Local Files',\n /**\n *@description Tooltip in Application Panel Sidebar of the Application panel\n *@example {https://example.com} PH1\n */\n cookiesUsedByFramesFromS: 'Cookies used by frames from {PH1}',\n /**\n *@description Text in Frames View of the Application panel\n */\n openedWindows: 'Opened Windows',\n /**\n *@description Label for plural of worker type: web workers\n */\n webWorkers: 'Web Workers',\n /**\n *@description Label in frame tree for unavailable document\n */\n documentNotAvailable: 'Document not available',\n /**\n *@description Description of content of unavailable document in Application panel\n */\n theContentOfThisDocumentHasBeen:\n 'The content of this document has been generated dynamically via \\'document.write()\\'.',\n /**\n *@description Text in Frames View of the Application panel\n */\n windowWithoutTitle: 'Window without title',\n /**\n *@description Default name for worker\n */\n worker: 'worker',\n /**\n * @description Aria text for screen reader to announce they can scroll to top of manifest if invoked\n */\n onInvokeManifestAlert: 'Manifest: Invoke to scroll to the top of manifest',\n /**\n * @description Aria text for screen reader to announce they can scroll to a section if invoked\n * @example {\"Identity\"} PH1\n */\n beforeInvokeAlert: '{PH1}: Invoke to scroll to this section in manifest',\n /**\n * @description Alert message for screen reader to announce which subsection is being scrolled to\n * @example {\"Identity\"} PH1\n */\n onInvokeAlert: 'Scrolled to {PH1}',\n /**\n * @description Application sidebar panel\n */\n applicationSidebarPanel: 'Application panel sidebar',\n /**\n *@description Tooltip in Application Panel Sidebar of the Application panel\n *@example {https://example.com} PH1\n */\n thirdPartyPhaseout: 'Cookies from {PH1} may have been blocked due to third-party cookie phaseout.',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/application/ApplicationPanelSidebar.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nfunction assertNotMainTarget(targetId: Protocol.Target.TargetID|'main'): asserts targetId is Protocol.Target.TargetID {\n if (targetId === 'main') {\n throw new Error('Unexpected main target id');\n }\n}\n\nexport namespace SharedStorageTreeElementDispatcher {\n export const enum Events {\n SHARED_STORAGE_TREE_ELEMENT_ADDED = 'SharedStorageTreeElementAdded',\n }\n\n export interface SharedStorageTreeElementAddedEvent {\n origin: string;\n }\n\n export type EventTypes = {\n [Events.SHARED_STORAGE_TREE_ELEMENT_ADDED]: SharedStorageTreeElementAddedEvent,\n };\n}\n\nexport class ApplicationPanelSidebar extends UI.Widget.VBox implements SDK.TargetManager.Observer {\n panel: ResourcesPanel;\n private readonly sidebarTree: UI.TreeOutline.TreeOutlineInShadow;\n private readonly applicationTreeElement: UI.TreeOutline.TreeElement;\n serviceWorkersTreeElement: ServiceWorkersTreeElement;\n localStorageListTreeElement: ExpandableApplicationPanelTreeElement;\n sessionStorageListTreeElement: ExpandableApplicationPanelTreeElement;\n extensionStorageListTreeElement: ExpandableApplicationPanelTreeElement|undefined;\n indexedDBListTreeElement: IndexedDBTreeElement;\n interestGroupTreeElement: InterestGroupTreeElement;\n cookieListTreeElement: ExpandableApplicationPanelTreeElement;\n trustTokensTreeElement: TrustTokensTreeElement;\n cacheStorageListTreeElement: ServiceWorkerCacheTreeElement;\n sharedStorageListTreeElement: SharedStorageListTreeElement;\n storageBucketsTreeElement: StorageBucketsTreeParentElement|undefined;\n private backForwardCacheListTreeElement?: BackForwardCacheTreeElement;\n backgroundFetchTreeElement: BackgroundServiceTreeElement;\n backgroundSyncTreeElement: BackgroundServiceTreeElement;\n bounceTrackingMitigationsTreeElement: BounceTrackingMitigationsTreeElement;\n notificationsTreeElement: BackgroundServiceTreeElement;\n paymentHandlerTreeElement: BackgroundServiceTreeElement;\n periodicBackgroundSyncTreeElement: BackgroundServiceTreeElement;\n pushMessagingTreeElement: BackgroundServiceTreeElement;\n reportingApiTreeElement: ReportingApiTreeElement;\n preloadingSummaryTreeElement: PreloadingSummaryTreeElement|undefined;\n private readonly resourcesSection: ResourcesSection;\n private domStorageTreeElements: Map;\n private extensionStorageTreeElements: Map;\n private sharedStorageTreeElements: Map;\n private domains: {\n [x: string]: boolean,\n };\n // Holds main frame target.\n private target?: SDK.Target.Target;\n private previousHoveredElement?: FrameTreeElement;\n readonly sharedStorageTreeElementDispatcher:\n Common.ObjectWrapper.ObjectWrapper;\n\n constructor(panel: ResourcesPanel) {\n super();\n\n this.panel = panel;\n\n this.sidebarTree = new UI.TreeOutline.TreeOutlineInShadow(UI.TreeOutline.TreeVariant.NAVIGATION_TREE);\n this.sidebarTree.element.classList.add('resources-sidebar');\n this.sidebarTree.hideOverflow();\n\n this.sidebarTree.element.classList.add('filter-all');\n // Listener needs to have been set up before the elements are added\n this.sidebarTree.addEventListener(UI.TreeOutline.Events.ElementAttached, this.treeElementAdded, this);\n\n this.contentElement.appendChild(this.sidebarTree.element);\n\n const applicationSectionTitle = i18nString(UIStrings.application);\n this.applicationTreeElement = this.addSidebarSection(applicationSectionTitle, 'application');\n const applicationPanelSidebar = this.applicationTreeElement.treeOutline?.contentElement;\n if (applicationPanelSidebar) {\n applicationPanelSidebar.ariaLabel = i18nString(UIStrings.applicationSidebarPanel);\n }\n const manifestTreeElement = new AppManifestTreeElement(panel);\n this.applicationTreeElement.appendChild(manifestTreeElement);\n manifestTreeElement.generateChildren();\n this.serviceWorkersTreeElement = new ServiceWorkersTreeElement(panel);\n this.applicationTreeElement.appendChild(this.serviceWorkersTreeElement);\n const clearStorageTreeElement = new ClearStorageTreeElement(panel);\n this.applicationTreeElement.appendChild(clearStorageTreeElement);\n\n const storageSectionTitle = i18nString(UIStrings.storage);\n const storageTreeElement = this.addSidebarSection(storageSectionTitle, 'storage');\n this.localStorageListTreeElement =\n new ExpandableApplicationPanelTreeElement(panel, i18nString(UIStrings.localStorage), 'local-storage');\n this.localStorageListTreeElement.setLink(\n 'https://developer.chrome.com/docs/devtools/storage/localstorage/?utm_source=devtools' as\n Platform.DevToolsPath.UrlString);\n const localStorageIcon = IconButton.Icon.create('table');\n this.localStorageListTreeElement.setLeadingIcons([localStorageIcon]);\n\n storageTreeElement.appendChild(this.localStorageListTreeElement);\n this.sessionStorageListTreeElement =\n new ExpandableApplicationPanelTreeElement(panel, i18nString(UIStrings.sessionStorage), 'session-storage');\n this.sessionStorageListTreeElement.setLink(\n 'https://developer.chrome.com/docs/devtools/storage/sessionstorage/?utm_source=devtools' as\n Platform.DevToolsPath.UrlString);\n const sessionStorageIcon = IconButton.Icon.create('table');\n this.sessionStorageListTreeElement.setLeadingIcons([sessionStorageIcon]);\n\n storageTreeElement.appendChild(this.sessionStorageListTreeElement);\n\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.EXTENSION_STORAGE_VIEWER)) {\n this.extensionStorageListTreeElement =\n new ExpandableApplicationPanelTreeElement(panel, i18nString(UIStrings.extensionStorage), 'extension-storage');\n this.extensionStorageListTreeElement.setLink(\n 'https://developer.chrome.com/docs/extensions/reference/api/storage/?utm_source=devtools' as\n Platform.DevToolsPath.UrlString);\n const extensionStorageIcon = IconButton.Icon.create('table');\n this.extensionStorageListTreeElement.setLeadingIcons([extensionStorageIcon]);\n\n storageTreeElement.appendChild(this.extensionStorageListTreeElement);\n }\n\n this.indexedDBListTreeElement = new IndexedDBTreeElement(panel);\n this.indexedDBListTreeElement.setLink(\n 'https://developer.chrome.com/docs/devtools/storage/indexeddb/?utm_source=devtools' as\n Platform.DevToolsPath.UrlString);\n storageTreeElement.appendChild(this.indexedDBListTreeElement);\n\n this.cookieListTreeElement =\n new ExpandableApplicationPanelTreeElement(panel, i18nString(UIStrings.cookies), 'cookies');\n this.cookieListTreeElement.setLink(\n 'https://developer.chrome.com/docs/devtools/storage/cookies/?utm_source=devtools' as\n Platform.DevToolsPath.UrlString);\n const cookieIcon = IconButton.Icon.create('cookie');\n this.cookieListTreeElement.setLeadingIcons([cookieIcon]);\n storageTreeElement.appendChild(this.cookieListTreeElement);\n\n this.trustTokensTreeElement = new TrustTokensTreeElement(panel);\n storageTreeElement.appendChild(this.trustTokensTreeElement);\n\n this.interestGroupTreeElement = new InterestGroupTreeElement(panel);\n storageTreeElement.appendChild(this.interestGroupTreeElement);\n\n this.sharedStorageListTreeElement = new SharedStorageListTreeElement(panel);\n storageTreeElement.appendChild(this.sharedStorageListTreeElement);\n\n this.cacheStorageListTreeElement = new ServiceWorkerCacheTreeElement(panel);\n storageTreeElement.appendChild(this.cacheStorageListTreeElement);\n\n this.storageBucketsTreeElement = new StorageBucketsTreeParentElement(panel);\n storageTreeElement.appendChild(this.storageBucketsTreeElement);\n\n const backgroundServiceSectionTitle = i18nString(UIStrings.backgroundServices);\n const backgroundServiceTreeElement = this.addSidebarSection(backgroundServiceSectionTitle, 'background-services');\n\n this.backForwardCacheListTreeElement = new BackForwardCacheTreeElement(panel);\n backgroundServiceTreeElement.appendChild(this.backForwardCacheListTreeElement);\n this.backgroundFetchTreeElement =\n new BackgroundServiceTreeElement(panel, Protocol.BackgroundService.ServiceName.BackgroundFetch);\n backgroundServiceTreeElement.appendChild(this.backgroundFetchTreeElement);\n this.backgroundSyncTreeElement =\n new BackgroundServiceTreeElement(panel, Protocol.BackgroundService.ServiceName.BackgroundSync);\n backgroundServiceTreeElement.appendChild(this.backgroundSyncTreeElement);\n\n this.bounceTrackingMitigationsTreeElement = new BounceTrackingMitigationsTreeElement(panel);\n backgroundServiceTreeElement.appendChild(this.bounceTrackingMitigationsTreeElement);\n\n this.notificationsTreeElement =\n new BackgroundServiceTreeElement(panel, Protocol.BackgroundService.ServiceName.Notifications);\n backgroundServiceTreeElement.appendChild(this.notificationsTreeElement);\n this.paymentHandlerTreeElement =\n new BackgroundServiceTreeElement(panel, Protocol.BackgroundService.ServiceName.PaymentHandler);\n backgroundServiceTreeElement.appendChild(this.paymentHandlerTreeElement);\n this.periodicBackgroundSyncTreeElement =\n new BackgroundServiceTreeElement(panel, Protocol.BackgroundService.ServiceName.PeriodicBackgroundSync);\n backgroundServiceTreeElement.appendChild(this.periodicBackgroundSyncTreeElement);\n\n this.preloadingSummaryTreeElement = new PreloadingSummaryTreeElement(panel);\n backgroundServiceTreeElement.appendChild(this.preloadingSummaryTreeElement);\n this.preloadingSummaryTreeElement.constructChildren(panel);\n\n this.pushMessagingTreeElement =\n new BackgroundServiceTreeElement(panel, Protocol.BackgroundService.ServiceName.PushMessaging);\n backgroundServiceTreeElement.appendChild(this.pushMessagingTreeElement);\n this.reportingApiTreeElement = new ReportingApiTreeElement(panel);\n backgroundServiceTreeElement.appendChild(this.reportingApiTreeElement);\n\n const resourcesSectionTitle = i18nString(UIStrings.frames);\n const resourcesTreeElement = this.addSidebarSection(resourcesSectionTitle, 'frames');\n this.resourcesSection = new ResourcesSection(panel, resourcesTreeElement);\n\n this.domStorageTreeElements = new Map();\n this.extensionStorageTreeElements = new Map();\n this.sharedStorageTreeElements = new Map();\n this.domains = {};\n\n this.sidebarTree.contentElement.addEventListener('mousemove', this.onmousemove.bind(this), false);\n this.sidebarTree.contentElement.addEventListener('mouseleave', this.onmouseleave.bind(this), false);\n\n SDK.TargetManager.TargetManager.instance().observeTargets(this, {scoped: true});\n SDK.TargetManager.TargetManager.instance().addModelListener(\n SDK.ResourceTreeModel.ResourceTreeModel, SDK.ResourceTreeModel.Events.FrameNavigated, this.frameNavigated, this,\n {scoped: true});\n\n const selection = this.panel.lastSelectedItemPath();\n if (!selection.length) {\n manifestTreeElement.select();\n }\n\n SDK.TargetManager.TargetManager.instance().observeModels(\n DOMStorageModel, {\n modelAdded: (model: DOMStorageModel) => this.domStorageModelAdded(model),\n modelRemoved: (model: DOMStorageModel) => this.domStorageModelRemoved(model),\n },\n {scoped: true});\n\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.EXTENSION_STORAGE_VIEWER)) {\n SDK.TargetManager.TargetManager.instance().observeModels(\n ExtensionStorageModel, {\n modelAdded: (model: ExtensionStorageModel) => this.extensionStorageModelAdded(model),\n modelRemoved: (model: ExtensionStorageModel) => this.extensionStorageModelRemoved(model),\n },\n {scoped: true});\n }\n\n SDK.TargetManager.TargetManager.instance().observeModels(\n IndexedDBModel, {\n modelAdded: (model: IndexedDBModel) => this.indexedDBModelAdded(model),\n modelRemoved: (model: IndexedDBModel) => this.indexedDBModelRemoved(model),\n },\n {scoped: true});\n SDK.TargetManager.TargetManager.instance().observeModels(\n InterestGroupStorageModel, {\n modelAdded: (model: InterestGroupStorageModel) => this.interestGroupModelAdded(model),\n modelRemoved: (model: InterestGroupStorageModel) => this.interestGroupModelRemoved(model),\n },\n {scoped: true});\n SDK.TargetManager.TargetManager.instance().observeModels(\n SharedStorageModel, {\n modelAdded: (model: SharedStorageModel) => this.sharedStorageModelAdded(model).catch(err => {\n console.error(err);\n }),\n modelRemoved: (model: SharedStorageModel) => this.sharedStorageModelRemoved(model),\n },\n {scoped: true});\n SDK.TargetManager.TargetManager.instance().observeModels(\n SDK.StorageBucketsModel.StorageBucketsModel, {\n modelAdded: (model: SDK.StorageBucketsModel.StorageBucketsModel) => this.storageBucketsModelAdded(model),\n modelRemoved: (model: SDK.StorageBucketsModel.StorageBucketsModel) => this.storageBucketsModelRemoved(model),\n },\n {scoped: true});\n\n this.sharedStorageTreeElementDispatcher =\n new Common.ObjectWrapper.ObjectWrapper();\n\n // Work-around for crbug.com/1152713: Something is wrong with custom scrollbars and size containment.\n // @ts-ignore\n this.contentElement.style.contain = 'layout style';\n }\n\n private addSidebarSection(title: string, jslogContext: string): UI.TreeOutline.TreeElement {\n const treeElement = new UI.TreeOutline.TreeElement(title, true, jslogContext);\n treeElement.listItemElement.classList.add('storage-group-list-item');\n treeElement.setCollapsible(false);\n treeElement.selectable = false;\n this.sidebarTree.appendChild(treeElement);\n UI.ARIAUtils.markAsHeading(treeElement.listItemElement, 3);\n UI.ARIAUtils.setLabel(treeElement.childrenListElement, title);\n return treeElement;\n }\n\n targetAdded(target: SDK.Target.Target): void {\n if (target !== target.outermostTarget()) {\n return;\n }\n\n this.target = target;\n\n const interestGroupModel = target.model(InterestGroupStorageModel);\n if (interestGroupModel) {\n interestGroupModel.addEventListener(\n InterestGroupModelEvents.INTEREST_GROUP_ACCESS, this.interestGroupAccess, this);\n }\n\n const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel);\n if (!resourceTreeModel) {\n return;\n }\n\n if (resourceTreeModel.cachedResourcesLoaded()) {\n this.initialize();\n }\n\n resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.CachedResourcesLoaded, this.initialize, this);\n resourceTreeModel.addEventListener(\n SDK.ResourceTreeModel.Events.WillLoadCachedResources, this.resetWithFrames, this);\n }\n\n targetRemoved(target: SDK.Target.Target): void {\n if (target !== this.target) {\n return;\n }\n delete this.target;\n\n const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel);\n if (resourceTreeModel) {\n resourceTreeModel.removeEventListener(SDK.ResourceTreeModel.Events.CachedResourcesLoaded, this.initialize, this);\n resourceTreeModel.removeEventListener(\n SDK.ResourceTreeModel.Events.WillLoadCachedResources, this.resetWithFrames, this);\n }\n\n const interestGroupModel = target.model(InterestGroupStorageModel);\n if (interestGroupModel) {\n interestGroupModel.removeEventListener(\n InterestGroupModelEvents.INTEREST_GROUP_ACCESS, this.interestGroupAccess, this);\n }\n\n this.resetWithFrames();\n }\n\n override focus(): void {\n this.sidebarTree.focus();\n }\n\n private initialize(): void {\n for (const frame of SDK.ResourceTreeModel.ResourceTreeModel.frames()) {\n this.addCookieDocument(frame);\n }\n const interestGroupModel = this.target && this.target.model(InterestGroupStorageModel);\n if (interestGroupModel) {\n interestGroupModel.enable();\n }\n\n this.cacheStorageListTreeElement.initialize();\n const backgroundServiceModel = this.target && this.target.model(BackgroundServiceModel) || null;\n this.backgroundFetchTreeElement && this.backgroundFetchTreeElement.initialize(backgroundServiceModel);\n this.backgroundSyncTreeElement && this.backgroundSyncTreeElement.initialize(backgroundServiceModel);\n this.notificationsTreeElement.initialize(backgroundServiceModel);\n this.paymentHandlerTreeElement.initialize(backgroundServiceModel);\n this.periodicBackgroundSyncTreeElement.initialize(backgroundServiceModel);\n this.pushMessagingTreeElement.initialize(backgroundServiceModel);\n this.storageBucketsTreeElement?.initialize();\n\n const preloadingModel = this.target?.model(SDK.PreloadingModel.PreloadingModel);\n if (preloadingModel) {\n this.preloadingSummaryTreeElement?.initialize(preloadingModel);\n }\n }\n\n private domStorageModelAdded(model: DOMStorageModel): void {\n model.enable();\n model.storages().forEach(this.addDOMStorage.bind(this));\n model.addEventListener(DOMStorageModelEvents.DOM_STORAGE_ADDED, this.domStorageAdded, this);\n model.addEventListener(DOMStorageModelEvents.DOM_STORAGE_REMOVED, this.domStorageRemoved, this);\n }\n\n private domStorageModelRemoved(model: DOMStorageModel): void {\n model.storages().forEach(this.removeDOMStorage.bind(this));\n model.removeEventListener(DOMStorageModelEvents.DOM_STORAGE_ADDED, this.domStorageAdded, this);\n model.removeEventListener(DOMStorageModelEvents.DOM_STORAGE_REMOVED, this.domStorageRemoved, this);\n }\n\n private extensionStorageModelAdded(model: ExtensionStorageModel): void {\n model.enable();\n model.storages().forEach(this.addExtensionStorage.bind(this));\n model.addEventListener(ExtensionStorageModelEvents.EXTENSION_STORAGE_ADDED, this.extensionStorageAdded, this);\n model.addEventListener(ExtensionStorageModelEvents.EXTENSION_STORAGE_REMOVED, this.extensionStorageRemoved, this);\n }\n\n private extensionStorageModelRemoved(model: ExtensionStorageModel): void {\n model.storages().forEach(this.removeExtensionStorage.bind(this));\n model.removeEventListener(ExtensionStorageModelEvents.EXTENSION_STORAGE_ADDED, this.extensionStorageAdded, this);\n model.removeEventListener(\n ExtensionStorageModelEvents.EXTENSION_STORAGE_REMOVED, this.extensionStorageRemoved, this);\n }\n\n private indexedDBModelAdded(model: IndexedDBModel): void {\n model.enable();\n this.indexedDBListTreeElement.addIndexedDBForModel(model);\n }\n\n private indexedDBModelRemoved(model: IndexedDBModel): void {\n this.indexedDBListTreeElement.removeIndexedDBForModel(model);\n }\n\n private interestGroupModelAdded(model: InterestGroupStorageModel): void {\n model.enable();\n model.addEventListener(InterestGroupModelEvents.INTEREST_GROUP_ACCESS, this.interestGroupAccess, this);\n }\n\n private interestGroupModelRemoved(model: InterestGroupStorageModel): void {\n model.disable();\n model.removeEventListener(InterestGroupModelEvents.INTEREST_GROUP_ACCESS, this.interestGroupAccess, this);\n }\n\n private async sharedStorageModelAdded(model: SharedStorageModel): Promise {\n await model.enable();\n for (const storage of model.storages()) {\n await this.addSharedStorage(storage);\n }\n model.addEventListener(SharedStorageModelEvents.SHARED_STORAGE_ADDED, this.sharedStorageAdded, this);\n model.addEventListener(SharedStorageModelEvents.SHARED_STORAGE_REMOVED, this.sharedStorageRemoved, this);\n model.addEventListener(SharedStorageModelEvents.SHARED_STORAGE_ACCESS, this.sharedStorageAccess, this);\n }\n\n private sharedStorageModelRemoved(model: SharedStorageModel): void {\n model.disable();\n for (const storage of model.storages()) {\n this.removeSharedStorage(storage);\n }\n model.removeEventListener(SharedStorageModelEvents.SHARED_STORAGE_ADDED, this.sharedStorageAdded, this);\n model.removeEventListener(SharedStorageModelEvents.SHARED_STORAGE_REMOVED, this.sharedStorageRemoved, this);\n model.removeEventListener(SharedStorageModelEvents.SHARED_STORAGE_ACCESS, this.sharedStorageAccess, this);\n }\n\n private storageBucketsModelAdded(model: SDK.StorageBucketsModel.StorageBucketsModel): void {\n model.enable();\n }\n\n private storageBucketsModelRemoved(model: SDK.StorageBucketsModel.StorageBucketsModel): void {\n this.storageBucketsTreeElement?.removeBucketsForModel(model);\n }\n\n private resetWithFrames(): void {\n this.resourcesSection.reset();\n this.reset();\n }\n\n private treeElementAdded(event: Common.EventTarget.EventTargetEvent): void {\n // On tree item selection its itemURL and those of its parents are persisted.\n // On reload/navigation we check for matches starting from the root on the\n // path to the current element. Matching nodes are expanded until we hit a\n // mismatch. This way we ensure that the longest matching path starting from\n // the root is expanded, even if we cannot match the whole path.\n const selection = this.panel.lastSelectedItemPath();\n if (!selection.length) {\n return;\n }\n const element = event.data;\n const elementPath = [element as UI.TreeOutline.TreeElement | ApplicationPanelTreeElement];\n for (let parent = element.parent as UI.TreeOutline.TreeElement | ApplicationPanelTreeElement | null;\n parent && 'itemURL' in parent && parent.itemURL; parent = parent.parent) {\n elementPath.push(parent as ApplicationPanelTreeElement);\n }\n\n let i = selection.length - 1;\n let j = elementPath.length - 1;\n while (i >= 0 && j >= 0 && selection[i] === (elementPath[j] as ApplicationPanelTreeElement).itemURL) {\n if (!elementPath[j].expanded) {\n if (i > 0) {\n elementPath[j].expand();\n }\n if (!elementPath[j].selected) {\n elementPath[j].select();\n }\n }\n i--;\n j--;\n }\n }\n\n private reset(): void {\n this.domains = {};\n this.cookieListTreeElement.removeChildren();\n this.interestGroupTreeElement.clearEvents();\n }\n\n private frameNavigated(event: Common.EventTarget.EventTargetEvent): void {\n const frame = event.data;\n\n if (frame.isOutermostFrame()) {\n this.reset();\n }\n this.addCookieDocument(frame);\n }\n\n private interestGroupAccess(event: Common.EventTarget.EventTargetEvent):\n void {\n this.interestGroupTreeElement.addEvent(event.data);\n }\n\n private addCookieDocument(frame: SDK.ResourceTreeModel.ResourceTreeFrame): void {\n // In case the current frame was unreachable, show its cookies\n // instead of the error interstitials because they might help to\n // debug why the frame was unreachable.\n const urlToParse = frame.unreachableUrl() || frame.url;\n const parsedURL = Common.ParsedURL.ParsedURL.fromString(urlToParse);\n if (!parsedURL || (parsedURL.scheme !== 'http' && parsedURL.scheme !== 'https' && parsedURL.scheme !== 'file')) {\n return;\n }\n\n const domain = parsedURL.securityOrigin();\n if (!this.domains[domain]) {\n this.domains[domain] = true;\n const cookieDomainTreeElement = new CookieTreeElement(this.panel, frame, parsedURL);\n this.cookieListTreeElement.appendChild(cookieDomainTreeElement);\n }\n }\n\n private domStorageAdded(event: Common.EventTarget.EventTargetEvent): void {\n const domStorage = (event.data as DOMStorage);\n this.addDOMStorage(domStorage);\n }\n\n private addDOMStorage(domStorage: DOMStorage): void {\n console.assert(!this.domStorageTreeElements.get(domStorage));\n console.assert(Boolean(domStorage.storageKey));\n\n const domStorageTreeElement = new DOMStorageTreeElement(this.panel, domStorage);\n this.domStorageTreeElements.set(domStorage, domStorageTreeElement);\n if (domStorage.isLocalStorage) {\n this.localStorageListTreeElement.appendChild(domStorageTreeElement, comparator);\n } else {\n this.sessionStorageListTreeElement.appendChild(domStorageTreeElement, comparator);\n }\n\n function comparator(a: UI.TreeOutline.TreeElement, b: UI.TreeOutline.TreeElement): number {\n const aTitle = a.titleAsText().toLocaleLowerCase();\n const bTitle = b.titleAsText().toLocaleUpperCase();\n return aTitle.localeCompare(bTitle);\n }\n }\n\n private domStorageRemoved(event: Common.EventTarget.EventTargetEvent): void {\n const domStorage = (event.data as DOMStorage);\n this.removeDOMStorage(domStorage);\n }\n\n private removeDOMStorage(domStorage: DOMStorage): void {\n const treeElement = this.domStorageTreeElements.get(domStorage);\n if (!treeElement) {\n return;\n }\n const wasSelected = treeElement.selected;\n const parentListTreeElement = treeElement.parent;\n if (parentListTreeElement) {\n parentListTreeElement.removeChild(treeElement);\n if (wasSelected) {\n parentListTreeElement.select();\n }\n }\n this.domStorageTreeElements.delete(domStorage);\n }\n\n private extensionStorageAdded(event: Common.EventTarget.EventTargetEvent): void {\n const extensionStorage = event.data;\n this.addExtensionStorage(extensionStorage);\n }\n\n private addExtensionStorage(extensionStorage: ExtensionStorage): void {\n console.assert(Boolean(this.extensionStorageListTreeElement));\n console.assert(!this.extensionStorageTreeElements.get(extensionStorage));\n\n const extensionStorageTreeElement = new ExtensionStorageTreeElement(this.panel, extensionStorage);\n this.extensionStorageTreeElements.set(extensionStorage, extensionStorageTreeElement);\n this.extensionStorageListTreeElement?.appendChild(extensionStorageTreeElement, comparator);\n\n function comparator(a: UI.TreeOutline.TreeElement, b: UI.TreeOutline.TreeElement): number {\n const aTitle = a.titleAsText().toLocaleLowerCase();\n const bTitle = b.titleAsText().toLocaleUpperCase();\n return aTitle.localeCompare(bTitle);\n }\n }\n\n private extensionStorageRemoved(event: Common.EventTarget.EventTargetEvent): void {\n const extensionStorage = event.data;\n this.removeExtensionStorage(extensionStorage);\n }\n\n private removeExtensionStorage(extensionStorage: ExtensionStorage): void {\n const treeElement = this.extensionStorageTreeElements.get(extensionStorage);\n if (!treeElement) {\n return;\n }\n const wasSelected = treeElement.selected;\n const parentListTreeElement = treeElement.parent;\n if (parentListTreeElement) {\n parentListTreeElement.removeChild(treeElement);\n if (wasSelected) {\n parentListTreeElement.select();\n }\n }\n this.extensionStorageTreeElements.delete(extensionStorage);\n }\n\n private async sharedStorageAdded(event: Common.EventTarget.EventTargetEvent): Promise {\n await this.addSharedStorage(event.data);\n }\n\n private async addSharedStorage(sharedStorage: SharedStorageForOrigin): Promise {\n const sharedStorageTreeElement = await SharedStorageTreeElement.createElement(this.panel, sharedStorage);\n\n // A tree element for `sharedStorage.securityOrigin` may have been added while we were waiting for `sharedStorageTreeElement` to be created.\n if (this.sharedStorageTreeElements.has(sharedStorage.securityOrigin)) {\n return;\n }\n this.sharedStorageTreeElements.set(sharedStorage.securityOrigin, sharedStorageTreeElement);\n this.sharedStorageListTreeElement.appendChild(sharedStorageTreeElement);\n this.sharedStorageTreeElementDispatcher.dispatchEventToListeners(\n SharedStorageTreeElementDispatcher.Events.SHARED_STORAGE_TREE_ELEMENT_ADDED,\n {origin: sharedStorage.securityOrigin});\n }\n\n private sharedStorageRemoved(event: Common.EventTarget.EventTargetEvent): void {\n this.removeSharedStorage(event.data);\n }\n\n private removeSharedStorage(sharedStorage: SharedStorageForOrigin): void {\n const treeElement = this.sharedStorageTreeElements.get(sharedStorage.securityOrigin);\n if (!treeElement) {\n return;\n }\n const wasSelected = treeElement.selected;\n const parentListTreeElement = treeElement.parent;\n if (parentListTreeElement) {\n parentListTreeElement.removeChild(treeElement);\n parentListTreeElement.setExpandable(parentListTreeElement.childCount() > 0);\n if (wasSelected) {\n parentListTreeElement.select();\n }\n }\n this.sharedStorageTreeElements.delete(sharedStorage.securityOrigin);\n }\n\n private sharedStorageAccess(event: Common.EventTarget.EventTargetEvent):\n void {\n this.sharedStorageListTreeElement.addEvent(event.data);\n }\n\n async showResource(resource: SDK.Resource.Resource, line?: number, column?: number): Promise {\n await this.resourcesSection.revealResource(resource, line, column);\n }\n\n showFrame(frame: SDK.ResourceTreeModel.ResourceTreeFrame): void {\n this.resourcesSection.revealAndSelectFrame(frame);\n }\n\n showFileSystem(view: UI.Widget.Widget): void {\n this.innerShowView(view);\n }\n\n private innerShowView(view: UI.Widget.Widget): void {\n this.panel.showView(view);\n }\n\n showPreloadingRuleSetView(revealInfo: PreloadingHelper.PreloadingForward.RuleSetView): void {\n if (this.preloadingSummaryTreeElement) {\n this.preloadingSummaryTreeElement.expandAndRevealRuleSet(revealInfo);\n }\n }\n\n showPreloadingAttemptViewWithFilter(filter: PreloadingHelper.PreloadingForward.AttemptViewWithFilter): void {\n if (this.preloadingSummaryTreeElement) {\n this.preloadingSummaryTreeElement.expandAndRevealAttempts(filter);\n }\n }\n\n private onmousemove(event: MouseEvent): void {\n const nodeUnderMouse = (event.target as Node);\n if (!nodeUnderMouse) {\n return;\n }\n\n const listNode = UI.UIUtils.enclosingNodeOrSelfWithNodeName(nodeUnderMouse, 'li');\n if (!listNode) {\n return;\n }\n\n const element = UI.TreeOutline.TreeElement.getTreeElementBylistItemNode(listNode);\n if (this.previousHoveredElement === element) {\n return;\n }\n\n if (this.previousHoveredElement) {\n this.previousHoveredElement.hovered = false;\n delete this.previousHoveredElement;\n }\n\n if (element instanceof FrameTreeElement) {\n this.previousHoveredElement = element;\n element.hovered = true;\n }\n }\n\n private onmouseleave(_event: MouseEvent): void {\n if (this.previousHoveredElement) {\n this.previousHoveredElement.hovered = false;\n delete this.previousHoveredElement;\n }\n }\n override wasShown(): void {\n super.wasShown();\n this.sidebarTree.registerCSSFiles([resourcesSidebarStyles]);\n }\n}\n\nexport class BackgroundServiceTreeElement extends ApplicationPanelTreeElement {\n private serviceName: Protocol.BackgroundService.ServiceName;\n private view: BackgroundServiceView|null;\n private model: BackgroundServiceModel|null;\n private selectedInternal: boolean;\n\n constructor(storagePanel: ResourcesPanel, serviceName: Protocol.BackgroundService.ServiceName) {\n super(\n storagePanel, BackgroundServiceView.getUIString(serviceName), false,\n Platform.StringUtilities.toKebabCase(serviceName));\n\n this.serviceName = serviceName;\n\n /* Whether the element has been selected. */\n this.selectedInternal = false;\n\n this.view = null;\n\n this.model = null;\n\n const backgroundServiceIcon = IconButton.Icon.create(this.getIconType());\n this.setLeadingIcons([backgroundServiceIcon]);\n }\n\n private getIconType(): string {\n switch (this.serviceName) {\n case Protocol.BackgroundService.ServiceName.BackgroundFetch:\n return 'arrow-up-down';\n case Protocol.BackgroundService.ServiceName.BackgroundSync:\n return 'sync';\n case Protocol.BackgroundService.ServiceName.PushMessaging:\n return 'cloud';\n case Protocol.BackgroundService.ServiceName.Notifications:\n return 'bell';\n case Protocol.BackgroundService.ServiceName.PaymentHandler:\n return 'credit-card';\n case Protocol.BackgroundService.ServiceName.PeriodicBackgroundSync:\n return 'watch';\n default:\n console.error(`Service ${this.serviceName} does not have a dedicated icon`);\n return 'table';\n }\n }\n\n initialize(model: BackgroundServiceModel|null): void {\n this.model = model;\n // Show the view if the model was initialized after selection.\n if (this.selectedInternal && !this.view) {\n this.onselect(false);\n }\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return `background-service://${this.serviceName}` as Platform.DevToolsPath.UrlString;\n }\n\n override get selectable(): boolean {\n if (!this.model) {\n return false;\n }\n return super.selectable;\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n this.selectedInternal = true;\n\n if (!this.model) {\n return false;\n }\n\n if (!this.view) {\n this.view = new BackgroundServiceView(this.serviceName, this.model);\n }\n this.showView(this.view);\n UI.Context.Context.instance().setFlavor(BackgroundServiceView, this.view);\n Host.userMetrics.panelShown('background_service_' + this.serviceName);\n return false;\n }\n}\n\nexport class ServiceWorkersTreeElement extends ApplicationPanelTreeElement {\n private view?: ServiceWorkersView;\n\n constructor(storagePanel: ResourcesPanel) {\n super(storagePanel, i18n.i18n.lockedString('Service workers'), false, 'service-workers');\n const icon = IconButton.Icon.create('gears');\n this.setLeadingIcons([icon]);\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return 'service-workers://' as Platform.DevToolsPath.UrlString;\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n if (!this.view) {\n this.view = new ServiceWorkersView();\n }\n this.showView(this.view);\n Host.userMetrics.panelShown('service-workers');\n return false;\n }\n}\n\nexport class AppManifestTreeElement extends ApplicationPanelTreeElement {\n private view: AppManifestView;\n constructor(storagePanel: ResourcesPanel) {\n super(storagePanel, i18nString(UIStrings.manifest), true, 'manifest');\n const icon = IconButton.Icon.create('document');\n this.setLeadingIcons([icon]);\n self.onInvokeElement(this.listItemElement, this.onInvoke.bind(this));\n const emptyView = new UI.EmptyWidget.EmptyWidget(i18nString(UIStrings.noManifestDetected));\n // TODO(crbug.com/1156978): Replace UI.ReportView.ReportView with ReportView.ts web component.\n const reportView = new UI.ReportView.ReportView(i18nString(UIStrings.appManifest));\n this.view = new AppManifestView(emptyView, reportView, new Common.Throttler.Throttler(1000));\n UI.ARIAUtils.setLabel(this.listItemElement, i18nString(UIStrings.onInvokeManifestAlert));\n const handleExpansion = (hasManifest: boolean): void => {\n this.setExpandable(hasManifest);\n };\n this.view.addEventListener(AppManifestViewEvents.MANIFEST_DETECTED, event => handleExpansion(event.data));\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return 'manifest://' as Platform.DevToolsPath.UrlString;\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n this.showView(this.view);\n Host.userMetrics.panelShown('app-manifest');\n return false;\n }\n\n generateChildren(): void {\n const staticSections = this.view.getStaticSections();\n for (const section of staticSections) {\n const sectionElement = section.getTitleElement();\n const childTitle = section.title();\n const sectionFieldElement = section.getFieldElement();\n const child = new ManifestChildTreeElement(\n this.resourcesPanel, sectionElement, childTitle, sectionFieldElement, section.jslogContext || '');\n this.appendChild(child);\n }\n }\n\n onInvoke(): void {\n this.view.getManifestElement().scrollIntoView();\n UI.ARIAUtils.alert(i18nString(UIStrings.onInvokeAlert, {PH1: this.listItemElement.title}));\n }\n\n showManifestView(): void {\n this.showView(this.view);\n }\n}\n\nexport class ManifestChildTreeElement extends ApplicationPanelTreeElement {\n #sectionElement: Element;\n #sectionFieldElement: HTMLElement;\n constructor(\n storagePanel: ResourcesPanel, element: Element, childTitle: string, fieldElement: HTMLElement,\n jslogContext: string) {\n super(storagePanel, childTitle, false, jslogContext);\n const icon = IconButton.Icon.create('document');\n this.setLeadingIcons([icon]);\n this.#sectionElement = element;\n this.#sectionFieldElement = fieldElement;\n self.onInvokeElement(this.listItemElement, this.onInvoke.bind(this));\n this.listItemElement.addEventListener('keydown', this.onInvokeElementKeydown.bind(this));\n UI.ARIAUtils.setLabel(\n this.listItemElement, i18nString(UIStrings.beforeInvokeAlert, {PH1: this.listItemElement.title}));\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return 'manifest://' + this.title as Platform.DevToolsPath.UrlString;\n }\n\n onInvoke(): void {\n (this.parent as AppManifestTreeElement)?.showManifestView();\n this.#sectionElement.scrollIntoView();\n UI.ARIAUtils.alert(i18nString(UIStrings.onInvokeAlert, {PH1: this.listItemElement.title}));\n Host.userMetrics.manifestSectionSelected(this.listItemElement.title);\n }\n // direct focus to the corresponding element\n onInvokeElementKeydown(event: KeyboardEvent): void {\n if (event.key !== 'Tab' || event.shiftKey) {\n return;\n }\n const checkBoxElement = this.#sectionFieldElement.querySelector('.mask-checkbox');\n let focusableElement: HTMLElement|null = this.#sectionFieldElement.querySelector('[tabindex=\"0\"]');\n if (checkBoxElement && checkBoxElement.shadowRoot) {\n focusableElement = checkBoxElement.shadowRoot.querySelector('input') || null;\n } else if (!focusableElement) {\n // special case for protocol handler section since it is a custom Element and has different structure than the others\n focusableElement = this.#sectionFieldElement.querySelector('devtools-protocol-handlers-view')\n ?.shadowRoot?.querySelector('[tabindex=\"0\"]') ||\n null;\n }\n if (focusableElement) {\n focusableElement?.focus();\n event.consume(true);\n }\n }\n}\n\nexport class ClearStorageTreeElement extends ApplicationPanelTreeElement {\n private view?: StorageView;\n constructor(storagePanel: ResourcesPanel) {\n super(storagePanel, i18nString(UIStrings.storage), false, 'storage');\n const icon = IconButton.Icon.create('database');\n this.setLeadingIcons([icon]);\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return 'clear-storage://' as Platform.DevToolsPath.UrlString;\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n if (!this.view) {\n this.view = new StorageView();\n }\n this.showView(this.view);\n Host.userMetrics.panelShown(Host.UserMetrics.PanelCodes[Host.UserMetrics.PanelCodes.storage]);\n return false;\n }\n}\n\nexport class IndexedDBTreeElement extends ExpandableApplicationPanelTreeElement {\n private idbDatabaseTreeElements: IDBDatabaseTreeElement[];\n private storageBucket?: Protocol.Storage.StorageBucket;\n constructor(storagePanel: ResourcesPanel, storageBucket?: Protocol.Storage.StorageBucket) {\n super(storagePanel, i18nString(UIStrings.indexeddb), 'indexed-db');\n const icon = IconButton.Icon.create('database');\n this.setLeadingIcons([icon]);\n this.idbDatabaseTreeElements = [];\n this.storageBucket = storageBucket;\n this.initialize();\n }\n\n private initialize(): void {\n SDK.TargetManager.TargetManager.instance().addModelListener(\n IndexedDBModel, IndexedDBModelEvents.DatabaseAdded, this.indexedDBAdded, this, {scoped: true});\n SDK.TargetManager.TargetManager.instance().addModelListener(\n IndexedDBModel, IndexedDBModelEvents.DatabaseRemoved, this.indexedDBRemoved, this, {scoped: true});\n SDK.TargetManager.TargetManager.instance().addModelListener(\n IndexedDBModel, IndexedDBModelEvents.DatabaseLoaded, this.indexedDBLoaded, this, {scoped: true});\n SDK.TargetManager.TargetManager.instance().addModelListener(\n IndexedDBModel, IndexedDBModelEvents.IndexedDBContentUpdated, this.indexedDBContentUpdated, this,\n {scoped: true});\n // TODO(szuend): Replace with a Set once two web tests no longer directly access this private\n // variable (indexeddb/live-update-indexeddb-content.js, indexeddb/delete-entry.js).\n this.idbDatabaseTreeElements = [];\n\n for (const indexedDBModel of SDK.TargetManager.TargetManager.instance().models(IndexedDBModel, {scoped: true})) {\n const databases = indexedDBModel.databases();\n for (let j = 0; j < databases.length; ++j) {\n this.addIndexedDB(indexedDBModel, databases[j]);\n }\n }\n }\n\n addIndexedDBForModel(model: IndexedDBModel): void {\n for (const databaseId of model.databases()) {\n this.addIndexedDB(model, databaseId);\n }\n }\n\n removeIndexedDBForModel(model: IndexedDBModel): void {\n const idbDatabaseTreeElements = this.idbDatabaseTreeElements.filter(element => element.model === model);\n for (const idbDatabaseTreeElement of idbDatabaseTreeElements) {\n this.removeIDBDatabaseTreeElement(idbDatabaseTreeElement);\n }\n }\n\n override onattach(): void {\n super.onattach();\n this.listItemElement.addEventListener('contextmenu', this.handleContextMenuEvent.bind(this), true);\n }\n\n private handleContextMenuEvent(event: MouseEvent): void {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.refreshIndexeddb), this.refreshIndexedDB.bind(this), {jslogContext: 'refresh-indexeddb'});\n void contextMenu.show();\n }\n\n refreshIndexedDB(): void {\n for (const indexedDBModel of SDK.TargetManager.TargetManager.instance().models(IndexedDBModel, {scoped: true})) {\n void indexedDBModel.refreshDatabaseNames();\n }\n }\n\n private databaseInTree(databaseId: DatabaseId): boolean {\n if (this.storageBucket) {\n return databaseId.inBucket(this.storageBucket);\n }\n return true;\n }\n\n private indexedDBAdded({\n data: {databaseId, model},\n }: Common.EventTarget.EventTargetEvent<{databaseId: DatabaseId, model: IndexedDBModel}>): void {\n this.addIndexedDB(model, databaseId);\n }\n\n private addIndexedDB(model: IndexedDBModel, databaseId: DatabaseId): void {\n if (!this.databaseInTree(databaseId)) {\n return;\n }\n const idbDatabaseTreeElement = new IDBDatabaseTreeElement(this.resourcesPanel, model, databaseId);\n this.idbDatabaseTreeElements.push(idbDatabaseTreeElement);\n this.appendChild(idbDatabaseTreeElement);\n model.refreshDatabase(databaseId);\n }\n\n private indexedDBRemoved({\n data: {databaseId, model},\n }: Common.EventTarget.EventTargetEvent<{databaseId: DatabaseId, model: IndexedDBModel}>): void {\n const idbDatabaseTreeElement = this.idbDatabaseTreeElement(model, databaseId);\n if (!idbDatabaseTreeElement) {\n return;\n }\n this.removeIDBDatabaseTreeElement(idbDatabaseTreeElement);\n }\n\n private removeIDBDatabaseTreeElement(idbDatabaseTreeElement: IDBDatabaseTreeElement): void {\n idbDatabaseTreeElement.clear();\n this.removeChild(idbDatabaseTreeElement);\n Platform.ArrayUtilities.removeElement(this.idbDatabaseTreeElements, idbDatabaseTreeElement);\n this.setExpandable(this.childCount() > 0);\n }\n\n private indexedDBLoaded(\n {data: {database, model, entriesUpdated}}: Common.EventTarget\n .EventTargetEvent<{database: IndexedDBModelDatabase, model: IndexedDBModel, entriesUpdated: boolean}>): void {\n const idbDatabaseTreeElement = this.idbDatabaseTreeElement(model, database.databaseId);\n if (!idbDatabaseTreeElement) {\n return;\n }\n idbDatabaseTreeElement.update(database, entriesUpdated);\n this.indexedDBLoadedForTest();\n }\n\n private indexedDBLoadedForTest(): void {\n // For sniffing in tests.\n }\n\n private indexedDBContentUpdated({\n data: {databaseId, objectStoreName, model},\n }: Common.EventTarget.EventTargetEvent<{databaseId: DatabaseId, objectStoreName: string, model: IndexedDBModel}>):\n void {\n const idbDatabaseTreeElement = this.idbDatabaseTreeElement(model, databaseId);\n if (!idbDatabaseTreeElement) {\n return;\n }\n idbDatabaseTreeElement.indexedDBContentUpdated(objectStoreName);\n }\n\n private idbDatabaseTreeElement(model: IndexedDBModel, databaseId: DatabaseId): IDBDatabaseTreeElement|null {\n return this.idbDatabaseTreeElements.find(x => x.databaseId.equals(databaseId) && x.model === model) || null;\n }\n}\n\nexport class IDBDatabaseTreeElement extends ApplicationPanelTreeElement {\n model: IndexedDBModel;\n databaseId: DatabaseId;\n private readonly idbObjectStoreTreeElements: Map;\n private database?: IndexedDBModelDatabase;\n private view?: LegacyWrapper.LegacyWrapper.LegacyWrapper;\n\n constructor(storagePanel: ResourcesPanel, model: IndexedDBModel, databaseId: DatabaseId) {\n super(storagePanel, databaseId.name, false, 'indexed-db-database');\n this.model = model;\n this.databaseId = databaseId;\n this.idbObjectStoreTreeElements = new Map();\n const icon = IconButton.Icon.create('database');\n this.setLeadingIcons([icon]);\n this.model.addEventListener(IndexedDBModelEvents.DatabaseNamesRefreshed, this.refreshIndexedDB, this);\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return 'indexedDB://' + this.databaseId.storageBucket.storageKey + '/' +\n (this.databaseId.storageBucket.name ?? '') + '/' + this.databaseId.name as Platform.DevToolsPath.UrlString;\n }\n\n override onattach(): void {\n super.onattach();\n this.listItemElement.addEventListener('contextmenu', this.handleContextMenuEvent.bind(this), true);\n }\n\n private handleContextMenuEvent(event: MouseEvent): void {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.refreshIndexeddb), this.refreshIndexedDB.bind(this), {jslogContext: 'refresh-indexeddb'});\n void contextMenu.show();\n }\n\n private refreshIndexedDB(): void {\n this.model.refreshDatabase(this.databaseId);\n }\n\n indexedDBContentUpdated(objectStoreName: string): void {\n const treeElement = this.idbObjectStoreTreeElements.get(objectStoreName);\n if (treeElement) {\n treeElement.markNeedsRefresh();\n }\n }\n\n update(database: IndexedDBModelDatabase, entriesUpdated: boolean): void {\n this.database = database;\n const objectStoreNames = new Set();\n for (const objectStoreName of [...this.database.objectStores.keys()].sort()) {\n const objectStore = this.database.objectStores.get(objectStoreName);\n if (!objectStore) {\n continue;\n }\n objectStoreNames.add(objectStore.name);\n let treeElement = this.idbObjectStoreTreeElements.get(objectStore.name);\n if (!treeElement) {\n treeElement = new IDBObjectStoreTreeElement(this.resourcesPanel, this.model, this.databaseId, objectStore);\n this.idbObjectStoreTreeElements.set(objectStore.name, treeElement);\n this.appendChild(treeElement);\n }\n treeElement.update(objectStore, entriesUpdated);\n }\n for (const objectStoreName of this.idbObjectStoreTreeElements.keys()) {\n if (!objectStoreNames.has(objectStoreName)) {\n this.objectStoreRemoved(objectStoreName);\n }\n }\n\n if (this.view) {\n this.view.getComponent().update(database);\n }\n\n this.updateTooltip();\n }\n\n private updateTooltip(): void {\n const version = this.database ? this.database.version : '-';\n if (Object.keys(this.idbObjectStoreTreeElements).length === 0) {\n this.tooltip = i18nString(UIStrings.versionSEmpty, {PH1: version});\n } else {\n this.tooltip = i18nString(UIStrings.versionS, {PH1: version});\n }\n }\n\n override get selectable(): boolean {\n if (!this.database) {\n return false;\n }\n return super.selectable;\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n if (!this.database) {\n return false;\n }\n if (!this.view) {\n this.view = LegacyWrapper.LegacyWrapper.legacyWrapper(\n UI.Widget.VBox, new IDBDatabaseView(this.model, this.database), 'indexeddb-data');\n }\n\n this.showView(this.view);\n Host.userMetrics.panelShown('indexed-db');\n return false;\n }\n\n private objectStoreRemoved(objectStoreName: string): void {\n const objectStoreTreeElement = this.idbObjectStoreTreeElements.get(objectStoreName);\n if (objectStoreTreeElement) {\n objectStoreTreeElement.clear();\n this.removeChild(objectStoreTreeElement);\n }\n this.idbObjectStoreTreeElements.delete(objectStoreName);\n this.updateTooltip();\n }\n\n clear(): void {\n for (const objectStoreName of this.idbObjectStoreTreeElements.keys()) {\n this.objectStoreRemoved(objectStoreName);\n }\n }\n}\n\nexport class IDBObjectStoreTreeElement extends ApplicationPanelTreeElement {\n private model: IndexedDBModel;\n private databaseId: DatabaseId;\n private readonly idbIndexTreeElements: Map;\n private objectStore: ObjectStore;\n private view: IDBDataView|null;\n\n constructor(storagePanel: ResourcesPanel, model: IndexedDBModel, databaseId: DatabaseId, objectStore: ObjectStore) {\n super(storagePanel, objectStore.name, false, 'indexed-db-object-store');\n this.model = model;\n this.databaseId = databaseId;\n this.idbIndexTreeElements = new Map();\n this.objectStore = objectStore;\n this.view = null;\n const icon = IconButton.Icon.create('table');\n this.setLeadingIcons([icon]);\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return 'indexedDB://' + this.databaseId.storageBucket.storageKey + '/' +\n (this.databaseId.storageBucket.name ?? '') + '/' + this.databaseId.name + '/' +\n this.objectStore.name as Platform.DevToolsPath.UrlString;\n }\n\n override onattach(): void {\n super.onattach();\n this.listItemElement.addEventListener('contextmenu', this.handleContextMenuEvent.bind(this), true);\n }\n\n markNeedsRefresh(): void {\n if (this.view) {\n this.view.markNeedsRefresh();\n }\n for (const treeElement of this.idbIndexTreeElements.values()) {\n treeElement.markNeedsRefresh();\n }\n }\n\n private handleContextMenuEvent(event: MouseEvent): void {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.clear), this.clearObjectStore.bind(this), {jslogContext: 'clear'});\n void contextMenu.show();\n }\n\n private refreshObjectStore(): void {\n if (this.view) {\n this.view.refreshData();\n }\n for (const treeElement of this.idbIndexTreeElements.values()) {\n treeElement.refreshIndex();\n }\n }\n\n private async clearObjectStore(): Promise {\n await this.model.clearObjectStore(this.databaseId, this.objectStore.name);\n this.update(this.objectStore, true);\n }\n\n update(objectStore: ObjectStore, entriesUpdated: boolean): void {\n this.objectStore = objectStore;\n\n const indexNames = new Set();\n for (const index of this.objectStore.indexes.values()) {\n indexNames.add(index.name);\n let treeElement = this.idbIndexTreeElements.get(index.name);\n if (!treeElement) {\n treeElement = new IDBIndexTreeElement(\n this.resourcesPanel, this.model, this.databaseId, this.objectStore, index,\n this.refreshObjectStore.bind(this));\n this.idbIndexTreeElements.set(index.name, treeElement);\n this.appendChild(treeElement);\n }\n treeElement.update(this.objectStore, index, entriesUpdated);\n }\n for (const indexName of this.idbIndexTreeElements.keys()) {\n if (!indexNames.has(indexName)) {\n this.indexRemoved(indexName);\n }\n }\n for (const [indexName, treeElement] of this.idbIndexTreeElements.entries()) {\n if (!indexNames.has(indexName)) {\n this.removeChild((treeElement as IDBIndexTreeElement));\n this.idbIndexTreeElements.delete((indexName as string));\n }\n }\n\n if (this.childCount()) {\n this.expand();\n }\n\n if (this.view && entriesUpdated) {\n this.view.update(this.objectStore, null);\n }\n\n this.updateTooltip();\n }\n\n private updateTooltip(): void {\n const keyPathString = this.objectStore.keyPathString;\n let tooltipString = keyPathString !== null ? i18nString(UIStrings.keyPathS, {PH1: keyPathString}) : '';\n if (this.objectStore.autoIncrement) {\n tooltipString += '\\n' + i18n.i18n.lockedString('autoIncrement');\n }\n this.tooltip = tooltipString;\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n if (!this.view) {\n this.view =\n new IDBDataView(this.model, this.databaseId, this.objectStore, null, this.refreshObjectStore.bind(this));\n }\n\n this.showView(this.view);\n Host.userMetrics.panelShown('indexed-db');\n return false;\n }\n\n private indexRemoved(indexName: string): void {\n const indexTreeElement = this.idbIndexTreeElements.get(indexName);\n if (indexTreeElement) {\n indexTreeElement.clear();\n this.removeChild(indexTreeElement);\n }\n this.idbIndexTreeElements.delete(indexName);\n }\n\n clear(): void {\n for (const indexName of this.idbIndexTreeElements.keys()) {\n this.indexRemoved(indexName);\n }\n if (this.view) {\n this.view.clear();\n }\n }\n}\n\nexport class IDBIndexTreeElement extends ApplicationPanelTreeElement {\n private model: IndexedDBModel;\n private databaseId: DatabaseId;\n private objectStore: ObjectStore;\n private index: Index;\n private refreshObjectStore: () => void;\n private view?: IDBDataView;\n\n constructor(\n storagePanel: ResourcesPanel, model: IndexedDBModel, databaseId: DatabaseId, objectStore: ObjectStore,\n index: Index, refreshObjectStore: () => void) {\n super(storagePanel, index.name, false, 'indexed-db');\n this.model = model;\n this.databaseId = databaseId;\n this.objectStore = objectStore;\n this.index = index;\n this.refreshObjectStore = refreshObjectStore;\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return 'indexedDB://' + this.databaseId.storageBucket.storageKey + '/' +\n (this.databaseId.storageBucket.name ?? '') + '/' + this.databaseId.name + '/' + this.objectStore.name + '/' +\n this.index.name as Platform.DevToolsPath.UrlString;\n }\n\n markNeedsRefresh(): void {\n if (this.view) {\n this.view.markNeedsRefresh();\n }\n }\n\n refreshIndex(): void {\n if (this.view) {\n this.view.refreshData();\n }\n }\n\n update(objectStore: ObjectStore, index: Index, entriesUpdated: boolean): void {\n this.objectStore = objectStore;\n this.index = index;\n\n if (this.view && entriesUpdated) {\n this.view.update(this.objectStore, this.index);\n }\n\n this.updateTooltip();\n }\n\n private updateTooltip(): void {\n const tooltipLines = [];\n const keyPathString = this.index.keyPathString;\n tooltipLines.push(i18nString(UIStrings.keyPathS, {PH1: keyPathString}));\n if (this.index.unique) {\n tooltipLines.push(i18n.i18n.lockedString('unique'));\n }\n if (this.index.multiEntry) {\n tooltipLines.push(i18n.i18n.lockedString('multiEntry'));\n }\n this.tooltip = tooltipLines.join('\\n');\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n if (!this.view) {\n this.view = new IDBDataView(this.model, this.databaseId, this.objectStore, this.index, this.refreshObjectStore);\n }\n\n this.showView(this.view);\n Host.userMetrics.panelShown('indexed-db');\n return false;\n }\n\n clear(): void {\n if (this.view) {\n this.view.clear();\n }\n }\n}\n\nexport class DOMStorageTreeElement extends ApplicationPanelTreeElement {\n private readonly domStorage: DOMStorage;\n constructor(storagePanel: ResourcesPanel, domStorage: DOMStorage) {\n super(\n storagePanel,\n domStorage.storageKey ? SDK.StorageKeyManager.parseStorageKey(domStorage.storageKey).origin :\n i18nString(UIStrings.localFiles),\n false, domStorage.isLocalStorage ? 'local-storage-for-domain' : 'session-storage-for-domain');\n this.domStorage = domStorage;\n const icon = IconButton.Icon.create('table');\n this.setLeadingIcons([icon]);\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return 'storage://' + this.domStorage.storageKey + '/' + (this.domStorage.isLocalStorage ? 'local' : 'session') as\n Platform.DevToolsPath.UrlString;\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n Host.userMetrics.panelShown('dom-storage');\n this.resourcesPanel.showDOMStorage(this.domStorage);\n return false;\n }\n\n override onattach(): void {\n super.onattach();\n this.listItemElement.addEventListener('contextmenu', this.handleContextMenuEvent.bind(this), true);\n }\n\n private handleContextMenuEvent(event: MouseEvent): void {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.clear), () => this.domStorage.clear(), {jslogContext: 'clear'});\n void contextMenu.show();\n }\n}\n\nexport class ExtensionStorageTreeElement extends ApplicationPanelTreeElement {\n private readonly extensionStorage: ExtensionStorage;\n constructor(storagePanel: ResourcesPanel, extensionStorage: ExtensionStorage) {\n super(\n storagePanel, extensionStorage.name + ` (${extensionStorage.storageArea})`, false,\n 'extension-storage-for-domain');\n this.extensionStorage = extensionStorage;\n const icon = IconButton.Icon.create('table');\n this.setLeadingIcons([icon]);\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return 'storage://' + this.extensionStorage.extensionId + '/' + this.extensionStorage.storageArea as\n Platform.DevToolsPath.UrlString;\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n Host.userMetrics.panelShown('dom-storage');\n\n // TODO(crbug.com/40963428): Call this.resourcesPanel to show extension\n // storage view\n\n return false;\n }\n\n override onattach(): void {\n super.onattach();\n this.listItemElement.addEventListener('contextmenu', this.handleContextMenuEvent.bind(this), true);\n }\n\n private handleContextMenuEvent(event: MouseEvent): void {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.clear), () => this.extensionStorage.clear(), {jslogContext: 'clear'});\n void contextMenu.show();\n }\n}\n\nexport class CookieTreeElement extends ApplicationPanelTreeElement {\n private readonly target: SDK.Target.Target;\n private readonly cookieDomainInternal: string;\n\n constructor(\n storagePanel: ResourcesPanel, frame: SDK.ResourceTreeModel.ResourceTreeFrame,\n cookieUrl: Common.ParsedURL.ParsedURL) {\n super(storagePanel, cookieUrl.securityOrigin() || i18nString(UIStrings.localFiles), false, 'cookies-for-frame');\n this.target = frame.resourceTreeModel().target();\n this.cookieDomainInternal = cookieUrl.securityOrigin();\n this.tooltip = i18nString(UIStrings.cookiesUsedByFramesFromS, {PH1: this.cookieDomainInternal});\n const icon = IconButton.Icon.create('cookie');\n // Note that we cannot use `cookieDomainInternal` here since it contains scheme.\n if (IssuesManager.RelatedIssue.hasThirdPartyPhaseoutCookieIssueForDomain(cookieUrl.domain())) {\n icon.name = 'warning-filled';\n icon.classList.add('warn-icon');\n this.tooltip = i18nString(UIStrings.thirdPartyPhaseout, {PH1: this.cookieDomainInternal});\n }\n this.setLeadingIcons([icon]);\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return 'cookies://' + this.cookieDomainInternal as Platform.DevToolsPath.UrlString;\n }\n\n cookieDomain(): string {\n return this.cookieDomainInternal;\n }\n\n override onattach(): void {\n super.onattach();\n this.listItemElement.addEventListener('contextmenu', this.handleContextMenuEvent.bind(this), true);\n }\n\n private handleContextMenuEvent(event: Event): void {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.clear), () => this.resourcesPanel.clearCookies(this.target, this.cookieDomainInternal),\n {jslogContext: 'clear'});\n void contextMenu.show();\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n this.resourcesPanel.showCookies(this.target, this.cookieDomainInternal);\n Host.userMetrics.panelShown(Host.UserMetrics.PanelCodes[Host.UserMetrics.PanelCodes.cookies]);\n return false;\n }\n}\n\nexport class StorageCategoryView extends UI.Widget.VBox {\n private emptyWidget: UI.EmptyWidget.EmptyWidget;\n private linkElement: HTMLElement|null;\n\n constructor() {\n super();\n\n this.element.classList.add('storage-view');\n this.emptyWidget = new UI.EmptyWidget.EmptyWidget('');\n this.linkElement = null;\n this.emptyWidget.show(this.element);\n }\n\n setText(text: string): void {\n this.emptyWidget.text = text;\n }\n\n setLink(link: Platform.DevToolsPath.UrlString|null): void {\n if (link && !this.linkElement) {\n this.linkElement = this.emptyWidget.appendLink(link);\n }\n if (!link && this.linkElement) {\n this.linkElement.classList.add('hidden');\n }\n if (link && this.linkElement) {\n this.linkElement.setAttribute('href', link);\n this.linkElement.classList.remove('hidden');\n }\n }\n}\n\nexport class ResourcesSection implements SDK.TargetManager.Observer {\n panel: ResourcesPanel;\n private readonly treeElement: UI.TreeOutline.TreeElement;\n private treeElementForFrameId: Map;\n private treeElementForTargetId: Map;\n\n constructor(storagePanel: ResourcesPanel, treeElement: UI.TreeOutline.TreeElement) {\n this.panel = storagePanel;\n this.treeElement = treeElement;\n UI.ARIAUtils.setLabel(this.treeElement.listItemNode, 'Resources Section');\n this.treeElementForFrameId = new Map();\n this.treeElementForTargetId = new Map();\n\n const frameManager = SDK.FrameManager.FrameManager.instance();\n frameManager.addEventListener(\n SDK.FrameManager.Events.FRAME_ADDED_TO_TARGET, event => this.frameAdded(event.data.frame), this);\n frameManager.addEventListener(\n SDK.FrameManager.Events.FRAME_REMOVED, event => this.frameDetached(event.data.frameId), this);\n frameManager.addEventListener(\n SDK.FrameManager.Events.FRAME_NAVIGATED, event => this.frameNavigated(event.data.frame), this);\n frameManager.addEventListener(\n SDK.FrameManager.Events.RESOURCE_ADDED, event => this.resourceAdded(event.data.resource), this);\n\n SDK.TargetManager.TargetManager.instance().addModelListener(\n SDK.ChildTargetManager.ChildTargetManager, SDK.ChildTargetManager.Events.TARGET_CREATED, this.windowOpened,\n this, {scoped: true});\n SDK.TargetManager.TargetManager.instance().addModelListener(\n SDK.ChildTargetManager.ChildTargetManager, SDK.ChildTargetManager.Events.TARGET_INFO_CHANGED,\n this.windowChanged, this, {scoped: true});\n SDK.TargetManager.TargetManager.instance().addModelListener(\n SDK.ChildTargetManager.ChildTargetManager, SDK.ChildTargetManager.Events.TARGET_DESTROYED, this.windowDestroyed,\n this, {scoped: true});\n\n SDK.TargetManager.TargetManager.instance().observeTargets(this, {scoped: true});\n }\n\n private initialize(): void {\n const frameManager = SDK.FrameManager.FrameManager.instance();\n for (const frame of frameManager.getAllFrames()) {\n if (!this.treeElementForFrameId.get(frame.id)) {\n this.addFrameAndParents(frame);\n }\n const childTargetManager = frame.resourceTreeModel().target().model(SDK.ChildTargetManager.ChildTargetManager);\n if (childTargetManager) {\n for (const targetInfo of childTargetManager.targetInfos()) {\n this.windowOpened({data: targetInfo});\n }\n }\n }\n }\n\n targetAdded(target: SDK.Target.Target): void {\n if (target.type() === SDK.Target.Type.Worker || target.type() === SDK.Target.Type.ServiceWorker) {\n void this.workerAdded(target);\n }\n if (target.type() === SDK.Target.Type.FRAME && target === target.outermostTarget()) {\n // Process existing frames, e.g. after prerendering activation or\n // switching between outermost targets.\n this.initialize();\n }\n }\n\n private async workerAdded(target: SDK.Target.Target): Promise {\n const parentTarget = target.parentTarget();\n if (!parentTarget) {\n return;\n }\n const parentTargetId = parentTarget.id();\n const frameTreeElement = this.treeElementForTargetId.get(parentTargetId);\n const targetId = target.id();\n assertNotMainTarget(targetId);\n const {targetInfo} = await parentTarget.targetAgent().invoke_getTargetInfo({targetId});\n if (frameTreeElement && targetInfo) {\n frameTreeElement.workerCreated(targetInfo);\n }\n }\n\n targetRemoved(_target: SDK.Target.Target): void {\n }\n\n private addFrameAndParents(frame: SDK.ResourceTreeModel.ResourceTreeFrame): void {\n const parentFrame = frame.parentFrame();\n if (parentFrame && !this.treeElementForFrameId.get(parentFrame.id)) {\n this.addFrameAndParents(parentFrame);\n }\n this.frameAdded(frame);\n }\n\n private expandFrame(frame: SDK.ResourceTreeModel.ResourceTreeFrame|null): boolean {\n if (!frame) {\n return false;\n }\n let treeElement = this.treeElementForFrameId.get(frame.id);\n if (!treeElement && !this.expandFrame(frame.parentFrame())) {\n return false;\n }\n treeElement = this.treeElementForFrameId.get(frame.id);\n if (!treeElement) {\n return false;\n }\n treeElement.expand();\n return true;\n }\n\n async revealResource(resource: SDK.Resource.Resource, line?: number, column?: number): Promise {\n if (!this.expandFrame(resource.frame())) {\n return;\n }\n const resourceTreeElement = FrameResourceTreeElement.forResource(resource);\n if (resourceTreeElement) {\n await resourceTreeElement.revealResource(line, column);\n }\n }\n\n revealAndSelectFrame(frame: SDK.ResourceTreeModel.ResourceTreeFrame): void {\n const frameTreeElement = this.treeElementForFrameId.get(frame.id);\n frameTreeElement?.reveal();\n frameTreeElement?.select();\n }\n\n private frameAdded(frame: SDK.ResourceTreeModel.ResourceTreeFrame): void {\n if (!SDK.TargetManager.TargetManager.instance().isInScope(frame.resourceTreeModel())) {\n return;\n }\n const parentFrame = frame.parentFrame();\n const parentTreeElement = parentFrame ? this.treeElementForFrameId.get(parentFrame.id) : this.treeElement;\n if (!parentTreeElement) {\n return;\n }\n\n const existingElement = this.treeElementForFrameId.get(frame.id);\n if (existingElement) {\n this.treeElementForFrameId.delete(frame.id);\n if (existingElement.parent) {\n existingElement.parent.removeChild(existingElement);\n }\n }\n\n const frameTreeElement = new FrameTreeElement(this, frame);\n this.treeElementForFrameId.set(frame.id, frameTreeElement);\n const targetId = frame.resourceTreeModel().target().id();\n if (!this.treeElementForTargetId.get(targetId)) {\n this.treeElementForTargetId.set(targetId, frameTreeElement);\n }\n parentTreeElement.appendChild(frameTreeElement);\n\n for (const resource of frame.resources()) {\n this.resourceAdded(resource);\n }\n }\n\n private frameDetached(frameId: Protocol.Page.FrameId): void {\n const frameTreeElement = this.treeElementForFrameId.get(frameId);\n if (!frameTreeElement) {\n return;\n }\n\n this.treeElementForFrameId.delete(frameId);\n if (frameTreeElement.parent) {\n frameTreeElement.parent.removeChild(frameTreeElement);\n }\n }\n\n private frameNavigated(frame: SDK.ResourceTreeModel.ResourceTreeFrame): void {\n if (!SDK.TargetManager.TargetManager.instance().isInScope(frame.resourceTreeModel())) {\n return;\n }\n const frameTreeElement = this.treeElementForFrameId.get(frame.id);\n if (frameTreeElement) {\n void frameTreeElement.frameNavigated(frame);\n }\n }\n\n private resourceAdded(resource: SDK.Resource.Resource): void {\n const frame = resource.frame();\n if (!frame) {\n return;\n }\n if (!SDK.TargetManager.TargetManager.instance().isInScope(frame.resourceTreeModel())) {\n return;\n }\n const frameTreeElement = this.treeElementForFrameId.get(frame.id);\n if (!frameTreeElement) {\n // This is a frame's main resource, it will be retained\n // and re-added by the resource manager;\n return;\n }\n frameTreeElement.appendResource(resource);\n }\n\n private windowOpened(event: Common.EventTarget.EventTargetEvent): void {\n const targetInfo = event.data;\n // Events for DevTools windows are ignored because they do not have an openerId\n if (targetInfo.openerId && targetInfo.type === 'page') {\n const frameTreeElement = this.treeElementForFrameId.get(targetInfo.openerId);\n if (frameTreeElement) {\n this.treeElementForTargetId.set(targetInfo.targetId, frameTreeElement);\n frameTreeElement.windowOpened(targetInfo);\n }\n }\n }\n\n private windowDestroyed(event: Common.EventTarget.EventTargetEvent): void {\n const targetId = event.data;\n const frameTreeElement = this.treeElementForTargetId.get(targetId);\n if (frameTreeElement) {\n frameTreeElement.windowDestroyed(targetId);\n this.treeElementForTargetId.delete(targetId);\n }\n }\n\n private windowChanged(event: Common.EventTarget.EventTargetEvent): void {\n const targetInfo = event.data;\n // Events for DevTools windows are ignored because they do not have an openerId\n if (targetInfo.openerId && targetInfo.type === 'page') {\n const frameTreeElement = this.treeElementForFrameId.get(targetInfo.openerId);\n if (frameTreeElement) {\n frameTreeElement.windowChanged(targetInfo);\n }\n }\n }\n\n reset(): void {\n this.treeElement.removeChildren();\n this.treeElementForFrameId.clear();\n this.treeElementForTargetId.clear();\n }\n}\n\nexport class FrameTreeElement extends ApplicationPanelTreeElement {\n private section: ResourcesSection;\n private frame: SDK.ResourceTreeModel.ResourceTreeFrame;\n private frameId: string;\n private readonly categoryElements: Map;\n private readonly treeElementForResource: Map;\n private treeElementForWindow: Map;\n private treeElementForWorker: Map;\n private view: LegacyWrapper.LegacyWrapper\n .LegacyWrapper|null;\n\n constructor(section: ResourcesSection, frame: SDK.ResourceTreeModel.ResourceTreeFrame) {\n super(section.panel, '', false, 'frame');\n this.section = section;\n this.frame = frame;\n this.frameId = frame.id;\n this.categoryElements = new Map();\n this.treeElementForResource = new Map();\n this.treeElementForWindow = new Map();\n this.treeElementForWorker = new Map();\n void this.frameNavigated(frame);\n this.view = null;\n }\n\n getIconTypeForFrame(frame: SDK.ResourceTreeModel.ResourceTreeFrame): 'frame-crossed'|'frame'|'iframe-crossed'|\n 'iframe' {\n if (frame.isOutermostFrame()) {\n return frame.unreachableUrl() ? 'frame-crossed' : 'frame';\n }\n return frame.unreachableUrl() ? 'iframe-crossed' : 'iframe';\n }\n\n async frameNavigated(frame: SDK.ResourceTreeModel.ResourceTreeFrame): Promise {\n const icon = IconButton.Icon.create(this.getIconTypeForFrame(frame));\n if (frame.unreachableUrl()) {\n icon.classList.add('red-icon');\n }\n this.setLeadingIcons([icon]);\n this.invalidateChildren();\n\n this.frameId = frame.id;\n if (this.title !== frame.displayName()) {\n this.title = frame.displayName();\n UI.ARIAUtils.setLabel(this.listItemElement, this.title);\n if (this.parent) {\n const parent = this.parent;\n // Insert frame at new position to preserve correct alphabetical order\n parent.removeChild(this);\n parent.appendChild(this);\n }\n }\n this.categoryElements.clear();\n this.treeElementForResource.clear();\n this.treeElementForWorker.clear();\n\n if (this.selected) {\n this.view = LegacyWrapper.LegacyWrapper.legacyWrapper(\n UI.Widget.Widget, new ApplicationComponents.FrameDetailsView.FrameDetailsReportView(this.frame));\n this.showView(this.view);\n } else {\n this.view = null;\n }\n\n // Service Workers' parent is always the outermost frame. We need to reconstruct\n // the service worker tree elements after those navigations which allow\n // the service workers to stay alive.\n if (frame.isOutermostFrame()) {\n const targets = SDK.TargetManager.TargetManager.instance().targets();\n for (const target of targets) {\n if (target.type() === SDK.Target.Type.ServiceWorker &&\n SDK.TargetManager.TargetManager.instance().isInScope(target)) {\n const targetId = target.id();\n assertNotMainTarget(targetId);\n const agent = frame.resourceTreeModel().target().targetAgent();\n const targetInfo = (await agent.invoke_getTargetInfo({targetId})).targetInfo;\n this.workerCreated(targetInfo);\n }\n }\n }\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n // This is used to persist over reloads/navigation which frame was selected.\n // A frame's title can change on DevTools refresh, so we resort to using\n // the URL instead (even though it is not guaranteed to be unique).\n if (this.frame.isOutermostFrame()) {\n return 'frame://' as Platform.DevToolsPath.UrlString;\n }\n return 'frame://' + encodeURI(this.frame.url) as Platform.DevToolsPath.UrlString;\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n if (!this.view) {\n this.view = LegacyWrapper.LegacyWrapper.legacyWrapper(\n UI.Widget.Widget, new ApplicationComponents.FrameDetailsView.FrameDetailsReportView(this.frame));\n }\n Host.userMetrics.panelShown('frame-details');\n this.showView(this.view);\n\n this.listItemElement.classList.remove('hovered');\n SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight();\n return false;\n }\n\n set hovered(hovered: boolean) {\n if (hovered) {\n this.listItemElement.classList.add('hovered');\n void this.frame.highlight();\n } else {\n this.listItemElement.classList.remove('hovered');\n SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight();\n }\n }\n\n appendResource(resource: SDK.Resource.Resource): void {\n const statusCode = resource.statusCode();\n if (statusCode >= 301 && statusCode <= 303) {\n return;\n }\n\n const resourceType = resource.resourceType();\n const categoryName = resourceType.name();\n let categoryElement =\n resourceType === Common.ResourceType.resourceTypes.Document ? this : this.categoryElements.get(categoryName);\n if (!categoryElement) {\n categoryElement = new ExpandableApplicationPanelTreeElement(\n this.section.panel, resource.resourceType().category().title(), categoryName, categoryName === 'Frames');\n this.categoryElements.set(resourceType.name(), categoryElement);\n this.appendChild(categoryElement, FrameTreeElement.presentationOrderCompare);\n }\n const resourceTreeElement = new FrameResourceTreeElement(this.section.panel, resource);\n categoryElement.appendChild(resourceTreeElement, FrameTreeElement.presentationOrderCompare);\n this.treeElementForResource.set(resource.url, resourceTreeElement);\n }\n\n windowOpened(targetInfo: Protocol.Target.TargetInfo): void {\n const categoryKey = 'opened-windows';\n let categoryElement = this.categoryElements.get(categoryKey);\n if (!categoryElement) {\n categoryElement = new ExpandableApplicationPanelTreeElement(\n this.section.panel, i18nString(UIStrings.openedWindows), categoryKey);\n this.categoryElements.set(categoryKey, categoryElement);\n this.appendChild(categoryElement, FrameTreeElement.presentationOrderCompare);\n }\n if (!this.treeElementForWindow.get(targetInfo.targetId)) {\n const windowTreeElement = new FrameWindowTreeElement(this.section.panel, targetInfo);\n categoryElement.appendChild(windowTreeElement);\n this.treeElementForWindow.set(targetInfo.targetId, windowTreeElement);\n }\n }\n\n workerCreated(targetInfo: Protocol.Target.TargetInfo): void {\n const categoryKey = targetInfo.type === 'service_worker' ? 'service-workers' : 'web-workers';\n const categoryName = targetInfo.type === 'service_worker' ? i18n.i18n.lockedString('Service workers') :\n i18nString(UIStrings.webWorkers);\n let categoryElement = this.categoryElements.get(categoryKey);\n if (!categoryElement) {\n categoryElement = new ExpandableApplicationPanelTreeElement(this.section.panel, categoryName, categoryKey);\n this.categoryElements.set(categoryKey, categoryElement);\n this.appendChild(categoryElement, FrameTreeElement.presentationOrderCompare);\n }\n if (!this.treeElementForWorker.get(targetInfo.targetId)) {\n const workerTreeElement = new WorkerTreeElement(this.section.panel, targetInfo);\n categoryElement.appendChild(workerTreeElement);\n this.treeElementForWorker.set(targetInfo.targetId, workerTreeElement);\n }\n }\n\n windowChanged(targetInfo: Protocol.Target.TargetInfo): void {\n const windowTreeElement = this.treeElementForWindow.get(targetInfo.targetId);\n if (!windowTreeElement) {\n return;\n }\n if (windowTreeElement.title !== targetInfo.title) {\n windowTreeElement.title = targetInfo.title;\n }\n windowTreeElement.update(targetInfo);\n }\n\n windowDestroyed(targetId: Protocol.Target.TargetID): void {\n const windowTreeElement = this.treeElementForWindow.get(targetId);\n if (windowTreeElement) {\n windowTreeElement.windowClosed();\n }\n }\n\n override appendChild(\n treeElement: UI.TreeOutline.TreeElement,\n comparator: ((arg0: UI.TreeOutline.TreeElement, arg1: UI.TreeOutline.TreeElement) => number)|\n undefined = FrameTreeElement.presentationOrderCompare): void {\n super.appendChild(treeElement, comparator);\n }\n\n /**\n * Order elements by type (first frames, then resources, last Document resources)\n * and then each of these groups in the alphabetical order.\n */\n private static presentationOrderCompare(\n treeElement1: UI.TreeOutline.TreeElement, treeElement2: UI.TreeOutline.TreeElement): number {\n function typeWeight(treeElement: UI.TreeOutline.TreeElement): number {\n if (treeElement instanceof ExpandableApplicationPanelTreeElement) {\n return 2;\n }\n if (treeElement instanceof FrameTreeElement) {\n return 1;\n }\n return 3;\n }\n\n const typeWeight1 = typeWeight(treeElement1);\n const typeWeight2 = typeWeight(treeElement2);\n return typeWeight1 - typeWeight2 || treeElement1.titleAsText().localeCompare(treeElement2.titleAsText());\n }\n}\n\nconst resourceToFrameResourceTreeElement = new WeakMap();\n\nexport class FrameResourceTreeElement extends ApplicationPanelTreeElement {\n private readonly panel: ResourcesPanel;\n private resource: SDK.Resource.Resource;\n private previewPromise: Promise|null;\n\n constructor(storagePanel: ResourcesPanel, resource: SDK.Resource.Resource) {\n super(\n storagePanel, resource.isGenerated ? i18nString(UIStrings.documentNotAvailable) : resource.displayName, false,\n 'frame-resource');\n this.panel = storagePanel;\n this.resource = resource;\n this.previewPromise = null;\n this.tooltip = resource.url;\n resourceToFrameResourceTreeElement.set(this.resource, this);\n\n const icon = IconButton.Icon.create('document', 'navigator-file-tree-item');\n icon.classList.add('navigator-' + resource.resourceType().name() + '-tree-item');\n this.setLeadingIcons([icon]);\n }\n\n static forResource(resource: SDK.Resource.Resource): FrameResourceTreeElement|undefined {\n return resourceToFrameResourceTreeElement.get(resource);\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return this.resource.url;\n }\n\n private preparePreview(): Promise {\n if (this.previewPromise) {\n return this.previewPromise;\n }\n const viewPromise = SourceFrame.PreviewFactory.PreviewFactory.createPreview(this.resource, this.resource.mimeType);\n this.previewPromise = viewPromise.then(view => {\n if (view) {\n return view;\n }\n return new UI.EmptyWidget.EmptyWidget(this.resource.url);\n });\n return this.previewPromise;\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n if (this.resource.isGenerated) {\n this.panel.showCategoryView(i18nString(UIStrings.theContentOfThisDocumentHasBeen), null);\n } else {\n void this.panel.scheduleShowView(this.preparePreview());\n }\n Host.userMetrics.panelShown('frame-resource');\n return false;\n }\n\n override ondblclick(_event: Event): boolean {\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(this.resource.url);\n return false;\n }\n\n override onattach(): void {\n super.onattach();\n this.listItemElement.draggable = true;\n this.listItemElement.addEventListener('dragstart', this.ondragstart.bind(this), false);\n this.listItemElement.addEventListener('contextmenu', this.handleContextMenuEvent.bind(this), true);\n }\n\n private ondragstart(event: DragEvent): boolean {\n if (!event.dataTransfer) {\n return false;\n }\n event.dataTransfer.setData('text/plain', this.resource.content || '');\n event.dataTransfer.effectAllowed = 'copy';\n return true;\n }\n\n private handleContextMenuEvent(event: MouseEvent): void {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n contextMenu.appendApplicableItems(this.resource);\n void contextMenu.show();\n }\n\n async revealResource(lineNumber?: number, columnNumber?: number): Promise {\n this.revealAndSelect(true);\n const view = await this.panel.scheduleShowView(this.preparePreview());\n if (!(view instanceof SourceFrame.ResourceSourceFrame.ResourceSourceFrame) || typeof lineNumber !== 'number') {\n return;\n }\n view.revealPosition({lineNumber, columnNumber}, true);\n }\n}\n\nclass FrameWindowTreeElement extends ApplicationPanelTreeElement {\n private targetInfo: Protocol.Target.TargetInfo;\n private isWindowClosed: boolean;\n private view: OpenedWindowDetailsView|null;\n\n constructor(storagePanel: ResourcesPanel, targetInfo: Protocol.Target.TargetInfo) {\n super(storagePanel, targetInfo.title || i18nString(UIStrings.windowWithoutTitle), false, 'window');\n this.targetInfo = targetInfo;\n this.isWindowClosed = false;\n this.view = null;\n this.updateIcon(targetInfo.canAccessOpener);\n }\n\n updateIcon(canAccessOpener: boolean): void {\n const iconType = canAccessOpener ? 'popup' : 'frame';\n const icon = IconButton.Icon.create(iconType);\n this.setLeadingIcons([icon]);\n }\n\n update(targetInfo: Protocol.Target.TargetInfo): void {\n if (targetInfo.canAccessOpener !== this.targetInfo.canAccessOpener) {\n this.updateIcon(targetInfo.canAccessOpener);\n }\n this.targetInfo = targetInfo;\n if (this.view) {\n this.view.setTargetInfo(targetInfo);\n this.view.update();\n }\n }\n\n windowClosed(): void {\n this.listItemElement.classList.add('window-closed');\n this.isWindowClosed = true;\n if (this.view) {\n this.view.setIsWindowClosed(true);\n this.view.update();\n }\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n if (!this.view) {\n this.view = new OpenedWindowDetailsView(this.targetInfo, this.isWindowClosed);\n } else {\n this.view.update();\n }\n this.showView(this.view);\n Host.userMetrics.panelShown('frame-window');\n return false;\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return this.targetInfo.url as Platform.DevToolsPath.UrlString;\n }\n}\n\nclass WorkerTreeElement extends ApplicationPanelTreeElement {\n private targetInfo: Protocol.Target.TargetInfo;\n private view: WorkerDetailsView|null;\n\n constructor(storagePanel: ResourcesPanel, targetInfo: Protocol.Target.TargetInfo) {\n super(storagePanel, targetInfo.title || targetInfo.url || i18nString(UIStrings.worker), false, 'worker');\n this.targetInfo = targetInfo;\n this.view = null;\n const icon = IconButton.Icon.create('gears', 'navigator-file-tree-item');\n this.setLeadingIcons([icon]);\n }\n\n override onselect(selectedByUser?: boolean): boolean {\n super.onselect(selectedByUser);\n if (!this.view) {\n this.view = new WorkerDetailsView(this.targetInfo);\n } else {\n this.view.update();\n }\n this.showView(this.view);\n Host.userMetrics.panelShown('frame-worker');\n return false;\n }\n\n override get itemURL(): Platform.DevToolsPath.UrlString {\n return this.targetInfo.url as Platform.DevToolsPath.UrlString;\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/application/ExtensionStorageModel.d.ts b/public/panels/application/ExtensionStorageModel.d.ts new file mode 100644 index 000000000..232dfabff --- /dev/null +++ b/public/panels/application/ExtensionStorageModel.d.ts @@ -0,0 +1,33 @@ +import * as Common from '../../core/common/common.js'; +import * as SDK from '../../core/sdk/sdk.js'; +import type * as ProtocolProxyApi from '../../generated/protocol-proxy-api.js'; +import * as Protocol from '../../generated/protocol.js'; +export declare class ExtensionStorage extends Common.ObjectWrapper.ObjectWrapper<{}> { + #private; + constructor(model: ExtensionStorageModel, extensionId: string, name: string, storageArea: Protocol.Extensions.StorageArea); + get extensionId(): string; + get name(): string; + get storageArea(): Protocol.Extensions.StorageArea; + getItems(): Promise<{ + [key: string]: unknown; + }>; + setItem(key: string, value: string): Promise; + removeItem(key: string): Promise; + clear(): Promise; +} +export declare class ExtensionStorageModel extends SDK.SDKModel.SDKModel { + #private; + readonly agent: ProtocolProxyApi.ExtensionsApi; + constructor(target: SDK.Target.Target); + enable(): void; + storageForIdAndArea(id: string, storageArea: Protocol.Extensions.StorageArea): ExtensionStorage | undefined; + storages(): ExtensionStorage[]; +} +export declare const enum Events { + EXTENSION_STORAGE_ADDED = "ExtensionStorageAdded", + EXTENSION_STORAGE_REMOVED = "ExtensionStorageRemoved" +} +export type EventTypes = { + [Events.EXTENSION_STORAGE_ADDED]: ExtensionStorage; + [Events.EXTENSION_STORAGE_REMOVED]: ExtensionStorage; +}; diff --git a/public/panels/application/ExtensionStorageModel.js b/public/panels/application/ExtensionStorageModel.js new file mode 100644 index 000000000..f68d81dde --- /dev/null +++ b/public/panels/application/ExtensionStorageModel.js @@ -0,0 +1,139 @@ +// Copyright 2024 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 * as Common from '../../core/common/common.js'; +import * as SDK from '../../core/sdk/sdk.js'; +export class ExtensionStorage extends Common.ObjectWrapper.ObjectWrapper { + #model; + #extensionIdInternal; + #nameInternal; + #storageAreaInternal; + constructor(model, extensionId, name, storageArea) { + super(); + this.#model = model; + this.#extensionIdInternal = extensionId; + this.#nameInternal = name; + this.#storageAreaInternal = storageArea; + } + get extensionId() { + return this.#extensionIdInternal; + } + get name() { + return this.#nameInternal; + } + get storageArea() { + return this.#storageAreaInternal; + } + async getItems() { + const response = await this.#model.agent.invoke_getStorageItems({ id: this.#extensionIdInternal, storageArea: this.#storageAreaInternal }); + if (response.getError()) { + throw new Error(response.getError()); + } + return response.data; + } + async setItem(key, value) { + const response = await this.#model.agent.invoke_setStorageItems({ id: this.#extensionIdInternal, storageArea: this.#storageAreaInternal, values: { [key]: value } }); + if (response.getError()) { + throw new Error(response.getError()); + } + } + async removeItem(key) { + const response = await this.#model.agent.invoke_removeStorageItems({ id: this.#extensionIdInternal, storageArea: this.#storageAreaInternal, keys: [key] }); + if (response.getError()) { + throw new Error(response.getError()); + } + } + async clear() { + const response = await this.#model.agent.invoke_clearStorageItems({ id: this.#extensionIdInternal, storageArea: this.#storageAreaInternal }); + if (response.getError()) { + throw new Error(response.getError()); + } + } +} +export class ExtensionStorageModel extends SDK.SDKModel.SDKModel { + #runtimeModelInternal; + #storagesInternal; + agent; + #enabled; + constructor(target) { + super(target); + this.#runtimeModelInternal = target.model(SDK.RuntimeModel.RuntimeModel); + this.#storagesInternal = new Map(); + this.agent = target.extensionsAgent(); + } + enable() { + if (this.#enabled) { + return; + } + if (this.#runtimeModelInternal) { + this.#runtimeModelInternal.addEventListener(SDK.RuntimeModel.Events.ExecutionContextCreated, this.#onExecutionContextCreated, this); + this.#runtimeModelInternal.addEventListener(SDK.RuntimeModel.Events.ExecutionContextDestroyed, this.#onExecutionContextDestroyed, this); + this.#runtimeModelInternal.executionContexts().forEach(this.#executionContextCreated, this); + } + this.#enabled = true; + } + #addExtension(id, name) { + for (const storageArea of ["session" /* Protocol.Extensions.StorageArea.Session */, "local" /* Protocol.Extensions.StorageArea.Local */, + "sync" /* Protocol.Extensions.StorageArea.Sync */, "managed" /* Protocol.Extensions.StorageArea.Managed */]) { + const storages = this.#storagesInternal.get(id); + const storage = new ExtensionStorage(this, id, name, storageArea); + if (!storages) { + this.#storagesInternal.set(id, new Map([[storageArea, storage]])); + } + else { + console.assert(!storages.get(storageArea)); + storages.set(storageArea, storage); + } + this.dispatchEventToListeners("ExtensionStorageAdded" /* Events.EXTENSION_STORAGE_ADDED */, storage); + } + } + #removeExtension(id) { + const storages = this.#storagesInternal.get(id); + if (!storages) { + return; + } + for (const [key, storage] of storages) { + this.dispatchEventToListeners("ExtensionStorageRemoved" /* Events.EXTENSION_STORAGE_REMOVED */, storage); + storages.delete(key); + } + this.#storagesInternal.delete(id); + } + #executionContextCreated(context) { + const extensionId = this.#extensionIdForContext(context); + if (extensionId) { + this.#addExtension(extensionId, context.name); + } + } + #onExecutionContextCreated(event) { + this.#executionContextCreated(event.data); + } + #extensionIdForContext(context) { + const url = Common.ParsedURL.ParsedURL.fromString(context.origin); + return url && url.scheme === 'chrome-extension' ? url.host : undefined; + } + #executionContextDestroyed(context) { + const extensionId = this.#extensionIdForContext(context); + if (extensionId) { + // Ignore event if there is still another context for this extension. + if (this.#runtimeModelInternal?.executionContexts().some(c => this.#extensionIdForContext(c) === extensionId)) { + return; + } + this.#removeExtension(extensionId); + } + } + #onExecutionContextDestroyed(event) { + this.#executionContextDestroyed(event.data); + } + storageForIdAndArea(id, storageArea) { + return this.#storagesInternal.get(id)?.get(storageArea); + } + storages() { + const result = []; + for (const storages of this.#storagesInternal.values()) { + result.push(...storages.values()); + } + return result; + } +} +SDK.SDKModel.SDKModel.register(ExtensionStorageModel, { capabilities: 4 /* SDK.Target.Capability.JS */, autostart: false }); +//# sourceMappingURL=ExtensionStorageModel.js.map \ No newline at end of file diff --git a/public/panels/application/ExtensionStorageModel.js.map b/public/panels/application/ExtensionStorageModel.js.map new file mode 100644 index 000000000..5e5743ff4 --- /dev/null +++ b/public/panels/application/ExtensionStorageModel.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ExtensionStorageModel.js","sourceRoot":"","sources":["../../../../../../front_end/panels/application/ExtensionStorageModel.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport type * as ProtocolProxyApi from '../../generated/protocol-proxy-api.js';\nimport * as Protocol from '../../generated/protocol.js';\n\nexport class ExtensionStorage extends Common.ObjectWrapper.ObjectWrapper<{}> {\n readonly #model: ExtensionStorageModel;\n readonly #extensionIdInternal: string;\n readonly #nameInternal: string;\n readonly #storageAreaInternal: Protocol.Extensions.StorageArea;\n\n constructor(\n model: ExtensionStorageModel, extensionId: string, name: string, storageArea: Protocol.Extensions.StorageArea) {\n super();\n this.#model = model;\n this.#extensionIdInternal = extensionId;\n this.#nameInternal = name;\n this.#storageAreaInternal = storageArea;\n }\n\n get extensionId(): string {\n return this.#extensionIdInternal;\n }\n\n get name(): string {\n return this.#nameInternal;\n }\n\n get storageArea(): Protocol.Extensions.StorageArea {\n return this.#storageAreaInternal;\n }\n\n async getItems(): Promise<{[key: string]: unknown}> {\n const response = await this.#model.agent.invoke_getStorageItems(\n {id: this.#extensionIdInternal, storageArea: this.#storageAreaInternal});\n if (response.getError()) {\n throw new Error(response.getError());\n }\n return response.data;\n }\n\n async setItem(key: string, value: string): Promise {\n const response = await this.#model.agent.invoke_setStorageItems(\n {id: this.#extensionIdInternal, storageArea: this.#storageAreaInternal, values: {[key]: value}});\n if (response.getError()) {\n throw new Error(response.getError());\n }\n }\n\n async removeItem(key: string): Promise {\n const response = await this.#model.agent.invoke_removeStorageItems(\n {id: this.#extensionIdInternal, storageArea: this.#storageAreaInternal, keys: [key]});\n if (response.getError()) {\n throw new Error(response.getError());\n }\n }\n\n async clear(): Promise {\n const response = await this.#model.agent.invoke_clearStorageItems(\n {id: this.#extensionIdInternal, storageArea: this.#storageAreaInternal});\n if (response.getError()) {\n throw new Error(response.getError());\n }\n }\n}\n\nexport class ExtensionStorageModel extends SDK.SDKModel.SDKModel {\n readonly #runtimeModelInternal: SDK.RuntimeModel.RuntimeModel|null;\n #storagesInternal: Map>;\n readonly agent: ProtocolProxyApi.ExtensionsApi;\n #enabled?: boolean;\n\n constructor(target: SDK.Target.Target) {\n super(target);\n\n this.#runtimeModelInternal = target.model(SDK.RuntimeModel.RuntimeModel);\n this.#storagesInternal = new Map();\n this.agent = target.extensionsAgent();\n }\n\n enable(): void {\n if (this.#enabled) {\n return;\n }\n\n if (this.#runtimeModelInternal) {\n this.#runtimeModelInternal.addEventListener(\n SDK.RuntimeModel.Events.ExecutionContextCreated, this.#onExecutionContextCreated, this);\n this.#runtimeModelInternal.addEventListener(\n SDK.RuntimeModel.Events.ExecutionContextDestroyed, this.#onExecutionContextDestroyed, this);\n this.#runtimeModelInternal.executionContexts().forEach(this.#executionContextCreated, this);\n }\n\n this.#enabled = true;\n }\n\n #addExtension(id: string, name: string): void {\n for (const storageArea\n of [Protocol.Extensions.StorageArea.Session, Protocol.Extensions.StorageArea.Local,\n Protocol.Extensions.StorageArea.Sync, Protocol.Extensions.StorageArea.Managed]) {\n const storages = this.#storagesInternal.get(id);\n const storage = new ExtensionStorage(this, id, name, storageArea);\n\n if (!storages) {\n this.#storagesInternal.set(id, new Map([[storageArea, storage]]));\n } else {\n console.assert(!storages.get(storageArea));\n storages.set(storageArea, storage);\n }\n\n this.dispatchEventToListeners(Events.EXTENSION_STORAGE_ADDED, storage);\n }\n }\n\n #removeExtension(id: string): void {\n const storages = this.#storagesInternal.get(id);\n\n if (!storages) {\n return;\n }\n\n for (const [key, storage] of storages) {\n this.dispatchEventToListeners(Events.EXTENSION_STORAGE_REMOVED, storage);\n storages.delete(key);\n }\n\n this.#storagesInternal.delete(id);\n }\n\n #executionContextCreated(context: SDK.RuntimeModel.ExecutionContext): void {\n const extensionId = this.#extensionIdForContext(context);\n if (extensionId) {\n this.#addExtension(extensionId, context.name);\n }\n }\n\n #onExecutionContextCreated(event: Common.EventTarget.EventTargetEvent): void {\n this.#executionContextCreated(event.data);\n }\n\n #extensionIdForContext(context: SDK.RuntimeModel.ExecutionContext): string|undefined {\n const url = Common.ParsedURL.ParsedURL.fromString(context.origin);\n return url && url.scheme === 'chrome-extension' ? url.host : undefined;\n }\n\n #executionContextDestroyed(context: SDK.RuntimeModel.ExecutionContext): void {\n const extensionId = this.#extensionIdForContext(context);\n if (extensionId) {\n // Ignore event if there is still another context for this extension.\n if (this.#runtimeModelInternal?.executionContexts().some(c => this.#extensionIdForContext(c) === extensionId)) {\n return;\n }\n\n this.#removeExtension(extensionId);\n }\n }\n\n #onExecutionContextDestroyed(event: Common.EventTarget.EventTargetEvent): void {\n this.#executionContextDestroyed(event.data);\n }\n\n storageForIdAndArea(id: string, storageArea: Protocol.Extensions.StorageArea): ExtensionStorage|undefined {\n return this.#storagesInternal.get(id)?.get(storageArea);\n }\n\n storages(): ExtensionStorage[] {\n const result = [];\n for (const storages of this.#storagesInternal.values()) {\n result.push(...storages.values());\n }\n return result;\n }\n}\n\nSDK.SDKModel.SDKModel.register(ExtensionStorageModel, {capabilities: SDK.Target.Capability.JS, autostart: false});\n\nexport const enum Events {\n EXTENSION_STORAGE_ADDED = 'ExtensionStorageAdded',\n EXTENSION_STORAGE_REMOVED = 'ExtensionStorageRemoved',\n}\n\nexport type EventTypes = {\n [Events.EXTENSION_STORAGE_ADDED]: ExtensionStorage,\n [Events.EXTENSION_STORAGE_REMOVED]: ExtensionStorage,\n};\n"]} \ No newline at end of file diff --git a/public/panels/application/ExtensionStorageModel.test.d.ts b/public/panels/application/ExtensionStorageModel.test.d.ts new file mode 100644 index 000000000..cb0ff5c3b --- /dev/null +++ b/public/panels/application/ExtensionStorageModel.test.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/public/panels/application/ExtensionStorageModel.test.js b/public/panels/application/ExtensionStorageModel.test.js new file mode 100644 index 000000000..2037acf6c --- /dev/null +++ b/public/panels/application/ExtensionStorageModel.test.js @@ -0,0 +1,161 @@ +// Copyright 2024 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 * as SDK from '../../core/sdk/sdk.js'; +import { createTarget } from '../../testing/EnvironmentHelpers.js'; +import { describeWithMockConnection } from '../../testing/MockConnection.js'; +import * as Resources from './application.js'; +class ExtensionStorageListener { + #model; + #storagesWatched; + constructor(model) { + this.#model = model; + this.#storagesWatched = new Array(); + this.#model.addEventListener("ExtensionStorageAdded" /* Resources.ExtensionStorageModel.Events.EXTENSION_STORAGE_ADDED */, this.#extensionStorageAdded, this); + this.#model.addEventListener("ExtensionStorageRemoved" /* Resources.ExtensionStorageModel.Events.EXTENSION_STORAGE_REMOVED */, this.#extensionStorageRemoved, this); + } + dispose() { + this.#model.removeEventListener("ExtensionStorageAdded" /* Resources.ExtensionStorageModel.Events.EXTENSION_STORAGE_ADDED */, this.#extensionStorageAdded, this); + this.#model.removeEventListener("ExtensionStorageRemoved" /* Resources.ExtensionStorageModel.Events.EXTENSION_STORAGE_REMOVED */, this.#extensionStorageRemoved, this); + } + #extensionStorageAdded(event) { + const storage = event.data; + this.#storagesWatched.push(storage); + } + #extensionStorageRemoved(event) { + const storage = event.data; + const index = this.#storagesWatched.indexOf(storage); + if (index === -1) { + return; + } + this.#storagesWatched = this.#storagesWatched.splice(index, 1); + } + async waitForStoragesAdded(expectedCount) { + while (this.#storagesWatched.length < expectedCount) { + await this.#model.once("ExtensionStorageAdded" /* Resources.ExtensionStorageModel.Events.EXTENSION_STORAGE_ADDED */); + } + } +} +describeWithMockConnection('ExtensionStorageModel', () => { + let extensionStorageModel; + let extensionStorage; + let target; + let listener; + const initId = 'extensionid'; + const initName = 'Test Extension'; + const initStorageArea = "local" /* Protocol.Extensions.StorageArea.Local */; + beforeEach(() => { + target = createTarget(); + extensionStorageModel = new Resources.ExtensionStorageModel.ExtensionStorageModel(target); + extensionStorage = + new Resources.ExtensionStorageModel.ExtensionStorage(extensionStorageModel, initId, initName, initStorageArea); + listener = new ExtensionStorageListener(extensionStorageModel); + }); + const createMockExecutionContext = (id, origin) => { + return { + id: id, + uniqueId: '', + origin: origin, + name: 'Test Extension', + }; + }; + it('ExtensionStorage is instantiated correctly', () => { + assert.strictEqual(extensionStorage.extensionId, initId); + assert.strictEqual(extensionStorage.name, initName); + assert.strictEqual(extensionStorage.storageArea, initStorageArea); + }); + const STORAGE_AREAS = [ + "session" /* Protocol.Extensions.StorageArea.Session */, + "local" /* Protocol.Extensions.StorageArea.Local */, + "sync" /* Protocol.Extensions.StorageArea.Sync */, + "managed" /* Protocol.Extensions.StorageArea.Managed */, + ]; + const ENTRIES = { + foo: 'bar', + }; + it('invokes storageAgent', async () => { + const getSpy = sinon.stub(extensionStorageModel.agent, 'invoke_getStorageItems').resolves({ + data: ENTRIES, + getError: () => undefined, + }); + const setSpy = sinon.stub(extensionStorageModel.agent, 'invoke_setStorageItems').resolves({ + getError: () => undefined, + }); + const removeSpy = sinon.stub(extensionStorageModel.agent, 'invoke_removeStorageItems').resolves({ + getError: () => undefined, + }); + const clearSpy = sinon.stub(extensionStorageModel.agent, 'invoke_clearStorageItems').resolves({ + getError: () => undefined, + }); + const data = await extensionStorage.getItems(); + assert.isTrue(getSpy.calledOnceWithExactly({ id: initId, storageArea: initStorageArea })); + assert.deepEqual(data, ENTRIES); + await extensionStorage.setItem('foo', 'baz'); + assert.isTrue(setSpy.calledOnceWithExactly({ id: initId, storageArea: initStorageArea, values: { foo: 'baz' } })); + await extensionStorage.removeItem('foo'); + assert.isTrue(removeSpy.calledOnceWithExactly({ id: initId, storageArea: initStorageArea, keys: ['foo'] })); + await extensionStorage.clear(); + assert.isTrue(clearSpy.calledOnceWithExactly({ id: initId, storageArea: initStorageArea })); + }); + it('adds/removes ExtensionStorage on Runtime events', async () => { + extensionStorageModel.enable(); + assert.isEmpty(extensionStorageModel.storages()); + const runtime = target.model(SDK.RuntimeModel.RuntimeModel); + assert.exists(runtime); + // Each extension adds four associated storage areas. + const addedPromise = listener.waitForStoragesAdded(4); + const mockExecutionContext = createMockExecutionContext(1, `chrome-extension://${initId}/sw.js`); + runtime.executionContextCreated(mockExecutionContext); + await addedPromise; + STORAGE_AREAS.forEach(area => assert.exists(extensionStorageModel.storageForIdAndArea(initId, area))); + runtime.executionContextDestroyed(mockExecutionContext.id); + assert.isEmpty(extensionStorageModel.storages()); + }); + it('does not add ExtensionStorage if origin invalid', async () => { + extensionStorageModel.enable(); + assert.isEmpty(extensionStorageModel.storages()); + const runtime = target.model(SDK.RuntimeModel.RuntimeModel); + assert.exists(runtime); + // The scheme is not valid (not chrome-extension://) so no storage should be added. + const mockExecutionContext = createMockExecutionContext(1, 'https://example.com'); + runtime.executionContextCreated(mockExecutionContext); + assert.isEmpty(extensionStorageModel.storages()); + }); + it('does not add ExtensionStorage if origin already added', async () => { + extensionStorageModel.enable(); + assert.isEmpty(extensionStorageModel.storages()); + // Each extension adds four associated storage areas. + const addedPromise = listener.waitForStoragesAdded(4); + const runtime = target.model(SDK.RuntimeModel.RuntimeModel); + assert.exists(runtime); + const mockExecutionContext = createMockExecutionContext(1, `chrome-extension://${initId}/sw.js`); + runtime.executionContextCreated(mockExecutionContext); + await addedPromise; + STORAGE_AREAS.forEach(area => assert.exists(extensionStorageModel.storageForIdAndArea(initId, area))); + assert.strictEqual(4, extensionStorageModel.storages().length); + runtime.executionContextCreated(mockExecutionContext); + assert.strictEqual(4, extensionStorageModel.storages().length); + }); + it('removes ExtensionStorage when last ExecutionContext is removed', async () => { + extensionStorageModel.enable(); + assert.isEmpty(extensionStorageModel.storages()); + // Each extension adds four associated storage areas. + const addedPromise = listener.waitForStoragesAdded(4); + const runtime = target.model(SDK.RuntimeModel.RuntimeModel); + assert.exists(runtime); + const mockExecutionContext1 = createMockExecutionContext(1, `chrome-extension://${initId}/sw.js`); + const mockExecutionContext2 = createMockExecutionContext(2, `chrome-extension://${initId}/another.js`); + runtime.executionContextCreated(mockExecutionContext1); + runtime.executionContextCreated(mockExecutionContext2); + await addedPromise; + STORAGE_AREAS.forEach(area => assert.exists(extensionStorageModel.storageForIdAndArea(initId, area))); + assert.strictEqual(4, extensionStorageModel.storages().length); + // If a single execution context is destroyed but another remains, + // ExtensionStorage should not be removed. + runtime.executionContextDestroyed(mockExecutionContext1.id); + assert.strictEqual(4, extensionStorageModel.storages().length); + runtime.executionContextDestroyed(mockExecutionContext2.id); + assert.strictEqual(0, extensionStorageModel.storages().length); + }); +}); +//# sourceMappingURL=ExtensionStorageModel.test.js.map \ No newline at end of file diff --git a/public/panels/application/ExtensionStorageModel.test.js.map b/public/panels/application/ExtensionStorageModel.test.js.map new file mode 100644 index 000000000..aa5ef6c50 --- /dev/null +++ b/public/panels/application/ExtensionStorageModel.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ExtensionStorageModel.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/application/ExtensionStorageModel.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Common from '../../core/common/common.js';\nimport type * as Platform from '../../core/platform/platform.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as Protocol from '../../generated/protocol.js';\nimport {createTarget} from '../../testing/EnvironmentHelpers.js';\nimport {describeWithMockConnection} from '../../testing/MockConnection.js';\n\nimport * as Resources from './application.js';\n\nclass ExtensionStorageListener {\n #model: Resources.ExtensionStorageModel.ExtensionStorageModel;\n #storagesWatched: Array;\n\n constructor(model: Resources.ExtensionStorageModel.ExtensionStorageModel) {\n this.#model = model;\n this.#storagesWatched = new Array();\n\n this.#model.addEventListener(\n Resources.ExtensionStorageModel.Events.EXTENSION_STORAGE_ADDED, this.#extensionStorageAdded, this);\n this.#model.addEventListener(\n Resources.ExtensionStorageModel.Events.EXTENSION_STORAGE_REMOVED, this.#extensionStorageRemoved, this);\n }\n\n dispose(): void {\n this.#model.removeEventListener(\n Resources.ExtensionStorageModel.Events.EXTENSION_STORAGE_ADDED, this.#extensionStorageAdded, this);\n this.#model.removeEventListener(\n Resources.ExtensionStorageModel.Events.EXTENSION_STORAGE_REMOVED, this.#extensionStorageRemoved, this);\n }\n\n #extensionStorageAdded(event: Common.EventTarget.EventTargetEvent):\n void {\n const storage = event.data;\n this.#storagesWatched.push(storage);\n }\n\n #extensionStorageRemoved(\n event: Common.EventTarget.EventTargetEvent): void {\n const storage = event.data;\n const index = this.#storagesWatched.indexOf(storage);\n if (index === -1) {\n return;\n }\n this.#storagesWatched = this.#storagesWatched.splice(index, 1);\n }\n\n async waitForStoragesAdded(expectedCount: number): Promise {\n while (this.#storagesWatched.length < expectedCount) {\n await this.#model.once(Resources.ExtensionStorageModel.Events.EXTENSION_STORAGE_ADDED);\n }\n }\n}\n\ndescribeWithMockConnection('ExtensionStorageModel', () => {\n let extensionStorageModel: Resources.ExtensionStorageModel.ExtensionStorageModel;\n let extensionStorage: Resources.ExtensionStorageModel.ExtensionStorage;\n let target: SDK.Target.Target;\n let listener: ExtensionStorageListener;\n const initId = 'extensionid';\n const initName = 'Test Extension';\n const initStorageArea = Protocol.Extensions.StorageArea.Local;\n\n beforeEach(() => {\n target = createTarget();\n extensionStorageModel = new Resources.ExtensionStorageModel.ExtensionStorageModel(target);\n extensionStorage =\n new Resources.ExtensionStorageModel.ExtensionStorage(extensionStorageModel, initId, initName, initStorageArea);\n listener = new ExtensionStorageListener(extensionStorageModel);\n });\n\n const createMockExecutionContext = (id: number, origin: string): Protocol.Runtime.ExecutionContextDescription => {\n return {\n id: id as Protocol.Runtime.ExecutionContextId,\n uniqueId: '',\n origin: origin as Platform.DevToolsPath.UrlString,\n name: 'Test Extension',\n };\n };\n\n it('ExtensionStorage is instantiated correctly', () => {\n assert.strictEqual(extensionStorage.extensionId, initId);\n assert.strictEqual(extensionStorage.name, initName);\n assert.strictEqual(extensionStorage.storageArea, initStorageArea);\n });\n\n const STORAGE_AREAS = [\n Protocol.Extensions.StorageArea.Session,\n Protocol.Extensions.StorageArea.Local,\n Protocol.Extensions.StorageArea.Sync,\n Protocol.Extensions.StorageArea.Managed,\n ];\n\n const ENTRIES = {\n foo: 'bar',\n };\n\n it('invokes storageAgent', async () => {\n const getSpy = sinon.stub(extensionStorageModel.agent, 'invoke_getStorageItems').resolves({\n data: ENTRIES,\n getError: () => undefined,\n });\n const setSpy = sinon.stub(extensionStorageModel.agent, 'invoke_setStorageItems').resolves({\n getError: () => undefined,\n });\n const removeSpy = sinon.stub(extensionStorageModel.agent, 'invoke_removeStorageItems').resolves({\n getError: () => undefined,\n });\n const clearSpy = sinon.stub(extensionStorageModel.agent, 'invoke_clearStorageItems').resolves({\n getError: () => undefined,\n });\n\n const data = await extensionStorage.getItems();\n assert.isTrue(getSpy.calledOnceWithExactly({id: initId, storageArea: initStorageArea}));\n assert.deepEqual(data, ENTRIES);\n\n await extensionStorage.setItem('foo', 'baz');\n assert.isTrue(setSpy.calledOnceWithExactly({id: initId, storageArea: initStorageArea, values: {foo: 'baz'}}));\n\n await extensionStorage.removeItem('foo');\n assert.isTrue(removeSpy.calledOnceWithExactly({id: initId, storageArea: initStorageArea, keys: ['foo']}));\n\n await extensionStorage.clear();\n assert.isTrue(clearSpy.calledOnceWithExactly({id: initId, storageArea: initStorageArea}));\n });\n\n it('adds/removes ExtensionStorage on Runtime events', async () => {\n extensionStorageModel.enable();\n\n assert.isEmpty(extensionStorageModel.storages());\n\n const runtime = target.model(SDK.RuntimeModel.RuntimeModel);\n assert.exists(runtime);\n\n // Each extension adds four associated storage areas.\n const addedPromise = listener.waitForStoragesAdded(4);\n\n const mockExecutionContext = createMockExecutionContext(1, `chrome-extension://${initId}/sw.js`);\n\n runtime.executionContextCreated(mockExecutionContext);\n\n await addedPromise;\n\n STORAGE_AREAS.forEach(area => assert.exists(extensionStorageModel.storageForIdAndArea(initId, area)));\n\n runtime.executionContextDestroyed(mockExecutionContext.id);\n assert.isEmpty(extensionStorageModel.storages());\n });\n\n it('does not add ExtensionStorage if origin invalid', async () => {\n extensionStorageModel.enable();\n\n assert.isEmpty(extensionStorageModel.storages());\n\n const runtime = target.model(SDK.RuntimeModel.RuntimeModel);\n assert.exists(runtime);\n\n // The scheme is not valid (not chrome-extension://) so no storage should be added.\n const mockExecutionContext = createMockExecutionContext(1, 'https://example.com');\n\n runtime.executionContextCreated(mockExecutionContext);\n assert.isEmpty(extensionStorageModel.storages());\n });\n\n it('does not add ExtensionStorage if origin already added', async () => {\n extensionStorageModel.enable();\n\n assert.isEmpty(extensionStorageModel.storages());\n\n // Each extension adds four associated storage areas.\n const addedPromise = listener.waitForStoragesAdded(4);\n\n const runtime = target.model(SDK.RuntimeModel.RuntimeModel);\n assert.exists(runtime);\n\n const mockExecutionContext = createMockExecutionContext(1, `chrome-extension://${initId}/sw.js`);\n runtime.executionContextCreated(mockExecutionContext);\n\n await addedPromise;\n\n STORAGE_AREAS.forEach(area => assert.exists(extensionStorageModel.storageForIdAndArea(initId, area)));\n assert.strictEqual(4, extensionStorageModel.storages().length);\n\n runtime.executionContextCreated(mockExecutionContext);\n assert.strictEqual(4, extensionStorageModel.storages().length);\n });\n\n it('removes ExtensionStorage when last ExecutionContext is removed', async () => {\n extensionStorageModel.enable();\n\n assert.isEmpty(extensionStorageModel.storages());\n\n // Each extension adds four associated storage areas.\n const addedPromise = listener.waitForStoragesAdded(4);\n\n const runtime = target.model(SDK.RuntimeModel.RuntimeModel);\n assert.exists(runtime);\n\n const mockExecutionContext1 = createMockExecutionContext(1, `chrome-extension://${initId}/sw.js`);\n const mockExecutionContext2 = createMockExecutionContext(2, `chrome-extension://${initId}/another.js`);\n\n runtime.executionContextCreated(mockExecutionContext1);\n runtime.executionContextCreated(mockExecutionContext2);\n await addedPromise;\n\n STORAGE_AREAS.forEach(area => assert.exists(extensionStorageModel.storageForIdAndArea(initId, area)));\n assert.strictEqual(4, extensionStorageModel.storages().length);\n\n // If a single execution context is destroyed but another remains,\n // ExtensionStorage should not be removed.\n runtime.executionContextDestroyed(mockExecutionContext1.id);\n assert.strictEqual(4, extensionStorageModel.storages().length);\n\n runtime.executionContextDestroyed(mockExecutionContext2.id);\n assert.strictEqual(0, extensionStorageModel.storages().length);\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/application/application-tsconfig.json b/public/panels/application/application-tsconfig.json index 6867fee30..82e330251 100644 --- a/public/panels/application/application-tsconfig.json +++ b/public/panels/application/application-tsconfig.json @@ -39,6 +39,7 @@ "../../../../../../front_end/panels/application/CookieItemsView.ts", "../../../../../../front_end/panels/application/DOMStorageItemsView.ts", "../../../../../../front_end/panels/application/DOMStorageModel.ts", + "../../../../../../front_end/panels/application/ExtensionStorageModel.ts", "../../../../../../front_end/panels/application/IndexedDBModel.ts", "../../../../../../front_end/panels/application/IndexedDBViews.ts", "../../../../../../front_end/panels/application/InterestGroupStorageModel.ts", diff --git a/public/panels/application/application.d.ts b/public/panels/application/application.d.ts index cd8f7f761..e746375b6 100644 --- a/public/panels/application/application.d.ts +++ b/public/panels/application/application.d.ts @@ -6,6 +6,7 @@ import * as BounceTrackingMitigationsTreeElement from './BounceTrackingMitigatio import * as CookieItemsView from './CookieItemsView.js'; import * as DOMStorageItemsView from './DOMStorageItemsView.js'; import * as DOMStorageModel from './DOMStorageModel.js'; +import * as ExtensionStorageModel from './ExtensionStorageModel.js'; import * as IndexedDBModel from './IndexedDBModel.js'; import * as IndexedDBViews from './IndexedDBViews.js'; import * as InterestGroupStorageModel from './InterestGroupStorageModel.js'; @@ -29,4 +30,4 @@ import * as StorageBucketsTreeElement from './StorageBucketsTreeElement.js'; import * as StorageItemsView from './StorageItemsView.js'; import * as StorageView from './StorageView.js'; import * as TrustTokensTreeElement from './TrustTokensTreeElement.js'; -export { ApplicationPanelSidebar, AppManifestView, BackgroundServiceModel, BackgroundServiceView, BounceTrackingMitigationsTreeElement, CookieItemsView, DOMStorageItemsView, DOMStorageModel, IndexedDBModel, IndexedDBViews, InterestGroupStorageModel, InterestGroupStorageView, InterestGroupTreeElement, OpenedWindowDetailsView, PreloadingTreeElement, PreloadingView, ReportingApiReportsView, ReportingApiView, ResourcesPanel, ServiceWorkerCacheViews, ServiceWorkersView, ServiceWorkerUpdateCycleView, SharedStorageEventsView, SharedStorageItemsView, SharedStorageListTreeElement, SharedStorageModel, SharedStorageTreeElement, StorageBucketsTreeElement, StorageItemsView, StorageView, TrustTokensTreeElement, }; +export { ApplicationPanelSidebar, AppManifestView, BackgroundServiceModel, BackgroundServiceView, BounceTrackingMitigationsTreeElement, CookieItemsView, DOMStorageItemsView, DOMStorageModel, ExtensionStorageModel, IndexedDBModel, IndexedDBViews, InterestGroupStorageModel, InterestGroupStorageView, InterestGroupTreeElement, OpenedWindowDetailsView, PreloadingTreeElement, PreloadingView, ReportingApiReportsView, ReportingApiView, ResourcesPanel, ServiceWorkerCacheViews, ServiceWorkersView, ServiceWorkerUpdateCycleView, SharedStorageEventsView, SharedStorageItemsView, SharedStorageListTreeElement, SharedStorageModel, SharedStorageTreeElement, StorageBucketsTreeElement, StorageItemsView, StorageView, TrustTokensTreeElement, }; diff --git a/public/panels/application/application.js b/public/panels/application/application.js index 1577e1468..e03971aec 100644 --- a/public/panels/application/application.js +++ b/public/panels/application/application.js @@ -9,6 +9,7 @@ import * as BounceTrackingMitigationsTreeElement from './BounceTrackingMitigatio import * as CookieItemsView from './CookieItemsView.js'; import * as DOMStorageItemsView from './DOMStorageItemsView.js'; import * as DOMStorageModel from './DOMStorageModel.js'; +import * as ExtensionStorageModel from './ExtensionStorageModel.js'; import * as IndexedDBModel from './IndexedDBModel.js'; import * as IndexedDBViews from './IndexedDBViews.js'; import * as InterestGroupStorageModel from './InterestGroupStorageModel.js'; @@ -32,5 +33,5 @@ import * as StorageBucketsTreeElement from './StorageBucketsTreeElement.js'; import * as StorageItemsView from './StorageItemsView.js'; import * as StorageView from './StorageView.js'; import * as TrustTokensTreeElement from './TrustTokensTreeElement.js'; -export { ApplicationPanelSidebar, AppManifestView, BackgroundServiceModel, BackgroundServiceView, BounceTrackingMitigationsTreeElement, CookieItemsView, DOMStorageItemsView, DOMStorageModel, IndexedDBModel, IndexedDBViews, InterestGroupStorageModel, InterestGroupStorageView, InterestGroupTreeElement, OpenedWindowDetailsView, PreloadingTreeElement, PreloadingView, ReportingApiReportsView, ReportingApiView, ResourcesPanel, ServiceWorkerCacheViews, ServiceWorkersView, ServiceWorkerUpdateCycleView, SharedStorageEventsView, SharedStorageItemsView, SharedStorageListTreeElement, SharedStorageModel, SharedStorageTreeElement, StorageBucketsTreeElement, StorageItemsView, StorageView, TrustTokensTreeElement, }; +export { ApplicationPanelSidebar, AppManifestView, BackgroundServiceModel, BackgroundServiceView, BounceTrackingMitigationsTreeElement, CookieItemsView, DOMStorageItemsView, DOMStorageModel, ExtensionStorageModel, IndexedDBModel, IndexedDBViews, InterestGroupStorageModel, InterestGroupStorageView, InterestGroupTreeElement, OpenedWindowDetailsView, PreloadingTreeElement, PreloadingView, ReportingApiReportsView, ReportingApiView, ResourcesPanel, ServiceWorkerCacheViews, ServiceWorkersView, ServiceWorkerUpdateCycleView, SharedStorageEventsView, SharedStorageItemsView, SharedStorageListTreeElement, SharedStorageModel, SharedStorageTreeElement, StorageBucketsTreeElement, StorageItemsView, StorageView, TrustTokensTreeElement, }; //# sourceMappingURL=application.js.map \ No newline at end of file diff --git a/public/panels/application/application.js.map b/public/panels/application/application.js.map index d2a8fa70d..294b98667 100644 --- a/public/panels/application/application.js.map +++ b/public/panels/application/application.js.map @@ -1 +1 @@ -{"version":3,"file":"application.js","sourceRoot":"","sources":["../../../../../../front_end/panels/application/application.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,uBAAuB,MAAM,8BAA8B,CAAC;AACxE,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,sBAAsB,MAAM,6BAA6B,CAAC;AACtE,OAAO,KAAK,qBAAqB,MAAM,4BAA4B,CAAC;AACpE,OAAO,KAAK,oCAAoC,MAAM,2CAA2C,CAAC;AAClG,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,mBAAmB,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,yBAAyB,MAAM,gCAAgC,CAAC;AAC5E,OAAO,KAAK,wBAAwB,MAAM,+BAA+B,CAAC;AAC1E,OAAO,KAAK,wBAAwB,MAAM,+BAA+B,CAAC;AAC1E,OAAO,KAAK,uBAAuB,MAAM,8BAA8B,CAAC;AACxE,OAAO,KAAK,cAAc,MAAM,gCAAgC,CAAC;AACjE,OAAO,KAAK,qBAAqB,MAAM,4BAA4B,CAAC;AACpE,OAAO,KAAK,uBAAuB,MAAM,8BAA8B,CAAC;AACxE,OAAO,KAAK,gBAAgB,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,uBAAuB,MAAM,8BAA8B,CAAC;AACxE,OAAO,KAAK,kBAAkB,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,4BAA4B,MAAM,mCAAmC,CAAC;AAClF,OAAO,KAAK,uBAAuB,MAAM,8BAA8B,CAAC;AACxE,OAAO,KAAK,sBAAsB,MAAM,6BAA6B,CAAC;AACtE,OAAO,KAAK,4BAA4B,MAAM,mCAAmC,CAAC;AAClF,OAAO,KAAK,kBAAkB,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,wBAAwB,MAAM,+BAA+B,CAAC;AAC1E,OAAO,KAAK,yBAAyB,MAAM,gCAAgC,CAAC;AAC5E,OAAO,KAAK,gBAAgB,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC;AAChD,OAAO,KAAK,sBAAsB,MAAM,6BAA6B,CAAC;AAEtE,OAAO,EACL,uBAAuB,EACvB,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,oCAAoC,EACpC,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,cAAc,EACd,yBAAyB,EACzB,wBAAwB,EACxB,wBAAwB,EACxB,uBAAuB,EACvB,qBAAqB,EACrB,cAAc,EACd,uBAAuB,EACvB,gBAAgB,EAChB,cAAc,EACd,uBAAuB,EACvB,kBAAkB,EAClB,4BAA4B,EAC5B,uBAAuB,EACvB,sBAAsB,EACtB,4BAA4B,EAC5B,kBAAkB,EAClB,wBAAwB,EACxB,yBAAyB,EACzB,gBAAgB,EAChB,WAAW,EACX,sBAAsB,GACvB,CAAC","sourcesContent":["// Copyright 2019 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as ApplicationPanelSidebar from './ApplicationPanelSidebar.js';\nimport * as AppManifestView from './AppManifestView.js';\nimport * as BackgroundServiceModel from './BackgroundServiceModel.js';\nimport * as BackgroundServiceView from './BackgroundServiceView.js';\nimport * as BounceTrackingMitigationsTreeElement from './BounceTrackingMitigationsTreeElement.js';\nimport * as CookieItemsView from './CookieItemsView.js';\nimport * as DOMStorageItemsView from './DOMStorageItemsView.js';\nimport * as DOMStorageModel from './DOMStorageModel.js';\nimport * as IndexedDBModel from './IndexedDBModel.js';\nimport * as IndexedDBViews from './IndexedDBViews.js';\nimport * as InterestGroupStorageModel from './InterestGroupStorageModel.js';\nimport * as InterestGroupStorageView from './InterestGroupStorageView.js';\nimport * as InterestGroupTreeElement from './InterestGroupTreeElement.js';\nimport * as OpenedWindowDetailsView from './OpenedWindowDetailsView.js';\nimport * as PreloadingView from './preloading/PreloadingView.js';\nimport * as PreloadingTreeElement from './PreloadingTreeElement.js';\nimport * as ReportingApiReportsView from './ReportingApiReportsView.js';\nimport * as ReportingApiView from './ReportingApiView.js';\nimport * as ResourcesPanel from './ResourcesPanel.js';\nimport * as ServiceWorkerCacheViews from './ServiceWorkerCacheViews.js';\nimport * as ServiceWorkersView from './ServiceWorkersView.js';\nimport * as ServiceWorkerUpdateCycleView from './ServiceWorkerUpdateCycleView.js';\nimport * as SharedStorageEventsView from './SharedStorageEventsView.js';\nimport * as SharedStorageItemsView from './SharedStorageItemsView.js';\nimport * as SharedStorageListTreeElement from './SharedStorageListTreeElement.js';\nimport * as SharedStorageModel from './SharedStorageModel.js';\nimport * as SharedStorageTreeElement from './SharedStorageTreeElement.js';\nimport * as StorageBucketsTreeElement from './StorageBucketsTreeElement.js';\nimport * as StorageItemsView from './StorageItemsView.js';\nimport * as StorageView from './StorageView.js';\nimport * as TrustTokensTreeElement from './TrustTokensTreeElement.js';\n\nexport {\n ApplicationPanelSidebar,\n AppManifestView,\n BackgroundServiceModel,\n BackgroundServiceView,\n BounceTrackingMitigationsTreeElement,\n CookieItemsView,\n DOMStorageItemsView,\n DOMStorageModel,\n IndexedDBModel,\n IndexedDBViews,\n InterestGroupStorageModel,\n InterestGroupStorageView,\n InterestGroupTreeElement,\n OpenedWindowDetailsView,\n PreloadingTreeElement,\n PreloadingView,\n ReportingApiReportsView,\n ReportingApiView,\n ResourcesPanel,\n ServiceWorkerCacheViews,\n ServiceWorkersView,\n ServiceWorkerUpdateCycleView,\n SharedStorageEventsView,\n SharedStorageItemsView,\n SharedStorageListTreeElement,\n SharedStorageModel,\n SharedStorageTreeElement,\n StorageBucketsTreeElement,\n StorageItemsView,\n StorageView,\n TrustTokensTreeElement,\n};\n"]} \ No newline at end of file +{"version":3,"file":"application.js","sourceRoot":"","sources":["../../../../../../front_end/panels/application/application.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,uBAAuB,MAAM,8BAA8B,CAAC;AACxE,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,sBAAsB,MAAM,6BAA6B,CAAC;AACtE,OAAO,KAAK,qBAAqB,MAAM,4BAA4B,CAAC;AACpE,OAAO,KAAK,oCAAoC,MAAM,2CAA2C,CAAC;AAClG,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,mBAAmB,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAC;AACxD,OAAO,KAAK,qBAAqB,MAAM,4BAA4B,CAAC;AACpE,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,yBAAyB,MAAM,gCAAgC,CAAC;AAC5E,OAAO,KAAK,wBAAwB,MAAM,+BAA+B,CAAC;AAC1E,OAAO,KAAK,wBAAwB,MAAM,+BAA+B,CAAC;AAC1E,OAAO,KAAK,uBAAuB,MAAM,8BAA8B,CAAC;AACxE,OAAO,KAAK,cAAc,MAAM,gCAAgC,CAAC;AACjE,OAAO,KAAK,qBAAqB,MAAM,4BAA4B,CAAC;AACpE,OAAO,KAAK,uBAAuB,MAAM,8BAA8B,CAAC;AACxE,OAAO,KAAK,gBAAgB,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,uBAAuB,MAAM,8BAA8B,CAAC;AACxE,OAAO,KAAK,kBAAkB,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,4BAA4B,MAAM,mCAAmC,CAAC;AAClF,OAAO,KAAK,uBAAuB,MAAM,8BAA8B,CAAC;AACxE,OAAO,KAAK,sBAAsB,MAAM,6BAA6B,CAAC;AACtE,OAAO,KAAK,4BAA4B,MAAM,mCAAmC,CAAC;AAClF,OAAO,KAAK,kBAAkB,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,wBAAwB,MAAM,+BAA+B,CAAC;AAC1E,OAAO,KAAK,yBAAyB,MAAM,gCAAgC,CAAC;AAC5E,OAAO,KAAK,gBAAgB,MAAM,uBAAuB,CAAC;AAC1D,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAC;AAChD,OAAO,KAAK,sBAAsB,MAAM,6BAA6B,CAAC;AAEtE,OAAO,EACL,uBAAuB,EACvB,eAAe,EACf,sBAAsB,EACtB,qBAAqB,EACrB,oCAAoC,EACpC,eAAe,EACf,mBAAmB,EACnB,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,cAAc,EACd,yBAAyB,EACzB,wBAAwB,EACxB,wBAAwB,EACxB,uBAAuB,EACvB,qBAAqB,EACrB,cAAc,EACd,uBAAuB,EACvB,gBAAgB,EAChB,cAAc,EACd,uBAAuB,EACvB,kBAAkB,EAClB,4BAA4B,EAC5B,uBAAuB,EACvB,sBAAsB,EACtB,4BAA4B,EAC5B,kBAAkB,EAClB,wBAAwB,EACxB,yBAAyB,EACzB,gBAAgB,EAChB,WAAW,EACX,sBAAsB,GACvB,CAAC","sourcesContent":["// Copyright 2019 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as ApplicationPanelSidebar from './ApplicationPanelSidebar.js';\nimport * as AppManifestView from './AppManifestView.js';\nimport * as BackgroundServiceModel from './BackgroundServiceModel.js';\nimport * as BackgroundServiceView from './BackgroundServiceView.js';\nimport * as BounceTrackingMitigationsTreeElement from './BounceTrackingMitigationsTreeElement.js';\nimport * as CookieItemsView from './CookieItemsView.js';\nimport * as DOMStorageItemsView from './DOMStorageItemsView.js';\nimport * as DOMStorageModel from './DOMStorageModel.js';\nimport * as ExtensionStorageModel from './ExtensionStorageModel.js';\nimport * as IndexedDBModel from './IndexedDBModel.js';\nimport * as IndexedDBViews from './IndexedDBViews.js';\nimport * as InterestGroupStorageModel from './InterestGroupStorageModel.js';\nimport * as InterestGroupStorageView from './InterestGroupStorageView.js';\nimport * as InterestGroupTreeElement from './InterestGroupTreeElement.js';\nimport * as OpenedWindowDetailsView from './OpenedWindowDetailsView.js';\nimport * as PreloadingView from './preloading/PreloadingView.js';\nimport * as PreloadingTreeElement from './PreloadingTreeElement.js';\nimport * as ReportingApiReportsView from './ReportingApiReportsView.js';\nimport * as ReportingApiView from './ReportingApiView.js';\nimport * as ResourcesPanel from './ResourcesPanel.js';\nimport * as ServiceWorkerCacheViews from './ServiceWorkerCacheViews.js';\nimport * as ServiceWorkersView from './ServiceWorkersView.js';\nimport * as ServiceWorkerUpdateCycleView from './ServiceWorkerUpdateCycleView.js';\nimport * as SharedStorageEventsView from './SharedStorageEventsView.js';\nimport * as SharedStorageItemsView from './SharedStorageItemsView.js';\nimport * as SharedStorageListTreeElement from './SharedStorageListTreeElement.js';\nimport * as SharedStorageModel from './SharedStorageModel.js';\nimport * as SharedStorageTreeElement from './SharedStorageTreeElement.js';\nimport * as StorageBucketsTreeElement from './StorageBucketsTreeElement.js';\nimport * as StorageItemsView from './StorageItemsView.js';\nimport * as StorageView from './StorageView.js';\nimport * as TrustTokensTreeElement from './TrustTokensTreeElement.js';\n\nexport {\n ApplicationPanelSidebar,\n AppManifestView,\n BackgroundServiceModel,\n BackgroundServiceView,\n BounceTrackingMitigationsTreeElement,\n CookieItemsView,\n DOMStorageItemsView,\n DOMStorageModel,\n ExtensionStorageModel,\n IndexedDBModel,\n IndexedDBViews,\n InterestGroupStorageModel,\n InterestGroupStorageView,\n InterestGroupTreeElement,\n OpenedWindowDetailsView,\n PreloadingTreeElement,\n PreloadingView,\n ReportingApiReportsView,\n ReportingApiView,\n ResourcesPanel,\n ServiceWorkerCacheViews,\n ServiceWorkersView,\n ServiceWorkerUpdateCycleView,\n SharedStorageEventsView,\n SharedStorageItemsView,\n SharedStorageListTreeElement,\n SharedStorageModel,\n SharedStorageTreeElement,\n StorageBucketsTreeElement,\n StorageItemsView,\n StorageView,\n TrustTokensTreeElement,\n};\n"]} \ No newline at end of file diff --git a/public/panels/application/unittests-tsconfig.json b/public/panels/application/unittests-tsconfig.json index b2be34a4c..a7e3fbfef 100644 --- a/public/panels/application/unittests-tsconfig.json +++ b/public/panels/application/unittests-tsconfig.json @@ -42,6 +42,7 @@ "../../../../../../front_end/panels/application/ApplicationPanelSidebar.test.ts", "../../../../../../front_end/panels/application/BackgroundServiceView.test.ts", "../../../../../../front_end/panels/application/DOMStorageModel.test.ts", + "../../../../../../front_end/panels/application/ExtensionStorageModel.test.ts", "../../../../../../front_end/panels/application/IndexedDBModel.test.ts", "../../../../../../front_end/panels/application/IndexedDBViews.test.ts", "../../../../../../front_end/panels/application/InterestGroupStorageView.test.ts", diff --git a/public/panels/console/ConsolePinPane.js b/public/panels/console/ConsolePinPane.js index 7a23fd2a4..84aa52457 100644 --- a/public/panels/console/ConsolePinPane.js +++ b/public/panels/console/ConsolePinPane.js @@ -249,7 +249,19 @@ export class ConsolePin { { key: 'Tab', run: (view) => { - if (CodeMirror.completionStatus !== null) { + if (CodeMirror.completionStatus(this.editor.state) !== null) { + return false; + } + // User should be able to tab out of edit field after auto complete is done + view.dispatch({ changes: { from: 0, to: view.state.doc.length, insert: this.committedExpression } }); + this.focusOut(); + return true; + }, + }, + { + key: 'Shift-Tab', + run: (view) => { + if (CodeMirror.completionStatus(this.editor.state) !== null) { return false; } // User should be able to tab out of edit field after auto complete is done diff --git a/public/panels/console/ConsolePinPane.js.map b/public/panels/console/ConsolePinPane.js.map index f89f802d1..8f2a01803 100644 --- a/public/panels/console/ConsolePinPane.js.map +++ b/public/panels/console/ConsolePinPane.js.map @@ -1 +1 @@ -{"version":3,"file":"ConsolePinPane.js","sourceRoot":"","sources":["../../../../../../front_end/panels/console/ConsolePinPane.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Root from '../../core/root/root.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';\nimport * as TextEditor from '../../ui/components/text_editor/text_editor.js';\nimport * as ObjectUI from '../../ui/legacy/components/object_ui/object_ui.js';\n// eslint-disable-next-line rulesdir/es_modules_import\nimport objectValueStyles from '../../ui/legacy/components/object_ui/objectValue.css.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport consolePinPaneStyles from './consolePinPane.css.js';\n\nconst UIStrings = {\n /**\n *@description A context menu item in the Console Pin Pane of the Console panel\n */\n removeExpression: 'Remove expression',\n /**\n *@description A context menu item in the Console Pin Pane of the Console panel\n */\n removeAllExpressions: 'Remove all expressions',\n /**\n *@description Screen reader label for delete button on a non-blank live expression\n *@example {document} PH1\n */\n removeExpressionS: 'Remove expression: {PH1}',\n /**\n *@description Screen reader label for delete button on a blank live expression\n */\n removeBlankExpression: 'Remove blank expression',\n /**\n *@description Text in Console Pin Pane of the Console panel\n */\n liveExpressionEditor: 'Live expression editor',\n /**\n *@description Text in Console Pin Pane of the Console panel\n */\n expression: 'Expression',\n /**\n *@description Side effect label title in Console Pin Pane of the Console panel\n */\n evaluateAllowingSideEffects: 'Evaluate, allowing side effects',\n /**\n *@description Text of a DOM element in Console Pin Pane of the Console panel\n */\n notAvailable: 'not available',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/console/ConsolePinPane.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nconst elementToConsolePin = new WeakMap();\n\nexport class ConsolePinPane extends UI.ThrottledWidget.ThrottledWidget {\n private pins: Set;\n private readonly pinsSetting: Common.Settings.Setting;\n constructor(private readonly liveExpressionButton: UI.Toolbar.ToolbarButton, private readonly focusOut: () => void) {\n super(true, 250);\n this.contentElement.classList.add('console-pins', 'monospace');\n this.contentElement.addEventListener('contextmenu', this.contextMenuEventFired.bind(this), false);\n this.contentElement.setAttribute('jslog', `${VisualLogging.pane('console-pins')}`);\n\n this.pins = new Set();\n this.pinsSetting = Common.Settings.Settings.instance().createLocalSetting('console-pins', []);\n for (const expression of this.pinsSetting.get()) {\n this.addPin(expression);\n }\n }\n\n override wasShown(): void {\n super.wasShown();\n this.registerCSSFiles([consolePinPaneStyles, objectValueStyles]);\n }\n\n override willHide(): void {\n for (const pin of this.pins) {\n pin.setHovered(false);\n }\n }\n\n savePins(): void {\n const toSave = Array.from(this.pins).map(pin => pin.expression());\n this.pinsSetting.set(toSave);\n }\n\n private contextMenuEventFired(event: Event): void {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n const target = UI.UIUtils.deepElementFromEvent(event);\n if (target) {\n const targetPinElement = target.enclosingNodeOrSelfWithClass('console-pin');\n if (targetPinElement) {\n const targetPin = elementToConsolePin.get(targetPinElement);\n if (targetPin) {\n contextMenu.editSection().appendItem(\n i18nString(UIStrings.removeExpression), this.removePin.bind(this, targetPin),\n {jslogContext: 'remove-expression'});\n targetPin.appendToContextMenu(contextMenu);\n }\n }\n }\n contextMenu.editSection().appendItem(\n i18nString(UIStrings.removeAllExpressions), this.removeAllPins.bind(this),\n {jslogContext: 'remove-all-expressions'});\n void contextMenu.show();\n }\n\n private removeAllPins(): void {\n for (const pin of this.pins) {\n this.removePin(pin);\n }\n }\n\n removePin(pin: ConsolePin): void {\n pin.element().remove();\n const newFocusedPin = this.focusedPinAfterDeletion(pin);\n this.pins.delete(pin);\n this.savePins();\n if (newFocusedPin) {\n void newFocusedPin.focus();\n } else {\n this.liveExpressionButton.focus();\n }\n }\n\n addPin(expression: string, userGesture?: boolean): void {\n const pin = new ConsolePin(expression, this, this.focusOut);\n this.contentElement.appendChild(pin.element());\n this.pins.add(pin);\n this.savePins();\n if (userGesture) {\n void pin.focus();\n }\n this.update();\n }\n\n private focusedPinAfterDeletion(deletedPin: ConsolePin): ConsolePin|null {\n const pinArray = Array.from(this.pins);\n for (let i = 0; i < pinArray.length; i++) {\n if (pinArray[i] === deletedPin) {\n if (pinArray.length === 1) {\n return null;\n }\n if (i === pinArray.length - 1) {\n return pinArray[i - 1];\n }\n return pinArray[i + 1];\n }\n }\n return null;\n }\n\n override async doUpdate(): Promise {\n if (!this.pins.size || !this.isShowing()) {\n return;\n }\n if (this.isShowing()) {\n this.update();\n }\n const updatePromises = Array.from(this.pins, pin => pin.updatePreview());\n await Promise.all(updatePromises);\n this.updatedForTest();\n }\n\n private updatedForTest(): void {\n }\n}\n\nexport class ConsolePin {\n private readonly pinElement: Element;\n private readonly pinPreview: HTMLElement;\n private lastResult: SDK.RuntimeModel.EvaluationResult|null;\n private lastExecutionContext: SDK.RuntimeModel.ExecutionContext|null;\n private editor: TextEditor.TextEditor.TextEditor;\n private committedExpression: string;\n private hovered: boolean;\n private lastNode: SDK.RemoteObject.RemoteObject|null;\n private deletePinIcon: UI.UIUtils.DevToolsCloseButton;\n\n constructor(expression: string, private readonly pinPane: ConsolePinPane, private readonly focusOut: () => void) {\n this.deletePinIcon = document.createElement('div', {is: 'dt-close-button'}) as UI.UIUtils.DevToolsCloseButton;\n this.deletePinIcon.classList.add('close-button');\n this.deletePinIcon.setTabbable(true);\n if (expression.length) {\n this.deletePinIcon.setAccessibleName(i18nString(UIStrings.removeExpressionS, {PH1: expression}));\n } else {\n this.deletePinIcon.setAccessibleName(i18nString(UIStrings.removeBlankExpression));\n }\n self.onInvokeElement(this.deletePinIcon, event => {\n pinPane.removePin(this);\n event.consume(true);\n });\n\n const fragment = UI.Fragment.Fragment.build`\n
\n ${this.deletePinIcon}\n
\n
\n
`;\n this.pinElement = fragment.element();\n this.pinPreview = (fragment.$('preview') as HTMLElement);\n const nameElement = (fragment.$('name') as HTMLElement);\n UI.Tooltip.Tooltip.install(nameElement, expression);\n elementToConsolePin.set(this.pinElement, this);\n\n this.lastResult = null;\n this.lastExecutionContext = null;\n this.committedExpression = expression;\n this.hovered = false;\n this.lastNode = null;\n this.editor = this.createEditor(expression, nameElement);\n\n this.pinPreview.addEventListener('mouseenter', this.setHovered.bind(this, true), false);\n this.pinPreview.addEventListener('mouseleave', this.setHovered.bind(this, false), false);\n this.pinPreview.addEventListener('click', (event: Event) => {\n if (this.lastNode) {\n void Common.Revealer.reveal(this.lastNode);\n event.consume();\n }\n }, false);\n\n // Prevent Esc from toggling the drawer\n nameElement.addEventListener('keydown', event => {\n if (event.key === 'Escape') {\n event.consume();\n }\n });\n }\n\n createEditor(doc: string, parent: HTMLElement): TextEditor.TextEditor.TextEditor {\n const extensions = [\n CodeMirror.EditorView.contentAttributes.of({'aria-label': i18nString(UIStrings.liveExpressionEditor)}),\n CodeMirror.EditorView.lineWrapping,\n CodeMirror.javascript.javascriptLanguage,\n TextEditor.Config.showCompletionHint,\n CodeMirror.placeholder(i18nString(UIStrings.expression)),\n CodeMirror.keymap.of([\n {\n key: 'Escape',\n run: (view: CodeMirror.EditorView) => {\n view.dispatch({changes: {from: 0, to: view.state.doc.length, insert: this.committedExpression}});\n this.focusOut();\n return true;\n },\n },\n {\n key: 'Enter',\n run: () => {\n this.focusOut();\n return true;\n },\n },\n {\n key: 'Mod-Enter',\n run: () => {\n this.focusOut();\n return true;\n },\n },\n {\n key: 'Tab',\n run: (view: CodeMirror.EditorView) => {\n if (CodeMirror.completionStatus !== null) {\n return false;\n }\n // User should be able to tab out of edit field after auto complete is done\n view.dispatch({changes: {from: 0, to: view.state.doc.length, insert: this.committedExpression}});\n this.focusOut();\n return true;\n },\n },\n ]),\n CodeMirror.EditorView.domEventHandlers({blur: (_e, view) => this.onBlur(view)}),\n TextEditor.Config.baseConfiguration(doc),\n TextEditor.Config.closeBrackets.instance(),\n TextEditor.Config.autocompletion.instance(),\n ];\n if (Root.Runtime.Runtime.queryParam('noJavaScriptCompletion') !== 'true') {\n extensions.push(TextEditor.JavaScript.completion());\n }\n const editor = new TextEditor.TextEditor.TextEditor(CodeMirror.EditorState.create({doc, extensions}));\n parent.appendChild(editor);\n return editor;\n }\n\n onBlur(editor: CodeMirror.EditorView): void {\n const text = editor.state.doc.toString();\n const trimmedText = text.trim();\n this.committedExpression = trimmedText;\n this.pinPane.savePins();\n if (this.committedExpression.length) {\n this.deletePinIcon.setAccessibleName(i18nString(UIStrings.removeExpressionS, {PH1: this.committedExpression}));\n } else {\n this.deletePinIcon.setAccessibleName(i18nString(UIStrings.removeBlankExpression));\n }\n editor.dispatch({\n selection: {anchor: trimmedText.length},\n changes: trimmedText !== text ? {from: 0, to: text.length, insert: trimmedText} : undefined,\n });\n }\n\n setHovered(hovered: boolean): void {\n if (this.hovered === hovered) {\n return;\n }\n this.hovered = hovered;\n if (!hovered && this.lastNode) {\n SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight();\n }\n }\n\n expression(): string {\n return this.committedExpression;\n }\n\n element(): Element {\n return this.pinElement;\n }\n\n async focus(): Promise {\n const editor = this.editor;\n editor.editor.focus();\n editor.dispatch({selection: {anchor: editor.state.doc.length}});\n }\n\n appendToContextMenu(contextMenu: UI.ContextMenu.ContextMenu): void {\n if (this.lastResult && !('error' in this.lastResult) && this.lastResult.object) {\n contextMenu.appendApplicableItems(this.lastResult.object);\n // Prevent result from being released manually. It will release along with 'console' group.\n this.lastResult = null;\n }\n }\n\n async updatePreview(): Promise {\n if (!this.editor) {\n return;\n }\n const text = TextEditor.Config.contentIncludingHint(this.editor.editor);\n const isEditing = this.pinElement.hasFocus();\n const throwOnSideEffect = isEditing && text !== this.committedExpression;\n const timeout = throwOnSideEffect ? 250 : undefined;\n const executionContext = UI.Context.Context.instance().flavor(SDK.RuntimeModel.ExecutionContext);\n const {preview, result} = await ObjectUI.JavaScriptREPL.JavaScriptREPL.evaluateAndBuildPreview(\n text, throwOnSideEffect, true /* replMode */, timeout, !isEditing /* allowErrors */, 'console',\n true /* awaitPromise */, true /* silent */);\n if (this.lastResult && this.lastExecutionContext) {\n this.lastExecutionContext.runtimeModel.releaseEvaluationResult(this.lastResult);\n }\n this.lastResult = result || null;\n this.lastExecutionContext = executionContext || null;\n\n const previewText = preview.deepTextContent();\n if (!previewText || previewText !== this.pinPreview.deepTextContent()) {\n this.pinPreview.removeChildren();\n if (result && SDK.RuntimeModel.RuntimeModel.isSideEffectFailure(result)) {\n const sideEffectLabel =\n (this.pinPreview.createChild('span', 'object-value-calculate-value-button') as HTMLElement);\n sideEffectLabel.textContent = '(…)';\n UI.Tooltip.Tooltip.install(sideEffectLabel, i18nString(UIStrings.evaluateAllowingSideEffects));\n } else if (previewText) {\n this.pinPreview.appendChild(preview);\n } else if (!isEditing) {\n UI.UIUtils.createTextChild(this.pinPreview, i18nString(UIStrings.notAvailable));\n }\n UI.Tooltip.Tooltip.install(this.pinPreview, previewText);\n }\n\n let node: SDK.RemoteObject.RemoteObject|null = null;\n if (result && !('error' in result) && result.object.type === 'object' && result.object.subtype === 'node') {\n node = result.object;\n }\n if (this.hovered) {\n if (node) {\n SDK.OverlayModel.OverlayModel.highlightObjectAsDOMNode(node);\n } else if (this.lastNode) {\n SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight();\n }\n }\n this.lastNode = node || null;\n\n const isError = result && !('error' in result) && result.exceptionDetails &&\n !SDK.RuntimeModel.RuntimeModel.isSideEffectFailure(result);\n this.pinElement.classList.toggle('error-level', Boolean(isError));\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"ConsolePinPane.js","sourceRoot":"","sources":["../../../../../../front_end/panels/console/ConsolePinPane.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,MAAM,MAAM,6BAA6B,CAAC;AACtD,OAAO,KAAK,IAAI,MAAM,yBAAyB,CAAC;AAChD,OAAO,KAAK,IAAI,MAAM,yBAAyB,CAAC;AAChD,OAAO,KAAK,GAAG,MAAM,uBAAuB,CAAC;AAC7C,OAAO,KAAK,UAAU,MAAM,sDAAsD,CAAC;AACnF,OAAO,KAAK,UAAU,MAAM,gDAAgD,CAAC;AAC7E,OAAO,KAAK,QAAQ,MAAM,mDAAmD,CAAC;AAC9E,sDAAsD;AACtD,OAAO,iBAAiB,MAAM,yDAAyD,CAAC;AACxF,OAAO,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAChD,OAAO,KAAK,aAAa,MAAM,2CAA2C,CAAC;AAE3E,OAAO,oBAAoB,MAAM,yBAAyB,CAAC;AAE3D,MAAM,SAAS,GAAG;IAChB;;OAEG;IACH,gBAAgB,EAAE,mBAAmB;IACrC;;OAEG;IACH,oBAAoB,EAAE,wBAAwB;IAC9C;;;OAGG;IACH,iBAAiB,EAAE,0BAA0B;IAC7C;;OAEG;IACH,qBAAqB,EAAE,yBAAyB;IAChD;;OAEG;IACH,oBAAoB,EAAE,wBAAwB;IAC9C;;OAEG;IACH,UAAU,EAAE,YAAY;IACxB;;OAEG;IACH,2BAA2B,EAAE,iCAAiC;IAC9D;;OAEG;IACH,YAAY,EAAE,eAAe;CAC9B,CAAC;AACF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,kCAAkC,EAAE,SAAS,CAAC,CAAC;AACxF,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAEtE,MAAM,mBAAmB,GAAG,IAAI,OAAO,EAAuB,CAAC;AAE/D,MAAM,OAAO,cAAe,SAAQ,EAAE,CAAC,eAAe,CAAC,eAAe;IAGvC;IAAiE;IAFtF,IAAI,CAAkB;IACb,WAAW,CAAoC;IAChE,YAA6B,oBAA8C,EAAmB,QAAoB;QAChH,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QADU,yBAAoB,GAApB,oBAAoB,CAA0B;QAAmB,aAAQ,GAAR,QAAQ,CAAY;QAEhH,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,GAAG,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;QAC/D,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC,aAAa,EAAE,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;QAClG,IAAI,CAAC,cAAc,CAAC,YAAY,CAAC,OAAO,EAAE,GAAG,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;QAEnF,IAAI,CAAC,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC;QACtB,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,kBAAkB,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;QAC9F,KAAK,MAAM,UAAU,IAAI,IAAI,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,CAAC;YAChD,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAEQ,QAAQ;QACf,KAAK,CAAC,QAAQ,EAAE,CAAC;QACjB,IAAI,CAAC,gBAAgB,CAAC,CAAC,oBAAoB,EAAE,iBAAiB,CAAC,CAAC,CAAC;IACnE,CAAC;IAEQ,QAAQ;QACf,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IAED,QAAQ;QACN,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;QAClE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAEO,qBAAqB,CAAC,KAAY;QACxC,MAAM,WAAW,GAAG,IAAI,EAAE,CAAC,WAAW,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC1D,MAAM,MAAM,GAAG,EAAE,CAAC,OAAO,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;QACtD,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,gBAAgB,GAAG,MAAM,CAAC,4BAA4B,CAAC,aAAa,CAAC,CAAC;YAC5E,IAAI,gBAAgB,EAAE,CAAC;gBACrB,MAAM,SAAS,GAAG,mBAAmB,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;gBAC5D,IAAI,SAAS,EAAE,CAAC;oBACd,WAAW,CAAC,WAAW,EAAE,CAAC,UAAU,CAChC,UAAU,CAAC,SAAS,CAAC,gBAAgB,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,EAC5E,EAAC,YAAY,EAAE,mBAAmB,EAAC,CAAC,CAAC;oBACzC,SAAS,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC;gBAC7C,CAAC;YACH,CAAC;QACH,CAAC;QACD,WAAW,CAAC,WAAW,EAAE,CAAC,UAAU,CAChC,UAAU,CAAC,SAAS,CAAC,oBAAoB,CAAC,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EACzE,EAAC,YAAY,EAAE,wBAAwB,EAAC,CAAC,CAAC;QAC9C,KAAK,WAAW,CAAC,IAAI,EAAE,CAAC;IAC1B,CAAC;IAEO,aAAa;QACnB,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;IAED,SAAS,CAAC,GAAe;QACvB,GAAG,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,CAAC;QACvB,MAAM,aAAa,GAAG,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAC;QACxD,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACtB,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChB,IAAI,aAAa,EAAE,CAAC;YAClB,KAAK,aAAa,CAAC,KAAK,EAAE,CAAC;QAC7B,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,oBAAoB,CAAC,KAAK,EAAE,CAAC;QACpC,CAAC;IACH,CAAC;IAED,MAAM,CAAC,UAAkB,EAAE,WAAqB;QAC9C,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC5D,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC/C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACnB,IAAI,CAAC,QAAQ,EAAE,CAAC;QAChB,IAAI,WAAW,EAAE,CAAC;YAChB,KAAK,GAAG,CAAC,KAAK,EAAE,CAAC;QACnB,CAAC;QACD,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IAEO,uBAAuB,CAAC,UAAsB;QACpD,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACzC,IAAI,QAAQ,CAAC,CAAC,CAAC,KAAK,UAAU,EAAE,CAAC;gBAC/B,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC1B,OAAO,IAAI,CAAC;gBACd,CAAC;gBACD,IAAI,CAAC,KAAK,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC9B,OAAO,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBACzB,CAAC;gBACD,OAAO,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YACzB,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAEQ,KAAK,CAAC,QAAQ;QACrB,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;YACzC,OAAO;QACT,CAAC;QACD,IAAI,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;YACrB,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,CAAC;QACD,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC;QACzE,MAAM,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAClC,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAEO,cAAc;IACtB,CAAC;CACF;AAED,MAAM,OAAO,UAAU;IAW4B;IAA0C;IAV1E,UAAU,CAAU;IACpB,UAAU,CAAc;IACjC,UAAU,CAAyC;IACnD,oBAAoB,CAAyC;IAC7D,MAAM,CAAmC;IACzC,mBAAmB,CAAS;IAC5B,OAAO,CAAU;IACjB,QAAQ,CAAqC;IAC7C,aAAa,CAAiC;IAEtD,YAAY,UAAkB,EAAmB,OAAuB,EAAmB,QAAoB;QAA9D,YAAO,GAAP,OAAO,CAAgB;QAAmB,aAAQ,GAAR,QAAQ,CAAY;QAC7G,IAAI,CAAC,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,EAAE,EAAC,EAAE,EAAE,iBAAiB,EAAC,CAAmC,CAAC;QAC9G,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QACjD,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,UAAU,CAAC,MAAM,EAAE,CAAC;YACtB,IAAI,CAAC,aAAa,CAAC,iBAAiB,CAAC,UAAU,CAAC,SAAS,CAAC,iBAAiB,EAAE,EAAC,GAAG,EAAE,UAAU,EAAC,CAAC,CAAC,CAAC;QACnG,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,aAAa,CAAC,iBAAiB,CAAC,UAAU,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC,CAAC;QACpF,CAAC;QACD,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,aAAa,EAAE,KAAK,CAAC,EAAE;YAC/C,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YACxB,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAA;;IAE3C,IAAI,CAAC,aAAa;kDAC4B,aAAa,CAAC,SAAS,EAAE,CAAC,KAAK,CAAC;YAC5E,MAAM,EAAE,IAAI;SACb,CAAC;;SAEG,CAAC;QACN,IAAI,CAAC,UAAU,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;QACrC,IAAI,CAAC,UAAU,GAAI,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAiB,CAAC;QACzD,MAAM,WAAW,GAAI,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAiB,CAAC;QACxD,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;QACpD,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QAE/C,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC;QACjC,IAAI,CAAC,mBAAmB,GAAG,UAAU,CAAC;QACtC,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QAEzD,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,YAAY,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;QACxF,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,YAAY,EAAE,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;QACzF,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,KAAY,EAAE,EAAE;YACzD,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAClB,KAAK,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC3C,KAAK,CAAC,OAAO,EAAE,CAAC;YAClB,CAAC;QACH,CAAC,EAAE,KAAK,CAAC,CAAC;QAEV,uCAAuC;QACvC,WAAW,CAAC,gBAAgB,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE;YAC9C,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;gBAC3B,KAAK,CAAC,OAAO,EAAE,CAAC;YAClB,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,YAAY,CAAC,GAAW,EAAE,MAAmB;QAC3C,MAAM,UAAU,GAAG;YACjB,UAAU,CAAC,UAAU,CAAC,iBAAiB,CAAC,EAAE,CAAC,EAAC,YAAY,EAAE,UAAU,CAAC,SAAS,CAAC,oBAAoB,CAAC,EAAC,CAAC;YACtG,UAAU,CAAC,UAAU,CAAC,YAAY;YAClC,UAAU,CAAC,UAAU,CAAC,kBAAkB;YACxC,UAAU,CAAC,MAAM,CAAC,kBAAkB;YACpC,UAAU,CAAC,WAAW,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;YACxD,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBACnB;oBACE,GAAG,EAAE,QAAQ;oBACb,GAAG,EAAE,CAAC,IAA2B,EAAE,EAAE;wBACnC,IAAI,CAAC,QAAQ,CAAC,EAAC,OAAO,EAAE,EAAC,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,mBAAmB,EAAC,EAAC,CAAC,CAAC;wBACjG,IAAI,CAAC,QAAQ,EAAE,CAAC;wBAChB,OAAO,IAAI,CAAC;oBACd,CAAC;iBACF;gBACD;oBACE,GAAG,EAAE,OAAO;oBACZ,GAAG,EAAE,GAAG,EAAE;wBACR,IAAI,CAAC,QAAQ,EAAE,CAAC;wBAChB,OAAO,IAAI,CAAC;oBACd,CAAC;iBACF;gBACD;oBACE,GAAG,EAAE,WAAW;oBAChB,GAAG,EAAE,GAAG,EAAE;wBACR,IAAI,CAAC,QAAQ,EAAE,CAAC;wBAChB,OAAO,IAAI,CAAC;oBACd,CAAC;iBACF;gBACD;oBACE,GAAG,EAAE,KAAK;oBACV,GAAG,EAAE,CAAC,IAA2B,EAAE,EAAE;wBACnC,IAAI,UAAU,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;4BAC5D,OAAO,KAAK,CAAC;wBACf,CAAC;wBACD,2EAA2E;wBAC3E,IAAI,CAAC,QAAQ,CAAC,EAAC,OAAO,EAAE,EAAC,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,mBAAmB,EAAC,EAAC,CAAC,CAAC;wBACjG,IAAI,CAAC,QAAQ,EAAE,CAAC;wBAChB,OAAO,IAAI,CAAC;oBACd,CAAC;iBACF;gBACD;oBACE,GAAG,EAAE,WAAW;oBAChB,GAAG,EAAE,CAAC,IAA2B,EAAE,EAAE;wBACnC,IAAI,UAAU,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;4BAC5D,OAAO,KAAK,CAAC;wBACf,CAAC;wBACD,2EAA2E;wBAC3E,IAAI,CAAC,QAAQ,CAAC,EAAC,OAAO,EAAE,EAAC,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,mBAAmB,EAAC,EAAC,CAAC,CAAC;wBACjG,IAAI,CAAC,QAAQ,EAAE,CAAC;wBAChB,OAAO,IAAI,CAAC;oBACd,CAAC;iBACF;aACF,CAAC;YACF,UAAU,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAC,IAAI,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAC,CAAC;YAC/E,UAAU,CAAC,MAAM,CAAC,iBAAiB,CAAC,GAAG,CAAC;YACxC,UAAU,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,EAAE;YAC1C,UAAU,CAAC,MAAM,CAAC,cAAc,CAAC,QAAQ,EAAE;SAC5C,CAAC;QACF,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,wBAAwB,CAAC,KAAK,MAAM,EAAE,CAAC;YACzE,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,UAAU,EAAE,CAAC,CAAC;QACtD,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,UAAU,CAAC,UAAU,CAAC,UAAU,CAAC,WAAW,CAAC,MAAM,CAAC,EAAC,GAAG,EAAE,UAAU,EAAC,CAAC,CAAC,CAAC;QACtG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAC3B,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,CAAC,MAA6B;QAClC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QACzC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAChC,IAAI,CAAC,mBAAmB,GAAG,WAAW,CAAC;QACvC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC;QACxB,IAAI,IAAI,CAAC,mBAAmB,CAAC,MAAM,EAAE,CAAC;YACpC,IAAI,CAAC,aAAa,CAAC,iBAAiB,CAAC,UAAU,CAAC,SAAS,CAAC,iBAAiB,EAAE,EAAC,GAAG,EAAE,IAAI,CAAC,mBAAmB,EAAC,CAAC,CAAC,CAAC;QACjH,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,aAAa,CAAC,iBAAiB,CAAC,UAAU,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC,CAAC;QACpF,CAAC;QACD,MAAM,CAAC,QAAQ,CAAC;YACd,SAAS,EAAE,EAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAC;YACvC,OAAO,EAAE,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,EAAC,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC,SAAS;SAC5F,CAAC,CAAC;IACL,CAAC;IAED,UAAU,CAAC,OAAgB;QACzB,IAAI,IAAI,CAAC,OAAO,KAAK,OAAO,EAAE,CAAC;YAC7B,OAAO;QACT,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC9B,GAAG,CAAC,YAAY,CAAC,YAAY,CAAC,oBAAoB,EAAE,CAAC;QACvD,CAAC;IACH,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,mBAAmB,CAAC;IAClC,CAAC;IAED,OAAO;QACL,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;IAED,KAAK,CAAC,KAAK;QACT,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC3B,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACtB,MAAM,CAAC,QAAQ,CAAC,EAAC,SAAS,EAAE,EAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,EAAC,EAAC,CAAC,CAAC;IAClE,CAAC;IAED,mBAAmB,CAAC,WAAuC;QACzD,IAAI,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;YAC/E,WAAW,CAAC,qBAAqB,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;YAC1D,2FAA2F;YAC3F,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACzB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,aAAa;QACjB,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACxE,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;QAC7C,MAAM,iBAAiB,GAAG,SAAS,IAAI,IAAI,KAAK,IAAI,CAAC,mBAAmB,CAAC;QACzE,MAAM,OAAO,GAAG,iBAAiB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;QACpD,MAAM,gBAAgB,GAAG,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;QACjG,MAAM,EAAC,OAAO,EAAE,MAAM,EAAC,GAAG,MAAM,QAAQ,CAAC,cAAc,CAAC,cAAc,CAAC,uBAAuB,CAC1F,IAAI,EAAE,iBAAiB,EAAE,IAAI,CAAC,cAAc,EAAE,OAAO,EAAE,CAAC,SAAS,CAAC,iBAAiB,EAAE,SAAS,EAC9F,IAAI,CAAC,kBAAkB,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QAChD,IAAI,IAAI,CAAC,UAAU,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;YACjD,IAAI,CAAC,oBAAoB,CAAC,YAAY,CAAC,uBAAuB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAClF,CAAC;QACD,IAAI,CAAC,UAAU,GAAG,MAAM,IAAI,IAAI,CAAC;QACjC,IAAI,CAAC,oBAAoB,GAAG,gBAAgB,IAAI,IAAI,CAAC;QAErD,MAAM,WAAW,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;QAC9C,IAAI,CAAC,WAAW,IAAI,WAAW,KAAK,IAAI,CAAC,UAAU,CAAC,eAAe,EAAE,EAAE,CAAC;YACtE,IAAI,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC;YACjC,IAAI,MAAM,IAAI,GAAG,CAAC,YAAY,CAAC,YAAY,CAAC,mBAAmB,CAAC,MAAM,CAAC,EAAE,CAAC;gBACxE,MAAM,eAAe,GAChB,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,MAAM,EAAE,qCAAqC,CAAiB,CAAC;gBAChG,eAAe,CAAC,WAAW,GAAG,KAAK,CAAC;gBACpC,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,eAAe,EAAE,UAAU,CAAC,SAAS,CAAC,2BAA2B,CAAC,CAAC,CAAC;YACjG,CAAC;iBAAM,IAAI,WAAW,EAAE,CAAC;gBACvB,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;YACvC,CAAC;iBAAM,IAAI,CAAC,SAAS,EAAE,CAAC;gBACtB,EAAE,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;YAClF,CAAC;YACD,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QAC3D,CAAC;QAED,IAAI,IAAI,GAAuC,IAAI,CAAC;QACpD,IAAI,MAAM,IAAI,CAAC,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;YAC1G,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC;QACvB,CAAC;QACD,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,IAAI,IAAI,EAAE,CAAC;gBACT,GAAG,CAAC,YAAY,CAAC,YAAY,CAAC,wBAAwB,CAAC,IAAI,CAAC,CAAC;YAC/D,CAAC;iBAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACzB,GAAG,CAAC,YAAY,CAAC,YAAY,CAAC,oBAAoB,EAAE,CAAC;YACvD,CAAC;QACH,CAAC;QACD,IAAI,CAAC,QAAQ,GAAG,IAAI,IAAI,IAAI,CAAC;QAE7B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,MAAM,CAAC,gBAAgB;YACrE,CAAC,GAAG,CAAC,YAAY,CAAC,YAAY,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC;QAC/D,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC,aAAa,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IACpE,CAAC;CACF","sourcesContent":["// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Root from '../../core/root/root.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';\nimport * as TextEditor from '../../ui/components/text_editor/text_editor.js';\nimport * as ObjectUI from '../../ui/legacy/components/object_ui/object_ui.js';\n// eslint-disable-next-line rulesdir/es_modules_import\nimport objectValueStyles from '../../ui/legacy/components/object_ui/objectValue.css.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport consolePinPaneStyles from './consolePinPane.css.js';\n\nconst UIStrings = {\n /**\n *@description A context menu item in the Console Pin Pane of the Console panel\n */\n removeExpression: 'Remove expression',\n /**\n *@description A context menu item in the Console Pin Pane of the Console panel\n */\n removeAllExpressions: 'Remove all expressions',\n /**\n *@description Screen reader label for delete button on a non-blank live expression\n *@example {document} PH1\n */\n removeExpressionS: 'Remove expression: {PH1}',\n /**\n *@description Screen reader label for delete button on a blank live expression\n */\n removeBlankExpression: 'Remove blank expression',\n /**\n *@description Text in Console Pin Pane of the Console panel\n */\n liveExpressionEditor: 'Live expression editor',\n /**\n *@description Text in Console Pin Pane of the Console panel\n */\n expression: 'Expression',\n /**\n *@description Side effect label title in Console Pin Pane of the Console panel\n */\n evaluateAllowingSideEffects: 'Evaluate, allowing side effects',\n /**\n *@description Text of a DOM element in Console Pin Pane of the Console panel\n */\n notAvailable: 'not available',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/console/ConsolePinPane.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nconst elementToConsolePin = new WeakMap();\n\nexport class ConsolePinPane extends UI.ThrottledWidget.ThrottledWidget {\n private pins: Set;\n private readonly pinsSetting: Common.Settings.Setting;\n constructor(private readonly liveExpressionButton: UI.Toolbar.ToolbarButton, private readonly focusOut: () => void) {\n super(true, 250);\n this.contentElement.classList.add('console-pins', 'monospace');\n this.contentElement.addEventListener('contextmenu', this.contextMenuEventFired.bind(this), false);\n this.contentElement.setAttribute('jslog', `${VisualLogging.pane('console-pins')}`);\n\n this.pins = new Set();\n this.pinsSetting = Common.Settings.Settings.instance().createLocalSetting('console-pins', []);\n for (const expression of this.pinsSetting.get()) {\n this.addPin(expression);\n }\n }\n\n override wasShown(): void {\n super.wasShown();\n this.registerCSSFiles([consolePinPaneStyles, objectValueStyles]);\n }\n\n override willHide(): void {\n for (const pin of this.pins) {\n pin.setHovered(false);\n }\n }\n\n savePins(): void {\n const toSave = Array.from(this.pins).map(pin => pin.expression());\n this.pinsSetting.set(toSave);\n }\n\n private contextMenuEventFired(event: Event): void {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n const target = UI.UIUtils.deepElementFromEvent(event);\n if (target) {\n const targetPinElement = target.enclosingNodeOrSelfWithClass('console-pin');\n if (targetPinElement) {\n const targetPin = elementToConsolePin.get(targetPinElement);\n if (targetPin) {\n contextMenu.editSection().appendItem(\n i18nString(UIStrings.removeExpression), this.removePin.bind(this, targetPin),\n {jslogContext: 'remove-expression'});\n targetPin.appendToContextMenu(contextMenu);\n }\n }\n }\n contextMenu.editSection().appendItem(\n i18nString(UIStrings.removeAllExpressions), this.removeAllPins.bind(this),\n {jslogContext: 'remove-all-expressions'});\n void contextMenu.show();\n }\n\n private removeAllPins(): void {\n for (const pin of this.pins) {\n this.removePin(pin);\n }\n }\n\n removePin(pin: ConsolePin): void {\n pin.element().remove();\n const newFocusedPin = this.focusedPinAfterDeletion(pin);\n this.pins.delete(pin);\n this.savePins();\n if (newFocusedPin) {\n void newFocusedPin.focus();\n } else {\n this.liveExpressionButton.focus();\n }\n }\n\n addPin(expression: string, userGesture?: boolean): void {\n const pin = new ConsolePin(expression, this, this.focusOut);\n this.contentElement.appendChild(pin.element());\n this.pins.add(pin);\n this.savePins();\n if (userGesture) {\n void pin.focus();\n }\n this.update();\n }\n\n private focusedPinAfterDeletion(deletedPin: ConsolePin): ConsolePin|null {\n const pinArray = Array.from(this.pins);\n for (let i = 0; i < pinArray.length; i++) {\n if (pinArray[i] === deletedPin) {\n if (pinArray.length === 1) {\n return null;\n }\n if (i === pinArray.length - 1) {\n return pinArray[i - 1];\n }\n return pinArray[i + 1];\n }\n }\n return null;\n }\n\n override async doUpdate(): Promise {\n if (!this.pins.size || !this.isShowing()) {\n return;\n }\n if (this.isShowing()) {\n this.update();\n }\n const updatePromises = Array.from(this.pins, pin => pin.updatePreview());\n await Promise.all(updatePromises);\n this.updatedForTest();\n }\n\n private updatedForTest(): void {\n }\n}\n\nexport class ConsolePin {\n private readonly pinElement: Element;\n private readonly pinPreview: HTMLElement;\n private lastResult: SDK.RuntimeModel.EvaluationResult|null;\n private lastExecutionContext: SDK.RuntimeModel.ExecutionContext|null;\n private editor: TextEditor.TextEditor.TextEditor;\n private committedExpression: string;\n private hovered: boolean;\n private lastNode: SDK.RemoteObject.RemoteObject|null;\n private deletePinIcon: UI.UIUtils.DevToolsCloseButton;\n\n constructor(expression: string, private readonly pinPane: ConsolePinPane, private readonly focusOut: () => void) {\n this.deletePinIcon = document.createElement('div', {is: 'dt-close-button'}) as UI.UIUtils.DevToolsCloseButton;\n this.deletePinIcon.classList.add('close-button');\n this.deletePinIcon.setTabbable(true);\n if (expression.length) {\n this.deletePinIcon.setAccessibleName(i18nString(UIStrings.removeExpressionS, {PH1: expression}));\n } else {\n this.deletePinIcon.setAccessibleName(i18nString(UIStrings.removeBlankExpression));\n }\n self.onInvokeElement(this.deletePinIcon, event => {\n pinPane.removePin(this);\n event.consume(true);\n });\n\n const fragment = UI.Fragment.Fragment.build`\n
\n ${this.deletePinIcon}\n
\n
\n
`;\n this.pinElement = fragment.element();\n this.pinPreview = (fragment.$('preview') as HTMLElement);\n const nameElement = (fragment.$('name') as HTMLElement);\n UI.Tooltip.Tooltip.install(nameElement, expression);\n elementToConsolePin.set(this.pinElement, this);\n\n this.lastResult = null;\n this.lastExecutionContext = null;\n this.committedExpression = expression;\n this.hovered = false;\n this.lastNode = null;\n this.editor = this.createEditor(expression, nameElement);\n\n this.pinPreview.addEventListener('mouseenter', this.setHovered.bind(this, true), false);\n this.pinPreview.addEventListener('mouseleave', this.setHovered.bind(this, false), false);\n this.pinPreview.addEventListener('click', (event: Event) => {\n if (this.lastNode) {\n void Common.Revealer.reveal(this.lastNode);\n event.consume();\n }\n }, false);\n\n // Prevent Esc from toggling the drawer\n nameElement.addEventListener('keydown', event => {\n if (event.key === 'Escape') {\n event.consume();\n }\n });\n }\n\n createEditor(doc: string, parent: HTMLElement): TextEditor.TextEditor.TextEditor {\n const extensions = [\n CodeMirror.EditorView.contentAttributes.of({'aria-label': i18nString(UIStrings.liveExpressionEditor)}),\n CodeMirror.EditorView.lineWrapping,\n CodeMirror.javascript.javascriptLanguage,\n TextEditor.Config.showCompletionHint,\n CodeMirror.placeholder(i18nString(UIStrings.expression)),\n CodeMirror.keymap.of([\n {\n key: 'Escape',\n run: (view: CodeMirror.EditorView) => {\n view.dispatch({changes: {from: 0, to: view.state.doc.length, insert: this.committedExpression}});\n this.focusOut();\n return true;\n },\n },\n {\n key: 'Enter',\n run: () => {\n this.focusOut();\n return true;\n },\n },\n {\n key: 'Mod-Enter',\n run: () => {\n this.focusOut();\n return true;\n },\n },\n {\n key: 'Tab',\n run: (view: CodeMirror.EditorView) => {\n if (CodeMirror.completionStatus(this.editor.state) !== null) {\n return false;\n }\n // User should be able to tab out of edit field after auto complete is done\n view.dispatch({changes: {from: 0, to: view.state.doc.length, insert: this.committedExpression}});\n this.focusOut();\n return true;\n },\n },\n {\n key: 'Shift-Tab',\n run: (view: CodeMirror.EditorView) => {\n if (CodeMirror.completionStatus(this.editor.state) !== null) {\n return false;\n }\n // User should be able to tab out of edit field after auto complete is done\n view.dispatch({changes: {from: 0, to: view.state.doc.length, insert: this.committedExpression}});\n this.focusOut();\n return true;\n },\n },\n ]),\n CodeMirror.EditorView.domEventHandlers({blur: (_e, view) => this.onBlur(view)}),\n TextEditor.Config.baseConfiguration(doc),\n TextEditor.Config.closeBrackets.instance(),\n TextEditor.Config.autocompletion.instance(),\n ];\n if (Root.Runtime.Runtime.queryParam('noJavaScriptCompletion') !== 'true') {\n extensions.push(TextEditor.JavaScript.completion());\n }\n const editor = new TextEditor.TextEditor.TextEditor(CodeMirror.EditorState.create({doc, extensions}));\n parent.appendChild(editor);\n return editor;\n }\n\n onBlur(editor: CodeMirror.EditorView): void {\n const text = editor.state.doc.toString();\n const trimmedText = text.trim();\n this.committedExpression = trimmedText;\n this.pinPane.savePins();\n if (this.committedExpression.length) {\n this.deletePinIcon.setAccessibleName(i18nString(UIStrings.removeExpressionS, {PH1: this.committedExpression}));\n } else {\n this.deletePinIcon.setAccessibleName(i18nString(UIStrings.removeBlankExpression));\n }\n editor.dispatch({\n selection: {anchor: trimmedText.length},\n changes: trimmedText !== text ? {from: 0, to: text.length, insert: trimmedText} : undefined,\n });\n }\n\n setHovered(hovered: boolean): void {\n if (this.hovered === hovered) {\n return;\n }\n this.hovered = hovered;\n if (!hovered && this.lastNode) {\n SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight();\n }\n }\n\n expression(): string {\n return this.committedExpression;\n }\n\n element(): Element {\n return this.pinElement;\n }\n\n async focus(): Promise {\n const editor = this.editor;\n editor.editor.focus();\n editor.dispatch({selection: {anchor: editor.state.doc.length}});\n }\n\n appendToContextMenu(contextMenu: UI.ContextMenu.ContextMenu): void {\n if (this.lastResult && !('error' in this.lastResult) && this.lastResult.object) {\n contextMenu.appendApplicableItems(this.lastResult.object);\n // Prevent result from being released manually. It will release along with 'console' group.\n this.lastResult = null;\n }\n }\n\n async updatePreview(): Promise {\n if (!this.editor) {\n return;\n }\n const text = TextEditor.Config.contentIncludingHint(this.editor.editor);\n const isEditing = this.pinElement.hasFocus();\n const throwOnSideEffect = isEditing && text !== this.committedExpression;\n const timeout = throwOnSideEffect ? 250 : undefined;\n const executionContext = UI.Context.Context.instance().flavor(SDK.RuntimeModel.ExecutionContext);\n const {preview, result} = await ObjectUI.JavaScriptREPL.JavaScriptREPL.evaluateAndBuildPreview(\n text, throwOnSideEffect, true /* replMode */, timeout, !isEditing /* allowErrors */, 'console',\n true /* awaitPromise */, true /* silent */);\n if (this.lastResult && this.lastExecutionContext) {\n this.lastExecutionContext.runtimeModel.releaseEvaluationResult(this.lastResult);\n }\n this.lastResult = result || null;\n this.lastExecutionContext = executionContext || null;\n\n const previewText = preview.deepTextContent();\n if (!previewText || previewText !== this.pinPreview.deepTextContent()) {\n this.pinPreview.removeChildren();\n if (result && SDK.RuntimeModel.RuntimeModel.isSideEffectFailure(result)) {\n const sideEffectLabel =\n (this.pinPreview.createChild('span', 'object-value-calculate-value-button') as HTMLElement);\n sideEffectLabel.textContent = '(…)';\n UI.Tooltip.Tooltip.install(sideEffectLabel, i18nString(UIStrings.evaluateAllowingSideEffects));\n } else if (previewText) {\n this.pinPreview.appendChild(preview);\n } else if (!isEditing) {\n UI.UIUtils.createTextChild(this.pinPreview, i18nString(UIStrings.notAvailable));\n }\n UI.Tooltip.Tooltip.install(this.pinPreview, previewText);\n }\n\n let node: SDK.RemoteObject.RemoteObject|null = null;\n if (result && !('error' in result) && result.object.type === 'object' && result.object.subtype === 'node') {\n node = result.object;\n }\n if (this.hovered) {\n if (node) {\n SDK.OverlayModel.OverlayModel.highlightObjectAsDOMNode(node);\n } else if (this.lastNode) {\n SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight();\n }\n }\n this.lastNode = node || null;\n\n const isError = result && !('error' in result) && result.exceptionDetails &&\n !SDK.RuntimeModel.RuntimeModel.isSideEffectFailure(result);\n this.pinElement.classList.toggle('error-level', Boolean(isError));\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/elements/PropertyMatchers.d.ts b/public/panels/elements/PropertyMatchers.d.ts index d141b8a0a..05b83fb79 100644 --- a/public/panels/elements/PropertyMatchers.d.ts +++ b/public/panels/elements/PropertyMatchers.d.ts @@ -66,7 +66,9 @@ export declare class LinearGradientMatcher extends LinearGradientMatcher_base { export declare class ColorMatch implements Match { readonly text: string; readonly node: CodeMirror.SyntaxNode; - constructor(text: string, node: CodeMirror.SyntaxNode); + private readonly currentColorCallback?; + computedText: (() => string | null) | undefined; + constructor(text: string, node: CodeMirror.SyntaxNode, currentColorCallback?: (() => string | null) | undefined); } declare const ColorMatcher_base: new () => { matchType: SDK.CSSPropertyParser.Constructor; @@ -74,6 +76,8 @@ declare const ColorMatcher_base: new () => { matches(_node: CodeMirror.SyntaxNode, _matching: SDK.CSSPropertyParser.BottomUpTreeMatching): SDK.CSSPropertyParser.Match | null; }; export declare class ColorMatcher extends ColorMatcher_base { + private readonly currentColorCallback?; + constructor(currentColorCallback?: (() => string | null) | undefined); accepts(propertyName: string): boolean; matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match | null; } @@ -215,11 +219,9 @@ export declare class GridTemplateMatcher extends GridTemplateMatcher_base { } export declare class AnchorFunctionMatch implements Match { readonly text: string; - readonly matching: BottomUpTreeMatching; readonly node: CodeMirror.SyntaxNode; - readonly functionName: string; - readonly args: CodeMirror.SyntaxNode[]; - constructor(text: string, matching: BottomUpTreeMatching, node: CodeMirror.SyntaxNode, functionName: string, args: CodeMirror.SyntaxNode[]); + readonly functionName: string | null; + constructor(text: string, node: CodeMirror.SyntaxNode, functionName: string | null); } declare const AnchorFunctionMatcher_base: new () => { matchType: SDK.CSSPropertyParser.Constructor; @@ -227,6 +229,7 @@ declare const AnchorFunctionMatcher_base: new () => { matches(_node: CodeMirror.SyntaxNode, _matching: SDK.CSSPropertyParser.BottomUpTreeMatching): SDK.CSSPropertyParser.Match | null; }; export declare class AnchorFunctionMatcher extends AnchorFunctionMatcher_base { + anchorFunction(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): string | null; matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match | null; } export declare class PositionAnchorMatch implements Match { diff --git a/public/panels/elements/PropertyMatchers.js b/public/panels/elements/PropertyMatchers.js index 9b1f834fb..106258a96 100644 --- a/public/panels/elements/PropertyMatchers.js +++ b/public/panels/elements/PropertyMatchers.js @@ -162,13 +162,22 @@ export class LinearGradientMatcher extends matcherBase(LinearGradientMatch) { export class ColorMatch { text; node; - constructor(text, node) { + currentColorCallback; + computedText; + constructor(text, node, currentColorCallback) { this.text = text; this.node = node; + this.currentColorCallback = currentColorCallback; + this.computedText = currentColorCallback; } } // clang-format off export class ColorMatcher extends matcherBase(ColorMatch) { + currentColorCallback; + constructor(currentColorCallback) { + super(); + this.currentColorCallback = currentColorCallback; + } // clang-format on accepts(propertyName) { return SDK.CSSMetadata.cssMetadata().isColorAwareProperty(propertyName); @@ -178,8 +187,14 @@ export class ColorMatcher extends matcherBase(ColorMatch) { if (node.name === 'ColorLiteral') { return new ColorMatch(text, node); } - if (node.name === 'ValueName' && Common.Color.Nicknames.has(text)) { - return new ColorMatch(text, node); + if (node.name === 'ValueName') { + if (Common.Color.Nicknames.has(text)) { + return new ColorMatch(text, node); + } + if (text.toLowerCase() === 'currentcolor' && this.currentColorCallback) { + const callback = this.currentColorCallback; + return new ColorMatch(text, node, () => callback() ?? text); + } } if (node.name === 'CallExpression') { const callee = node.getChild('Callee'); @@ -545,33 +560,53 @@ export class GridTemplateMatcher extends matcherBase(GridTemplateMatch) { } export class AnchorFunctionMatch { text; - matching; node; functionName; - args; - constructor(text, matching, node, functionName, args) { + constructor(text, node, functionName) { this.text = text; - this.matching = matching; this.node = node; this.functionName = functionName; - this.args = args; } } // clang-format off export class AnchorFunctionMatcher extends matcherBase(AnchorFunctionMatch) { - matches(node, matching) { + anchorFunction(node, matching) { if (node.name !== 'CallExpression') { return null; } const calleeText = matching.ast.text(node.getChild('Callee')); - if (calleeText !== 'anchor' && calleeText !== 'anchor-size') { + if (calleeText === 'anchor' || calleeText === 'anchor-size') { + return calleeText; + } + return null; + } + matches(node, matching) { + if (node.name === 'VariableName') { + // Double-dashed anchor reference to be rendered with a link to its matching anchor. + let parent = node.parent; + if (!parent || parent.name !== 'ArgList') { + return null; + } + parent = parent.parent; + if (!parent || !this.anchorFunction(parent, matching)) { + return null; + } + return new AnchorFunctionMatch(matching.ast.text(node), node, null); + } + const calleeText = this.anchorFunction(node, matching); + if (!calleeText) { + return null; + } + // Match if the anchor/anchor-size function implicitly references an anchor. + const args = ASTUtils.children(node.getChild('ArgList')); + if (calleeText === 'anchor' && args.length <= 2) { return null; } - const [firstArg] = ASTUtils.callArgs(node); - if (!firstArg || firstArg.length === 0) { + if (args.find(arg => arg.name === 'VariableName')) { + // We have an explicit anchor reference, no need to render swatch. return null; } - return new AnchorFunctionMatch(matching.ast.text(node), matching, node, calleeText, firstArg); + return new AnchorFunctionMatch(matching.ast.text(node), node, calleeText); } } // clang-format on diff --git a/public/panels/elements/PropertyMatchers.js.map b/public/panels/elements/PropertyMatchers.js.map index 4c3f4ea85..eca2f836e 100644 --- a/public/panels/elements/PropertyMatchers.js.map +++ b/public/panels/elements/PropertyMatchers.js.map @@ -1 +1 @@ -{"version":3,"file":"PropertyMatchers.js","sourceRoot":"","sources":["../../../../../../front_end/panels/elements/PropertyMatchers.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport type * as Platform from '../../core/platform/platform.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport type * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';\nimport * as InlineEditor from '../../ui/legacy/components/inline_editor/inline_editor.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\ntype Match = SDK.CSSPropertyParser.Match;\ntype BottomUpTreeMatching = SDK.CSSPropertyParser.BottomUpTreeMatching;\ntype SyntaxTree = SDK.CSSPropertyParser.SyntaxTree;\n\nconst ASTUtils = SDK.CSSPropertyParser.ASTUtils;\nconst matcherBase = SDK.CSSPropertyParser.matcherBase;\nconst tokenizeDeclaration = SDK.CSSPropertyParser.tokenizeDeclaration;\n\nexport class AngleMatch implements SDK.CSSPropertyParser.Match {\n constructor(readonly text: string, readonly node: CodeMirror.SyntaxNode) {\n }\n\n computedText(): string {\n return this.text;\n }\n}\n\n// clang-format off\nexport class AngleMatcher extends matcherBase(AngleMatch) {\n // clang-format on\n override accepts(propertyName: string): boolean {\n return SDK.CSSMetadata.cssMetadata().isAngleAwareProperty(propertyName);\n }\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n if (node.name !== 'NumberLiteral') {\n return null;\n }\n const unit = node.getChild('Unit');\n // TODO(crbug/1138628) handle unitless 0\n if (!unit || !['deg', 'grad', 'rad', 'turn'].includes(matching.ast.text(unit))) {\n return null;\n }\n\n return new AngleMatch(matching.ast.text(node), node);\n }\n}\n\nfunction literalToNumber(node: CodeMirror.SyntaxNode, ast: SyntaxTree): number|null {\n if (node.type.name !== 'NumberLiteral') {\n return null;\n }\n const text = ast.text(node);\n\n return Number(text.substring(0, text.length - ast.text(node.getChild('Unit')).length));\n}\n\nexport class ColorMixMatch implements Match {\n constructor(\n readonly text: string, readonly node: CodeMirror.SyntaxNode, readonly space: CodeMirror.SyntaxNode[],\n readonly color1: CodeMirror.SyntaxNode[], readonly color2: CodeMirror.SyntaxNode[]) {\n }\n}\n\n// clang-format off\nexport class ColorMixMatcher extends matcherBase(ColorMixMatch) {\n // clang-format on\n override accepts(propertyName: string): boolean {\n return SDK.CSSMetadata.cssMetadata().isColorAwareProperty(propertyName);\n }\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n if (node.name !== 'CallExpression' || matching.ast.text(node.getChild('Callee')) !== 'color-mix') {\n return null;\n }\n\n const computedValueTree = tokenizeDeclaration('--property', matching.getComputedText(node));\n if (!computedValueTree) {\n return null;\n }\n\n const value = ASTUtils.declValue(computedValueTree.tree);\n if (!value) {\n return null;\n }\n const computedValueArgs = ASTUtils.callArgs(value);\n if (computedValueArgs.length !== 3) {\n return null;\n }\n\n const [space, color1, color2] = computedValueArgs;\n // Verify that all arguments are there, and that the space starts with a literal `in`.\n if (space.length < 2 || computedValueTree.text(ASTUtils.stripComments(space).next().value) !== 'in' ||\n color1.length < 1 || color2.length < 1) {\n return null;\n }\n\n // Verify there's at most one percentage value for each color.\n const p1 =\n color1.filter(n => n.type.name === 'NumberLiteral' && computedValueTree.text(n.getChild('Unit')) === '%');\n const p2 =\n color2.filter(n => n.type.name === 'NumberLiteral' && computedValueTree.text(n.getChild('Unit')) === '%');\n if (p1.length > 1 || p2.length > 1) {\n return null;\n }\n\n // Verify that if both colors carry percentages, they aren't both zero (which is an invalid property value).\n if (p1[0] && p2[0] && (literalToNumber(p1[0], computedValueTree) ?? 0) === 0 &&\n (literalToNumber(p2[0], computedValueTree) ?? 0) === 0) {\n return null;\n }\n\n const args = ASTUtils.callArgs(node);\n if (args.length !== 3) {\n return null;\n }\n return new ColorMixMatch(matching.ast.text(node), node, args[0], args[1], args[2]);\n }\n}\n\n// clang-format off\nexport class URLMatch implements Match {\n constructor(\n readonly url: Platform.DevToolsPath.UrlString, readonly text: string, readonly node: CodeMirror.SyntaxNode) {\n }\n}\n\n// clang-format off\nexport class URLMatcher extends matcherBase(URLMatch) {\n // clang-format on\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n if (node.name !== 'CallLiteral') {\n return null;\n }\n const callee = node.getChild('CallTag');\n if (!callee || matching.ast.text(callee) !== 'url') {\n return null;\n }\n const [, lparenNode, urlNode, rparenNode] = ASTUtils.siblings(callee);\n if (matching.ast.text(lparenNode) !== '(' ||\n (urlNode.name !== 'ParenthesizedContent' && urlNode.name !== 'StringLiteral') ||\n matching.ast.text(rparenNode) !== ')') {\n return null;\n }\n\n const text = matching.ast.text(urlNode);\n const url = (urlNode.name === 'StringLiteral' ? text.substr(1, text.length - 2) : text.trim()) as\n Platform.DevToolsPath.UrlString;\n return new URLMatch(url, matching.ast.text(node), node);\n }\n}\n\nexport class LinearGradientMatch implements Match {\n constructor(readonly text: string, readonly node: CodeMirror.SyntaxNode) {\n }\n}\n\n// clang-format off\nexport class LinearGradientMatcher extends matcherBase(LinearGradientMatch) {\n // clang-format on\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n const text = matching.ast.text(node);\n if (node.name === 'CallExpression' && matching.ast.text(node.getChild('Callee')) === 'linear-gradient') {\n return new LinearGradientMatch(text, node);\n }\n return null;\n }\n override accepts(propertyName: string): boolean {\n return ['background', 'background-image', '-webkit-mask-image'].includes(propertyName);\n }\n}\n\nexport class ColorMatch implements Match {\n constructor(readonly text: string, readonly node: CodeMirror.SyntaxNode) {\n }\n}\n\n// clang-format off\nexport class ColorMatcher extends matcherBase(ColorMatch) {\n // clang-format on\n override accepts(propertyName: string): boolean {\n return SDK.CSSMetadata.cssMetadata().isColorAwareProperty(propertyName);\n }\n\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n const text = matching.ast.text(node);\n if (node.name === 'ColorLiteral') {\n return new ColorMatch(text, node);\n }\n if (node.name === 'ValueName' && Common.Color.Nicknames.has(text)) {\n return new ColorMatch(text, node);\n }\n if (node.name === 'CallExpression') {\n const callee = node.getChild('Callee');\n if (callee && matching.ast.text(callee).match(/^(rgba?|hsla?|hwba?|lab|lch|oklab|oklch|color)$/)) {\n return new ColorMatch(text, node);\n }\n }\n return null;\n }\n}\n\nexport class LightDarkColorMatch implements Match {\n constructor(\n readonly text: string, readonly node: CodeMirror.SyntaxNode, readonly light: CodeMirror.SyntaxNode[],\n readonly dark: CodeMirror.SyntaxNode[]) {\n }\n}\n\n// clang-format off\nexport class LightDarkColorMatcher extends matcherBase(LightDarkColorMatch) {\n // clang-format on\n override accepts(propertyName: string): boolean {\n return SDK.CSSMetadata.cssMetadata().isColorAwareProperty(propertyName);\n }\n\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n if (node.name !== 'CallExpression' || matching.ast.text(node.getChild('Callee')) !== 'light-dark') {\n return null;\n }\n const args = ASTUtils.callArgs(node);\n if (args.length !== 2 || args[0].length === 0 || args[1].length === 0) {\n return null;\n }\n return new LightDarkColorMatch(matching.ast.text(node), node, args[0], args[1]);\n }\n}\n\nexport const enum LinkableNameProperties {\n ANIMATION = 'animation',\n ANIMATION_NAME = 'animation-name',\n FONT_PALETTE = 'font-palette',\n POSITION_TRY_FALLBACKS = 'position-try-fallbacks',\n POSITION_TRY = 'position-try',\n}\n\nconst enum AnimationLonghandPart {\n DIRECTION = 'direction',\n FILL_MODE = 'fill-mode',\n PLAY_STATE = 'play-state',\n ITERATION_COUNT = 'iteration-count',\n EASING_FUNCTION = 'easing-function',\n}\n\nexport class LinkableNameMatch implements Match {\n constructor(\n readonly text: string, readonly node: CodeMirror.SyntaxNode, readonly properyName: LinkableNameProperties) {\n }\n}\n\n// clang-format off\nexport class LinkableNameMatcher extends matcherBase(LinkableNameMatch) {\n // clang-format on\n private static isLinkableNameProperty(propertyName: string): propertyName is LinkableNameProperties {\n const names: string[] = [\n LinkableNameProperties.ANIMATION,\n LinkableNameProperties.ANIMATION_NAME,\n LinkableNameProperties.FONT_PALETTE,\n LinkableNameProperties.POSITION_TRY_FALLBACKS,\n LinkableNameProperties.POSITION_TRY,\n ];\n return names.includes(propertyName);\n }\n\n static readonly identifierAnimationLonghandMap: Map = new Map(\n Object.entries({\n normal: AnimationLonghandPart.DIRECTION,\n alternate: AnimationLonghandPart.DIRECTION,\n reverse: AnimationLonghandPart.DIRECTION,\n 'alternate-reverse': AnimationLonghandPart.DIRECTION,\n none: AnimationLonghandPart.FILL_MODE,\n forwards: AnimationLonghandPart.FILL_MODE,\n backwards: AnimationLonghandPart.FILL_MODE,\n both: AnimationLonghandPart.FILL_MODE,\n running: AnimationLonghandPart.PLAY_STATE,\n paused: AnimationLonghandPart.PLAY_STATE,\n infinite: AnimationLonghandPart.ITERATION_COUNT,\n linear: AnimationLonghandPart.EASING_FUNCTION,\n ease: AnimationLonghandPart.EASING_FUNCTION,\n 'ease-in': AnimationLonghandPart.EASING_FUNCTION,\n 'ease-out': AnimationLonghandPart.EASING_FUNCTION,\n 'ease-in-out': AnimationLonghandPart.EASING_FUNCTION,\n }),\n );\n\n private matchAnimationNameInShorthand(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n // Order is important within each animation definition for distinguishing values from other keywords.\n // When parsing, keywords that are valid for properties other than animation-name\n // whose values were not found earlier in the shorthand must be accepted for those properties rather than for animation-name.\n // See the details in: https://w3c.github.io/csswg-drafts/css-animations/#animation.\n const text = matching.ast.text(node);\n // This is not a known identifier, so return it as `animation-name`.\n if (!LinkableNameMatcher.identifierAnimationLonghandMap.has(text)) {\n return new LinkableNameMatch(text, node, LinkableNameProperties.ANIMATION);\n }\n // There can be multiple `animation` declarations splitted by a comma.\n // So, we find the declaration nodes that are related to the node argument.\n const declarations = ASTUtils.split(ASTUtils.siblings(ASTUtils.declValue(matching.ast.tree)));\n const currentDeclarationNodes = declarations.find(\n declaration => declaration[0].from <= node.from && declaration[declaration.length - 1].to >= node.to);\n if (!currentDeclarationNodes) {\n return null;\n }\n\n // We reparse here until the node argument since a variable might be\n // providing a meaningful value such as a timing keyword,\n // that might change the meaning of the node.\n const computedText = matching.getComputedTextRange(currentDeclarationNodes[0], node);\n const tokenized = tokenizeDeclaration('--p', computedText);\n if (!tokenized) {\n return null;\n }\n\n const identifierCategory =\n LinkableNameMatcher.identifierAnimationLonghandMap.get(text); // The category of the node argument\n for (let itNode: typeof tokenized.tree|null = ASTUtils.declValue(tokenized.tree); itNode?.nextSibling;\n itNode = itNode.nextSibling) {\n // Run through all the nodes that come before node argument\n // and check whether a value in the same category is found.\n // if so, it means our identifier is an `animation-name` keyword.\n if (itNode.name === 'ValueName') {\n const categoryValue = LinkableNameMatcher.identifierAnimationLonghandMap.get(tokenized.text(itNode));\n if (categoryValue && categoryValue === identifierCategory) {\n return new LinkableNameMatch(text, node, LinkableNameProperties.ANIMATION);\n }\n }\n }\n\n return null;\n }\n\n override accepts(propertyName: string): boolean {\n return LinkableNameMatcher.isLinkableNameProperty(propertyName);\n }\n\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n const {propertyName} = matching.ast;\n const text = matching.ast.text(node);\n const parentNode = node.parent;\n if (!parentNode) {\n return null;\n }\n\n const isParentADeclaration = parentNode.name === 'Declaration';\n const isInsideVarCall = parentNode.name === 'ArgList' && parentNode.prevSibling?.name === 'Callee' &&\n matching.ast.text(parentNode.prevSibling) === 'var';\n const isAParentDeclarationOrVarCall = isParentADeclaration || isInsideVarCall;\n // `position-try-fallbacks` and `position-try` only accept names with dashed ident.\n const shouldMatchOnlyVariableName = propertyName === LinkableNameProperties.POSITION_TRY ||\n propertyName === LinkableNameProperties.POSITION_TRY_FALLBACKS;\n // We only mark top level nodes or nodes that are inside `var()` expressions as linkable names.\n if (!propertyName || (node.name !== 'ValueName' && node.name !== 'VariableName') ||\n !isAParentDeclarationOrVarCall || (node.name === 'ValueName' && shouldMatchOnlyVariableName)) {\n return null;\n }\n\n if (propertyName === 'animation') {\n return this.matchAnimationNameInShorthand(node, matching);\n }\n\n // The assertion here is safe since this matcher only runs for\n // properties with names inside `LinkableNameProperties` (See the `accepts` function.)\n return new LinkableNameMatch(text, node, propertyName as LinkableNameProperties);\n }\n}\n\nexport class BezierMatch implements Match {\n constructor(readonly text: string, readonly node: CodeMirror.SyntaxNode) {\n }\n}\n\n// clang-format off\nexport class BezierMatcher extends matcherBase(BezierMatch) {\n // clang-format on\n override accepts(propertyName: string): boolean {\n return SDK.CSSMetadata.cssMetadata().isBezierAwareProperty(propertyName);\n }\n\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n const text = matching.ast.text(node);\n\n const isCubicBezierKeyword = node.name === 'ValueName' && UI.Geometry.CubicBezier.KeywordValues.has(text);\n const isCubicBezierOrLinearFunction = node.name === 'CallExpression' &&\n ['cubic-bezier', 'linear'].includes(matching.ast.text(node.getChild('Callee')));\n\n if (!isCubicBezierKeyword && !isCubicBezierOrLinearFunction) {\n return null;\n }\n\n if (!InlineEditor.AnimationTimingModel.AnimationTimingModel.parse(text)) {\n return null;\n }\n return new BezierMatch(text, node);\n }\n}\n\nexport class StringMatch implements Match {\n constructor(readonly text: string, readonly node: CodeMirror.SyntaxNode) {\n }\n}\n\n// clang-format off\nexport class StringMatcher extends matcherBase(StringMatch) {\n // clang-format on\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n return node.name === 'StringLiteral' ? new StringMatch(matching.ast.text(node), node) : null;\n }\n}\n\nexport const enum ShadowType {\n BOX_SHADOW = 'boxShadow',\n TEXT_SHADOW = 'textShadow',\n}\nexport class ShadowMatch implements Match {\n constructor(readonly text: string, readonly node: CodeMirror.SyntaxNode, readonly shadowType: ShadowType) {\n }\n}\n\n// clang-format off\nexport class ShadowMatcher extends matcherBase(ShadowMatch) {\n // clang-format on\n override accepts(propertyName: string): boolean {\n return SDK.CSSMetadata.cssMetadata().isShadowProperty(propertyName);\n }\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n if (node.name !== 'Declaration') {\n return null;\n }\n const valueNodes = ASTUtils.siblings(ASTUtils.declValue(node));\n const valueText = matching.ast.textRange(valueNodes[0], valueNodes[valueNodes.length - 1]);\n return new ShadowMatch(\n valueText, node, matching.ast.propertyName === 'text-shadow' ? ShadowType.TEXT_SHADOW : ShadowType.BOX_SHADOW);\n }\n}\n\nexport class FontMatch implements Match {\n constructor(readonly text: string, readonly node: CodeMirror.SyntaxNode) {\n }\n}\n\n// clang-format off\nexport class FontMatcher extends matcherBase(FontMatch) {\n // clang-format on\n override accepts(propertyName: string): boolean {\n return SDK.CSSMetadata.cssMetadata().isFontAwareProperty(propertyName);\n }\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n if (node.name === 'Declaration') {\n return null;\n }\n const regex = matching.ast.propertyName === 'font-family' ? InlineEditor.FontEditorUtils.FontFamilyRegex :\n InlineEditor.FontEditorUtils.FontPropertiesRegex;\n const text = matching.ast.text(node);\n return regex.test(text) ? new FontMatch(text, node) : null;\n }\n}\n\nexport class LengthMatch implements Match {\n constructor(readonly text: string, readonly node: CodeMirror.SyntaxNode) {\n }\n}\n\n// clang-format off\nexport class LengthMatcher extends matcherBase(LengthMatch) {\n // clang-format on\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n const text = matching.ast.text(node);\n const regexp = new RegExp(`^${InlineEditor.CSSLength.CSS_LENGTH_REGEX.source}$`);\n const match = regexp.exec(text);\n if (!match || match.index !== 0) {\n return null;\n }\n return new LengthMatch(match[0], node);\n }\n}\n\nexport class GridTemplateMatch implements Match {\n constructor(readonly text: string, readonly node: CodeMirror.SyntaxNode, readonly lines: CodeMirror.SyntaxNode[][]) {\n }\n}\n\n// clang-format off\nexport class GridTemplateMatcher extends matcherBase(GridTemplateMatch) {\n // clang-format on\n override accepts(propertyName: string): boolean {\n return SDK.CSSMetadata.cssMetadata().isGridAreaDefiningProperty(propertyName);\n }\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n if (node.name !== 'Declaration' || matching.hasUnresolvedVars(node)) {\n return null;\n }\n\n const lines: CodeMirror.SyntaxNode[][] = [];\n let curLine: CodeMirror.SyntaxNode[] = [];\n // The following two states are designed to consume different cases of LineNames:\n // 1. no LineNames in between StringLiterals;\n // 2. one LineNames in between, which means the LineNames belongs to the current line;\n // 3. two LineNames in between, which means the second LineNames starts a new line.\n // `hasLeadingLineNames` tracks if the current row already starts with a LineNames and\n // with no following StringLiteral yet, which means that the next StringLiteral should\n // be appended to the same `curLine`, instead of creating a new line.\n let hasLeadingLineNames = false;\n // `needClosingLineNames` tracks if the current row can still consume an optional LineNames,\n // which will decide if we should start a new line or not when a LineNames is encountered.\n let needClosingLineNames = false;\n // Gather row definitions of [? ? ?], which\n // be rendered into separate lines.\n function parseNodes(nodes: CodeMirror.SyntaxNode[], varParsingMode = false): void {\n for (const curNode of nodes) {\n if (matching.getMatch(curNode) instanceof SDK.CSSPropertyParser.VariableMatch) {\n const computedValueTree = tokenizeDeclaration('--property', matching.getComputedText(curNode));\n if (!computedValueTree) {\n continue;\n }\n const varNodes = ASTUtils.siblings(ASTUtils.declValue(computedValueTree.tree));\n if (varNodes.length === 0) {\n continue;\n }\n if ((varNodes[0].name === 'StringLiteral' && !hasLeadingLineNames) ||\n (varNodes[0].name === 'LineNames' && !needClosingLineNames)) {\n // The variable value either starts with a string, or with a line name that belongs to a new row;\n // therefore we start a new line with the variable.\n lines.push(curLine);\n curLine = [curNode];\n } else {\n curLine.push(curNode);\n }\n // We parse computed nodes of this variable to correctly advance local states, but\n // these computed nodes won't be added to the lines.\n parseNodes(varNodes, true);\n } else if (curNode.name === 'BinaryExpression') {\n parseNodes(ASTUtils.siblings(curNode.firstChild));\n } else if (curNode.name === 'StringLiteral') {\n if (!varParsingMode) {\n if (hasLeadingLineNames) {\n curLine.push(curNode);\n } else {\n lines.push(curLine);\n curLine = [curNode];\n }\n }\n needClosingLineNames = true;\n hasLeadingLineNames = false;\n } else if (curNode.name === 'LineNames') {\n if (!varParsingMode) {\n if (needClosingLineNames) {\n curLine.push(curNode);\n } else {\n lines.push(curLine);\n curLine = [curNode];\n }\n }\n hasLeadingLineNames = !needClosingLineNames;\n needClosingLineNames = !needClosingLineNames;\n } else if (!varParsingMode) {\n curLine.push(curNode);\n }\n }\n }\n\n const valueNodes = ASTUtils.siblings(ASTUtils.declValue(node));\n parseNodes(valueNodes);\n lines.push(curLine);\n const valueText = matching.ast.textRange(valueNodes[0], valueNodes[valueNodes.length - 1]);\n return new GridTemplateMatch(valueText, node, lines.filter(line => line.length > 0));\n }\n}\nexport class AnchorFunctionMatch implements Match {\n constructor(\n readonly text: string, readonly matching: BottomUpTreeMatching, readonly node: CodeMirror.SyntaxNode,\n readonly functionName: string, readonly args: CodeMirror.SyntaxNode[]) {\n }\n}\n\n// clang-format off\nexport class AnchorFunctionMatcher extends matcherBase(AnchorFunctionMatch) {\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n if (node.name !== 'CallExpression') {\n return null;\n }\n\n const calleeText = matching.ast.text(node.getChild('Callee'));\n if (calleeText !== 'anchor' && calleeText !== 'anchor-size') {\n return null;\n }\n\n const [firstArg] = ASTUtils.callArgs(node);\n if (!firstArg || firstArg.length === 0) {\n return null;\n }\n\n return new AnchorFunctionMatch(matching.ast.text(node), matching, node, calleeText, firstArg);\n }\n}\n// clang-format on\n\n// For linking `position-anchor: --anchor-name`.\nexport class PositionAnchorMatch implements Match {\n constructor(readonly text: string, readonly matching: BottomUpTreeMatching, readonly node: CodeMirror.SyntaxNode) {\n }\n}\n\n// clang-format off\nexport class PositionAnchorMatcher extends matcherBase(PositionAnchorMatch) {\n override accepts(propertyName: string): boolean {\n return propertyName === 'position-anchor';\n }\n\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n if (node.name !== 'VariableName') {\n return null;\n }\n\n const dashedIdentifier = matching.ast.text(node);\n return new PositionAnchorMatch(dashedIdentifier, matching, node);\n }\n}\n// clang-format on\n"]} \ No newline at end of file +{"version":3,"file":"PropertyMatchers.js","sourceRoot":"","sources":["../../../../../../front_end/panels/elements/PropertyMatchers.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport type * as Platform from '../../core/platform/platform.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport type * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';\nimport * as InlineEditor from '../../ui/legacy/components/inline_editor/inline_editor.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\ntype Match = SDK.CSSPropertyParser.Match;\ntype BottomUpTreeMatching = SDK.CSSPropertyParser.BottomUpTreeMatching;\ntype SyntaxTree = SDK.CSSPropertyParser.SyntaxTree;\n\nconst ASTUtils = SDK.CSSPropertyParser.ASTUtils;\nconst matcherBase = SDK.CSSPropertyParser.matcherBase;\nconst tokenizeDeclaration = SDK.CSSPropertyParser.tokenizeDeclaration;\n\nexport class AngleMatch implements SDK.CSSPropertyParser.Match {\n constructor(readonly text: string, readonly node: CodeMirror.SyntaxNode) {\n }\n\n computedText(): string {\n return this.text;\n }\n}\n\n// clang-format off\nexport class AngleMatcher extends matcherBase(AngleMatch) {\n // clang-format on\n override accepts(propertyName: string): boolean {\n return SDK.CSSMetadata.cssMetadata().isAngleAwareProperty(propertyName);\n }\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n if (node.name !== 'NumberLiteral') {\n return null;\n }\n const unit = node.getChild('Unit');\n // TODO(crbug/1138628) handle unitless 0\n if (!unit || !['deg', 'grad', 'rad', 'turn'].includes(matching.ast.text(unit))) {\n return null;\n }\n\n return new AngleMatch(matching.ast.text(node), node);\n }\n}\n\nfunction literalToNumber(node: CodeMirror.SyntaxNode, ast: SyntaxTree): number|null {\n if (node.type.name !== 'NumberLiteral') {\n return null;\n }\n const text = ast.text(node);\n\n return Number(text.substring(0, text.length - ast.text(node.getChild('Unit')).length));\n}\n\nexport class ColorMixMatch implements Match {\n constructor(\n readonly text: string, readonly node: CodeMirror.SyntaxNode, readonly space: CodeMirror.SyntaxNode[],\n readonly color1: CodeMirror.SyntaxNode[], readonly color2: CodeMirror.SyntaxNode[]) {\n }\n}\n\n// clang-format off\nexport class ColorMixMatcher extends matcherBase(ColorMixMatch) {\n // clang-format on\n override accepts(propertyName: string): boolean {\n return SDK.CSSMetadata.cssMetadata().isColorAwareProperty(propertyName);\n }\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n if (node.name !== 'CallExpression' || matching.ast.text(node.getChild('Callee')) !== 'color-mix') {\n return null;\n }\n\n const computedValueTree = tokenizeDeclaration('--property', matching.getComputedText(node));\n if (!computedValueTree) {\n return null;\n }\n\n const value = ASTUtils.declValue(computedValueTree.tree);\n if (!value) {\n return null;\n }\n const computedValueArgs = ASTUtils.callArgs(value);\n if (computedValueArgs.length !== 3) {\n return null;\n }\n\n const [space, color1, color2] = computedValueArgs;\n // Verify that all arguments are there, and that the space starts with a literal `in`.\n if (space.length < 2 || computedValueTree.text(ASTUtils.stripComments(space).next().value) !== 'in' ||\n color1.length < 1 || color2.length < 1) {\n return null;\n }\n\n // Verify there's at most one percentage value for each color.\n const p1 =\n color1.filter(n => n.type.name === 'NumberLiteral' && computedValueTree.text(n.getChild('Unit')) === '%');\n const p2 =\n color2.filter(n => n.type.name === 'NumberLiteral' && computedValueTree.text(n.getChild('Unit')) === '%');\n if (p1.length > 1 || p2.length > 1) {\n return null;\n }\n\n // Verify that if both colors carry percentages, they aren't both zero (which is an invalid property value).\n if (p1[0] && p2[0] && (literalToNumber(p1[0], computedValueTree) ?? 0) === 0 &&\n (literalToNumber(p2[0], computedValueTree) ?? 0) === 0) {\n return null;\n }\n\n const args = ASTUtils.callArgs(node);\n if (args.length !== 3) {\n return null;\n }\n return new ColorMixMatch(matching.ast.text(node), node, args[0], args[1], args[2]);\n }\n}\n\n// clang-format off\nexport class URLMatch implements Match {\n constructor(\n readonly url: Platform.DevToolsPath.UrlString, readonly text: string, readonly node: CodeMirror.SyntaxNode) {\n }\n}\n\n// clang-format off\nexport class URLMatcher extends matcherBase(URLMatch) {\n // clang-format on\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n if (node.name !== 'CallLiteral') {\n return null;\n }\n const callee = node.getChild('CallTag');\n if (!callee || matching.ast.text(callee) !== 'url') {\n return null;\n }\n const [, lparenNode, urlNode, rparenNode] = ASTUtils.siblings(callee);\n if (matching.ast.text(lparenNode) !== '(' ||\n (urlNode.name !== 'ParenthesizedContent' && urlNode.name !== 'StringLiteral') ||\n matching.ast.text(rparenNode) !== ')') {\n return null;\n }\n\n const text = matching.ast.text(urlNode);\n const url = (urlNode.name === 'StringLiteral' ? text.substr(1, text.length - 2) : text.trim()) as\n Platform.DevToolsPath.UrlString;\n return new URLMatch(url, matching.ast.text(node), node);\n }\n}\n\nexport class LinearGradientMatch implements Match {\n constructor(readonly text: string, readonly node: CodeMirror.SyntaxNode) {\n }\n}\n\n// clang-format off\nexport class LinearGradientMatcher extends matcherBase(LinearGradientMatch) {\n // clang-format on\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n const text = matching.ast.text(node);\n if (node.name === 'CallExpression' && matching.ast.text(node.getChild('Callee')) === 'linear-gradient') {\n return new LinearGradientMatch(text, node);\n }\n return null;\n }\n override accepts(propertyName: string): boolean {\n return ['background', 'background-image', '-webkit-mask-image'].includes(propertyName);\n }\n}\n\nexport class ColorMatch implements Match {\n computedText: (() => string | null)|undefined;\n constructor(\n readonly text: string, readonly node: CodeMirror.SyntaxNode,\n private readonly currentColorCallback?: () => string | null) {\n this.computedText = currentColorCallback;\n }\n}\n\n// clang-format off\nexport class ColorMatcher extends matcherBase(ColorMatch) {\n constructor(private readonly currentColorCallback?: () => string|null) {\n super();\n }\n // clang-format on\n override accepts(propertyName: string): boolean {\n return SDK.CSSMetadata.cssMetadata().isColorAwareProperty(propertyName);\n }\n\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n const text = matching.ast.text(node);\n if (node.name === 'ColorLiteral') {\n return new ColorMatch(text, node);\n }\n if (node.name === 'ValueName') {\n if (Common.Color.Nicknames.has(text)) {\n return new ColorMatch(text, node);\n }\n if (text.toLowerCase() === 'currentcolor' && this.currentColorCallback) {\n const callback = this.currentColorCallback;\n return new ColorMatch(text, node, () => callback() ?? text);\n }\n }\n if (node.name === 'CallExpression') {\n const callee = node.getChild('Callee');\n if (callee && matching.ast.text(callee).match(/^(rgba?|hsla?|hwba?|lab|lch|oklab|oklch|color)$/)) {\n return new ColorMatch(text, node);\n }\n }\n return null;\n }\n}\n\nexport class LightDarkColorMatch implements Match {\n constructor(\n readonly text: string, readonly node: CodeMirror.SyntaxNode, readonly light: CodeMirror.SyntaxNode[],\n readonly dark: CodeMirror.SyntaxNode[]) {\n }\n}\n\n// clang-format off\nexport class LightDarkColorMatcher extends matcherBase(LightDarkColorMatch) {\n // clang-format on\n override accepts(propertyName: string): boolean {\n return SDK.CSSMetadata.cssMetadata().isColorAwareProperty(propertyName);\n }\n\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n if (node.name !== 'CallExpression' || matching.ast.text(node.getChild('Callee')) !== 'light-dark') {\n return null;\n }\n const args = ASTUtils.callArgs(node);\n if (args.length !== 2 || args[0].length === 0 || args[1].length === 0) {\n return null;\n }\n return new LightDarkColorMatch(matching.ast.text(node), node, args[0], args[1]);\n }\n}\n\nexport const enum LinkableNameProperties {\n ANIMATION = 'animation',\n ANIMATION_NAME = 'animation-name',\n FONT_PALETTE = 'font-palette',\n POSITION_TRY_FALLBACKS = 'position-try-fallbacks',\n POSITION_TRY = 'position-try',\n}\n\nconst enum AnimationLonghandPart {\n DIRECTION = 'direction',\n FILL_MODE = 'fill-mode',\n PLAY_STATE = 'play-state',\n ITERATION_COUNT = 'iteration-count',\n EASING_FUNCTION = 'easing-function',\n}\n\nexport class LinkableNameMatch implements Match {\n constructor(\n readonly text: string, readonly node: CodeMirror.SyntaxNode, readonly properyName: LinkableNameProperties) {\n }\n}\n\n// clang-format off\nexport class LinkableNameMatcher extends matcherBase(LinkableNameMatch) {\n // clang-format on\n private static isLinkableNameProperty(propertyName: string): propertyName is LinkableNameProperties {\n const names: string[] = [\n LinkableNameProperties.ANIMATION,\n LinkableNameProperties.ANIMATION_NAME,\n LinkableNameProperties.FONT_PALETTE,\n LinkableNameProperties.POSITION_TRY_FALLBACKS,\n LinkableNameProperties.POSITION_TRY,\n ];\n return names.includes(propertyName);\n }\n\n static readonly identifierAnimationLonghandMap: Map = new Map(\n Object.entries({\n normal: AnimationLonghandPart.DIRECTION,\n alternate: AnimationLonghandPart.DIRECTION,\n reverse: AnimationLonghandPart.DIRECTION,\n 'alternate-reverse': AnimationLonghandPart.DIRECTION,\n none: AnimationLonghandPart.FILL_MODE,\n forwards: AnimationLonghandPart.FILL_MODE,\n backwards: AnimationLonghandPart.FILL_MODE,\n both: AnimationLonghandPart.FILL_MODE,\n running: AnimationLonghandPart.PLAY_STATE,\n paused: AnimationLonghandPart.PLAY_STATE,\n infinite: AnimationLonghandPart.ITERATION_COUNT,\n linear: AnimationLonghandPart.EASING_FUNCTION,\n ease: AnimationLonghandPart.EASING_FUNCTION,\n 'ease-in': AnimationLonghandPart.EASING_FUNCTION,\n 'ease-out': AnimationLonghandPart.EASING_FUNCTION,\n 'ease-in-out': AnimationLonghandPart.EASING_FUNCTION,\n }),\n );\n\n private matchAnimationNameInShorthand(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n // Order is important within each animation definition for distinguishing values from other keywords.\n // When parsing, keywords that are valid for properties other than animation-name\n // whose values were not found earlier in the shorthand must be accepted for those properties rather than for animation-name.\n // See the details in: https://w3c.github.io/csswg-drafts/css-animations/#animation.\n const text = matching.ast.text(node);\n // This is not a known identifier, so return it as `animation-name`.\n if (!LinkableNameMatcher.identifierAnimationLonghandMap.has(text)) {\n return new LinkableNameMatch(text, node, LinkableNameProperties.ANIMATION);\n }\n // There can be multiple `animation` declarations splitted by a comma.\n // So, we find the declaration nodes that are related to the node argument.\n const declarations = ASTUtils.split(ASTUtils.siblings(ASTUtils.declValue(matching.ast.tree)));\n const currentDeclarationNodes = declarations.find(\n declaration => declaration[0].from <= node.from && declaration[declaration.length - 1].to >= node.to);\n if (!currentDeclarationNodes) {\n return null;\n }\n\n // We reparse here until the node argument since a variable might be\n // providing a meaningful value such as a timing keyword,\n // that might change the meaning of the node.\n const computedText = matching.getComputedTextRange(currentDeclarationNodes[0], node);\n const tokenized = tokenizeDeclaration('--p', computedText);\n if (!tokenized) {\n return null;\n }\n\n const identifierCategory =\n LinkableNameMatcher.identifierAnimationLonghandMap.get(text); // The category of the node argument\n for (let itNode: typeof tokenized.tree|null = ASTUtils.declValue(tokenized.tree); itNode?.nextSibling;\n itNode = itNode.nextSibling) {\n // Run through all the nodes that come before node argument\n // and check whether a value in the same category is found.\n // if so, it means our identifier is an `animation-name` keyword.\n if (itNode.name === 'ValueName') {\n const categoryValue = LinkableNameMatcher.identifierAnimationLonghandMap.get(tokenized.text(itNode));\n if (categoryValue && categoryValue === identifierCategory) {\n return new LinkableNameMatch(text, node, LinkableNameProperties.ANIMATION);\n }\n }\n }\n\n return null;\n }\n\n override accepts(propertyName: string): boolean {\n return LinkableNameMatcher.isLinkableNameProperty(propertyName);\n }\n\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n const {propertyName} = matching.ast;\n const text = matching.ast.text(node);\n const parentNode = node.parent;\n if (!parentNode) {\n return null;\n }\n\n const isParentADeclaration = parentNode.name === 'Declaration';\n const isInsideVarCall = parentNode.name === 'ArgList' && parentNode.prevSibling?.name === 'Callee' &&\n matching.ast.text(parentNode.prevSibling) === 'var';\n const isAParentDeclarationOrVarCall = isParentADeclaration || isInsideVarCall;\n // `position-try-fallbacks` and `position-try` only accept names with dashed ident.\n const shouldMatchOnlyVariableName = propertyName === LinkableNameProperties.POSITION_TRY ||\n propertyName === LinkableNameProperties.POSITION_TRY_FALLBACKS;\n // We only mark top level nodes or nodes that are inside `var()` expressions as linkable names.\n if (!propertyName || (node.name !== 'ValueName' && node.name !== 'VariableName') ||\n !isAParentDeclarationOrVarCall || (node.name === 'ValueName' && shouldMatchOnlyVariableName)) {\n return null;\n }\n\n if (propertyName === 'animation') {\n return this.matchAnimationNameInShorthand(node, matching);\n }\n\n // The assertion here is safe since this matcher only runs for\n // properties with names inside `LinkableNameProperties` (See the `accepts` function.)\n return new LinkableNameMatch(text, node, propertyName as LinkableNameProperties);\n }\n}\n\nexport class BezierMatch implements Match {\n constructor(readonly text: string, readonly node: CodeMirror.SyntaxNode) {\n }\n}\n\n// clang-format off\nexport class BezierMatcher extends matcherBase(BezierMatch) {\n // clang-format on\n override accepts(propertyName: string): boolean {\n return SDK.CSSMetadata.cssMetadata().isBezierAwareProperty(propertyName);\n }\n\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n const text = matching.ast.text(node);\n\n const isCubicBezierKeyword = node.name === 'ValueName' && UI.Geometry.CubicBezier.KeywordValues.has(text);\n const isCubicBezierOrLinearFunction = node.name === 'CallExpression' &&\n ['cubic-bezier', 'linear'].includes(matching.ast.text(node.getChild('Callee')));\n\n if (!isCubicBezierKeyword && !isCubicBezierOrLinearFunction) {\n return null;\n }\n\n if (!InlineEditor.AnimationTimingModel.AnimationTimingModel.parse(text)) {\n return null;\n }\n return new BezierMatch(text, node);\n }\n}\n\nexport class StringMatch implements Match {\n constructor(readonly text: string, readonly node: CodeMirror.SyntaxNode) {\n }\n}\n\n// clang-format off\nexport class StringMatcher extends matcherBase(StringMatch) {\n // clang-format on\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n return node.name === 'StringLiteral' ? new StringMatch(matching.ast.text(node), node) : null;\n }\n}\n\nexport const enum ShadowType {\n BOX_SHADOW = 'boxShadow',\n TEXT_SHADOW = 'textShadow',\n}\nexport class ShadowMatch implements Match {\n constructor(readonly text: string, readonly node: CodeMirror.SyntaxNode, readonly shadowType: ShadowType) {\n }\n}\n\n// clang-format off\nexport class ShadowMatcher extends matcherBase(ShadowMatch) {\n // clang-format on\n override accepts(propertyName: string): boolean {\n return SDK.CSSMetadata.cssMetadata().isShadowProperty(propertyName);\n }\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n if (node.name !== 'Declaration') {\n return null;\n }\n const valueNodes = ASTUtils.siblings(ASTUtils.declValue(node));\n const valueText = matching.ast.textRange(valueNodes[0], valueNodes[valueNodes.length - 1]);\n return new ShadowMatch(\n valueText, node, matching.ast.propertyName === 'text-shadow' ? ShadowType.TEXT_SHADOW : ShadowType.BOX_SHADOW);\n }\n}\n\nexport class FontMatch implements Match {\n constructor(readonly text: string, readonly node: CodeMirror.SyntaxNode) {\n }\n}\n\n// clang-format off\nexport class FontMatcher extends matcherBase(FontMatch) {\n // clang-format on\n override accepts(propertyName: string): boolean {\n return SDK.CSSMetadata.cssMetadata().isFontAwareProperty(propertyName);\n }\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n if (node.name === 'Declaration') {\n return null;\n }\n const regex = matching.ast.propertyName === 'font-family' ? InlineEditor.FontEditorUtils.FontFamilyRegex :\n InlineEditor.FontEditorUtils.FontPropertiesRegex;\n const text = matching.ast.text(node);\n return regex.test(text) ? new FontMatch(text, node) : null;\n }\n}\n\nexport class LengthMatch implements Match {\n constructor(readonly text: string, readonly node: CodeMirror.SyntaxNode) {\n }\n}\n\n// clang-format off\nexport class LengthMatcher extends matcherBase(LengthMatch) {\n // clang-format on\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n const text = matching.ast.text(node);\n const regexp = new RegExp(`^${InlineEditor.CSSLength.CSS_LENGTH_REGEX.source}$`);\n const match = regexp.exec(text);\n if (!match || match.index !== 0) {\n return null;\n }\n return new LengthMatch(match[0], node);\n }\n}\n\nexport class GridTemplateMatch implements Match {\n constructor(readonly text: string, readonly node: CodeMirror.SyntaxNode, readonly lines: CodeMirror.SyntaxNode[][]) {\n }\n}\n\n// clang-format off\nexport class GridTemplateMatcher extends matcherBase(GridTemplateMatch) {\n // clang-format on\n override accepts(propertyName: string): boolean {\n return SDK.CSSMetadata.cssMetadata().isGridAreaDefiningProperty(propertyName);\n }\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n if (node.name !== 'Declaration' || matching.hasUnresolvedVars(node)) {\n return null;\n }\n\n const lines: CodeMirror.SyntaxNode[][] = [];\n let curLine: CodeMirror.SyntaxNode[] = [];\n // The following two states are designed to consume different cases of LineNames:\n // 1. no LineNames in between StringLiterals;\n // 2. one LineNames in between, which means the LineNames belongs to the current line;\n // 3. two LineNames in between, which means the second LineNames starts a new line.\n // `hasLeadingLineNames` tracks if the current row already starts with a LineNames and\n // with no following StringLiteral yet, which means that the next StringLiteral should\n // be appended to the same `curLine`, instead of creating a new line.\n let hasLeadingLineNames = false;\n // `needClosingLineNames` tracks if the current row can still consume an optional LineNames,\n // which will decide if we should start a new line or not when a LineNames is encountered.\n let needClosingLineNames = false;\n // Gather row definitions of [? ? ?], which\n // be rendered into separate lines.\n function parseNodes(nodes: CodeMirror.SyntaxNode[], varParsingMode = false): void {\n for (const curNode of nodes) {\n if (matching.getMatch(curNode) instanceof SDK.CSSPropertyParser.VariableMatch) {\n const computedValueTree = tokenizeDeclaration('--property', matching.getComputedText(curNode));\n if (!computedValueTree) {\n continue;\n }\n const varNodes = ASTUtils.siblings(ASTUtils.declValue(computedValueTree.tree));\n if (varNodes.length === 0) {\n continue;\n }\n if ((varNodes[0].name === 'StringLiteral' && !hasLeadingLineNames) ||\n (varNodes[0].name === 'LineNames' && !needClosingLineNames)) {\n // The variable value either starts with a string, or with a line name that belongs to a new row;\n // therefore we start a new line with the variable.\n lines.push(curLine);\n curLine = [curNode];\n } else {\n curLine.push(curNode);\n }\n // We parse computed nodes of this variable to correctly advance local states, but\n // these computed nodes won't be added to the lines.\n parseNodes(varNodes, true);\n } else if (curNode.name === 'BinaryExpression') {\n parseNodes(ASTUtils.siblings(curNode.firstChild));\n } else if (curNode.name === 'StringLiteral') {\n if (!varParsingMode) {\n if (hasLeadingLineNames) {\n curLine.push(curNode);\n } else {\n lines.push(curLine);\n curLine = [curNode];\n }\n }\n needClosingLineNames = true;\n hasLeadingLineNames = false;\n } else if (curNode.name === 'LineNames') {\n if (!varParsingMode) {\n if (needClosingLineNames) {\n curLine.push(curNode);\n } else {\n lines.push(curLine);\n curLine = [curNode];\n }\n }\n hasLeadingLineNames = !needClosingLineNames;\n needClosingLineNames = !needClosingLineNames;\n } else if (!varParsingMode) {\n curLine.push(curNode);\n }\n }\n }\n\n const valueNodes = ASTUtils.siblings(ASTUtils.declValue(node));\n parseNodes(valueNodes);\n lines.push(curLine);\n const valueText = matching.ast.textRange(valueNodes[0], valueNodes[valueNodes.length - 1]);\n return new GridTemplateMatch(valueText, node, lines.filter(line => line.length > 0));\n }\n}\nexport class AnchorFunctionMatch implements Match {\n constructor(readonly text: string, readonly node: CodeMirror.SyntaxNode, readonly functionName: string|null) {\n }\n}\n\n// clang-format off\nexport class AnchorFunctionMatcher extends matcherBase(AnchorFunctionMatch) {\n anchorFunction(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): string|null {\n if (node.name !== 'CallExpression') {\n return null;\n }\n const calleeText = matching.ast.text(node.getChild('Callee'));\n if (calleeText === 'anchor' || calleeText === 'anchor-size') {\n return calleeText;\n }\n return null;\n }\n\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n if (node.name === 'VariableName') {\n // Double-dashed anchor reference to be rendered with a link to its matching anchor.\n let parent = node.parent;\n if (!parent || parent.name !== 'ArgList') {\n return null;\n }\n parent = parent.parent;\n if (!parent || !this.anchorFunction(parent, matching)) {\n return null;\n }\n return new AnchorFunctionMatch(matching.ast.text(node), node, null);\n }\n const calleeText = this.anchorFunction(node, matching);\n if (!calleeText) {\n return null;\n }\n // Match if the anchor/anchor-size function implicitly references an anchor.\n const args = ASTUtils.children(node.getChild('ArgList'));\n if (calleeText === 'anchor' && args.length <= 2) {\n return null;\n }\n if (args.find(arg => arg.name === 'VariableName')) {\n // We have an explicit anchor reference, no need to render swatch.\n return null;\n }\n return new AnchorFunctionMatch(matching.ast.text(node), node, calleeText);\n }\n}\n// clang-format on\n\n// For linking `position-anchor: --anchor-name`.\nexport class PositionAnchorMatch implements Match {\n constructor(readonly text: string, readonly matching: BottomUpTreeMatching, readonly node: CodeMirror.SyntaxNode) {\n }\n}\n\n// clang-format off\nexport class PositionAnchorMatcher extends matcherBase(PositionAnchorMatch) {\n override accepts(propertyName: string): boolean {\n return propertyName === 'position-anchor';\n }\n\n override matches(node: CodeMirror.SyntaxNode, matching: BottomUpTreeMatching): Match|null {\n if (node.name !== 'VariableName') {\n return null;\n }\n\n const dashedIdentifier = matching.ast.text(node);\n return new PositionAnchorMatch(dashedIdentifier, matching, node);\n }\n}\n// clang-format on\n"]} \ No newline at end of file diff --git a/public/panels/elements/PropertyMatchers.test.js b/public/panels/elements/PropertyMatchers.test.js index 31bd17689..d86fb3969 100644 --- a/public/panels/elements/PropertyMatchers.test.js +++ b/public/panels/elements/PropertyMatchers.test.js @@ -350,11 +350,13 @@ describe('Matchers for SDK.CSSPropertyParser.BottomUpTreeMatching', () => { const { match, text } = matchSingleValue('left', 'anchor', new Elements.PropertyMatchers.AnchorFunctionMatcher()); assert.isNull(match, text); }); - it('should not match if the anchor() and anchor-size() calls dont have any arguments', () => { + it('should not match anchor() call without arguments', () => { const { match: anchorMatch } = matchSingleValue('left', 'anchor()', new Elements.PropertyMatchers.AnchorFunctionMatcher()); assert.isNull(anchorMatch); - const { match: anchorSizeMatch } = matchSingleValue('width', 'anchor-size()', new Elements.PropertyMatchers.AnchorFunctionMatcher()); - assert.isNull(anchorSizeMatch); + }); + it('should match anchor-size() call without arguments', () => { + const { match: anchorSizeMatch, text: anchorSizeText } = matchSingleValue('width', 'anchor-size()', new Elements.PropertyMatchers.AnchorFunctionMatcher()); + assert.exists(anchorSizeMatch, anchorSizeText); }); it('should match if it is an anchor() or anchor-size() call', () => { const { match: anchorMatch, text: anchorText } = matchSingleValue('left', 'anchor(left)', new Elements.PropertyMatchers.AnchorFunctionMatcher()); @@ -363,12 +365,20 @@ describe('Matchers for SDK.CSSPropertyParser.BottomUpTreeMatching', () => { assert.exists(anchorSizeMatch, anchorSizeText); }); it('should match dashed identifier as name from the first argument', () => { - const { ast: anchorAst, match: anchorMatch, text: anchorText } = matchSingleValue('left', 'anchor(--dashed-ident left)', new Elements.PropertyMatchers.AnchorFunctionMatcher()); + const { match: anchorMatch, text: anchorText } = matchSingleValue('left', 'anchor(--dashed-ident left)', new Elements.PropertyMatchers.AnchorFunctionMatcher()); + assert.exists(anchorMatch, anchorText); + assert.strictEqual(anchorMatch.text, '--dashed-ident'); + const { match: anchorSizeMatch, text: anchorSizeText } = matchSingleValue('width', 'anchor-size(--dashed-ident width)', new Elements.PropertyMatchers.AnchorFunctionMatcher()); + assert.exists(anchorSizeMatch, anchorSizeText); + assert.strictEqual(anchorSizeMatch.text, '--dashed-ident'); + }); + it('should match dashed identifier as name from the second argument', () => { + const { match: anchorMatch, text: anchorText } = matchSingleValue('left', 'anchor(right --dashed-ident)', new Elements.PropertyMatchers.AnchorFunctionMatcher()); assert.exists(anchorMatch, anchorText); - assert.strictEqual(anchorAst.text(anchorMatch.args[0]), '--dashed-ident'); - const { ast: anchorSizeAst, match: anchorSizeMatch, text: anchorSizeText } = matchSingleValue('width', 'anchor-size(--dashed-ident width)', new Elements.PropertyMatchers.AnchorFunctionMatcher()); + assert.strictEqual(anchorMatch.text, '--dashed-ident'); + const { match: anchorSizeMatch, text: anchorSizeText } = matchSingleValue('width', 'anchor-size(height --dashed-ident)', new Elements.PropertyMatchers.AnchorFunctionMatcher()); assert.exists(anchorSizeMatch, anchorSizeText); - assert.strictEqual(anchorSizeAst.text(anchorSizeMatch.args[0]), '--dashed-ident'); + assert.strictEqual(anchorSizeMatch.text, '--dashed-ident'); }); }); describe('PositionAnchorMatcher', () => { diff --git a/public/panels/elements/PropertyMatchers.test.js.map b/public/panels/elements/PropertyMatchers.test.js.map index d99bb7b87..78fff6e3a 100644 --- a/public/panels/elements/PropertyMatchers.test.js.map +++ b/public/panels/elements/PropertyMatchers.test.js.map @@ -1 +1 @@ -{"version":3,"file":"PropertyMatchers.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/elements/PropertyMatchers.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as SDK from '../../core/sdk/sdk.js';\nimport {Printer} from '../../testing/PropertyParser.js';\nimport type * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';\n\nimport * as Elements from './elements.js';\n\nfunction matchSingleValue(\n name: string, value: string, matcher: SDK.CSSPropertyParser.Matcher):\n {ast: SDK.CSSPropertyParser.SyntaxTree|null, match: T|null, text: string} {\n const ast = SDK.CSSPropertyParser.tokenizeDeclaration(name, value);\n if (!ast) {\n return {ast, match: null, text: value};\n }\n\n const matchedResult = SDK.CSSPropertyParser.BottomUpTreeMatching.walk(ast, [matcher]);\n const matchedNode =\n SDK.CSSPropertyParser.TreeSearch.find(ast, n => matchedResult.getMatch(n) instanceof matcher.matchType);\n const match = matchedNode && matchedResult.getMatch(matchedNode);\n\n return {\n ast,\n match: match instanceof matcher.matchType ? match : null,\n text: Printer.walk(ast).get(),\n };\n}\n\nfunction injectVariableSubstitutions(variables: Record) {\n const {getComputedText, getComputedTextRange, getMatch} = SDK.CSSPropertyParser.BottomUpTreeMatching.prototype;\n const variableNames = new Map();\n function injectChunk(matching: SDK.CSSPropertyParser.BottomUpTreeMatching): void {\n if (matching.computedText.chunkCount === 0) {\n const propertyOffset = matching.ast.rule.indexOf(matching.ast.propertyName ?? '--');\n assert.isAbove(propertyOffset, 0);\n for (const [varName, value] of Object.entries(variables)) {\n const varText = `var(${varName})`;\n for (let offset = matching.ast.rule.indexOf(varText); offset >= 0;\n offset = matching.ast.rule.indexOf(varText, offset + 1)) {\n matching.computedText.push(\n {text: varText, computedText: () => value, node: {} as CodeMirror.SyntaxNode}, offset - propertyOffset);\n }\n variableNames.set(varText, {varName, value});\n }\n }\n }\n\n sinon.stub(SDK.CSSPropertyParser.BottomUpTreeMatching.prototype, 'getComputedText')\n .callsFake(function(this: SDK.CSSPropertyParser.BottomUpTreeMatching, node: CodeMirror.SyntaxNode): string {\n injectChunk(this);\n return getComputedText.call(this, node);\n });\n sinon.stub(SDK.CSSPropertyParser.BottomUpTreeMatching.prototype, 'getComputedTextRange')\n .callsFake(function(\n this: SDK.CSSPropertyParser.BottomUpTreeMatching, from: CodeMirror.SyntaxNode,\n to: CodeMirror.SyntaxNode): string {\n injectChunk(this);\n return getComputedTextRange.call(this, from, to);\n });\n sinon.stub(SDK.CSSPropertyParser.BottomUpTreeMatching.prototype, 'getMatch')\n .callsFake(function(this: SDK.CSSPropertyParser.BottomUpTreeMatching, node: CodeMirror.SyntaxNode):\n SDK.CSSPropertyParser.Match|undefined {\n injectChunk(this);\n const resolvedValue = variableNames.get(this.ast.text(node));\n if (!resolvedValue) {\n return getMatch.call(this, node);\n }\n return new SDK.CSSPropertyParser.VariableMatch(\n this.ast.text(node), node, resolvedValue.varName, [], this, () => resolvedValue.value);\n });\n}\n\ndescribe('Matchers for SDK.CSSPropertyParser.BottomUpTreeMatching', () => {\n it('parses colors', () => {\n for (const fail of ['red-blue', '#f', '#foobar', '', 'rgbz(1 2 2)', 'tan(45deg)']) {\n const {match, text} = matchSingleValue('color', fail, new Elements.PropertyMatchers.ColorMatcher());\n assert.isNull(match, text);\n }\n for (const succeed\n of ['rgb(/* R */155, /* G */51, /* B */255)', 'red', 'rgb(0 0 0)', 'rgba(0 0 0)', '#fff', '#ffff',\n '#ffffff', '#ffffffff']) {\n const {match, text} = matchSingleValue('color', succeed, new Elements.PropertyMatchers.ColorMatcher());\n assert.exists(match, text);\n assert.strictEqual(match.text, succeed);\n }\n // The property name matters:\n for (const fail\n of ['rgb(/* R */155, /* G */51, /* B */255)', 'red', 'rgb(0 0 0)', 'rgba(0 0 0)', '#fff', '#ffff',\n '#ffffff', '#ffffffff']) {\n const {match, text} = matchSingleValue('width', fail, new Elements.PropertyMatchers.ColorMatcher());\n assert.isNull(match, text);\n }\n });\n\n it('parses colors in logical border properties', () => {\n for (const success\n of ['border-block-end', 'border-block-end-color', 'border-block-start', 'border-block-start-color',\n 'border-inline-end', 'border-inline-end-color', 'border-inline-start', 'border-inline-start-color']) {\n const {ast, match, text} = matchSingleValue(success, 'red', new Elements.PropertyMatchers.ColorMatcher());\n assert.exists(match, text);\n assert.strictEqual(match.text, 'red');\n assert.strictEqual(ast?.propertyName, success);\n }\n });\n\n it('parses linear gradients', () => {\n for (const succeed\n of ['linear-gradient(90deg, red, blue)', 'linear-gradient(to top left, red, blue)',\n 'linear-gradient(in oklab, red, blue)']) {\n const {match, text} =\n matchSingleValue('background', succeed, new Elements.PropertyMatchers.LinearGradientMatcher());\n assert.exists(match, text);\n assert.strictEqual(match.text, succeed);\n }\n for (const fail\n of ['linear-gradient(90deg, red, blue)', 'linear-gradient(to top left, red, blue)',\n 'linear-gradient(in oklab, red, blue)']) {\n const {match, text} = matchSingleValue('width', fail, new Elements.PropertyMatchers.ColorMatcher());\n assert.isNull(match, text);\n }\n });\n\n it('parses colors in masks', () => {\n for (const succeed of ['mask', 'mask-image', 'mask-border', 'mask-border-source']) {\n const ast = SDK.CSSPropertyParser.tokenizeDeclaration(succeed, 'linear-gradient(to top, red, var(--other))');\n assert.exists(ast, succeed);\n const matching =\n SDK.CSSPropertyParser.BottomUpTreeMatching.walk(ast, [new Elements.PropertyMatchers.ColorMatcher()]);\n const colorNode = SDK.CSSPropertyParser.TreeSearch.find(ast, node => ast.text(node) === 'red');\n assert.exists(colorNode);\n const match = matching.getMatch(colorNode);\n assert.exists(match);\n assert.instanceOf(match, Elements.PropertyMatchers.ColorMatch);\n assert.strictEqual(match.text, 'red');\n }\n });\n\n it('parses color-mix with vars', () => {\n injectVariableSubstitutions({\n '--interpolation': 'shorter',\n '--color1': 'red',\n '--percentage': '13%',\n '--rgb': 'shorter',\n '--space': 'in srgb',\n '--color2': '25% blue',\n '--multiple-colors': 'red, blue',\n });\n {\n const {ast, match, text} = matchSingleValue(\n 'color', 'color-mix(in srgb var(--interpolation) hue, red var(--percentage), rgb(var(--rgb)))',\n new Elements.PropertyMatchers.ColorMixMatcher());\n assert.exists(ast, text);\n assert.exists(match, text);\n assert.deepStrictEqual(match.space.map(n => ast.text(n)), ['in', 'srgb', 'var(--interpolation)', 'hue']);\n assert.strictEqual(match.color1.map(n => ast.text(n)).join(), 'red,var(--percentage)');\n assert.strictEqual(match.color2.map(n => ast.text(n)).join(), 'rgb(var(--rgb))');\n }\n {\n const {ast, match, text} = matchSingleValue(\n 'color', 'color-mix(var(--space), var(--color1), var(--color2))',\n new Elements.PropertyMatchers.ColorMixMatcher());\n assert.exists(ast, text);\n assert.exists(match, text);\n assert.strictEqual(match.space.map(n => ast.text(n)).join(), 'var(--space)');\n assert.strictEqual(match.color1.map(n => ast.text(n)).join(), 'var(--color1)');\n assert.strictEqual(match.color2.map(n => ast.text(n)).join(), 'var(--color2)');\n }\n\n for (const fail\n of ['color-mix(var(--color1), var(--color1), var(--color2))',\n 'color-mix(var(--space), var(--color1) var(--percentage) var(--percentage), var(--color2))',\n 'color-mix(var(--space), var(--color1) 10% var(--percentage), var(--color2))',\n 'color-mix(var(--space), var(--color1), var(--color2) 15%)',\n 'color-mix(var(--space), var(--color1), var(--color2) var(--percentage))',\n 'color-mix(var(--space), var(--multiple-colors))',\n ]) {\n const {ast, match, text} = matchSingleValue('color', fail, new Elements.PropertyMatchers.ColorMixMatcher());\n assert.exists(ast, text);\n assert.isNull(match, text);\n }\n });\n\n it('parses color-mix', () => {\n function check(space: string, color1: string, color2: string): void {\n const {ast, match, text} = matchSingleValue(\n 'color', `color-mix(${space}, ${color1}, ${color2})`, new Elements.PropertyMatchers.ColorMixMatcher());\n assert.exists(ast, text);\n assert.exists(match, text);\n\n assert.deepStrictEqual(match.space.map(n => ast.text(n)).join(' '), space, text);\n assert.strictEqual(match.color1.map(n => ast.text(n)).join(' '), color1, text);\n assert.strictEqual(match.color2.map(n => ast.text(n)).join(' '), color2, text);\n }\n\n function checkFailure(space: string, color1: string, color2: string): void {\n const {match, text} = matchSingleValue(\n 'color', `color-mix(${space}, ${color1}, ${color2})`, new Elements.PropertyMatchers.ColorMixMatcher());\n assert.isNull(match, text);\n }\n\n check('in srgb shorter hue', 'red 35%', 'blue');\n check('in /*asd*/ srgb shorter hue', 'red 35%', 'blue');\n check('in srgb', 'red 35%', 'blue');\n check('in srgb', '35% red', 'blue 16%');\n check('in srgb', '/*a*/ 35% /*b*/ red /*c*/', '/*a*/ blue /*b*/ 16% /*c*/');\n checkFailure('insrgb shorter hue', 'red 35%', 'blue');\n checkFailure('/*asd*/srgb in', 'red 35%', 'blue');\n checkFailure('in srgb', '0% red', 'blue 0%');\n });\n\n it('parses URLs', () => {\n const url = 'http://example.com';\n {\n const {match, text} =\n matchSingleValue('background-image', `url(${url})`, new Elements.PropertyMatchers.URLMatcher());\n assert.exists(match);\n assert.strictEqual(match.url, url, text);\n }\n {\n const {match, text} =\n matchSingleValue('background-image', `url(\"${url}\")`, new Elements.PropertyMatchers.URLMatcher());\n assert.exists(match);\n assert.strictEqual(match.url, url, text);\n }\n });\n\n it('parses angles correctly', () => {\n for (const succeed of ['45deg', '1.3rad', '-25grad', '2.3turn']) {\n const {ast, match, text} = matchSingleValue('transform', succeed, new Elements.PropertyMatchers.AngleMatcher());\n assert.exists(ast, succeed);\n assert.exists(match, text);\n assert.strictEqual(match.text, succeed);\n }\n for (const fail of ['0DEG', '0', '123', '2em']) {\n const {match, text} = matchSingleValue('transform', fail, new Elements.PropertyMatchers.AngleMatcher());\n assert.isNull(match, text);\n }\n });\n\n it('parses linkable names correctly', () => {\n function match(name: string, value: string) {\n const ast = SDK.CSSPropertyParser.tokenizeDeclaration(name, value);\n assert.exists(ast);\n const matchedResult = SDK.CSSPropertyParser.BottomUpTreeMatching.walk(ast, [\n new Elements.PropertyMatchers.LinkableNameMatcher(),\n ]);\n\n const matches = SDK.CSSPropertyParser.TreeSearch.findAll(\n ast, node => matchedResult.getMatch(node) instanceof Elements.PropertyMatchers.LinkableNameMatch);\n return matches.map(m => matchedResult.getMatch(m)?.text);\n }\n\n assert.deepStrictEqual(match('animation-name', 'first, second, -moz-third'), ['first', 'second', '-moz-third']);\n assert.deepStrictEqual(match('animation-name', 'first'), ['first']);\n assert.deepStrictEqual(match('font-palette', 'first'), ['first']);\n {\n assert.deepStrictEqual(match('position-try-fallbacks', 'flip-block'), []);\n assert.deepStrictEqual(match('position-try-fallbacks', '--one'), ['--one']);\n assert.deepStrictEqual(match('position-try-fallbacks', '--one, --two'), ['--one', '--two']);\n }\n {\n assert.deepStrictEqual(match('position-try', 'flip-block'), []);\n assert.deepStrictEqual(match('position-try', '--one'), ['--one']);\n assert.deepStrictEqual(match('position-try', '--one, --two'), ['--one', '--two']);\n }\n {\n injectVariableSubstitutions({\n '--duration-and-easing': '1s linear',\n });\n assert.deepStrictEqual(match('animation', '1s linear --animation-name'), ['--animation-name']);\n assert.deepStrictEqual(match('animation', '1s linear linear'), ['linear']);\n assert.deepStrictEqual(\n match('animation', '1s linear --first-name, 1s ease-in --second-name'), ['--first-name', '--second-name']);\n assert.deepStrictEqual(match('animation', '1s linear'), []);\n // Matching to variable names inside `var()` functions are fine as it is handled by variable renderer in usage.\n assert.deepStrictEqual(\n match('animation', 'var(--duration-and-easing) linear'), ['--duration-and-easing', 'linear']);\n assert.deepStrictEqual(\n match('animation', '1s linear var(--non-existent, --animation-name)'),\n ['--non-existent', '--animation-name']);\n }\n });\n\n it('parses easing functions properly', () => {\n for (const succeed\n of ['linear', 'ease', 'ease-in', 'ease-out', 'ease-in-out', 'linear(0 0%, 1 100%)',\n 'cubic-bezier(0.3, 0.3, 0.3, 0.3)']) {\n const {ast, match, text} =\n matchSingleValue('animation-timing-function', succeed, new Elements.PropertyMatchers.BezierMatcher());\n assert.exists(ast, succeed);\n assert.exists(match, text);\n assert.strictEqual(match.text, succeed);\n }\n\n const {ast, match, text} = matchSingleValue('border', 'ease-in', new Elements.PropertyMatchers.BezierMatcher());\n assert.exists(ast, 'border');\n assert.isNull(match, text);\n });\n\n it('parses strings correctly', () => {\n function match(name: string, value: string) {\n const ast = SDK.CSSPropertyParser.tokenizeDeclaration(name, value);\n assert.exists(ast);\n const matchedResult =\n SDK.CSSPropertyParser.BottomUpTreeMatching.walk(ast, [new Elements.PropertyMatchers.StringMatcher()]);\n assert.exists(matchedResult);\n\n const match = SDK.CSSPropertyParser.TreeSearch.find(\n ast, node => matchedResult.getMatch(node) instanceof Elements.PropertyMatchers.StringMatch);\n assert.exists(match);\n }\n match('quotes', '\"\\'\" \"\\'\"');\n match('content', '\"foobar\"');\n match('--image-file-accelerometer-back', 'url(\"devtools\\:\\/\\/devtools\\/bundled\\/Images\\/accelerometer-back\\.svg\")');\n });\n\n it('parses shadows correctly', () => {\n const {match, text} = matchSingleValue(\n 'box-shadow', '/*0*/3px 3px red, -1em 0 .4em /*a*/ olive /*b*/', new Elements.PropertyMatchers.ShadowMatcher());\n assert.exists(match, text);\n assert.strictEqual(match.text, '/*0*/3px 3px red, -1em 0 .4em /*a*/ olive');\n });\n\n it('parses fonts correctly', () => {\n for (const fontSize of ['-.23', 'smaller', '17px']) {\n const {ast, match, text} = matchSingleValue('font-size', fontSize, new Elements.PropertyMatchers.FontMatcher());\n\n assert.exists(ast, text);\n assert.exists(match, text);\n assert.strictEqual(match.text, fontSize);\n }\n\n {\n const ast = SDK.CSSPropertyParser.tokenizeDeclaration('font-family', '\"Gill Sans\", sans-serif');\n assert.exists(ast);\n const matchedResult =\n SDK.CSSPropertyParser.BottomUpTreeMatching.walk(ast, [new Elements.PropertyMatchers.FontMatcher()]);\n assert.exists(matchedResult);\n\n const matches = SDK.CSSPropertyParser.TreeSearch.findAll(\n ast, node => matchedResult.getMatch(node) instanceof Elements.PropertyMatchers.FontMatch);\n assert.deepStrictEqual(matches.map(m => matchedResult.getMatch(m)?.text), ['\"Gill Sans\"', 'sans-serif']);\n }\n });\n\n it('parses grid templates correctly', () => {\n injectVariableSubstitutions({\n '--row': '\"a a b\"',\n '--row-with-names': '[name1] \"a a\" [name2]',\n '--line-name': '[name1]',\n '--double-row': '\"a b\" \"b c\"',\n });\n\n {\n const {ast, match, text} = matchSingleValue('grid', '\"a a\"', new Elements.PropertyMatchers.GridTemplateMatcher());\n assert.exists(ast, text);\n assert.exists(match, text);\n assert.strictEqual(match.lines.map(line => line.map(n => ast.text(n)).join(' ')).join('\\n'), '\"a a\"');\n }\n {\n const {ast, match, text} = matchSingleValue(\n 'grid-template-areas', '\"a a a\" \"b b b\" \"c c c\"', new Elements.PropertyMatchers.GridTemplateMatcher());\n assert.exists(ast, text);\n assert.exists(match, text);\n assert.deepStrictEqual(\n match.lines.map(line => line.map(n => ast.text(n)).join(' ')), ['\"a a a\"', '\"b b b\"', '\"c c c\"']);\n }\n {\n const {ast, match, text} = matchSingleValue(\n 'grid-template', '\"a a a\" var(--row) / auto 1fr auto', new Elements.PropertyMatchers.GridTemplateMatcher());\n assert.exists(ast, text);\n assert.exists(match, text);\n assert.deepStrictEqual(\n match.lines.map(line => line.map(n => ast.text(n)).join(' ')), ['\"a a a\"', 'var(--row) / auto 1fr auto']);\n }\n {\n const {ast, match, text} = matchSingleValue(\n 'grid', '[header-top] \"a a\" var(--row-with-names) [main-top] \"b b b\" 1fr [main-bottom] / auto 1fr auto;',\n\n new Elements.PropertyMatchers.GridTemplateMatcher());\n assert.exists(ast, text);\n assert.exists(match, text);\n assert.deepStrictEqual(\n match.lines.map(line => line.map(n => ast.text(n)).join(' ')),\n ['[header-top] \"a a\" var(--row-with-names)', '[main-top] \"b b b\" 1fr [main-bottom] / auto 1fr auto']);\n }\n {\n const {ast, match, text} = matchSingleValue(\n 'grid', '[header-top] \"a a\" \"b b b\" var(--line-name) \"c c\" / auto 1fr auto;',\n\n new Elements.PropertyMatchers.GridTemplateMatcher());\n assert.exists(ast, text);\n assert.exists(match, text);\n assert.deepStrictEqual(\n match.lines.map(line => line.map(n => ast.text(n)).join(' ')),\n ['[header-top] \"a a\"', '\"b b b\" var(--line-name)', '\"c c\" / auto 1fr auto']);\n }\n {\n const {ast, match, text} = matchSingleValue(\n 'grid', '[line1] \"a a\" [line2] var(--double-row) \"b b\" / auto 1fr auto;',\n\n new Elements.PropertyMatchers.GridTemplateMatcher());\n assert.exists(ast, text);\n assert.exists(match, text);\n assert.deepStrictEqual(\n match.lines.map(line => line.map(n => ast.text(n)).join(' ')),\n ['[line1] \"a a\" [line2]', 'var(--double-row)', '\"b b\" / auto 1fr auto']);\n }\n {\n const {ast, match, text} = matchSingleValue(\n 'grid', '\"a a\" var(--unresolved) / auto 1fr auto;', new Elements.PropertyMatchers.GridTemplateMatcher());\n assert.exists(ast, text);\n assert.exists(match, text);\n assert.deepStrictEqual(\n match.lines.map(line => line.map(n => ast.text(n)).join(' ')), ['\"a a\" var(--unresolved) / auto 1fr auto']);\n }\n });\n\n it('parses light-dark correctly', () => {\n for (const fail of ['light-dark()', 'light-dark(red)', 'light-dark(var(--foo))']) {\n const {match, text} = matchSingleValue('color', fail, new Elements.PropertyMatchers.LightDarkColorMatcher());\n assert.isNull(match, text);\n }\n\n for (const succeed\n of ['light-dark(red, blue)', 'light-dark(var(--foo), red)', 'light-dark(red, var(--foo))',\n 'light-dark(var(--foo), var(--bar))']) {\n const {ast, match, text} =\n matchSingleValue('color', succeed, new Elements.PropertyMatchers.LightDarkColorMatcher());\n assert.exists(ast, text);\n assert.exists(match, text);\n\n const [light, dark] = succeed.slice('light-dark('.length, -1).split(', ');\n assert.lengthOf(match.light, 1);\n assert.lengthOf(match.dark, 1);\n assert.strictEqual(ast.text(match.light[0]), light);\n assert.strictEqual(ast.text(match.dark[0]), dark);\n }\n\n // light-dark only applies to color properties\n const {match, text} =\n matchSingleValue('width', 'light-dark(red, blue)', new Elements.PropertyMatchers.LightDarkColorMatcher());\n assert.isNull(match, text);\n });\n\n describe('AnchorFunctionMatcher', () => {\n it('should not match when it is not a call expression', () => {\n const {match, text} = matchSingleValue('left', 'anchor', new Elements.PropertyMatchers.AnchorFunctionMatcher());\n assert.isNull(match, text);\n });\n\n it('should not match if the anchor() and anchor-size() calls dont have any arguments', () => {\n const {match: anchorMatch} =\n matchSingleValue('left', 'anchor()', new Elements.PropertyMatchers.AnchorFunctionMatcher());\n assert.isNull(anchorMatch);\n\n const {match: anchorSizeMatch} =\n matchSingleValue('width', 'anchor-size()', new Elements.PropertyMatchers.AnchorFunctionMatcher());\n assert.isNull(anchorSizeMatch);\n });\n\n it('should match if it is an anchor() or anchor-size() call', () => {\n const {match: anchorMatch, text: anchorText} =\n matchSingleValue('left', 'anchor(left)', new Elements.PropertyMatchers.AnchorFunctionMatcher());\n assert.exists(anchorMatch, anchorText);\n\n const {match: anchorSizeMatch, text: anchorSizeText} =\n matchSingleValue('width', 'anchor-size(width)', new Elements.PropertyMatchers.AnchorFunctionMatcher());\n assert.exists(anchorSizeMatch, anchorSizeText);\n });\n\n it('should match dashed identifier as name from the first argument', () => {\n const {ast: anchorAst, match: anchorMatch, text: anchorText} = matchSingleValue(\n 'left', 'anchor(--dashed-ident left)', new Elements.PropertyMatchers.AnchorFunctionMatcher());\n assert.exists(anchorMatch, anchorText);\n assert.strictEqual(anchorAst!.text(anchorMatch.args[0]), '--dashed-ident');\n\n const {ast: anchorSizeAst, match: anchorSizeMatch, text: anchorSizeText} = matchSingleValue(\n 'width', 'anchor-size(--dashed-ident width)', new Elements.PropertyMatchers.AnchorFunctionMatcher());\n assert.exists(anchorSizeMatch, anchorSizeText);\n assert.strictEqual(anchorSizeAst!.text(anchorSizeMatch.args[0]), '--dashed-ident');\n });\n });\n\n describe('PositionAnchorMatcher', () => {\n it('should match `position-anchor` property with dashed identifier', () => {\n const {match, text} =\n matchSingleValue('position-anchor', '--dashed-ident', new Elements.PropertyMatchers.PositionAnchorMatcher());\n assert.exists(match, text);\n assert.strictEqual(match.text, '--dashed-ident');\n });\n\n it('should not match `position-anchor` property when it is not a dashed identifier', () => {\n const {match} = matchSingleValue(\n 'position-anchor', 'something-non-dashed', new Elements.PropertyMatchers.PositionAnchorMatcher());\n assert.isNull(match);\n });\n });\n\n it('matches lengths', () => {\n const {match, text} = matchSingleValue('min-width', '100px', new Elements.PropertyMatchers.LengthMatcher());\n assert.exists(match, text);\n assert.strictEqual(match.text, '100px');\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"PropertyMatchers.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/elements/PropertyMatchers.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as SDK from '../../core/sdk/sdk.js';\nimport {Printer} from '../../testing/PropertyParser.js';\nimport type * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';\n\nimport * as Elements from './elements.js';\n\nfunction matchSingleValue(\n name: string, value: string, matcher: SDK.CSSPropertyParser.Matcher):\n {ast: SDK.CSSPropertyParser.SyntaxTree|null, match: T|null, text: string} {\n const ast = SDK.CSSPropertyParser.tokenizeDeclaration(name, value);\n if (!ast) {\n return {ast, match: null, text: value};\n }\n\n const matchedResult = SDK.CSSPropertyParser.BottomUpTreeMatching.walk(ast, [matcher]);\n const matchedNode =\n SDK.CSSPropertyParser.TreeSearch.find(ast, n => matchedResult.getMatch(n) instanceof matcher.matchType);\n const match = matchedNode && matchedResult.getMatch(matchedNode);\n\n return {\n ast,\n match: match instanceof matcher.matchType ? match : null,\n text: Printer.walk(ast).get(),\n };\n}\n\nfunction injectVariableSubstitutions(variables: Record) {\n const {getComputedText, getComputedTextRange, getMatch} = SDK.CSSPropertyParser.BottomUpTreeMatching.prototype;\n const variableNames = new Map();\n function injectChunk(matching: SDK.CSSPropertyParser.BottomUpTreeMatching): void {\n if (matching.computedText.chunkCount === 0) {\n const propertyOffset = matching.ast.rule.indexOf(matching.ast.propertyName ?? '--');\n assert.isAbove(propertyOffset, 0);\n for (const [varName, value] of Object.entries(variables)) {\n const varText = `var(${varName})`;\n for (let offset = matching.ast.rule.indexOf(varText); offset >= 0;\n offset = matching.ast.rule.indexOf(varText, offset + 1)) {\n matching.computedText.push(\n {text: varText, computedText: () => value, node: {} as CodeMirror.SyntaxNode}, offset - propertyOffset);\n }\n variableNames.set(varText, {varName, value});\n }\n }\n }\n\n sinon.stub(SDK.CSSPropertyParser.BottomUpTreeMatching.prototype, 'getComputedText')\n .callsFake(function(this: SDK.CSSPropertyParser.BottomUpTreeMatching, node: CodeMirror.SyntaxNode): string {\n injectChunk(this);\n return getComputedText.call(this, node);\n });\n sinon.stub(SDK.CSSPropertyParser.BottomUpTreeMatching.prototype, 'getComputedTextRange')\n .callsFake(function(\n this: SDK.CSSPropertyParser.BottomUpTreeMatching, from: CodeMirror.SyntaxNode,\n to: CodeMirror.SyntaxNode): string {\n injectChunk(this);\n return getComputedTextRange.call(this, from, to);\n });\n sinon.stub(SDK.CSSPropertyParser.BottomUpTreeMatching.prototype, 'getMatch')\n .callsFake(function(this: SDK.CSSPropertyParser.BottomUpTreeMatching, node: CodeMirror.SyntaxNode):\n SDK.CSSPropertyParser.Match|undefined {\n injectChunk(this);\n const resolvedValue = variableNames.get(this.ast.text(node));\n if (!resolvedValue) {\n return getMatch.call(this, node);\n }\n return new SDK.CSSPropertyParser.VariableMatch(\n this.ast.text(node), node, resolvedValue.varName, [], this, () => resolvedValue.value);\n });\n}\n\ndescribe('Matchers for SDK.CSSPropertyParser.BottomUpTreeMatching', () => {\n it('parses colors', () => {\n for (const fail of ['red-blue', '#f', '#foobar', '', 'rgbz(1 2 2)', 'tan(45deg)']) {\n const {match, text} = matchSingleValue('color', fail, new Elements.PropertyMatchers.ColorMatcher());\n assert.isNull(match, text);\n }\n for (const succeed\n of ['rgb(/* R */155, /* G */51, /* B */255)', 'red', 'rgb(0 0 0)', 'rgba(0 0 0)', '#fff', '#ffff',\n '#ffffff', '#ffffffff']) {\n const {match, text} = matchSingleValue('color', succeed, new Elements.PropertyMatchers.ColorMatcher());\n assert.exists(match, text);\n assert.strictEqual(match.text, succeed);\n }\n // The property name matters:\n for (const fail\n of ['rgb(/* R */155, /* G */51, /* B */255)', 'red', 'rgb(0 0 0)', 'rgba(0 0 0)', '#fff', '#ffff',\n '#ffffff', '#ffffffff']) {\n const {match, text} = matchSingleValue('width', fail, new Elements.PropertyMatchers.ColorMatcher());\n assert.isNull(match, text);\n }\n });\n\n it('parses colors in logical border properties', () => {\n for (const success\n of ['border-block-end', 'border-block-end-color', 'border-block-start', 'border-block-start-color',\n 'border-inline-end', 'border-inline-end-color', 'border-inline-start', 'border-inline-start-color']) {\n const {ast, match, text} = matchSingleValue(success, 'red', new Elements.PropertyMatchers.ColorMatcher());\n assert.exists(match, text);\n assert.strictEqual(match.text, 'red');\n assert.strictEqual(ast?.propertyName, success);\n }\n });\n\n it('parses linear gradients', () => {\n for (const succeed\n of ['linear-gradient(90deg, red, blue)', 'linear-gradient(to top left, red, blue)',\n 'linear-gradient(in oklab, red, blue)']) {\n const {match, text} =\n matchSingleValue('background', succeed, new Elements.PropertyMatchers.LinearGradientMatcher());\n assert.exists(match, text);\n assert.strictEqual(match.text, succeed);\n }\n for (const fail\n of ['linear-gradient(90deg, red, blue)', 'linear-gradient(to top left, red, blue)',\n 'linear-gradient(in oklab, red, blue)']) {\n const {match, text} = matchSingleValue('width', fail, new Elements.PropertyMatchers.ColorMatcher());\n assert.isNull(match, text);\n }\n });\n\n it('parses colors in masks', () => {\n for (const succeed of ['mask', 'mask-image', 'mask-border', 'mask-border-source']) {\n const ast = SDK.CSSPropertyParser.tokenizeDeclaration(succeed, 'linear-gradient(to top, red, var(--other))');\n assert.exists(ast, succeed);\n const matching =\n SDK.CSSPropertyParser.BottomUpTreeMatching.walk(ast, [new Elements.PropertyMatchers.ColorMatcher()]);\n const colorNode = SDK.CSSPropertyParser.TreeSearch.find(ast, node => ast.text(node) === 'red');\n assert.exists(colorNode);\n const match = matching.getMatch(colorNode);\n assert.exists(match);\n assert.instanceOf(match, Elements.PropertyMatchers.ColorMatch);\n assert.strictEqual(match.text, 'red');\n }\n });\n\n it('parses color-mix with vars', () => {\n injectVariableSubstitutions({\n '--interpolation': 'shorter',\n '--color1': 'red',\n '--percentage': '13%',\n '--rgb': 'shorter',\n '--space': 'in srgb',\n '--color2': '25% blue',\n '--multiple-colors': 'red, blue',\n });\n {\n const {ast, match, text} = matchSingleValue(\n 'color', 'color-mix(in srgb var(--interpolation) hue, red var(--percentage), rgb(var(--rgb)))',\n new Elements.PropertyMatchers.ColorMixMatcher());\n assert.exists(ast, text);\n assert.exists(match, text);\n assert.deepStrictEqual(match.space.map(n => ast.text(n)), ['in', 'srgb', 'var(--interpolation)', 'hue']);\n assert.strictEqual(match.color1.map(n => ast.text(n)).join(), 'red,var(--percentage)');\n assert.strictEqual(match.color2.map(n => ast.text(n)).join(), 'rgb(var(--rgb))');\n }\n {\n const {ast, match, text} = matchSingleValue(\n 'color', 'color-mix(var(--space), var(--color1), var(--color2))',\n new Elements.PropertyMatchers.ColorMixMatcher());\n assert.exists(ast, text);\n assert.exists(match, text);\n assert.strictEqual(match.space.map(n => ast.text(n)).join(), 'var(--space)');\n assert.strictEqual(match.color1.map(n => ast.text(n)).join(), 'var(--color1)');\n assert.strictEqual(match.color2.map(n => ast.text(n)).join(), 'var(--color2)');\n }\n\n for (const fail\n of ['color-mix(var(--color1), var(--color1), var(--color2))',\n 'color-mix(var(--space), var(--color1) var(--percentage) var(--percentage), var(--color2))',\n 'color-mix(var(--space), var(--color1) 10% var(--percentage), var(--color2))',\n 'color-mix(var(--space), var(--color1), var(--color2) 15%)',\n 'color-mix(var(--space), var(--color1), var(--color2) var(--percentage))',\n 'color-mix(var(--space), var(--multiple-colors))',\n ]) {\n const {ast, match, text} = matchSingleValue('color', fail, new Elements.PropertyMatchers.ColorMixMatcher());\n assert.exists(ast, text);\n assert.isNull(match, text);\n }\n });\n\n it('parses color-mix', () => {\n function check(space: string, color1: string, color2: string): void {\n const {ast, match, text} = matchSingleValue(\n 'color', `color-mix(${space}, ${color1}, ${color2})`, new Elements.PropertyMatchers.ColorMixMatcher());\n assert.exists(ast, text);\n assert.exists(match, text);\n\n assert.deepStrictEqual(match.space.map(n => ast.text(n)).join(' '), space, text);\n assert.strictEqual(match.color1.map(n => ast.text(n)).join(' '), color1, text);\n assert.strictEqual(match.color2.map(n => ast.text(n)).join(' '), color2, text);\n }\n\n function checkFailure(space: string, color1: string, color2: string): void {\n const {match, text} = matchSingleValue(\n 'color', `color-mix(${space}, ${color1}, ${color2})`, new Elements.PropertyMatchers.ColorMixMatcher());\n assert.isNull(match, text);\n }\n\n check('in srgb shorter hue', 'red 35%', 'blue');\n check('in /*asd*/ srgb shorter hue', 'red 35%', 'blue');\n check('in srgb', 'red 35%', 'blue');\n check('in srgb', '35% red', 'blue 16%');\n check('in srgb', '/*a*/ 35% /*b*/ red /*c*/', '/*a*/ blue /*b*/ 16% /*c*/');\n checkFailure('insrgb shorter hue', 'red 35%', 'blue');\n checkFailure('/*asd*/srgb in', 'red 35%', 'blue');\n checkFailure('in srgb', '0% red', 'blue 0%');\n });\n\n it('parses URLs', () => {\n const url = 'http://example.com';\n {\n const {match, text} =\n matchSingleValue('background-image', `url(${url})`, new Elements.PropertyMatchers.URLMatcher());\n assert.exists(match);\n assert.strictEqual(match.url, url, text);\n }\n {\n const {match, text} =\n matchSingleValue('background-image', `url(\"${url}\")`, new Elements.PropertyMatchers.URLMatcher());\n assert.exists(match);\n assert.strictEqual(match.url, url, text);\n }\n });\n\n it('parses angles correctly', () => {\n for (const succeed of ['45deg', '1.3rad', '-25grad', '2.3turn']) {\n const {ast, match, text} = matchSingleValue('transform', succeed, new Elements.PropertyMatchers.AngleMatcher());\n assert.exists(ast, succeed);\n assert.exists(match, text);\n assert.strictEqual(match.text, succeed);\n }\n for (const fail of ['0DEG', '0', '123', '2em']) {\n const {match, text} = matchSingleValue('transform', fail, new Elements.PropertyMatchers.AngleMatcher());\n assert.isNull(match, text);\n }\n });\n\n it('parses linkable names correctly', () => {\n function match(name: string, value: string) {\n const ast = SDK.CSSPropertyParser.tokenizeDeclaration(name, value);\n assert.exists(ast);\n const matchedResult = SDK.CSSPropertyParser.BottomUpTreeMatching.walk(ast, [\n new Elements.PropertyMatchers.LinkableNameMatcher(),\n ]);\n\n const matches = SDK.CSSPropertyParser.TreeSearch.findAll(\n ast, node => matchedResult.getMatch(node) instanceof Elements.PropertyMatchers.LinkableNameMatch);\n return matches.map(m => matchedResult.getMatch(m)?.text);\n }\n\n assert.deepStrictEqual(match('animation-name', 'first, second, -moz-third'), ['first', 'second', '-moz-third']);\n assert.deepStrictEqual(match('animation-name', 'first'), ['first']);\n assert.deepStrictEqual(match('font-palette', 'first'), ['first']);\n {\n assert.deepStrictEqual(match('position-try-fallbacks', 'flip-block'), []);\n assert.deepStrictEqual(match('position-try-fallbacks', '--one'), ['--one']);\n assert.deepStrictEqual(match('position-try-fallbacks', '--one, --two'), ['--one', '--two']);\n }\n {\n assert.deepStrictEqual(match('position-try', 'flip-block'), []);\n assert.deepStrictEqual(match('position-try', '--one'), ['--one']);\n assert.deepStrictEqual(match('position-try', '--one, --two'), ['--one', '--two']);\n }\n {\n injectVariableSubstitutions({\n '--duration-and-easing': '1s linear',\n });\n assert.deepStrictEqual(match('animation', '1s linear --animation-name'), ['--animation-name']);\n assert.deepStrictEqual(match('animation', '1s linear linear'), ['linear']);\n assert.deepStrictEqual(\n match('animation', '1s linear --first-name, 1s ease-in --second-name'), ['--first-name', '--second-name']);\n assert.deepStrictEqual(match('animation', '1s linear'), []);\n // Matching to variable names inside `var()` functions are fine as it is handled by variable renderer in usage.\n assert.deepStrictEqual(\n match('animation', 'var(--duration-and-easing) linear'), ['--duration-and-easing', 'linear']);\n assert.deepStrictEqual(\n match('animation', '1s linear var(--non-existent, --animation-name)'),\n ['--non-existent', '--animation-name']);\n }\n });\n\n it('parses easing functions properly', () => {\n for (const succeed\n of ['linear', 'ease', 'ease-in', 'ease-out', 'ease-in-out', 'linear(0 0%, 1 100%)',\n 'cubic-bezier(0.3, 0.3, 0.3, 0.3)']) {\n const {ast, match, text} =\n matchSingleValue('animation-timing-function', succeed, new Elements.PropertyMatchers.BezierMatcher());\n assert.exists(ast, succeed);\n assert.exists(match, text);\n assert.strictEqual(match.text, succeed);\n }\n\n const {ast, match, text} = matchSingleValue('border', 'ease-in', new Elements.PropertyMatchers.BezierMatcher());\n assert.exists(ast, 'border');\n assert.isNull(match, text);\n });\n\n it('parses strings correctly', () => {\n function match(name: string, value: string) {\n const ast = SDK.CSSPropertyParser.tokenizeDeclaration(name, value);\n assert.exists(ast);\n const matchedResult =\n SDK.CSSPropertyParser.BottomUpTreeMatching.walk(ast, [new Elements.PropertyMatchers.StringMatcher()]);\n assert.exists(matchedResult);\n\n const match = SDK.CSSPropertyParser.TreeSearch.find(\n ast, node => matchedResult.getMatch(node) instanceof Elements.PropertyMatchers.StringMatch);\n assert.exists(match);\n }\n match('quotes', '\"\\'\" \"\\'\"');\n match('content', '\"foobar\"');\n match('--image-file-accelerometer-back', 'url(\"devtools\\:\\/\\/devtools\\/bundled\\/Images\\/accelerometer-back\\.svg\")');\n });\n\n it('parses shadows correctly', () => {\n const {match, text} = matchSingleValue(\n 'box-shadow', '/*0*/3px 3px red, -1em 0 .4em /*a*/ olive /*b*/', new Elements.PropertyMatchers.ShadowMatcher());\n assert.exists(match, text);\n assert.strictEqual(match.text, '/*0*/3px 3px red, -1em 0 .4em /*a*/ olive');\n });\n\n it('parses fonts correctly', () => {\n for (const fontSize of ['-.23', 'smaller', '17px']) {\n const {ast, match, text} = matchSingleValue('font-size', fontSize, new Elements.PropertyMatchers.FontMatcher());\n\n assert.exists(ast, text);\n assert.exists(match, text);\n assert.strictEqual(match.text, fontSize);\n }\n\n {\n const ast = SDK.CSSPropertyParser.tokenizeDeclaration('font-family', '\"Gill Sans\", sans-serif');\n assert.exists(ast);\n const matchedResult =\n SDK.CSSPropertyParser.BottomUpTreeMatching.walk(ast, [new Elements.PropertyMatchers.FontMatcher()]);\n assert.exists(matchedResult);\n\n const matches = SDK.CSSPropertyParser.TreeSearch.findAll(\n ast, node => matchedResult.getMatch(node) instanceof Elements.PropertyMatchers.FontMatch);\n assert.deepStrictEqual(matches.map(m => matchedResult.getMatch(m)?.text), ['\"Gill Sans\"', 'sans-serif']);\n }\n });\n\n it('parses grid templates correctly', () => {\n injectVariableSubstitutions({\n '--row': '\"a a b\"',\n '--row-with-names': '[name1] \"a a\" [name2]',\n '--line-name': '[name1]',\n '--double-row': '\"a b\" \"b c\"',\n });\n\n {\n const {ast, match, text} = matchSingleValue('grid', '\"a a\"', new Elements.PropertyMatchers.GridTemplateMatcher());\n assert.exists(ast, text);\n assert.exists(match, text);\n assert.strictEqual(match.lines.map(line => line.map(n => ast.text(n)).join(' ')).join('\\n'), '\"a a\"');\n }\n {\n const {ast, match, text} = matchSingleValue(\n 'grid-template-areas', '\"a a a\" \"b b b\" \"c c c\"', new Elements.PropertyMatchers.GridTemplateMatcher());\n assert.exists(ast, text);\n assert.exists(match, text);\n assert.deepStrictEqual(\n match.lines.map(line => line.map(n => ast.text(n)).join(' ')), ['\"a a a\"', '\"b b b\"', '\"c c c\"']);\n }\n {\n const {ast, match, text} = matchSingleValue(\n 'grid-template', '\"a a a\" var(--row) / auto 1fr auto', new Elements.PropertyMatchers.GridTemplateMatcher());\n assert.exists(ast, text);\n assert.exists(match, text);\n assert.deepStrictEqual(\n match.lines.map(line => line.map(n => ast.text(n)).join(' ')), ['\"a a a\"', 'var(--row) / auto 1fr auto']);\n }\n {\n const {ast, match, text} = matchSingleValue(\n 'grid', '[header-top] \"a a\" var(--row-with-names) [main-top] \"b b b\" 1fr [main-bottom] / auto 1fr auto;',\n\n new Elements.PropertyMatchers.GridTemplateMatcher());\n assert.exists(ast, text);\n assert.exists(match, text);\n assert.deepStrictEqual(\n match.lines.map(line => line.map(n => ast.text(n)).join(' ')),\n ['[header-top] \"a a\" var(--row-with-names)', '[main-top] \"b b b\" 1fr [main-bottom] / auto 1fr auto']);\n }\n {\n const {ast, match, text} = matchSingleValue(\n 'grid', '[header-top] \"a a\" \"b b b\" var(--line-name) \"c c\" / auto 1fr auto;',\n\n new Elements.PropertyMatchers.GridTemplateMatcher());\n assert.exists(ast, text);\n assert.exists(match, text);\n assert.deepStrictEqual(\n match.lines.map(line => line.map(n => ast.text(n)).join(' ')),\n ['[header-top] \"a a\"', '\"b b b\" var(--line-name)', '\"c c\" / auto 1fr auto']);\n }\n {\n const {ast, match, text} = matchSingleValue(\n 'grid', '[line1] \"a a\" [line2] var(--double-row) \"b b\" / auto 1fr auto;',\n\n new Elements.PropertyMatchers.GridTemplateMatcher());\n assert.exists(ast, text);\n assert.exists(match, text);\n assert.deepStrictEqual(\n match.lines.map(line => line.map(n => ast.text(n)).join(' ')),\n ['[line1] \"a a\" [line2]', 'var(--double-row)', '\"b b\" / auto 1fr auto']);\n }\n {\n const {ast, match, text} = matchSingleValue(\n 'grid', '\"a a\" var(--unresolved) / auto 1fr auto;', new Elements.PropertyMatchers.GridTemplateMatcher());\n assert.exists(ast, text);\n assert.exists(match, text);\n assert.deepStrictEqual(\n match.lines.map(line => line.map(n => ast.text(n)).join(' ')), ['\"a a\" var(--unresolved) / auto 1fr auto']);\n }\n });\n\n it('parses light-dark correctly', () => {\n for (const fail of ['light-dark()', 'light-dark(red)', 'light-dark(var(--foo))']) {\n const {match, text} = matchSingleValue('color', fail, new Elements.PropertyMatchers.LightDarkColorMatcher());\n assert.isNull(match, text);\n }\n\n for (const succeed\n of ['light-dark(red, blue)', 'light-dark(var(--foo), red)', 'light-dark(red, var(--foo))',\n 'light-dark(var(--foo), var(--bar))']) {\n const {ast, match, text} =\n matchSingleValue('color', succeed, new Elements.PropertyMatchers.LightDarkColorMatcher());\n assert.exists(ast, text);\n assert.exists(match, text);\n\n const [light, dark] = succeed.slice('light-dark('.length, -1).split(', ');\n assert.lengthOf(match.light, 1);\n assert.lengthOf(match.dark, 1);\n assert.strictEqual(ast.text(match.light[0]), light);\n assert.strictEqual(ast.text(match.dark[0]), dark);\n }\n\n // light-dark only applies to color properties\n const {match, text} =\n matchSingleValue('width', 'light-dark(red, blue)', new Elements.PropertyMatchers.LightDarkColorMatcher());\n assert.isNull(match, text);\n });\n\n describe('AnchorFunctionMatcher', () => {\n it('should not match when it is not a call expression', () => {\n const {match, text} = matchSingleValue('left', 'anchor', new Elements.PropertyMatchers.AnchorFunctionMatcher());\n assert.isNull(match, text);\n });\n\n it('should not match anchor() call without arguments', () => {\n const {match: anchorMatch} =\n matchSingleValue('left', 'anchor()', new Elements.PropertyMatchers.AnchorFunctionMatcher());\n assert.isNull(anchorMatch);\n });\n\n it('should match anchor-size() call without arguments', () => {\n const {match: anchorSizeMatch, text: anchorSizeText} =\n matchSingleValue('width', 'anchor-size()', new Elements.PropertyMatchers.AnchorFunctionMatcher());\n assert.exists(anchorSizeMatch, anchorSizeText);\n });\n\n it('should match if it is an anchor() or anchor-size() call', () => {\n const {match: anchorMatch, text: anchorText} =\n matchSingleValue('left', 'anchor(left)', new Elements.PropertyMatchers.AnchorFunctionMatcher());\n assert.exists(anchorMatch, anchorText);\n\n const {match: anchorSizeMatch, text: anchorSizeText} =\n matchSingleValue('width', 'anchor-size(width)', new Elements.PropertyMatchers.AnchorFunctionMatcher());\n assert.exists(anchorSizeMatch, anchorSizeText);\n });\n\n it('should match dashed identifier as name from the first argument', () => {\n const {match: anchorMatch, text: anchorText} = matchSingleValue(\n 'left', 'anchor(--dashed-ident left)', new Elements.PropertyMatchers.AnchorFunctionMatcher());\n assert.exists(anchorMatch, anchorText);\n assert.strictEqual(anchorMatch.text, '--dashed-ident');\n\n const {match: anchorSizeMatch, text: anchorSizeText} = matchSingleValue(\n 'width', 'anchor-size(--dashed-ident width)', new Elements.PropertyMatchers.AnchorFunctionMatcher());\n assert.exists(anchorSizeMatch, anchorSizeText);\n assert.strictEqual(anchorSizeMatch.text, '--dashed-ident');\n });\n\n it('should match dashed identifier as name from the second argument', () => {\n const {match: anchorMatch, text: anchorText} = matchSingleValue(\n 'left', 'anchor(right --dashed-ident)', new Elements.PropertyMatchers.AnchorFunctionMatcher());\n assert.exists(anchorMatch, anchorText);\n assert.strictEqual(anchorMatch.text, '--dashed-ident');\n\n const {match: anchorSizeMatch, text: anchorSizeText} = matchSingleValue(\n 'width', 'anchor-size(height --dashed-ident)', new Elements.PropertyMatchers.AnchorFunctionMatcher());\n assert.exists(anchorSizeMatch, anchorSizeText);\n assert.strictEqual(anchorSizeMatch.text, '--dashed-ident');\n });\n });\n\n describe('PositionAnchorMatcher', () => {\n it('should match `position-anchor` property with dashed identifier', () => {\n const {match, text} =\n matchSingleValue('position-anchor', '--dashed-ident', new Elements.PropertyMatchers.PositionAnchorMatcher());\n assert.exists(match, text);\n assert.strictEqual(match.text, '--dashed-ident');\n });\n\n it('should not match `position-anchor` property when it is not a dashed identifier', () => {\n const {match} = matchSingleValue(\n 'position-anchor', 'something-non-dashed', new Elements.PropertyMatchers.PositionAnchorMatcher());\n assert.isNull(match);\n });\n });\n\n it('matches lengths', () => {\n const {match, text} = matchSingleValue('min-width', '100px', new Elements.PropertyMatchers.LengthMatcher());\n assert.exists(match, text);\n assert.strictEqual(match.text, '100px');\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/elements/StylePropertyTreeElement.js b/public/panels/elements/StylePropertyTreeElement.js index 3dff94acd..f9e021a61 100644 --- a/public/panels/elements/StylePropertyTreeElement.js +++ b/public/panels/elements/StylePropertyTreeElement.js @@ -213,12 +213,12 @@ export class ColorRenderer { this.treeElement = treeElement; } matcher() { - return new ColorMatcher(); + const getCurrentColorCallback = () => this.treeElement.getComputedStyle('color'); + return new ColorMatcher(getCurrentColorCallback); } #getValueChild(match, context) { const valueChild = document.createElement('span'); - if (match.node.name === 'ColorLiteral' || - (match.node.name === 'ValueName' && Common.Color.Nicknames.has(match.text))) { + if (match.node.name === 'ColorLiteral' || match.node.name === 'ValueName') { valueChild.appendChild(document.createTextNode(match.text)); return { valueChild }; } @@ -921,32 +921,32 @@ export class AnchorFunctionRenderer { } anchorDecoratedForTest() { } - async #decorateAnchor(container, identifier) { + async #decorateAnchor(container, addSpace, identifier) { await decorateAnchorForAnchorLink(container, this.#treeElement, { identifier, - needsSpace: true, + needsSpace: addSpace, }); this.anchorDecoratedForTest(); } render(match, context) { const content = document.createElement('span'); - content.appendChild(document.createTextNode(`${match.functionName}(`)); - const firstArgText = match.matching.ast.text(match.args[0]); - const hasDashedIdentifier = firstArgText.startsWith('--'); - const linkContainer = document.createElement('span'); - if (hasDashedIdentifier) { - linkContainer.textContent = `${firstArgText} `; - } - content.appendChild(linkContainer); - const remainingArgsContainer = content.appendChild(document.createElement('span')); - if (hasDashedIdentifier) { - Renderer.renderInto(match.args.slice(1), context, remainingArgsContainer); + if (match.node.name === 'VariableName') { + // Link an anchor double-dashed ident to its matching anchor element. + content.appendChild(document.createTextNode(match.text)); + void this.#decorateAnchor(content, /* addSpace */ false, match.text); } else { - Renderer.renderInto(match.args, context, remainingArgsContainer); + // The matcher passes a 'CallExpression' node with a functionName + // ('anchor' or 'anchor-size') if the arguments need to have an implicit + // anchor link swatch rendered. + content.appendChild(document.createTextNode(`${match.functionName}(`)); + const swatchContainer = document.createElement('span'); + content.appendChild(swatchContainer); + const args = ASTUtils.children(match.node.getChild('ArgList')); + const remainingArgs = args.splice(1); + void this.#decorateAnchor(swatchContainer, /* addSpace */ remainingArgs.length > 1); + Renderer.renderInto(remainingArgs, context, content); } - void this.#decorateAnchor(linkContainer, hasDashedIdentifier ? firstArgText : undefined); - content.appendChild(document.createTextNode(')')); return [content]; } matcher() { diff --git a/public/panels/elements/StylePropertyTreeElement.js.map b/public/panels/elements/StylePropertyTreeElement.js.map index 5bba2a2f9..6b9ad8247 100644 --- a/public/panels/elements/StylePropertyTreeElement.js.map +++ b/public/panels/elements/StylePropertyTreeElement.js.map @@ -1 +1 @@ -{"version":3,"file":"StylePropertyTreeElement.js","sourceRoot":"","sources":["../../../../../../front_end/panels/elements/StylePropertyTreeElement.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as Host from '../../core/host/host.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as Root from '../../core/root/root.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as Bindings from '../../models/bindings/bindings.js';\nimport * as TextUtils from '../../models/text_utils/text_utils.js';\nimport type * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';\nimport * as IconButton from '../../ui/components/icon_button/icon_button.js';\nimport * as ColorPicker from '../../ui/legacy/components/color_picker/color_picker.js';\nimport * as InlineEditor from '../../ui/legacy/components/inline_editor/inline_editor.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport {\n BezierPopoverIcon,\n ColorSwatchPopoverIcon,\n ColorSwatchPopoverIconEvents,\n ShadowEvents,\n ShadowSwatchPopoverHelper,\n} from './ColorSwatchPopoverIcon.js';\nimport * as ElementsComponents from './components/components.js';\nimport {cssRuleValidatorsMap, type Hint} from './CSSRuleValidator.js';\nimport {ElementsPanel} from './ElementsPanel.js';\nimport {\n type AnchorFunctionMatch,\n AnchorFunctionMatcher,\n AngleMatch,\n AngleMatcher,\n type BezierMatch,\n BezierMatcher,\n ColorMatch,\n ColorMatcher,\n ColorMixMatch,\n ColorMixMatcher,\n type FontMatch,\n FontMatcher,\n type GridTemplateMatch,\n GridTemplateMatcher,\n type LengthMatch,\n LengthMatcher,\n type LightDarkColorMatch,\n LightDarkColorMatcher,\n type LinearGradientMatch,\n LinearGradientMatcher,\n type LinkableNameMatch,\n LinkableNameMatcher,\n LinkableNameProperties,\n type PositionAnchorMatch,\n PositionAnchorMatcher,\n type ShadowMatch,\n ShadowMatcher,\n ShadowType,\n} from './PropertyMatchers.js';\nimport {type MatchRenderer, Renderer, RenderingContext, StringRenderer, URLRenderer} from './PropertyRenderer.js';\nimport {StyleEditorWidget} from './StyleEditorWidget.js';\nimport {type StylePropertiesSection} from './StylePropertiesSection.js';\nimport {getCssDeclarationAsJavascriptProperty} from './StylePropertyUtils.js';\nimport {\n CSSPropertyPrompt,\n REGISTERED_PROPERTY_SECTION_NAME,\n StylesSidebarPane,\n} from './StylesSidebarPane.js';\n\nconst ASTUtils = SDK.CSSPropertyParser.ASTUtils;\nconst FlexboxEditor = ElementsComponents.StylePropertyEditor.FlexboxEditor;\nconst GridEditor = ElementsComponents.StylePropertyEditor.GridEditor;\n\nexport const activeHints = new WeakMap();\n\nconst UIStrings = {\n /**\n *@description Text in Color Swatch Popover Icon of the Elements panel\n */\n shiftClickToChangeColorFormat: 'Shift + Click to change color format.',\n /**\n *@description Swatch icon element title in Color Swatch Popover Icon of the Elements panel\n *@example {Shift + Click to change color format.} PH1\n */\n openColorPickerS: 'Open color picker. {PH1}',\n /**\n *@description Context menu item for style property in edit mode\n */\n togglePropertyAndContinueEditing: 'Toggle property and continue editing',\n /**\n *@description Context menu item for style property in edit mode\n */\n revealInSourcesPanel: 'Reveal in Sources panel',\n /**\n *@description A context menu item in Styles panel to copy CSS declaration\n */\n copyDeclaration: 'Copy declaration',\n /**\n *@description A context menu item in Styles panel to copy CSS property\n */\n copyProperty: 'Copy property',\n /**\n *@description A context menu item in the Watch Expressions Sidebar Pane of the Sources panel and Network pane request.\n */\n copyValue: 'Copy value',\n /**\n *@description A context menu item in Styles panel to copy CSS rule\n */\n copyRule: 'Copy rule',\n /**\n *@description A context menu item in Styles panel to copy all CSS declarations\n */\n copyAllDeclarations: 'Copy all declarations',\n /**\n *@description A context menu item in Styles panel to copy all the CSS changes\n */\n copyAllCSSChanges: 'Copy all CSS changes',\n /**\n *@description A context menu item in Styles panel to view the computed CSS property value.\n */\n viewComputedValue: 'View computed value',\n /**\n * @description Title of the button that opens the flexbox editor in the Styles panel.\n */\n flexboxEditorButton: 'Open `flexbox` editor',\n /**\n * @description Title of the button that opens the CSS Grid editor in the Styles panel.\n */\n gridEditorButton: 'Open `grid` editor',\n /**\n *@description A context menu item in Styles panel to copy CSS declaration as JavaScript property.\n */\n copyCssDeclarationAsJs: 'Copy declaration as JS',\n /**\n *@description A context menu item in Styles panel to copy all declarations of CSS rule as JavaScript properties.\n */\n copyAllCssDeclarationsAsJs: 'Copy all declarations as JS',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/elements/StylePropertyTreeElement.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nconst parentMap = new WeakMap();\n\ninterface StylePropertyTreeElementParams {\n stylesPane: StylesSidebarPane;\n section: StylePropertiesSection;\n matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles;\n property: SDK.CSSProperty.CSSProperty;\n isShorthand: boolean;\n inherited: boolean;\n overloaded: boolean;\n newProperty: boolean;\n}\n\nexport class VariableRenderer implements MatchRenderer {\n readonly #treeElement: StylePropertyTreeElement;\n readonly #style: SDK.CSSStyleDeclaration.CSSStyleDeclaration;\n constructor(treeElement: StylePropertyTreeElement, style: SDK.CSSStyleDeclaration.CSSStyleDeclaration) {\n this.#treeElement = treeElement;\n this.#style = style;\n }\n\n matcher(): SDK.CSSPropertyParser.VariableMatcher {\n return new SDK.CSSPropertyParser.VariableMatcher(this.computedText.bind(this));\n }\n\n resolveVariable(match: SDK.CSSPropertyParser.VariableMatch): SDK.CSSMatchedStyles.CSSVariableValue|null {\n return this.#matchedStyles.computeCSSVariable(this.#style, match.name);\n }\n\n fallbackValue(match: SDK.CSSPropertyParser.VariableMatch): string|null {\n if (match.fallback.length === 0 ||\n match.matching.hasUnresolvedVarsRange(match.fallback[0], match.fallback[match.fallback.length - 1])) {\n return null;\n }\n return match.matching.getComputedTextRange(match.fallback[0], match.fallback[match.fallback.length - 1]);\n }\n\n // clang-format off\n computedText(match: SDK.CSSPropertyParser.VariableMatch): string|null {\n return this.resolveVariable(match)?.value ?? this.fallbackValue(match);\n }\n // clang-format on\n\n render(match: SDK.CSSPropertyParser.VariableMatch, context: RenderingContext): Node[] {\n const renderedFallback = match.fallback.length > 0 ? Renderer.render(match.fallback, context) : undefined;\n\n const {declaration, value: variableValue} = this.resolveVariable(match) ?? {};\n const fromFallback = !variableValue;\n const computedValue = variableValue ?? this.fallbackValue(match);\n\n const varSwatch = new InlineEditor.LinkSwatch.CSSVarSwatch();\n varSwatch.data = {\n computedValue,\n variableName: match.name,\n fromFallback,\n fallbackText: match.fallback.map(n => context.ast.text(n)).join(' '),\n onLinkActivate: name => this.#handleVarDefinitionActivate(declaration ?? name),\n };\n\n if (renderedFallback?.nodes.length) {\n // When slotting someting into the fallback slot, also emit text children so that .textContent produces the\n // correct var value.\n varSwatch.appendChild(document.createTextNode(`var(${match.name}`));\n const span = varSwatch.appendChild(document.createElement('span'));\n span.appendChild(document.createTextNode(', '));\n span.slot = 'fallback';\n renderedFallback.nodes.forEach(n => span.appendChild(n));\n varSwatch.appendChild(document.createTextNode(')'));\n } else {\n UI.UIUtils.createTextChild(varSwatch, match.text);\n }\n\n if (varSwatch.link) {\n this.#pane.addPopover(varSwatch.link, {\n contents: () => this.#treeElement.getVariablePopoverContents(match.name, variableValue ?? null),\n jslogContext: 'elements.css-var',\n });\n }\n\n const color = computedValue && Common.Color.parse(computedValue);\n if (!color) {\n return [varSwatch];\n }\n\n const colorSwatch = new ColorRenderer(this.#treeElement).renderColorSwatch(color, varSwatch);\n context.addControl('color', colorSwatch);\n\n if (fromFallback) {\n renderedFallback?.cssControls.get('color')?.forEach(\n innerSwatch => innerSwatch.addEventListener(InlineEditor.ColorSwatch.ColorChangedEvent.eventName, ev => {\n colorSwatch.setColor(ev.data.color);\n }));\n }\n\n return [colorSwatch];\n }\n\n get #pane(): StylesSidebarPane {\n return this.#treeElement.parentPane();\n }\n\n get #matchedStyles(): SDK.CSSMatchedStyles.CSSMatchedStyles {\n return this.#treeElement.matchedStyles();\n }\n\n #handleVarDefinitionActivate(variable: string|SDK.CSSProperty.CSSProperty|\n SDK.CSSMatchedStyles.CSSRegisteredProperty): void {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.CustomPropertyLinkClicked);\n Host.userMetrics.swatchActivated(Host.UserMetrics.SwatchType.VAR_LINK);\n if (variable instanceof SDK.CSSProperty.CSSProperty) {\n this.#pane.revealProperty(variable);\n } else if (variable instanceof SDK.CSSMatchedStyles.CSSRegisteredProperty) {\n this.#pane.jumpToProperty('initial-value', variable.propertyName(), REGISTERED_PROPERTY_SECTION_NAME);\n } else {\n this.#pane.jumpToProperty(variable) ||\n this.#pane.jumpToProperty('initial-value', variable, REGISTERED_PROPERTY_SECTION_NAME);\n }\n }\n}\n\nexport class LinearGradientRenderer implements MatchRenderer {\n matcher(): SDK.CSSPropertyParser.Matcher {\n return new LinearGradientMatcher();\n }\n render(match: LinearGradientMatch, context: RenderingContext): Node[] {\n const children = ASTUtils.children(match.node);\n const {nodes, cssControls} = Renderer.render(children, context);\n const angles = cssControls.get('angle');\n const angle = angles?.length === 1 ? angles[0] : null;\n\n if (angle instanceof InlineEditor.CSSAngle.CSSAngle) {\n angle.updateProperty(context.matchedResult.getComputedText(match.node));\n const args = ASTUtils.callArgs(match.node);\n const angleNode = args[0]?.find(node => context.matchedResult.getMatch(node) instanceof AngleMatch);\n const angleMatch = angleNode && context.matchedResult.getMatch(angleNode);\n if (angleMatch) {\n angle.addEventListener(InlineEditor.InlineEditorUtils.ValueChangedEvent.eventName, ev => {\n angle.updateProperty(\n context.matchedResult.getComputedText(match.node, new Map([[angleMatch, ev.data.value]])));\n });\n }\n }\n return nodes;\n }\n}\n\nexport class ColorRenderer implements MatchRenderer {\n constructor(private readonly treeElement: StylePropertyTreeElement) {\n }\n\n matcher(): ColorMatcher {\n return new ColorMatcher();\n }\n\n #getValueChild(match: ColorMatch, context: RenderingContext):\n {valueChild: HTMLSpanElement, cssControls?: SDK.CSSPropertyParser.CSSControlMap} {\n const valueChild = document.createElement('span');\n if (match.node.name === 'ColorLiteral' ||\n (match.node.name === 'ValueName' && Common.Color.Nicknames.has(match.text))) {\n valueChild.appendChild(document.createTextNode(match.text));\n return {valueChild};\n }\n const {cssControls} = Renderer.renderInto(ASTUtils.children(match.node), context, valueChild);\n return {valueChild, cssControls};\n }\n\n render(match: ColorMatch, context: RenderingContext): Node[] {\n const {valueChild, cssControls} = this.#getValueChild(match, context);\n let colorText = context.matchedResult.getComputedText(match.node);\n // Evaluate relative color values\n if (match.node.name === 'CallExpression' && colorText.match(/^[^)]*\\(\\W*from\\W+/) &&\n !context.matchedResult.hasUnresolvedVars(match.node) && CSS.supports('color', colorText)) {\n const fakeSpan = document.body.appendChild(document.createElement('span'));\n fakeSpan.style.backgroundColor = colorText;\n colorText = window.getComputedStyle(fakeSpan).backgroundColor?.toString() || colorText;\n fakeSpan.remove();\n }\n\n // Now try render a color swatch if the result is parsable.\n const color = Common.Color.parse(colorText);\n if (!color) {\n return [document.createTextNode(colorText)];\n }\n const swatch = this.renderColorSwatch(color, valueChild);\n context.addControl('color', swatch);\n\n // For hsl/hwb colors, hook up the angle swatch for the hue.\n if (cssControls && match.node.name === 'CallExpression' &&\n context.ast.text(match.node.getChild('Callee')).match(/^(hsla?|hwba?)/)) {\n const [angle] = cssControls.get('angle') ?? [];\n if (angle instanceof InlineEditor.CSSAngle.CSSAngle) {\n angle.updateProperty(swatch.getColor()?.asString() ?? '');\n angle.addEventListener(InlineEditor.InlineEditorUtils.ValueChangedEvent.eventName, ev => {\n const hue = Common.Color.parseHueNumeric(ev.data.value);\n const color = swatch.getColor();\n if (!hue || !color) {\n return;\n }\n if (color.is(Common.Color.Format.HSL) || color.is(Common.Color.Format.HSLA)) {\n swatch.setColor(new Common.Color.HSL(hue, color.s, color.l, color.alpha));\n } else if (color.is(Common.Color.Format.HWB) || color.is(Common.Color.Format.HWBA)) {\n swatch.setColor(new Common.Color.HWB(hue, color.w, color.b, color.alpha));\n }\n angle.updateProperty(swatch.getColor()?.asString() ?? '');\n });\n }\n }\n return [swatch];\n }\n\n renderColorSwatch(color: Common.Color.Color|undefined, valueChild?: Node): InlineEditor.ColorSwatch.ColorSwatch {\n const editable = this.treeElement.editable();\n const shiftClickMessage = i18nString(UIStrings.shiftClickToChangeColorFormat);\n const tooltip = editable ? i18nString(UIStrings.openColorPickerS, {PH1: shiftClickMessage}) : '';\n\n const swatch = new InlineEditor.ColorSwatch.ColorSwatch(tooltip);\n swatch.setReadonly(!editable);\n if (color) {\n swatch.renderColor(color);\n }\n\n if (!valueChild) {\n valueChild = swatch.createChild('span');\n if (color) {\n valueChild.textContent = color.getAuthoredText() ?? color.asString();\n }\n }\n swatch.appendChild(valueChild);\n\n const onColorChanged = (): void => {\n void this.treeElement.applyStyleText(this.treeElement.renderedPropertyText(), false);\n };\n\n swatch.addEventListener(InlineEditor.ColorSwatch.ClickEvent.eventName, () => {\n Host.userMetrics.swatchActivated(Host.UserMetrics.SwatchType.COLOR);\n });\n swatch.addEventListener(InlineEditor.ColorSwatch.ColorChangedEvent.eventName, onColorChanged);\n\n if (editable) {\n const swatchIcon =\n new ColorSwatchPopoverIcon(this.treeElement, this.treeElement.parentPane().swatchPopoverHelper(), swatch);\n swatchIcon.addEventListener(ColorSwatchPopoverIconEvents.COLOR_CHANGED, ev => {\n const color = Common.Color.parse(ev.data);\n if (color) {\n swatch.setColorText(color);\n }\n });\n void this.#addColorContrastInfo(swatchIcon);\n }\n\n return swatch;\n }\n\n async #addColorContrastInfo(swatchIcon: ColorSwatchPopoverIcon): Promise {\n const cssModel = this.treeElement.parentPane().cssModel();\n const node = this.treeElement.node();\n if (this.treeElement.property.name !== 'color' || !cssModel || !node || typeof node.id === 'undefined') {\n return;\n }\n const contrastInfo = new ColorPicker.ContrastInfo.ContrastInfo(await cssModel.getBackgroundColors(node.id));\n swatchIcon.setContrastInfo(contrastInfo);\n }\n}\n\nexport class LightDarkColorRenderer implements MatchRenderer {\n readonly #treeElement: StylePropertyTreeElement;\n constructor(treeElement: StylePropertyTreeElement) {\n this.#treeElement = treeElement;\n }\n\n matcher(): LightDarkColorMatcher {\n return new LightDarkColorMatcher();\n }\n\n render(match: LightDarkColorMatch, context: RenderingContext): Node[] {\n const content = document.createElement('span');\n content.appendChild(document.createTextNode('light-dark('));\n const light = content.appendChild(document.createElement('span'));\n content.appendChild(document.createTextNode(', '));\n const dark = content.appendChild(document.createElement('span'));\n content.appendChild(document.createTextNode(')'));\n const {cssControls: lightControls} = Renderer.renderInto(match.light, context, light);\n const {cssControls: darkControls} = Renderer.renderInto(match.dark, context, dark);\n\n if (context.matchedResult.hasUnresolvedVars(match.node)) {\n return [content];\n }\n\n const color = Common.Color.parse(\n context.matchedResult.getComputedTextRange(match.light[0], match.light[match.light.length - 1]));\n if (!color) {\n return [content];\n }\n\n // Pass an undefined color here to insert a placeholder swatch that will be filled in from the async\n // applyColorScheme below.\n const colorSwatch = new ColorRenderer(this.#treeElement).renderColorSwatch(undefined, content);\n context.addControl('color', colorSwatch);\n void this.applyColorScheme(match, context, colorSwatch, light, dark, lightControls, darkControls);\n\n return [colorSwatch];\n }\n\n async applyColorScheme(\n match: LightDarkColorMatch, context: RenderingContext, colorSwatch: InlineEditor.ColorSwatch.ColorSwatch,\n light: HTMLSpanElement, dark: HTMLSpanElement, lightControls: SDK.CSSPropertyParser.CSSControlMap,\n darkControls: SDK.CSSPropertyParser.CSSControlMap): Promise {\n const activeColor = await this.#activeColor(match);\n if (!activeColor) {\n return;\n }\n\n const activeColorSwatches = (activeColor === match.light ? lightControls : darkControls).get('color');\n activeColorSwatches?.forEach(\n swatch => swatch.addEventListener(\n InlineEditor.ColorSwatch.ColorChangedEvent.eventName, ev => colorSwatch.setColor(ev.data.color)));\n const inactiveColor = (activeColor === match.light) ? dark : light;\n const colorText = context.matchedResult.getComputedTextRange(activeColor[0], activeColor[activeColor.length - 1]);\n const color = colorText && Common.Color.parse(colorText);\n inactiveColor.style.textDecoration = 'line-through';\n if (color) {\n colorSwatch.renderColor(color);\n }\n }\n\n // Returns the syntax node group corresponding the active color scheme:\n // If the element has color-scheme set to light or dark, return the respective group.\n // If the element has color-scheme set to both light and dark, we check the prefers-color-scheme media query.\n async #activeColor(match: LightDarkColorMatch): Promise {\n const activeColorSchemes = this.#treeElement.getComputedStyle('color-scheme')?.split(' ') ?? [];\n const hasLight = activeColorSchemes.includes(SDK.CSSModel.ColorScheme.LIGHT);\n const hasDark = activeColorSchemes.includes(SDK.CSSModel.ColorScheme.DARK);\n\n if (!hasDark && !hasLight) {\n return match.light;\n }\n if (!hasLight) {\n return match.dark;\n }\n if (!hasDark) {\n return match.light;\n }\n\n switch (await this.#treeElement.parentPane().cssModel()?.colorScheme()) {\n case SDK.CSSModel.ColorScheme.DARK:\n return match.dark;\n case SDK.CSSModel.ColorScheme.LIGHT:\n return match.light;\n default:\n return undefined;\n }\n }\n}\n\nexport class ColorMixRenderer implements MatchRenderer {\n #pane: StylesSidebarPane;\n constructor(pane: StylesSidebarPane) {\n this.#pane = pane;\n }\n\n render(match: ColorMixMatch, context: RenderingContext): Node[] {\n const hookUpColorArg = (node: Node, onChange: (newColorText: string) => void): boolean => {\n if (node instanceof InlineEditor.ColorMixSwatch.ColorMixSwatch ||\n node instanceof InlineEditor.ColorSwatch.ColorSwatch) {\n if (node instanceof InlineEditor.ColorSwatch.ColorSwatch) {\n node.addEventListener(\n InlineEditor.ColorSwatch.ColorChangedEvent.eventName,\n ev => onChange(ev.data.color.getAuthoredText() ?? ev.data.color.asString()));\n } else {\n node.addEventListener(InlineEditor.ColorMixSwatch.Events.COLOR_CHANGED, ev => onChange(ev.data.text));\n }\n const color = node.getText();\n if (color) {\n onChange(color);\n return true;\n }\n }\n return false;\n };\n\n const contentChild = document.createElement('span');\n contentChild.appendChild(document.createTextNode('color-mix('));\n Renderer.renderInto(match.space, context, contentChild);\n contentChild.appendChild(document.createTextNode(', '));\n const color1 = Renderer.renderInto(match.color1, context, contentChild).cssControls.get('color') ?? [];\n contentChild.appendChild(document.createTextNode(', '));\n const color2 = Renderer.renderInto(match.color2, context, contentChild).cssControls.get('color') ?? [];\n contentChild.appendChild(document.createTextNode(')'));\n\n if (context.matchedResult.hasUnresolvedVars(match.node) || color1.length !== 1 || color2.length !== 1) {\n return [contentChild];\n }\n\n const swatch = new InlineEditor.ColorMixSwatch.ColorMixSwatch();\n if (!hookUpColorArg(color1[0], text => swatch.setFirstColor(text)) ||\n !hookUpColorArg(color2[0], text => swatch.setSecondColor(text))) {\n return [contentChild];\n }\n\n const space = match.space.map(space => context.matchedResult.getComputedText(space)).join(' ');\n const color1Text = match.color1.map(color => context.matchedResult.getComputedText(color)).join(' ');\n const color2Text = match.color2.map(color => context.matchedResult.getComputedText(color)).join(' ');\n swatch.appendChild(contentChild);\n swatch.setColorMixText(`color-mix(${space}, ${color1Text}, ${color2Text})`);\n swatch.setRegisterPopoverCallback(swatch => {\n if (swatch.icon) {\n this.#pane.addPopover(swatch.icon, {\n contents: () => {\n const color = swatch.mixedColor();\n if (!color) {\n return undefined;\n }\n const span = document.createElement('span');\n span.style.padding = '11px 7px';\n const rgb = color.as(Common.Color.Format.HEX);\n const text = rgb.isGamutClipped() ? color.asString() : rgb.asString();\n if (!text) {\n return undefined;\n }\n span.appendChild(document.createTextNode(text));\n return span;\n },\n jslogContext: 'elements.css-color-mix',\n });\n }\n });\n\n context.addControl('color', swatch);\n return [swatch];\n }\n\n matcher(): ColorMixMatcher {\n return new ColorMixMatcher();\n }\n}\n\nexport class AngleRenderer implements MatchRenderer {\n #treeElement: StylePropertyTreeElement;\n constructor(treeElement: StylePropertyTreeElement) {\n this.#treeElement = treeElement;\n }\n\n render(match: AngleMatch, context: RenderingContext): Node[] {\n const angleText = match.text;\n if (!this.#treeElement.editable()) {\n return [document.createTextNode(angleText)];\n }\n const cssAngle = new InlineEditor.CSSAngle.CSSAngle();\n cssAngle.setAttribute('jslog', `${VisualLogging.showStyleEditor().track({click: true}).context('css-angle')}`);\n const valueElement = document.createElement('span');\n valueElement.textContent = angleText;\n cssAngle.data = {\n angleText,\n containingPane:\n (this.#treeElement.parentPane().element.enclosingNodeOrSelfWithClass('style-panes-wrapper') as HTMLElement),\n };\n cssAngle.append(valueElement);\n\n cssAngle.addEventListener('popovertoggled', ({data}) => {\n const section = this.#treeElement.section();\n if (!section) {\n return;\n }\n\n if (data.open) {\n this.#treeElement.parentPane().hideAllPopovers();\n this.#treeElement.parentPane().activeCSSAngle = cssAngle;\n Host.userMetrics.swatchActivated(Host.UserMetrics.SwatchType.ANGLE);\n }\n\n section.element.classList.toggle('has-open-popover', data.open);\n this.#treeElement.parentPane().setEditingStyle(data.open);\n\n // Commit the value as a major change after the angle popover is closed.\n if (!data.open) {\n void this.#treeElement.applyStyleText(this.#treeElement.renderedPropertyText(), true);\n }\n });\n cssAngle.addEventListener('valuechanged', async ({data}) => {\n valueElement.textContent = data.value;\n await this.#treeElement.applyStyleText(this.#treeElement.renderedPropertyText(), false);\n });\n cssAngle.addEventListener('unitchanged', ({data}) => {\n valueElement.textContent = data.value;\n });\n\n context.addControl('angle', cssAngle);\n return [cssAngle];\n }\n\n matcher(): AngleMatcher {\n return new AngleMatcher();\n }\n}\n\nexport class LinkableNameRenderer implements MatchRenderer {\n readonly #treeElement: StylePropertyTreeElement;\n constructor(treeElement: StylePropertyTreeElement) {\n this.#treeElement = treeElement;\n }\n\n #getLinkData(match: LinkableNameMatch):\n {jslogContext: string, metric: null|Host.UserMetrics.SwatchType, ruleBlock: string, isDefined: boolean} {\n switch (match.properyName) {\n case LinkableNameProperties.ANIMATION:\n case LinkableNameProperties.ANIMATION_NAME:\n return {\n jslogContext: 'css-animation-name',\n metric: Host.UserMetrics.SwatchType.ANIMATION_NAME_LINK,\n ruleBlock: '@keyframes',\n isDefined: Boolean(this.#treeElement.matchedStyles().keyframes().find(kf => kf.name().text === match.text)),\n };\n case LinkableNameProperties.FONT_PALETTE:\n return {\n jslogContext: 'css-font-palette',\n metric: null,\n ruleBlock: '@font-palette-values',\n isDefined: this.#treeElement.matchedStyles().fontPaletteValuesRule()?.name().text === match.text,\n };\n case LinkableNameProperties.POSITION_TRY:\n case LinkableNameProperties.POSITION_TRY_FALLBACKS:\n return {\n jslogContext: 'css-position-try',\n metric: Host.UserMetrics.SwatchType.POSITION_TRY_LINK,\n ruleBlock: '@position-try',\n isDefined:\n Boolean(this.#treeElement.matchedStyles().positionTryRules().find(pt => pt.name().text === match.text)),\n };\n }\n }\n\n render(match: LinkableNameMatch): Node[] {\n const swatch = new InlineEditor.LinkSwatch.LinkSwatch();\n UI.UIUtils.createTextChild(swatch, match.text);\n const {metric, jslogContext, ruleBlock, isDefined} = this.#getLinkData(match);\n swatch.data = {\n text: match.text,\n isDefined,\n onLinkActivate: (): void => {\n metric && Host.userMetrics.swatchActivated(metric);\n this.#treeElement.parentPane().jumpToSectionBlock(`${ruleBlock} ${match.text}`);\n },\n jslogContext,\n };\n\n return [swatch];\n }\n\n matcher(): LinkableNameMatcher {\n return new LinkableNameMatcher();\n }\n}\n\nexport class BezierRenderer implements MatchRenderer {\n readonly #treeElement: StylePropertyTreeElement;\n constructor(treeElement: StylePropertyTreeElement) {\n this.#treeElement = treeElement;\n }\n\n render(match: BezierMatch): Node[] {\n return [this.renderSwatch(match)];\n }\n\n renderSwatch(match: BezierMatch): Node {\n if (!this.#treeElement.editable()) {\n return document.createTextNode(match.text);\n }\n const swatchPopoverHelper = this.#treeElement.parentPane().swatchPopoverHelper();\n const swatch = InlineEditor.Swatches.BezierSwatch.create();\n swatch.iconElement().addEventListener('click', () => {\n Host.userMetrics.swatchActivated(Host.UserMetrics.SwatchType.ANIMATION_TIMING);\n });\n swatch.setBezierText(match.text);\n new BezierPopoverIcon({treeElement: this.#treeElement, swatchPopoverHelper, swatch});\n return swatch;\n }\n\n matcher(): BezierMatcher {\n return new BezierMatcher();\n }\n}\n\nexport const enum ShadowPropertyType {\n X = 'x',\n Y = 'y',\n SPREAD = 'spread',\n BLUR = 'blur',\n INSET = 'inset',\n COLOR = 'color',\n}\n\ntype ShadowProperty = {\n value: string|CodeMirror.SyntaxNode,\n source: CodeMirror.SyntaxNode|null,\n expansionContext: RenderingContext|null,\n propertyType: ShadowPropertyType,\n};\n\ntype ShadowLengthProperty = ShadowProperty&{\n length: InlineEditor.CSSShadowEditor.CSSLength,\n propertyType: Exclude,\n};\n\n// The shadow model is an abstraction over the various shadow properties on the one hand and the order they were defined\n// in on the other, so that modifications through the shadow editor can retain the property order in the authored text.\n// The model also looks through var()s by keeping a mapping between individual properties and any var()s they are coming\n// from, replacing the var() functions as needed with concrete values when edited.\nexport class ShadowModel implements InlineEditor.CSSShadowEditor.CSSShadowModel {\n readonly #properties: ShadowProperty[];\n readonly #shadowType: ShadowType;\n readonly #context: RenderingContext;\n\n constructor(shadowType: ShadowType, properties: ShadowProperty[], context: RenderingContext) {\n this.#shadowType = shadowType;\n this.#properties = properties;\n this.#context = context;\n }\n isBoxShadow(): boolean {\n return this.#shadowType === ShadowType.BOX_SHADOW;\n }\n inset(): boolean {\n return Boolean(this.#properties.find(property => property.propertyType === ShadowPropertyType.INSET));\n }\n #length(lengthType: ShadowLengthProperty['propertyType']): InlineEditor.CSSShadowEditor.CSSLength {\n return this.#properties.find((property): property is ShadowLengthProperty => property.propertyType === lengthType)\n ?.length ??\n InlineEditor.CSSShadowEditor.CSSLength.zero();\n }\n offsetX(): InlineEditor.CSSShadowEditor.CSSLength {\n return this.#length(ShadowPropertyType.X);\n }\n offsetY(): InlineEditor.CSSShadowEditor.CSSLength {\n return this.#length(ShadowPropertyType.Y);\n }\n blurRadius(): InlineEditor.CSSShadowEditor.CSSLength {\n return this.#length(ShadowPropertyType.BLUR);\n }\n spreadRadius(): InlineEditor.CSSShadowEditor.CSSLength {\n return this.#length(ShadowPropertyType.SPREAD);\n }\n\n #needsExpansion(property: ShadowProperty): boolean {\n return Boolean(property.expansionContext && property.source);\n }\n\n #expandPropertyIfNeeded(property: ShadowProperty): void {\n if (this.#needsExpansion(property)) {\n // Rendering prefers `source` if present. It's sufficient to clear it in order to switch rendering to render the\n // individual properties directly.\n const source = property.source;\n this.#properties.filter(property => property.source === source).forEach(property => {\n property.source = null;\n });\n }\n }\n\n #expandOrGetProperty(propertyType: Exclude):\n {property: ShadowProperty|undefined, index: number};\n #expandOrGetProperty(propertyType: ShadowLengthProperty['propertyType']):\n {property: ShadowLengthProperty|undefined, index: number};\n #expandOrGetProperty(propertyType: ShadowPropertyType): {property: ShadowProperty|undefined, index: number} {\n const index = this.#properties.findIndex(property => property.propertyType === propertyType);\n const property = index >= 0 ? this.#properties[index] : undefined;\n property && this.#expandPropertyIfNeeded(property);\n return {property, index};\n }\n\n setInset(inset: boolean): void {\n if (!this.isBoxShadow()) {\n return;\n }\n\n const {property, index} = this.#expandOrGetProperty(ShadowPropertyType.INSET);\n if (property) {\n // For `inset`, remove the entry if value is false, otherwise don't touch it.\n if (!inset) {\n this.#properties.splice(index, 1);\n }\n } else {\n this.#properties.unshift(\n {value: 'inset', source: null, expansionContext: null, propertyType: ShadowPropertyType.INSET});\n }\n }\n #setLength(value: InlineEditor.CSSShadowEditor.CSSLength, propertyType: ShadowLengthProperty['propertyType']): void {\n const {property} = this.#expandOrGetProperty(propertyType);\n if (property) {\n property.value = value.asCSSText();\n property.length = value;\n property.source = null;\n } else {\n // Lengths are ordered X, Y, Blur, Spread, with the latter two being optional. When inserting an optional property\n // we need to insert it after Y or after Blur, depending on what's being inserted and which properties are\n // present.\n const insertionIdx = 1 +\n this.#properties.findLastIndex(\n property => property.propertyType === ShadowPropertyType.Y ||\n (propertyType === ShadowPropertyType.SPREAD && property.propertyType === ShadowPropertyType.BLUR));\n if (insertionIdx > 0 && insertionIdx < this.#properties.length &&\n this.#needsExpansion(this.#properties[insertionIdx]) &&\n this.#properties[insertionIdx - 1].source === this.#properties[insertionIdx].source) {\n // This prevents the edge case where insertion after the last length would break up a group of values that\n // require expansion.\n this.#expandPropertyIfNeeded(this.#properties[insertionIdx]);\n }\n this.#properties.splice(\n insertionIdx, 0,\n {value: value.asCSSText(), length: value, source: null, expansionContext: null, propertyType} as\n ShadowLengthProperty);\n }\n }\n setOffsetX(value: InlineEditor.CSSShadowEditor.CSSLength): void {\n this.#setLength(value, ShadowPropertyType.X);\n }\n setOffsetY(value: InlineEditor.CSSShadowEditor.CSSLength): void {\n this.#setLength(value, ShadowPropertyType.Y);\n }\n setBlurRadius(value: InlineEditor.CSSShadowEditor.CSSLength): void {\n this.#setLength(value, ShadowPropertyType.BLUR);\n }\n setSpreadRadius(value: InlineEditor.CSSShadowEditor.CSSLength): void {\n if (this.isBoxShadow()) {\n this.#setLength(value, ShadowPropertyType.SPREAD);\n }\n }\n\n renderContents(parent: HTMLElement): void {\n parent.removeChildren();\n const span = parent.createChild('span');\n let previousSource = null;\n for (const property of this.#properties) {\n if (!property.source || property.source !== previousSource) {\n if (property !== this.#properties[0]) {\n span.append(' ');\n }\n // If `source` is present on the property that means it came from a var() and we'll use that to render.\n if (property.source) {\n span.append(...Renderer.render(property.source, this.#context).nodes);\n } else if (typeof property.value === 'string') {\n span.append(property.value);\n } else {\n span.append(...Renderer.render(property.value, property.expansionContext ?? this.#context).nodes);\n }\n }\n previousSource = property.source;\n }\n }\n}\n\nexport class ShadowRenderer implements MatchRenderer {\n readonly #treeElement: StylePropertyTreeElement;\n constructor(treeElement: StylePropertyTreeElement) {\n this.#treeElement = treeElement;\n }\n\n shadowModel(shadow: CodeMirror.SyntaxNode[], shadowType: ShadowType, context: RenderingContext): null|ShadowModel {\n const properties: Array = [];\n const missingLengths: ShadowLengthProperty['propertyType'][] =\n [ShadowPropertyType.SPREAD, ShadowPropertyType.BLUR, ShadowPropertyType.Y, ShadowPropertyType.X];\n let stillAcceptsLengths = true;\n\n // We're parsing the individual shadow properties into an array here retaining the ordering. This also looks through\n // var() functions by re-parsing the variable values on the fly. For properties coming from a var() we're keeping\n // track of their origin to allow for adhoc expansion when one of those properties is edited.\n\n const queue: {\n value: CodeMirror.SyntaxNode,\n source: CodeMirror.SyntaxNode,\n match: SDK.CSSPropertyParser.Match|undefined,\n expansionContext: RenderingContext|null,\n }[] =\n shadow.map(\n value => ({value, source: value, match: context.matchedResult.getMatch(value), expansionContext: null}));\n for (let item = queue.shift(); item; item = queue.shift()) {\n const {value, source, match, expansionContext} = item;\n const text = (expansionContext ?? context).ast.text(value);\n if (value.name === 'NumberLiteral') {\n if (!stillAcceptsLengths) {\n return null;\n }\n const propertyType = missingLengths.pop();\n if (propertyType === undefined ||\n (propertyType === ShadowPropertyType.SPREAD && shadowType === ShadowType.TEXT_SHADOW)) {\n return null;\n }\n const length = InlineEditor.CSSShadowEditor.CSSLength.parse(text);\n if (!length) {\n return null;\n }\n properties.push({value, source, length, propertyType, expansionContext});\n } else if (match instanceof SDK.CSSPropertyParser.VariableMatch) {\n // This doesn't come from any computed text, so we can rely on context here\n const computedValue = context.matchedResult.getComputedText(value);\n const computedValueAst = SDK.CSSPropertyParser.tokenizeDeclaration('--property', computedValue);\n if (!computedValueAst) {\n return null;\n }\n const matches =\n SDK.CSSPropertyParser.BottomUpTreeMatching.walkExcludingSuccessors(computedValueAst, [new ColorMatcher()]);\n if (matches.hasUnresolvedVars(matches.ast.tree)) {\n return null;\n }\n queue.unshift(...ASTUtils.siblings(ASTUtils.declValue(matches.ast.tree))\n .map(matchedNode => ({\n value: matchedNode,\n source: value,\n match: matches.getMatch(matchedNode),\n expansionContext: new RenderingContext(computedValueAst, context.renderers, matches),\n })));\n } else {\n // The length properties must come in one block, so if there were any lengths before, followed by a non-length\n // property, we will not allow any future lengths.\n stillAcceptsLengths = missingLengths.length === 4;\n if (value.name === 'ValueName' && text.toLowerCase() === 'inset') {\n if (shadowType === ShadowType.TEXT_SHADOW ||\n properties.find(({propertyType}) => propertyType === ShadowPropertyType.INSET)) {\n return null;\n }\n properties.push({value, source, propertyType: ShadowPropertyType.INSET, expansionContext});\n } else if (match instanceof ColorMatch || match instanceof ColorMixMatch) {\n if (properties.find(({propertyType}) => propertyType === ShadowPropertyType.COLOR)) {\n return null;\n }\n properties.push({value, source, propertyType: ShadowPropertyType.COLOR, expansionContext});\n } else if (value.name !== 'Comment' && value.name !== 'Important') {\n return null;\n }\n }\n }\n if (missingLengths.length > 2) {\n // X and Y are mandatory\n return null;\n }\n return new ShadowModel(shadowType, properties, context);\n }\n\n render(match: ShadowMatch, context: RenderingContext): Node[] {\n const shadows = ASTUtils.split(ASTUtils.siblings(ASTUtils.declValue(match.node)));\n const result: Node[] = [];\n\n for (const shadow of shadows) {\n const model = this.shadowModel(shadow, match.shadowType, context);\n const isImportant = shadow.find(node => node.name === 'Important');\n\n if (shadow !== shadows[0]) {\n result.push(document.createTextNode(', '));\n }\n\n if (!model) {\n const {nodes} = Renderer.render(shadow, context);\n result.push(...nodes);\n continue;\n }\n\n const swatch = new InlineEditor.Swatches.CSSShadowSwatch(model);\n swatch.setAttribute('jslog', `${VisualLogging.showStyleEditor('css-shadow').track({click: true})}`);\n swatch.iconElement().addEventListener('click', () => {\n Host.userMetrics.swatchActivated(Host.UserMetrics.SwatchType.SHADOW);\n });\n model.renderContents(swatch);\n const popoverHelper = new ShadowSwatchPopoverHelper(\n this.#treeElement, this.#treeElement.parentPane().swatchPopoverHelper(), swatch);\n popoverHelper.addEventListener(ShadowEvents.SHADOW_CHANGED, () => {\n model.renderContents(swatch);\n void this.#treeElement.applyStyleText(this.#treeElement.renderedPropertyText(), false);\n });\n result.push(swatch);\n\n if (isImportant) {\n result.push(...[document.createTextNode(' '), ...Renderer.render(isImportant, context).nodes]);\n }\n }\n\n return result;\n }\n\n matcher(): ShadowMatcher {\n return new ShadowMatcher();\n }\n}\n\nexport class FontRenderer implements MatchRenderer {\n constructor(readonly treeElement: StylePropertyTreeElement) {\n }\n\n render(match: FontMatch): Node[] {\n this.treeElement.section().registerFontProperty(this.treeElement);\n return [document.createTextNode(match.text)];\n }\n\n matcher(): FontMatcher {\n return new FontMatcher();\n }\n}\n\nexport class GridTemplateRenderer implements MatchRenderer {\n render(match: GridTemplateMatch, context: RenderingContext): Node[] {\n if (match.lines.length <= 1) {\n return Renderer.render(ASTUtils.siblings(ASTUtils.declValue(match.node)), context).nodes;\n }\n\n const indent = Common.Settings.Settings.instance().moduleSetting('text-editor-indent').get();\n const container = document.createDocumentFragment();\n for (const line of match.lines) {\n const value = Renderer.render(line, context);\n const lineBreak = UI.Fragment.html`
${indent.repeat(2)}`;\n container.append(lineBreak, ...value.nodes);\n }\n return [container];\n }\n\n matcher(): GridTemplateMatcher {\n return new GridTemplateMatcher();\n }\n}\n\nexport class LengthRenderer implements MatchRenderer {\n readonly #treeElement: StylePropertyTreeElement;\n constructor(treeElement: StylePropertyTreeElement) {\n this.#treeElement = treeElement;\n }\n\n render(match: LengthMatch, _context: RenderingContext): Node[] {\n const lengthText = match.text;\n if (!this.#treeElement.editable()) {\n return [document.createTextNode(lengthText)];\n }\n const cssLength = new InlineEditor.CSSLength.CSSLength();\n const valueElement = document.createElement('span');\n valueElement.textContent = lengthText;\n cssLength.data = {lengthText};\n cssLength.append(valueElement);\n\n const onValueChanged = (event: Event): void => {\n const {data} = (event as InlineEditor.InlineEditorUtils.ValueChangedEvent);\n\n valueElement.textContent = data.value;\n this.#treeElement.parentPane().setEditingStyle(true);\n void this.#treeElement.applyStyleText(this.#treeElement.renderedPropertyText(), false);\n };\n\n const onDraggingFinished = (): void => {\n this.#treeElement.parentPane().setEditingStyle(false);\n };\n\n cssLength.addEventListener('valuechanged', onValueChanged);\n cssLength.addEventListener('draggingfinished', onDraggingFinished);\n\n return [cssLength];\n }\n\n matcher(): LengthMatcher {\n return new LengthMatcher();\n }\n}\n\nasync function decorateAnchorForAnchorLink(container: HTMLElement, treeElement: StylePropertyTreeElement, options: {\n identifier?: string, needsSpace: boolean,\n}): Promise {\n const anchorNode = await treeElement.node()?.getAnchorBySpecifier(options.identifier) ?? undefined;\n const link = new ElementsComponents.AnchorFunctionLinkSwatch.AnchorFunctionLinkSwatch({\n identifier: options.identifier,\n anchorNode,\n needsSpace: options.needsSpace,\n onLinkActivate: () => {\n if (!anchorNode) {\n return;\n }\n\n void Common.Revealer.reveal(anchorNode, false);\n },\n onMouseEnter: () => {\n anchorNode?.highlight();\n },\n onMouseLeave: () => {\n SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight();\n },\n });\n\n container.removeChildren();\n container.appendChild(link);\n}\n\nexport class AnchorFunctionRenderer implements MatchRenderer {\n #treeElement: StylePropertyTreeElement;\n constructor(treeElement: StylePropertyTreeElement) {\n this.#treeElement = treeElement;\n }\n\n anchorDecoratedForTest(): void {\n }\n\n async #decorateAnchor(container: HTMLElement, identifier?: string): Promise {\n await decorateAnchorForAnchorLink(container, this.#treeElement, {\n identifier,\n needsSpace: true,\n });\n this.anchorDecoratedForTest();\n }\n\n render(match: AnchorFunctionMatch, context: RenderingContext): Node[] {\n const content = document.createElement('span');\n content.appendChild(document.createTextNode(`${match.functionName}(`));\n\n const firstArgText = match.matching.ast.text(match.args[0]);\n const hasDashedIdentifier = firstArgText.startsWith('--');\n const linkContainer = document.createElement('span');\n if (hasDashedIdentifier) {\n linkContainer.textContent = `${firstArgText} `;\n }\n content.appendChild(linkContainer);\n\n const remainingArgsContainer = content.appendChild(document.createElement('span'));\n if (hasDashedIdentifier) {\n Renderer.renderInto(match.args.slice(1), context, remainingArgsContainer);\n } else {\n Renderer.renderInto(match.args, context, remainingArgsContainer);\n }\n\n void this.#decorateAnchor(linkContainer, hasDashedIdentifier ? firstArgText : undefined);\n content.appendChild(document.createTextNode(')'));\n return [content];\n }\n\n matcher(): AnchorFunctionMatcher {\n return new AnchorFunctionMatcher();\n }\n}\n\nexport class PositionAnchorRenderer implements MatchRenderer {\n #treeElement: StylePropertyTreeElement;\n\n constructor(treeElement: StylePropertyTreeElement) {\n this.#treeElement = treeElement;\n }\n\n anchorDecoratedForTest(): void {\n }\n\n render(match: PositionAnchorMatch): Node[] {\n const content = document.createElement('span');\n content.appendChild(document.createTextNode(match.text));\n void decorateAnchorForAnchorLink(content, this.#treeElement, {\n identifier: match.text,\n needsSpace: false,\n }).then(() => this.anchorDecoratedForTest());\n return [content];\n }\n\n matcher(): PositionAnchorMatcher {\n return new PositionAnchorMatcher();\n }\n}\n\nexport class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {\n private readonly style: SDK.CSSStyleDeclaration.CSSStyleDeclaration;\n private matchedStylesInternal: SDK.CSSMatchedStyles.CSSMatchedStyles;\n property: SDK.CSSProperty.CSSProperty;\n private readonly inheritedInternal: boolean;\n private overloadedInternal: boolean;\n private parentPaneInternal: StylesSidebarPane;\n #parentSection: StylePropertiesSection;\n isShorthand: boolean;\n private readonly applyStyleThrottler: Common.Throttler.Throttler;\n private newProperty: boolean;\n private expandedDueToFilter: boolean;\n valueElement: HTMLElement|null;\n nameElement: HTMLElement|null;\n private expandElement: IconButton.Icon.Icon|null;\n private originalPropertyText: string;\n private hasBeenEditedIncrementally: boolean;\n private prompt: CSSPropertyPrompt|null;\n private lastComputedValue: string|null;\n private computedStyles: Map|null = null;\n private parentsComputedStyles: Map|null = null;\n private contextForTest!: Context|undefined;\n #propertyTextFromSource: string;\n #gridNames: Set|undefined = undefined;\n\n constructor(\n {stylesPane, section, matchedStyles, property, isShorthand, inherited, overloaded, newProperty}:\n StylePropertyTreeElementParams,\n ) {\n // Pass an empty title, the title gets made later in onattach.\n const jslogContext = property.name.startsWith('--') ? 'custom-property' : property.name;\n super('', isShorthand, jslogContext);\n this.style = property.ownerStyle;\n this.matchedStylesInternal = matchedStyles;\n this.property = property;\n this.inheritedInternal = inherited;\n this.overloadedInternal = overloaded;\n this.selectable = false;\n this.parentPaneInternal = stylesPane;\n this.#parentSection = section;\n this.isShorthand = isShorthand;\n this.applyStyleThrottler = new Common.Throttler.Throttler(0);\n this.newProperty = newProperty;\n if (this.newProperty) {\n this.listItemElement.textContent = '';\n }\n this.expandedDueToFilter = false;\n this.valueElement = null;\n this.nameElement = null;\n this.expandElement = null;\n this.originalPropertyText = '';\n this.hasBeenEditedIncrementally = false;\n this.prompt = null;\n\n this.lastComputedValue = null;\n\n this.#propertyTextFromSource = property.propertyText || '';\n }\n\n async gridNames(): Promise> {\n if (!SDK.CSSMetadata.cssMetadata().isGridNameAwareProperty(this.name)) {\n return new Set();\n }\n for (let node = this.parentPaneInternal.node()?.parentNode; node; node = node?.parentNode) {\n const style = await this.parentPaneInternal.cssModel()?.getComputedStyle(node.id);\n const display = style?.get('display');\n const isGrid = display === 'grid' || display === 'inline-grid';\n if (!isGrid) {\n continue;\n }\n const getNames = (propertyName: string, astNodeName: string): string[] => {\n const propertyValue = style?.get(propertyName);\n if (!propertyValue) {\n return [];\n }\n const ast = SDK.CSSPropertyParser.tokenizeDeclaration(propertyName, propertyValue);\n if (!ast) {\n return [];\n }\n return SDK.CSSPropertyParser.TreeSearch.findAll(ast, node => node.name === astNodeName)\n .map(node => ast.text(node));\n };\n if (SDK.CSSMetadata.cssMetadata().isGridAreaNameAwareProperty(this.name)) {\n return new Set(\n getNames('grid-template-areas', 'StringLiteral')\n ?.flatMap(row => row.substring(1, row.length - 1).split(/\\s+/).filter(cell => !cell.match(/^\\.*$/))));\n }\n if (SDK.CSSMetadata.cssMetadata().isGridColumnNameAwareProperty(this.name)) {\n return new Set(getNames('grid-template-columns', 'LineName'));\n }\n return new Set(getNames('grid-template-rows', 'LineName'));\n }\n return new Set();\n }\n\n matchedStyles(): SDK.CSSMatchedStyles.CSSMatchedStyles {\n return this.matchedStylesInternal;\n }\n\n editable(): boolean {\n const isLonghandInsideShorthand = this.parent instanceof StylePropertyTreeElement && this.parent.isShorthand;\n const hasSourceData = Boolean(this.style.styleSheetId && this.style.range);\n return !isLonghandInsideShorthand && hasSourceData;\n }\n\n inherited(): boolean {\n return this.inheritedInternal;\n }\n\n overloaded(): boolean {\n return this.overloadedInternal;\n }\n\n setOverloaded(x: boolean): void {\n if (x === this.overloadedInternal) {\n return;\n }\n this.overloadedInternal = x;\n this.updateState();\n }\n\n setComputedStyles(computedStyles: Map|null): void {\n this.computedStyles = computedStyles;\n }\n\n getComputedStyle(property: string): string|null {\n return this.computedStyles?.get(property) ?? null;\n }\n\n setParentsComputedStyles(parentsComputedStyles: Map|null): void {\n this.parentsComputedStyles = parentsComputedStyles;\n }\n\n get name(): string {\n return this.property.name;\n }\n\n get value(): string {\n return this.property.value;\n }\n\n updateFilter(): boolean {\n const regex = this.parentPaneInternal.filterRegex();\n const matches = regex !== null && (regex.test(this.property.name) || regex.test(this.property.value));\n this.listItemElement.classList.toggle('filter-match', matches);\n\n void this.onpopulate();\n let hasMatchingChildren = false;\n\n for (let i = 0; i < this.childCount(); ++i) {\n const child = (this.childAt(i) as StylePropertyTreeElement | null);\n if (!child || (child && !child.updateFilter())) {\n continue;\n }\n hasMatchingChildren = true;\n }\n\n if (!regex) {\n if (this.expandedDueToFilter) {\n this.collapse();\n }\n this.expandedDueToFilter = false;\n } else if (hasMatchingChildren && !this.expanded) {\n this.expand();\n this.expandedDueToFilter = true;\n } else if (!hasMatchingChildren && this.expanded && this.expandedDueToFilter) {\n this.collapse();\n this.expandedDueToFilter = false;\n }\n return matches;\n }\n\n renderedPropertyText(): string {\n if (!this.nameElement || !this.valueElement) {\n return '';\n }\n return this.nameElement.textContent + ': ' + this.valueElement.textContent;\n }\n\n private updateState(): void {\n if (!this.listItemElement) {\n return;\n }\n\n if (this.style.isPropertyImplicit(this.name)) {\n this.listItemElement.classList.add('implicit');\n } else {\n this.listItemElement.classList.remove('implicit');\n }\n\n const hasIgnorableError = !this.property.parsedOk && StylesSidebarPane.ignoreErrorsForProperty(this.property);\n if (hasIgnorableError) {\n this.listItemElement.classList.add('has-ignorable-error');\n } else {\n this.listItemElement.classList.remove('has-ignorable-error');\n }\n\n if (this.inherited()) {\n this.listItemElement.classList.add('inherited');\n } else {\n this.listItemElement.classList.remove('inherited');\n }\n\n if (this.overloaded()) {\n this.listItemElement.classList.add('overloaded');\n } else {\n this.listItemElement.classList.remove('overloaded');\n }\n\n if (this.property.disabled) {\n this.listItemElement.classList.add('disabled');\n } else {\n this.listItemElement.classList.remove('disabled');\n }\n\n this.listItemElement.classList.toggle('changed', this.isPropertyChanged(this.property));\n }\n\n node(): SDK.DOMModel.DOMNode|null {\n return this.parentPaneInternal.node();\n }\n\n parentPane(): StylesSidebarPane {\n return this.parentPaneInternal;\n }\n\n section(): StylePropertiesSection {\n return this.#parentSection;\n }\n\n private updatePane(): void {\n this.#parentSection.refreshUpdate(this);\n }\n\n private async toggleDisabled(disabled: boolean): Promise {\n const oldStyleRange = this.style.range;\n if (!oldStyleRange) {\n return;\n }\n\n this.parentPaneInternal.setUserOperation(true);\n const success = await this.property.setDisabled(disabled);\n this.parentPaneInternal.setUserOperation(false);\n\n if (!success) {\n return;\n }\n this.matchedStylesInternal.resetActiveProperties();\n this.updatePane();\n this.styleTextAppliedForTest();\n }\n\n private isPropertyChanged(property: SDK.CSSProperty.CSSProperty): boolean {\n if (!Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.STYLES_PANE_CSS_CHANGES)) {\n return false;\n }\n // Check local cache first, then check against diffs from the workspace.\n return this.#propertyTextFromSource !== property.propertyText || this.parentPane().isPropertyChanged(property);\n }\n\n override async onpopulate(): Promise {\n if (!this.#gridNames) {\n this.#gridNames = await this.gridNames();\n }\n\n // Only populate once and if this property is a shorthand.\n if (this.childCount() || !this.isShorthand) {\n return;\n }\n\n const longhandProperties = this.property.getLonghandProperties();\n const leadingProperties = this.style.leadingProperties();\n\n for (const property of longhandProperties) {\n const name = property.name;\n let inherited = false;\n let overloaded = false;\n\n inherited = this.#parentSection.isPropertyInherited(name);\n overloaded = this.matchedStylesInternal.propertyState(property) === SDK.CSSMatchedStyles.PropertyState.OVERLOADED;\n\n const leadingProperty = leadingProperties.find(property => property.name === name && property.activeInStyle());\n if (leadingProperty) {\n overloaded = true;\n }\n\n const item = new StylePropertyTreeElement({\n stylesPane: this.parentPaneInternal,\n section: this.#parentSection,\n matchedStyles: this.matchedStylesInternal,\n property,\n isShorthand: false,\n inherited,\n overloaded,\n newProperty: false,\n });\n item.setComputedStyles(this.computedStyles);\n item.setParentsComputedStyles(this.parentsComputedStyles);\n this.appendChild(item);\n }\n }\n\n override onattach(): void {\n this.updateTitle();\n\n this.listItemElement.addEventListener('mousedown', event => {\n if (event.button === 0) {\n parentMap.set(this.parentPaneInternal, this);\n }\n }, false);\n this.listItemElement.addEventListener('mouseup', this.mouseUp.bind(this));\n this.listItemElement.addEventListener('click', event => {\n if (!event.target) {\n return;\n }\n\n const node = (event.target as HTMLElement);\n if (!node.hasSelection() && event.target !== this.listItemElement) {\n event.consume(true);\n }\n });\n\n // Copy context menu.\n this.listItemElement.addEventListener('contextmenu', this.handleCopyContextMenuEvent.bind(this));\n }\n\n override onexpand(): void {\n this.updateExpandElement();\n }\n\n override oncollapse(): void {\n this.updateExpandElement();\n }\n\n private updateExpandElement(): void {\n if (!this.expandElement) {\n return;\n }\n if (this.expanded) {\n this.expandElement.name = 'triangle-down';\n } else {\n this.expandElement.name = 'triangle-right';\n }\n }\n\n #getRegisteredPropertyDetails(variableName: string): ElementsComponents.CSSVariableValueView.RegisteredPropertyDetails\n |undefined {\n const registration = this.matchedStyles().getRegisteredProperty(variableName);\n const goToDefinition = (): void =>\n this.parentPaneInternal.jumpToSection(variableName, REGISTERED_PROPERTY_SECTION_NAME);\n return registration ? {registration, goToDefinition} : undefined;\n }\n\n getVariablePopoverContents(variableName: string, computedValue: string|null): HTMLElement|undefined {\n return new ElementsComponents.CSSVariableValueView.CSSVariableValueView({\n variableName,\n value: computedValue ?? undefined,\n details: this.#getRegisteredPropertyDetails(variableName),\n });\n }\n\n // Resolves a CSS expression to its computed value with `var()` calls updated.\n // Still returns the string even when a `var()` call is not resolved.\n #computeCSSExpression(style: SDK.CSSStyleDeclaration.CSSStyleDeclaration, text: string): string|null {\n const ast = SDK.CSSPropertyParser.tokenizeDeclaration('--unused', text);\n if (!ast) {\n return null;\n }\n\n const matching: SDK.CSSPropertyParser.BottomUpTreeMatching = SDK.CSSPropertyParser.BottomUpTreeMatching.walk(\n ast, [new SDK.CSSPropertyParser.VariableMatcher((match: SDK.CSSPropertyParser.VariableMatch) => {\n const variableValue = this.matchedStylesInternal.computeCSSVariable(style, match.name)?.value;\n if (variableValue !== undefined) {\n return variableValue;\n }\n\n if (match.fallback.length === 0 ||\n match.matching.hasUnresolvedVarsRange(match.fallback[0], match.fallback[match.fallback.length - 1])) {\n return null;\n }\n return match.matching.getComputedTextRange(match.fallback[0], match.fallback[match.fallback.length - 1]);\n })]);\n\n const decl = SDK.CSSPropertyParser.ASTUtils.siblings(SDK.CSSPropertyParser.ASTUtils.declValue(matching.ast.tree));\n return matching.getComputedTextRange(decl[0], decl[decl.length - 1]);\n }\n\n refreshIfComputedValueChanged(): void {\n this.#gridNames = undefined;\n const computedValue = this.#computeCSSExpression(this.property.ownerStyle, this.property.value);\n if (computedValue === this.lastComputedValue) {\n return;\n }\n this.lastComputedValue = computedValue;\n this.innerUpdateTitle();\n }\n\n updateTitle(): void {\n this.lastComputedValue = this.#computeCSSExpression(this.property.ownerStyle, this.property.value);\n this.innerUpdateTitle();\n }\n\n private innerUpdateTitle(): void {\n this.updateState();\n if (this.isExpandable()) {\n this.expandElement = IconButton.Icon.create('triangle-right', 'expand-icon');\n this.expandElement.setAttribute('jslog', `${VisualLogging.expand().track({click: true})}`);\n }\n\n const renderers: MatchRenderer[] = this.property.parsedOk ?\n [\n new VariableRenderer(this, this.style),\n new ColorRenderer(this),\n new ColorMixRenderer(this.parentPaneInternal),\n new URLRenderer(this.style.parentRule, this.node()),\n new AngleRenderer(this),\n new LinkableNameRenderer(this),\n new BezierRenderer(this),\n new StringRenderer(),\n new ShadowRenderer(this),\n new FontRenderer(this),\n new LightDarkColorRenderer(this),\n new GridTemplateRenderer(),\n new LinearGradientRenderer(),\n new AnchorFunctionRenderer(this),\n new PositionAnchorRenderer(this),\n ] :\n [];\n\n if (!Root.Runtime.experiments.isEnabled('css-type-component-length-deprecate') && this.property.parsedOk) {\n renderers.push(new LengthRenderer(this));\n }\n\n this.listItemElement.removeChildren();\n this.valueElement = Renderer.renderValueElement(this.name, this.value, renderers);\n this.nameElement = Renderer.renderNameElement(this.name);\n if (this.property.name.startsWith('--') && this.nameElement) {\n this.parentPaneInternal.addPopover(this.nameElement, {\n contents: () => this.getVariablePopoverContents(\n this.property.name,\n this.matchedStylesInternal.computeCSSVariable(this.style, this.property.name)?.value ?? null),\n jslogContext: 'elements.css-var',\n });\n }\n if (!this.treeOutline) {\n return;\n }\n\n const indent = Common.Settings.Settings.instance().moduleSetting('text-editor-indent').get();\n UI.UIUtils.createTextChild(\n this.listItemElement.createChild('span', 'styles-clipboard-only'),\n indent.repeat(this.section().nestingLevel + 1) + (this.property.disabled ? '/* ' : ''));\n if (this.nameElement) {\n this.listItemElement.appendChild(this.nameElement);\n }\n if (this.valueElement) {\n const lineBreakValue =\n this.valueElement.firstElementChild && this.valueElement.firstElementChild.tagName === 'BR';\n const separator = lineBreakValue ? ':' : ': ';\n this.listItemElement.createChild('span', 'styles-name-value-separator').textContent = separator;\n if (this.expandElement) {\n this.listItemElement.appendChild(this.expandElement);\n this.updateExpandElement();\n }\n this.listItemElement.appendChild(this.valueElement);\n const semicolon = this.listItemElement.createChild('span', 'styles-semicolon');\n semicolon.textContent = ';';\n semicolon.onmouseup = this.mouseUp.bind(this);\n if (this.property.disabled) {\n UI.UIUtils.createTextChild(this.listItemElement.createChild('span', 'styles-clipboard-only'), ' */');\n }\n }\n\n if (this.valueElement && this.#parentSection.editable && this.property.name === 'display') {\n const propertyValue = this.property.trimmedValueWithoutImportant();\n const isFlex = propertyValue === 'flex' || propertyValue === 'inline-flex';\n const isGrid = propertyValue === 'grid' || propertyValue === 'inline-grid';\n if (isFlex || isGrid) {\n const key = `${this.#parentSection.getSectionIdx()}_${this.#parentSection.nextEditorTriggerButtonIdx}`;\n const button = StyleEditorWidget.createTriggerButton(\n this.parentPaneInternal, this.#parentSection, isFlex ? FlexboxEditor : GridEditor,\n isFlex ? i18nString(UIStrings.flexboxEditorButton) : i18nString(UIStrings.gridEditorButton), key);\n button.setAttribute(\n 'jslog', `${VisualLogging.showStyleEditor().track({click: true}).context(isFlex ? 'flex' : 'grid')}`);\n this.#parentSection.nextEditorTriggerButtonIdx++;\n button.addEventListener('click', () => {\n Host.userMetrics.swatchActivated(\n isFlex ? Host.UserMetrics.SwatchType.FLEX : Host.UserMetrics.SwatchType.GRID);\n });\n this.listItemElement.appendChild(button);\n const helper = this.parentPaneInternal.swatchPopoverHelper();\n if (helper.isShowing(StyleEditorWidget.instance()) && StyleEditorWidget.instance().getTriggerKey() === key) {\n helper.setAnchorElement(button);\n }\n }\n }\n\n if (this.property.parsedOk) {\n this.updateAuthoringHint();\n } else {\n // Avoid having longhands under an invalid shorthand.\n this.listItemElement.classList.add('not-parsed-ok');\n\n const registrationDetails = this.#getRegisteredPropertyDetails(this.property.name);\n const tooltip = registrationDetails ?\n new ElementsComponents.CSSVariableValueView.CSSVariableParserError(registrationDetails) :\n null;\n // Add a separate exclamation mark IMG element with a tooltip.\n this.listItemElement.insertBefore(\n this.parentPaneInternal.createExclamationMark(this.property, tooltip), this.listItemElement.firstChild);\n\n // When the property is valid but the property value is invalid,\n // add line-through only to the property value.\n const invalidPropertyValue = SDK.CSSMetadata.cssMetadata().isCSSPropertyName(this.property.name);\n if (invalidPropertyValue) {\n this.listItemElement.classList.add('invalid-property-value');\n }\n }\n\n if (!this.property.activeInStyle()) {\n this.listItemElement.classList.add('inactive');\n }\n this.updateFilter();\n\n if (this.property.parsedOk && this.parent && this.parent.root) {\n const enabledCheckboxElement = document.createElement('input');\n enabledCheckboxElement.classList.add('enabled-button', 'small');\n enabledCheckboxElement.type = 'checkbox';\n enabledCheckboxElement.checked = !this.property.disabled;\n enabledCheckboxElement.setAttribute('jslog', `${VisualLogging.toggle().track({click: true})}`);\n enabledCheckboxElement.addEventListener('mousedown', event => event.consume(), false);\n enabledCheckboxElement.addEventListener('click', event => {\n void this.toggleDisabled(!this.property.disabled);\n event.consume();\n }, false);\n if (this.nameElement && this.valueElement) {\n UI.ARIAUtils.setLabel(\n enabledCheckboxElement, `${this.nameElement.textContent} ${this.valueElement.textContent}`);\n }\n\n const copyIcon = IconButton.Icon.create('copy', 'copy');\n UI.Tooltip.Tooltip.install(copyIcon, i18nString(UIStrings.copyDeclaration));\n copyIcon.addEventListener('click', () => {\n const propertyText = `${this.property.name}: ${this.property.value};`;\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(propertyText);\n Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.DECLARATION_VIA_CHANGED_LINE);\n });\n this.listItemElement.append(copyIcon);\n this.listItemElement.insertBefore(enabledCheckboxElement, this.listItemElement.firstChild);\n }\n }\n\n updateAuthoringHint(): void {\n this.listItemElement.classList.remove('inactive-property');\n const existingElement = this.listItemElement.querySelector('.hint');\n if (existingElement) {\n activeHints.delete(existingElement);\n existingElement?.closest('.hint-wrapper')?.remove();\n }\n const propertyName = this.property.name;\n\n if (!cssRuleValidatorsMap.has(propertyName)) {\n return;\n }\n\n // Different rules apply to SVG nodes altogether. We currently don't have SVG-specific hints.\n if (this.node()?.isSVGNode()) {\n return;\n }\n\n const cssModel = this.parentPaneInternal.cssModel();\n const fontFaces = cssModel?.fontFaces() || [];\n\n const localName = this.node()?.localName();\n for (const validator of cssRuleValidatorsMap.get(propertyName) || []) {\n const hint = validator.getHint(\n propertyName, this.computedStyles || undefined, this.parentsComputedStyles || undefined,\n localName?.toLowerCase(), fontFaces);\n if (hint) {\n Host.userMetrics.cssHintShown(validator.getMetricType());\n const wrapper = document.createElement('span');\n wrapper.classList.add('hint-wrapper');\n const hintIcon = new IconButton.Icon.Icon();\n hintIcon.data = {iconName: 'info', color: 'var(--icon-default)', width: '14px', height: '14px'};\n hintIcon.classList.add('hint');\n wrapper.append(hintIcon);\n activeHints.set(hintIcon, hint);\n this.listItemElement.append(wrapper);\n this.listItemElement.classList.add('inactive-property');\n break;\n }\n }\n }\n\n private mouseUp(event: MouseEvent): void {\n const activeTreeElement = parentMap.get(this.parentPaneInternal);\n parentMap.delete(this.parentPaneInternal);\n if (!activeTreeElement) {\n return;\n }\n if (this.listItemElement.hasSelection()) {\n return;\n }\n if (UI.UIUtils.isBeingEdited((event.target as Node))) {\n return;\n }\n if (event.composedPath()[0] instanceof HTMLButtonElement) {\n return;\n }\n\n event.consume(true);\n\n if (event.target === this.listItemElement) {\n return;\n }\n\n let selectedElement = event.target as Element;\n if (UI.KeyboardShortcut.KeyboardShortcut.eventHasCtrlEquivalentKey(event) && this.#parentSection.navigable) {\n this.navigateToSource(selectedElement);\n return;\n }\n\n if (this.expandElement && selectedElement === this.expandElement) {\n return;\n }\n\n if (!this.#parentSection.editable) {\n return;\n }\n\n selectedElement = selectedElement.enclosingNodeOrSelfWithClass('webkit-css-property') ||\n selectedElement.enclosingNodeOrSelfWithClass('value') ||\n selectedElement.enclosingNodeOrSelfWithClass('styles-semicolon');\n if (!selectedElement || selectedElement === this.nameElement) {\n VisualLogging.logClick(this.nameElement as Element, event);\n this.startEditingName();\n } else {\n VisualLogging.logClick(this.valueElement as Element, event);\n this.startEditingValue();\n }\n }\n\n private handleContextMenuEvent(context: Context, event: Event): void {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n if (this.property.parsedOk && this.parent && this.parent.root) {\n const sectionIndex = this.parentPaneInternal.focusedSectionIndex();\n contextMenu.defaultSection().appendCheckboxItem(\n i18nString(UIStrings.togglePropertyAndContinueEditing), async () => {\n if (this.treeOutline) {\n const propertyIndex = this.treeOutline.rootElement().indexOfChild(this);\n // order matters here: this.editingCancelled may invalidate this.treeOutline.\n this.editingCancelled(null, context);\n await this.toggleDisabled(!this.property.disabled);\n event.consume();\n this.parentPaneInternal.continueEditingElement(sectionIndex, propertyIndex);\n }\n }, {checked: !this.property.disabled, jslogContext: 'toggle-property-and-continue-editing'});\n }\n const revealCallback = this.navigateToSource.bind(this) as () => void;\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.revealInSourcesPanel), revealCallback, {jslogContext: 'reveal-in-sources-panel'});\n void contextMenu.show();\n }\n\n private handleCopyContextMenuEvent(event: Event): void {\n const target = (event.target as Element | null);\n\n if (!target) {\n return;\n }\n\n const contextMenu = this.createCopyContextMenu(event);\n void contextMenu.show();\n }\n\n createCopyContextMenu(event: Event): UI.ContextMenu.ContextMenu {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n contextMenu.headerSection().appendItem(i18nString(UIStrings.copyDeclaration), () => {\n const propertyText = `${this.property.name}: ${this.property.value};`;\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(propertyText);\n Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.DECLARATION_VIA_CONTEXT_MENU);\n }, {jslogContext: 'copy-declaration'});\n\n contextMenu.headerSection().appendItem(i18nString(UIStrings.copyProperty), () => {\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(this.property.name);\n Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.PROPERTY_VIA_CONTEXT_MENU);\n }, {jslogContext: 'copy-property'});\n\n contextMenu.headerSection().appendItem(i18nString(UIStrings.copyValue), () => {\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(this.property.value);\n Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.VALUE_VIA_CONTEXT_MENU);\n }, {jslogContext: 'copy-value'});\n\n contextMenu.headerSection().appendItem(i18nString(UIStrings.copyRule), () => {\n const ruleText = StylesSidebarPane.formatLeadingProperties(this.#parentSection).ruleText;\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(ruleText);\n Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.RULE_VIA_CONTEXT_MENU);\n }, {jslogContext: 'copy-rule'});\n\n contextMenu.headerSection().appendItem(\n i18nString(UIStrings.copyCssDeclarationAsJs), this.copyCssDeclarationAsJs.bind(this),\n {jslogContext: 'copy-css-declaration-as-js'});\n\n contextMenu.clipboardSection().appendItem(i18nString(UIStrings.copyAllDeclarations), () => {\n const allDeclarationText = StylesSidebarPane.formatLeadingProperties(this.#parentSection).allDeclarationText;\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(allDeclarationText);\n Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.ALL_DECLARATIONS_VIA_CONTEXT_MENU);\n }, {jslogContext: 'copy-all-declarations'});\n\n contextMenu.clipboardSection().appendItem(\n i18nString(UIStrings.copyAllCssDeclarationsAsJs), this.copyAllCssDeclarationAsJs.bind(this),\n {jslogContext: 'copy-all-css-declarations-as-js'});\n\n // TODO(changhaohan): conditionally add this item only when there are changes to copy\n contextMenu.defaultSection().appendItem(i18nString(UIStrings.copyAllCSSChanges), async () => {\n const allChanges = await this.parentPane().getFormattedChanges();\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(allChanges);\n Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.ALL_CHANGES_VIA_STYLES_TAB);\n }, {jslogContext: 'copy-all-css-changes'});\n\n contextMenu.footerSection().appendItem(i18nString(UIStrings.viewComputedValue), () => {\n void this.viewComputedValue();\n }, {jslogContext: 'view-computed-value'});\n\n return contextMenu;\n }\n\n private async viewComputedValue(): Promise {\n const computedStyleWidget = ElementsPanel.instance().getComputedStyleWidget();\n\n if (!computedStyleWidget.isShowing()) {\n await UI.ViewManager.ViewManager.instance().showView('Computed');\n }\n\n let propertyNamePattern = '';\n if (this.isShorthand) {\n propertyNamePattern = '^' + this.property.name + '-';\n } else {\n propertyNamePattern = '^' + this.property.name + '$';\n }\n const regex = new RegExp(propertyNamePattern, 'i');\n await computedStyleWidget.filterComputedStyles(regex);\n\n computedStyleWidget.input.setValue(this.property.name);\n computedStyleWidget.input.element.focus();\n }\n\n private copyCssDeclarationAsJs(): void {\n const cssDeclarationValue = getCssDeclarationAsJavascriptProperty(this.property);\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(cssDeclarationValue);\n Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.DECLARATION_AS_JS_VIA_CONTEXT_MENU);\n }\n\n private copyAllCssDeclarationAsJs(): void {\n const leadingProperties = this.#parentSection.style().leadingProperties();\n const cssDeclarationsAsJsProperties =\n leadingProperties.filter(property => !property.disabled).map(getCssDeclarationAsJavascriptProperty);\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(cssDeclarationsAsJsProperties.join(',\\n'));\n Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.ALL_DECLARATINS_AS_JS_VIA_CONTEXT_MENU);\n }\n\n private navigateToSource(element: Element, omitFocus?: boolean): void {\n if (!this.#parentSection.navigable) {\n return;\n }\n const propertyNameClicked = element === this.nameElement;\n const uiLocation = Bindings.CSSWorkspaceBinding.CSSWorkspaceBinding.instance().propertyUILocation(\n this.property, propertyNameClicked);\n if (uiLocation) {\n void Common.Revealer.reveal(uiLocation, omitFocus);\n }\n }\n\n startEditingValue(): void {\n const context: Context = {\n expanded: this.expanded,\n hasChildren: this.isExpandable(),\n isEditingName: false,\n originalProperty: this.property,\n previousContent: this.value,\n };\n\n // Grid definitions are often multiline. Instead of showing the authored text reformat it a little bit nicer.\n if (SDK.CSSMetadata.cssMetadata().isGridAreaDefiningProperty(this.name)) {\n const splitResult =\n TextUtils.TextUtils.Utils.splitStringByRegexes(this.value, [SDK.CSSMetadata.GridAreaRowRegex]);\n context.previousContent = splitResult.map(result => result.value.trim()).join('\\n');\n }\n\n this.#startEditing(context);\n }\n\n startEditingName(): void {\n const context: Context = {\n expanded: this.expanded,\n hasChildren: this.isExpandable(),\n isEditingName: true,\n originalProperty: this.property,\n previousContent: this.name.split('\\n').map(l => l.trim()).join('\\n'),\n };\n\n this.#startEditing(context);\n }\n\n #startEditing(context: Context): void {\n this.contextForTest = context;\n\n // FIXME: we don't allow editing of longhand properties under a shorthand right now.\n if (this.parent instanceof StylePropertyTreeElement && this.parent.isShorthand) {\n return;\n }\n\n const selectedElement = context.isEditingName ? this.nameElement : this.valueElement;\n if (!selectedElement) {\n return;\n }\n\n if (UI.UIUtils.isBeingEdited(selectedElement)) {\n return;\n }\n\n // Lie about our children to prevent expanding on double click and to collapse shorthands.\n this.setExpandable(false);\n\n selectedElement.parentElement?.classList.add('child-editing');\n selectedElement.textContent = context.previousContent; // remove color swatch and the like\n\n function pasteHandler(this: StylePropertyTreeElement, context: Context, event: Event): void {\n const clipboardEvent = (event as ClipboardEvent);\n const clipboardData = clipboardEvent.clipboardData;\n if (!clipboardData) {\n return;\n }\n\n const data = clipboardData.getData('Text');\n if (!data) {\n return;\n }\n const colonIdx = data.indexOf(':');\n if (colonIdx < 0) {\n return;\n }\n const name = data.substring(0, colonIdx).trim();\n const value = data.substring(colonIdx + 1).trim();\n\n event.preventDefault();\n\n if (typeof context.originalName === 'undefined') {\n if (this.nameElement) {\n context.originalName = this.nameElement.textContent || '';\n }\n\n if (this.valueElement) {\n context.originalValue = this.valueElement.textContent || '';\n }\n }\n this.property.name = name;\n this.property.value = value;\n if (this.nameElement) {\n this.nameElement.textContent = name;\n this.nameElement.normalize();\n }\n\n if (this.valueElement) {\n this.valueElement.textContent = value;\n this.valueElement.normalize();\n }\n\n const target = (event.target as HTMLElement);\n void this.editingCommitted(target.textContent || '', context, 'forward');\n }\n\n function blurListener(this: StylePropertyTreeElement, context: Context, event: Event): void {\n const target = (event.target as HTMLElement);\n let text: (string|null) = target.textContent;\n if (!context.isEditingName) {\n text = this.value || text;\n }\n void this.editingCommitted(text || '', context, '');\n }\n\n this.originalPropertyText = this.property.propertyText || '';\n\n this.parentPaneInternal.setEditingStyle(true, this);\n selectedElement.parentElement?.scrollIntoViewIfNeeded(false);\n\n this.prompt = new CSSPropertyPrompt(this, context.isEditingName, Array.from(this.#gridNames ?? []));\n this.prompt.setAutocompletionTimeout(0);\n\n this.prompt.addEventListener(UI.TextPrompt.Events.TEXT_CHANGED, () => {\n void this.applyFreeFlowStyleTextEdit(context);\n });\n\n const invalidString = this.property.getInvalidStringForInvalidProperty();\n if (invalidString) {\n UI.ARIAUtils.alert(invalidString);\n }\n\n const proxyElement = this.prompt.attachAndStartEditing(selectedElement, blurListener.bind(this, context));\n this.navigateToSource(selectedElement, true);\n\n proxyElement.addEventListener('keydown', this.editingNameValueKeyDown.bind(this, context), false);\n proxyElement.addEventListener('keypress', this.editingNameValueKeyPress.bind(this, context), false);\n if (context.isEditingName) {\n proxyElement.addEventListener('paste', pasteHandler.bind(this, context), false);\n proxyElement.addEventListener('contextmenu', this.handleContextMenuEvent.bind(this, context), false);\n }\n\n selectedElement.getComponentSelection()?.selectAllChildren(selectedElement);\n }\n\n private editingNameValueKeyDown(context: Context, event: Event): void {\n if (event.handled) {\n return;\n }\n\n const keyboardEvent = (event as KeyboardEvent);\n const target = (keyboardEvent.target as HTMLElement);\n let result;\n if ((keyboardEvent.key === 'Enter' && !keyboardEvent.shiftKey) ||\n (context.isEditingName && keyboardEvent.key === ' ')) {\n result = 'forward';\n } else if (\n keyboardEvent.keyCode === UI.KeyboardShortcut.Keys.Esc.code ||\n keyboardEvent.key === Platform.KeyboardUtilities.ESCAPE_KEY) {\n result = 'cancel';\n } else if (\n !context.isEditingName && this.newProperty &&\n keyboardEvent.keyCode === UI.KeyboardShortcut.Keys.Backspace.code) {\n // For a new property, when Backspace is pressed at the beginning of new property value, move back to the property name.\n const selection = target.getComponentSelection();\n if (selection && selection.isCollapsed && !selection.focusOffset) {\n event.preventDefault();\n result = 'backward';\n }\n } else if (keyboardEvent.key === 'Tab') {\n result = keyboardEvent.shiftKey ? 'backward' : 'forward';\n event.preventDefault();\n }\n\n if (result) {\n switch (result) {\n case 'cancel':\n this.editingCancelled(null, context);\n break;\n case 'forward':\n case 'backward':\n void this.editingCommitted(target.textContent || '', context, result);\n break;\n }\n\n event.consume();\n return;\n }\n }\n\n private editingNameValueKeyPress(context: Context, event: Event): void {\n function shouldCommitValueSemicolon(text: string, cursorPosition: number): boolean {\n // FIXME: should this account for semicolons inside comments?\n let openQuote = '';\n for (let i = 0; i < cursorPosition; ++i) {\n const ch = text[i];\n if (ch === '\\\\' && openQuote !== '') {\n ++i;\n } // skip next character inside string\n else if (!openQuote && (ch === '\"' || ch === '\\'')) {\n openQuote = ch;\n } else if (openQuote === ch) {\n openQuote = '';\n }\n }\n return !openQuote;\n }\n\n const keyboardEvent = (event as KeyboardEvent);\n const target = (keyboardEvent.target as HTMLElement);\n const keyChar = String.fromCharCode(keyboardEvent.charCode);\n const selectionLeftOffset = this.#selectionLeftOffset(target);\n const isFieldInputTerminated =\n (context.isEditingName ? keyChar === ':' :\n keyChar === ';' && selectionLeftOffset !== null &&\n shouldCommitValueSemicolon(target.textContent || '', selectionLeftOffset));\n if (isFieldInputTerminated) {\n // Enter or colon (for name)/semicolon outside of string (for value).\n event.consume(true);\n void this.editingCommitted(target.textContent || '', context, 'forward');\n return;\n }\n }\n\n /** @returns Selection offset relative to `element` */\n #selectionLeftOffset(element: HTMLElement): number|null {\n const selection = element.getComponentSelection();\n if (!selection?.containsNode(element, true)) {\n return null;\n }\n\n let leftOffset = selection.anchorOffset;\n let node: ChildNode|(Node | null) = selection.anchorNode;\n\n while (node !== element) {\n while (node?.previousSibling) {\n node = node.previousSibling;\n leftOffset += node.textContent?.length ?? 0;\n }\n node = node?.parentNodeOrShadowHost() ?? null;\n }\n\n return leftOffset;\n }\n\n private async applyFreeFlowStyleTextEdit(context: Context): Promise {\n if (!this.prompt || !this.parentPaneInternal.node()) {\n return;\n }\n\n const enteredText = this.prompt.text();\n if (context.isEditingName && enteredText.includes(':')) {\n void this.editingCommitted(enteredText, context, 'forward');\n return;\n }\n\n const valueText = this.prompt.textWithCurrentSuggestion();\n if (valueText.includes(';')) {\n return;\n }\n // Prevent destructive side-effects during live-edit. crbug.com/433889\n const parentNode = this.parentPaneInternal.node();\n if (parentNode) {\n const isPseudo = Boolean(parentNode.pseudoType());\n if (isPseudo) {\n if (this.name.toLowerCase() === 'content') {\n return;\n }\n const lowerValueText = valueText.trim().toLowerCase();\n if (lowerValueText.startsWith('content:') || lowerValueText === 'display: none') {\n return;\n }\n }\n }\n\n if (context.isEditingName) {\n if (valueText.includes(':')) {\n await this.applyStyleText(valueText, false);\n } else if (this.hasBeenEditedIncrementally) {\n await this.applyOriginalStyle(context);\n }\n } else {\n if (this.nameElement) {\n await this.applyStyleText(`${this.nameElement.textContent}: ${valueText}`, false);\n }\n }\n }\n\n kickFreeFlowStyleEditForTest(): Promise {\n const context = this.contextForTest;\n return this.applyFreeFlowStyleTextEdit((context as Context));\n }\n\n editingEnded(context: Context): void {\n this.setExpandable(context.hasChildren);\n if (context.expanded) {\n this.expand();\n }\n const editedElement = context.isEditingName ? this.nameElement : this.valueElement;\n // The proxyElement has been deleted, no need to remove listener.\n if (editedElement && editedElement.parentElement) {\n editedElement.parentElement.classList.remove('child-editing');\n }\n\n this.parentPaneInternal.setEditingStyle(false);\n }\n\n editingCancelled(element: Element|null, context: Context): void {\n this.removePrompt();\n\n if (this.hasBeenEditedIncrementally) {\n void this.applyOriginalStyle(context);\n } else if (this.newProperty && this.treeOutline) {\n this.treeOutline.removeChild(this);\n }\n this.updateTitle();\n\n // This should happen last, as it clears the info necessary to restore the property value after [Page]Up/Down changes.\n this.editingEnded(context);\n }\n\n private async applyOriginalStyle(context: Context): Promise {\n await this.applyStyleText(this.originalPropertyText, false, context.originalProperty);\n }\n\n private findSibling(moveDirection: string): StylePropertyTreeElement|null {\n let target: (StylePropertyTreeElement|null)|this = this;\n do {\n const sibling: UI.TreeOutline.TreeElement|null =\n moveDirection === 'forward' ? target.nextSibling : target.previousSibling;\n target = sibling instanceof StylePropertyTreeElement ? sibling : null;\n } while (target && target.inherited());\n\n return target;\n }\n\n private async editingCommitted(userInput: string, context: Context, moveDirection: string): Promise {\n this.removePrompt();\n this.editingEnded(context);\n const isEditingName = context.isEditingName;\n // If the underlying property has been ripped out, always assume that the value having been entered was\n // a name-value pair and attempt to process it via the SDK.\n if (!this.nameElement || !this.valueElement) {\n return;\n }\n\n const nameElementValue = this.nameElement.textContent || '';\n const nameValueEntered = (isEditingName && nameElementValue.includes(':')) || !this.property;\n\n // Determine where to move to before making changes\n let createNewProperty = false;\n let moveToSelector = false;\n const isDataPasted = typeof context.originalName !== 'undefined';\n const isDirtyViaPaste = isDataPasted &&\n (this.nameElement.textContent !== context.originalName ||\n this.valueElement.textContent !== context.originalValue);\n const isPropertySplitPaste =\n isDataPasted && isEditingName && this.valueElement.textContent !== context.originalValue;\n let moveTo: (StylePropertyTreeElement|null)|this = this;\n const moveToOther = (isEditingName !== (moveDirection === 'forward'));\n const abandonNewProperty = this.newProperty && !userInput && (moveToOther || isEditingName);\n if (moveDirection === 'forward' && (!isEditingName || isPropertySplitPaste) ||\n moveDirection === 'backward' && isEditingName) {\n moveTo = moveTo.findSibling(moveDirection);\n if (!moveTo) {\n if (moveDirection === 'forward' && (!this.newProperty || userInput)) {\n createNewProperty = true;\n } else if (moveDirection === 'backward') {\n moveToSelector = true;\n }\n }\n }\n\n // Make the Changes and trigger the moveToNextCallback after updating.\n let moveToIndex = -1;\n if (moveTo !== null && this.treeOutline) {\n moveToIndex = this.treeOutline.rootElement().indexOfChild((moveTo as UI.TreeOutline.TreeElement));\n }\n const blankInput = Platform.StringUtilities.isWhitespace(userInput);\n const shouldCommitNewProperty = this.newProperty &&\n (isPropertySplitPaste || moveToOther || (!moveDirection && !isEditingName) || (isEditingName && blankInput) ||\n nameValueEntered);\n if (((userInput !== context.previousContent || isDirtyViaPaste) && !this.newProperty) || shouldCommitNewProperty) {\n let propertyText;\n if (nameValueEntered) {\n propertyText = this.nameElement.textContent;\n } else if (\n blankInput ||\n (this.newProperty && Platform.StringUtilities.isWhitespace(this.valueElement.textContent || ''))) {\n propertyText = '';\n } else {\n if (isEditingName) {\n propertyText = userInput + ': ' + this.property.value;\n } else {\n propertyText = this.property.name + ': ' + userInput;\n }\n }\n await this.applyStyleText(propertyText || '', true);\n moveToNextCallback.call(this, this.newProperty, !blankInput, this.#parentSection);\n } else {\n if (isEditingName) {\n this.property.name = userInput;\n } else {\n this.property.value = userInput;\n }\n if (!isDataPasted && !this.newProperty) {\n this.updateTitle();\n }\n moveToNextCallback.call(this, this.newProperty, false, this.#parentSection);\n }\n\n /**\n * The Callback to start editing the next/previous property/selector.\n */\n function moveToNextCallback(\n this: StylePropertyTreeElement, alreadyNew: boolean, valueChanged: boolean,\n section: StylePropertiesSection): void {\n if (!moveDirection) {\n this.parentPaneInternal.resetFocus();\n return;\n }\n\n // User just tabbed through without changes.\n if (moveTo && moveTo.parent) {\n if (isEditingName) {\n moveTo.startEditingValue();\n } else {\n moveTo.startEditingName();\n }\n return;\n }\n\n // User has made a change then tabbed, wiping all the original treeElements.\n // Recalculate the new treeElement for the same property we were going to edit next.\n if (moveTo && !moveTo.parent) {\n const rootElement = section.propertiesTreeOutline.rootElement();\n if (moveDirection === 'forward' && blankInput && !isEditingName) {\n --moveToIndex;\n }\n if (moveToIndex >= rootElement.childCount() && !this.newProperty) {\n createNewProperty = true;\n } else {\n const treeElement =\n (moveToIndex >= 0 ? rootElement.childAt(moveToIndex) : null) as StylePropertyTreeElement | null;\n if (treeElement) {\n if (alreadyNew && blankInput) {\n if (moveDirection === 'forward') {\n treeElement.startEditingName();\n } else {\n treeElement.startEditingValue();\n }\n } else if (!isEditingName || isPropertySplitPaste) {\n treeElement.startEditingName();\n } else {\n treeElement.startEditingValue();\n }\n return;\n }\n if (!alreadyNew) {\n moveToSelector = true;\n }\n }\n }\n\n // Create a new attribute in this section (or move to next editable selector if possible).\n if (createNewProperty) {\n if (alreadyNew && !valueChanged && (isEditingName !== (moveDirection === 'backward'))) {\n return;\n }\n\n section.addNewBlankProperty().startEditingName();\n return;\n }\n\n if (abandonNewProperty) {\n moveTo = this.findSibling(moveDirection);\n const sectionToEdit = (moveTo || moveDirection === 'backward') ? section : section.nextEditableSibling();\n if (sectionToEdit) {\n if (sectionToEdit.style().parentRule) {\n sectionToEdit.startEditingSelector();\n } else {\n sectionToEdit.moveEditorFromSelector(moveDirection);\n }\n }\n return;\n }\n\n if (moveToSelector) {\n if (section.style().parentRule) {\n section.startEditingSelector();\n } else {\n section.moveEditorFromSelector(moveDirection);\n }\n }\n }\n }\n\n private removePrompt(): void {\n // BUG 53242. This cannot go into editingEnded(), as it should always happen first for any editing outcome.\n if (this.prompt) {\n this.prompt.detach();\n this.prompt = null;\n }\n }\n\n styleTextAppliedForTest(): void {\n }\n\n applyStyleText(styleText: string, majorChange: boolean, property?: SDK.CSSProperty.CSSProperty|null): Promise {\n return this.applyStyleThrottler.schedule(this.innerApplyStyleText.bind(this, styleText, majorChange, property));\n }\n\n private async innerApplyStyleText(\n styleText: string, majorChange: boolean, property?: SDK.CSSProperty.CSSProperty|null): Promise {\n // this.property might have been nulled at the end of the last innerApplyStyleText\n if (!this.treeOutline || !this.property) {\n return;\n }\n\n const oldStyleRange = this.style.range;\n if (!oldStyleRange) {\n return;\n }\n\n const hasBeenEditedIncrementally = this.hasBeenEditedIncrementally;\n styleText = styleText.replace(/[\\xA0\\t]/g, ' ').trim(); // Replace   with whitespace.\n if (!styleText.length && majorChange && this.newProperty && !hasBeenEditedIncrementally) {\n // The user deleted everything and never applied a new property value via Up/Down scrolling/live editing, so remove the tree element and update.\n this.parent && this.parent.removeChild(this);\n return;\n }\n\n const currentNode = this.parentPaneInternal.node();\n this.parentPaneInternal.setUserOperation(true);\n\n styleText += Platform.StringUtilities.findUnclosedCssQuote(styleText);\n styleText += ')'.repeat(Platform.StringUtilities.countUnmatchedLeftParentheses(styleText));\n\n // Append a \";\" if the new text does not end in \";\".\n // FIXME: this does not handle trailing comments.\n if (styleText.length && !/;\\s*$/.test(styleText)) {\n styleText += ';';\n }\n\n const overwriteProperty = !this.newProperty || hasBeenEditedIncrementally;\n let success: boolean = await this.property.setText(styleText, majorChange, overwriteProperty);\n // Revert to the original text if applying the new text failed\n if (hasBeenEditedIncrementally && majorChange && !success) {\n majorChange = false;\n success = await this.property.setText(this.originalPropertyText, majorChange, overwriteProperty);\n }\n this.parentPaneInternal.setUserOperation(false);\n\n // TODO: using this.property.index to access its containing StyleDeclaration's property will result in\n // off-by-1 errors when the containing StyleDeclaration's respective property has already been deleted.\n // These referencing logic needs to be updated to be more robust.\n const updatedProperty = property || this.style.propertyAt(this.property.index);\n const isPropertyWithinBounds = this.property.index < this.style.allProperties().length;\n if (!success || (!updatedProperty && isPropertyWithinBounds)) {\n if (majorChange) {\n // It did not apply, cancel editing.\n if (this.newProperty) {\n this.treeOutline.removeChild(this);\n } else {\n this.updateTitle();\n }\n }\n this.styleTextAppliedForTest();\n return;\n }\n if (updatedProperty) {\n this.listItemElement.classList.toggle('changed', this.isPropertyChanged(updatedProperty));\n this.parentPane().updateChangeStatus();\n }\n\n this.matchedStylesInternal.resetActiveProperties();\n this.hasBeenEditedIncrementally = true;\n\n // null check for updatedProperty before setting this.property as the code never expects this.property to be undefined or null.\n // This occurs when deleting the last index of a StylePropertiesSection as this.style._allProperties array gets updated\n // before we index it when setting the value for updatedProperty\n const deleteProperty = majorChange && !styleText.length;\n if (deleteProperty) {\n this.#parentSection.resetToolbars();\n } else if (!deleteProperty && updatedProperty) {\n this.property = updatedProperty;\n }\n\n if (currentNode === this.node()) {\n this.updatePane();\n }\n\n this.styleTextAppliedForTest();\n }\n\n override ondblclick(): boolean {\n return true; // handled\n }\n\n override isEventWithinDisclosureTriangle(event: Event): boolean {\n return event.target === this.expandElement;\n }\n}\nexport interface Context {\n expanded: boolean;\n hasChildren: boolean;\n isEditingName: boolean;\n originalProperty?: SDK.CSSProperty.CSSProperty;\n originalName?: string;\n originalValue?: string;\n previousContent: string;\n}\n"]} \ No newline at end of file +{"version":3,"file":"StylePropertyTreeElement.js","sourceRoot":"","sources":["../../../../../../front_end/panels/elements/StylePropertyTreeElement.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2018 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as Host from '../../core/host/host.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as Root from '../../core/root/root.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as Bindings from '../../models/bindings/bindings.js';\nimport * as TextUtils from '../../models/text_utils/text_utils.js';\nimport type * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';\nimport * as IconButton from '../../ui/components/icon_button/icon_button.js';\nimport * as ColorPicker from '../../ui/legacy/components/color_picker/color_picker.js';\nimport * as InlineEditor from '../../ui/legacy/components/inline_editor/inline_editor.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport {\n BezierPopoverIcon,\n ColorSwatchPopoverIcon,\n ColorSwatchPopoverIconEvents,\n ShadowEvents,\n ShadowSwatchPopoverHelper,\n} from './ColorSwatchPopoverIcon.js';\nimport * as ElementsComponents from './components/components.js';\nimport {cssRuleValidatorsMap, type Hint} from './CSSRuleValidator.js';\nimport {ElementsPanel} from './ElementsPanel.js';\nimport {\n type AnchorFunctionMatch,\n AnchorFunctionMatcher,\n AngleMatch,\n AngleMatcher,\n type BezierMatch,\n BezierMatcher,\n ColorMatch,\n ColorMatcher,\n ColorMixMatch,\n ColorMixMatcher,\n type FontMatch,\n FontMatcher,\n type GridTemplateMatch,\n GridTemplateMatcher,\n type LengthMatch,\n LengthMatcher,\n type LightDarkColorMatch,\n LightDarkColorMatcher,\n type LinearGradientMatch,\n LinearGradientMatcher,\n type LinkableNameMatch,\n LinkableNameMatcher,\n LinkableNameProperties,\n type PositionAnchorMatch,\n PositionAnchorMatcher,\n type ShadowMatch,\n ShadowMatcher,\n ShadowType,\n} from './PropertyMatchers.js';\nimport {type MatchRenderer, Renderer, RenderingContext, StringRenderer, URLRenderer} from './PropertyRenderer.js';\nimport {StyleEditorWidget} from './StyleEditorWidget.js';\nimport {type StylePropertiesSection} from './StylePropertiesSection.js';\nimport {getCssDeclarationAsJavascriptProperty} from './StylePropertyUtils.js';\nimport {\n CSSPropertyPrompt,\n REGISTERED_PROPERTY_SECTION_NAME,\n StylesSidebarPane,\n} from './StylesSidebarPane.js';\n\nconst ASTUtils = SDK.CSSPropertyParser.ASTUtils;\nconst FlexboxEditor = ElementsComponents.StylePropertyEditor.FlexboxEditor;\nconst GridEditor = ElementsComponents.StylePropertyEditor.GridEditor;\n\nexport const activeHints = new WeakMap();\n\nconst UIStrings = {\n /**\n *@description Text in Color Swatch Popover Icon of the Elements panel\n */\n shiftClickToChangeColorFormat: 'Shift + Click to change color format.',\n /**\n *@description Swatch icon element title in Color Swatch Popover Icon of the Elements panel\n *@example {Shift + Click to change color format.} PH1\n */\n openColorPickerS: 'Open color picker. {PH1}',\n /**\n *@description Context menu item for style property in edit mode\n */\n togglePropertyAndContinueEditing: 'Toggle property and continue editing',\n /**\n *@description Context menu item for style property in edit mode\n */\n revealInSourcesPanel: 'Reveal in Sources panel',\n /**\n *@description A context menu item in Styles panel to copy CSS declaration\n */\n copyDeclaration: 'Copy declaration',\n /**\n *@description A context menu item in Styles panel to copy CSS property\n */\n copyProperty: 'Copy property',\n /**\n *@description A context menu item in the Watch Expressions Sidebar Pane of the Sources panel and Network pane request.\n */\n copyValue: 'Copy value',\n /**\n *@description A context menu item in Styles panel to copy CSS rule\n */\n copyRule: 'Copy rule',\n /**\n *@description A context menu item in Styles panel to copy all CSS declarations\n */\n copyAllDeclarations: 'Copy all declarations',\n /**\n *@description A context menu item in Styles panel to copy all the CSS changes\n */\n copyAllCSSChanges: 'Copy all CSS changes',\n /**\n *@description A context menu item in Styles panel to view the computed CSS property value.\n */\n viewComputedValue: 'View computed value',\n /**\n * @description Title of the button that opens the flexbox editor in the Styles panel.\n */\n flexboxEditorButton: 'Open `flexbox` editor',\n /**\n * @description Title of the button that opens the CSS Grid editor in the Styles panel.\n */\n gridEditorButton: 'Open `grid` editor',\n /**\n *@description A context menu item in Styles panel to copy CSS declaration as JavaScript property.\n */\n copyCssDeclarationAsJs: 'Copy declaration as JS',\n /**\n *@description A context menu item in Styles panel to copy all declarations of CSS rule as JavaScript properties.\n */\n copyAllCssDeclarationsAsJs: 'Copy all declarations as JS',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/elements/StylePropertyTreeElement.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nconst parentMap = new WeakMap();\n\ninterface StylePropertyTreeElementParams {\n stylesPane: StylesSidebarPane;\n section: StylePropertiesSection;\n matchedStyles: SDK.CSSMatchedStyles.CSSMatchedStyles;\n property: SDK.CSSProperty.CSSProperty;\n isShorthand: boolean;\n inherited: boolean;\n overloaded: boolean;\n newProperty: boolean;\n}\n\nexport class VariableRenderer implements MatchRenderer {\n readonly #treeElement: StylePropertyTreeElement;\n readonly #style: SDK.CSSStyleDeclaration.CSSStyleDeclaration;\n constructor(treeElement: StylePropertyTreeElement, style: SDK.CSSStyleDeclaration.CSSStyleDeclaration) {\n this.#treeElement = treeElement;\n this.#style = style;\n }\n\n matcher(): SDK.CSSPropertyParser.VariableMatcher {\n return new SDK.CSSPropertyParser.VariableMatcher(this.computedText.bind(this));\n }\n\n resolveVariable(match: SDK.CSSPropertyParser.VariableMatch): SDK.CSSMatchedStyles.CSSVariableValue|null {\n return this.#matchedStyles.computeCSSVariable(this.#style, match.name);\n }\n\n fallbackValue(match: SDK.CSSPropertyParser.VariableMatch): string|null {\n if (match.fallback.length === 0 ||\n match.matching.hasUnresolvedVarsRange(match.fallback[0], match.fallback[match.fallback.length - 1])) {\n return null;\n }\n return match.matching.getComputedTextRange(match.fallback[0], match.fallback[match.fallback.length - 1]);\n }\n\n // clang-format off\n computedText(match: SDK.CSSPropertyParser.VariableMatch): string|null {\n return this.resolveVariable(match)?.value ?? this.fallbackValue(match);\n }\n // clang-format on\n\n render(match: SDK.CSSPropertyParser.VariableMatch, context: RenderingContext): Node[] {\n const renderedFallback = match.fallback.length > 0 ? Renderer.render(match.fallback, context) : undefined;\n\n const {declaration, value: variableValue} = this.resolveVariable(match) ?? {};\n const fromFallback = !variableValue;\n const computedValue = variableValue ?? this.fallbackValue(match);\n\n const varSwatch = new InlineEditor.LinkSwatch.CSSVarSwatch();\n varSwatch.data = {\n computedValue,\n variableName: match.name,\n fromFallback,\n fallbackText: match.fallback.map(n => context.ast.text(n)).join(' '),\n onLinkActivate: name => this.#handleVarDefinitionActivate(declaration ?? name),\n };\n\n if (renderedFallback?.nodes.length) {\n // When slotting someting into the fallback slot, also emit text children so that .textContent produces the\n // correct var value.\n varSwatch.appendChild(document.createTextNode(`var(${match.name}`));\n const span = varSwatch.appendChild(document.createElement('span'));\n span.appendChild(document.createTextNode(', '));\n span.slot = 'fallback';\n renderedFallback.nodes.forEach(n => span.appendChild(n));\n varSwatch.appendChild(document.createTextNode(')'));\n } else {\n UI.UIUtils.createTextChild(varSwatch, match.text);\n }\n\n if (varSwatch.link) {\n this.#pane.addPopover(varSwatch.link, {\n contents: () => this.#treeElement.getVariablePopoverContents(match.name, variableValue ?? null),\n jslogContext: 'elements.css-var',\n });\n }\n\n const color = computedValue && Common.Color.parse(computedValue);\n if (!color) {\n return [varSwatch];\n }\n\n const colorSwatch = new ColorRenderer(this.#treeElement).renderColorSwatch(color, varSwatch);\n context.addControl('color', colorSwatch);\n\n if (fromFallback) {\n renderedFallback?.cssControls.get('color')?.forEach(\n innerSwatch => innerSwatch.addEventListener(InlineEditor.ColorSwatch.ColorChangedEvent.eventName, ev => {\n colorSwatch.setColor(ev.data.color);\n }));\n }\n\n return [colorSwatch];\n }\n\n get #pane(): StylesSidebarPane {\n return this.#treeElement.parentPane();\n }\n\n get #matchedStyles(): SDK.CSSMatchedStyles.CSSMatchedStyles {\n return this.#treeElement.matchedStyles();\n }\n\n #handleVarDefinitionActivate(variable: string|SDK.CSSProperty.CSSProperty|\n SDK.CSSMatchedStyles.CSSRegisteredProperty): void {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.CustomPropertyLinkClicked);\n Host.userMetrics.swatchActivated(Host.UserMetrics.SwatchType.VAR_LINK);\n if (variable instanceof SDK.CSSProperty.CSSProperty) {\n this.#pane.revealProperty(variable);\n } else if (variable instanceof SDK.CSSMatchedStyles.CSSRegisteredProperty) {\n this.#pane.jumpToProperty('initial-value', variable.propertyName(), REGISTERED_PROPERTY_SECTION_NAME);\n } else {\n this.#pane.jumpToProperty(variable) ||\n this.#pane.jumpToProperty('initial-value', variable, REGISTERED_PROPERTY_SECTION_NAME);\n }\n }\n}\n\nexport class LinearGradientRenderer implements MatchRenderer {\n matcher(): SDK.CSSPropertyParser.Matcher {\n return new LinearGradientMatcher();\n }\n render(match: LinearGradientMatch, context: RenderingContext): Node[] {\n const children = ASTUtils.children(match.node);\n const {nodes, cssControls} = Renderer.render(children, context);\n const angles = cssControls.get('angle');\n const angle = angles?.length === 1 ? angles[0] : null;\n\n if (angle instanceof InlineEditor.CSSAngle.CSSAngle) {\n angle.updateProperty(context.matchedResult.getComputedText(match.node));\n const args = ASTUtils.callArgs(match.node);\n const angleNode = args[0]?.find(node => context.matchedResult.getMatch(node) instanceof AngleMatch);\n const angleMatch = angleNode && context.matchedResult.getMatch(angleNode);\n if (angleMatch) {\n angle.addEventListener(InlineEditor.InlineEditorUtils.ValueChangedEvent.eventName, ev => {\n angle.updateProperty(\n context.matchedResult.getComputedText(match.node, new Map([[angleMatch, ev.data.value]])));\n });\n }\n }\n return nodes;\n }\n}\n\nexport class ColorRenderer implements MatchRenderer {\n constructor(private readonly treeElement: StylePropertyTreeElement) {\n }\n\n matcher(): ColorMatcher {\n const getCurrentColorCallback = (): string|null => this.treeElement.getComputedStyle('color');\n return new ColorMatcher(getCurrentColorCallback);\n }\n\n #getValueChild(match: ColorMatch, context: RenderingContext):\n {valueChild: HTMLSpanElement, cssControls?: SDK.CSSPropertyParser.CSSControlMap} {\n const valueChild = document.createElement('span');\n if (match.node.name === 'ColorLiteral' || match.node.name === 'ValueName') {\n valueChild.appendChild(document.createTextNode(match.text));\n return {valueChild};\n }\n const {cssControls} = Renderer.renderInto(ASTUtils.children(match.node), context, valueChild);\n return {valueChild, cssControls};\n }\n\n render(match: ColorMatch, context: RenderingContext): Node[] {\n const {valueChild, cssControls} = this.#getValueChild(match, context);\n let colorText = context.matchedResult.getComputedText(match.node);\n // Evaluate relative color values\n if (match.node.name === 'CallExpression' && colorText.match(/^[^)]*\\(\\W*from\\W+/) &&\n !context.matchedResult.hasUnresolvedVars(match.node) && CSS.supports('color', colorText)) {\n const fakeSpan = document.body.appendChild(document.createElement('span'));\n fakeSpan.style.backgroundColor = colorText;\n colorText = window.getComputedStyle(fakeSpan).backgroundColor?.toString() || colorText;\n fakeSpan.remove();\n }\n\n // Now try render a color swatch if the result is parsable.\n const color = Common.Color.parse(colorText);\n if (!color) {\n return [document.createTextNode(colorText)];\n }\n const swatch = this.renderColorSwatch(color, valueChild);\n context.addControl('color', swatch);\n\n // For hsl/hwb colors, hook up the angle swatch for the hue.\n if (cssControls && match.node.name === 'CallExpression' &&\n context.ast.text(match.node.getChild('Callee')).match(/^(hsla?|hwba?)/)) {\n const [angle] = cssControls.get('angle') ?? [];\n if (angle instanceof InlineEditor.CSSAngle.CSSAngle) {\n angle.updateProperty(swatch.getColor()?.asString() ?? '');\n angle.addEventListener(InlineEditor.InlineEditorUtils.ValueChangedEvent.eventName, ev => {\n const hue = Common.Color.parseHueNumeric(ev.data.value);\n const color = swatch.getColor();\n if (!hue || !color) {\n return;\n }\n if (color.is(Common.Color.Format.HSL) || color.is(Common.Color.Format.HSLA)) {\n swatch.setColor(new Common.Color.HSL(hue, color.s, color.l, color.alpha));\n } else if (color.is(Common.Color.Format.HWB) || color.is(Common.Color.Format.HWBA)) {\n swatch.setColor(new Common.Color.HWB(hue, color.w, color.b, color.alpha));\n }\n angle.updateProperty(swatch.getColor()?.asString() ?? '');\n });\n }\n }\n return [swatch];\n }\n\n renderColorSwatch(color: Common.Color.Color|undefined, valueChild?: Node): InlineEditor.ColorSwatch.ColorSwatch {\n const editable = this.treeElement.editable();\n const shiftClickMessage = i18nString(UIStrings.shiftClickToChangeColorFormat);\n const tooltip = editable ? i18nString(UIStrings.openColorPickerS, {PH1: shiftClickMessage}) : '';\n\n const swatch = new InlineEditor.ColorSwatch.ColorSwatch(tooltip);\n swatch.setReadonly(!editable);\n if (color) {\n swatch.renderColor(color);\n }\n\n if (!valueChild) {\n valueChild = swatch.createChild('span');\n if (color) {\n valueChild.textContent = color.getAuthoredText() ?? color.asString();\n }\n }\n swatch.appendChild(valueChild);\n\n const onColorChanged = (): void => {\n void this.treeElement.applyStyleText(this.treeElement.renderedPropertyText(), false);\n };\n\n swatch.addEventListener(InlineEditor.ColorSwatch.ClickEvent.eventName, () => {\n Host.userMetrics.swatchActivated(Host.UserMetrics.SwatchType.COLOR);\n });\n swatch.addEventListener(InlineEditor.ColorSwatch.ColorChangedEvent.eventName, onColorChanged);\n\n if (editable) {\n const swatchIcon =\n new ColorSwatchPopoverIcon(this.treeElement, this.treeElement.parentPane().swatchPopoverHelper(), swatch);\n swatchIcon.addEventListener(ColorSwatchPopoverIconEvents.COLOR_CHANGED, ev => {\n const color = Common.Color.parse(ev.data);\n if (color) {\n swatch.setColorText(color);\n }\n });\n void this.#addColorContrastInfo(swatchIcon);\n }\n\n return swatch;\n }\n\n async #addColorContrastInfo(swatchIcon: ColorSwatchPopoverIcon): Promise {\n const cssModel = this.treeElement.parentPane().cssModel();\n const node = this.treeElement.node();\n if (this.treeElement.property.name !== 'color' || !cssModel || !node || typeof node.id === 'undefined') {\n return;\n }\n const contrastInfo = new ColorPicker.ContrastInfo.ContrastInfo(await cssModel.getBackgroundColors(node.id));\n swatchIcon.setContrastInfo(contrastInfo);\n }\n}\n\nexport class LightDarkColorRenderer implements MatchRenderer {\n readonly #treeElement: StylePropertyTreeElement;\n constructor(treeElement: StylePropertyTreeElement) {\n this.#treeElement = treeElement;\n }\n\n matcher(): LightDarkColorMatcher {\n return new LightDarkColorMatcher();\n }\n\n render(match: LightDarkColorMatch, context: RenderingContext): Node[] {\n const content = document.createElement('span');\n content.appendChild(document.createTextNode('light-dark('));\n const light = content.appendChild(document.createElement('span'));\n content.appendChild(document.createTextNode(', '));\n const dark = content.appendChild(document.createElement('span'));\n content.appendChild(document.createTextNode(')'));\n const {cssControls: lightControls} = Renderer.renderInto(match.light, context, light);\n const {cssControls: darkControls} = Renderer.renderInto(match.dark, context, dark);\n\n if (context.matchedResult.hasUnresolvedVars(match.node)) {\n return [content];\n }\n\n const color = Common.Color.parse(\n context.matchedResult.getComputedTextRange(match.light[0], match.light[match.light.length - 1]));\n if (!color) {\n return [content];\n }\n\n // Pass an undefined color here to insert a placeholder swatch that will be filled in from the async\n // applyColorScheme below.\n const colorSwatch = new ColorRenderer(this.#treeElement).renderColorSwatch(undefined, content);\n context.addControl('color', colorSwatch);\n void this.applyColorScheme(match, context, colorSwatch, light, dark, lightControls, darkControls);\n\n return [colorSwatch];\n }\n\n async applyColorScheme(\n match: LightDarkColorMatch, context: RenderingContext, colorSwatch: InlineEditor.ColorSwatch.ColorSwatch,\n light: HTMLSpanElement, dark: HTMLSpanElement, lightControls: SDK.CSSPropertyParser.CSSControlMap,\n darkControls: SDK.CSSPropertyParser.CSSControlMap): Promise {\n const activeColor = await this.#activeColor(match);\n if (!activeColor) {\n return;\n }\n\n const activeColorSwatches = (activeColor === match.light ? lightControls : darkControls).get('color');\n activeColorSwatches?.forEach(\n swatch => swatch.addEventListener(\n InlineEditor.ColorSwatch.ColorChangedEvent.eventName, ev => colorSwatch.setColor(ev.data.color)));\n const inactiveColor = (activeColor === match.light) ? dark : light;\n const colorText = context.matchedResult.getComputedTextRange(activeColor[0], activeColor[activeColor.length - 1]);\n const color = colorText && Common.Color.parse(colorText);\n inactiveColor.style.textDecoration = 'line-through';\n if (color) {\n colorSwatch.renderColor(color);\n }\n }\n\n // Returns the syntax node group corresponding the active color scheme:\n // If the element has color-scheme set to light or dark, return the respective group.\n // If the element has color-scheme set to both light and dark, we check the prefers-color-scheme media query.\n async #activeColor(match: LightDarkColorMatch): Promise {\n const activeColorSchemes = this.#treeElement.getComputedStyle('color-scheme')?.split(' ') ?? [];\n const hasLight = activeColorSchemes.includes(SDK.CSSModel.ColorScheme.LIGHT);\n const hasDark = activeColorSchemes.includes(SDK.CSSModel.ColorScheme.DARK);\n\n if (!hasDark && !hasLight) {\n return match.light;\n }\n if (!hasLight) {\n return match.dark;\n }\n if (!hasDark) {\n return match.light;\n }\n\n switch (await this.#treeElement.parentPane().cssModel()?.colorScheme()) {\n case SDK.CSSModel.ColorScheme.DARK:\n return match.dark;\n case SDK.CSSModel.ColorScheme.LIGHT:\n return match.light;\n default:\n return undefined;\n }\n }\n}\n\nexport class ColorMixRenderer implements MatchRenderer {\n #pane: StylesSidebarPane;\n constructor(pane: StylesSidebarPane) {\n this.#pane = pane;\n }\n\n render(match: ColorMixMatch, context: RenderingContext): Node[] {\n const hookUpColorArg = (node: Node, onChange: (newColorText: string) => void): boolean => {\n if (node instanceof InlineEditor.ColorMixSwatch.ColorMixSwatch ||\n node instanceof InlineEditor.ColorSwatch.ColorSwatch) {\n if (node instanceof InlineEditor.ColorSwatch.ColorSwatch) {\n node.addEventListener(\n InlineEditor.ColorSwatch.ColorChangedEvent.eventName,\n ev => onChange(ev.data.color.getAuthoredText() ?? ev.data.color.asString()));\n } else {\n node.addEventListener(InlineEditor.ColorMixSwatch.Events.COLOR_CHANGED, ev => onChange(ev.data.text));\n }\n const color = node.getText();\n if (color) {\n onChange(color);\n return true;\n }\n }\n return false;\n };\n\n const contentChild = document.createElement('span');\n contentChild.appendChild(document.createTextNode('color-mix('));\n Renderer.renderInto(match.space, context, contentChild);\n contentChild.appendChild(document.createTextNode(', '));\n const color1 = Renderer.renderInto(match.color1, context, contentChild).cssControls.get('color') ?? [];\n contentChild.appendChild(document.createTextNode(', '));\n const color2 = Renderer.renderInto(match.color2, context, contentChild).cssControls.get('color') ?? [];\n contentChild.appendChild(document.createTextNode(')'));\n\n if (context.matchedResult.hasUnresolvedVars(match.node) || color1.length !== 1 || color2.length !== 1) {\n return [contentChild];\n }\n\n const swatch = new InlineEditor.ColorMixSwatch.ColorMixSwatch();\n if (!hookUpColorArg(color1[0], text => swatch.setFirstColor(text)) ||\n !hookUpColorArg(color2[0], text => swatch.setSecondColor(text))) {\n return [contentChild];\n }\n\n const space = match.space.map(space => context.matchedResult.getComputedText(space)).join(' ');\n const color1Text = match.color1.map(color => context.matchedResult.getComputedText(color)).join(' ');\n const color2Text = match.color2.map(color => context.matchedResult.getComputedText(color)).join(' ');\n swatch.appendChild(contentChild);\n swatch.setColorMixText(`color-mix(${space}, ${color1Text}, ${color2Text})`);\n swatch.setRegisterPopoverCallback(swatch => {\n if (swatch.icon) {\n this.#pane.addPopover(swatch.icon, {\n contents: () => {\n const color = swatch.mixedColor();\n if (!color) {\n return undefined;\n }\n const span = document.createElement('span');\n span.style.padding = '11px 7px';\n const rgb = color.as(Common.Color.Format.HEX);\n const text = rgb.isGamutClipped() ? color.asString() : rgb.asString();\n if (!text) {\n return undefined;\n }\n span.appendChild(document.createTextNode(text));\n return span;\n },\n jslogContext: 'elements.css-color-mix',\n });\n }\n });\n\n context.addControl('color', swatch);\n return [swatch];\n }\n\n matcher(): ColorMixMatcher {\n return new ColorMixMatcher();\n }\n}\n\nexport class AngleRenderer implements MatchRenderer {\n #treeElement: StylePropertyTreeElement;\n constructor(treeElement: StylePropertyTreeElement) {\n this.#treeElement = treeElement;\n }\n\n render(match: AngleMatch, context: RenderingContext): Node[] {\n const angleText = match.text;\n if (!this.#treeElement.editable()) {\n return [document.createTextNode(angleText)];\n }\n const cssAngle = new InlineEditor.CSSAngle.CSSAngle();\n cssAngle.setAttribute('jslog', `${VisualLogging.showStyleEditor().track({click: true}).context('css-angle')}`);\n const valueElement = document.createElement('span');\n valueElement.textContent = angleText;\n cssAngle.data = {\n angleText,\n containingPane:\n (this.#treeElement.parentPane().element.enclosingNodeOrSelfWithClass('style-panes-wrapper') as HTMLElement),\n };\n cssAngle.append(valueElement);\n\n cssAngle.addEventListener('popovertoggled', ({data}) => {\n const section = this.#treeElement.section();\n if (!section) {\n return;\n }\n\n if (data.open) {\n this.#treeElement.parentPane().hideAllPopovers();\n this.#treeElement.parentPane().activeCSSAngle = cssAngle;\n Host.userMetrics.swatchActivated(Host.UserMetrics.SwatchType.ANGLE);\n }\n\n section.element.classList.toggle('has-open-popover', data.open);\n this.#treeElement.parentPane().setEditingStyle(data.open);\n\n // Commit the value as a major change after the angle popover is closed.\n if (!data.open) {\n void this.#treeElement.applyStyleText(this.#treeElement.renderedPropertyText(), true);\n }\n });\n cssAngle.addEventListener('valuechanged', async ({data}) => {\n valueElement.textContent = data.value;\n await this.#treeElement.applyStyleText(this.#treeElement.renderedPropertyText(), false);\n });\n cssAngle.addEventListener('unitchanged', ({data}) => {\n valueElement.textContent = data.value;\n });\n\n context.addControl('angle', cssAngle);\n return [cssAngle];\n }\n\n matcher(): AngleMatcher {\n return new AngleMatcher();\n }\n}\n\nexport class LinkableNameRenderer implements MatchRenderer {\n readonly #treeElement: StylePropertyTreeElement;\n constructor(treeElement: StylePropertyTreeElement) {\n this.#treeElement = treeElement;\n }\n\n #getLinkData(match: LinkableNameMatch):\n {jslogContext: string, metric: null|Host.UserMetrics.SwatchType, ruleBlock: string, isDefined: boolean} {\n switch (match.properyName) {\n case LinkableNameProperties.ANIMATION:\n case LinkableNameProperties.ANIMATION_NAME:\n return {\n jslogContext: 'css-animation-name',\n metric: Host.UserMetrics.SwatchType.ANIMATION_NAME_LINK,\n ruleBlock: '@keyframes',\n isDefined: Boolean(this.#treeElement.matchedStyles().keyframes().find(kf => kf.name().text === match.text)),\n };\n case LinkableNameProperties.FONT_PALETTE:\n return {\n jslogContext: 'css-font-palette',\n metric: null,\n ruleBlock: '@font-palette-values',\n isDefined: this.#treeElement.matchedStyles().fontPaletteValuesRule()?.name().text === match.text,\n };\n case LinkableNameProperties.POSITION_TRY:\n case LinkableNameProperties.POSITION_TRY_FALLBACKS:\n return {\n jslogContext: 'css-position-try',\n metric: Host.UserMetrics.SwatchType.POSITION_TRY_LINK,\n ruleBlock: '@position-try',\n isDefined:\n Boolean(this.#treeElement.matchedStyles().positionTryRules().find(pt => pt.name().text === match.text)),\n };\n }\n }\n\n render(match: LinkableNameMatch): Node[] {\n const swatch = new InlineEditor.LinkSwatch.LinkSwatch();\n UI.UIUtils.createTextChild(swatch, match.text);\n const {metric, jslogContext, ruleBlock, isDefined} = this.#getLinkData(match);\n swatch.data = {\n text: match.text,\n isDefined,\n onLinkActivate: (): void => {\n metric && Host.userMetrics.swatchActivated(metric);\n this.#treeElement.parentPane().jumpToSectionBlock(`${ruleBlock} ${match.text}`);\n },\n jslogContext,\n };\n\n return [swatch];\n }\n\n matcher(): LinkableNameMatcher {\n return new LinkableNameMatcher();\n }\n}\n\nexport class BezierRenderer implements MatchRenderer {\n readonly #treeElement: StylePropertyTreeElement;\n constructor(treeElement: StylePropertyTreeElement) {\n this.#treeElement = treeElement;\n }\n\n render(match: BezierMatch): Node[] {\n return [this.renderSwatch(match)];\n }\n\n renderSwatch(match: BezierMatch): Node {\n if (!this.#treeElement.editable()) {\n return document.createTextNode(match.text);\n }\n const swatchPopoverHelper = this.#treeElement.parentPane().swatchPopoverHelper();\n const swatch = InlineEditor.Swatches.BezierSwatch.create();\n swatch.iconElement().addEventListener('click', () => {\n Host.userMetrics.swatchActivated(Host.UserMetrics.SwatchType.ANIMATION_TIMING);\n });\n swatch.setBezierText(match.text);\n new BezierPopoverIcon({treeElement: this.#treeElement, swatchPopoverHelper, swatch});\n return swatch;\n }\n\n matcher(): BezierMatcher {\n return new BezierMatcher();\n }\n}\n\nexport const enum ShadowPropertyType {\n X = 'x',\n Y = 'y',\n SPREAD = 'spread',\n BLUR = 'blur',\n INSET = 'inset',\n COLOR = 'color',\n}\n\ntype ShadowProperty = {\n value: string|CodeMirror.SyntaxNode,\n source: CodeMirror.SyntaxNode|null,\n expansionContext: RenderingContext|null,\n propertyType: ShadowPropertyType,\n};\n\ntype ShadowLengthProperty = ShadowProperty&{\n length: InlineEditor.CSSShadowEditor.CSSLength,\n propertyType: Exclude,\n};\n\n// The shadow model is an abstraction over the various shadow properties on the one hand and the order they were defined\n// in on the other, so that modifications through the shadow editor can retain the property order in the authored text.\n// The model also looks through var()s by keeping a mapping between individual properties and any var()s they are coming\n// from, replacing the var() functions as needed with concrete values when edited.\nexport class ShadowModel implements InlineEditor.CSSShadowEditor.CSSShadowModel {\n readonly #properties: ShadowProperty[];\n readonly #shadowType: ShadowType;\n readonly #context: RenderingContext;\n\n constructor(shadowType: ShadowType, properties: ShadowProperty[], context: RenderingContext) {\n this.#shadowType = shadowType;\n this.#properties = properties;\n this.#context = context;\n }\n isBoxShadow(): boolean {\n return this.#shadowType === ShadowType.BOX_SHADOW;\n }\n inset(): boolean {\n return Boolean(this.#properties.find(property => property.propertyType === ShadowPropertyType.INSET));\n }\n #length(lengthType: ShadowLengthProperty['propertyType']): InlineEditor.CSSShadowEditor.CSSLength {\n return this.#properties.find((property): property is ShadowLengthProperty => property.propertyType === lengthType)\n ?.length ??\n InlineEditor.CSSShadowEditor.CSSLength.zero();\n }\n offsetX(): InlineEditor.CSSShadowEditor.CSSLength {\n return this.#length(ShadowPropertyType.X);\n }\n offsetY(): InlineEditor.CSSShadowEditor.CSSLength {\n return this.#length(ShadowPropertyType.Y);\n }\n blurRadius(): InlineEditor.CSSShadowEditor.CSSLength {\n return this.#length(ShadowPropertyType.BLUR);\n }\n spreadRadius(): InlineEditor.CSSShadowEditor.CSSLength {\n return this.#length(ShadowPropertyType.SPREAD);\n }\n\n #needsExpansion(property: ShadowProperty): boolean {\n return Boolean(property.expansionContext && property.source);\n }\n\n #expandPropertyIfNeeded(property: ShadowProperty): void {\n if (this.#needsExpansion(property)) {\n // Rendering prefers `source` if present. It's sufficient to clear it in order to switch rendering to render the\n // individual properties directly.\n const source = property.source;\n this.#properties.filter(property => property.source === source).forEach(property => {\n property.source = null;\n });\n }\n }\n\n #expandOrGetProperty(propertyType: Exclude):\n {property: ShadowProperty|undefined, index: number};\n #expandOrGetProperty(propertyType: ShadowLengthProperty['propertyType']):\n {property: ShadowLengthProperty|undefined, index: number};\n #expandOrGetProperty(propertyType: ShadowPropertyType): {property: ShadowProperty|undefined, index: number} {\n const index = this.#properties.findIndex(property => property.propertyType === propertyType);\n const property = index >= 0 ? this.#properties[index] : undefined;\n property && this.#expandPropertyIfNeeded(property);\n return {property, index};\n }\n\n setInset(inset: boolean): void {\n if (!this.isBoxShadow()) {\n return;\n }\n\n const {property, index} = this.#expandOrGetProperty(ShadowPropertyType.INSET);\n if (property) {\n // For `inset`, remove the entry if value is false, otherwise don't touch it.\n if (!inset) {\n this.#properties.splice(index, 1);\n }\n } else {\n this.#properties.unshift(\n {value: 'inset', source: null, expansionContext: null, propertyType: ShadowPropertyType.INSET});\n }\n }\n #setLength(value: InlineEditor.CSSShadowEditor.CSSLength, propertyType: ShadowLengthProperty['propertyType']): void {\n const {property} = this.#expandOrGetProperty(propertyType);\n if (property) {\n property.value = value.asCSSText();\n property.length = value;\n property.source = null;\n } else {\n // Lengths are ordered X, Y, Blur, Spread, with the latter two being optional. When inserting an optional property\n // we need to insert it after Y or after Blur, depending on what's being inserted and which properties are\n // present.\n const insertionIdx = 1 +\n this.#properties.findLastIndex(\n property => property.propertyType === ShadowPropertyType.Y ||\n (propertyType === ShadowPropertyType.SPREAD && property.propertyType === ShadowPropertyType.BLUR));\n if (insertionIdx > 0 && insertionIdx < this.#properties.length &&\n this.#needsExpansion(this.#properties[insertionIdx]) &&\n this.#properties[insertionIdx - 1].source === this.#properties[insertionIdx].source) {\n // This prevents the edge case where insertion after the last length would break up a group of values that\n // require expansion.\n this.#expandPropertyIfNeeded(this.#properties[insertionIdx]);\n }\n this.#properties.splice(\n insertionIdx, 0,\n {value: value.asCSSText(), length: value, source: null, expansionContext: null, propertyType} as\n ShadowLengthProperty);\n }\n }\n setOffsetX(value: InlineEditor.CSSShadowEditor.CSSLength): void {\n this.#setLength(value, ShadowPropertyType.X);\n }\n setOffsetY(value: InlineEditor.CSSShadowEditor.CSSLength): void {\n this.#setLength(value, ShadowPropertyType.Y);\n }\n setBlurRadius(value: InlineEditor.CSSShadowEditor.CSSLength): void {\n this.#setLength(value, ShadowPropertyType.BLUR);\n }\n setSpreadRadius(value: InlineEditor.CSSShadowEditor.CSSLength): void {\n if (this.isBoxShadow()) {\n this.#setLength(value, ShadowPropertyType.SPREAD);\n }\n }\n\n renderContents(parent: HTMLElement): void {\n parent.removeChildren();\n const span = parent.createChild('span');\n let previousSource = null;\n for (const property of this.#properties) {\n if (!property.source || property.source !== previousSource) {\n if (property !== this.#properties[0]) {\n span.append(' ');\n }\n // If `source` is present on the property that means it came from a var() and we'll use that to render.\n if (property.source) {\n span.append(...Renderer.render(property.source, this.#context).nodes);\n } else if (typeof property.value === 'string') {\n span.append(property.value);\n } else {\n span.append(...Renderer.render(property.value, property.expansionContext ?? this.#context).nodes);\n }\n }\n previousSource = property.source;\n }\n }\n}\n\nexport class ShadowRenderer implements MatchRenderer {\n readonly #treeElement: StylePropertyTreeElement;\n constructor(treeElement: StylePropertyTreeElement) {\n this.#treeElement = treeElement;\n }\n\n shadowModel(shadow: CodeMirror.SyntaxNode[], shadowType: ShadowType, context: RenderingContext): null|ShadowModel {\n const properties: Array = [];\n const missingLengths: ShadowLengthProperty['propertyType'][] =\n [ShadowPropertyType.SPREAD, ShadowPropertyType.BLUR, ShadowPropertyType.Y, ShadowPropertyType.X];\n let stillAcceptsLengths = true;\n\n // We're parsing the individual shadow properties into an array here retaining the ordering. This also looks through\n // var() functions by re-parsing the variable values on the fly. For properties coming from a var() we're keeping\n // track of their origin to allow for adhoc expansion when one of those properties is edited.\n\n const queue: {\n value: CodeMirror.SyntaxNode,\n source: CodeMirror.SyntaxNode,\n match: SDK.CSSPropertyParser.Match|undefined,\n expansionContext: RenderingContext|null,\n }[] =\n shadow.map(\n value => ({value, source: value, match: context.matchedResult.getMatch(value), expansionContext: null}));\n for (let item = queue.shift(); item; item = queue.shift()) {\n const {value, source, match, expansionContext} = item;\n const text = (expansionContext ?? context).ast.text(value);\n if (value.name === 'NumberLiteral') {\n if (!stillAcceptsLengths) {\n return null;\n }\n const propertyType = missingLengths.pop();\n if (propertyType === undefined ||\n (propertyType === ShadowPropertyType.SPREAD && shadowType === ShadowType.TEXT_SHADOW)) {\n return null;\n }\n const length = InlineEditor.CSSShadowEditor.CSSLength.parse(text);\n if (!length) {\n return null;\n }\n properties.push({value, source, length, propertyType, expansionContext});\n } else if (match instanceof SDK.CSSPropertyParser.VariableMatch) {\n // This doesn't come from any computed text, so we can rely on context here\n const computedValue = context.matchedResult.getComputedText(value);\n const computedValueAst = SDK.CSSPropertyParser.tokenizeDeclaration('--property', computedValue);\n if (!computedValueAst) {\n return null;\n }\n const matches =\n SDK.CSSPropertyParser.BottomUpTreeMatching.walkExcludingSuccessors(computedValueAst, [new ColorMatcher()]);\n if (matches.hasUnresolvedVars(matches.ast.tree)) {\n return null;\n }\n queue.unshift(...ASTUtils.siblings(ASTUtils.declValue(matches.ast.tree))\n .map(matchedNode => ({\n value: matchedNode,\n source: value,\n match: matches.getMatch(matchedNode),\n expansionContext: new RenderingContext(computedValueAst, context.renderers, matches),\n })));\n } else {\n // The length properties must come in one block, so if there were any lengths before, followed by a non-length\n // property, we will not allow any future lengths.\n stillAcceptsLengths = missingLengths.length === 4;\n if (value.name === 'ValueName' && text.toLowerCase() === 'inset') {\n if (shadowType === ShadowType.TEXT_SHADOW ||\n properties.find(({propertyType}) => propertyType === ShadowPropertyType.INSET)) {\n return null;\n }\n properties.push({value, source, propertyType: ShadowPropertyType.INSET, expansionContext});\n } else if (match instanceof ColorMatch || match instanceof ColorMixMatch) {\n if (properties.find(({propertyType}) => propertyType === ShadowPropertyType.COLOR)) {\n return null;\n }\n properties.push({value, source, propertyType: ShadowPropertyType.COLOR, expansionContext});\n } else if (value.name !== 'Comment' && value.name !== 'Important') {\n return null;\n }\n }\n }\n if (missingLengths.length > 2) {\n // X and Y are mandatory\n return null;\n }\n return new ShadowModel(shadowType, properties, context);\n }\n\n render(match: ShadowMatch, context: RenderingContext): Node[] {\n const shadows = ASTUtils.split(ASTUtils.siblings(ASTUtils.declValue(match.node)));\n const result: Node[] = [];\n\n for (const shadow of shadows) {\n const model = this.shadowModel(shadow, match.shadowType, context);\n const isImportant = shadow.find(node => node.name === 'Important');\n\n if (shadow !== shadows[0]) {\n result.push(document.createTextNode(', '));\n }\n\n if (!model) {\n const {nodes} = Renderer.render(shadow, context);\n result.push(...nodes);\n continue;\n }\n\n const swatch = new InlineEditor.Swatches.CSSShadowSwatch(model);\n swatch.setAttribute('jslog', `${VisualLogging.showStyleEditor('css-shadow').track({click: true})}`);\n swatch.iconElement().addEventListener('click', () => {\n Host.userMetrics.swatchActivated(Host.UserMetrics.SwatchType.SHADOW);\n });\n model.renderContents(swatch);\n const popoverHelper = new ShadowSwatchPopoverHelper(\n this.#treeElement, this.#treeElement.parentPane().swatchPopoverHelper(), swatch);\n popoverHelper.addEventListener(ShadowEvents.SHADOW_CHANGED, () => {\n model.renderContents(swatch);\n void this.#treeElement.applyStyleText(this.#treeElement.renderedPropertyText(), false);\n });\n result.push(swatch);\n\n if (isImportant) {\n result.push(...[document.createTextNode(' '), ...Renderer.render(isImportant, context).nodes]);\n }\n }\n\n return result;\n }\n\n matcher(): ShadowMatcher {\n return new ShadowMatcher();\n }\n}\n\nexport class FontRenderer implements MatchRenderer {\n constructor(readonly treeElement: StylePropertyTreeElement) {\n }\n\n render(match: FontMatch): Node[] {\n this.treeElement.section().registerFontProperty(this.treeElement);\n return [document.createTextNode(match.text)];\n }\n\n matcher(): FontMatcher {\n return new FontMatcher();\n }\n}\n\nexport class GridTemplateRenderer implements MatchRenderer {\n render(match: GridTemplateMatch, context: RenderingContext): Node[] {\n if (match.lines.length <= 1) {\n return Renderer.render(ASTUtils.siblings(ASTUtils.declValue(match.node)), context).nodes;\n }\n\n const indent = Common.Settings.Settings.instance().moduleSetting('text-editor-indent').get();\n const container = document.createDocumentFragment();\n for (const line of match.lines) {\n const value = Renderer.render(line, context);\n const lineBreak = UI.Fragment.html`
${indent.repeat(2)}`;\n container.append(lineBreak, ...value.nodes);\n }\n return [container];\n }\n\n matcher(): GridTemplateMatcher {\n return new GridTemplateMatcher();\n }\n}\n\nexport class LengthRenderer implements MatchRenderer {\n readonly #treeElement: StylePropertyTreeElement;\n constructor(treeElement: StylePropertyTreeElement) {\n this.#treeElement = treeElement;\n }\n\n render(match: LengthMatch, _context: RenderingContext): Node[] {\n const lengthText = match.text;\n if (!this.#treeElement.editable()) {\n return [document.createTextNode(lengthText)];\n }\n const cssLength = new InlineEditor.CSSLength.CSSLength();\n const valueElement = document.createElement('span');\n valueElement.textContent = lengthText;\n cssLength.data = {lengthText};\n cssLength.append(valueElement);\n\n const onValueChanged = (event: Event): void => {\n const {data} = (event as InlineEditor.InlineEditorUtils.ValueChangedEvent);\n\n valueElement.textContent = data.value;\n this.#treeElement.parentPane().setEditingStyle(true);\n void this.#treeElement.applyStyleText(this.#treeElement.renderedPropertyText(), false);\n };\n\n const onDraggingFinished = (): void => {\n this.#treeElement.parentPane().setEditingStyle(false);\n };\n\n cssLength.addEventListener('valuechanged', onValueChanged);\n cssLength.addEventListener('draggingfinished', onDraggingFinished);\n\n return [cssLength];\n }\n\n matcher(): LengthMatcher {\n return new LengthMatcher();\n }\n}\n\nasync function decorateAnchorForAnchorLink(container: HTMLElement, treeElement: StylePropertyTreeElement, options: {\n identifier?: string, needsSpace: boolean,\n}): Promise {\n const anchorNode = await treeElement.node()?.getAnchorBySpecifier(options.identifier) ?? undefined;\n const link = new ElementsComponents.AnchorFunctionLinkSwatch.AnchorFunctionLinkSwatch({\n identifier: options.identifier,\n anchorNode,\n needsSpace: options.needsSpace,\n onLinkActivate: () => {\n if (!anchorNode) {\n return;\n }\n\n void Common.Revealer.reveal(anchorNode, false);\n },\n onMouseEnter: () => {\n anchorNode?.highlight();\n },\n onMouseLeave: () => {\n SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight();\n },\n });\n\n container.removeChildren();\n container.appendChild(link);\n}\n\nexport class AnchorFunctionRenderer implements MatchRenderer {\n #treeElement: StylePropertyTreeElement;\n constructor(treeElement: StylePropertyTreeElement) {\n this.#treeElement = treeElement;\n }\n\n anchorDecoratedForTest(): void {\n }\n\n async #decorateAnchor(container: HTMLElement, addSpace: boolean, identifier?: string): Promise {\n await decorateAnchorForAnchorLink(container, this.#treeElement, {\n identifier,\n needsSpace: addSpace,\n });\n this.anchorDecoratedForTest();\n }\n\n render(match: AnchorFunctionMatch, context: RenderingContext): Node[] {\n const content = document.createElement('span');\n if (match.node.name === 'VariableName') {\n // Link an anchor double-dashed ident to its matching anchor element.\n content.appendChild(document.createTextNode(match.text));\n void this.#decorateAnchor(content, /* addSpace */ false, match.text);\n } else {\n // The matcher passes a 'CallExpression' node with a functionName\n // ('anchor' or 'anchor-size') if the arguments need to have an implicit\n // anchor link swatch rendered.\n content.appendChild(document.createTextNode(`${match.functionName}(`));\n const swatchContainer = document.createElement('span');\n content.appendChild(swatchContainer);\n const args = ASTUtils.children(match.node.getChild('ArgList'));\n const remainingArgs = args.splice(1);\n void this.#decorateAnchor(swatchContainer, /* addSpace */ remainingArgs.length > 1);\n Renderer.renderInto(remainingArgs, context, content);\n }\n return [content];\n }\n\n matcher(): AnchorFunctionMatcher {\n return new AnchorFunctionMatcher();\n }\n}\n\nexport class PositionAnchorRenderer implements MatchRenderer {\n #treeElement: StylePropertyTreeElement;\n\n constructor(treeElement: StylePropertyTreeElement) {\n this.#treeElement = treeElement;\n }\n\n anchorDecoratedForTest(): void {\n }\n\n render(match: PositionAnchorMatch): Node[] {\n const content = document.createElement('span');\n content.appendChild(document.createTextNode(match.text));\n void decorateAnchorForAnchorLink(content, this.#treeElement, {\n identifier: match.text,\n needsSpace: false,\n }).then(() => this.anchorDecoratedForTest());\n return [content];\n }\n\n matcher(): PositionAnchorMatcher {\n return new PositionAnchorMatcher();\n }\n}\n\nexport class StylePropertyTreeElement extends UI.TreeOutline.TreeElement {\n private readonly style: SDK.CSSStyleDeclaration.CSSStyleDeclaration;\n private matchedStylesInternal: SDK.CSSMatchedStyles.CSSMatchedStyles;\n property: SDK.CSSProperty.CSSProperty;\n private readonly inheritedInternal: boolean;\n private overloadedInternal: boolean;\n private parentPaneInternal: StylesSidebarPane;\n #parentSection: StylePropertiesSection;\n isShorthand: boolean;\n private readonly applyStyleThrottler: Common.Throttler.Throttler;\n private newProperty: boolean;\n private expandedDueToFilter: boolean;\n valueElement: HTMLElement|null;\n nameElement: HTMLElement|null;\n private expandElement: IconButton.Icon.Icon|null;\n private originalPropertyText: string;\n private hasBeenEditedIncrementally: boolean;\n private prompt: CSSPropertyPrompt|null;\n private lastComputedValue: string|null;\n private computedStyles: Map|null = null;\n private parentsComputedStyles: Map|null = null;\n private contextForTest!: Context|undefined;\n #propertyTextFromSource: string;\n #gridNames: Set|undefined = undefined;\n\n constructor(\n {stylesPane, section, matchedStyles, property, isShorthand, inherited, overloaded, newProperty}:\n StylePropertyTreeElementParams,\n ) {\n // Pass an empty title, the title gets made later in onattach.\n const jslogContext = property.name.startsWith('--') ? 'custom-property' : property.name;\n super('', isShorthand, jslogContext);\n this.style = property.ownerStyle;\n this.matchedStylesInternal = matchedStyles;\n this.property = property;\n this.inheritedInternal = inherited;\n this.overloadedInternal = overloaded;\n this.selectable = false;\n this.parentPaneInternal = stylesPane;\n this.#parentSection = section;\n this.isShorthand = isShorthand;\n this.applyStyleThrottler = new Common.Throttler.Throttler(0);\n this.newProperty = newProperty;\n if (this.newProperty) {\n this.listItemElement.textContent = '';\n }\n this.expandedDueToFilter = false;\n this.valueElement = null;\n this.nameElement = null;\n this.expandElement = null;\n this.originalPropertyText = '';\n this.hasBeenEditedIncrementally = false;\n this.prompt = null;\n\n this.lastComputedValue = null;\n\n this.#propertyTextFromSource = property.propertyText || '';\n }\n\n async gridNames(): Promise> {\n if (!SDK.CSSMetadata.cssMetadata().isGridNameAwareProperty(this.name)) {\n return new Set();\n }\n for (let node = this.parentPaneInternal.node()?.parentNode; node; node = node?.parentNode) {\n const style = await this.parentPaneInternal.cssModel()?.getComputedStyle(node.id);\n const display = style?.get('display');\n const isGrid = display === 'grid' || display === 'inline-grid';\n if (!isGrid) {\n continue;\n }\n const getNames = (propertyName: string, astNodeName: string): string[] => {\n const propertyValue = style?.get(propertyName);\n if (!propertyValue) {\n return [];\n }\n const ast = SDK.CSSPropertyParser.tokenizeDeclaration(propertyName, propertyValue);\n if (!ast) {\n return [];\n }\n return SDK.CSSPropertyParser.TreeSearch.findAll(ast, node => node.name === astNodeName)\n .map(node => ast.text(node));\n };\n if (SDK.CSSMetadata.cssMetadata().isGridAreaNameAwareProperty(this.name)) {\n return new Set(\n getNames('grid-template-areas', 'StringLiteral')\n ?.flatMap(row => row.substring(1, row.length - 1).split(/\\s+/).filter(cell => !cell.match(/^\\.*$/))));\n }\n if (SDK.CSSMetadata.cssMetadata().isGridColumnNameAwareProperty(this.name)) {\n return new Set(getNames('grid-template-columns', 'LineName'));\n }\n return new Set(getNames('grid-template-rows', 'LineName'));\n }\n return new Set();\n }\n\n matchedStyles(): SDK.CSSMatchedStyles.CSSMatchedStyles {\n return this.matchedStylesInternal;\n }\n\n editable(): boolean {\n const isLonghandInsideShorthand = this.parent instanceof StylePropertyTreeElement && this.parent.isShorthand;\n const hasSourceData = Boolean(this.style.styleSheetId && this.style.range);\n return !isLonghandInsideShorthand && hasSourceData;\n }\n\n inherited(): boolean {\n return this.inheritedInternal;\n }\n\n overloaded(): boolean {\n return this.overloadedInternal;\n }\n\n setOverloaded(x: boolean): void {\n if (x === this.overloadedInternal) {\n return;\n }\n this.overloadedInternal = x;\n this.updateState();\n }\n\n setComputedStyles(computedStyles: Map|null): void {\n this.computedStyles = computedStyles;\n }\n\n getComputedStyle(property: string): string|null {\n return this.computedStyles?.get(property) ?? null;\n }\n\n setParentsComputedStyles(parentsComputedStyles: Map|null): void {\n this.parentsComputedStyles = parentsComputedStyles;\n }\n\n get name(): string {\n return this.property.name;\n }\n\n get value(): string {\n return this.property.value;\n }\n\n updateFilter(): boolean {\n const regex = this.parentPaneInternal.filterRegex();\n const matches = regex !== null && (regex.test(this.property.name) || regex.test(this.property.value));\n this.listItemElement.classList.toggle('filter-match', matches);\n\n void this.onpopulate();\n let hasMatchingChildren = false;\n\n for (let i = 0; i < this.childCount(); ++i) {\n const child = (this.childAt(i) as StylePropertyTreeElement | null);\n if (!child || (child && !child.updateFilter())) {\n continue;\n }\n hasMatchingChildren = true;\n }\n\n if (!regex) {\n if (this.expandedDueToFilter) {\n this.collapse();\n }\n this.expandedDueToFilter = false;\n } else if (hasMatchingChildren && !this.expanded) {\n this.expand();\n this.expandedDueToFilter = true;\n } else if (!hasMatchingChildren && this.expanded && this.expandedDueToFilter) {\n this.collapse();\n this.expandedDueToFilter = false;\n }\n return matches;\n }\n\n renderedPropertyText(): string {\n if (!this.nameElement || !this.valueElement) {\n return '';\n }\n return this.nameElement.textContent + ': ' + this.valueElement.textContent;\n }\n\n private updateState(): void {\n if (!this.listItemElement) {\n return;\n }\n\n if (this.style.isPropertyImplicit(this.name)) {\n this.listItemElement.classList.add('implicit');\n } else {\n this.listItemElement.classList.remove('implicit');\n }\n\n const hasIgnorableError = !this.property.parsedOk && StylesSidebarPane.ignoreErrorsForProperty(this.property);\n if (hasIgnorableError) {\n this.listItemElement.classList.add('has-ignorable-error');\n } else {\n this.listItemElement.classList.remove('has-ignorable-error');\n }\n\n if (this.inherited()) {\n this.listItemElement.classList.add('inherited');\n } else {\n this.listItemElement.classList.remove('inherited');\n }\n\n if (this.overloaded()) {\n this.listItemElement.classList.add('overloaded');\n } else {\n this.listItemElement.classList.remove('overloaded');\n }\n\n if (this.property.disabled) {\n this.listItemElement.classList.add('disabled');\n } else {\n this.listItemElement.classList.remove('disabled');\n }\n\n this.listItemElement.classList.toggle('changed', this.isPropertyChanged(this.property));\n }\n\n node(): SDK.DOMModel.DOMNode|null {\n return this.parentPaneInternal.node();\n }\n\n parentPane(): StylesSidebarPane {\n return this.parentPaneInternal;\n }\n\n section(): StylePropertiesSection {\n return this.#parentSection;\n }\n\n private updatePane(): void {\n this.#parentSection.refreshUpdate(this);\n }\n\n private async toggleDisabled(disabled: boolean): Promise {\n const oldStyleRange = this.style.range;\n if (!oldStyleRange) {\n return;\n }\n\n this.parentPaneInternal.setUserOperation(true);\n const success = await this.property.setDisabled(disabled);\n this.parentPaneInternal.setUserOperation(false);\n\n if (!success) {\n return;\n }\n this.matchedStylesInternal.resetActiveProperties();\n this.updatePane();\n this.styleTextAppliedForTest();\n }\n\n private isPropertyChanged(property: SDK.CSSProperty.CSSProperty): boolean {\n if (!Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.STYLES_PANE_CSS_CHANGES)) {\n return false;\n }\n // Check local cache first, then check against diffs from the workspace.\n return this.#propertyTextFromSource !== property.propertyText || this.parentPane().isPropertyChanged(property);\n }\n\n override async onpopulate(): Promise {\n if (!this.#gridNames) {\n this.#gridNames = await this.gridNames();\n }\n\n // Only populate once and if this property is a shorthand.\n if (this.childCount() || !this.isShorthand) {\n return;\n }\n\n const longhandProperties = this.property.getLonghandProperties();\n const leadingProperties = this.style.leadingProperties();\n\n for (const property of longhandProperties) {\n const name = property.name;\n let inherited = false;\n let overloaded = false;\n\n inherited = this.#parentSection.isPropertyInherited(name);\n overloaded = this.matchedStylesInternal.propertyState(property) === SDK.CSSMatchedStyles.PropertyState.OVERLOADED;\n\n const leadingProperty = leadingProperties.find(property => property.name === name && property.activeInStyle());\n if (leadingProperty) {\n overloaded = true;\n }\n\n const item = new StylePropertyTreeElement({\n stylesPane: this.parentPaneInternal,\n section: this.#parentSection,\n matchedStyles: this.matchedStylesInternal,\n property,\n isShorthand: false,\n inherited,\n overloaded,\n newProperty: false,\n });\n item.setComputedStyles(this.computedStyles);\n item.setParentsComputedStyles(this.parentsComputedStyles);\n this.appendChild(item);\n }\n }\n\n override onattach(): void {\n this.updateTitle();\n\n this.listItemElement.addEventListener('mousedown', event => {\n if (event.button === 0) {\n parentMap.set(this.parentPaneInternal, this);\n }\n }, false);\n this.listItemElement.addEventListener('mouseup', this.mouseUp.bind(this));\n this.listItemElement.addEventListener('click', event => {\n if (!event.target) {\n return;\n }\n\n const node = (event.target as HTMLElement);\n if (!node.hasSelection() && event.target !== this.listItemElement) {\n event.consume(true);\n }\n });\n\n // Copy context menu.\n this.listItemElement.addEventListener('contextmenu', this.handleCopyContextMenuEvent.bind(this));\n }\n\n override onexpand(): void {\n this.updateExpandElement();\n }\n\n override oncollapse(): void {\n this.updateExpandElement();\n }\n\n private updateExpandElement(): void {\n if (!this.expandElement) {\n return;\n }\n if (this.expanded) {\n this.expandElement.name = 'triangle-down';\n } else {\n this.expandElement.name = 'triangle-right';\n }\n }\n\n #getRegisteredPropertyDetails(variableName: string): ElementsComponents.CSSVariableValueView.RegisteredPropertyDetails\n |undefined {\n const registration = this.matchedStyles().getRegisteredProperty(variableName);\n const goToDefinition = (): void =>\n this.parentPaneInternal.jumpToSection(variableName, REGISTERED_PROPERTY_SECTION_NAME);\n return registration ? {registration, goToDefinition} : undefined;\n }\n\n getVariablePopoverContents(variableName: string, computedValue: string|null): HTMLElement|undefined {\n return new ElementsComponents.CSSVariableValueView.CSSVariableValueView({\n variableName,\n value: computedValue ?? undefined,\n details: this.#getRegisteredPropertyDetails(variableName),\n });\n }\n\n // Resolves a CSS expression to its computed value with `var()` calls updated.\n // Still returns the string even when a `var()` call is not resolved.\n #computeCSSExpression(style: SDK.CSSStyleDeclaration.CSSStyleDeclaration, text: string): string|null {\n const ast = SDK.CSSPropertyParser.tokenizeDeclaration('--unused', text);\n if (!ast) {\n return null;\n }\n\n const matching: SDK.CSSPropertyParser.BottomUpTreeMatching = SDK.CSSPropertyParser.BottomUpTreeMatching.walk(\n ast, [new SDK.CSSPropertyParser.VariableMatcher((match: SDK.CSSPropertyParser.VariableMatch) => {\n const variableValue = this.matchedStylesInternal.computeCSSVariable(style, match.name)?.value;\n if (variableValue !== undefined) {\n return variableValue;\n }\n\n if (match.fallback.length === 0 ||\n match.matching.hasUnresolvedVarsRange(match.fallback[0], match.fallback[match.fallback.length - 1])) {\n return null;\n }\n return match.matching.getComputedTextRange(match.fallback[0], match.fallback[match.fallback.length - 1]);\n })]);\n\n const decl = SDK.CSSPropertyParser.ASTUtils.siblings(SDK.CSSPropertyParser.ASTUtils.declValue(matching.ast.tree));\n return matching.getComputedTextRange(decl[0], decl[decl.length - 1]);\n }\n\n refreshIfComputedValueChanged(): void {\n this.#gridNames = undefined;\n const computedValue = this.#computeCSSExpression(this.property.ownerStyle, this.property.value);\n if (computedValue === this.lastComputedValue) {\n return;\n }\n this.lastComputedValue = computedValue;\n this.innerUpdateTitle();\n }\n\n updateTitle(): void {\n this.lastComputedValue = this.#computeCSSExpression(this.property.ownerStyle, this.property.value);\n this.innerUpdateTitle();\n }\n\n private innerUpdateTitle(): void {\n this.updateState();\n if (this.isExpandable()) {\n this.expandElement = IconButton.Icon.create('triangle-right', 'expand-icon');\n this.expandElement.setAttribute('jslog', `${VisualLogging.expand().track({click: true})}`);\n }\n\n const renderers: MatchRenderer[] = this.property.parsedOk ?\n [\n new VariableRenderer(this, this.style),\n new ColorRenderer(this),\n new ColorMixRenderer(this.parentPaneInternal),\n new URLRenderer(this.style.parentRule, this.node()),\n new AngleRenderer(this),\n new LinkableNameRenderer(this),\n new BezierRenderer(this),\n new StringRenderer(),\n new ShadowRenderer(this),\n new FontRenderer(this),\n new LightDarkColorRenderer(this),\n new GridTemplateRenderer(),\n new LinearGradientRenderer(),\n new AnchorFunctionRenderer(this),\n new PositionAnchorRenderer(this),\n ] :\n [];\n\n if (!Root.Runtime.experiments.isEnabled('css-type-component-length-deprecate') && this.property.parsedOk) {\n renderers.push(new LengthRenderer(this));\n }\n\n this.listItemElement.removeChildren();\n this.valueElement = Renderer.renderValueElement(this.name, this.value, renderers);\n this.nameElement = Renderer.renderNameElement(this.name);\n if (this.property.name.startsWith('--') && this.nameElement) {\n this.parentPaneInternal.addPopover(this.nameElement, {\n contents: () => this.getVariablePopoverContents(\n this.property.name,\n this.matchedStylesInternal.computeCSSVariable(this.style, this.property.name)?.value ?? null),\n jslogContext: 'elements.css-var',\n });\n }\n if (!this.treeOutline) {\n return;\n }\n\n const indent = Common.Settings.Settings.instance().moduleSetting('text-editor-indent').get();\n UI.UIUtils.createTextChild(\n this.listItemElement.createChild('span', 'styles-clipboard-only'),\n indent.repeat(this.section().nestingLevel + 1) + (this.property.disabled ? '/* ' : ''));\n if (this.nameElement) {\n this.listItemElement.appendChild(this.nameElement);\n }\n if (this.valueElement) {\n const lineBreakValue =\n this.valueElement.firstElementChild && this.valueElement.firstElementChild.tagName === 'BR';\n const separator = lineBreakValue ? ':' : ': ';\n this.listItemElement.createChild('span', 'styles-name-value-separator').textContent = separator;\n if (this.expandElement) {\n this.listItemElement.appendChild(this.expandElement);\n this.updateExpandElement();\n }\n this.listItemElement.appendChild(this.valueElement);\n const semicolon = this.listItemElement.createChild('span', 'styles-semicolon');\n semicolon.textContent = ';';\n semicolon.onmouseup = this.mouseUp.bind(this);\n if (this.property.disabled) {\n UI.UIUtils.createTextChild(this.listItemElement.createChild('span', 'styles-clipboard-only'), ' */');\n }\n }\n\n if (this.valueElement && this.#parentSection.editable && this.property.name === 'display') {\n const propertyValue = this.property.trimmedValueWithoutImportant();\n const isFlex = propertyValue === 'flex' || propertyValue === 'inline-flex';\n const isGrid = propertyValue === 'grid' || propertyValue === 'inline-grid';\n if (isFlex || isGrid) {\n const key = `${this.#parentSection.getSectionIdx()}_${this.#parentSection.nextEditorTriggerButtonIdx}`;\n const button = StyleEditorWidget.createTriggerButton(\n this.parentPaneInternal, this.#parentSection, isFlex ? FlexboxEditor : GridEditor,\n isFlex ? i18nString(UIStrings.flexboxEditorButton) : i18nString(UIStrings.gridEditorButton), key);\n button.setAttribute(\n 'jslog', `${VisualLogging.showStyleEditor().track({click: true}).context(isFlex ? 'flex' : 'grid')}`);\n this.#parentSection.nextEditorTriggerButtonIdx++;\n button.addEventListener('click', () => {\n Host.userMetrics.swatchActivated(\n isFlex ? Host.UserMetrics.SwatchType.FLEX : Host.UserMetrics.SwatchType.GRID);\n });\n this.listItemElement.appendChild(button);\n const helper = this.parentPaneInternal.swatchPopoverHelper();\n if (helper.isShowing(StyleEditorWidget.instance()) && StyleEditorWidget.instance().getTriggerKey() === key) {\n helper.setAnchorElement(button);\n }\n }\n }\n\n if (this.property.parsedOk) {\n this.updateAuthoringHint();\n } else {\n // Avoid having longhands under an invalid shorthand.\n this.listItemElement.classList.add('not-parsed-ok');\n\n const registrationDetails = this.#getRegisteredPropertyDetails(this.property.name);\n const tooltip = registrationDetails ?\n new ElementsComponents.CSSVariableValueView.CSSVariableParserError(registrationDetails) :\n null;\n // Add a separate exclamation mark IMG element with a tooltip.\n this.listItemElement.insertBefore(\n this.parentPaneInternal.createExclamationMark(this.property, tooltip), this.listItemElement.firstChild);\n\n // When the property is valid but the property value is invalid,\n // add line-through only to the property value.\n const invalidPropertyValue = SDK.CSSMetadata.cssMetadata().isCSSPropertyName(this.property.name);\n if (invalidPropertyValue) {\n this.listItemElement.classList.add('invalid-property-value');\n }\n }\n\n if (!this.property.activeInStyle()) {\n this.listItemElement.classList.add('inactive');\n }\n this.updateFilter();\n\n if (this.property.parsedOk && this.parent && this.parent.root) {\n const enabledCheckboxElement = document.createElement('input');\n enabledCheckboxElement.classList.add('enabled-button', 'small');\n enabledCheckboxElement.type = 'checkbox';\n enabledCheckboxElement.checked = !this.property.disabled;\n enabledCheckboxElement.setAttribute('jslog', `${VisualLogging.toggle().track({click: true})}`);\n enabledCheckboxElement.addEventListener('mousedown', event => event.consume(), false);\n enabledCheckboxElement.addEventListener('click', event => {\n void this.toggleDisabled(!this.property.disabled);\n event.consume();\n }, false);\n if (this.nameElement && this.valueElement) {\n UI.ARIAUtils.setLabel(\n enabledCheckboxElement, `${this.nameElement.textContent} ${this.valueElement.textContent}`);\n }\n\n const copyIcon = IconButton.Icon.create('copy', 'copy');\n UI.Tooltip.Tooltip.install(copyIcon, i18nString(UIStrings.copyDeclaration));\n copyIcon.addEventListener('click', () => {\n const propertyText = `${this.property.name}: ${this.property.value};`;\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(propertyText);\n Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.DECLARATION_VIA_CHANGED_LINE);\n });\n this.listItemElement.append(copyIcon);\n this.listItemElement.insertBefore(enabledCheckboxElement, this.listItemElement.firstChild);\n }\n }\n\n updateAuthoringHint(): void {\n this.listItemElement.classList.remove('inactive-property');\n const existingElement = this.listItemElement.querySelector('.hint');\n if (existingElement) {\n activeHints.delete(existingElement);\n existingElement?.closest('.hint-wrapper')?.remove();\n }\n const propertyName = this.property.name;\n\n if (!cssRuleValidatorsMap.has(propertyName)) {\n return;\n }\n\n // Different rules apply to SVG nodes altogether. We currently don't have SVG-specific hints.\n if (this.node()?.isSVGNode()) {\n return;\n }\n\n const cssModel = this.parentPaneInternal.cssModel();\n const fontFaces = cssModel?.fontFaces() || [];\n\n const localName = this.node()?.localName();\n for (const validator of cssRuleValidatorsMap.get(propertyName) || []) {\n const hint = validator.getHint(\n propertyName, this.computedStyles || undefined, this.parentsComputedStyles || undefined,\n localName?.toLowerCase(), fontFaces);\n if (hint) {\n Host.userMetrics.cssHintShown(validator.getMetricType());\n const wrapper = document.createElement('span');\n wrapper.classList.add('hint-wrapper');\n const hintIcon = new IconButton.Icon.Icon();\n hintIcon.data = {iconName: 'info', color: 'var(--icon-default)', width: '14px', height: '14px'};\n hintIcon.classList.add('hint');\n wrapper.append(hintIcon);\n activeHints.set(hintIcon, hint);\n this.listItemElement.append(wrapper);\n this.listItemElement.classList.add('inactive-property');\n break;\n }\n }\n }\n\n private mouseUp(event: MouseEvent): void {\n const activeTreeElement = parentMap.get(this.parentPaneInternal);\n parentMap.delete(this.parentPaneInternal);\n if (!activeTreeElement) {\n return;\n }\n if (this.listItemElement.hasSelection()) {\n return;\n }\n if (UI.UIUtils.isBeingEdited((event.target as Node))) {\n return;\n }\n if (event.composedPath()[0] instanceof HTMLButtonElement) {\n return;\n }\n\n event.consume(true);\n\n if (event.target === this.listItemElement) {\n return;\n }\n\n let selectedElement = event.target as Element;\n if (UI.KeyboardShortcut.KeyboardShortcut.eventHasCtrlEquivalentKey(event) && this.#parentSection.navigable) {\n this.navigateToSource(selectedElement);\n return;\n }\n\n if (this.expandElement && selectedElement === this.expandElement) {\n return;\n }\n\n if (!this.#parentSection.editable) {\n return;\n }\n\n selectedElement = selectedElement.enclosingNodeOrSelfWithClass('webkit-css-property') ||\n selectedElement.enclosingNodeOrSelfWithClass('value') ||\n selectedElement.enclosingNodeOrSelfWithClass('styles-semicolon');\n if (!selectedElement || selectedElement === this.nameElement) {\n VisualLogging.logClick(this.nameElement as Element, event);\n this.startEditingName();\n } else {\n VisualLogging.logClick(this.valueElement as Element, event);\n this.startEditingValue();\n }\n }\n\n private handleContextMenuEvent(context: Context, event: Event): void {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n if (this.property.parsedOk && this.parent && this.parent.root) {\n const sectionIndex = this.parentPaneInternal.focusedSectionIndex();\n contextMenu.defaultSection().appendCheckboxItem(\n i18nString(UIStrings.togglePropertyAndContinueEditing), async () => {\n if (this.treeOutline) {\n const propertyIndex = this.treeOutline.rootElement().indexOfChild(this);\n // order matters here: this.editingCancelled may invalidate this.treeOutline.\n this.editingCancelled(null, context);\n await this.toggleDisabled(!this.property.disabled);\n event.consume();\n this.parentPaneInternal.continueEditingElement(sectionIndex, propertyIndex);\n }\n }, {checked: !this.property.disabled, jslogContext: 'toggle-property-and-continue-editing'});\n }\n const revealCallback = this.navigateToSource.bind(this) as () => void;\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.revealInSourcesPanel), revealCallback, {jslogContext: 'reveal-in-sources-panel'});\n void contextMenu.show();\n }\n\n private handleCopyContextMenuEvent(event: Event): void {\n const target = (event.target as Element | null);\n\n if (!target) {\n return;\n }\n\n const contextMenu = this.createCopyContextMenu(event);\n void contextMenu.show();\n }\n\n createCopyContextMenu(event: Event): UI.ContextMenu.ContextMenu {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n contextMenu.headerSection().appendItem(i18nString(UIStrings.copyDeclaration), () => {\n const propertyText = `${this.property.name}: ${this.property.value};`;\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(propertyText);\n Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.DECLARATION_VIA_CONTEXT_MENU);\n }, {jslogContext: 'copy-declaration'});\n\n contextMenu.headerSection().appendItem(i18nString(UIStrings.copyProperty), () => {\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(this.property.name);\n Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.PROPERTY_VIA_CONTEXT_MENU);\n }, {jslogContext: 'copy-property'});\n\n contextMenu.headerSection().appendItem(i18nString(UIStrings.copyValue), () => {\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(this.property.value);\n Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.VALUE_VIA_CONTEXT_MENU);\n }, {jslogContext: 'copy-value'});\n\n contextMenu.headerSection().appendItem(i18nString(UIStrings.copyRule), () => {\n const ruleText = StylesSidebarPane.formatLeadingProperties(this.#parentSection).ruleText;\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(ruleText);\n Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.RULE_VIA_CONTEXT_MENU);\n }, {jslogContext: 'copy-rule'});\n\n contextMenu.headerSection().appendItem(\n i18nString(UIStrings.copyCssDeclarationAsJs), this.copyCssDeclarationAsJs.bind(this),\n {jslogContext: 'copy-css-declaration-as-js'});\n\n contextMenu.clipboardSection().appendItem(i18nString(UIStrings.copyAllDeclarations), () => {\n const allDeclarationText = StylesSidebarPane.formatLeadingProperties(this.#parentSection).allDeclarationText;\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(allDeclarationText);\n Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.ALL_DECLARATIONS_VIA_CONTEXT_MENU);\n }, {jslogContext: 'copy-all-declarations'});\n\n contextMenu.clipboardSection().appendItem(\n i18nString(UIStrings.copyAllCssDeclarationsAsJs), this.copyAllCssDeclarationAsJs.bind(this),\n {jslogContext: 'copy-all-css-declarations-as-js'});\n\n // TODO(changhaohan): conditionally add this item only when there are changes to copy\n contextMenu.defaultSection().appendItem(i18nString(UIStrings.copyAllCSSChanges), async () => {\n const allChanges = await this.parentPane().getFormattedChanges();\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(allChanges);\n Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.ALL_CHANGES_VIA_STYLES_TAB);\n }, {jslogContext: 'copy-all-css-changes'});\n\n contextMenu.footerSection().appendItem(i18nString(UIStrings.viewComputedValue), () => {\n void this.viewComputedValue();\n }, {jslogContext: 'view-computed-value'});\n\n return contextMenu;\n }\n\n private async viewComputedValue(): Promise {\n const computedStyleWidget = ElementsPanel.instance().getComputedStyleWidget();\n\n if (!computedStyleWidget.isShowing()) {\n await UI.ViewManager.ViewManager.instance().showView('Computed');\n }\n\n let propertyNamePattern = '';\n if (this.isShorthand) {\n propertyNamePattern = '^' + this.property.name + '-';\n } else {\n propertyNamePattern = '^' + this.property.name + '$';\n }\n const regex = new RegExp(propertyNamePattern, 'i');\n await computedStyleWidget.filterComputedStyles(regex);\n\n computedStyleWidget.input.setValue(this.property.name);\n computedStyleWidget.input.element.focus();\n }\n\n private copyCssDeclarationAsJs(): void {\n const cssDeclarationValue = getCssDeclarationAsJavascriptProperty(this.property);\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(cssDeclarationValue);\n Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.DECLARATION_AS_JS_VIA_CONTEXT_MENU);\n }\n\n private copyAllCssDeclarationAsJs(): void {\n const leadingProperties = this.#parentSection.style().leadingProperties();\n const cssDeclarationsAsJsProperties =\n leadingProperties.filter(property => !property.disabled).map(getCssDeclarationAsJavascriptProperty);\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.copyText(cssDeclarationsAsJsProperties.join(',\\n'));\n Host.userMetrics.styleTextCopied(Host.UserMetrics.StyleTextCopied.ALL_DECLARATINS_AS_JS_VIA_CONTEXT_MENU);\n }\n\n private navigateToSource(element: Element, omitFocus?: boolean): void {\n if (!this.#parentSection.navigable) {\n return;\n }\n const propertyNameClicked = element === this.nameElement;\n const uiLocation = Bindings.CSSWorkspaceBinding.CSSWorkspaceBinding.instance().propertyUILocation(\n this.property, propertyNameClicked);\n if (uiLocation) {\n void Common.Revealer.reveal(uiLocation, omitFocus);\n }\n }\n\n startEditingValue(): void {\n const context: Context = {\n expanded: this.expanded,\n hasChildren: this.isExpandable(),\n isEditingName: false,\n originalProperty: this.property,\n previousContent: this.value,\n };\n\n // Grid definitions are often multiline. Instead of showing the authored text reformat it a little bit nicer.\n if (SDK.CSSMetadata.cssMetadata().isGridAreaDefiningProperty(this.name)) {\n const splitResult =\n TextUtils.TextUtils.Utils.splitStringByRegexes(this.value, [SDK.CSSMetadata.GridAreaRowRegex]);\n context.previousContent = splitResult.map(result => result.value.trim()).join('\\n');\n }\n\n this.#startEditing(context);\n }\n\n startEditingName(): void {\n const context: Context = {\n expanded: this.expanded,\n hasChildren: this.isExpandable(),\n isEditingName: true,\n originalProperty: this.property,\n previousContent: this.name.split('\\n').map(l => l.trim()).join('\\n'),\n };\n\n this.#startEditing(context);\n }\n\n #startEditing(context: Context): void {\n this.contextForTest = context;\n\n // FIXME: we don't allow editing of longhand properties under a shorthand right now.\n if (this.parent instanceof StylePropertyTreeElement && this.parent.isShorthand) {\n return;\n }\n\n const selectedElement = context.isEditingName ? this.nameElement : this.valueElement;\n if (!selectedElement) {\n return;\n }\n\n if (UI.UIUtils.isBeingEdited(selectedElement)) {\n return;\n }\n\n // Lie about our children to prevent expanding on double click and to collapse shorthands.\n this.setExpandable(false);\n\n selectedElement.parentElement?.classList.add('child-editing');\n selectedElement.textContent = context.previousContent; // remove color swatch and the like\n\n function pasteHandler(this: StylePropertyTreeElement, context: Context, event: Event): void {\n const clipboardEvent = (event as ClipboardEvent);\n const clipboardData = clipboardEvent.clipboardData;\n if (!clipboardData) {\n return;\n }\n\n const data = clipboardData.getData('Text');\n if (!data) {\n return;\n }\n const colonIdx = data.indexOf(':');\n if (colonIdx < 0) {\n return;\n }\n const name = data.substring(0, colonIdx).trim();\n const value = data.substring(colonIdx + 1).trim();\n\n event.preventDefault();\n\n if (typeof context.originalName === 'undefined') {\n if (this.nameElement) {\n context.originalName = this.nameElement.textContent || '';\n }\n\n if (this.valueElement) {\n context.originalValue = this.valueElement.textContent || '';\n }\n }\n this.property.name = name;\n this.property.value = value;\n if (this.nameElement) {\n this.nameElement.textContent = name;\n this.nameElement.normalize();\n }\n\n if (this.valueElement) {\n this.valueElement.textContent = value;\n this.valueElement.normalize();\n }\n\n const target = (event.target as HTMLElement);\n void this.editingCommitted(target.textContent || '', context, 'forward');\n }\n\n function blurListener(this: StylePropertyTreeElement, context: Context, event: Event): void {\n const target = (event.target as HTMLElement);\n let text: (string|null) = target.textContent;\n if (!context.isEditingName) {\n text = this.value || text;\n }\n void this.editingCommitted(text || '', context, '');\n }\n\n this.originalPropertyText = this.property.propertyText || '';\n\n this.parentPaneInternal.setEditingStyle(true, this);\n selectedElement.parentElement?.scrollIntoViewIfNeeded(false);\n\n this.prompt = new CSSPropertyPrompt(this, context.isEditingName, Array.from(this.#gridNames ?? []));\n this.prompt.setAutocompletionTimeout(0);\n\n this.prompt.addEventListener(UI.TextPrompt.Events.TEXT_CHANGED, () => {\n void this.applyFreeFlowStyleTextEdit(context);\n });\n\n const invalidString = this.property.getInvalidStringForInvalidProperty();\n if (invalidString) {\n UI.ARIAUtils.alert(invalidString);\n }\n\n const proxyElement = this.prompt.attachAndStartEditing(selectedElement, blurListener.bind(this, context));\n this.navigateToSource(selectedElement, true);\n\n proxyElement.addEventListener('keydown', this.editingNameValueKeyDown.bind(this, context), false);\n proxyElement.addEventListener('keypress', this.editingNameValueKeyPress.bind(this, context), false);\n if (context.isEditingName) {\n proxyElement.addEventListener('paste', pasteHandler.bind(this, context), false);\n proxyElement.addEventListener('contextmenu', this.handleContextMenuEvent.bind(this, context), false);\n }\n\n selectedElement.getComponentSelection()?.selectAllChildren(selectedElement);\n }\n\n private editingNameValueKeyDown(context: Context, event: Event): void {\n if (event.handled) {\n return;\n }\n\n const keyboardEvent = (event as KeyboardEvent);\n const target = (keyboardEvent.target as HTMLElement);\n let result;\n if ((keyboardEvent.key === 'Enter' && !keyboardEvent.shiftKey) ||\n (context.isEditingName && keyboardEvent.key === ' ')) {\n result = 'forward';\n } else if (\n keyboardEvent.keyCode === UI.KeyboardShortcut.Keys.Esc.code ||\n keyboardEvent.key === Platform.KeyboardUtilities.ESCAPE_KEY) {\n result = 'cancel';\n } else if (\n !context.isEditingName && this.newProperty &&\n keyboardEvent.keyCode === UI.KeyboardShortcut.Keys.Backspace.code) {\n // For a new property, when Backspace is pressed at the beginning of new property value, move back to the property name.\n const selection = target.getComponentSelection();\n if (selection && selection.isCollapsed && !selection.focusOffset) {\n event.preventDefault();\n result = 'backward';\n }\n } else if (keyboardEvent.key === 'Tab') {\n result = keyboardEvent.shiftKey ? 'backward' : 'forward';\n event.preventDefault();\n }\n\n if (result) {\n switch (result) {\n case 'cancel':\n this.editingCancelled(null, context);\n break;\n case 'forward':\n case 'backward':\n void this.editingCommitted(target.textContent || '', context, result);\n break;\n }\n\n event.consume();\n return;\n }\n }\n\n private editingNameValueKeyPress(context: Context, event: Event): void {\n function shouldCommitValueSemicolon(text: string, cursorPosition: number): boolean {\n // FIXME: should this account for semicolons inside comments?\n let openQuote = '';\n for (let i = 0; i < cursorPosition; ++i) {\n const ch = text[i];\n if (ch === '\\\\' && openQuote !== '') {\n ++i;\n } // skip next character inside string\n else if (!openQuote && (ch === '\"' || ch === '\\'')) {\n openQuote = ch;\n } else if (openQuote === ch) {\n openQuote = '';\n }\n }\n return !openQuote;\n }\n\n const keyboardEvent = (event as KeyboardEvent);\n const target = (keyboardEvent.target as HTMLElement);\n const keyChar = String.fromCharCode(keyboardEvent.charCode);\n const selectionLeftOffset = this.#selectionLeftOffset(target);\n const isFieldInputTerminated =\n (context.isEditingName ? keyChar === ':' :\n keyChar === ';' && selectionLeftOffset !== null &&\n shouldCommitValueSemicolon(target.textContent || '', selectionLeftOffset));\n if (isFieldInputTerminated) {\n // Enter or colon (for name)/semicolon outside of string (for value).\n event.consume(true);\n void this.editingCommitted(target.textContent || '', context, 'forward');\n return;\n }\n }\n\n /** @returns Selection offset relative to `element` */\n #selectionLeftOffset(element: HTMLElement): number|null {\n const selection = element.getComponentSelection();\n if (!selection?.containsNode(element, true)) {\n return null;\n }\n\n let leftOffset = selection.anchorOffset;\n let node: ChildNode|(Node | null) = selection.anchorNode;\n\n while (node !== element) {\n while (node?.previousSibling) {\n node = node.previousSibling;\n leftOffset += node.textContent?.length ?? 0;\n }\n node = node?.parentNodeOrShadowHost() ?? null;\n }\n\n return leftOffset;\n }\n\n private async applyFreeFlowStyleTextEdit(context: Context): Promise {\n if (!this.prompt || !this.parentPaneInternal.node()) {\n return;\n }\n\n const enteredText = this.prompt.text();\n if (context.isEditingName && enteredText.includes(':')) {\n void this.editingCommitted(enteredText, context, 'forward');\n return;\n }\n\n const valueText = this.prompt.textWithCurrentSuggestion();\n if (valueText.includes(';')) {\n return;\n }\n // Prevent destructive side-effects during live-edit. crbug.com/433889\n const parentNode = this.parentPaneInternal.node();\n if (parentNode) {\n const isPseudo = Boolean(parentNode.pseudoType());\n if (isPseudo) {\n if (this.name.toLowerCase() === 'content') {\n return;\n }\n const lowerValueText = valueText.trim().toLowerCase();\n if (lowerValueText.startsWith('content:') || lowerValueText === 'display: none') {\n return;\n }\n }\n }\n\n if (context.isEditingName) {\n if (valueText.includes(':')) {\n await this.applyStyleText(valueText, false);\n } else if (this.hasBeenEditedIncrementally) {\n await this.applyOriginalStyle(context);\n }\n } else {\n if (this.nameElement) {\n await this.applyStyleText(`${this.nameElement.textContent}: ${valueText}`, false);\n }\n }\n }\n\n kickFreeFlowStyleEditForTest(): Promise {\n const context = this.contextForTest;\n return this.applyFreeFlowStyleTextEdit((context as Context));\n }\n\n editingEnded(context: Context): void {\n this.setExpandable(context.hasChildren);\n if (context.expanded) {\n this.expand();\n }\n const editedElement = context.isEditingName ? this.nameElement : this.valueElement;\n // The proxyElement has been deleted, no need to remove listener.\n if (editedElement && editedElement.parentElement) {\n editedElement.parentElement.classList.remove('child-editing');\n }\n\n this.parentPaneInternal.setEditingStyle(false);\n }\n\n editingCancelled(element: Element|null, context: Context): void {\n this.removePrompt();\n\n if (this.hasBeenEditedIncrementally) {\n void this.applyOriginalStyle(context);\n } else if (this.newProperty && this.treeOutline) {\n this.treeOutline.removeChild(this);\n }\n this.updateTitle();\n\n // This should happen last, as it clears the info necessary to restore the property value after [Page]Up/Down changes.\n this.editingEnded(context);\n }\n\n private async applyOriginalStyle(context: Context): Promise {\n await this.applyStyleText(this.originalPropertyText, false, context.originalProperty);\n }\n\n private findSibling(moveDirection: string): StylePropertyTreeElement|null {\n let target: (StylePropertyTreeElement|null)|this = this;\n do {\n const sibling: UI.TreeOutline.TreeElement|null =\n moveDirection === 'forward' ? target.nextSibling : target.previousSibling;\n target = sibling instanceof StylePropertyTreeElement ? sibling : null;\n } while (target && target.inherited());\n\n return target;\n }\n\n private async editingCommitted(userInput: string, context: Context, moveDirection: string): Promise {\n this.removePrompt();\n this.editingEnded(context);\n const isEditingName = context.isEditingName;\n // If the underlying property has been ripped out, always assume that the value having been entered was\n // a name-value pair and attempt to process it via the SDK.\n if (!this.nameElement || !this.valueElement) {\n return;\n }\n\n const nameElementValue = this.nameElement.textContent || '';\n const nameValueEntered = (isEditingName && nameElementValue.includes(':')) || !this.property;\n\n // Determine where to move to before making changes\n let createNewProperty = false;\n let moveToSelector = false;\n const isDataPasted = typeof context.originalName !== 'undefined';\n const isDirtyViaPaste = isDataPasted &&\n (this.nameElement.textContent !== context.originalName ||\n this.valueElement.textContent !== context.originalValue);\n const isPropertySplitPaste =\n isDataPasted && isEditingName && this.valueElement.textContent !== context.originalValue;\n let moveTo: (StylePropertyTreeElement|null)|this = this;\n const moveToOther = (isEditingName !== (moveDirection === 'forward'));\n const abandonNewProperty = this.newProperty && !userInput && (moveToOther || isEditingName);\n if (moveDirection === 'forward' && (!isEditingName || isPropertySplitPaste) ||\n moveDirection === 'backward' && isEditingName) {\n moveTo = moveTo.findSibling(moveDirection);\n if (!moveTo) {\n if (moveDirection === 'forward' && (!this.newProperty || userInput)) {\n createNewProperty = true;\n } else if (moveDirection === 'backward') {\n moveToSelector = true;\n }\n }\n }\n\n // Make the Changes and trigger the moveToNextCallback after updating.\n let moveToIndex = -1;\n if (moveTo !== null && this.treeOutline) {\n moveToIndex = this.treeOutline.rootElement().indexOfChild((moveTo as UI.TreeOutline.TreeElement));\n }\n const blankInput = Platform.StringUtilities.isWhitespace(userInput);\n const shouldCommitNewProperty = this.newProperty &&\n (isPropertySplitPaste || moveToOther || (!moveDirection && !isEditingName) || (isEditingName && blankInput) ||\n nameValueEntered);\n if (((userInput !== context.previousContent || isDirtyViaPaste) && !this.newProperty) || shouldCommitNewProperty) {\n let propertyText;\n if (nameValueEntered) {\n propertyText = this.nameElement.textContent;\n } else if (\n blankInput ||\n (this.newProperty && Platform.StringUtilities.isWhitespace(this.valueElement.textContent || ''))) {\n propertyText = '';\n } else {\n if (isEditingName) {\n propertyText = userInput + ': ' + this.property.value;\n } else {\n propertyText = this.property.name + ': ' + userInput;\n }\n }\n await this.applyStyleText(propertyText || '', true);\n moveToNextCallback.call(this, this.newProperty, !blankInput, this.#parentSection);\n } else {\n if (isEditingName) {\n this.property.name = userInput;\n } else {\n this.property.value = userInput;\n }\n if (!isDataPasted && !this.newProperty) {\n this.updateTitle();\n }\n moveToNextCallback.call(this, this.newProperty, false, this.#parentSection);\n }\n\n /**\n * The Callback to start editing the next/previous property/selector.\n */\n function moveToNextCallback(\n this: StylePropertyTreeElement, alreadyNew: boolean, valueChanged: boolean,\n section: StylePropertiesSection): void {\n if (!moveDirection) {\n this.parentPaneInternal.resetFocus();\n return;\n }\n\n // User just tabbed through without changes.\n if (moveTo && moveTo.parent) {\n if (isEditingName) {\n moveTo.startEditingValue();\n } else {\n moveTo.startEditingName();\n }\n return;\n }\n\n // User has made a change then tabbed, wiping all the original treeElements.\n // Recalculate the new treeElement for the same property we were going to edit next.\n if (moveTo && !moveTo.parent) {\n const rootElement = section.propertiesTreeOutline.rootElement();\n if (moveDirection === 'forward' && blankInput && !isEditingName) {\n --moveToIndex;\n }\n if (moveToIndex >= rootElement.childCount() && !this.newProperty) {\n createNewProperty = true;\n } else {\n const treeElement =\n (moveToIndex >= 0 ? rootElement.childAt(moveToIndex) : null) as StylePropertyTreeElement | null;\n if (treeElement) {\n if (alreadyNew && blankInput) {\n if (moveDirection === 'forward') {\n treeElement.startEditingName();\n } else {\n treeElement.startEditingValue();\n }\n } else if (!isEditingName || isPropertySplitPaste) {\n treeElement.startEditingName();\n } else {\n treeElement.startEditingValue();\n }\n return;\n }\n if (!alreadyNew) {\n moveToSelector = true;\n }\n }\n }\n\n // Create a new attribute in this section (or move to next editable selector if possible).\n if (createNewProperty) {\n if (alreadyNew && !valueChanged && (isEditingName !== (moveDirection === 'backward'))) {\n return;\n }\n\n section.addNewBlankProperty().startEditingName();\n return;\n }\n\n if (abandonNewProperty) {\n moveTo = this.findSibling(moveDirection);\n const sectionToEdit = (moveTo || moveDirection === 'backward') ? section : section.nextEditableSibling();\n if (sectionToEdit) {\n if (sectionToEdit.style().parentRule) {\n sectionToEdit.startEditingSelector();\n } else {\n sectionToEdit.moveEditorFromSelector(moveDirection);\n }\n }\n return;\n }\n\n if (moveToSelector) {\n if (section.style().parentRule) {\n section.startEditingSelector();\n } else {\n section.moveEditorFromSelector(moveDirection);\n }\n }\n }\n }\n\n private removePrompt(): void {\n // BUG 53242. This cannot go into editingEnded(), as it should always happen first for any editing outcome.\n if (this.prompt) {\n this.prompt.detach();\n this.prompt = null;\n }\n }\n\n styleTextAppliedForTest(): void {\n }\n\n applyStyleText(styleText: string, majorChange: boolean, property?: SDK.CSSProperty.CSSProperty|null): Promise {\n return this.applyStyleThrottler.schedule(this.innerApplyStyleText.bind(this, styleText, majorChange, property));\n }\n\n private async innerApplyStyleText(\n styleText: string, majorChange: boolean, property?: SDK.CSSProperty.CSSProperty|null): Promise {\n // this.property might have been nulled at the end of the last innerApplyStyleText\n if (!this.treeOutline || !this.property) {\n return;\n }\n\n const oldStyleRange = this.style.range;\n if (!oldStyleRange) {\n return;\n }\n\n const hasBeenEditedIncrementally = this.hasBeenEditedIncrementally;\n styleText = styleText.replace(/[\\xA0\\t]/g, ' ').trim(); // Replace   with whitespace.\n if (!styleText.length && majorChange && this.newProperty && !hasBeenEditedIncrementally) {\n // The user deleted everything and never applied a new property value via Up/Down scrolling/live editing, so remove the tree element and update.\n this.parent && this.parent.removeChild(this);\n return;\n }\n\n const currentNode = this.parentPaneInternal.node();\n this.parentPaneInternal.setUserOperation(true);\n\n styleText += Platform.StringUtilities.findUnclosedCssQuote(styleText);\n styleText += ')'.repeat(Platform.StringUtilities.countUnmatchedLeftParentheses(styleText));\n\n // Append a \";\" if the new text does not end in \";\".\n // FIXME: this does not handle trailing comments.\n if (styleText.length && !/;\\s*$/.test(styleText)) {\n styleText += ';';\n }\n\n const overwriteProperty = !this.newProperty || hasBeenEditedIncrementally;\n let success: boolean = await this.property.setText(styleText, majorChange, overwriteProperty);\n // Revert to the original text if applying the new text failed\n if (hasBeenEditedIncrementally && majorChange && !success) {\n majorChange = false;\n success = await this.property.setText(this.originalPropertyText, majorChange, overwriteProperty);\n }\n this.parentPaneInternal.setUserOperation(false);\n\n // TODO: using this.property.index to access its containing StyleDeclaration's property will result in\n // off-by-1 errors when the containing StyleDeclaration's respective property has already been deleted.\n // These referencing logic needs to be updated to be more robust.\n const updatedProperty = property || this.style.propertyAt(this.property.index);\n const isPropertyWithinBounds = this.property.index < this.style.allProperties().length;\n if (!success || (!updatedProperty && isPropertyWithinBounds)) {\n if (majorChange) {\n // It did not apply, cancel editing.\n if (this.newProperty) {\n this.treeOutline.removeChild(this);\n } else {\n this.updateTitle();\n }\n }\n this.styleTextAppliedForTest();\n return;\n }\n if (updatedProperty) {\n this.listItemElement.classList.toggle('changed', this.isPropertyChanged(updatedProperty));\n this.parentPane().updateChangeStatus();\n }\n\n this.matchedStylesInternal.resetActiveProperties();\n this.hasBeenEditedIncrementally = true;\n\n // null check for updatedProperty before setting this.property as the code never expects this.property to be undefined or null.\n // This occurs when deleting the last index of a StylePropertiesSection as this.style._allProperties array gets updated\n // before we index it when setting the value for updatedProperty\n const deleteProperty = majorChange && !styleText.length;\n if (deleteProperty) {\n this.#parentSection.resetToolbars();\n } else if (!deleteProperty && updatedProperty) {\n this.property = updatedProperty;\n }\n\n if (currentNode === this.node()) {\n this.updatePane();\n }\n\n this.styleTextAppliedForTest();\n }\n\n override ondblclick(): boolean {\n return true; // handled\n }\n\n override isEventWithinDisclosureTriangle(event: Event): boolean {\n return event.target === this.expandElement;\n }\n}\nexport interface Context {\n expanded: boolean;\n hasChildren: boolean;\n isEditingName: boolean;\n originalProperty?: SDK.CSSProperty.CSSProperty;\n originalName?: string;\n originalValue?: string;\n previousContent: string;\n}\n"]} \ No newline at end of file diff --git a/public/panels/elements/StylePropertyTreeElement.test.js b/public/panels/elements/StylePropertyTreeElement.test.js index 5f0cdb222..a9a5dec4d 100644 --- a/public/panels/elements/StylePropertyTreeElement.test.js +++ b/public/panels/elements/StylePropertyTreeElement.test.js @@ -596,6 +596,24 @@ describeWithMockConnection('StylePropertyTreeElement', () => { const colorSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-swatch'); assert.isNull(colorSwatch); }); + it('correctly renders currentcolor', () => { + const stylePropertyTreeElement = getTreeElement('background-color', 'currentcolor'); + stylePropertyTreeElement.setComputedStyles(new Map([['color', 'red']])); + stylePropertyTreeElement.updateTitle(); + const colorSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-swatch'); + assert.isOk(colorSwatch); + assert.isOk(colorSwatch.getColor()); + assert.strictEqual(colorSwatch?.getColor()?.asString(), 'red'); + }); + it('renders relative colors using currentcolor', () => { + const stylePropertyTreeElement = getTreeElement('color', 'hsl(from currentcolor h calc(s/2) l / alpha)'); + stylePropertyTreeElement.setComputedStyles(new Map([['color', 'blue']])); + stylePropertyTreeElement.updateTitle(); + const colorSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-swatch'); + assert.isOk(colorSwatch); + assert.isOk(colorSwatch.getColor()); + assert.strictEqual(colorSwatch?.getColor()?.asString("hsl" /* Common.Color.Format.HSL */), 'hsl(240deg 50% 50%)'); + }); }); describe('BezierRenderer', () => { it('renders the easing function swatch', () => { diff --git a/public/panels/elements/StylePropertyTreeElement.test.js.map b/public/panels/elements/StylePropertyTreeElement.test.js.map index 0ec88111f..95efca863 100644 --- a/public/panels/elements/StylePropertyTreeElement.test.js.map +++ b/public/panels/elements/StylePropertyTreeElement.test.js.map @@ -1 +1 @@ -{"version":3,"file":"StylePropertyTreeElement.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/elements/StylePropertyTreeElement.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as Protocol from '../../generated/protocol.js';\nimport * as Bindings from '../../models/bindings/bindings.js';\nimport * as TextUtils from '../../models/text_utils/text_utils.js';\nimport * as Workspace from '../../models/workspace/workspace.js';\nimport {renderElementIntoDOM} from '../../testing/DOMHelpers.js';\nimport {createTarget} from '../../testing/EnvironmentHelpers.js';\nimport {expectCall} from '../../testing/ExpectStubCall.js';\nimport {describeWithMockConnection, setMockConnectionResponseHandler} from '../../testing/MockConnection.js';\nimport * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';\nimport * as InlineEditor from '../../ui/legacy/components/inline_editor/inline_editor.js';\nimport * as LegacyUI from '../../ui/legacy/legacy.js';\n\nimport * as ElementsComponents from './components/components.js';\nimport * as Elements from './elements.js';\n\ndescribeWithMockConnection('StylePropertyTreeElement', () => {\n let stylesSidebarPane: Elements.StylesSidebarPane.StylesSidebarPane;\n let mockStylePropertiesSection: sinon.SinonStubbedInstance;\n let mockCssStyleDeclaration: sinon.SinonStubbedInstance;\n let mockMatchedStyles: sinon.SinonStubbedInstance;\n let mockVariableMap: Record;\n\n beforeEach(async () => {\n stylesSidebarPane = Elements.StylesSidebarPane.StylesSidebarPane.instance({forceNew: true});\n mockVariableMap = {\n '--a': 'red',\n '--b': 'blue',\n '--blue': 'blue',\n '--space': 'shorter hue',\n '--garbage-space': 'this-is-garbage-text',\n '--prop': 'customproperty',\n '--zero': '0',\n };\n\n mockStylePropertiesSection = sinon.createStubInstance(Elements.StylePropertiesSection.StylePropertiesSection);\n mockCssStyleDeclaration = sinon.createStubInstance(SDK.CSSStyleDeclaration.CSSStyleDeclaration);\n mockMatchedStyles = sinon.createStubInstance(SDK.CSSMatchedStyles.CSSMatchedStyles);\n mockMatchedStyles.keyframes.returns([]);\n mockMatchedStyles.availableCSSVariables.returns(Object.keys(mockVariableMap));\n mockMatchedStyles.computeCSSVariable.callsFake((style, name) => {\n return {\n value: mockVariableMap[name],\n declaration: sinon.createStubInstance(SDK.CSSProperty.CSSProperty),\n };\n });\n mockCssStyleDeclaration.leadingProperties.returns([]);\n mockCssStyleDeclaration.styleSheetId = 'stylesheet-id' as Protocol.CSS.StyleSheetId;\n mockCssStyleDeclaration.range = new TextUtils.TextRange.TextRange(0, 0, 10, 10);\n\n const workspace = Workspace.Workspace.WorkspaceImpl.instance({forceNew: true});\n const resourceMapping =\n new Bindings.ResourceMapping.ResourceMapping(SDK.TargetManager.TargetManager.instance(), workspace);\n Bindings.CSSWorkspaceBinding.CSSWorkspaceBinding.instance(\n {forceNew: true, resourceMapping, targetManager: SDK.TargetManager.TargetManager.instance()});\n });\n\n function getTreeElement(name: string, value: string, longhandProperties: Protocol.CSS.CSSProperty[] = []) {\n const property = new SDK.CSSProperty.CSSProperty(\n mockCssStyleDeclaration, 0, name, value, true, false, true, false, '', undefined, longhandProperties);\n return new Elements.StylePropertyTreeElement.StylePropertyTreeElement({\n stylesPane: stylesSidebarPane,\n section: mockStylePropertiesSection,\n matchedStyles: mockMatchedStyles,\n property,\n isShorthand: longhandProperties.length > 0,\n inherited: false,\n overloaded: false,\n newProperty: true,\n });\n }\n\n describe('updateTitle', () => {\n it('timing swatch, shadow swatch and length swatch are not shown for longhands expanded inside shorthands',\n async () => {\n const stylePropertyTreeElement = getTreeElement('', '', [\n {name: 'animation-timing-function', value: 'linear'},\n {name: 'text-shadow', value: '2px 2px #ff0000'},\n {name: 'box-shadow', value: '2px 2px #ff0000'},\n {name: 'margin-top', value: '10px'},\n ]);\n await stylePropertyTreeElement.onpopulate();\n\n stylePropertyTreeElement.updateTitle();\n stylePropertyTreeElement.expand();\n\n const assertNullSwatchOnChildAt = (n: number, swatchSelector: string) => {\n const childValueElement =\n (stylePropertyTreeElement.childAt(n) as Elements.StylePropertyTreeElement.StylePropertyTreeElement)\n .valueElement;\n assert.exists(childValueElement);\n assert.notExists(childValueElement.querySelector(swatchSelector));\n };\n assertNullSwatchOnChildAt(0, '[is=\"bezier-swatch\"]');\n assertNullSwatchOnChildAt(1, '[is=\"css-shadow-swatch\"]');\n assertNullSwatchOnChildAt(2, '[is=\"css-shadow-swatch\"]');\n assertNullSwatchOnChildAt(3, 'devtools-css-length');\n });\n\n describe('color-mix swatch', () => {\n it('should show color mix swatch when color-mix is used with a color', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'color-mix(in srgb, red, blue)');\n stylePropertyTreeElement.updateTitle();\n\n const colorMixSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-mix-swatch');\n const colorSwatches =\n Array.from(stylePropertyTreeElement.valueElement?.querySelectorAll('devtools-color-swatch') || []);\n assert.exists(colorMixSwatch);\n assert.exists(colorSwatches.find(colorSwatch => colorSwatch.textContent === 'red'));\n assert.exists(colorSwatches.find(colorSwatch => colorSwatch.textContent === 'blue'));\n });\n\n it('should show color mix swatch when color-mix is used with a known variable as color', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'color-mix(in srgb, var(--a), var(--b))');\n stylePropertyTreeElement.updateTitle();\n\n const colorMixSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-mix-swatch');\n const cssVarSwatches =\n Array.from(stylePropertyTreeElement.valueElement?.querySelectorAll('devtools-css-var-swatch') || []);\n assert.exists(colorMixSwatch);\n assert.exists(cssVarSwatches.find(cssVarSwatch => cssVarSwatch.textContent === 'var(--a)'));\n assert.exists(cssVarSwatches.find(cssVarSwatch => cssVarSwatch.textContent === 'var(--b)'));\n });\n\n it('should not show color mix swatch when color-mix is used with an unknown variable as color', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'color-mix(in srgb, var(--unknown-a), var(--b))');\n stylePropertyTreeElement.updateTitle();\n\n const colorMixSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-mix-swatch');\n assert.isNull(colorMixSwatch);\n });\n\n it('should show color mix swatch when color-mix is used with a known variable in interpolation method', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'color-mix(in lch var(--space), var(--a), var(--b))');\n stylePropertyTreeElement.updateTitle();\n\n const colorMixSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-mix-swatch');\n assert.exists(colorMixSwatch);\n assert.isTrue(colorMixSwatch.textContent?.includes('var(--space)'));\n });\n\n it('should show color mix swatch when color-mix is used with an known variable in interpolation method even if it is not a valid method',\n () => {\n const stylePropertyTreeElement =\n getTreeElement('color', 'color-mix(in lch var(--garbage-space), var(--a), var(--b))');\n stylePropertyTreeElement.updateTitle();\n\n const colorMixSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-mix-swatch');\n assert.exists(colorMixSwatch);\n assert.isTrue(colorMixSwatch.textContent?.includes('var(--garbage-space)'));\n });\n\n it('should not show color mix swatch when color-mix is used with an unknown variable in interpolation method',\n () => {\n const stylePropertyTreeElement =\n getTreeElement('color', 'color-mix(in lch var(--not-existing-space), var(--a), var(--b))');\n\n stylePropertyTreeElement.updateTitle();\n\n const colorMixSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-mix-swatch');\n assert.isNull(colorMixSwatch);\n });\n\n it('shows a popover with it\\'s computed color as RGB if possible', () => {\n const cssPropertyWithColorMix = new SDK.CSSProperty.CSSProperty(\n mockCssStyleDeclaration, 0, 'color', 'color-mix(in srgb, red 50%, yellow)', true, false, true, false, '',\n undefined);\n const stylePropertyTreeElement = new Elements.StylePropertyTreeElement.StylePropertyTreeElement({\n stylesPane: stylesSidebarPane,\n section: mockStylePropertiesSection,\n matchedStyles: mockMatchedStyles,\n property: cssPropertyWithColorMix,\n isShorthand: false,\n inherited: false,\n overloaded: false,\n newProperty: true,\n });\n\n const addPopoverSpy = sinon.spy(stylesSidebarPane, 'addPopover');\n stylePropertyTreeElement.updateTitle();\n const colorMixSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-mix-swatch');\n assert.exists(colorMixSwatch);\n renderElementIntoDOM(colorMixSwatch);\n\n assert.isTrue(addPopoverSpy.calledOnce);\n assert.strictEqual(addPopoverSpy.args[0][0], colorMixSwatch.icon);\n assert.strictEqual(addPopoverSpy.args[0][1].contents()?.textContent, '#ff8000');\n });\n\n it('shows a popover with it\\'s computed color as wide gamut if necessary', () => {\n const cssPropertyWithColorMix = new SDK.CSSProperty.CSSProperty(\n mockCssStyleDeclaration, 0, 'color', 'color-mix(in srgb, oklch(.5 .5 .5) 50%, yellow)', true, false, true,\n false, '', undefined);\n const stylePropertyTreeElement = new Elements.StylePropertyTreeElement.StylePropertyTreeElement({\n stylesPane: stylesSidebarPane,\n section: mockStylePropertiesSection,\n matchedStyles: mockMatchedStyles,\n property: cssPropertyWithColorMix,\n isShorthand: false,\n inherited: false,\n overloaded: false,\n newProperty: true,\n });\n\n const addPopoverSpy = sinon.spy(stylesSidebarPane, 'addPopover');\n stylePropertyTreeElement.updateTitle();\n const colorMixSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-mix-swatch');\n assert.exists(colorMixSwatch);\n renderElementIntoDOM(colorMixSwatch);\n\n assert.isTrue(addPopoverSpy.calledOnce);\n assert.strictEqual(addPopoverSpy.args[0][0], colorMixSwatch.icon);\n assert.strictEqual(addPopoverSpy.args[0][1].contents()?.textContent, 'color(srgb 1 0.24 0.17)');\n });\n\n it('propagates updates to outer color-mixes', () => {\n const cssPropertyWithColorMix = new SDK.CSSProperty.CSSProperty(\n mockCssStyleDeclaration, 0, 'color', 'color-mix(in srgb, color-mix(in oklch, red, green), blue)', true,\n false, true, false, '', undefined);\n const stylePropertyTreeElement = new Elements.StylePropertyTreeElement.StylePropertyTreeElement({\n stylesPane: stylesSidebarPane,\n section: mockStylePropertiesSection,\n matchedStyles: mockMatchedStyles,\n property: cssPropertyWithColorMix,\n isShorthand: false,\n inherited: false,\n overloaded: false,\n newProperty: true,\n });\n\n stylePropertyTreeElement.updateTitle();\n\n const outerColorMix = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-mix-swatch');\n assert.exists(outerColorMix);\n const handler = sinon.fake();\n outerColorMix.addEventListener(InlineEditor.ColorMixSwatch.Events.COLOR_CHANGED, handler);\n const innerColorMix = outerColorMix.querySelector('devtools-color-mix-swatch');\n assert.exists(innerColorMix);\n assert.strictEqual(outerColorMix.getText(), 'color-mix(in srgb, color-mix(in oklch, red, green), blue)');\n assert.strictEqual(innerColorMix.getText(), 'color-mix(in oklch, red, green)');\n innerColorMix.setFirstColor('blue');\n assert.deepStrictEqual(\n handler.args[0][0].data, {text: 'color-mix(in srgb, color-mix(in oklch, blue, green), blue)'});\n assert.strictEqual(outerColorMix.getText(), 'color-mix(in srgb, color-mix(in oklch, blue, green), blue)');\n\n // setFirstColor does not actually update the rendered color swatches or the textContent, which is why the first\n // color is still red here.\n const colorSwatch = innerColorMix.querySelector('devtools-color-swatch');\n assert.isOk(colorSwatch);\n const newColor = colorSwatch.getColor()?.as(Common.Color.Format.HEX);\n assert.isOk(newColor);\n colorSwatch.setColor(newColor);\n assert.strictEqual(outerColorMix.getText(), 'color-mix(in srgb, color-mix(in oklch, #ff0000, green), blue)');\n assert.deepStrictEqual(\n handler.args[1][0].data, {text: 'color-mix(in srgb, color-mix(in oklch, #ff0000, green), blue)'});\n });\n });\n\n describe('animation-name', () => {\n it('should link-swatch be rendered for animation-name declaration', () => {\n const stylePropertyTreeElement = getTreeElement('animation-name', 'first-keyframe');\n stylePropertyTreeElement.updateTitle();\n\n const animationNameSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-link-swatch');\n assert.isNotNull(animationNameSwatch);\n });\n\n it('should two link-swatches be rendered for animation-name declaration that contains two keyframe references',\n () => {\n const stylePropertyTreeElement = getTreeElement('animation-name', 'first-keyframe, second-keyframe');\n stylePropertyTreeElement.updateTitle();\n\n const animationNameSwatches =\n stylePropertyTreeElement.valueElement?.querySelectorAll('devtools-link-swatch');\n assert.strictEqual(animationNameSwatches?.length, 2);\n });\n });\n });\n\n it('applies the new style when the color format is changed', async () => {\n const stylePropertyTreeElement = getTreeElement('color', 'color(srgb .5 .5 1)');\n const applyStyleTextStub = sinon.stub(stylePropertyTreeElement, 'applyStyleText');\n // Make sure we don't leave a dangling promise behind:\n const returnValue = (async () => {})();\n await returnValue;\n applyStyleTextStub.returns(returnValue);\n\n stylePropertyTreeElement.updateTitle();\n\n const {valueElement} = stylePropertyTreeElement;\n assert.exists(valueElement);\n\n const swatch = valueElement.querySelector(\n `${InlineEditor.ColorSwatch.ColorSwatch.litTagName.value}`);\n\n assert.exists(swatch);\n\n const expectedColorString = swatch.getColor()?.asString(Common.Color.Format.LAB);\n assert.exists(expectedColorString);\n assert.match(expectedColorString, /lab\\([-.0-9]* [-.0-9]* [-.0-9]*\\)/);\n\n const newColor = swatch.getColor()?.as(Common.Color.Format.LAB);\n assert.isOk(newColor);\n swatch.setColorText(newColor);\n assert.deepEqual(stylePropertyTreeElement.renderedPropertyText(), `color: ${expectedColorString}`);\n\n assert.isTrue(applyStyleTextStub.alwaysCalledWith(`color: ${expectedColorString}`, false));\n });\n\n describe('Context menu', () => {\n const expectedHeaderSectionItemsLabels =\n ['Copy declaration', 'Copy property', 'Copy value', 'Copy rule', 'Copy declaration as JS'];\n const expectedClipboardSectionItemsLabels = ['Copy all declarations', 'Copy all declarations as JS'];\n const expectedDefaultSectionItemsLabels = ['Copy all CSS changes'];\n const expectedFooterSectionItemsLabels = ['View computed value'];\n\n it('should create a context menu', () => {\n const verifySection = (expectedSectionItemLabels: string[], sectionItems: LegacyUI.ContextMenu.Item[]) => {\n const sectionItemLabels = sectionItems.map(item => item.buildDescriptor().label);\n assert.deepEqual(sectionItemLabels, expectedSectionItemLabels);\n };\n const stylePropertyTreeElement = getTreeElement('', '');\n const event = new CustomEvent('contextmenu');\n const contextMenu = stylePropertyTreeElement.createCopyContextMenu(event);\n\n const headerSection = contextMenu.headerSection();\n const clipboardSection = contextMenu.clipboardSection();\n const defaultSection = contextMenu.defaultSection();\n const footerSection = contextMenu.footerSection();\n verifySection(expectedHeaderSectionItemsLabels, headerSection.items);\n verifySection(expectedClipboardSectionItemsLabels, clipboardSection.items);\n verifySection(expectedDefaultSectionItemsLabels, defaultSection.items);\n verifySection(expectedFooterSectionItemsLabels, footerSection.items);\n });\n });\n\n describe('CSS hints', () => {\n it('should create a hint for inline elements', () => {\n sinon.stub(stylesSidebarPane, 'node').returns({\n localName() {\n return 'span';\n },\n isSVGNode() {\n return false;\n },\n } as SDK.DOMModel.DOMNode);\n const stylePropertyTreeElement = getTreeElement('width', '100px');\n stylePropertyTreeElement.setComputedStyles(new Map([\n ['width', '100px'],\n ['display', 'inline'],\n ]));\n stylePropertyTreeElement.updateAuthoringHint();\n assert(\n stylePropertyTreeElement.listItemElement.classList.contains('inactive-property'),\n 'CSS hint was not rendered.');\n });\n\n it('should not create a hint for SVG elements', () => {\n sinon.stub(stylesSidebarPane, 'node').returns({\n localName() {\n return 'rect';\n },\n isSVGNode() {\n return true;\n },\n } as SDK.DOMModel.DOMNode);\n const stylePropertyTreeElement = getTreeElement('width', '100px');\n stylePropertyTreeElement.setComputedStyles(new Map([\n ['width', '100px'],\n ['display', 'inline'],\n ]));\n stylePropertyTreeElement.updateAuthoringHint();\n assert(\n !stylePropertyTreeElement.listItemElement.classList.contains('inactive-property'),\n 'CSS hint was rendered unexpectedly.');\n });\n });\n\n describe('custom-properties', () => {\n it('linkifies var functions to declarations', async () => {\n const cssCustomPropertyDef = new SDK.CSSProperty.CSSProperty(\n mockCssStyleDeclaration, 0, '--prop', 'value', true, false, true, false, '', undefined);\n mockMatchedStyles.computeCSSVariable.callsFake(\n (_, name) => name === '--prop' ?\n {value: 'computedvalue', declaration: cssCustomPropertyDef, fromFallback: false} :\n null);\n const renderValueSpy = sinon.spy(Elements.PropertyRenderer.Renderer, 'renderValueElement');\n\n const stylePropertyTreeElement = getTreeElement('prop', 'var(--prop)');\n stylePropertyTreeElement.updateTitle();\n\n const varSwatch =\n renderValueSpy.returnValues.find(value => value.firstChild instanceof InlineEditor.LinkSwatch.CSSVarSwatch)\n ?.firstChild as InlineEditor.LinkSwatch.CSSVarSwatch |\n undefined;\n assert.exists(varSwatch);\n const revealPropertySpy = sinon.spy(stylesSidebarPane, 'revealProperty');\n varSwatch.link?.linkElement?.click();\n assert.isTrue(revealPropertySpy.calledWith(cssCustomPropertyDef));\n });\n\n it('linkifies property definition to registrations', async () => {\n const addElementPopoverHook = sinon.stub(stylesSidebarPane, 'addPopover');\n const stylePropertyTreeElement = getTreeElement('--prop', 'value');\n stylePropertyTreeElement.updateTitle();\n\n assert.isTrue(addElementPopoverHook.calledOnce);\n\n const registration = sinon.createStubInstance(SDK.CSSMatchedStyles.CSSRegisteredProperty);\n mockMatchedStyles.getRegisteredProperty.callsFake(name => name === '--prop' ? registration : undefined);\n mockMatchedStyles.computeCSSVariable.returns(\n {value: 'computedvalue', declaration: sinon.createStubInstance(SDK.CSSProperty.CSSProperty)});\n const popoverContents = addElementPopoverHook.args[0][1].contents();\n assert.isTrue(popoverContents instanceof ElementsComponents.CSSVariableValueView.CSSVariableValueView);\n const {details} = popoverContents as ElementsComponents.CSSVariableValueView.CSSVariableValueView;\n assert.exists(details);\n\n const jumpToSectionSpy = sinon.spy(stylesSidebarPane, 'jumpToSection');\n details.goToDefinition();\n assert.isTrue(jumpToSectionSpy.calledOnceWithExactly(\n '--prop', Elements.StylesSidebarPane.REGISTERED_PROPERTY_SECTION_NAME));\n });\n\n it('linkifies var functions to initial-value registrations', async () => {\n mockMatchedStyles.computeCSSVariable.returns({\n value: 'computedvalue',\n declaration: sinon.createStubInstance(SDK.CSSMatchedStyles.CSSRegisteredProperty, {propertyName: '--prop'}),\n });\n const renderValueSpy = sinon.spy(Elements.PropertyRenderer.Renderer, 'renderValueElement');\n\n const stylePropertyTreeElement = getTreeElement('prop', 'var(--prop)');\n stylePropertyTreeElement.updateTitle();\n\n const varSwatch =\n renderValueSpy.returnValues.find(value => value.firstChild instanceof InlineEditor.LinkSwatch.CSSVarSwatch)\n ?.firstChild as InlineEditor.LinkSwatch.CSSVarSwatch |\n undefined;\n assert.exists(varSwatch);\n const jumpToPropertySpy = sinon.spy(stylesSidebarPane, 'jumpToProperty');\n varSwatch.link?.linkElement?.click();\n assert.isTrue(jumpToPropertySpy.calledWith(\n 'initial-value', '--prop', Elements.StylesSidebarPane.REGISTERED_PROPERTY_SECTION_NAME));\n });\n });\n\n describe('CSSVarSwatch', () => {\n it('should render a CSSVarSwatch for variable usage without fallback', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'var(--a)');\n stylePropertyTreeElement.updateTitle();\n assert.exists(stylePropertyTreeElement.valueElement);\n\n const cssVarSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-css-var-swatch');\n assert.exists(cssVarSwatch);\n\n const linkSwatch = cssVarSwatch.shadowRoot?.querySelector('devtools-base-link-swatch');\n assert.exists(linkSwatch);\n\n assert.strictEqual(cssVarSwatch.textContent, 'var(--a)');\n assert.strictEqual(linkSwatch.shadowRoot?.textContent, '--a');\n assert.strictEqual(stylePropertyTreeElement.valueElement.textContent, 'var(--a)');\n });\n\n it('should render a CSSVarSwatch for variable usage with fallback', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'var(--not-existing, red)');\n stylePropertyTreeElement.updateTitle();\n assert.exists(stylePropertyTreeElement.valueElement);\n\n const cssVarSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-css-var-swatch');\n assert.exists(cssVarSwatch);\n\n const linkSwatch = cssVarSwatch.shadowRoot?.querySelector('devtools-base-link-swatch');\n assert.exists(linkSwatch);\n\n assert.strictEqual(linkSwatch.shadowRoot?.textContent, '--not-existing');\n assert.strictEqual(cssVarSwatch.deepTextContent(), 'var(--not-existing, red)');\n assert.strictEqual(stylePropertyTreeElement.valueElement.textContent, 'var(--not-existing, red)');\n });\n\n it('should render a CSSVarSwatch inside CSSVarSwatch for variable usage with another variable fallback', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'var(--not-existing, var(--a))');\n stylePropertyTreeElement.updateTitle();\n assert.exists(stylePropertyTreeElement.valueElement);\n\n const cssVarSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-css-var-swatch');\n assert.exists(cssVarSwatch);\n\n const firstLinkSwatch = cssVarSwatch.shadowRoot?.querySelector('devtools-base-link-swatch');\n const insideCssVarSwatch = cssVarSwatch.querySelector('devtools-css-var-swatch');\n const secondLinkSwatch = insideCssVarSwatch?.shadowRoot?.querySelector('devtools-base-link-swatch');\n assert.strictEqual(stylePropertyTreeElement.valueElement.textContent, 'var(--not-existing, var(--a))');\n assert.strictEqual(firstLinkSwatch?.shadowRoot?.textContent, '--not-existing');\n assert.strictEqual(cssVarSwatch.textContent, 'var(--not-existing, var(--a))');\n assert.strictEqual(secondLinkSwatch?.shadowRoot?.textContent, '--a');\n assert.strictEqual(insideCssVarSwatch?.textContent, 'var(--a)');\n });\n\n it('should render a CSSVarSwatch inside CSSVarSwatch for variable usage with calc expression as fallback', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'var(--not-existing, calc(15px + 20px))');\n stylePropertyTreeElement.updateTitle();\n assert.exists(stylePropertyTreeElement.valueElement);\n\n const cssVarSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-css-var-swatch');\n assert.exists(cssVarSwatch);\n\n const firstLinkSwatch = cssVarSwatch.shadowRoot?.querySelector('devtools-base-link-swatch');\n\n assert.strictEqual(stylePropertyTreeElement.valueElement.textContent, 'var(--not-existing, calc(15px + 20px))');\n assert.strictEqual(firstLinkSwatch?.shadowRoot?.textContent, '--not-existing');\n assert.strictEqual(cssVarSwatch.textContent, 'var(--not-existing, calc(15px + 20px))');\n });\n\n it('should render a CSSVarSwatch inside CSSVarSwatch for variable usage with color and also a color swatch', () => {\n for (const varName of ['--a', '--not-existing']) {\n const stylePropertyTreeElement = getTreeElement('color', `var(${varName}, var(--blue))`);\n stylePropertyTreeElement.updateTitle();\n assert.exists(stylePropertyTreeElement.valueElement);\n\n const cssVarSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-css-var-swatch');\n assert.exists(cssVarSwatch);\n\n const colorSwatch = cssVarSwatch.querySelector('devtools-color-swatch');\n assert.exists(colorSwatch);\n assert.isTrue(InlineEditor.ColorSwatch.ColorSwatch.isColorSwatch(colorSwatch));\n\n const firstLinkSwatch = cssVarSwatch.shadowRoot?.querySelector('devtools-base-link-swatch');\n\n assert.strictEqual(stylePropertyTreeElement.valueElement.textContent, `var(${varName}, var(--blue))`);\n assert.strictEqual(firstLinkSwatch?.shadowRoot?.textContent, varName);\n assert.strictEqual(cssVarSwatch.textContent, `var(${varName}, var(--blue))`);\n }\n });\n\n it('should render CSSVarSwatches for multiple var() usages in the same property declaration', () => {\n const stylePropertyTreeElement = getTreeElement('--shadow', 'var(--a) var(--b)');\n stylePropertyTreeElement.updateTitle();\n\n const cssVarSwatches = stylePropertyTreeElement.valueElement?.querySelectorAll('devtools-css-var-swatch');\n assert.strictEqual(cssVarSwatches?.length, 2);\n });\n\n it('should render a CSSVarSwatch for var() with spaces', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'var( --test )');\n stylePropertyTreeElement.updateTitle();\n assert.exists(stylePropertyTreeElement.valueElement);\n\n const cssVarSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-css-var-swatch');\n assert.exists(cssVarSwatch);\n\n const linkSwatch = cssVarSwatch.shadowRoot?.querySelector('devtools-base-link-swatch');\n assert.strictEqual(linkSwatch?.shadowRoot?.textContent, '--test');\n assert.strictEqual(cssVarSwatch.textContent, 'var( --test )');\n assert.strictEqual(stylePropertyTreeElement.valueElement.textContent, 'var( --test )');\n });\n\n it('connects nested color swatches', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'var(--void, red)');\n stylePropertyTreeElement.updateTitle();\n assert.exists(stylePropertyTreeElement.valueElement);\n\n const cssVarSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-css-var-swatch');\n assert.exists(cssVarSwatch);\n const outerColorSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-swatch');\n assert.exists(outerColorSwatch);\n const innerColorSwatch = cssVarSwatch.querySelector('devtools-color-swatch');\n assert.exists(innerColorSwatch);\n assert.notStrictEqual(outerColorSwatch, innerColorSwatch);\n const color = new Common.Color.Lab(1, 0, 0, null, undefined);\n innerColorSwatch.setColor(color);\n assert.strictEqual(outerColorSwatch.getColor(), color);\n });\n\n it('only connects nested color swatches if the fallback is actually taken', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'var(--blue, red)');\n stylePropertyTreeElement.updateTitle();\n assert.exists(stylePropertyTreeElement.valueElement);\n\n const cssVarSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-css-var-swatch');\n assert.exists(cssVarSwatch);\n const outerColorSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-swatch');\n assert.exists(outerColorSwatch);\n const innerColorSwatch = cssVarSwatch.querySelector('devtools-color-swatch');\n assert.exists(innerColorSwatch);\n assert.notStrictEqual(outerColorSwatch, innerColorSwatch);\n const color = new Common.Color.Lab(1, 0, 0, null, undefined);\n innerColorSwatch.setColor(color);\n assert.strictEqual(outerColorSwatch.getColor()?.asString(), 'blue');\n });\n });\n\n function setUpStyles(\n cssModel: SDK.CSSModel.CSSModel,\n cssProperties: {name: string, value: string}[],\n styleSheetId = '0' as Protocol.CSS.StyleSheetId,\n origin = Protocol.CSS.StyleSheetOrigin.Regular,\n selector = 'div',\n ): Promise {\n const matchedPayload: Protocol.CSS.RuleMatch[] = [{\n rule: {\n selectorList: {selectors: [{text: selector}], text: selector},\n origin,\n style: {cssProperties, shorthandEntries: []},\n },\n matchingSelectors: [0],\n }];\n if (cssModel.styleSheetHeaderForId(styleSheetId)) {\n cssModel.styleSheetRemoved(styleSheetId);\n }\n cssModel.styleSheetAdded({\n styleSheetId,\n frameId: '' as Protocol.Page.FrameId,\n sourceURL: '',\n origin,\n title: '',\n disabled: false,\n isInline: false,\n isMutable: false,\n isConstructed: false,\n startLine: 0,\n startColumn: 0,\n length: 0,\n endLine: 0,\n endColumn: 0,\n });\n const node = sinon.createStubInstance(SDK.DOMModel.DOMNode);\n node.id = 0 as Protocol.DOM.NodeId;\n return SDK.CSSMatchedStyles.CSSMatchedStyles.create({\n cssModel,\n node,\n inlinePayload: null,\n attributesPayload: null,\n matchedPayload,\n pseudoPayload: [],\n inheritedPayload: [],\n inheritedPseudoPayload: [],\n animationsPayload: [],\n parentLayoutNodeId: undefined,\n positionTryRules: [],\n propertyRules: [],\n cssPropertyRegistrations: [],\n fontPaletteValuesRule: undefined,\n });\n }\n\n describe('VariableRenderer', () => {\n it('computes the text for var()s correctly', async () => {\n const cssModel = new SDK.CSSModel.CSSModel(createTarget());\n\n async function matchProperty(value: string, name = 'color') {\n const matchedStyles = await setUpStyles(cssModel, [\n {name: '--blue', value: 'blue'},\n {name, value},\n ]);\n const property = matchedStyles.nodeStyles()[0].leadingProperties()[1];\n const stylePropertyTreeElement = new Elements.StylePropertyTreeElement.StylePropertyTreeElement({\n stylesPane: stylesSidebarPane,\n section: mockStylePropertiesSection,\n matchedStyles,\n property,\n isShorthand: false,\n inherited: false,\n overloaded: false,\n newProperty: true,\n });\n\n const ast =\n SDK.CSSPropertyParser.tokenizeDeclaration(stylePropertyTreeElement.name, stylePropertyTreeElement.value);\n assert.exists(ast);\n const matching = SDK.CSSPropertyParser.BottomUpTreeMatching.walk(\n ast, [new Elements.StylePropertyTreeElement\n .VariableRenderer(stylePropertyTreeElement, stylePropertyTreeElement.property.ownerStyle)\n .matcher()]);\n\n const res = {\n hasUnresolvedVars: matching.hasUnresolvedVars(ast.tree),\n computedText: matching.getComputedText(ast.tree),\n };\n return res;\n }\n\n assert.deepStrictEqual(\n await matchProperty('var( --blue )'), {hasUnresolvedVars: false, computedText: 'color: blue'});\n assert.deepStrictEqual(\n await matchProperty('var(--no, var(--blue))'), {hasUnresolvedVars: false, computedText: 'color: blue'});\n assert.deepStrictEqual(\n await matchProperty('pre var(--no) post'),\n {hasUnresolvedVars: true, computedText: 'color: pre var(--no) post'});\n assert.deepStrictEqual(\n await matchProperty('var(--no, var(--no2))'),\n {hasUnresolvedVars: true, computedText: 'color: var(--no, var(--no2))'});\n });\n\n it('layers correctly with the font renderer', () => {\n const stylePropertyTreeElement = getTreeElement('font-size', 'calc(1 + var(--no))');\n stylePropertyTreeElement.updateTitle();\n assert.exists(stylePropertyTreeElement.valueElement?.querySelector('devtools-css-var-swatch'));\n });\n });\n\n describe('ColorRenderer', () => {\n it('correctly renders children of the color swatch', () => {\n const value = 'rgb(255, var(--zero), var(--zero))';\n const stylePropertyTreeElement = getTreeElement('color', value);\n stylePropertyTreeElement.updateTitle();\n\n assert.strictEqual(stylePropertyTreeElement.valueElement?.textContent, value);\n const colorSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-swatch');\n assert.exists(colorSwatch);\n assert.strictEqual(colorSwatch.getColor()?.asString(Common.Color.Format.HEX), '#ff0000');\n\n const varSwatches = stylePropertyTreeElement.valueElement?.querySelectorAll('devtools-css-var-swatch');\n assert.exists(varSwatches);\n assert.lengthOf(varSwatches, 2);\n });\n\n it('connects correctly with an inner angle swatch', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'hsl(120deg, 50%, 25%)');\n stylePropertyTreeElement.updateTitle();\n const colorSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-swatch');\n\n assert.exists(colorSwatch);\n assert.strictEqual(colorSwatch.getColor()?.asString(Common.Color.Format.HSL), 'hsl(120deg 50% 25%)');\n const eventHandler = sinon.stub<[InlineEditor.ColorSwatch.ColorChangedEvent]>();\n colorSwatch.addEventListener(InlineEditor.ColorSwatch.ColorChangedEvent.eventName, eventHandler);\n\n const angleSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-css-angle');\n assert.exists(angleSwatch);\n angleSwatch.updateAngle({value: 130, unit: InlineEditor.CSSAngleUtils.AngleUnit.DEG});\n assert.strictEqual(colorSwatch.getColor()?.asString(Common.Color.Format.HSL), 'hsl(130deg 50% 25%)');\n assert.isTrue(eventHandler.calledOnce);\n assert.strictEqual(eventHandler.args[0][0].data.color, colorSwatch.getColor());\n });\n\n it('renders relative colors', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'hsl( from var(--blue) h calc(s/2) l / alpha)');\n stylePropertyTreeElement.updateTitle();\n const colorSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-swatch');\n assert.isOk(colorSwatch);\n assert.isOk(colorSwatch.getColor());\n assert.strictEqual(colorSwatch?.getColor()?.asString(Common.Color.Format.HSL), 'hsl(240deg 50% 50%)');\n });\n\n it('does not render relative colors if property text is invalid', () => {\n const invalidColor = 'hsl( from var(--zero) h calc(s/2) l / alpha)';\n const stylePropertyTreeElement = getTreeElement('color', invalidColor);\n stylePropertyTreeElement.updateTitle();\n const colorSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-swatch');\n assert.isNull(colorSwatch);\n });\n });\n\n describe('BezierRenderer', () => {\n it('renders the easing function swatch', () => {\n const stylePropertyTreeElement = getTreeElement('animation-timing-function', 'ease-out');\n stylePropertyTreeElement.updateTitle();\n assert.instanceOf(stylePropertyTreeElement.valueElement?.firstChild, InlineEditor.Swatches.BezierSwatch);\n });\n });\n\n describe('UrlRenderer', () => {\n it('linkifies and unescapes urls', () => {\n const stylePropertyTreeElement = getTreeElement('--url', 'url(devtools:\\\\/\\\\/abc)');\n stylePropertyTreeElement.updateTitle();\n\n assert.strictEqual(stylePropertyTreeElement.valueElement?.textContent, 'url(devtools://abc)');\n });\n });\n\n describe('StringRenderer', () => {\n it('unescapes strings', () => {\n const stylePropertyTreeElement = getTreeElement('content', '\"\\\\2716\"');\n stylePropertyTreeElement.updateTitle();\n\n assert.strictEqual(\n (stylePropertyTreeElement.valueElement?.firstElementChild as HTMLElement | null | undefined)?.title,\n '\"\\u2716\"');\n });\n });\n\n describe('ShadowRenderer', () => {\n it('parses shadows correctly', () => {\n const parseShadow = (property: string, value: string, success: boolean) => {\n const stylePropertyTreeElement = getTreeElement(property, value);\n stylePropertyTreeElement.updateTitle();\n\n assert.strictEqual(\n stylePropertyTreeElement.valueElement?.firstElementChild instanceof InlineEditor.Swatches.CSSShadowSwatch,\n success);\n assert.strictEqual(stylePropertyTreeElement.valueElement?.textContent, value);\n };\n\n const parseTextShadowSuccess = (value: string) => parseShadow('text-shadow', value, true);\n const parseTextShadowFailure = (value: string) => parseShadow('text-shadow', value, false);\n const parseBoxShadowSuccess = (value: string) => parseShadow('box-shadow', value, true);\n const parseBoxShadowFailure = (value: string) => parseShadow('box-shadow', value, false);\n\n parseTextShadowSuccess('0 0');\n parseTextShadowSuccess('1px 2px');\n parseTextShadowSuccess('1px 2px black');\n parseTextShadowSuccess('1px 2px 2px');\n parseTextShadowSuccess('rgb(0, 0, 0) 1px 2px 2px');\n parseTextShadowSuccess('1px 2px 2px rgb(0, 0, 0)');\n parseTextShadowSuccess('1px 2px black, 0 0 #ffffff');\n parseTextShadowSuccess('1px -2px black, 0 0 rgb(0, 0, 0), 3px 3.5px 3px');\n parseTextShadowSuccess('1px -2px black, 0 0 rgb(0, 0, 0), 3px 3.5px 3px !important');\n parseTextShadowSuccess('1px 2px black, , 0 0 #ffffff');\n\n parseTextShadowFailure('');\n parseTextShadowFailure('0');\n parseTextShadowFailure('1 2 black !important');\n parseTextShadowFailure('1px black 2px');\n parseTextShadowFailure('1px 2px 2px 3px');\n parseTextShadowFailure('inset 1px 2px 2px');\n parseTextShadowFailure('red 1px 2px 2px red');\n parseTextShadowFailure('1px 2px rgb(0, 0, 0) 2px');\n parseTextShadowFailure('hello 1px 2px');\n parseTextShadowFailure('1px 2px black 0 0 #ffffff');\n // TODO(crbug.com/40945390) Add coverage after rolling codemirror: parseTextShadowFailure('1px2px');\n parseTextShadowFailure('1px 2pxrgb(0, 0, 0)');\n\n parseBoxShadowSuccess('0 0');\n parseBoxShadowSuccess('1px 2px');\n parseBoxShadowSuccess('1px 2px black');\n parseBoxShadowSuccess('1px 2px 2px');\n parseBoxShadowSuccess('1px 2px 2px 3px');\n parseBoxShadowSuccess('inset 1px 2px');\n parseBoxShadowSuccess('1px 2px inset');\n parseBoxShadowSuccess('INSET 1px 2px 2px 3px');\n parseBoxShadowSuccess('rgb(0, 0, 0) 1px 2px 2px');\n parseBoxShadowSuccess('inset rgb(0, 0, 0) 1px 2px 2px');\n parseBoxShadowSuccess('inset 1px 2px 2px 3px rgb(0, 0, 0)');\n parseBoxShadowSuccess('1px 2px 2px 3px rgb(0, 0, 0) inset');\n parseBoxShadowSuccess('1px 2px black, inset 0 0 #ffffff');\n parseBoxShadowSuccess('1px -2px black, inset 0 0 rgb(0, 0, 0), 3px 3.5px 3px 4px');\n parseBoxShadowSuccess('1px 2px black, , 0 0 #ffffff');\n\n parseBoxShadowFailure('');\n parseBoxShadowFailure('0');\n parseBoxShadowFailure('1 2 black');\n parseBoxShadowFailure('1px black 2px');\n parseBoxShadowFailure('1px 2px 2px 3px 4px');\n parseBoxShadowFailure('1px 2px 2px inset 3px');\n parseBoxShadowFailure('inset 1px 2px 2px inset');\n parseBoxShadowFailure('1px 2px rgb(0, 0, 0) 2px');\n parseBoxShadowFailure('hello 1px 2px');\n parseBoxShadowFailure('1px 2px black 0 0 #ffffff');\n // TODO(crbug.com/40945390) Add coverage after rolling codemirror: parseBoxShadowFailure('1px2px');\n parseBoxShadowFailure('1px 2pxrgb(0, 0, 0)');\n });\n\n it('renders the shadow swatch and color swatch', () => {\n const stylePropertyTreeElement = getTreeElement('box-shadow', 'inset 10px 10px blue');\n stylePropertyTreeElement.updateTitle();\n\n assert.instanceOf(\n stylePropertyTreeElement.valueElement?.firstElementChild, InlineEditor.Swatches.CSSShadowSwatch);\n const colorSwatch =\n stylePropertyTreeElement.valueElement?.firstElementChild?.querySelector('devtools-color-swatch');\n assert.exists(colorSwatch);\n assert.strictEqual(colorSwatch.getColor()?.asString(), 'blue');\n });\n\n it('renders multiple icons for multiple shadows', () => {\n const stylePropertyTreeElement = getTreeElement('box-shadow', 'inset 10px 11px blue, notashadow, 6px 5px red');\n stylePropertyTreeElement.updateTitle();\n\n const swatches = stylePropertyTreeElement.valueElement?.querySelectorAll('css-shadow-swatch');\n assert.exists(swatches);\n assert.strictEqual(swatches.length, 2);\n assert.strictEqual(swatches[0].textContent, 'inset 10px 11px blue');\n assert.strictEqual(swatches[1].textContent, '6px 5px red');\n });\n\n it('correctly parses text-shadow', () => {\n const stylePropertyTreeElement =\n getTreeElement('text-shadow', 'inset 10px 11px blue, 6px 5px red, 5px 5px 0 0 yellow');\n stylePropertyTreeElement.updateTitle();\n const swatches = stylePropertyTreeElement.valueElement?.querySelectorAll('css-shadow-swatch');\n assert.exists(swatches);\n assert.strictEqual(swatches.length, 1);\n assert.strictEqual(swatches[0].textContent, '6px 5px red');\n });\n\n it('renders a color-mix child', () => {\n const stylePropertyTreeElement = getTreeElement('box-shadow', '10px 11px color-mix(in srgb, red, blue)');\n stylePropertyTreeElement.updateTitle();\n assert.instanceOf(\n stylePropertyTreeElement.valueElement?.firstElementChild, InlineEditor.Swatches.CSSShadowSwatch);\n const swatches = stylePropertyTreeElement.valueElement?.querySelectorAll('devtools-color-mix-swatch');\n assert.exists(swatches);\n });\n\n it('renders shadow icon in the presence of a var()', () => {\n mockVariableMap['--offset'] = '10px 10px';\n mockVariableMap['--shadow'] = '10px 10px blue';\n\n const stylePropertyTreeElement = getTreeElement('box-shadow', 'var(--offset) red, var(--shadow)');\n stylePropertyTreeElement.updateTitle();\n const swatches = stylePropertyTreeElement.valueElement?.querySelectorAll('css-shadow-swatch');\n assert.exists(swatches);\n assert.strictEqual(swatches.length, 2);\n assert.strictEqual(swatches[0].textContent, 'var(--offset) red');\n assert.strictEqual(swatches[1].textContent, 'var(--shadow)');\n });\n\n it('opens a shadow editor with the correct values', () => {\n mockVariableMap['--offset'] = '10px 10px';\n\n const stylePropertyTreeElement =\n getTreeElement('box-shadow', 'var(--offset) red, inset 8px 9px 10px 11px yellow');\n stylePropertyTreeElement.updateTitle();\n const swatches = stylePropertyTreeElement.valueElement?.querySelectorAll('css-shadow-swatch');\n assert.exists(swatches);\n assert.strictEqual(swatches.length, 2);\n\n const showPopoverStub = sinon.stub(stylePropertyTreeElement.parentPane().swatchPopoverHelper(), 'show');\n\n const editorProperties = (editor: InlineEditor.CSSShadowEditor.CSSShadowEditor): string[] =>\n Array.from(editor.contentElement.querySelectorAll('.shadow-editor-field'))\n .map(\n field => field.querySelector('input')?.value ??\n Array.from(field.querySelectorAll('button'))\n .map(button => button.classList.contains('enabled') ? button.textContent : undefined)\n .filter((b): b is string => Boolean(b)))\n .flat();\n\n {\n swatches[0].iconElement().click();\n assert.isTrue(showPopoverStub.calledOnce);\n assert.instanceOf(showPopoverStub.args[0][0], InlineEditor.CSSShadowEditor.CSSShadowEditor);\n const editor = showPopoverStub.args[0][0] as InlineEditor.CSSShadowEditor.CSSShadowEditor;\n const text = editorProperties(editor);\n assert.deepStrictEqual(text, ['Outset', '10px', '10px', '0', '0']);\n }\n\n {\n swatches[1].iconElement().click();\n assert.isTrue(showPopoverStub.calledTwice);\n assert.instanceOf(showPopoverStub.args[1][0], InlineEditor.CSSShadowEditor.CSSShadowEditor);\n const editor = showPopoverStub.args[1][0] as InlineEditor.CSSShadowEditor.CSSShadowEditor;\n const text = editorProperties(editor);\n assert.deepStrictEqual(text, ['Inset', '8px', '9px', '10px', '11px']);\n }\n });\n\n it('updates the style for shadow editor changes', () => {\n const stylePropertyTreeElement = getTreeElement('box-shadow', '10px 11px red');\n stylePropertyTreeElement.updateTitle();\n const swatches = stylePropertyTreeElement.valueElement?.querySelectorAll('css-shadow-swatch');\n assert.exists(swatches);\n assert.strictEqual(swatches.length, 1);\n const showPopoverStub = sinon.stub(stylePropertyTreeElement.parentPane().swatchPopoverHelper(), 'show');\n swatches[0].iconElement().click();\n assert.isTrue(showPopoverStub.calledOnce);\n\n const applyStyleTextStub = sinon.stub(stylePropertyTreeElement, 'applyStyleText');\n const button =\n showPopoverStub.args[0][0].contentElement.querySelector('.shadow-editor-button-right') as HTMLElement | null;\n button?.click();\n\n assert.isTrue(applyStyleTextStub.calledOnceWithExactly('box-shadow: inset 10px 11px red', false));\n });\n\n it('updates the style for shadow editor changes and respects ordering', () => {\n mockVariableMap['--y-color'] = '11px red';\n const stylePropertyTreeElement = getTreeElement('box-shadow', '10px var(--y-color)');\n stylePropertyTreeElement.updateTitle();\n const swatches = stylePropertyTreeElement.valueElement?.querySelectorAll('css-shadow-swatch');\n assert.exists(swatches);\n assert.strictEqual(swatches.length, 1);\n const showPopoverStub = sinon.stub(stylePropertyTreeElement.parentPane().swatchPopoverHelper(), 'show');\n swatches[0].iconElement().click();\n assert.isTrue(showPopoverStub.calledOnce);\n\n const applyStyleTextStub = sinon.stub(stylePropertyTreeElement, 'applyStyleText');\n const inputs = Array.from(showPopoverStub.args[0][0].contentElement.querySelectorAll('.shadow-editor-field'))\n .map(field => field.querySelector('input'));\n assert.exists(inputs[3]);\n inputs[3].value = '13px';\n inputs[3].dispatchEvent(new InputEvent('input', {data: '13px'}));\n\n assert.isTrue(applyStyleTextStub.calledOnceWithExactly('box-shadow: 10px 11px 13px red', false));\n });\n\n it('correctly builds and updates the shadow model', () => {\n mockVariableMap['--props'] = '12px 13px red';\n const stylePropertyTreeElement = getTreeElement('box-shadow', '10px 11px red, var(--props)');\n stylePropertyTreeElement.updateTitle();\n const swatches = stylePropertyTreeElement.valueElement?.querySelectorAll('css-shadow-swatch');\n assert.exists(swatches);\n assert.lengthOf(swatches, 2);\n\n assert.isTrue(swatches[0].model().isBoxShadow());\n assert.isFalse(swatches[0].model().inset());\n assert.strictEqual(swatches[0].model().offsetX().asCSSText(), '10px');\n assert.strictEqual(swatches[0].model().offsetY().asCSSText(), '11px');\n assert.strictEqual(swatches[0].model().blurRadius().asCSSText(), '0');\n assert.strictEqual(swatches[0].model().spreadRadius().asCSSText(), '0');\n\n swatches[0].model().setSpreadRadius(new InlineEditor.CSSShadowEditor.CSSLength(8, 'px'));\n swatches[0].model().setBlurRadius(new InlineEditor.CSSShadowEditor.CSSLength(5, 'px'));\n assert.strictEqual(swatches[0].model().blurRadius().asCSSText(), '5px');\n assert.strictEqual(swatches[0].model().spreadRadius().asCSSText(), '8px');\n\n assert.isTrue(swatches[1].model().isBoxShadow());\n assert.isFalse(swatches[1].model().inset());\n assert.strictEqual(swatches[1].model().offsetX().asCSSText(), '12px');\n assert.strictEqual(swatches[1].model().offsetY().asCSSText(), '13px');\n assert.strictEqual(swatches[1].model().blurRadius().asCSSText(), '0');\n assert.strictEqual(swatches[1].model().spreadRadius().asCSSText(), '0');\n\n swatches[1].model().setBlurRadius(new InlineEditor.CSSShadowEditor.CSSLength(5, 'px'));\n swatches[1].model().setSpreadRadius(new InlineEditor.CSSShadowEditor.CSSLength(8, 'px'));\n assert.strictEqual(swatches[1].model().blurRadius().asCSSText(), '5px');\n assert.strictEqual(swatches[1].model().spreadRadius().asCSSText(), '8px');\n });\n\n class StubSyntaxnode implements CodeMirror.SyntaxNode {\n parent: CodeMirror.SyntaxNode|null = null;\n firstChild: CodeMirror.SyntaxNode|null = null;\n lastChild: CodeMirror.SyntaxNode|null = null;\n childAfter(): CodeMirror.SyntaxNode|null {\n return null;\n }\n childBefore(): CodeMirror.SyntaxNode|null {\n return null;\n }\n enter(): CodeMirror.SyntaxNode|null {\n return null;\n }\n nextSibling: CodeMirror.SyntaxNode|null = null;\n prevSibling: CodeMirror.SyntaxNode|null = null;\n cursor(): CodeMirror.TreeCursor {\n throw new Error('Method not implemented.');\n }\n resolve(): CodeMirror.SyntaxNode {\n return this;\n }\n resolveInner(): CodeMirror.SyntaxNode {\n return this;\n }\n enterUnfinishedNodesBefore(): CodeMirror.SyntaxNode {\n return this;\n }\n toTree(): CodeMirror.Tree {\n throw new Error('Method not implemented.');\n }\n getChild(): CodeMirror.SyntaxNode|null {\n throw new Error('Method not implemented.');\n }\n getChildren(): CodeMirror.SyntaxNode[] {\n throw new Error('Method not implemented.');\n }\n from: number = 0;\n to: number = 0;\n type = new CodeMirror.NodeType();\n name: string = '';\n tree: CodeMirror.Tree|null = null;\n node: CodeMirror.SyntaxNode = this;\n matchContext(): boolean {\n return false;\n }\n }\n\n it('shadow model renders text properties, authored properties, and computed text properties correctly', () => {\n const renderingContext = sinon.createStubInstance(Elements.PropertyRenderer.RenderingContext);\n const expansionContext = sinon.createStubInstance(Elements.PropertyRenderer.RenderingContext);\n const y = new StubSyntaxnode();\n const spread = new StubSyntaxnode();\n const blur = new StubSyntaxnode();\n const variable = new StubSyntaxnode();\n const properties = [\n {\n value: '10px',\n source: null,\n expansionContext: null,\n propertyType: Elements.StylePropertyTreeElement.ShadowPropertyType.X,\n },\n {\n value: y,\n source: null,\n expansionContext: null,\n propertyType: Elements.StylePropertyTreeElement.ShadowPropertyType.Y,\n },\n {\n value: blur,\n source: variable,\n expansionContext,\n propertyType: Elements.StylePropertyTreeElement.ShadowPropertyType.BLUR,\n },\n {\n value: spread,\n source: variable,\n expansionContext,\n propertyType: Elements.StylePropertyTreeElement.ShadowPropertyType.SPREAD,\n },\n ];\n\n sinon.stub(Elements.PropertyRenderer.Renderer, 'render').callsFake((nodeOrNodes, context) => {\n if (!Array.isArray(nodeOrNodes)) {\n nodeOrNodes = [nodeOrNodes];\n }\n const nodes = nodeOrNodes\n .map(node => {\n switch (node) {\n case y:\n return context === renderingContext && document.createTextNode('y');\n case blur:\n return context === expansionContext && document.createTextNode('blur');\n case spread:\n return context === expansionContext && document.createTextNode('spread');\n case variable:\n return context === renderingContext && document.createTextNode('var()');\n default:\n return undefined;\n }\n })\n .filter((b): b is Text => Boolean(b));\n return {\n nodes,\n nodeGroups: [nodes],\n cssControls: new Map(),\n };\n });\n const model = new Elements.StylePropertyTreeElement.ShadowModel(\n Elements.PropertyMatchers.ShadowType.BOX_SHADOW, properties, renderingContext);\n\n const container = document.createElement('div');\n model.renderContents(container);\n assert.strictEqual(container.textContent, '10px y var()');\n\n model.setBlurRadius(new InlineEditor.CSSShadowEditor.CSSLength(12, 'px'));\n model.renderContents(container);\n assert.strictEqual(container.textContent, '10px y 12px spread');\n assert.deepStrictEqual(properties.map(p => p.source), [null, null, null, null]);\n });\n });\n\n describe('AnchorFunctionRenderer', () => {\n let anchorDecoratedForTestStub: sinon.SinonStub;\n let getAnchorBySpecifierStub: sinon.SinonStub;\n let revealStub: sinon.SinonStub;\n let hideDOMNodeHighlightStub: sinon.SinonStub;\n let highlightMock: sinon.SinonExpectation;\n let fakeParentNode: SDK.DOMModel.DOMNode;\n let fakeDOMNode: SDK.DOMModel.DOMNode;\n\n beforeEach(() => {\n fakeParentNode = {\n localName() {\n return 'span';\n },\n isSVGNode() {\n return false;\n },\n getAnchorBySpecifier() {\n return Promise.resolve(fakeDOMNode);\n },\n } as SDK.DOMModel.DOMNode;\n\n fakeDOMNode = {\n localName() {\n return 'span';\n },\n isSVGNode() {\n return false;\n },\n highlight() {\n highlightMock();\n },\n } as SDK.DOMModel.DOMNode;\n highlightMock = sinon.mock();\n anchorDecoratedForTestStub =\n sinon.stub(Elements.StylePropertyTreeElement.AnchorFunctionRenderer.prototype, 'anchorDecoratedForTest');\n getAnchorBySpecifierStub =\n sinon.stub(SDK.DOMModel.DOMNode.prototype, 'getAnchorBySpecifier').resolves(fakeDOMNode);\n revealStub = sinon.stub(Common.Revealer.RevealerRegistry.prototype, 'reveal');\n hideDOMNodeHighlightStub = sinon.stub(SDK.OverlayModel.OverlayModel, 'hideDOMNodeHighlight');\n });\n\n afterEach(() => {\n anchorDecoratedForTestStub.restore();\n getAnchorBySpecifierStub.restore();\n revealStub.restore();\n hideDOMNodeHighlightStub.restore();\n });\n\n it('renders anchor() function correctly', async () => {\n const stylePropertyTreeElement = getTreeElement('left', 'anchor(top)');\n\n stylePropertyTreeElement.updateTitle();\n\n assert.strictEqual(stylePropertyTreeElement.valueElement!.textContent, 'anchor(top)');\n });\n\n it('renders `AnchorFunctionLinkSwatch` after decorating the element', async () => {\n const waitForDecorationPromise = expectCall(anchorDecoratedForTestStub);\n const stylePropertyTreeElement = getTreeElement('left', 'anchor(--identifier top)');\n sinon.stub(stylePropertyTreeElement, 'node').returns(fakeParentNode);\n\n stylePropertyTreeElement.updateTitle();\n await waitForDecorationPromise;\n const anchorFunctionLinkSwatch =\n stylePropertyTreeElement.valueElement!.querySelector('devtools-anchor-function-link-swatch')! as\n ElementsComponents.AnchorFunctionLinkSwatch.AnchorFunctionLinkSwatch;\n\n assert.strictEqual(anchorFunctionLinkSwatch.dataForTest().identifier, '--identifier');\n });\n\n it('should highlight node when `onMouseEnter` triggered from `AnchorFunctionLinkSwatch`', async () => {\n const waitForDecorationPromise = expectCall(anchorDecoratedForTestStub);\n const stylePropertyTreeElement = getTreeElement('left', 'anchor(--identifier top)');\n sinon.stub(stylePropertyTreeElement, 'node').returns(fakeParentNode);\n\n stylePropertyTreeElement.updateTitle();\n await waitForDecorationPromise;\n const anchorFunctionLinkSwatch =\n stylePropertyTreeElement.valueElement!.querySelector('devtools-anchor-function-link-swatch')! as\n ElementsComponents.AnchorFunctionLinkSwatch.AnchorFunctionLinkSwatch;\n anchorFunctionLinkSwatch.dataForTest().onMouseEnter();\n\n assert.isTrue(highlightMock.calledOnce);\n });\n\n it('should clear DOM highlight when `onMouseLeave` triggered from `AnchorFunctionLinkSwatch`', async () => {\n const waitForDecorationPromise = expectCall(anchorDecoratedForTestStub);\n const stylePropertyTreeElement = getTreeElement('left', 'anchor(--identifier top)');\n sinon.stub(stylePropertyTreeElement, 'node').returns(fakeParentNode);\n\n stylePropertyTreeElement.updateTitle();\n await waitForDecorationPromise;\n const anchorFunctionLinkSwatch =\n stylePropertyTreeElement.valueElement!.querySelector('devtools-anchor-function-link-swatch')! as\n ElementsComponents.AnchorFunctionLinkSwatch.AnchorFunctionLinkSwatch;\n anchorFunctionLinkSwatch.dataForTest().onMouseLeave();\n\n assert.isTrue(hideDOMNodeHighlightStub.calledOnce);\n });\n\n it('should reveal anchor node when `onLinkActivate` triggered from `AnchorFunctionLinkSwatch`', async () => {\n const waitForDecorationPromise = expectCall(anchorDecoratedForTestStub);\n const stylePropertyTreeElement = getTreeElement('left', 'anchor(--identifier top)');\n sinon.stub(stylePropertyTreeElement, 'node').returns(fakeParentNode);\n\n stylePropertyTreeElement.updateTitle();\n await waitForDecorationPromise;\n const anchorFunctionLinkSwatch =\n stylePropertyTreeElement.valueElement!.querySelector('devtools-anchor-function-link-swatch')! as\n ElementsComponents.AnchorFunctionLinkSwatch.AnchorFunctionLinkSwatch;\n anchorFunctionLinkSwatch.dataForTest().onLinkActivate();\n\n assert.isTrue(revealStub.calledOnce);\n assert.isTrue(revealStub.calledWith(fakeDOMNode));\n });\n });\n\n describe('AnchorFunctionRenderer', () => {\n let anchorDecoratedForTestStub: sinon.SinonStub;\n let getAnchorBySpecifierStub: sinon.SinonStub;\n let highlightMock: sinon.SinonExpectation;\n let fakeDOMNode: SDK.DOMModel.DOMNode;\n\n beforeEach(() => {\n fakeDOMNode = {\n localName() {\n return 'span';\n },\n isSVGNode() {\n return false;\n },\n highlight() {\n highlightMock();\n },\n } as SDK.DOMModel.DOMNode;\n highlightMock = sinon.mock();\n anchorDecoratedForTestStub =\n sinon.stub(Elements.StylePropertyTreeElement.PositionAnchorRenderer.prototype, 'anchorDecoratedForTest');\n getAnchorBySpecifierStub =\n sinon.stub(SDK.DOMModel.DOMNode.prototype, 'getAnchorBySpecifier').resolves(fakeDOMNode);\n });\n\n afterEach(() => {\n anchorDecoratedForTestStub.restore();\n getAnchorBySpecifierStub.restore();\n });\n\n it('renders `position-anchor` property correctly before anchor is decorated', async () => {\n const stylePropertyTreeElement = getTreeElement('position-anchor', '--anchor');\n\n stylePropertyTreeElement.updateTitle();\n\n assert.strictEqual(stylePropertyTreeElement.valueElement!.textContent, '--anchor');\n });\n\n it('renders `position-anchor` property correctly after anchor is decorated', async () => {\n const waitForDecorationPromise = expectCall(anchorDecoratedForTestStub);\n const stylePropertyTreeElement = getTreeElement('position-anchor', '--anchor');\n\n stylePropertyTreeElement.updateTitle();\n await waitForDecorationPromise;\n\n const anchorFunctionLinkSwatch =\n stylePropertyTreeElement.valueElement!.querySelector('devtools-anchor-function-link-swatch');\n assert.exists(anchorFunctionLinkSwatch);\n });\n });\n\n describe('LightDarkColorRenderer', () => {\n it('renders light-dark correctly', async () => {\n const colorSchemeSpy =\n sinon.spy(Elements.StylePropertyTreeElement.LightDarkColorRenderer.prototype, 'applyColorScheme');\n\n async function check(colorScheme: SDK.CSSModel.ColorScheme, lightText: string, darkText: string) {\n const variableName = (text: string) => text.substring('var('.length, text.length - 1);\n const lightDark = `light-dark(${lightText}, ${darkText})`;\n const stylePropertyTreeElement = getTreeElement('color', lightDark);\n stylePropertyTreeElement.setComputedStyles(new Map([['color-scheme', colorScheme]]));\n stylePropertyTreeElement.updateTitle();\n await Promise.all(colorSchemeSpy.returnValues);\n\n const swatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-swatch');\n assert.exists(swatch);\n assert.strictEqual(swatch?.textContent, lightDark);\n const activeColor = colorScheme === SDK.CSSModel.ColorScheme.LIGHT ? lightText : darkText;\n assert.strictEqual(\n swatch.getColor()?.getAuthoredText(), mockVariableMap[variableName(activeColor)] ?? activeColor);\n const [light, dark] = swatch.querySelectorAll('devtools-color-swatch');\n assert.exists(light);\n assert.exists(dark);\n const active = colorScheme === SDK.CSSModel.ColorScheme.LIGHT ? light : dark;\n const inactive = colorScheme === SDK.CSSModel.ColorScheme.LIGHT ? dark : light;\n assert.strictEqual(inactive.parentElement?.style.textDecoration, 'line-through');\n assert.strictEqual(active.parentElement?.style.textDecoration, '');\n }\n\n await check(SDK.CSSModel.ColorScheme.LIGHT, 'red', 'blue');\n await check(SDK.CSSModel.ColorScheme.DARK, 'red', 'blue');\n await check(SDK.CSSModel.ColorScheme.LIGHT, 'red', 'var(--blue)');\n await check(SDK.CSSModel.ColorScheme.DARK, 'red', 'var(--blue)');\n await check(SDK.CSSModel.ColorScheme.LIGHT, 'var(--blue)', 'red');\n await check(SDK.CSSModel.ColorScheme.DARK, 'var(--blue)', 'red');\n });\n\n it('renders light-dark correctly if the color scheme cannot be resolved', async () => {\n const lightDark = 'light-dark(red, blue)';\n const cssModel = sinon.createStubInstance(SDK.CSSModel.CSSModel);\n sinon.stub(stylesSidebarPane, 'cssModel').returns(cssModel);\n cssModel.colorScheme.resolves(undefined);\n const stylePropertyTreeElement = getTreeElement('color', lightDark);\n stylePropertyTreeElement.setComputedStyles(new Map([['color-scheme', 'light dark']]));\n const colorSchemeSpy =\n sinon.spy(Elements.StylePropertyTreeElement.LightDarkColorRenderer.prototype, 'applyColorScheme');\n stylePropertyTreeElement.updateTitle();\n await Promise.all(colorSchemeSpy.returnValues);\n\n const swatches = stylePropertyTreeElement.valueElement?.querySelectorAll('devtools-color-swatch');\n assert.exists(swatches);\n assert.lengthOf(swatches, 3);\n assert.isNull(swatches[0].getColor());\n assert.strictEqual(swatches[0].textContent, 'light-dark(red, blue)');\n assert.strictEqual(swatches[1].textContent, 'red');\n assert.strictEqual(swatches[2].textContent, 'blue');\n });\n\n it('renders light-dark without color-scheme correctly', async () => {\n const lightDark = 'light-dark(red, blue)';\n const stylePropertyTreeElement = getTreeElement('color', lightDark);\n // leave color-scheme unset\n const colorSchemeSpy =\n sinon.spy(Elements.StylePropertyTreeElement.LightDarkColorRenderer.prototype, 'applyColorScheme');\n stylePropertyTreeElement.updateTitle();\n await Promise.all(colorSchemeSpy.returnValues);\n\n const swatches = stylePropertyTreeElement.valueElement?.querySelectorAll('devtools-color-swatch');\n assert.exists(swatches);\n assert.lengthOf(swatches, 3);\n assert.strictEqual(swatches[0].getText(), 'red');\n assert.strictEqual(swatches[0].textContent, 'light-dark(red, blue)');\n assert.strictEqual(swatches[1].textContent, 'red');\n assert.strictEqual(swatches[2].textContent, 'blue');\n });\n\n it('renders light-dark with undefined vars correctly', async () => {\n const lightDark = 'light-dark(red, var(--undefined))';\n const stylePropertyTreeElement = getTreeElement('color', lightDark);\n stylePropertyTreeElement.setComputedStyles(new Map([['color-scheme', 'light dark']]));\n const colorSchemeSpy =\n sinon.spy(Elements.StylePropertyTreeElement.LightDarkColorRenderer.prototype, 'applyColorScheme');\n stylePropertyTreeElement.updateTitle();\n await Promise.all(colorSchemeSpy.returnValues);\n\n const swatches = stylePropertyTreeElement.valueElement?.querySelectorAll('devtools-color-swatch');\n assert.exists(swatches);\n assert.lengthOf(swatches, 1);\n assert.strictEqual(swatches[0].textContent, 'red');\n assert.strictEqual(swatches[0].parentElement?.style.textDecoration, '');\n });\n\n it('connects inner and outer swatches', async () => {\n const colorSchemeSpy =\n sinon.spy(Elements.StylePropertyTreeElement.LightDarkColorRenderer.prototype, 'applyColorScheme');\n for (const colorScheme of [SDK.CSSModel.ColorScheme.LIGHT, SDK.CSSModel.ColorScheme.DARK]) {\n const lightDark = 'light-dark(red, blue)';\n const stylePropertyTreeElement = getTreeElement('color', lightDark);\n stylePropertyTreeElement.setComputedStyles(new Map([['color-scheme', colorScheme]]));\n stylePropertyTreeElement.updateTitle();\n await Promise.all(colorSchemeSpy.returnValues);\n\n const outerSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-swatch');\n assert.exists(outerSwatch);\n const innerSwatches = outerSwatch.querySelectorAll('devtools-color-swatch');\n assert.lengthOf(innerSwatches, 2);\n const [lightSwatch, darkSwatch] = innerSwatches;\n const newLightColor = Common.Color.parse('white') as Common.Color.Color;\n const newDarkColor = Common.Color.parse('black') as Common.Color.Color;\n lightSwatch.setColor(newLightColor);\n darkSwatch.setColor(newDarkColor);\n\n if (colorScheme === SDK.CSSModel.ColorScheme.DARK) {\n assert.strictEqual(outerSwatch.getColor(), newDarkColor);\n } else {\n assert.strictEqual(outerSwatch.getColor(), newLightColor);\n }\n }\n });\n });\n\n describe('LinearGradientRenderer', () => {\n it('correctly connects to an angle match', () => {\n const stylePropertyTreeElement = getTreeElement('background', 'linear-gradient(45deg, red, var(--blue))');\n stylePropertyTreeElement.updateTitle();\n const swatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-css-angle');\n assert.exists(swatch);\n swatch.data = {\n angleText: swatch.textContent ?? '',\n containingPane: document.createElement('div'),\n };\n\n sinon.stub(swatch, 'dispatchEvent');\n swatch.popOver();\n const popover = swatch.shadowRoot?.querySelector('devtools-css-angle-editor');\n assert.exists(popover);\n const clock = popover.shadowRoot?.querySelector('.clock');\n assert.exists(clock);\n assert.strictEqual(clock.style.background, 'linear-gradient(45deg, red, blue)');\n });\n });\n\n describe('LengthRenderer', () => {\n it('renders the length too', () => {\n const stylePropertyTreeElement = getTreeElement('width', '100px');\n stylePropertyTreeElement.updateTitle();\n const swatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-css-length');\n assert.exists(swatch);\n });\n });\n\n describe('Autocompletion', function(this: Mocha.Suite) {\n let promptStub: sinon.SinonStub>;\n beforeEach(async () => {\n promptStub = sinon.stub(Elements.StylesSidebarPane.CSSPropertyPrompt.prototype, 'initialize').resolves([]);\n setMockConnectionResponseHandler('CSS.enable', () => ({}));\n\n const cssModel = new SDK.CSSModel.CSSModel(createTarget());\n await cssModel.resumeModel();\n const domModel = cssModel.domModel();\n const gridNode = new SDK.DOMModel.DOMNode(domModel);\n gridNode.id = 0 as Protocol.DOM.NodeId;\n const currentNode = new SDK.DOMModel.DOMNode(domModel);\n currentNode.id = 1 as Protocol.DOM.NodeId;\n currentNode.parentNode = gridNode;\n LegacyUI.Context.Context.instance().setFlavor(SDK.DOMModel.DOMNode, currentNode);\n });\n\n function suggestions() {\n assert.lengthOf(promptStub.args, 1);\n return promptStub.args[0][0].call(null, '', '');\n }\n\n function setParentComputedStyle(style: Record) {\n const computedStyle = Object.keys(style).map(name => ({name, value: style[name]}));\n setMockConnectionResponseHandler('CSS.getComputedStyleForNode', ({nodeId}) => {\n if (nodeId === 0) {\n return {computedStyle};\n }\n return {};\n });\n }\n\n it('includes grid row names', async () => {\n setParentComputedStyle({display: 'grid', 'grid-template-rows': '[row-name] 1fr [row-name-2]'});\n const stylePropertyTreeElement = getTreeElement('grid-row', 'somename');\n await stylePropertyTreeElement.onpopulate();\n stylePropertyTreeElement.updateTitle();\n stylePropertyTreeElement.startEditingValue();\n const autocompletions = await suggestions();\n assert.deepEqual(\n autocompletions.map(({text}) => text),\n ['row-name', 'row-name-2', 'auto', 'none', 'inherit', 'initial', 'revert', 'revert-layer', 'unset']);\n });\n\n it('includes grid column names', async () => {\n setParentComputedStyle({display: 'grid', 'grid-template-columns': '[col-name] 1fr [col-name-2]'});\n const stylePropertyTreeElement = getTreeElement('grid-column', 'somename');\n await stylePropertyTreeElement.onpopulate();\n stylePropertyTreeElement.updateTitle();\n stylePropertyTreeElement.startEditingValue();\n const autocompletions = await suggestions();\n assert.deepEqual(\n autocompletions.map(({text}) => text),\n ['col-name', 'col-name-2', 'auto', 'none', 'inherit', 'initial', 'revert', 'revert-layer', 'unset']);\n });\n\n it('includes grid area names', async () => {\n setParentComputedStyle({display: 'grid', 'grid-template-areas': '\"area-name-a area-name-b\" \"area-name-c .\"'});\n const stylePropertyTreeElement = getTreeElement('grid-area', 'somename');\n await stylePropertyTreeElement.onpopulate();\n stylePropertyTreeElement.updateTitle();\n stylePropertyTreeElement.startEditingValue();\n const autocompletions = await suggestions();\n assert.deepEqual(autocompletions.map(({text}) => text), [\n 'area-name-a',\n 'area-name-b',\n 'area-name-c',\n 'auto',\n 'none',\n 'inherit',\n 'initial',\n 'revert',\n 'revert-layer',\n 'unset',\n ]);\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"StylePropertyTreeElement.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/elements/StylePropertyTreeElement.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as Protocol from '../../generated/protocol.js';\nimport * as Bindings from '../../models/bindings/bindings.js';\nimport * as TextUtils from '../../models/text_utils/text_utils.js';\nimport * as Workspace from '../../models/workspace/workspace.js';\nimport {renderElementIntoDOM} from '../../testing/DOMHelpers.js';\nimport {createTarget} from '../../testing/EnvironmentHelpers.js';\nimport {expectCall} from '../../testing/ExpectStubCall.js';\nimport {describeWithMockConnection, setMockConnectionResponseHandler} from '../../testing/MockConnection.js';\nimport * as CodeMirror from '../../third_party/codemirror.next/codemirror.next.js';\nimport * as InlineEditor from '../../ui/legacy/components/inline_editor/inline_editor.js';\nimport * as LegacyUI from '../../ui/legacy/legacy.js';\n\nimport * as ElementsComponents from './components/components.js';\nimport * as Elements from './elements.js';\n\ndescribeWithMockConnection('StylePropertyTreeElement', () => {\n let stylesSidebarPane: Elements.StylesSidebarPane.StylesSidebarPane;\n let mockStylePropertiesSection: sinon.SinonStubbedInstance;\n let mockCssStyleDeclaration: sinon.SinonStubbedInstance;\n let mockMatchedStyles: sinon.SinonStubbedInstance;\n let mockVariableMap: Record;\n\n beforeEach(async () => {\n stylesSidebarPane = Elements.StylesSidebarPane.StylesSidebarPane.instance({forceNew: true});\n mockVariableMap = {\n '--a': 'red',\n '--b': 'blue',\n '--blue': 'blue',\n '--space': 'shorter hue',\n '--garbage-space': 'this-is-garbage-text',\n '--prop': 'customproperty',\n '--zero': '0',\n };\n\n mockStylePropertiesSection = sinon.createStubInstance(Elements.StylePropertiesSection.StylePropertiesSection);\n mockCssStyleDeclaration = sinon.createStubInstance(SDK.CSSStyleDeclaration.CSSStyleDeclaration);\n mockMatchedStyles = sinon.createStubInstance(SDK.CSSMatchedStyles.CSSMatchedStyles);\n mockMatchedStyles.keyframes.returns([]);\n mockMatchedStyles.availableCSSVariables.returns(Object.keys(mockVariableMap));\n mockMatchedStyles.computeCSSVariable.callsFake((style, name) => {\n return {\n value: mockVariableMap[name],\n declaration: sinon.createStubInstance(SDK.CSSProperty.CSSProperty),\n };\n });\n mockCssStyleDeclaration.leadingProperties.returns([]);\n mockCssStyleDeclaration.styleSheetId = 'stylesheet-id' as Protocol.CSS.StyleSheetId;\n mockCssStyleDeclaration.range = new TextUtils.TextRange.TextRange(0, 0, 10, 10);\n\n const workspace = Workspace.Workspace.WorkspaceImpl.instance({forceNew: true});\n const resourceMapping =\n new Bindings.ResourceMapping.ResourceMapping(SDK.TargetManager.TargetManager.instance(), workspace);\n Bindings.CSSWorkspaceBinding.CSSWorkspaceBinding.instance(\n {forceNew: true, resourceMapping, targetManager: SDK.TargetManager.TargetManager.instance()});\n });\n\n function getTreeElement(name: string, value: string, longhandProperties: Protocol.CSS.CSSProperty[] = []) {\n const property = new SDK.CSSProperty.CSSProperty(\n mockCssStyleDeclaration, 0, name, value, true, false, true, false, '', undefined, longhandProperties);\n return new Elements.StylePropertyTreeElement.StylePropertyTreeElement({\n stylesPane: stylesSidebarPane,\n section: mockStylePropertiesSection,\n matchedStyles: mockMatchedStyles,\n property,\n isShorthand: longhandProperties.length > 0,\n inherited: false,\n overloaded: false,\n newProperty: true,\n });\n }\n\n describe('updateTitle', () => {\n it('timing swatch, shadow swatch and length swatch are not shown for longhands expanded inside shorthands',\n async () => {\n const stylePropertyTreeElement = getTreeElement('', '', [\n {name: 'animation-timing-function', value: 'linear'},\n {name: 'text-shadow', value: '2px 2px #ff0000'},\n {name: 'box-shadow', value: '2px 2px #ff0000'},\n {name: 'margin-top', value: '10px'},\n ]);\n await stylePropertyTreeElement.onpopulate();\n\n stylePropertyTreeElement.updateTitle();\n stylePropertyTreeElement.expand();\n\n const assertNullSwatchOnChildAt = (n: number, swatchSelector: string) => {\n const childValueElement =\n (stylePropertyTreeElement.childAt(n) as Elements.StylePropertyTreeElement.StylePropertyTreeElement)\n .valueElement;\n assert.exists(childValueElement);\n assert.notExists(childValueElement.querySelector(swatchSelector));\n };\n assertNullSwatchOnChildAt(0, '[is=\"bezier-swatch\"]');\n assertNullSwatchOnChildAt(1, '[is=\"css-shadow-swatch\"]');\n assertNullSwatchOnChildAt(2, '[is=\"css-shadow-swatch\"]');\n assertNullSwatchOnChildAt(3, 'devtools-css-length');\n });\n\n describe('color-mix swatch', () => {\n it('should show color mix swatch when color-mix is used with a color', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'color-mix(in srgb, red, blue)');\n stylePropertyTreeElement.updateTitle();\n\n const colorMixSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-mix-swatch');\n const colorSwatches =\n Array.from(stylePropertyTreeElement.valueElement?.querySelectorAll('devtools-color-swatch') || []);\n assert.exists(colorMixSwatch);\n assert.exists(colorSwatches.find(colorSwatch => colorSwatch.textContent === 'red'));\n assert.exists(colorSwatches.find(colorSwatch => colorSwatch.textContent === 'blue'));\n });\n\n it('should show color mix swatch when color-mix is used with a known variable as color', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'color-mix(in srgb, var(--a), var(--b))');\n stylePropertyTreeElement.updateTitle();\n\n const colorMixSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-mix-swatch');\n const cssVarSwatches =\n Array.from(stylePropertyTreeElement.valueElement?.querySelectorAll('devtools-css-var-swatch') || []);\n assert.exists(colorMixSwatch);\n assert.exists(cssVarSwatches.find(cssVarSwatch => cssVarSwatch.textContent === 'var(--a)'));\n assert.exists(cssVarSwatches.find(cssVarSwatch => cssVarSwatch.textContent === 'var(--b)'));\n });\n\n it('should not show color mix swatch when color-mix is used with an unknown variable as color', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'color-mix(in srgb, var(--unknown-a), var(--b))');\n stylePropertyTreeElement.updateTitle();\n\n const colorMixSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-mix-swatch');\n assert.isNull(colorMixSwatch);\n });\n\n it('should show color mix swatch when color-mix is used with a known variable in interpolation method', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'color-mix(in lch var(--space), var(--a), var(--b))');\n stylePropertyTreeElement.updateTitle();\n\n const colorMixSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-mix-swatch');\n assert.exists(colorMixSwatch);\n assert.isTrue(colorMixSwatch.textContent?.includes('var(--space)'));\n });\n\n it('should show color mix swatch when color-mix is used with an known variable in interpolation method even if it is not a valid method',\n () => {\n const stylePropertyTreeElement =\n getTreeElement('color', 'color-mix(in lch var(--garbage-space), var(--a), var(--b))');\n stylePropertyTreeElement.updateTitle();\n\n const colorMixSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-mix-swatch');\n assert.exists(colorMixSwatch);\n assert.isTrue(colorMixSwatch.textContent?.includes('var(--garbage-space)'));\n });\n\n it('should not show color mix swatch when color-mix is used with an unknown variable in interpolation method',\n () => {\n const stylePropertyTreeElement =\n getTreeElement('color', 'color-mix(in lch var(--not-existing-space), var(--a), var(--b))');\n\n stylePropertyTreeElement.updateTitle();\n\n const colorMixSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-mix-swatch');\n assert.isNull(colorMixSwatch);\n });\n\n it('shows a popover with it\\'s computed color as RGB if possible', () => {\n const cssPropertyWithColorMix = new SDK.CSSProperty.CSSProperty(\n mockCssStyleDeclaration, 0, 'color', 'color-mix(in srgb, red 50%, yellow)', true, false, true, false, '',\n undefined);\n const stylePropertyTreeElement = new Elements.StylePropertyTreeElement.StylePropertyTreeElement({\n stylesPane: stylesSidebarPane,\n section: mockStylePropertiesSection,\n matchedStyles: mockMatchedStyles,\n property: cssPropertyWithColorMix,\n isShorthand: false,\n inherited: false,\n overloaded: false,\n newProperty: true,\n });\n\n const addPopoverSpy = sinon.spy(stylesSidebarPane, 'addPopover');\n stylePropertyTreeElement.updateTitle();\n const colorMixSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-mix-swatch');\n assert.exists(colorMixSwatch);\n renderElementIntoDOM(colorMixSwatch);\n\n assert.isTrue(addPopoverSpy.calledOnce);\n assert.strictEqual(addPopoverSpy.args[0][0], colorMixSwatch.icon);\n assert.strictEqual(addPopoverSpy.args[0][1].contents()?.textContent, '#ff8000');\n });\n\n it('shows a popover with it\\'s computed color as wide gamut if necessary', () => {\n const cssPropertyWithColorMix = new SDK.CSSProperty.CSSProperty(\n mockCssStyleDeclaration, 0, 'color', 'color-mix(in srgb, oklch(.5 .5 .5) 50%, yellow)', true, false, true,\n false, '', undefined);\n const stylePropertyTreeElement = new Elements.StylePropertyTreeElement.StylePropertyTreeElement({\n stylesPane: stylesSidebarPane,\n section: mockStylePropertiesSection,\n matchedStyles: mockMatchedStyles,\n property: cssPropertyWithColorMix,\n isShorthand: false,\n inherited: false,\n overloaded: false,\n newProperty: true,\n });\n\n const addPopoverSpy = sinon.spy(stylesSidebarPane, 'addPopover');\n stylePropertyTreeElement.updateTitle();\n const colorMixSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-mix-swatch');\n assert.exists(colorMixSwatch);\n renderElementIntoDOM(colorMixSwatch);\n\n assert.isTrue(addPopoverSpy.calledOnce);\n assert.strictEqual(addPopoverSpy.args[0][0], colorMixSwatch.icon);\n assert.strictEqual(addPopoverSpy.args[0][1].contents()?.textContent, 'color(srgb 1 0.24 0.17)');\n });\n\n it('propagates updates to outer color-mixes', () => {\n const cssPropertyWithColorMix = new SDK.CSSProperty.CSSProperty(\n mockCssStyleDeclaration, 0, 'color', 'color-mix(in srgb, color-mix(in oklch, red, green), blue)', true,\n false, true, false, '', undefined);\n const stylePropertyTreeElement = new Elements.StylePropertyTreeElement.StylePropertyTreeElement({\n stylesPane: stylesSidebarPane,\n section: mockStylePropertiesSection,\n matchedStyles: mockMatchedStyles,\n property: cssPropertyWithColorMix,\n isShorthand: false,\n inherited: false,\n overloaded: false,\n newProperty: true,\n });\n\n stylePropertyTreeElement.updateTitle();\n\n const outerColorMix = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-mix-swatch');\n assert.exists(outerColorMix);\n const handler = sinon.fake();\n outerColorMix.addEventListener(InlineEditor.ColorMixSwatch.Events.COLOR_CHANGED, handler);\n const innerColorMix = outerColorMix.querySelector('devtools-color-mix-swatch');\n assert.exists(innerColorMix);\n assert.strictEqual(outerColorMix.getText(), 'color-mix(in srgb, color-mix(in oklch, red, green), blue)');\n assert.strictEqual(innerColorMix.getText(), 'color-mix(in oklch, red, green)');\n innerColorMix.setFirstColor('blue');\n assert.deepStrictEqual(\n handler.args[0][0].data, {text: 'color-mix(in srgb, color-mix(in oklch, blue, green), blue)'});\n assert.strictEqual(outerColorMix.getText(), 'color-mix(in srgb, color-mix(in oklch, blue, green), blue)');\n\n // setFirstColor does not actually update the rendered color swatches or the textContent, which is why the first\n // color is still red here.\n const colorSwatch = innerColorMix.querySelector('devtools-color-swatch');\n assert.isOk(colorSwatch);\n const newColor = colorSwatch.getColor()?.as(Common.Color.Format.HEX);\n assert.isOk(newColor);\n colorSwatch.setColor(newColor);\n assert.strictEqual(outerColorMix.getText(), 'color-mix(in srgb, color-mix(in oklch, #ff0000, green), blue)');\n assert.deepStrictEqual(\n handler.args[1][0].data, {text: 'color-mix(in srgb, color-mix(in oklch, #ff0000, green), blue)'});\n });\n });\n\n describe('animation-name', () => {\n it('should link-swatch be rendered for animation-name declaration', () => {\n const stylePropertyTreeElement = getTreeElement('animation-name', 'first-keyframe');\n stylePropertyTreeElement.updateTitle();\n\n const animationNameSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-link-swatch');\n assert.isNotNull(animationNameSwatch);\n });\n\n it('should two link-swatches be rendered for animation-name declaration that contains two keyframe references',\n () => {\n const stylePropertyTreeElement = getTreeElement('animation-name', 'first-keyframe, second-keyframe');\n stylePropertyTreeElement.updateTitle();\n\n const animationNameSwatches =\n stylePropertyTreeElement.valueElement?.querySelectorAll('devtools-link-swatch');\n assert.strictEqual(animationNameSwatches?.length, 2);\n });\n });\n });\n\n it('applies the new style when the color format is changed', async () => {\n const stylePropertyTreeElement = getTreeElement('color', 'color(srgb .5 .5 1)');\n const applyStyleTextStub = sinon.stub(stylePropertyTreeElement, 'applyStyleText');\n // Make sure we don't leave a dangling promise behind:\n const returnValue = (async () => {})();\n await returnValue;\n applyStyleTextStub.returns(returnValue);\n\n stylePropertyTreeElement.updateTitle();\n\n const {valueElement} = stylePropertyTreeElement;\n assert.exists(valueElement);\n\n const swatch = valueElement.querySelector(\n `${InlineEditor.ColorSwatch.ColorSwatch.litTagName.value}`);\n\n assert.exists(swatch);\n\n const expectedColorString = swatch.getColor()?.asString(Common.Color.Format.LAB);\n assert.exists(expectedColorString);\n assert.match(expectedColorString, /lab\\([-.0-9]* [-.0-9]* [-.0-9]*\\)/);\n\n const newColor = swatch.getColor()?.as(Common.Color.Format.LAB);\n assert.isOk(newColor);\n swatch.setColorText(newColor);\n assert.deepEqual(stylePropertyTreeElement.renderedPropertyText(), `color: ${expectedColorString}`);\n\n assert.isTrue(applyStyleTextStub.alwaysCalledWith(`color: ${expectedColorString}`, false));\n });\n\n describe('Context menu', () => {\n const expectedHeaderSectionItemsLabels =\n ['Copy declaration', 'Copy property', 'Copy value', 'Copy rule', 'Copy declaration as JS'];\n const expectedClipboardSectionItemsLabels = ['Copy all declarations', 'Copy all declarations as JS'];\n const expectedDefaultSectionItemsLabels = ['Copy all CSS changes'];\n const expectedFooterSectionItemsLabels = ['View computed value'];\n\n it('should create a context menu', () => {\n const verifySection = (expectedSectionItemLabels: string[], sectionItems: LegacyUI.ContextMenu.Item[]) => {\n const sectionItemLabels = sectionItems.map(item => item.buildDescriptor().label);\n assert.deepEqual(sectionItemLabels, expectedSectionItemLabels);\n };\n const stylePropertyTreeElement = getTreeElement('', '');\n const event = new CustomEvent('contextmenu');\n const contextMenu = stylePropertyTreeElement.createCopyContextMenu(event);\n\n const headerSection = contextMenu.headerSection();\n const clipboardSection = contextMenu.clipboardSection();\n const defaultSection = contextMenu.defaultSection();\n const footerSection = contextMenu.footerSection();\n verifySection(expectedHeaderSectionItemsLabels, headerSection.items);\n verifySection(expectedClipboardSectionItemsLabels, clipboardSection.items);\n verifySection(expectedDefaultSectionItemsLabels, defaultSection.items);\n verifySection(expectedFooterSectionItemsLabels, footerSection.items);\n });\n });\n\n describe('CSS hints', () => {\n it('should create a hint for inline elements', () => {\n sinon.stub(stylesSidebarPane, 'node').returns({\n localName() {\n return 'span';\n },\n isSVGNode() {\n return false;\n },\n } as SDK.DOMModel.DOMNode);\n const stylePropertyTreeElement = getTreeElement('width', '100px');\n stylePropertyTreeElement.setComputedStyles(new Map([\n ['width', '100px'],\n ['display', 'inline'],\n ]));\n stylePropertyTreeElement.updateAuthoringHint();\n assert(\n stylePropertyTreeElement.listItemElement.classList.contains('inactive-property'),\n 'CSS hint was not rendered.');\n });\n\n it('should not create a hint for SVG elements', () => {\n sinon.stub(stylesSidebarPane, 'node').returns({\n localName() {\n return 'rect';\n },\n isSVGNode() {\n return true;\n },\n } as SDK.DOMModel.DOMNode);\n const stylePropertyTreeElement = getTreeElement('width', '100px');\n stylePropertyTreeElement.setComputedStyles(new Map([\n ['width', '100px'],\n ['display', 'inline'],\n ]));\n stylePropertyTreeElement.updateAuthoringHint();\n assert(\n !stylePropertyTreeElement.listItemElement.classList.contains('inactive-property'),\n 'CSS hint was rendered unexpectedly.');\n });\n });\n\n describe('custom-properties', () => {\n it('linkifies var functions to declarations', async () => {\n const cssCustomPropertyDef = new SDK.CSSProperty.CSSProperty(\n mockCssStyleDeclaration, 0, '--prop', 'value', true, false, true, false, '', undefined);\n mockMatchedStyles.computeCSSVariable.callsFake(\n (_, name) => name === '--prop' ?\n {value: 'computedvalue', declaration: cssCustomPropertyDef, fromFallback: false} :\n null);\n const renderValueSpy = sinon.spy(Elements.PropertyRenderer.Renderer, 'renderValueElement');\n\n const stylePropertyTreeElement = getTreeElement('prop', 'var(--prop)');\n stylePropertyTreeElement.updateTitle();\n\n const varSwatch =\n renderValueSpy.returnValues.find(value => value.firstChild instanceof InlineEditor.LinkSwatch.CSSVarSwatch)\n ?.firstChild as InlineEditor.LinkSwatch.CSSVarSwatch |\n undefined;\n assert.exists(varSwatch);\n const revealPropertySpy = sinon.spy(stylesSidebarPane, 'revealProperty');\n varSwatch.link?.linkElement?.click();\n assert.isTrue(revealPropertySpy.calledWith(cssCustomPropertyDef));\n });\n\n it('linkifies property definition to registrations', async () => {\n const addElementPopoverHook = sinon.stub(stylesSidebarPane, 'addPopover');\n const stylePropertyTreeElement = getTreeElement('--prop', 'value');\n stylePropertyTreeElement.updateTitle();\n\n assert.isTrue(addElementPopoverHook.calledOnce);\n\n const registration = sinon.createStubInstance(SDK.CSSMatchedStyles.CSSRegisteredProperty);\n mockMatchedStyles.getRegisteredProperty.callsFake(name => name === '--prop' ? registration : undefined);\n mockMatchedStyles.computeCSSVariable.returns(\n {value: 'computedvalue', declaration: sinon.createStubInstance(SDK.CSSProperty.CSSProperty)});\n const popoverContents = addElementPopoverHook.args[0][1].contents();\n assert.isTrue(popoverContents instanceof ElementsComponents.CSSVariableValueView.CSSVariableValueView);\n const {details} = popoverContents as ElementsComponents.CSSVariableValueView.CSSVariableValueView;\n assert.exists(details);\n\n const jumpToSectionSpy = sinon.spy(stylesSidebarPane, 'jumpToSection');\n details.goToDefinition();\n assert.isTrue(jumpToSectionSpy.calledOnceWithExactly(\n '--prop', Elements.StylesSidebarPane.REGISTERED_PROPERTY_SECTION_NAME));\n });\n\n it('linkifies var functions to initial-value registrations', async () => {\n mockMatchedStyles.computeCSSVariable.returns({\n value: 'computedvalue',\n declaration: sinon.createStubInstance(SDK.CSSMatchedStyles.CSSRegisteredProperty, {propertyName: '--prop'}),\n });\n const renderValueSpy = sinon.spy(Elements.PropertyRenderer.Renderer, 'renderValueElement');\n\n const stylePropertyTreeElement = getTreeElement('prop', 'var(--prop)');\n stylePropertyTreeElement.updateTitle();\n\n const varSwatch =\n renderValueSpy.returnValues.find(value => value.firstChild instanceof InlineEditor.LinkSwatch.CSSVarSwatch)\n ?.firstChild as InlineEditor.LinkSwatch.CSSVarSwatch |\n undefined;\n assert.exists(varSwatch);\n const jumpToPropertySpy = sinon.spy(stylesSidebarPane, 'jumpToProperty');\n varSwatch.link?.linkElement?.click();\n assert.isTrue(jumpToPropertySpy.calledWith(\n 'initial-value', '--prop', Elements.StylesSidebarPane.REGISTERED_PROPERTY_SECTION_NAME));\n });\n });\n\n describe('CSSVarSwatch', () => {\n it('should render a CSSVarSwatch for variable usage without fallback', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'var(--a)');\n stylePropertyTreeElement.updateTitle();\n assert.exists(stylePropertyTreeElement.valueElement);\n\n const cssVarSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-css-var-swatch');\n assert.exists(cssVarSwatch);\n\n const linkSwatch = cssVarSwatch.shadowRoot?.querySelector('devtools-base-link-swatch');\n assert.exists(linkSwatch);\n\n assert.strictEqual(cssVarSwatch.textContent, 'var(--a)');\n assert.strictEqual(linkSwatch.shadowRoot?.textContent, '--a');\n assert.strictEqual(stylePropertyTreeElement.valueElement.textContent, 'var(--a)');\n });\n\n it('should render a CSSVarSwatch for variable usage with fallback', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'var(--not-existing, red)');\n stylePropertyTreeElement.updateTitle();\n assert.exists(stylePropertyTreeElement.valueElement);\n\n const cssVarSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-css-var-swatch');\n assert.exists(cssVarSwatch);\n\n const linkSwatch = cssVarSwatch.shadowRoot?.querySelector('devtools-base-link-swatch');\n assert.exists(linkSwatch);\n\n assert.strictEqual(linkSwatch.shadowRoot?.textContent, '--not-existing');\n assert.strictEqual(cssVarSwatch.deepTextContent(), 'var(--not-existing, red)');\n assert.strictEqual(stylePropertyTreeElement.valueElement.textContent, 'var(--not-existing, red)');\n });\n\n it('should render a CSSVarSwatch inside CSSVarSwatch for variable usage with another variable fallback', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'var(--not-existing, var(--a))');\n stylePropertyTreeElement.updateTitle();\n assert.exists(stylePropertyTreeElement.valueElement);\n\n const cssVarSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-css-var-swatch');\n assert.exists(cssVarSwatch);\n\n const firstLinkSwatch = cssVarSwatch.shadowRoot?.querySelector('devtools-base-link-swatch');\n const insideCssVarSwatch = cssVarSwatch.querySelector('devtools-css-var-swatch');\n const secondLinkSwatch = insideCssVarSwatch?.shadowRoot?.querySelector('devtools-base-link-swatch');\n assert.strictEqual(stylePropertyTreeElement.valueElement.textContent, 'var(--not-existing, var(--a))');\n assert.strictEqual(firstLinkSwatch?.shadowRoot?.textContent, '--not-existing');\n assert.strictEqual(cssVarSwatch.textContent, 'var(--not-existing, var(--a))');\n assert.strictEqual(secondLinkSwatch?.shadowRoot?.textContent, '--a');\n assert.strictEqual(insideCssVarSwatch?.textContent, 'var(--a)');\n });\n\n it('should render a CSSVarSwatch inside CSSVarSwatch for variable usage with calc expression as fallback', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'var(--not-existing, calc(15px + 20px))');\n stylePropertyTreeElement.updateTitle();\n assert.exists(stylePropertyTreeElement.valueElement);\n\n const cssVarSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-css-var-swatch');\n assert.exists(cssVarSwatch);\n\n const firstLinkSwatch = cssVarSwatch.shadowRoot?.querySelector('devtools-base-link-swatch');\n\n assert.strictEqual(stylePropertyTreeElement.valueElement.textContent, 'var(--not-existing, calc(15px + 20px))');\n assert.strictEqual(firstLinkSwatch?.shadowRoot?.textContent, '--not-existing');\n assert.strictEqual(cssVarSwatch.textContent, 'var(--not-existing, calc(15px + 20px))');\n });\n\n it('should render a CSSVarSwatch inside CSSVarSwatch for variable usage with color and also a color swatch', () => {\n for (const varName of ['--a', '--not-existing']) {\n const stylePropertyTreeElement = getTreeElement('color', `var(${varName}, var(--blue))`);\n stylePropertyTreeElement.updateTitle();\n assert.exists(stylePropertyTreeElement.valueElement);\n\n const cssVarSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-css-var-swatch');\n assert.exists(cssVarSwatch);\n\n const colorSwatch = cssVarSwatch.querySelector('devtools-color-swatch');\n assert.exists(colorSwatch);\n assert.isTrue(InlineEditor.ColorSwatch.ColorSwatch.isColorSwatch(colorSwatch));\n\n const firstLinkSwatch = cssVarSwatch.shadowRoot?.querySelector('devtools-base-link-swatch');\n\n assert.strictEqual(stylePropertyTreeElement.valueElement.textContent, `var(${varName}, var(--blue))`);\n assert.strictEqual(firstLinkSwatch?.shadowRoot?.textContent, varName);\n assert.strictEqual(cssVarSwatch.textContent, `var(${varName}, var(--blue))`);\n }\n });\n\n it('should render CSSVarSwatches for multiple var() usages in the same property declaration', () => {\n const stylePropertyTreeElement = getTreeElement('--shadow', 'var(--a) var(--b)');\n stylePropertyTreeElement.updateTitle();\n\n const cssVarSwatches = stylePropertyTreeElement.valueElement?.querySelectorAll('devtools-css-var-swatch');\n assert.strictEqual(cssVarSwatches?.length, 2);\n });\n\n it('should render a CSSVarSwatch for var() with spaces', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'var( --test )');\n stylePropertyTreeElement.updateTitle();\n assert.exists(stylePropertyTreeElement.valueElement);\n\n const cssVarSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-css-var-swatch');\n assert.exists(cssVarSwatch);\n\n const linkSwatch = cssVarSwatch.shadowRoot?.querySelector('devtools-base-link-swatch');\n assert.strictEqual(linkSwatch?.shadowRoot?.textContent, '--test');\n assert.strictEqual(cssVarSwatch.textContent, 'var( --test )');\n assert.strictEqual(stylePropertyTreeElement.valueElement.textContent, 'var( --test )');\n });\n\n it('connects nested color swatches', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'var(--void, red)');\n stylePropertyTreeElement.updateTitle();\n assert.exists(stylePropertyTreeElement.valueElement);\n\n const cssVarSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-css-var-swatch');\n assert.exists(cssVarSwatch);\n const outerColorSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-swatch');\n assert.exists(outerColorSwatch);\n const innerColorSwatch = cssVarSwatch.querySelector('devtools-color-swatch');\n assert.exists(innerColorSwatch);\n assert.notStrictEqual(outerColorSwatch, innerColorSwatch);\n const color = new Common.Color.Lab(1, 0, 0, null, undefined);\n innerColorSwatch.setColor(color);\n assert.strictEqual(outerColorSwatch.getColor(), color);\n });\n\n it('only connects nested color swatches if the fallback is actually taken', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'var(--blue, red)');\n stylePropertyTreeElement.updateTitle();\n assert.exists(stylePropertyTreeElement.valueElement);\n\n const cssVarSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-css-var-swatch');\n assert.exists(cssVarSwatch);\n const outerColorSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-swatch');\n assert.exists(outerColorSwatch);\n const innerColorSwatch = cssVarSwatch.querySelector('devtools-color-swatch');\n assert.exists(innerColorSwatch);\n assert.notStrictEqual(outerColorSwatch, innerColorSwatch);\n const color = new Common.Color.Lab(1, 0, 0, null, undefined);\n innerColorSwatch.setColor(color);\n assert.strictEqual(outerColorSwatch.getColor()?.asString(), 'blue');\n });\n });\n\n function setUpStyles(\n cssModel: SDK.CSSModel.CSSModel,\n cssProperties: {name: string, value: string}[],\n styleSheetId = '0' as Protocol.CSS.StyleSheetId,\n origin = Protocol.CSS.StyleSheetOrigin.Regular,\n selector = 'div',\n ): Promise {\n const matchedPayload: Protocol.CSS.RuleMatch[] = [{\n rule: {\n selectorList: {selectors: [{text: selector}], text: selector},\n origin,\n style: {cssProperties, shorthandEntries: []},\n },\n matchingSelectors: [0],\n }];\n if (cssModel.styleSheetHeaderForId(styleSheetId)) {\n cssModel.styleSheetRemoved(styleSheetId);\n }\n cssModel.styleSheetAdded({\n styleSheetId,\n frameId: '' as Protocol.Page.FrameId,\n sourceURL: '',\n origin,\n title: '',\n disabled: false,\n isInline: false,\n isMutable: false,\n isConstructed: false,\n startLine: 0,\n startColumn: 0,\n length: 0,\n endLine: 0,\n endColumn: 0,\n });\n const node = sinon.createStubInstance(SDK.DOMModel.DOMNode);\n node.id = 0 as Protocol.DOM.NodeId;\n return SDK.CSSMatchedStyles.CSSMatchedStyles.create({\n cssModel,\n node,\n inlinePayload: null,\n attributesPayload: null,\n matchedPayload,\n pseudoPayload: [],\n inheritedPayload: [],\n inheritedPseudoPayload: [],\n animationsPayload: [],\n parentLayoutNodeId: undefined,\n positionTryRules: [],\n propertyRules: [],\n cssPropertyRegistrations: [],\n fontPaletteValuesRule: undefined,\n });\n }\n\n describe('VariableRenderer', () => {\n it('computes the text for var()s correctly', async () => {\n const cssModel = new SDK.CSSModel.CSSModel(createTarget());\n\n async function matchProperty(value: string, name = 'color') {\n const matchedStyles = await setUpStyles(cssModel, [\n {name: '--blue', value: 'blue'},\n {name, value},\n ]);\n const property = matchedStyles.nodeStyles()[0].leadingProperties()[1];\n const stylePropertyTreeElement = new Elements.StylePropertyTreeElement.StylePropertyTreeElement({\n stylesPane: stylesSidebarPane,\n section: mockStylePropertiesSection,\n matchedStyles,\n property,\n isShorthand: false,\n inherited: false,\n overloaded: false,\n newProperty: true,\n });\n\n const ast =\n SDK.CSSPropertyParser.tokenizeDeclaration(stylePropertyTreeElement.name, stylePropertyTreeElement.value);\n assert.exists(ast);\n const matching = SDK.CSSPropertyParser.BottomUpTreeMatching.walk(\n ast, [new Elements.StylePropertyTreeElement\n .VariableRenderer(stylePropertyTreeElement, stylePropertyTreeElement.property.ownerStyle)\n .matcher()]);\n\n const res = {\n hasUnresolvedVars: matching.hasUnresolvedVars(ast.tree),\n computedText: matching.getComputedText(ast.tree),\n };\n return res;\n }\n\n assert.deepStrictEqual(\n await matchProperty('var( --blue )'), {hasUnresolvedVars: false, computedText: 'color: blue'});\n assert.deepStrictEqual(\n await matchProperty('var(--no, var(--blue))'), {hasUnresolvedVars: false, computedText: 'color: blue'});\n assert.deepStrictEqual(\n await matchProperty('pre var(--no) post'),\n {hasUnresolvedVars: true, computedText: 'color: pre var(--no) post'});\n assert.deepStrictEqual(\n await matchProperty('var(--no, var(--no2))'),\n {hasUnresolvedVars: true, computedText: 'color: var(--no, var(--no2))'});\n });\n\n it('layers correctly with the font renderer', () => {\n const stylePropertyTreeElement = getTreeElement('font-size', 'calc(1 + var(--no))');\n stylePropertyTreeElement.updateTitle();\n assert.exists(stylePropertyTreeElement.valueElement?.querySelector('devtools-css-var-swatch'));\n });\n });\n\n describe('ColorRenderer', () => {\n it('correctly renders children of the color swatch', () => {\n const value = 'rgb(255, var(--zero), var(--zero))';\n const stylePropertyTreeElement = getTreeElement('color', value);\n stylePropertyTreeElement.updateTitle();\n\n assert.strictEqual(stylePropertyTreeElement.valueElement?.textContent, value);\n const colorSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-swatch');\n assert.exists(colorSwatch);\n assert.strictEqual(colorSwatch.getColor()?.asString(Common.Color.Format.HEX), '#ff0000');\n\n const varSwatches = stylePropertyTreeElement.valueElement?.querySelectorAll('devtools-css-var-swatch');\n assert.exists(varSwatches);\n assert.lengthOf(varSwatches, 2);\n });\n\n it('connects correctly with an inner angle swatch', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'hsl(120deg, 50%, 25%)');\n stylePropertyTreeElement.updateTitle();\n const colorSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-swatch');\n\n assert.exists(colorSwatch);\n assert.strictEqual(colorSwatch.getColor()?.asString(Common.Color.Format.HSL), 'hsl(120deg 50% 25%)');\n const eventHandler = sinon.stub<[InlineEditor.ColorSwatch.ColorChangedEvent]>();\n colorSwatch.addEventListener(InlineEditor.ColorSwatch.ColorChangedEvent.eventName, eventHandler);\n\n const angleSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-css-angle');\n assert.exists(angleSwatch);\n angleSwatch.updateAngle({value: 130, unit: InlineEditor.CSSAngleUtils.AngleUnit.DEG});\n assert.strictEqual(colorSwatch.getColor()?.asString(Common.Color.Format.HSL), 'hsl(130deg 50% 25%)');\n assert.isTrue(eventHandler.calledOnce);\n assert.strictEqual(eventHandler.args[0][0].data.color, colorSwatch.getColor());\n });\n\n it('renders relative colors', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'hsl( from var(--blue) h calc(s/2) l / alpha)');\n stylePropertyTreeElement.updateTitle();\n const colorSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-swatch');\n assert.isOk(colorSwatch);\n assert.isOk(colorSwatch.getColor());\n assert.strictEqual(colorSwatch?.getColor()?.asString(Common.Color.Format.HSL), 'hsl(240deg 50% 50%)');\n });\n\n it('does not render relative colors if property text is invalid', () => {\n const invalidColor = 'hsl( from var(--zero) h calc(s/2) l / alpha)';\n const stylePropertyTreeElement = getTreeElement('color', invalidColor);\n stylePropertyTreeElement.updateTitle();\n const colorSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-swatch');\n assert.isNull(colorSwatch);\n });\n\n it('correctly renders currentcolor', () => {\n const stylePropertyTreeElement = getTreeElement('background-color', 'currentcolor');\n stylePropertyTreeElement.setComputedStyles(new Map([['color', 'red']]));\n stylePropertyTreeElement.updateTitle();\n const colorSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-swatch');\n assert.isOk(colorSwatch);\n assert.isOk(colorSwatch.getColor());\n assert.strictEqual(colorSwatch?.getColor()?.asString(), 'red');\n });\n\n it('renders relative colors using currentcolor', () => {\n const stylePropertyTreeElement = getTreeElement('color', 'hsl(from currentcolor h calc(s/2) l / alpha)');\n stylePropertyTreeElement.setComputedStyles(new Map([['color', 'blue']]));\n stylePropertyTreeElement.updateTitle();\n const colorSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-swatch');\n assert.isOk(colorSwatch);\n assert.isOk(colorSwatch.getColor());\n assert.strictEqual(colorSwatch?.getColor()?.asString(Common.Color.Format.HSL), 'hsl(240deg 50% 50%)');\n });\n });\n\n describe('BezierRenderer', () => {\n it('renders the easing function swatch', () => {\n const stylePropertyTreeElement = getTreeElement('animation-timing-function', 'ease-out');\n stylePropertyTreeElement.updateTitle();\n assert.instanceOf(stylePropertyTreeElement.valueElement?.firstChild, InlineEditor.Swatches.BezierSwatch);\n });\n });\n\n describe('UrlRenderer', () => {\n it('linkifies and unescapes urls', () => {\n const stylePropertyTreeElement = getTreeElement('--url', 'url(devtools:\\\\/\\\\/abc)');\n stylePropertyTreeElement.updateTitle();\n\n assert.strictEqual(stylePropertyTreeElement.valueElement?.textContent, 'url(devtools://abc)');\n });\n });\n\n describe('StringRenderer', () => {\n it('unescapes strings', () => {\n const stylePropertyTreeElement = getTreeElement('content', '\"\\\\2716\"');\n stylePropertyTreeElement.updateTitle();\n\n assert.strictEqual(\n (stylePropertyTreeElement.valueElement?.firstElementChild as HTMLElement | null | undefined)?.title,\n '\"\\u2716\"');\n });\n });\n\n describe('ShadowRenderer', () => {\n it('parses shadows correctly', () => {\n const parseShadow = (property: string, value: string, success: boolean) => {\n const stylePropertyTreeElement = getTreeElement(property, value);\n stylePropertyTreeElement.updateTitle();\n\n assert.strictEqual(\n stylePropertyTreeElement.valueElement?.firstElementChild instanceof InlineEditor.Swatches.CSSShadowSwatch,\n success);\n assert.strictEqual(stylePropertyTreeElement.valueElement?.textContent, value);\n };\n\n const parseTextShadowSuccess = (value: string) => parseShadow('text-shadow', value, true);\n const parseTextShadowFailure = (value: string) => parseShadow('text-shadow', value, false);\n const parseBoxShadowSuccess = (value: string) => parseShadow('box-shadow', value, true);\n const parseBoxShadowFailure = (value: string) => parseShadow('box-shadow', value, false);\n\n parseTextShadowSuccess('0 0');\n parseTextShadowSuccess('1px 2px');\n parseTextShadowSuccess('1px 2px black');\n parseTextShadowSuccess('1px 2px 2px');\n parseTextShadowSuccess('rgb(0, 0, 0) 1px 2px 2px');\n parseTextShadowSuccess('1px 2px 2px rgb(0, 0, 0)');\n parseTextShadowSuccess('1px 2px black, 0 0 #ffffff');\n parseTextShadowSuccess('1px -2px black, 0 0 rgb(0, 0, 0), 3px 3.5px 3px');\n parseTextShadowSuccess('1px -2px black, 0 0 rgb(0, 0, 0), 3px 3.5px 3px !important');\n parseTextShadowSuccess('1px 2px black, , 0 0 #ffffff');\n\n parseTextShadowFailure('');\n parseTextShadowFailure('0');\n parseTextShadowFailure('1 2 black !important');\n parseTextShadowFailure('1px black 2px');\n parseTextShadowFailure('1px 2px 2px 3px');\n parseTextShadowFailure('inset 1px 2px 2px');\n parseTextShadowFailure('red 1px 2px 2px red');\n parseTextShadowFailure('1px 2px rgb(0, 0, 0) 2px');\n parseTextShadowFailure('hello 1px 2px');\n parseTextShadowFailure('1px 2px black 0 0 #ffffff');\n // TODO(crbug.com/40945390) Add coverage after rolling codemirror: parseTextShadowFailure('1px2px');\n parseTextShadowFailure('1px 2pxrgb(0, 0, 0)');\n\n parseBoxShadowSuccess('0 0');\n parseBoxShadowSuccess('1px 2px');\n parseBoxShadowSuccess('1px 2px black');\n parseBoxShadowSuccess('1px 2px 2px');\n parseBoxShadowSuccess('1px 2px 2px 3px');\n parseBoxShadowSuccess('inset 1px 2px');\n parseBoxShadowSuccess('1px 2px inset');\n parseBoxShadowSuccess('INSET 1px 2px 2px 3px');\n parseBoxShadowSuccess('rgb(0, 0, 0) 1px 2px 2px');\n parseBoxShadowSuccess('inset rgb(0, 0, 0) 1px 2px 2px');\n parseBoxShadowSuccess('inset 1px 2px 2px 3px rgb(0, 0, 0)');\n parseBoxShadowSuccess('1px 2px 2px 3px rgb(0, 0, 0) inset');\n parseBoxShadowSuccess('1px 2px black, inset 0 0 #ffffff');\n parseBoxShadowSuccess('1px -2px black, inset 0 0 rgb(0, 0, 0), 3px 3.5px 3px 4px');\n parseBoxShadowSuccess('1px 2px black, , 0 0 #ffffff');\n\n parseBoxShadowFailure('');\n parseBoxShadowFailure('0');\n parseBoxShadowFailure('1 2 black');\n parseBoxShadowFailure('1px black 2px');\n parseBoxShadowFailure('1px 2px 2px 3px 4px');\n parseBoxShadowFailure('1px 2px 2px inset 3px');\n parseBoxShadowFailure('inset 1px 2px 2px inset');\n parseBoxShadowFailure('1px 2px rgb(0, 0, 0) 2px');\n parseBoxShadowFailure('hello 1px 2px');\n parseBoxShadowFailure('1px 2px black 0 0 #ffffff');\n // TODO(crbug.com/40945390) Add coverage after rolling codemirror: parseBoxShadowFailure('1px2px');\n parseBoxShadowFailure('1px 2pxrgb(0, 0, 0)');\n });\n\n it('renders the shadow swatch and color swatch', () => {\n const stylePropertyTreeElement = getTreeElement('box-shadow', 'inset 10px 10px blue');\n stylePropertyTreeElement.updateTitle();\n\n assert.instanceOf(\n stylePropertyTreeElement.valueElement?.firstElementChild, InlineEditor.Swatches.CSSShadowSwatch);\n const colorSwatch =\n stylePropertyTreeElement.valueElement?.firstElementChild?.querySelector('devtools-color-swatch');\n assert.exists(colorSwatch);\n assert.strictEqual(colorSwatch.getColor()?.asString(), 'blue');\n });\n\n it('renders multiple icons for multiple shadows', () => {\n const stylePropertyTreeElement = getTreeElement('box-shadow', 'inset 10px 11px blue, notashadow, 6px 5px red');\n stylePropertyTreeElement.updateTitle();\n\n const swatches = stylePropertyTreeElement.valueElement?.querySelectorAll('css-shadow-swatch');\n assert.exists(swatches);\n assert.strictEqual(swatches.length, 2);\n assert.strictEqual(swatches[0].textContent, 'inset 10px 11px blue');\n assert.strictEqual(swatches[1].textContent, '6px 5px red');\n });\n\n it('correctly parses text-shadow', () => {\n const stylePropertyTreeElement =\n getTreeElement('text-shadow', 'inset 10px 11px blue, 6px 5px red, 5px 5px 0 0 yellow');\n stylePropertyTreeElement.updateTitle();\n const swatches = stylePropertyTreeElement.valueElement?.querySelectorAll('css-shadow-swatch');\n assert.exists(swatches);\n assert.strictEqual(swatches.length, 1);\n assert.strictEqual(swatches[0].textContent, '6px 5px red');\n });\n\n it('renders a color-mix child', () => {\n const stylePropertyTreeElement = getTreeElement('box-shadow', '10px 11px color-mix(in srgb, red, blue)');\n stylePropertyTreeElement.updateTitle();\n assert.instanceOf(\n stylePropertyTreeElement.valueElement?.firstElementChild, InlineEditor.Swatches.CSSShadowSwatch);\n const swatches = stylePropertyTreeElement.valueElement?.querySelectorAll('devtools-color-mix-swatch');\n assert.exists(swatches);\n });\n\n it('renders shadow icon in the presence of a var()', () => {\n mockVariableMap['--offset'] = '10px 10px';\n mockVariableMap['--shadow'] = '10px 10px blue';\n\n const stylePropertyTreeElement = getTreeElement('box-shadow', 'var(--offset) red, var(--shadow)');\n stylePropertyTreeElement.updateTitle();\n const swatches = stylePropertyTreeElement.valueElement?.querySelectorAll('css-shadow-swatch');\n assert.exists(swatches);\n assert.strictEqual(swatches.length, 2);\n assert.strictEqual(swatches[0].textContent, 'var(--offset) red');\n assert.strictEqual(swatches[1].textContent, 'var(--shadow)');\n });\n\n it('opens a shadow editor with the correct values', () => {\n mockVariableMap['--offset'] = '10px 10px';\n\n const stylePropertyTreeElement =\n getTreeElement('box-shadow', 'var(--offset) red, inset 8px 9px 10px 11px yellow');\n stylePropertyTreeElement.updateTitle();\n const swatches = stylePropertyTreeElement.valueElement?.querySelectorAll('css-shadow-swatch');\n assert.exists(swatches);\n assert.strictEqual(swatches.length, 2);\n\n const showPopoverStub = sinon.stub(stylePropertyTreeElement.parentPane().swatchPopoverHelper(), 'show');\n\n const editorProperties = (editor: InlineEditor.CSSShadowEditor.CSSShadowEditor): string[] =>\n Array.from(editor.contentElement.querySelectorAll('.shadow-editor-field'))\n .map(\n field => field.querySelector('input')?.value ??\n Array.from(field.querySelectorAll('button'))\n .map(button => button.classList.contains('enabled') ? button.textContent : undefined)\n .filter((b): b is string => Boolean(b)))\n .flat();\n\n {\n swatches[0].iconElement().click();\n assert.isTrue(showPopoverStub.calledOnce);\n assert.instanceOf(showPopoverStub.args[0][0], InlineEditor.CSSShadowEditor.CSSShadowEditor);\n const editor = showPopoverStub.args[0][0] as InlineEditor.CSSShadowEditor.CSSShadowEditor;\n const text = editorProperties(editor);\n assert.deepStrictEqual(text, ['Outset', '10px', '10px', '0', '0']);\n }\n\n {\n swatches[1].iconElement().click();\n assert.isTrue(showPopoverStub.calledTwice);\n assert.instanceOf(showPopoverStub.args[1][0], InlineEditor.CSSShadowEditor.CSSShadowEditor);\n const editor = showPopoverStub.args[1][0] as InlineEditor.CSSShadowEditor.CSSShadowEditor;\n const text = editorProperties(editor);\n assert.deepStrictEqual(text, ['Inset', '8px', '9px', '10px', '11px']);\n }\n });\n\n it('updates the style for shadow editor changes', () => {\n const stylePropertyTreeElement = getTreeElement('box-shadow', '10px 11px red');\n stylePropertyTreeElement.updateTitle();\n const swatches = stylePropertyTreeElement.valueElement?.querySelectorAll('css-shadow-swatch');\n assert.exists(swatches);\n assert.strictEqual(swatches.length, 1);\n const showPopoverStub = sinon.stub(stylePropertyTreeElement.parentPane().swatchPopoverHelper(), 'show');\n swatches[0].iconElement().click();\n assert.isTrue(showPopoverStub.calledOnce);\n\n const applyStyleTextStub = sinon.stub(stylePropertyTreeElement, 'applyStyleText');\n const button =\n showPopoverStub.args[0][0].contentElement.querySelector('.shadow-editor-button-right') as HTMLElement | null;\n button?.click();\n\n assert.isTrue(applyStyleTextStub.calledOnceWithExactly('box-shadow: inset 10px 11px red', false));\n });\n\n it('updates the style for shadow editor changes and respects ordering', () => {\n mockVariableMap['--y-color'] = '11px red';\n const stylePropertyTreeElement = getTreeElement('box-shadow', '10px var(--y-color)');\n stylePropertyTreeElement.updateTitle();\n const swatches = stylePropertyTreeElement.valueElement?.querySelectorAll('css-shadow-swatch');\n assert.exists(swatches);\n assert.strictEqual(swatches.length, 1);\n const showPopoverStub = sinon.stub(stylePropertyTreeElement.parentPane().swatchPopoverHelper(), 'show');\n swatches[0].iconElement().click();\n assert.isTrue(showPopoverStub.calledOnce);\n\n const applyStyleTextStub = sinon.stub(stylePropertyTreeElement, 'applyStyleText');\n const inputs = Array.from(showPopoverStub.args[0][0].contentElement.querySelectorAll('.shadow-editor-field'))\n .map(field => field.querySelector('input'));\n assert.exists(inputs[3]);\n inputs[3].value = '13px';\n inputs[3].dispatchEvent(new InputEvent('input', {data: '13px'}));\n\n assert.isTrue(applyStyleTextStub.calledOnceWithExactly('box-shadow: 10px 11px 13px red', false));\n });\n\n it('correctly builds and updates the shadow model', () => {\n mockVariableMap['--props'] = '12px 13px red';\n const stylePropertyTreeElement = getTreeElement('box-shadow', '10px 11px red, var(--props)');\n stylePropertyTreeElement.updateTitle();\n const swatches = stylePropertyTreeElement.valueElement?.querySelectorAll('css-shadow-swatch');\n assert.exists(swatches);\n assert.lengthOf(swatches, 2);\n\n assert.isTrue(swatches[0].model().isBoxShadow());\n assert.isFalse(swatches[0].model().inset());\n assert.strictEqual(swatches[0].model().offsetX().asCSSText(), '10px');\n assert.strictEqual(swatches[0].model().offsetY().asCSSText(), '11px');\n assert.strictEqual(swatches[0].model().blurRadius().asCSSText(), '0');\n assert.strictEqual(swatches[0].model().spreadRadius().asCSSText(), '0');\n\n swatches[0].model().setSpreadRadius(new InlineEditor.CSSShadowEditor.CSSLength(8, 'px'));\n swatches[0].model().setBlurRadius(new InlineEditor.CSSShadowEditor.CSSLength(5, 'px'));\n assert.strictEqual(swatches[0].model().blurRadius().asCSSText(), '5px');\n assert.strictEqual(swatches[0].model().spreadRadius().asCSSText(), '8px');\n\n assert.isTrue(swatches[1].model().isBoxShadow());\n assert.isFalse(swatches[1].model().inset());\n assert.strictEqual(swatches[1].model().offsetX().asCSSText(), '12px');\n assert.strictEqual(swatches[1].model().offsetY().asCSSText(), '13px');\n assert.strictEqual(swatches[1].model().blurRadius().asCSSText(), '0');\n assert.strictEqual(swatches[1].model().spreadRadius().asCSSText(), '0');\n\n swatches[1].model().setBlurRadius(new InlineEditor.CSSShadowEditor.CSSLength(5, 'px'));\n swatches[1].model().setSpreadRadius(new InlineEditor.CSSShadowEditor.CSSLength(8, 'px'));\n assert.strictEqual(swatches[1].model().blurRadius().asCSSText(), '5px');\n assert.strictEqual(swatches[1].model().spreadRadius().asCSSText(), '8px');\n });\n\n class StubSyntaxnode implements CodeMirror.SyntaxNode {\n parent: CodeMirror.SyntaxNode|null = null;\n firstChild: CodeMirror.SyntaxNode|null = null;\n lastChild: CodeMirror.SyntaxNode|null = null;\n childAfter(): CodeMirror.SyntaxNode|null {\n return null;\n }\n childBefore(): CodeMirror.SyntaxNode|null {\n return null;\n }\n enter(): CodeMirror.SyntaxNode|null {\n return null;\n }\n nextSibling: CodeMirror.SyntaxNode|null = null;\n prevSibling: CodeMirror.SyntaxNode|null = null;\n cursor(): CodeMirror.TreeCursor {\n throw new Error('Method not implemented.');\n }\n resolve(): CodeMirror.SyntaxNode {\n return this;\n }\n resolveInner(): CodeMirror.SyntaxNode {\n return this;\n }\n enterUnfinishedNodesBefore(): CodeMirror.SyntaxNode {\n return this;\n }\n toTree(): CodeMirror.Tree {\n throw new Error('Method not implemented.');\n }\n getChild(): CodeMirror.SyntaxNode|null {\n throw new Error('Method not implemented.');\n }\n getChildren(): CodeMirror.SyntaxNode[] {\n throw new Error('Method not implemented.');\n }\n from: number = 0;\n to: number = 0;\n type = new CodeMirror.NodeType();\n name: string = '';\n tree: CodeMirror.Tree|null = null;\n node: CodeMirror.SyntaxNode = this;\n matchContext(): boolean {\n return false;\n }\n }\n\n it('shadow model renders text properties, authored properties, and computed text properties correctly', () => {\n const renderingContext = sinon.createStubInstance(Elements.PropertyRenderer.RenderingContext);\n const expansionContext = sinon.createStubInstance(Elements.PropertyRenderer.RenderingContext);\n const y = new StubSyntaxnode();\n const spread = new StubSyntaxnode();\n const blur = new StubSyntaxnode();\n const variable = new StubSyntaxnode();\n const properties = [\n {\n value: '10px',\n source: null,\n expansionContext: null,\n propertyType: Elements.StylePropertyTreeElement.ShadowPropertyType.X,\n },\n {\n value: y,\n source: null,\n expansionContext: null,\n propertyType: Elements.StylePropertyTreeElement.ShadowPropertyType.Y,\n },\n {\n value: blur,\n source: variable,\n expansionContext,\n propertyType: Elements.StylePropertyTreeElement.ShadowPropertyType.BLUR,\n },\n {\n value: spread,\n source: variable,\n expansionContext,\n propertyType: Elements.StylePropertyTreeElement.ShadowPropertyType.SPREAD,\n },\n ];\n\n sinon.stub(Elements.PropertyRenderer.Renderer, 'render').callsFake((nodeOrNodes, context) => {\n if (!Array.isArray(nodeOrNodes)) {\n nodeOrNodes = [nodeOrNodes];\n }\n const nodes = nodeOrNodes\n .map(node => {\n switch (node) {\n case y:\n return context === renderingContext && document.createTextNode('y');\n case blur:\n return context === expansionContext && document.createTextNode('blur');\n case spread:\n return context === expansionContext && document.createTextNode('spread');\n case variable:\n return context === renderingContext && document.createTextNode('var()');\n default:\n return undefined;\n }\n })\n .filter((b): b is Text => Boolean(b));\n return {\n nodes,\n nodeGroups: [nodes],\n cssControls: new Map(),\n };\n });\n const model = new Elements.StylePropertyTreeElement.ShadowModel(\n Elements.PropertyMatchers.ShadowType.BOX_SHADOW, properties, renderingContext);\n\n const container = document.createElement('div');\n model.renderContents(container);\n assert.strictEqual(container.textContent, '10px y var()');\n\n model.setBlurRadius(new InlineEditor.CSSShadowEditor.CSSLength(12, 'px'));\n model.renderContents(container);\n assert.strictEqual(container.textContent, '10px y 12px spread');\n assert.deepStrictEqual(properties.map(p => p.source), [null, null, null, null]);\n });\n });\n\n describe('AnchorFunctionRenderer', () => {\n let anchorDecoratedForTestStub: sinon.SinonStub;\n let getAnchorBySpecifierStub: sinon.SinonStub;\n let revealStub: sinon.SinonStub;\n let hideDOMNodeHighlightStub: sinon.SinonStub;\n let highlightMock: sinon.SinonExpectation;\n let fakeParentNode: SDK.DOMModel.DOMNode;\n let fakeDOMNode: SDK.DOMModel.DOMNode;\n\n beforeEach(() => {\n fakeParentNode = {\n localName() {\n return 'span';\n },\n isSVGNode() {\n return false;\n },\n getAnchorBySpecifier() {\n return Promise.resolve(fakeDOMNode);\n },\n } as SDK.DOMModel.DOMNode;\n\n fakeDOMNode = {\n localName() {\n return 'span';\n },\n isSVGNode() {\n return false;\n },\n highlight() {\n highlightMock();\n },\n } as SDK.DOMModel.DOMNode;\n highlightMock = sinon.mock();\n anchorDecoratedForTestStub =\n sinon.stub(Elements.StylePropertyTreeElement.AnchorFunctionRenderer.prototype, 'anchorDecoratedForTest');\n getAnchorBySpecifierStub =\n sinon.stub(SDK.DOMModel.DOMNode.prototype, 'getAnchorBySpecifier').resolves(fakeDOMNode);\n revealStub = sinon.stub(Common.Revealer.RevealerRegistry.prototype, 'reveal');\n hideDOMNodeHighlightStub = sinon.stub(SDK.OverlayModel.OverlayModel, 'hideDOMNodeHighlight');\n });\n\n afterEach(() => {\n anchorDecoratedForTestStub.restore();\n getAnchorBySpecifierStub.restore();\n revealStub.restore();\n hideDOMNodeHighlightStub.restore();\n });\n\n it('renders anchor() function correctly', async () => {\n const stylePropertyTreeElement = getTreeElement('left', 'anchor(top)');\n\n stylePropertyTreeElement.updateTitle();\n\n assert.strictEqual(stylePropertyTreeElement.valueElement!.textContent, 'anchor(top)');\n });\n\n it('renders `AnchorFunctionLinkSwatch` after decorating the element', async () => {\n const waitForDecorationPromise = expectCall(anchorDecoratedForTestStub);\n const stylePropertyTreeElement = getTreeElement('left', 'anchor(--identifier top)');\n sinon.stub(stylePropertyTreeElement, 'node').returns(fakeParentNode);\n\n stylePropertyTreeElement.updateTitle();\n await waitForDecorationPromise;\n const anchorFunctionLinkSwatch =\n stylePropertyTreeElement.valueElement!.querySelector('devtools-anchor-function-link-swatch')! as\n ElementsComponents.AnchorFunctionLinkSwatch.AnchorFunctionLinkSwatch;\n\n assert.strictEqual(anchorFunctionLinkSwatch.dataForTest().identifier, '--identifier');\n });\n\n it('should highlight node when `onMouseEnter` triggered from `AnchorFunctionLinkSwatch`', async () => {\n const waitForDecorationPromise = expectCall(anchorDecoratedForTestStub);\n const stylePropertyTreeElement = getTreeElement('left', 'anchor(--identifier top)');\n sinon.stub(stylePropertyTreeElement, 'node').returns(fakeParentNode);\n\n stylePropertyTreeElement.updateTitle();\n await waitForDecorationPromise;\n const anchorFunctionLinkSwatch =\n stylePropertyTreeElement.valueElement!.querySelector('devtools-anchor-function-link-swatch')! as\n ElementsComponents.AnchorFunctionLinkSwatch.AnchorFunctionLinkSwatch;\n anchorFunctionLinkSwatch.dataForTest().onMouseEnter();\n\n assert.isTrue(highlightMock.calledOnce);\n });\n\n it('should clear DOM highlight when `onMouseLeave` triggered from `AnchorFunctionLinkSwatch`', async () => {\n const waitForDecorationPromise = expectCall(anchorDecoratedForTestStub);\n const stylePropertyTreeElement = getTreeElement('left', 'anchor(--identifier top)');\n sinon.stub(stylePropertyTreeElement, 'node').returns(fakeParentNode);\n\n stylePropertyTreeElement.updateTitle();\n await waitForDecorationPromise;\n const anchorFunctionLinkSwatch =\n stylePropertyTreeElement.valueElement!.querySelector('devtools-anchor-function-link-swatch')! as\n ElementsComponents.AnchorFunctionLinkSwatch.AnchorFunctionLinkSwatch;\n anchorFunctionLinkSwatch.dataForTest().onMouseLeave();\n\n assert.isTrue(hideDOMNodeHighlightStub.calledOnce);\n });\n\n it('should reveal anchor node when `onLinkActivate` triggered from `AnchorFunctionLinkSwatch`', async () => {\n const waitForDecorationPromise = expectCall(anchorDecoratedForTestStub);\n const stylePropertyTreeElement = getTreeElement('left', 'anchor(--identifier top)');\n sinon.stub(stylePropertyTreeElement, 'node').returns(fakeParentNode);\n\n stylePropertyTreeElement.updateTitle();\n await waitForDecorationPromise;\n const anchorFunctionLinkSwatch =\n stylePropertyTreeElement.valueElement!.querySelector('devtools-anchor-function-link-swatch')! as\n ElementsComponents.AnchorFunctionLinkSwatch.AnchorFunctionLinkSwatch;\n anchorFunctionLinkSwatch.dataForTest().onLinkActivate();\n\n assert.isTrue(revealStub.calledOnce);\n assert.isTrue(revealStub.calledWith(fakeDOMNode));\n });\n });\n\n describe('AnchorFunctionRenderer', () => {\n let anchorDecoratedForTestStub: sinon.SinonStub;\n let getAnchorBySpecifierStub: sinon.SinonStub;\n let highlightMock: sinon.SinonExpectation;\n let fakeDOMNode: SDK.DOMModel.DOMNode;\n\n beforeEach(() => {\n fakeDOMNode = {\n localName() {\n return 'span';\n },\n isSVGNode() {\n return false;\n },\n highlight() {\n highlightMock();\n },\n } as SDK.DOMModel.DOMNode;\n highlightMock = sinon.mock();\n anchorDecoratedForTestStub =\n sinon.stub(Elements.StylePropertyTreeElement.PositionAnchorRenderer.prototype, 'anchorDecoratedForTest');\n getAnchorBySpecifierStub =\n sinon.stub(SDK.DOMModel.DOMNode.prototype, 'getAnchorBySpecifier').resolves(fakeDOMNode);\n });\n\n afterEach(() => {\n anchorDecoratedForTestStub.restore();\n getAnchorBySpecifierStub.restore();\n });\n\n it('renders `position-anchor` property correctly before anchor is decorated', async () => {\n const stylePropertyTreeElement = getTreeElement('position-anchor', '--anchor');\n\n stylePropertyTreeElement.updateTitle();\n\n assert.strictEqual(stylePropertyTreeElement.valueElement!.textContent, '--anchor');\n });\n\n it('renders `position-anchor` property correctly after anchor is decorated', async () => {\n const waitForDecorationPromise = expectCall(anchorDecoratedForTestStub);\n const stylePropertyTreeElement = getTreeElement('position-anchor', '--anchor');\n\n stylePropertyTreeElement.updateTitle();\n await waitForDecorationPromise;\n\n const anchorFunctionLinkSwatch =\n stylePropertyTreeElement.valueElement!.querySelector('devtools-anchor-function-link-swatch');\n assert.exists(anchorFunctionLinkSwatch);\n });\n });\n\n describe('LightDarkColorRenderer', () => {\n it('renders light-dark correctly', async () => {\n const colorSchemeSpy =\n sinon.spy(Elements.StylePropertyTreeElement.LightDarkColorRenderer.prototype, 'applyColorScheme');\n\n async function check(colorScheme: SDK.CSSModel.ColorScheme, lightText: string, darkText: string) {\n const variableName = (text: string) => text.substring('var('.length, text.length - 1);\n const lightDark = `light-dark(${lightText}, ${darkText})`;\n const stylePropertyTreeElement = getTreeElement('color', lightDark);\n stylePropertyTreeElement.setComputedStyles(new Map([['color-scheme', colorScheme]]));\n stylePropertyTreeElement.updateTitle();\n await Promise.all(colorSchemeSpy.returnValues);\n\n const swatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-swatch');\n assert.exists(swatch);\n assert.strictEqual(swatch?.textContent, lightDark);\n const activeColor = colorScheme === SDK.CSSModel.ColorScheme.LIGHT ? lightText : darkText;\n assert.strictEqual(\n swatch.getColor()?.getAuthoredText(), mockVariableMap[variableName(activeColor)] ?? activeColor);\n const [light, dark] = swatch.querySelectorAll('devtools-color-swatch');\n assert.exists(light);\n assert.exists(dark);\n const active = colorScheme === SDK.CSSModel.ColorScheme.LIGHT ? light : dark;\n const inactive = colorScheme === SDK.CSSModel.ColorScheme.LIGHT ? dark : light;\n assert.strictEqual(inactive.parentElement?.style.textDecoration, 'line-through');\n assert.strictEqual(active.parentElement?.style.textDecoration, '');\n }\n\n await check(SDK.CSSModel.ColorScheme.LIGHT, 'red', 'blue');\n await check(SDK.CSSModel.ColorScheme.DARK, 'red', 'blue');\n await check(SDK.CSSModel.ColorScheme.LIGHT, 'red', 'var(--blue)');\n await check(SDK.CSSModel.ColorScheme.DARK, 'red', 'var(--blue)');\n await check(SDK.CSSModel.ColorScheme.LIGHT, 'var(--blue)', 'red');\n await check(SDK.CSSModel.ColorScheme.DARK, 'var(--blue)', 'red');\n });\n\n it('renders light-dark correctly if the color scheme cannot be resolved', async () => {\n const lightDark = 'light-dark(red, blue)';\n const cssModel = sinon.createStubInstance(SDK.CSSModel.CSSModel);\n sinon.stub(stylesSidebarPane, 'cssModel').returns(cssModel);\n cssModel.colorScheme.resolves(undefined);\n const stylePropertyTreeElement = getTreeElement('color', lightDark);\n stylePropertyTreeElement.setComputedStyles(new Map([['color-scheme', 'light dark']]));\n const colorSchemeSpy =\n sinon.spy(Elements.StylePropertyTreeElement.LightDarkColorRenderer.prototype, 'applyColorScheme');\n stylePropertyTreeElement.updateTitle();\n await Promise.all(colorSchemeSpy.returnValues);\n\n const swatches = stylePropertyTreeElement.valueElement?.querySelectorAll('devtools-color-swatch');\n assert.exists(swatches);\n assert.lengthOf(swatches, 3);\n assert.isNull(swatches[0].getColor());\n assert.strictEqual(swatches[0].textContent, 'light-dark(red, blue)');\n assert.strictEqual(swatches[1].textContent, 'red');\n assert.strictEqual(swatches[2].textContent, 'blue');\n });\n\n it('renders light-dark without color-scheme correctly', async () => {\n const lightDark = 'light-dark(red, blue)';\n const stylePropertyTreeElement = getTreeElement('color', lightDark);\n // leave color-scheme unset\n const colorSchemeSpy =\n sinon.spy(Elements.StylePropertyTreeElement.LightDarkColorRenderer.prototype, 'applyColorScheme');\n stylePropertyTreeElement.updateTitle();\n await Promise.all(colorSchemeSpy.returnValues);\n\n const swatches = stylePropertyTreeElement.valueElement?.querySelectorAll('devtools-color-swatch');\n assert.exists(swatches);\n assert.lengthOf(swatches, 3);\n assert.strictEqual(swatches[0].getText(), 'red');\n assert.strictEqual(swatches[0].textContent, 'light-dark(red, blue)');\n assert.strictEqual(swatches[1].textContent, 'red');\n assert.strictEqual(swatches[2].textContent, 'blue');\n });\n\n it('renders light-dark with undefined vars correctly', async () => {\n const lightDark = 'light-dark(red, var(--undefined))';\n const stylePropertyTreeElement = getTreeElement('color', lightDark);\n stylePropertyTreeElement.setComputedStyles(new Map([['color-scheme', 'light dark']]));\n const colorSchemeSpy =\n sinon.spy(Elements.StylePropertyTreeElement.LightDarkColorRenderer.prototype, 'applyColorScheme');\n stylePropertyTreeElement.updateTitle();\n await Promise.all(colorSchemeSpy.returnValues);\n\n const swatches = stylePropertyTreeElement.valueElement?.querySelectorAll('devtools-color-swatch');\n assert.exists(swatches);\n assert.lengthOf(swatches, 1);\n assert.strictEqual(swatches[0].textContent, 'red');\n assert.strictEqual(swatches[0].parentElement?.style.textDecoration, '');\n });\n\n it('connects inner and outer swatches', async () => {\n const colorSchemeSpy =\n sinon.spy(Elements.StylePropertyTreeElement.LightDarkColorRenderer.prototype, 'applyColorScheme');\n for (const colorScheme of [SDK.CSSModel.ColorScheme.LIGHT, SDK.CSSModel.ColorScheme.DARK]) {\n const lightDark = 'light-dark(red, blue)';\n const stylePropertyTreeElement = getTreeElement('color', lightDark);\n stylePropertyTreeElement.setComputedStyles(new Map([['color-scheme', colorScheme]]));\n stylePropertyTreeElement.updateTitle();\n await Promise.all(colorSchemeSpy.returnValues);\n\n const outerSwatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-color-swatch');\n assert.exists(outerSwatch);\n const innerSwatches = outerSwatch.querySelectorAll('devtools-color-swatch');\n assert.lengthOf(innerSwatches, 2);\n const [lightSwatch, darkSwatch] = innerSwatches;\n const newLightColor = Common.Color.parse('white') as Common.Color.Color;\n const newDarkColor = Common.Color.parse('black') as Common.Color.Color;\n lightSwatch.setColor(newLightColor);\n darkSwatch.setColor(newDarkColor);\n\n if (colorScheme === SDK.CSSModel.ColorScheme.DARK) {\n assert.strictEqual(outerSwatch.getColor(), newDarkColor);\n } else {\n assert.strictEqual(outerSwatch.getColor(), newLightColor);\n }\n }\n });\n });\n\n describe('LinearGradientRenderer', () => {\n it('correctly connects to an angle match', () => {\n const stylePropertyTreeElement = getTreeElement('background', 'linear-gradient(45deg, red, var(--blue))');\n stylePropertyTreeElement.updateTitle();\n const swatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-css-angle');\n assert.exists(swatch);\n swatch.data = {\n angleText: swatch.textContent ?? '',\n containingPane: document.createElement('div'),\n };\n\n sinon.stub(swatch, 'dispatchEvent');\n swatch.popOver();\n const popover = swatch.shadowRoot?.querySelector('devtools-css-angle-editor');\n assert.exists(popover);\n const clock = popover.shadowRoot?.querySelector('.clock');\n assert.exists(clock);\n assert.strictEqual(clock.style.background, 'linear-gradient(45deg, red, blue)');\n });\n });\n\n describe('LengthRenderer', () => {\n it('renders the length too', () => {\n const stylePropertyTreeElement = getTreeElement('width', '100px');\n stylePropertyTreeElement.updateTitle();\n const swatch = stylePropertyTreeElement.valueElement?.querySelector('devtools-css-length');\n assert.exists(swatch);\n });\n });\n\n describe('Autocompletion', function(this: Mocha.Suite) {\n let promptStub: sinon.SinonStub>;\n beforeEach(async () => {\n promptStub = sinon.stub(Elements.StylesSidebarPane.CSSPropertyPrompt.prototype, 'initialize').resolves([]);\n setMockConnectionResponseHandler('CSS.enable', () => ({}));\n\n const cssModel = new SDK.CSSModel.CSSModel(createTarget());\n await cssModel.resumeModel();\n const domModel = cssModel.domModel();\n const gridNode = new SDK.DOMModel.DOMNode(domModel);\n gridNode.id = 0 as Protocol.DOM.NodeId;\n const currentNode = new SDK.DOMModel.DOMNode(domModel);\n currentNode.id = 1 as Protocol.DOM.NodeId;\n currentNode.parentNode = gridNode;\n LegacyUI.Context.Context.instance().setFlavor(SDK.DOMModel.DOMNode, currentNode);\n });\n\n function suggestions() {\n assert.lengthOf(promptStub.args, 1);\n return promptStub.args[0][0].call(null, '', '');\n }\n\n function setParentComputedStyle(style: Record) {\n const computedStyle = Object.keys(style).map(name => ({name, value: style[name]}));\n setMockConnectionResponseHandler('CSS.getComputedStyleForNode', ({nodeId}) => {\n if (nodeId === 0) {\n return {computedStyle};\n }\n return {};\n });\n }\n\n it('includes grid row names', async () => {\n setParentComputedStyle({display: 'grid', 'grid-template-rows': '[row-name] 1fr [row-name-2]'});\n const stylePropertyTreeElement = getTreeElement('grid-row', 'somename');\n await stylePropertyTreeElement.onpopulate();\n stylePropertyTreeElement.updateTitle();\n stylePropertyTreeElement.startEditingValue();\n const autocompletions = await suggestions();\n assert.deepEqual(\n autocompletions.map(({text}) => text),\n ['row-name', 'row-name-2', 'auto', 'none', 'inherit', 'initial', 'revert', 'revert-layer', 'unset']);\n });\n\n it('includes grid column names', async () => {\n setParentComputedStyle({display: 'grid', 'grid-template-columns': '[col-name] 1fr [col-name-2]'});\n const stylePropertyTreeElement = getTreeElement('grid-column', 'somename');\n await stylePropertyTreeElement.onpopulate();\n stylePropertyTreeElement.updateTitle();\n stylePropertyTreeElement.startEditingValue();\n const autocompletions = await suggestions();\n assert.deepEqual(\n autocompletions.map(({text}) => text),\n ['col-name', 'col-name-2', 'auto', 'none', 'inherit', 'initial', 'revert', 'revert-layer', 'unset']);\n });\n\n it('includes grid area names', async () => {\n setParentComputedStyle({display: 'grid', 'grid-template-areas': '\"area-name-a area-name-b\" \"area-name-c .\"'});\n const stylePropertyTreeElement = getTreeElement('grid-area', 'somename');\n await stylePropertyTreeElement.onpopulate();\n stylePropertyTreeElement.updateTitle();\n stylePropertyTreeElement.startEditingValue();\n const autocompletions = await suggestions();\n assert.deepEqual(autocompletions.map(({text}) => text), [\n 'area-name-a',\n 'area-name-b',\n 'area-name-c',\n 'auto',\n 'none',\n 'inherit',\n 'initial',\n 'revert',\n 'revert-layer',\n 'unset',\n ]);\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/elements/domLinkifier.css.js b/public/panels/elements/domLinkifier.css.js index bba89825f..b504012aa 100644 --- a/public/panels/elements/domLinkifier.css.js +++ b/public/panels/elements/domLinkifier.css.js @@ -21,6 +21,11 @@ styles.replaceSync( pointer-events: auto; outline-offset: 2px; + /* If the element has lots of classes, don't let the label get too wide */ + text-overflow: ellipsis; + overflow: hidden; + max-width: min(100%, 550px); + &:focus-visible { outline-width: unset; } diff --git a/public/panels/explain/components/ConsoleInsight.js b/public/panels/explain/components/ConsoleInsight.js index 1d49aae1a..fe6ba1ac5 100644 --- a/public/panels/explain/components/ConsoleInsight.js +++ b/public/panels/explain/components/ConsoleInsight.js @@ -912,15 +912,15 @@ export class ConsoleInsight extends HTMLElement { Settings <${Buttons.Button.Button.litTagName} - class='lets-go-button' + class='continue-button' @click=${this.#onConsentReminderConfirmed} .data=${{ variant: "primary" /* Buttons.Button.Variant.PRIMARY */, - jslogContext: 'lets-go', - title: 'Let\'s go', + jslogContext: 'continue', + title: 'continue', }} > - Let's go + Continue `; diff --git a/public/panels/explain/components/ConsoleInsight.js.map b/public/panels/explain/components/ConsoleInsight.js.map index 8deb99970..c83c970c0 100644 --- a/public/panels/explain/components/ConsoleInsight.js.map +++ b/public/panels/explain/components/ConsoleInsight.js.map @@ -1 +1 @@ -{"version":3,"file":"ConsoleInsight.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/explain/components/ConsoleInsight.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../../core/common/common.js';\nimport * as Host from '../../../core/host/host.js';\nimport * as i18n from '../../../core/i18n/i18n.js';\nimport type * as Platform from '../../../core/platform/platform.js';\nimport * as Root from '../../../core/root/root.js';\nimport * as SDK from '../../../core/sdk/sdk.js';\nimport * as Marked from '../../../third_party/marked/marked.js';\nimport * as Buttons from '../../../ui/components/buttons/buttons.js';\nimport * as IconButton from '../../../ui/components/icon_button/icon_button.js';\nimport * as Input from '../../../ui/components/input/input.js';\nimport * as MarkdownView from '../../../ui/components/markdown_view/markdown_view.js';\nimport * as Spinners from '../../../ui/components/spinners/spinners.js';\nimport * as UI from '../../../ui/legacy/legacy.js';\nimport * as LitHtml from '../../../ui/lit-html/lit-html.js';\nimport * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';\nimport {type PromptBuilder, type Source, SourceType} from '../PromptBuilder.js';\n\nimport styles from './consoleInsight.css.js';\nimport listStyles from './consoleInsightSourcesList.css.js';\n\n// Note: privacy and legal notices are not localized so far.\nconst UIStrings = {\n /**\n * @description The title of the insight source \"Console message\".\n */\n consoleMessage: 'Console message',\n /**\n * @description The title of the insight source \"Stacktrace\".\n */\n stackTrace: 'Stacktrace',\n /**\n * @description The title of the insight source \"Network request\".\n */\n networkRequest: 'Network request',\n /**\n * @description The title of the insight source \"Related code\".\n */\n relatedCode: 'Related code',\n /**\n * @description The title that is shown while the insight is being generated.\n */\n generating: 'Generating explanation…',\n /**\n * @description The header that indicates that the content shown is a console\n * insight.\n */\n insight: 'Explanation',\n /**\n * @description The title of the a button that closes the insight pane.\n */\n closeInsight: 'Close explanation',\n /**\n * @description The title of the list of source data that was used to generate the insight.\n */\n inputData: 'Data used to understand this message',\n /**\n * @description The title of the button that allows submitting positive\n * feedback about the console insight.\n */\n goodResponse: 'Good response',\n /**\n * @description The title of the button that allows submitting negative\n * feedback about the console insight.\n */\n badResponse: 'Bad response',\n /**\n * @description The title of the button that opens a page to report a legal\n * issue with the console insight.\n */\n report: 'Report legal issue',\n /**\n * @description The text of the header inside the console insight pane when there was an error generating an insight.\n */\n error: 'DevTools has encountered an error',\n /**\n * @description The message shown when an error has been encountered.\n */\n errorBody: 'Something went wrong. Try again.',\n /**\n * @description Label for screenreaders that is added to the end of the link\n * title to indicate that the link will be opened in a new tab.\n */\n opensInNewTab: '(opens in a new tab)',\n /**\n * @description The title of a link that allows the user to learn more about\n * the feature.\n */\n learnMore: 'Learn more',\n /**\n * @description The title of the message when the console insight is not available for some reason.\n */\n notAvailable: 'This feature is not available',\n /**\n * @description The error message when the user is not logged in into Chrome.\n */\n notLoggedIn: 'This feature is only available when you sign into Chrome with your Google account.',\n /**\n * @description The error message when the user is not logged in into Chrome.\n */\n syncIsOff: 'This feature requires you to turn on Chrome sync.',\n /**\n * @description The title of the button that opens Chrome settings.\n */\n updateSettings: 'Update Settings',\n /**\n * @description The header shown when the internet connection is not\n * available.\n */\n offlineHeader: 'DevTools can’t reach the internet',\n /**\n * @description Message shown when the user is offline.\n */\n offline: 'Check your internet connection and try again.',\n /**\n * @description The message shown if the user is not logged in.\n */\n signInToUse: 'Sign in to use this feature',\n /**\n * @description The title of the button that cancels a console insight flow.\n */\n cancel: 'Cancel',\n /**\n * @description The title of the button that disables the Console insight (this) feature.\n */\n disableFeature: 'Disable this feature',\n /**\n * @description The title of the button that goes to the next page.\n */\n next: 'Next',\n /**\n * @description The title of the button that goes back to the previous page.\n */\n back: 'Back',\n /**\n * @description The title of the button that lets the user to continue\n * with using the feature.\n */\n continue: 'Continue',\n /**\n * @description The title of the button that searches for the console\n * insight using a search engine instead of using console insights.\n */\n search: 'Use search instead',\n /**\n * @description Shown to the user when the network request data is not\n * available and a page reload might populate it.\n */\n reloadRecommendation:\n 'Reload the page to capture related network request data for this message in order to create a better insight.',\n /**\n * @description Shown to the user when they need to enable the console insights feature in settings in order to use it.\n * @example {Console insights in Settings} PH1\n */\n turnOnInSettings:\n 'Turn on {PH1} to receive AI assistance for understanding and addressing console warnings and errors.',\n /**\n * @description Text for a link to Chrome DevTools Settings.\n */\n settingsLink: 'Console insights in Settings',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/explain/components/ConsoleInsight.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nconst {render, html, Directives} = LitHtml;\n\nexport class CloseEvent extends Event {\n static readonly eventName = 'close';\n\n constructor() {\n super(CloseEvent.eventName, {composed: true, bubbles: true});\n }\n}\n\ntype PublicPromptBuilder = Pick;\ntype PublicAidaClient = Pick;\n\nfunction localizeType(sourceType: SourceType): string {\n switch (sourceType) {\n case SourceType.MESSAGE:\n return i18nString(UIStrings.consoleMessage);\n case SourceType.STACKTRACE:\n return i18nString(UIStrings.stackTrace);\n case SourceType.NETWORK_REQUEST:\n return i18nString(UIStrings.networkRequest);\n case SourceType.RELATED_CODE:\n return i18nString(UIStrings.relatedCode);\n }\n}\n\nconst TERMS_OF_SERVICE_URL = 'https://policies.google.com/terms';\nconst PRIVACY_POLICY_URL = 'https://policies.google.com/privacy';\nconst CODE_SNIPPET_WARNING_URL = 'https://support.google.com/legal/answer/13505487';\nconst LEARNMORE_URL = 'https://goo.gle/devtools-console-messages-ai' as Platform.DevToolsPath.UrlString;\nconst REPORT_URL = 'https://support.google.com/legal/troubleshooter/1114905?hl=en#ts=1115658%2C13380504' as\n Platform.DevToolsPath.UrlString;\nconst CHROME_SETTINGS_URL = 'chrome://settings' as Platform.DevToolsPath.UrlString;\n\nconst enum State {\n INSIGHT = 'insight',\n LOADING = 'loading',\n ERROR = 'error',\n CONSENT_ONBOARDING = 'consent-onboarding',\n CONSENT_REMINDER = 'consent-reminder',\n NOT_LOGGED_IN = 'not-logged-in',\n SYNC_IS_OFF = 'sync-is-off',\n OFFLINE = 'offline',\n}\n\nconst enum ConsentOnboardingPage {\n PAGE1 = 'private',\n PAGE2 = 'legal',\n}\n\ntype StateData = {\n type: State.LOADING,\n consentOnboardingFinished: boolean,\n consentReminderConfirmed: boolean,\n}|{\n type: State.INSIGHT,\n tokens: MarkdownView.MarkdownView.MarkdownViewData['tokens'],\n validMarkdown: boolean,\n sources: Source[],\n isPageReloadRecommended: boolean,\n completed: boolean,\n}&Host.AidaClient.AidaResponse|{\n type: State.ERROR,\n error: string,\n}|{\n type: State.CONSENT_REMINDER,\n sources: Source[],\n isPageReloadRecommended: boolean,\n}|{\n type: State.CONSENT_ONBOARDING,\n page: ConsentOnboardingPage,\n}|{\n type: State.NOT_LOGGED_IN,\n}|{\n type: State.SYNC_IS_OFF,\n}|{\n type: State.OFFLINE,\n};\n\nexport class ConsoleInsight extends HTMLElement {\n static async create(promptBuilder: PublicPromptBuilder, aidaClient: PublicAidaClient): Promise {\n const aidaAvailability = await Host.AidaClient.AidaClient.checkAccessPreconditions();\n return new ConsoleInsight(promptBuilder, aidaClient, aidaAvailability);\n }\n\n static readonly litTagName = LitHtml.literal`devtools-console-insight`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n\n #promptBuilder: PublicPromptBuilder;\n #aidaClient: PublicAidaClient;\n #renderer = new MarkdownView.MarkdownView.MarkdownInsightRenderer();\n\n // Main state.\n #state: StateData;\n\n // Rating sub-form state.\n #selectedRating?: boolean;\n\n #consoleInsightsEnabledSetting: Common.Settings.Setting|undefined;\n\n constructor(\n promptBuilder: PublicPromptBuilder, aidaClient: PublicAidaClient,\n aidaAvailability: Host.AidaClient.AidaAccessPreconditions) {\n super();\n this.#promptBuilder = promptBuilder;\n this.#aidaClient = aidaClient;\n this.#consoleInsightsEnabledSetting = this.#getConsoleInsightsEnabledSetting();\n\n switch (aidaAvailability) {\n case Host.AidaClient.AidaAccessPreconditions.AVAILABLE:\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n if (this.#consoleInsightsEnabledSetting?.disabled()) {\n this.#state = {\n type: State.CONSENT_ONBOARDING,\n page: ConsentOnboardingPage.PAGE1,\n };\n break;\n }\n // Allows skipping the consent reminder if the user enabled the feature via settings in the current session\n const skipReminder =\n Common.Settings.Settings.instance()\n .createSetting('console-insights-skip-reminder', false, Common.Settings.SettingStorageType.SESSION)\n .get();\n this.#state = {\n type: State.LOADING,\n consentReminderConfirmed: this.#getOnboardingCompletedSetting().get() || skipReminder,\n consentOnboardingFinished: this.#consoleInsightsEnabledSetting?.getIfNotDisabled() === true,\n };\n } else {\n this.#state = {\n type: State.LOADING,\n consentReminderConfirmed: false,\n consentOnboardingFinished: this.#getOnboardingCompletedSetting().get(),\n };\n }\n break;\n case Host.AidaClient.AidaAccessPreconditions.NO_ACCOUNT_EMAIL:\n this.#state = {\n type: State.NOT_LOGGED_IN,\n };\n break;\n case Host.AidaClient.AidaAccessPreconditions.NO_ACTIVE_SYNC:\n this.#state = {\n type: State.SYNC_IS_OFF,\n };\n break;\n case Host.AidaClient.AidaAccessPreconditions.NO_INTERNET:\n this.#state = {\n type: State.OFFLINE,\n };\n break;\n }\n\n this.#render();\n // Stop keyboard event propagation to avoid Console acting on the events\n // inside the insight component.\n this.addEventListener('keydown', e => {\n e.stopPropagation();\n });\n this.addEventListener('keyup', e => {\n e.stopPropagation();\n });\n this.addEventListener('keypress', e => {\n e.stopPropagation();\n });\n this.addEventListener('click', e => {\n e.stopPropagation();\n });\n this.focus();\n }\n\n // The 'console-insights-enabled'-setting controls different things, depending on the 'gen-ai-settings-panel' experiment.\n // experiment off:\n // setting off -> no entrypoints for console insights shown\n // setting on -> entrypoints are shown\n // experiment on:\n // setting off -> entrypoints are shown, and point to the AI setting panel where the setting can be turned on\n // setting on -> entrypoints are shown, and lead to directly generating a console insight\n #getConsoleInsightsEnabledSetting(): Common.Settings.Setting|undefined {\n try {\n return Common.Settings.moduleSetting('console-insights-enabled') as Common.Settings.Setting;\n } catch {\n return;\n }\n }\n\n // The 'console-insights-onboarding-finished'-setting controls different things, depending on the 'gen-ai-settings-panel' experiment.\n // experiment off:\n // setting off -> 2-page onboarding disclaimer is shown before generating a console insight\n // setting on -> no onboarding disclaimer\n // experiment on:\n // setting off -> single page consent reminder is shown, unless the 'console-insights-enabled'-setting has been enabled in the current DevTools session\n // setting on -> no consent reminder shown\n #getOnboardingCompletedSetting(): Common.Settings.Setting {\n return Common.Settings.Settings.instance().createLocalSetting('console-insights-onboarding-finished', false);\n }\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [styles, Input.checkboxStyles];\n this.classList.add('opening');\n this.#consoleInsightsEnabledSetting?.addChangeListener(this.#onConsoleInsightsSettingChanged, this);\n if (this.#state.type === State.LOADING && this.#state.consentOnboardingFinished &&\n this.#state.consentReminderConfirmed) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.GeneratingInsightWithoutDisclaimer);\n }\n void this.#generateInsightIfNeeded();\n }\n\n disconnectedCallback(): void {\n this.#consoleInsightsEnabledSetting?.removeChangeListener(this.#onConsoleInsightsSettingChanged, this);\n }\n\n #onConsoleInsightsSettingChanged(): void {\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n if (this.#consoleInsightsEnabledSetting?.getIfNotDisabled() === true) {\n this.#getOnboardingCompletedSetting().set(true);\n }\n if (this.#state.type === State.CONSENT_ONBOARDING &&\n this.#consoleInsightsEnabledSetting?.getIfNotDisabled() === true) {\n this.#transitionTo({\n type: State.LOADING,\n consentReminderConfirmed: true,\n consentOnboardingFinished: true,\n });\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsOptInTeaserConfirmedInSettings);\n void this.#generateInsightIfNeeded();\n }\n if (this.#state.type === State.CONSENT_REMINDER &&\n this.#consoleInsightsEnabledSetting?.getIfNotDisabled() === false) {\n this.#transitionTo({\n type: State.LOADING,\n consentReminderConfirmed: false,\n consentOnboardingFinished: false,\n });\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsReminderTeaserAbortedInSettings);\n void this.#generateInsightIfNeeded();\n }\n }\n }\n\n #transitionTo(newState: StateData): void {\n const previousState = this.#state;\n this.#state = newState;\n this.#render();\n if (newState.type !== previousState.type) {\n this.#focusHeader();\n }\n }\n\n async #generateInsightIfNeeded(): Promise {\n if (this.#state.type !== State.LOADING) {\n return;\n }\n if (!this.#state.consentOnboardingFinished) {\n this.#transitionTo({\n type: State.CONSENT_ONBOARDING,\n page: ConsentOnboardingPage.PAGE1,\n });\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsOptInTeaserShown);\n } else {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsOnboardingShown);\n }\n return;\n }\n if (!this.#state.consentReminderConfirmed) {\n const {sources, isPageReloadRecommended} = await this.#promptBuilder.buildPrompt();\n this.#transitionTo({\n type: State.CONSENT_REMINDER,\n sources,\n isPageReloadRecommended,\n });\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsReminderTeaserShown);\n } else {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightConsentReminderShown);\n }\n return;\n }\n await this.#generateInsight();\n }\n\n #onClose(): void {\n if (this.#state.type === State.CONSENT_REMINDER) {\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsReminderTeaserCanceled);\n } else {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightConsentReminderCanceled);\n }\n } else if (this.#state.type === State.CONSENT_ONBOARDING) {\n if (this.#state.page === ConsentOnboardingPage.PAGE1) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsOnboardingCanceledOnPage1);\n } else {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsOnboardingCanceledOnPage2);\n }\n }\n this.shadowRoot?.addEventListener('animationend', () => {\n this.dispatchEvent(new CloseEvent());\n }, {once: true});\n this.classList.add('closing');\n }\n\n #onRating(event: Event): void {\n if (this.#state.type !== State.INSIGHT) {\n throw new Error('Unexpected state');\n }\n if (this.#state.metadata?.rpcGlobalId === undefined) {\n throw new Error('RPC Id not in metadata');\n }\n // If it was rated, do not record again.\n if (this.#selectedRating !== undefined) {\n return;\n }\n\n this.#selectedRating = (event.target as HTMLElement).dataset.rating === 'true';\n this.#render();\n if (this.#selectedRating) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightRatedPositive);\n } else {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightRatedNegative);\n }\n const disallowLogging =\n Common.Settings.Settings.instance().getHostConfig().aidaAvailability?.disallowLogging ?? true;\n void this.#aidaClient.registerClientEvent({\n corresponding_aida_rpc_global_id: this.#state.metadata.rpcGlobalId,\n disable_user_content_logging: disallowLogging,\n do_conversation_client_event: {\n user_feedback: {\n sentiment: this.#selectedRating ? Host.AidaClient.Rating.POSITIVE : Host.AidaClient.Rating.NEGATIVE,\n },\n },\n });\n }\n\n #onReport(): void {\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(REPORT_URL);\n }\n\n #onSearch(): void {\n const query = this.#promptBuilder.getSearchQuery();\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.openSearchResultsInNewTab(query);\n }\n\n async #onConsentReminderConfirmed(): Promise {\n this.#getOnboardingCompletedSetting().set(true);\n this.#transitionTo({\n type: State.LOADING,\n consentReminderConfirmed: true,\n consentOnboardingFinished: true,\n });\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsReminderTeaserConfirmed);\n } else {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightConsentReminderConfirmed);\n }\n await this.#generateInsight();\n }\n\n async #generateInsight(): Promise {\n try {\n for await (const {sources, isPageReloadRecommended, explanation, metadata, completed} of this.#getInsight()) {\n const tokens = this.#validateMarkdown(explanation);\n const valid = tokens !== false;\n this.#transitionTo({\n type: State.INSIGHT,\n tokens: valid ? tokens : [],\n validMarkdown: valid,\n explanation,\n sources,\n metadata,\n isPageReloadRecommended,\n completed,\n });\n }\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightGenerated);\n } catch (err) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightErrored);\n this.#transitionTo({\n type: State.ERROR,\n error: err.message,\n });\n }\n }\n\n /**\n * Validates the markdown by trying to render it.\n */\n #validateMarkdown(text: string): Marked.Marked.TokensList|false {\n try {\n const tokens = Marked.Marked.lexer(text);\n for (const token of tokens) {\n this.#renderer.renderToken(token);\n }\n return tokens;\n } catch {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightErroredMarkdown);\n return false;\n }\n }\n\n async *\n #getInsight(): AsyncGenerator<\n {sources: Source[], isPageReloadRecommended: boolean}&Host.AidaClient.AidaResponse, void, void> {\n const {prompt, sources, isPageReloadRecommended} = await this.#promptBuilder.buildPrompt();\n try {\n for await (\n const response of this.#aidaClient.fetch(Host.AidaClient.AidaClient.buildConsoleInsightsRequest(prompt))) {\n yield {sources, isPageReloadRecommended, ...response};\n }\n } catch (err) {\n if (err.message === 'Server responded: permission denied') {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightErroredPermissionDenied);\n } else if (err.message.startsWith('Cannot send request:')) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightErroredCannotSend);\n } else if (err.message.startsWith('Request failed:')) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightErroredRequestFailed);\n } else if (err.message.startsWith('Cannot parse chunk:')) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightErroredCannotParseChunk);\n } else if (err.message === 'Unknown chunk result') {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightErroredUnknownChunk);\n } else if (err.message.startsWith('Server responded:')) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightErroredApi);\n } else {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightErroredOther);\n }\n throw err;\n }\n }\n\n #onGoToSettings(): void {\n const rootTarget = SDK.TargetManager.TargetManager.instance().rootTarget();\n if (rootTarget === null) {\n return;\n }\n const url = CHROME_SETTINGS_URL;\n void rootTarget.targetAgent().invoke_createTarget({url}).then(result => {\n if (result.getError()) {\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(url);\n }\n });\n }\n\n #onDisableFeature(): void {\n this.#consoleInsightsEnabledSetting?.set(false);\n this.#onClose();\n UI.InspectorView.InspectorView.instance().displayReloadRequiredWarning('Reload for the change to apply.');\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsOnboardingFeatureDisabled);\n }\n\n #goToNextPage(): void {\n this.#transitionTo({\n type: State.CONSENT_ONBOARDING,\n page: ConsentOnboardingPage.PAGE2,\n });\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsOnboardingNextPage);\n }\n\n #focusHeader(): void {\n this.addEventListener('animationend', () => {\n (this.#shadow.querySelector('header h2') as HTMLElement | undefined)?.focus();\n }, {once: true});\n }\n\n #termsChecked(): boolean {\n const checkbox = this.#shadow.querySelector('.terms') as HTMLInputElement | undefined;\n if (!checkbox?.checked) {\n return false;\n }\n return true;\n }\n\n #onConsentOnboardingConfirmed(): void {\n if (!this.#termsChecked()) {\n return;\n }\n this.#getOnboardingCompletedSetting().set(true);\n this.#transitionTo({\n type: State.LOADING,\n consentReminderConfirmed: false,\n consentOnboardingFinished: this.#getOnboardingCompletedSetting().get(),\n });\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsOnboardingConfirmed);\n void this.#generateInsightIfNeeded();\n }\n\n #goToPrevPage(): void {\n this.#transitionTo({\n type: State.CONSENT_ONBOARDING,\n page: ConsentOnboardingPage.PAGE1,\n });\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsOnboardingPrevPage);\n }\n\n #renderCancelButton(): LitHtml.TemplateResult {\n // clang-format off\n return html`<${Buttons.Button.Button.litTagName}\n class=\"cancel-button\"\n @click=${this.#onClose}\n .data=${\n {\n variant: Buttons.Button.Variant.OUTLINED,\n jslogContext: 'cancel',\n } as Buttons.Button.ButtonData\n }\n >\n ${i18nString(UIStrings.cancel)}\n `;\n // clang-format on\n }\n\n #renderDisableFeatureButton(): LitHtml.TemplateResult {\n // clang-format off\n return html`<${Buttons.Button.Button.litTagName}\n @click=${this.#onDisableFeature}\n class=\"disable-button\"\n .data=${\n {\n variant: Buttons.Button.Variant.OUTLINED,\n jslogContext: 'disable',\n } as Buttons.Button.ButtonData\n }\n >\n ${i18nString(UIStrings.disableFeature)}\n `;\n // clang-format on\n }\n\n #renderNextButton(): LitHtml.TemplateResult {\n // clang-format off\n return html`<${Buttons.Button.Button.litTagName}\n class=\"next-button\"\n @click=${this.#goToNextPage}\n .data=${\n {\n variant: Buttons.Button.Variant.PRIMARY,\n jslogContext: 'next',\n } as Buttons.Button.ButtonData\n }\n >\n ${i18nString(UIStrings.next)}\n `;\n // clang-format on\n }\n\n #renderBackButton(): LitHtml.TemplateResult {\n // clang-format off\n return html`<${Buttons.Button.Button.litTagName}\n @click=${this.#goToPrevPage}\n .data=${\n {\n variant: Buttons.Button.Variant.OUTLINED,\n jslogContext: 'back',\n } as Buttons.Button.ButtonData\n }\n >\n ${i18nString(UIStrings.back)}\n `;\n // clang-format on\n }\n\n #renderContinueButton(handler: (event: Event) => void, disabled = false): LitHtml.TemplateResult {\n // clang-format off\n return html`<${Buttons.Button.Button.litTagName}\n @click=${handler}\n class=\"continue-button\"\n .data=${\n {\n variant: Buttons.Button.Variant.PRIMARY,\n disabled,\n jslogContext: 'continue',\n } as Buttons.Button.ButtonData\n }\n >\n ${i18nString(UIStrings.continue)}\n `;\n // clang-format on\n }\n\n #renderSearchButton(): LitHtml.TemplateResult {\n // clang-format off\n return html`<${Buttons.Button.Button.litTagName}\n @click=${this.#onSearch}\n class=\"search-button\"\n .data=${\n {\n variant: Buttons.Button.Variant.OUTLINED,\n jslogContext: 'search',\n } as Buttons.Button.ButtonData\n }\n >\n ${i18nString(UIStrings.search)}\n `;\n // clang-format on\n }\n\n #renderLearnMoreAboutInsights(): LitHtml.TemplateResult {\n // clang-format off\n return html`\n ${i18nString(UIStrings.learnMore)}\n `;\n // clang-format on\n }\n\n #onTermsChange(): void {\n this.#render();\n }\n\n #renderMain(): LitHtml.TemplateResult {\n const jslog = `${VisualLogging.section(this.#state.type).track({resize: true})}`;\n const disallowLogging =\n Common.Settings.Settings.instance().getHostConfig().aidaAvailability?.disallowLogging ?? true;\n // clang-format off\n switch (this.#state.type) {\n case State.LOADING:\n return html`
\n
\n \n \n \n \n \n \n \n
\n
`;\n case State.INSIGHT:\n return html`\n
\n ${\n this.#state.validMarkdown ? html`<${MarkdownView.MarkdownView.MarkdownView.litTagName}\n .data=${{tokens: this.#state.tokens, renderer: this.#renderer} as MarkdownView.MarkdownView.MarkdownViewData}>\n `: this.#state.explanation\n }\n
\n ${i18nString(UIStrings.inputData)}\n <${ConsoleInsightSourcesList.litTagName} .sources=${this.#state.sources} .isPageReloadRecommended=${this.#state.isPageReloadRecommended}>\n \n
\n
\n ${this.#renderSearchButton()}\n
\n
`;\n case State.ERROR:\n return html`\n
\n
${i18nString(UIStrings.errorBody)}
\n
`;\n case State.CONSENT_REMINDER:\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n return html`\n
\n

Things to consider

\n
\n
\n <${IconButton.Icon.Icon.litTagName} .data=${{\n iconName: 'google',\n width: 'var(--sys-size-8)',\n height: 'var(--sys-size-8)',\n } as IconButton.Icon.IconData}>\n \n
\n
The console message, associated stack trace, related source code, and the associated network headers are sent to Google to generate explanations. This data may be seen by human reviewers to improve this feature. Avoid sharing sensitive or personal information.
\n
\n <${IconButton.Icon.Icon.litTagName} .data=${{\n iconName: 'policy',\n width: 'var(--sys-size-8)',\n height: 'var(--sys-size-8)',\n } as IconButton.Icon.IconData}>\n \n
\n
Use of this feature is subject to the\n Google Terms of Service\n and\n Google Privacy Policy\n
\n
\n <${IconButton.Icon.Icon.litTagName} .data=${{\n iconName: 'warning',\n width: 'var(--sys-size-8)',\n height: 'var(--sys-size-8)',\n } as IconButton.Icon.IconData}>\n \n
\n
\n Use generated code snippets with caution\n
\n
\n
\n `;\n }\n return html`\n
\n

The following data will be sent to Google to understand the context for the console message.\n ${disallowLogging ? '' : 'Human reviewers may process this information for quality purposes. Don’t submit sensitive information.'}\n Read Google’s Terms of Service.

\n <${ConsoleInsightSourcesList.litTagName} .sources=${this.#state.sources} .isPageReloadRecommended=${this.#state.isPageReloadRecommended}>\n \n
\n `;\n case State.CONSENT_ONBOARDING: {\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n const settingsLink = document.createElement('button');\n settingsLink.textContent = i18nString(UIStrings.settingsLink);\n settingsLink.classList.add('link');\n UI.ARIAUtils.markAsLink(settingsLink);\n settingsLink.addEventListener('click', () => {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsOptInTeaserSettingsLinkClicked);\n void UI.ViewManager.ViewManager.instance().showView('chrome-ai');\n });\n settingsLink.setAttribute('jslog', `${VisualLogging.action('open-ai-settings').track({click: true})}`);\n\n return html`
\n
\n <${IconButton.Icon.Icon.litTagName} .data=${{\n iconName: 'lightbulb-spark',\n width: 'var(--sys-size-8)',\n height: 'var(--sys-size-8)',\n } as IconButton.Icon.IconData}>\n \n
\n
\n ${i18n.i18n.getFormatLocalizedString(str_, UIStrings.turnOnInSettings, {PH1: settingsLink})}\n ${this.#renderLearnMoreAboutInsights()}\n
\n
`;\n }\n switch (this.#state.page) {\n case ConsentOnboardingPage.PAGE1:\n return html`
\n

This notice and our privacy notice describe how Chrome DevTools handles your data. Please read them carefully.

\n\n

Chrome DevTools uses the console message, associated stack trace, related source code, and the associated network headers as input data. When you use \"Understand this message\", Google collects this input data, generated output, related feature usage information, and your feedback. Google uses this data to provide, improve, and develop Google products and services and machine learning technologies, including Google's enterprise products such as Google Cloud.

\n\n

To help with quality and improve our products, human reviewers may read, annotate, and process the above-mentioned input data, generated output, related feature usage information, and your feedback. Please do not include sensitive (e.g., confidential) or personal information that can be used to identify you or others in your prompts or feedback. Your data will be stored in a way where Google cannot tell who provided it and can no longer fulfill any deletion requests and will be retained for up to 18 months. We may refrain from collecting data to improve our product if your Google account is managed by an organization and depending on your region.

\n
`;\n case ConsentOnboardingPage.PAGE2:\n return html`
\n

As you try \"Understand this message\", here are key things to know:\n\n

    \n
  • Chrome DevTools uses console message, associated stack trace, related source code, and the associated network headers to provide answers.
  • \n
  • Chrome DevTools uses experimental technology, and may generate inaccurate or offensive information that doesn't represent Google's views. Voting on the responses will help make this feature better.
  • \n
  • This feature is an experimental feature and subject to future changes.
  • \n
  • Use generated code snippets with caution.
  • \n
\n

\n\n

\n \n

\n
`;\n }\n }\n case State.NOT_LOGGED_IN:\n return html`\n
\n
${i18nString(UIStrings.notLoggedIn)}
\n
`;\n case State.SYNC_IS_OFF:\n return html`\n
\n
${i18nString(UIStrings.syncIsOff)}
\n
`;\n case State.OFFLINE:\n return html`\n
\n
${i18nString(UIStrings.offline)}
\n
`;\n }\n // clang-format on\n }\n\n #renderDisclaimer(): LitHtml.LitTemplate {\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n // clang-format off\n return LitHtml.html`\n Chrome AI may generate inaccurate info that does not represent Google's views. Data sent to Google may be seen by human reviewers to improve this feature.\n \n or\n learn more\n `;\n }\n return LitHtml.html`\n This feature may display inaccurate or offensive information that doesn't represent Google's views.\n ${i18nString(UIStrings.learnMore)}\n `;\n // clang-format on\n }\n\n #renderFooter(): LitHtml.LitTemplate {\n const showThumbsUpDownButtons =\n !(Common.Settings.Settings.instance().getHostConfig().aidaAvailability?.disallowLogging ?? true);\n const disclaimer = this.#renderDisclaimer();\n // clang-format off\n switch (this.#state.type) {\n case State.LOADING:\n return LitHtml.nothing;\n case State.ERROR:\n case State.OFFLINE:\n return html`
\n
\n ${disclaimer}\n
\n
`;\n case State.NOT_LOGGED_IN:\n case State.SYNC_IS_OFF:\n return html`
\n
\n
\n <${Buttons.Button.Button.litTagName}\n @click=${this.#onGoToSettings}\n .data=${\n {\n variant: Buttons.Button.Variant.PRIMARY,\n jslogContext: 'update-settings',\n } as Buttons.Button.ButtonData\n }\n >\n ${UIStrings.updateSettings}\n \n
\n
`;\n case State.CONSENT_REMINDER:\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n return html`
\n
\n
\n <${Buttons.Button.Button.litTagName}\n @click=${() => {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsReminderTeaserSettingsLinkClicked);\n void UI.ViewManager.ViewManager.instance().showView('chrome-ai');\n }}\n .data=${\n {\n variant: Buttons.Button.Variant.TONAL,\n jslogContext: 'settings',\n title: 'Settings',\n } as Buttons.Button.ButtonData\n }\n >\n Settings\n \n <${Buttons.Button.Button.litTagName}\n class='lets-go-button'\n @click=${this.#onConsentReminderConfirmed}\n .data=${\n {\n variant: Buttons.Button.Variant.PRIMARY,\n jslogContext: 'lets-go',\n title: 'Let\\'s go',\n } as Buttons.Button.ButtonData\n }\n >\n Let's go\n \n
\n
`;\n }\n return html`
\n
\n ${disclaimer}\n
\n
\n
\n ${this.#renderCancelButton()}\n ${this.#renderContinueButton(this.#onConsentReminderConfirmed)}\n
\n
`;\n case State.CONSENT_ONBOARDING:\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n return LitHtml.nothing;\n }\n switch (this.#state.page) {\n case ConsentOnboardingPage.PAGE1:\n return html`
\n
\n ${this.#renderLearnMoreAboutInsights()}\n
\n
\n
\n ${this.#renderCancelButton()}\n ${this.#renderDisableFeatureButton()}\n ${this.#renderNextButton()}\n
\n
`;\n case ConsentOnboardingPage.PAGE2:\n return html`
\n
\n ${this.#renderLearnMoreAboutInsights()}\n
\n
\n
\n ${this.#renderBackButton()}\n ${this.#renderDisableFeatureButton()}\n ${this.#renderContinueButton(this.#onConsentOnboardingConfirmed, !this.#termsChecked())}\n
\n
`;\n }\n case State.INSIGHT:\n return html`
\n
\n ${disclaimer}\n
\n
\n
\n ${showThumbsUpDownButtons ? html`\n <${Buttons.Button.Button.litTagName}\n data-rating=${'true'}\n .data=${\n {\n variant: Buttons.Button.Variant.ICON,\n size: Buttons.Button.Size.SMALL,\n iconName: 'thumb-up',\n active: this.#selectedRating !== undefined && this.#selectedRating,\n title: i18nString(UIStrings.goodResponse),\n jslogContext: 'thumbs-up',\n } as Buttons.Button.ButtonData\n }\n @click=${this.#onRating}\n >\n <${Buttons.Button.Button.litTagName}\n data-rating=${'false'}\n .data=${\n {\n variant: Buttons.Button.Variant.ICON,\n size: Buttons.Button.Size.SMALL,\n iconName: 'thumb-down',\n active: this.#selectedRating !== undefined && !this.#selectedRating,\n title: i18nString(UIStrings.badResponse),\n jslogContext: 'thumbs-down',\n } as Buttons.Button.ButtonData\n }\n @click=${this.#onRating}\n >\n ` : LitHtml.nothing}\n <${Buttons.Button.Button.litTagName}\n .data=${\n {\n variant: Buttons.Button.Variant.ICON,\n size: Buttons.Button.Size.SMALL,\n iconName: 'report',\n title: i18nString(UIStrings.report),\n jslogContext: 'report',\n } as Buttons.Button.ButtonData\n }\n @click=${this.#onReport}\n >\n
\n\n
`;\n }\n // clang-format on\n }\n\n #getHeader(): string {\n switch (this.#state.type) {\n case State.NOT_LOGGED_IN:\n return i18nString(UIStrings.signInToUse);\n case State.SYNC_IS_OFF:\n return i18nString(UIStrings.notAvailable);\n case State.OFFLINE:\n return i18nString(UIStrings.offlineHeader);\n case State.LOADING:\n return i18nString(UIStrings.generating);\n case State.INSIGHT:\n return i18nString(UIStrings.insight);\n case State.ERROR:\n return i18nString(UIStrings.error);\n case State.CONSENT_REMINDER:\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n return 'Understand console messages with Chrome AI';\n }\n return i18nString(UIStrings.inputData);\n case State.CONSENT_ONBOARDING:\n switch (this.#state.page) {\n case ConsentOnboardingPage.PAGE1:\n return 'Privacy notice';\n case ConsentOnboardingPage.PAGE2:\n return 'Legal notice';\n }\n }\n }\n\n #renderSpinner(): LitHtml.LitTemplate {\n // clang-format off\n if (this.#state.type === State.INSIGHT && !this.#state.completed) {\n return html`<${Spinners.Spinner.Spinner.litTagName}>`;\n }\n return LitHtml.nothing;\n // clang-format on\n }\n\n #renderHeader(): LitHtml.LitTemplate {\n if (this.#state.type === State.CONSENT_ONBOARDING &&\n Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n return LitHtml.nothing;\n }\n const hasIcon = Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL) &&\n this.#state.type === State.CONSENT_REMINDER;\n // clang-format off\n return html`\n
\n ${hasIcon ? html`\n
\n <${IconButton.Icon.Icon.litTagName} .data=${{\n iconName: 'lightbulb-spark',\n width: '18px',\n height: '18px',\n } as IconButton.Icon.IconData}>\n \n
`\n : LitHtml.nothing}\n
\n

\n ${this.#getHeader()}\n

\n ${this.#renderSpinner()}\n
\n
\n <${Buttons.Button.Button.litTagName}\n .data=${\n {\n variant: Buttons.Button.Variant.ICON,\n size: Buttons.Button.Size.SMALL,\n iconName: 'cross',\n title: i18nString(UIStrings.closeInsight),\n } as Buttons.Button.ButtonData\n }\n jslog=${VisualLogging.close().track({click: true})}\n @click=${this.#onClose}\n >\n
\n
\n `;\n // clang-format on\n }\n\n #render(): void {\n // clang-format off\n render(html`\n
\n
\n ${this.#renderHeader()}\n ${this.#renderMain()}\n ${this.#renderFooter()}\n
\n
\n `, this.#shadow, {\n host: this,\n });\n // clang-format on\n }\n}\n\nclass ConsoleInsightSourcesList extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-console-insight-sources-list`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n #sources: Source[] = [];\n #isPageReloadRecommended = false;\n\n constructor() {\n super();\n this.#shadow.adoptedStyleSheets = [listStyles, Input.checkboxStyles];\n }\n\n #render(): void {\n // clang-format off\n render(html`\n
    \n ${Directives.repeat(this.#sources, item => item.value, item => {\n return html`
  • \n <${IconButton.Icon.Icon.litTagName} name=\"open-externally\">\n ${localizeType(item.type)}\n
  • `;\n })}\n ${this.#isPageReloadRecommended ? LitHtml.html`
  • \n <${IconButton.Icon.Icon.litTagName} name=\"warning\">\n ${i18nString(UIStrings.reloadRecommendation)}
  • ` : LitHtml.nothing}\n
\n `, this.#shadow, {\n host: this,\n });\n // clang-format on\n }\n\n set sources(values: Source[]) {\n this.#sources = values;\n this.#render();\n }\n\n set isPageReloadRecommended(isPageReloadRecommended: boolean) {\n this.#isPageReloadRecommended = isPageReloadRecommended;\n this.#render();\n }\n}\n\ncustomElements.define('devtools-console-insight', ConsoleInsight);\ncustomElements.define('devtools-console-insight-sources-list', ConsoleInsightSourcesList);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-console-insight': ConsoleInsight;\n 'devtools-console-insight-sources-list': ConsoleInsightSourcesList;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"ConsoleInsight.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/explain/components/ConsoleInsight.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../../core/common/common.js';\nimport * as Host from '../../../core/host/host.js';\nimport * as i18n from '../../../core/i18n/i18n.js';\nimport type * as Platform from '../../../core/platform/platform.js';\nimport * as Root from '../../../core/root/root.js';\nimport * as SDK from '../../../core/sdk/sdk.js';\nimport * as Marked from '../../../third_party/marked/marked.js';\nimport * as Buttons from '../../../ui/components/buttons/buttons.js';\nimport * as IconButton from '../../../ui/components/icon_button/icon_button.js';\nimport * as Input from '../../../ui/components/input/input.js';\nimport * as MarkdownView from '../../../ui/components/markdown_view/markdown_view.js';\nimport * as Spinners from '../../../ui/components/spinners/spinners.js';\nimport * as UI from '../../../ui/legacy/legacy.js';\nimport * as LitHtml from '../../../ui/lit-html/lit-html.js';\nimport * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';\nimport {type PromptBuilder, type Source, SourceType} from '../PromptBuilder.js';\n\nimport styles from './consoleInsight.css.js';\nimport listStyles from './consoleInsightSourcesList.css.js';\n\n// Note: privacy and legal notices are not localized so far.\nconst UIStrings = {\n /**\n * @description The title of the insight source \"Console message\".\n */\n consoleMessage: 'Console message',\n /**\n * @description The title of the insight source \"Stacktrace\".\n */\n stackTrace: 'Stacktrace',\n /**\n * @description The title of the insight source \"Network request\".\n */\n networkRequest: 'Network request',\n /**\n * @description The title of the insight source \"Related code\".\n */\n relatedCode: 'Related code',\n /**\n * @description The title that is shown while the insight is being generated.\n */\n generating: 'Generating explanation…',\n /**\n * @description The header that indicates that the content shown is a console\n * insight.\n */\n insight: 'Explanation',\n /**\n * @description The title of the a button that closes the insight pane.\n */\n closeInsight: 'Close explanation',\n /**\n * @description The title of the list of source data that was used to generate the insight.\n */\n inputData: 'Data used to understand this message',\n /**\n * @description The title of the button that allows submitting positive\n * feedback about the console insight.\n */\n goodResponse: 'Good response',\n /**\n * @description The title of the button that allows submitting negative\n * feedback about the console insight.\n */\n badResponse: 'Bad response',\n /**\n * @description The title of the button that opens a page to report a legal\n * issue with the console insight.\n */\n report: 'Report legal issue',\n /**\n * @description The text of the header inside the console insight pane when there was an error generating an insight.\n */\n error: 'DevTools has encountered an error',\n /**\n * @description The message shown when an error has been encountered.\n */\n errorBody: 'Something went wrong. Try again.',\n /**\n * @description Label for screenreaders that is added to the end of the link\n * title to indicate that the link will be opened in a new tab.\n */\n opensInNewTab: '(opens in a new tab)',\n /**\n * @description The title of a link that allows the user to learn more about\n * the feature.\n */\n learnMore: 'Learn more',\n /**\n * @description The title of the message when the console insight is not available for some reason.\n */\n notAvailable: 'This feature is not available',\n /**\n * @description The error message when the user is not logged in into Chrome.\n */\n notLoggedIn: 'This feature is only available when you sign into Chrome with your Google account.',\n /**\n * @description The error message when the user is not logged in into Chrome.\n */\n syncIsOff: 'This feature requires you to turn on Chrome sync.',\n /**\n * @description The title of the button that opens Chrome settings.\n */\n updateSettings: 'Update Settings',\n /**\n * @description The header shown when the internet connection is not\n * available.\n */\n offlineHeader: 'DevTools can’t reach the internet',\n /**\n * @description Message shown when the user is offline.\n */\n offline: 'Check your internet connection and try again.',\n /**\n * @description The message shown if the user is not logged in.\n */\n signInToUse: 'Sign in to use this feature',\n /**\n * @description The title of the button that cancels a console insight flow.\n */\n cancel: 'Cancel',\n /**\n * @description The title of the button that disables the Console insight (this) feature.\n */\n disableFeature: 'Disable this feature',\n /**\n * @description The title of the button that goes to the next page.\n */\n next: 'Next',\n /**\n * @description The title of the button that goes back to the previous page.\n */\n back: 'Back',\n /**\n * @description The title of the button that lets the user to continue\n * with using the feature.\n */\n continue: 'Continue',\n /**\n * @description The title of the button that searches for the console\n * insight using a search engine instead of using console insights.\n */\n search: 'Use search instead',\n /**\n * @description Shown to the user when the network request data is not\n * available and a page reload might populate it.\n */\n reloadRecommendation:\n 'Reload the page to capture related network request data for this message in order to create a better insight.',\n /**\n * @description Shown to the user when they need to enable the console insights feature in settings in order to use it.\n * @example {Console insights in Settings} PH1\n */\n turnOnInSettings:\n 'Turn on {PH1} to receive AI assistance for understanding and addressing console warnings and errors.',\n /**\n * @description Text for a link to Chrome DevTools Settings.\n */\n settingsLink: 'Console insights in Settings',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/explain/components/ConsoleInsight.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nconst {render, html, Directives} = LitHtml;\n\nexport class CloseEvent extends Event {\n static readonly eventName = 'close';\n\n constructor() {\n super(CloseEvent.eventName, {composed: true, bubbles: true});\n }\n}\n\ntype PublicPromptBuilder = Pick;\ntype PublicAidaClient = Pick;\n\nfunction localizeType(sourceType: SourceType): string {\n switch (sourceType) {\n case SourceType.MESSAGE:\n return i18nString(UIStrings.consoleMessage);\n case SourceType.STACKTRACE:\n return i18nString(UIStrings.stackTrace);\n case SourceType.NETWORK_REQUEST:\n return i18nString(UIStrings.networkRequest);\n case SourceType.RELATED_CODE:\n return i18nString(UIStrings.relatedCode);\n }\n}\n\nconst TERMS_OF_SERVICE_URL = 'https://policies.google.com/terms';\nconst PRIVACY_POLICY_URL = 'https://policies.google.com/privacy';\nconst CODE_SNIPPET_WARNING_URL = 'https://support.google.com/legal/answer/13505487';\nconst LEARNMORE_URL = 'https://goo.gle/devtools-console-messages-ai' as Platform.DevToolsPath.UrlString;\nconst REPORT_URL = 'https://support.google.com/legal/troubleshooter/1114905?hl=en#ts=1115658%2C13380504' as\n Platform.DevToolsPath.UrlString;\nconst CHROME_SETTINGS_URL = 'chrome://settings' as Platform.DevToolsPath.UrlString;\n\nconst enum State {\n INSIGHT = 'insight',\n LOADING = 'loading',\n ERROR = 'error',\n CONSENT_ONBOARDING = 'consent-onboarding',\n CONSENT_REMINDER = 'consent-reminder',\n NOT_LOGGED_IN = 'not-logged-in',\n SYNC_IS_OFF = 'sync-is-off',\n OFFLINE = 'offline',\n}\n\nconst enum ConsentOnboardingPage {\n PAGE1 = 'private',\n PAGE2 = 'legal',\n}\n\ntype StateData = {\n type: State.LOADING,\n consentOnboardingFinished: boolean,\n consentReminderConfirmed: boolean,\n}|{\n type: State.INSIGHT,\n tokens: MarkdownView.MarkdownView.MarkdownViewData['tokens'],\n validMarkdown: boolean,\n sources: Source[],\n isPageReloadRecommended: boolean,\n completed: boolean,\n}&Host.AidaClient.AidaResponse|{\n type: State.ERROR,\n error: string,\n}|{\n type: State.CONSENT_REMINDER,\n sources: Source[],\n isPageReloadRecommended: boolean,\n}|{\n type: State.CONSENT_ONBOARDING,\n page: ConsentOnboardingPage,\n}|{\n type: State.NOT_LOGGED_IN,\n}|{\n type: State.SYNC_IS_OFF,\n}|{\n type: State.OFFLINE,\n};\n\nexport class ConsoleInsight extends HTMLElement {\n static async create(promptBuilder: PublicPromptBuilder, aidaClient: PublicAidaClient): Promise {\n const aidaAvailability = await Host.AidaClient.AidaClient.checkAccessPreconditions();\n return new ConsoleInsight(promptBuilder, aidaClient, aidaAvailability);\n }\n\n static readonly litTagName = LitHtml.literal`devtools-console-insight`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n\n #promptBuilder: PublicPromptBuilder;\n #aidaClient: PublicAidaClient;\n #renderer = new MarkdownView.MarkdownView.MarkdownInsightRenderer();\n\n // Main state.\n #state: StateData;\n\n // Rating sub-form state.\n #selectedRating?: boolean;\n\n #consoleInsightsEnabledSetting: Common.Settings.Setting|undefined;\n\n constructor(\n promptBuilder: PublicPromptBuilder, aidaClient: PublicAidaClient,\n aidaAvailability: Host.AidaClient.AidaAccessPreconditions) {\n super();\n this.#promptBuilder = promptBuilder;\n this.#aidaClient = aidaClient;\n this.#consoleInsightsEnabledSetting = this.#getConsoleInsightsEnabledSetting();\n\n switch (aidaAvailability) {\n case Host.AidaClient.AidaAccessPreconditions.AVAILABLE:\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n if (this.#consoleInsightsEnabledSetting?.disabled()) {\n this.#state = {\n type: State.CONSENT_ONBOARDING,\n page: ConsentOnboardingPage.PAGE1,\n };\n break;\n }\n // Allows skipping the consent reminder if the user enabled the feature via settings in the current session\n const skipReminder =\n Common.Settings.Settings.instance()\n .createSetting('console-insights-skip-reminder', false, Common.Settings.SettingStorageType.SESSION)\n .get();\n this.#state = {\n type: State.LOADING,\n consentReminderConfirmed: this.#getOnboardingCompletedSetting().get() || skipReminder,\n consentOnboardingFinished: this.#consoleInsightsEnabledSetting?.getIfNotDisabled() === true,\n };\n } else {\n this.#state = {\n type: State.LOADING,\n consentReminderConfirmed: false,\n consentOnboardingFinished: this.#getOnboardingCompletedSetting().get(),\n };\n }\n break;\n case Host.AidaClient.AidaAccessPreconditions.NO_ACCOUNT_EMAIL:\n this.#state = {\n type: State.NOT_LOGGED_IN,\n };\n break;\n case Host.AidaClient.AidaAccessPreconditions.NO_ACTIVE_SYNC:\n this.#state = {\n type: State.SYNC_IS_OFF,\n };\n break;\n case Host.AidaClient.AidaAccessPreconditions.NO_INTERNET:\n this.#state = {\n type: State.OFFLINE,\n };\n break;\n }\n\n this.#render();\n // Stop keyboard event propagation to avoid Console acting on the events\n // inside the insight component.\n this.addEventListener('keydown', e => {\n e.stopPropagation();\n });\n this.addEventListener('keyup', e => {\n e.stopPropagation();\n });\n this.addEventListener('keypress', e => {\n e.stopPropagation();\n });\n this.addEventListener('click', e => {\n e.stopPropagation();\n });\n this.focus();\n }\n\n // The 'console-insights-enabled'-setting controls different things, depending on the 'gen-ai-settings-panel' experiment.\n // experiment off:\n // setting off -> no entrypoints for console insights shown\n // setting on -> entrypoints are shown\n // experiment on:\n // setting off -> entrypoints are shown, and point to the AI setting panel where the setting can be turned on\n // setting on -> entrypoints are shown, and lead to directly generating a console insight\n #getConsoleInsightsEnabledSetting(): Common.Settings.Setting|undefined {\n try {\n return Common.Settings.moduleSetting('console-insights-enabled') as Common.Settings.Setting;\n } catch {\n return;\n }\n }\n\n // The 'console-insights-onboarding-finished'-setting controls different things, depending on the 'gen-ai-settings-panel' experiment.\n // experiment off:\n // setting off -> 2-page onboarding disclaimer is shown before generating a console insight\n // setting on -> no onboarding disclaimer\n // experiment on:\n // setting off -> single page consent reminder is shown, unless the 'console-insights-enabled'-setting has been enabled in the current DevTools session\n // setting on -> no consent reminder shown\n #getOnboardingCompletedSetting(): Common.Settings.Setting {\n return Common.Settings.Settings.instance().createLocalSetting('console-insights-onboarding-finished', false);\n }\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [styles, Input.checkboxStyles];\n this.classList.add('opening');\n this.#consoleInsightsEnabledSetting?.addChangeListener(this.#onConsoleInsightsSettingChanged, this);\n if (this.#state.type === State.LOADING && this.#state.consentOnboardingFinished &&\n this.#state.consentReminderConfirmed) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.GeneratingInsightWithoutDisclaimer);\n }\n void this.#generateInsightIfNeeded();\n }\n\n disconnectedCallback(): void {\n this.#consoleInsightsEnabledSetting?.removeChangeListener(this.#onConsoleInsightsSettingChanged, this);\n }\n\n #onConsoleInsightsSettingChanged(): void {\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n if (this.#consoleInsightsEnabledSetting?.getIfNotDisabled() === true) {\n this.#getOnboardingCompletedSetting().set(true);\n }\n if (this.#state.type === State.CONSENT_ONBOARDING &&\n this.#consoleInsightsEnabledSetting?.getIfNotDisabled() === true) {\n this.#transitionTo({\n type: State.LOADING,\n consentReminderConfirmed: true,\n consentOnboardingFinished: true,\n });\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsOptInTeaserConfirmedInSettings);\n void this.#generateInsightIfNeeded();\n }\n if (this.#state.type === State.CONSENT_REMINDER &&\n this.#consoleInsightsEnabledSetting?.getIfNotDisabled() === false) {\n this.#transitionTo({\n type: State.LOADING,\n consentReminderConfirmed: false,\n consentOnboardingFinished: false,\n });\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsReminderTeaserAbortedInSettings);\n void this.#generateInsightIfNeeded();\n }\n }\n }\n\n #transitionTo(newState: StateData): void {\n const previousState = this.#state;\n this.#state = newState;\n this.#render();\n if (newState.type !== previousState.type) {\n this.#focusHeader();\n }\n }\n\n async #generateInsightIfNeeded(): Promise {\n if (this.#state.type !== State.LOADING) {\n return;\n }\n if (!this.#state.consentOnboardingFinished) {\n this.#transitionTo({\n type: State.CONSENT_ONBOARDING,\n page: ConsentOnboardingPage.PAGE1,\n });\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsOptInTeaserShown);\n } else {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsOnboardingShown);\n }\n return;\n }\n if (!this.#state.consentReminderConfirmed) {\n const {sources, isPageReloadRecommended} = await this.#promptBuilder.buildPrompt();\n this.#transitionTo({\n type: State.CONSENT_REMINDER,\n sources,\n isPageReloadRecommended,\n });\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsReminderTeaserShown);\n } else {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightConsentReminderShown);\n }\n return;\n }\n await this.#generateInsight();\n }\n\n #onClose(): void {\n if (this.#state.type === State.CONSENT_REMINDER) {\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsReminderTeaserCanceled);\n } else {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightConsentReminderCanceled);\n }\n } else if (this.#state.type === State.CONSENT_ONBOARDING) {\n if (this.#state.page === ConsentOnboardingPage.PAGE1) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsOnboardingCanceledOnPage1);\n } else {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsOnboardingCanceledOnPage2);\n }\n }\n this.shadowRoot?.addEventListener('animationend', () => {\n this.dispatchEvent(new CloseEvent());\n }, {once: true});\n this.classList.add('closing');\n }\n\n #onRating(event: Event): void {\n if (this.#state.type !== State.INSIGHT) {\n throw new Error('Unexpected state');\n }\n if (this.#state.metadata?.rpcGlobalId === undefined) {\n throw new Error('RPC Id not in metadata');\n }\n // If it was rated, do not record again.\n if (this.#selectedRating !== undefined) {\n return;\n }\n\n this.#selectedRating = (event.target as HTMLElement).dataset.rating === 'true';\n this.#render();\n if (this.#selectedRating) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightRatedPositive);\n } else {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightRatedNegative);\n }\n const disallowLogging =\n Common.Settings.Settings.instance().getHostConfig().aidaAvailability?.disallowLogging ?? true;\n void this.#aidaClient.registerClientEvent({\n corresponding_aida_rpc_global_id: this.#state.metadata.rpcGlobalId,\n disable_user_content_logging: disallowLogging,\n do_conversation_client_event: {\n user_feedback: {\n sentiment: this.#selectedRating ? Host.AidaClient.Rating.POSITIVE : Host.AidaClient.Rating.NEGATIVE,\n },\n },\n });\n }\n\n #onReport(): void {\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(REPORT_URL);\n }\n\n #onSearch(): void {\n const query = this.#promptBuilder.getSearchQuery();\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.openSearchResultsInNewTab(query);\n }\n\n async #onConsentReminderConfirmed(): Promise {\n this.#getOnboardingCompletedSetting().set(true);\n this.#transitionTo({\n type: State.LOADING,\n consentReminderConfirmed: true,\n consentOnboardingFinished: true,\n });\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsReminderTeaserConfirmed);\n } else {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightConsentReminderConfirmed);\n }\n await this.#generateInsight();\n }\n\n async #generateInsight(): Promise {\n try {\n for await (const {sources, isPageReloadRecommended, explanation, metadata, completed} of this.#getInsight()) {\n const tokens = this.#validateMarkdown(explanation);\n const valid = tokens !== false;\n this.#transitionTo({\n type: State.INSIGHT,\n tokens: valid ? tokens : [],\n validMarkdown: valid,\n explanation,\n sources,\n metadata,\n isPageReloadRecommended,\n completed,\n });\n }\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightGenerated);\n } catch (err) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightErrored);\n this.#transitionTo({\n type: State.ERROR,\n error: err.message,\n });\n }\n }\n\n /**\n * Validates the markdown by trying to render it.\n */\n #validateMarkdown(text: string): Marked.Marked.TokensList|false {\n try {\n const tokens = Marked.Marked.lexer(text);\n for (const token of tokens) {\n this.#renderer.renderToken(token);\n }\n return tokens;\n } catch {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightErroredMarkdown);\n return false;\n }\n }\n\n async *\n #getInsight(): AsyncGenerator<\n {sources: Source[], isPageReloadRecommended: boolean}&Host.AidaClient.AidaResponse, void, void> {\n const {prompt, sources, isPageReloadRecommended} = await this.#promptBuilder.buildPrompt();\n try {\n for await (\n const response of this.#aidaClient.fetch(Host.AidaClient.AidaClient.buildConsoleInsightsRequest(prompt))) {\n yield {sources, isPageReloadRecommended, ...response};\n }\n } catch (err) {\n if (err.message === 'Server responded: permission denied') {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightErroredPermissionDenied);\n } else if (err.message.startsWith('Cannot send request:')) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightErroredCannotSend);\n } else if (err.message.startsWith('Request failed:')) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightErroredRequestFailed);\n } else if (err.message.startsWith('Cannot parse chunk:')) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightErroredCannotParseChunk);\n } else if (err.message === 'Unknown chunk result') {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightErroredUnknownChunk);\n } else if (err.message.startsWith('Server responded:')) {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightErroredApi);\n } else {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightErroredOther);\n }\n throw err;\n }\n }\n\n #onGoToSettings(): void {\n const rootTarget = SDK.TargetManager.TargetManager.instance().rootTarget();\n if (rootTarget === null) {\n return;\n }\n const url = CHROME_SETTINGS_URL;\n void rootTarget.targetAgent().invoke_createTarget({url}).then(result => {\n if (result.getError()) {\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(url);\n }\n });\n }\n\n #onDisableFeature(): void {\n this.#consoleInsightsEnabledSetting?.set(false);\n this.#onClose();\n UI.InspectorView.InspectorView.instance().displayReloadRequiredWarning('Reload for the change to apply.');\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsOnboardingFeatureDisabled);\n }\n\n #goToNextPage(): void {\n this.#transitionTo({\n type: State.CONSENT_ONBOARDING,\n page: ConsentOnboardingPage.PAGE2,\n });\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsOnboardingNextPage);\n }\n\n #focusHeader(): void {\n this.addEventListener('animationend', () => {\n (this.#shadow.querySelector('header h2') as HTMLElement | undefined)?.focus();\n }, {once: true});\n }\n\n #termsChecked(): boolean {\n const checkbox = this.#shadow.querySelector('.terms') as HTMLInputElement | undefined;\n if (!checkbox?.checked) {\n return false;\n }\n return true;\n }\n\n #onConsentOnboardingConfirmed(): void {\n if (!this.#termsChecked()) {\n return;\n }\n this.#getOnboardingCompletedSetting().set(true);\n this.#transitionTo({\n type: State.LOADING,\n consentReminderConfirmed: false,\n consentOnboardingFinished: this.#getOnboardingCompletedSetting().get(),\n });\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsOnboardingConfirmed);\n void this.#generateInsightIfNeeded();\n }\n\n #goToPrevPage(): void {\n this.#transitionTo({\n type: State.CONSENT_ONBOARDING,\n page: ConsentOnboardingPage.PAGE1,\n });\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsOnboardingPrevPage);\n }\n\n #renderCancelButton(): LitHtml.TemplateResult {\n // clang-format off\n return html`<${Buttons.Button.Button.litTagName}\n class=\"cancel-button\"\n @click=${this.#onClose}\n .data=${\n {\n variant: Buttons.Button.Variant.OUTLINED,\n jslogContext: 'cancel',\n } as Buttons.Button.ButtonData\n }\n >\n ${i18nString(UIStrings.cancel)}\n `;\n // clang-format on\n }\n\n #renderDisableFeatureButton(): LitHtml.TemplateResult {\n // clang-format off\n return html`<${Buttons.Button.Button.litTagName}\n @click=${this.#onDisableFeature}\n class=\"disable-button\"\n .data=${\n {\n variant: Buttons.Button.Variant.OUTLINED,\n jslogContext: 'disable',\n } as Buttons.Button.ButtonData\n }\n >\n ${i18nString(UIStrings.disableFeature)}\n `;\n // clang-format on\n }\n\n #renderNextButton(): LitHtml.TemplateResult {\n // clang-format off\n return html`<${Buttons.Button.Button.litTagName}\n class=\"next-button\"\n @click=${this.#goToNextPage}\n .data=${\n {\n variant: Buttons.Button.Variant.PRIMARY,\n jslogContext: 'next',\n } as Buttons.Button.ButtonData\n }\n >\n ${i18nString(UIStrings.next)}\n `;\n // clang-format on\n }\n\n #renderBackButton(): LitHtml.TemplateResult {\n // clang-format off\n return html`<${Buttons.Button.Button.litTagName}\n @click=${this.#goToPrevPage}\n .data=${\n {\n variant: Buttons.Button.Variant.OUTLINED,\n jslogContext: 'back',\n } as Buttons.Button.ButtonData\n }\n >\n ${i18nString(UIStrings.back)}\n `;\n // clang-format on\n }\n\n #renderContinueButton(handler: (event: Event) => void, disabled = false): LitHtml.TemplateResult {\n // clang-format off\n return html`<${Buttons.Button.Button.litTagName}\n @click=${handler}\n class=\"continue-button\"\n .data=${\n {\n variant: Buttons.Button.Variant.PRIMARY,\n disabled,\n jslogContext: 'continue',\n } as Buttons.Button.ButtonData\n }\n >\n ${i18nString(UIStrings.continue)}\n `;\n // clang-format on\n }\n\n #renderSearchButton(): LitHtml.TemplateResult {\n // clang-format off\n return html`<${Buttons.Button.Button.litTagName}\n @click=${this.#onSearch}\n class=\"search-button\"\n .data=${\n {\n variant: Buttons.Button.Variant.OUTLINED,\n jslogContext: 'search',\n } as Buttons.Button.ButtonData\n }\n >\n ${i18nString(UIStrings.search)}\n `;\n // clang-format on\n }\n\n #renderLearnMoreAboutInsights(): LitHtml.TemplateResult {\n // clang-format off\n return html`\n ${i18nString(UIStrings.learnMore)}\n `;\n // clang-format on\n }\n\n #onTermsChange(): void {\n this.#render();\n }\n\n #renderMain(): LitHtml.TemplateResult {\n const jslog = `${VisualLogging.section(this.#state.type).track({resize: true})}`;\n const disallowLogging =\n Common.Settings.Settings.instance().getHostConfig().aidaAvailability?.disallowLogging ?? true;\n // clang-format off\n switch (this.#state.type) {\n case State.LOADING:\n return html`
\n
\n \n \n \n \n \n \n \n
\n
`;\n case State.INSIGHT:\n return html`\n
\n ${\n this.#state.validMarkdown ? html`<${MarkdownView.MarkdownView.MarkdownView.litTagName}\n .data=${{tokens: this.#state.tokens, renderer: this.#renderer} as MarkdownView.MarkdownView.MarkdownViewData}>\n `: this.#state.explanation\n }\n
\n ${i18nString(UIStrings.inputData)}\n <${ConsoleInsightSourcesList.litTagName} .sources=${this.#state.sources} .isPageReloadRecommended=${this.#state.isPageReloadRecommended}>\n \n
\n
\n ${this.#renderSearchButton()}\n
\n
`;\n case State.ERROR:\n return html`\n
\n
${i18nString(UIStrings.errorBody)}
\n
`;\n case State.CONSENT_REMINDER:\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n return html`\n
\n

Things to consider

\n
\n
\n <${IconButton.Icon.Icon.litTagName} .data=${{\n iconName: 'google',\n width: 'var(--sys-size-8)',\n height: 'var(--sys-size-8)',\n } as IconButton.Icon.IconData}>\n \n
\n
The console message, associated stack trace, related source code, and the associated network headers are sent to Google to generate explanations. This data may be seen by human reviewers to improve this feature. Avoid sharing sensitive or personal information.
\n
\n <${IconButton.Icon.Icon.litTagName} .data=${{\n iconName: 'policy',\n width: 'var(--sys-size-8)',\n height: 'var(--sys-size-8)',\n } as IconButton.Icon.IconData}>\n \n
\n
Use of this feature is subject to the\n Google Terms of Service\n and\n Google Privacy Policy\n
\n
\n <${IconButton.Icon.Icon.litTagName} .data=${{\n iconName: 'warning',\n width: 'var(--sys-size-8)',\n height: 'var(--sys-size-8)',\n } as IconButton.Icon.IconData}>\n \n
\n
\n Use generated code snippets with caution\n
\n
\n
\n `;\n }\n return html`\n
\n

The following data will be sent to Google to understand the context for the console message.\n ${disallowLogging ? '' : 'Human reviewers may process this information for quality purposes. Don’t submit sensitive information.'}\n Read Google’s Terms of Service.

\n <${ConsoleInsightSourcesList.litTagName} .sources=${this.#state.sources} .isPageReloadRecommended=${this.#state.isPageReloadRecommended}>\n \n
\n `;\n case State.CONSENT_ONBOARDING: {\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n const settingsLink = document.createElement('button');\n settingsLink.textContent = i18nString(UIStrings.settingsLink);\n settingsLink.classList.add('link');\n UI.ARIAUtils.markAsLink(settingsLink);\n settingsLink.addEventListener('click', () => {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsOptInTeaserSettingsLinkClicked);\n void UI.ViewManager.ViewManager.instance().showView('chrome-ai');\n });\n settingsLink.setAttribute('jslog', `${VisualLogging.action('open-ai-settings').track({click: true})}`);\n\n return html`
\n
\n <${IconButton.Icon.Icon.litTagName} .data=${{\n iconName: 'lightbulb-spark',\n width: 'var(--sys-size-8)',\n height: 'var(--sys-size-8)',\n } as IconButton.Icon.IconData}>\n \n
\n
\n ${i18n.i18n.getFormatLocalizedString(str_, UIStrings.turnOnInSettings, {PH1: settingsLink})}\n ${this.#renderLearnMoreAboutInsights()}\n
\n
`;\n }\n switch (this.#state.page) {\n case ConsentOnboardingPage.PAGE1:\n return html`
\n

This notice and our privacy notice describe how Chrome DevTools handles your data. Please read them carefully.

\n\n

Chrome DevTools uses the console message, associated stack trace, related source code, and the associated network headers as input data. When you use \"Understand this message\", Google collects this input data, generated output, related feature usage information, and your feedback. Google uses this data to provide, improve, and develop Google products and services and machine learning technologies, including Google's enterprise products such as Google Cloud.

\n\n

To help with quality and improve our products, human reviewers may read, annotate, and process the above-mentioned input data, generated output, related feature usage information, and your feedback. Please do not include sensitive (e.g., confidential) or personal information that can be used to identify you or others in your prompts or feedback. Your data will be stored in a way where Google cannot tell who provided it and can no longer fulfill any deletion requests and will be retained for up to 18 months. We may refrain from collecting data to improve our product if your Google account is managed by an organization and depending on your region.

\n
`;\n case ConsentOnboardingPage.PAGE2:\n return html`
\n

As you try \"Understand this message\", here are key things to know:\n\n

    \n
  • Chrome DevTools uses console message, associated stack trace, related source code, and the associated network headers to provide answers.
  • \n
  • Chrome DevTools uses experimental technology, and may generate inaccurate or offensive information that doesn't represent Google's views. Voting on the responses will help make this feature better.
  • \n
  • This feature is an experimental feature and subject to future changes.
  • \n
  • Use generated code snippets with caution.
  • \n
\n

\n\n

\n \n

\n
`;\n }\n }\n case State.NOT_LOGGED_IN:\n return html`\n
\n
${i18nString(UIStrings.notLoggedIn)}
\n
`;\n case State.SYNC_IS_OFF:\n return html`\n
\n
${i18nString(UIStrings.syncIsOff)}
\n
`;\n case State.OFFLINE:\n return html`\n
\n
${i18nString(UIStrings.offline)}
\n
`;\n }\n // clang-format on\n }\n\n #renderDisclaimer(): LitHtml.LitTemplate {\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n // clang-format off\n return LitHtml.html`\n Chrome AI may generate inaccurate info that does not represent Google's views. Data sent to Google may be seen by human reviewers to improve this feature.\n \n or\n learn more\n `;\n }\n return LitHtml.html`\n This feature may display inaccurate or offensive information that doesn't represent Google's views.\n ${i18nString(UIStrings.learnMore)}\n `;\n // clang-format on\n }\n\n #renderFooter(): LitHtml.LitTemplate {\n const showThumbsUpDownButtons =\n !(Common.Settings.Settings.instance().getHostConfig().aidaAvailability?.disallowLogging ?? true);\n const disclaimer = this.#renderDisclaimer();\n // clang-format off\n switch (this.#state.type) {\n case State.LOADING:\n return LitHtml.nothing;\n case State.ERROR:\n case State.OFFLINE:\n return html`
\n
\n ${disclaimer}\n
\n
`;\n case State.NOT_LOGGED_IN:\n case State.SYNC_IS_OFF:\n return html`
\n
\n
\n <${Buttons.Button.Button.litTagName}\n @click=${this.#onGoToSettings}\n .data=${\n {\n variant: Buttons.Button.Variant.PRIMARY,\n jslogContext: 'update-settings',\n } as Buttons.Button.ButtonData\n }\n >\n ${UIStrings.updateSettings}\n \n
\n
`;\n case State.CONSENT_REMINDER:\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n return html`
\n
\n
\n <${Buttons.Button.Button.litTagName}\n @click=${() => {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.InsightsReminderTeaserSettingsLinkClicked);\n void UI.ViewManager.ViewManager.instance().showView('chrome-ai');\n }}\n .data=${\n {\n variant: Buttons.Button.Variant.TONAL,\n jslogContext: 'settings',\n title: 'Settings',\n } as Buttons.Button.ButtonData\n }\n >\n Settings\n \n <${Buttons.Button.Button.litTagName}\n class='continue-button'\n @click=${this.#onConsentReminderConfirmed}\n .data=${\n {\n variant: Buttons.Button.Variant.PRIMARY,\n jslogContext: 'continue',\n title: 'continue',\n } as Buttons.Button.ButtonData\n }\n >\n Continue\n \n
\n
`;\n }\n return html`
\n
\n ${disclaimer}\n
\n
\n
\n ${this.#renderCancelButton()}\n ${this.#renderContinueButton(this.#onConsentReminderConfirmed)}\n
\n
`;\n case State.CONSENT_ONBOARDING:\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n return LitHtml.nothing;\n }\n switch (this.#state.page) {\n case ConsentOnboardingPage.PAGE1:\n return html`
\n
\n ${this.#renderLearnMoreAboutInsights()}\n
\n
\n
\n ${this.#renderCancelButton()}\n ${this.#renderDisableFeatureButton()}\n ${this.#renderNextButton()}\n
\n
`;\n case ConsentOnboardingPage.PAGE2:\n return html`
\n
\n ${this.#renderLearnMoreAboutInsights()}\n
\n
\n
\n ${this.#renderBackButton()}\n ${this.#renderDisableFeatureButton()}\n ${this.#renderContinueButton(this.#onConsentOnboardingConfirmed, !this.#termsChecked())}\n
\n
`;\n }\n case State.INSIGHT:\n return html`
\n
\n ${disclaimer}\n
\n
\n
\n ${showThumbsUpDownButtons ? html`\n <${Buttons.Button.Button.litTagName}\n data-rating=${'true'}\n .data=${\n {\n variant: Buttons.Button.Variant.ICON,\n size: Buttons.Button.Size.SMALL,\n iconName: 'thumb-up',\n active: this.#selectedRating !== undefined && this.#selectedRating,\n title: i18nString(UIStrings.goodResponse),\n jslogContext: 'thumbs-up',\n } as Buttons.Button.ButtonData\n }\n @click=${this.#onRating}\n >\n <${Buttons.Button.Button.litTagName}\n data-rating=${'false'}\n .data=${\n {\n variant: Buttons.Button.Variant.ICON,\n size: Buttons.Button.Size.SMALL,\n iconName: 'thumb-down',\n active: this.#selectedRating !== undefined && !this.#selectedRating,\n title: i18nString(UIStrings.badResponse),\n jslogContext: 'thumbs-down',\n } as Buttons.Button.ButtonData\n }\n @click=${this.#onRating}\n >\n ` : LitHtml.nothing}\n <${Buttons.Button.Button.litTagName}\n .data=${\n {\n variant: Buttons.Button.Variant.ICON,\n size: Buttons.Button.Size.SMALL,\n iconName: 'report',\n title: i18nString(UIStrings.report),\n jslogContext: 'report',\n } as Buttons.Button.ButtonData\n }\n @click=${this.#onReport}\n >\n
\n\n
`;\n }\n // clang-format on\n }\n\n #getHeader(): string {\n switch (this.#state.type) {\n case State.NOT_LOGGED_IN:\n return i18nString(UIStrings.signInToUse);\n case State.SYNC_IS_OFF:\n return i18nString(UIStrings.notAvailable);\n case State.OFFLINE:\n return i18nString(UIStrings.offlineHeader);\n case State.LOADING:\n return i18nString(UIStrings.generating);\n case State.INSIGHT:\n return i18nString(UIStrings.insight);\n case State.ERROR:\n return i18nString(UIStrings.error);\n case State.CONSENT_REMINDER:\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n return 'Understand console messages with Chrome AI';\n }\n return i18nString(UIStrings.inputData);\n case State.CONSENT_ONBOARDING:\n switch (this.#state.page) {\n case ConsentOnboardingPage.PAGE1:\n return 'Privacy notice';\n case ConsentOnboardingPage.PAGE2:\n return 'Legal notice';\n }\n }\n }\n\n #renderSpinner(): LitHtml.LitTemplate {\n // clang-format off\n if (this.#state.type === State.INSIGHT && !this.#state.completed) {\n return html`<${Spinners.Spinner.Spinner.litTagName}>`;\n }\n return LitHtml.nothing;\n // clang-format on\n }\n\n #renderHeader(): LitHtml.LitTemplate {\n if (this.#state.type === State.CONSENT_ONBOARDING &&\n Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n return LitHtml.nothing;\n }\n const hasIcon = Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL) &&\n this.#state.type === State.CONSENT_REMINDER;\n // clang-format off\n return html`\n
\n ${hasIcon ? html`\n
\n <${IconButton.Icon.Icon.litTagName} .data=${{\n iconName: 'lightbulb-spark',\n width: '18px',\n height: '18px',\n } as IconButton.Icon.IconData}>\n \n
`\n : LitHtml.nothing}\n
\n

\n ${this.#getHeader()}\n

\n ${this.#renderSpinner()}\n
\n
\n <${Buttons.Button.Button.litTagName}\n .data=${\n {\n variant: Buttons.Button.Variant.ICON,\n size: Buttons.Button.Size.SMALL,\n iconName: 'cross',\n title: i18nString(UIStrings.closeInsight),\n } as Buttons.Button.ButtonData\n }\n jslog=${VisualLogging.close().track({click: true})}\n @click=${this.#onClose}\n >\n
\n
\n `;\n // clang-format on\n }\n\n #render(): void {\n // clang-format off\n render(html`\n
\n
\n ${this.#renderHeader()}\n ${this.#renderMain()}\n ${this.#renderFooter()}\n
\n
\n `, this.#shadow, {\n host: this,\n });\n // clang-format on\n }\n}\n\nclass ConsoleInsightSourcesList extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-console-insight-sources-list`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n #sources: Source[] = [];\n #isPageReloadRecommended = false;\n\n constructor() {\n super();\n this.#shadow.adoptedStyleSheets = [listStyles, Input.checkboxStyles];\n }\n\n #render(): void {\n // clang-format off\n render(html`\n
    \n ${Directives.repeat(this.#sources, item => item.value, item => {\n return html`
  • \n <${IconButton.Icon.Icon.litTagName} name=\"open-externally\">\n ${localizeType(item.type)}\n
  • `;\n })}\n ${this.#isPageReloadRecommended ? LitHtml.html`
  • \n <${IconButton.Icon.Icon.litTagName} name=\"warning\">\n ${i18nString(UIStrings.reloadRecommendation)}
  • ` : LitHtml.nothing}\n
\n `, this.#shadow, {\n host: this,\n });\n // clang-format on\n }\n\n set sources(values: Source[]) {\n this.#sources = values;\n this.#render();\n }\n\n set isPageReloadRecommended(isPageReloadRecommended: boolean) {\n this.#isPageReloadRecommended = isPageReloadRecommended;\n this.#render();\n }\n}\n\ncustomElements.define('devtools-console-insight', ConsoleInsight);\ncustomElements.define('devtools-console-insight-sources-list', ConsoleInsightSourcesList);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-console-insight': ConsoleInsight;\n 'devtools-console-insight-sources-list': ConsoleInsightSourcesList;\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/explain/components/ConsoleInsight.test.js b/public/panels/explain/components/ConsoleInsight.test.js index 26f2012b1..7ab27581b 100644 --- a/public/panels/explain/components/ConsoleInsight.test.js +++ b/public/panels/explain/components/ConsoleInsight.test.js @@ -98,7 +98,7 @@ describeWithEnvironment('ConsoleInsight', () => { await drainMicroTasks(); assert.isNotNull(component.shadowRoot); assert.strictEqual(component.shadowRoot.querySelector('h2')?.innerText, 'Understand console messages with Chrome AI'); - dispatchClickEvent(component.shadowRoot.querySelector('.lets-go-button'), { + dispatchClickEvent(component.shadowRoot.querySelector('.continue-button'), { bubbles: true, composed: true, }); diff --git a/public/panels/explain/components/ConsoleInsight.test.js.map b/public/panels/explain/components/ConsoleInsight.test.js.map index d15ed46fd..f00e48887 100644 --- a/public/panels/explain/components/ConsoleInsight.test.js.map +++ b/public/panels/explain/components/ConsoleInsight.test.js.map @@ -1 +1 @@ -{"version":3,"file":"ConsoleInsight.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/explain/components/ConsoleInsight.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../../core/common/common.js';\nimport * as Host from '../../../core/host/host.js';\nimport * as Root from '../../../core/root/root.js';\nimport {\n dispatchClickEvent,\n getCleanTextContentFromElements,\n renderElementIntoDOM,\n} from '../../../testing/DOMHelpers.js';\nimport {describeWithEnvironment, getGetHostConfigStub} from '../../../testing/EnvironmentHelpers.js';\nimport * as Explain from '../explain.js';\n\ndescribeWithEnvironment('ConsoleInsight', () => {\n function getTestAidaClient() {\n return {\n async *\n fetch() {\n yield {explanation: 'test', metadata: {rpcGlobalId: 0}, completed: true};\n },\n registerClientEvent: sinon.spy(),\n };\n }\n\n function getTestPromptBuilder() {\n return {\n async buildPrompt() {\n return {\n prompt: '',\n sources: [\n {\n type: Explain.SourceType.MESSAGE,\n value: 'error message',\n },\n ],\n isPageReloadRecommended: true,\n };\n },\n getSearchQuery() {\n return '';\n },\n };\n }\n\n async function drainMicroTasks() {\n await new Promise(resolve => setTimeout(resolve, 0));\n }\n\n function skipConsentOnboarding() {\n beforeEach(() => {\n Common.Settings.settingForTest('console-insights-onboarding-finished').set(true);\n });\n\n afterEach(() => {\n Common.Settings.settingForTest('console-insights-onboarding-finished').set(false);\n });\n }\n\n describe('new consent onboarding', () => {\n before(() => {\n Root.Runtime.experiments.enableForTest(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL);\n });\n\n after(() => {\n Root.Runtime.experiments.disableForTest(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL);\n Common.Settings.settingForTest('console-insights-enabled').set(false);\n Common.Settings.settingForTest('console-insights-onboarding-finished').set(false);\n });\n\n it('shows opt-in teaser when setting is disabled', async () => {\n Common.Settings.settingForTest('console-insights-enabled').set(false);\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n assert.isNotNull(component.shadowRoot);\n assert.deepEqual(\n getCleanTextContentFromElements(component.shadowRoot, 'main'),\n [\n 'Turn on Console insights in Settings to receive AI assistance for understanding and addressing console warnings and errors. Learn more',\n ],\n );\n });\n\n it('shows opt-in teaser when setting is disabled via disabledCondition', async () => {\n Common.Settings.settingForTest('console-insights-onboarding-finished').set(true);\n const setting = Common.Settings.settingForTest('console-insights-enabled');\n setting.set(true);\n setting.setRegistration({\n settingName: 'console-insights-enabled',\n settingType: Common.Settings.SettingType.BOOLEAN,\n defaultValue: true,\n disabledCondition: () => {\n return {disabled: true, reason: 'disabled for test'};\n },\n });\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n assert.isNotNull(component.shadowRoot);\n assert.deepEqual(\n getCleanTextContentFromElements(component.shadowRoot, 'main'),\n [\n 'Turn on Console insights in Settings to receive AI assistance for understanding and addressing console warnings and errors. Learn more',\n ],\n );\n\n setting.setRegistration({\n settingName: 'console-insights-enabled',\n settingType: Common.Settings.SettingType.BOOLEAN,\n defaultValue: false,\n });\n });\n\n it('shows reminder on first run of console insights', async () => {\n Common.Settings.settingForTest('console-insights-enabled').set(true);\n Common.Settings.settingForTest('console-insights-onboarding-finished').set(false);\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n assert.isNotNull(component.shadowRoot);\n assert.strictEqual(\n component.shadowRoot!.querySelector('h2')?.innerText, 'Understand console messages with Chrome AI');\n\n dispatchClickEvent(component.shadowRoot!.querySelector('.lets-go-button')!, {\n bubbles: true,\n composed: true,\n });\n await drainMicroTasks();\n // Rating buttons are shown.\n assert(component.shadowRoot!.querySelector('.rating'));\n });\n\n it('immediately renders insight on subsequent runs', async () => {\n Common.Settings.settingForTest('console-insights-enabled').set(true);\n Common.Settings.settingForTest('console-insights-onboarding-finished').set(true);\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n assert.isNotNull(component.shadowRoot);\n // Rating buttons are shown.\n assert(component.shadowRoot!.querySelector('.rating'));\n });\n });\n\n describe('consent onboarding', () => {\n afterEach(() => {\n Common.Settings.settingForTest('console-insights-onboarding-finished').set(false);\n });\n\n it('should show privacy notice first', async () => {\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n assert.strictEqual(component.shadowRoot!.querySelector('h2')?.innerText, 'Privacy notice');\n });\n\n it('should show legal notice second', async () => {\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n dispatchClickEvent(component.shadowRoot!.querySelector('.next-button')!);\n await drainMicroTasks();\n assert.strictEqual(component.shadowRoot!.querySelector('h2')?.innerText, 'Legal notice');\n });\n\n it('should not confirm legal notice without checkbox', async () => {\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n dispatchClickEvent(component.shadowRoot!.querySelector('.next-button')!);\n await drainMicroTasks();\n dispatchClickEvent(component.shadowRoot!.querySelector('.continue-button')!);\n await drainMicroTasks();\n assert.strictEqual(component.shadowRoot!.querySelector('h2')?.innerText, 'Legal notice');\n });\n\n it('should confirm legal notice if checkbox is pressed', async () => {\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n dispatchClickEvent(component.shadowRoot!.querySelector('.next-button')!);\n await drainMicroTasks();\n dispatchClickEvent(component.shadowRoot!.querySelector('input')!);\n await drainMicroTasks();\n dispatchClickEvent(component.shadowRoot!.querySelector('.continue-button')!);\n await drainMicroTasks();\n assert.strictEqual(component.shadowRoot!.querySelector('h2')?.innerText, 'Data used to understand this message');\n await drainMicroTasks();\n assert.strictEqual(Common.Settings.settingForTest('console-insights-onboarding-finished').get(), true);\n });\n\n it('can cancel the onboarding flow', async () => {\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n dispatchClickEvent(component.shadowRoot!.querySelector('.cancel-button')!);\n await drainMicroTasks();\n assert(component.getAttribute('class')?.includes('closing'));\n });\n\n it('can disable the feature', async () => {\n Common.Settings.settingForTest('console-insights-enabled').set(true);\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n dispatchClickEvent(component.shadowRoot!.querySelector('.disable-button')!);\n await drainMicroTasks();\n assert.strictEqual(Common.Settings.settingForTest('console-insights-enabled').get(), false);\n });\n });\n\n describe('with consent onboarding finished', () => {\n skipConsentOnboarding();\n\n it('shows the consent reminder flow for signed-in users', async () => {\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n assert.strictEqual(component.shadowRoot!.querySelector('h2')?.innerText, 'Data used to understand this message');\n // Continue button is present.\n assert(component.shadowRoot!.querySelector('.continue-button'));\n });\n\n it('consent reminder can be accepted', async () => {\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n dispatchClickEvent(component.shadowRoot!.querySelector('.continue-button')!, {\n bubbles: true,\n composed: true,\n });\n // Expected to be rendered in the next task.\n await new Promise(resolve => setTimeout(resolve, 0));\n // Rating buttons are shown.\n assert(component.shadowRoot!.querySelector('.rating'));\n });\n\n const renderInsight = async(aidaClient = getTestAidaClient()): Promise => {\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), aidaClient, Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n dispatchClickEvent(component.shadowRoot!.querySelector('.continue-button')!, {\n bubbles: true,\n composed: true,\n });\n // Expected to be rendered in the next task.\n await new Promise(resolve => setTimeout(resolve, 0));\n return component;\n };\n\n const reportsRating = (positive: boolean) => async () => {\n const stub = getGetHostConfigStub({});\n const actionTaken = sinon.stub(Host.userMetrics, 'actionTaken');\n const aidaClient = getTestAidaClient();\n const component = await renderInsight(aidaClient);\n dispatchClickEvent(component.shadowRoot!.querySelector(`.rating [data-rating=${positive}]`)!, {\n bubbles: true,\n composed: true,\n });\n\n assert(aidaClient.registerClientEvent.calledOnce);\n sinon.assert.match(aidaClient.registerClientEvent.firstCall.firstArg, sinon.match({\n corresponding_aida_rpc_global_id: 0,\n do_conversation_client_event: {\n user_feedback: {sentiment: positive ? 'POSITIVE' : 'NEGATIVE'},\n },\n }));\n assert(actionTaken.calledWith(\n positive ? Host.UserMetrics.Action.InsightRatedPositive : Host.UserMetrics.Action.InsightRatedNegative));\n\n dispatchClickEvent(component.shadowRoot!.querySelector(`.rating [data-rating=${positive}]`)!, {\n bubbles: true,\n composed: true,\n });\n // Can only rate once.\n assert(aidaClient.registerClientEvent.calledOnce);\n stub.restore();\n };\n\n it('reports positive rating', reportsRating(true));\n it('reports negative rating', reportsRating(false));\n\n it('has no thumbs up/down buttons if logging is disabled', async () => {\n const stub = getGetHostConfigStub({\n aidaAvailability: {\n disallowLogging: true,\n },\n devToolsConsoleInsights: {\n enabled: true,\n },\n });\n const component = await renderInsight();\n const thumbsUpButton = component.shadowRoot!.querySelector('.rating [data-rating=\"true\"]');\n assert.isNull(thumbsUpButton);\n const thumbsDownButton = component.shadowRoot!.querySelector('.rating [data-rating=\"false\"]');\n assert.isNull(thumbsDownButton);\n\n stub.restore();\n });\n });\n\n it('report if the user is not logged in', async () => {\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.NO_ACCOUNT_EMAIL);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n const content = component.shadowRoot!.querySelector('main')!.innerText.trim();\n assert.strictEqual(content, 'This feature is only available when you sign into Chrome with your Google account.');\n });\n\n it('report if the sync is not enabled', async () => {\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.NO_ACTIVE_SYNC);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n const content = component.shadowRoot!.querySelector('main')!.innerText.trim();\n assert.strictEqual(content, 'This feature requires you to turn on Chrome sync.');\n });\n\n it('report if the navigator is offline', async () => {\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.NO_INTERNET);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n const content = component.shadowRoot!.querySelector('main')!.innerText.trim();\n assert.strictEqual(content, 'Check your internet connection and try again.');\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"ConsoleInsight.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/explain/components/ConsoleInsight.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../../core/common/common.js';\nimport * as Host from '../../../core/host/host.js';\nimport * as Root from '../../../core/root/root.js';\nimport {\n dispatchClickEvent,\n getCleanTextContentFromElements,\n renderElementIntoDOM,\n} from '../../../testing/DOMHelpers.js';\nimport {describeWithEnvironment, getGetHostConfigStub} from '../../../testing/EnvironmentHelpers.js';\nimport * as Explain from '../explain.js';\n\ndescribeWithEnvironment('ConsoleInsight', () => {\n function getTestAidaClient() {\n return {\n async *\n fetch() {\n yield {explanation: 'test', metadata: {rpcGlobalId: 0}, completed: true};\n },\n registerClientEvent: sinon.spy(),\n };\n }\n\n function getTestPromptBuilder() {\n return {\n async buildPrompt() {\n return {\n prompt: '',\n sources: [\n {\n type: Explain.SourceType.MESSAGE,\n value: 'error message',\n },\n ],\n isPageReloadRecommended: true,\n };\n },\n getSearchQuery() {\n return '';\n },\n };\n }\n\n async function drainMicroTasks() {\n await new Promise(resolve => setTimeout(resolve, 0));\n }\n\n function skipConsentOnboarding() {\n beforeEach(() => {\n Common.Settings.settingForTest('console-insights-onboarding-finished').set(true);\n });\n\n afterEach(() => {\n Common.Settings.settingForTest('console-insights-onboarding-finished').set(false);\n });\n }\n\n describe('new consent onboarding', () => {\n before(() => {\n Root.Runtime.experiments.enableForTest(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL);\n });\n\n after(() => {\n Root.Runtime.experiments.disableForTest(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL);\n Common.Settings.settingForTest('console-insights-enabled').set(false);\n Common.Settings.settingForTest('console-insights-onboarding-finished').set(false);\n });\n\n it('shows opt-in teaser when setting is disabled', async () => {\n Common.Settings.settingForTest('console-insights-enabled').set(false);\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n assert.isNotNull(component.shadowRoot);\n assert.deepEqual(\n getCleanTextContentFromElements(component.shadowRoot, 'main'),\n [\n 'Turn on Console insights in Settings to receive AI assistance for understanding and addressing console warnings and errors. Learn more',\n ],\n );\n });\n\n it('shows opt-in teaser when setting is disabled via disabledCondition', async () => {\n Common.Settings.settingForTest('console-insights-onboarding-finished').set(true);\n const setting = Common.Settings.settingForTest('console-insights-enabled');\n setting.set(true);\n setting.setRegistration({\n settingName: 'console-insights-enabled',\n settingType: Common.Settings.SettingType.BOOLEAN,\n defaultValue: true,\n disabledCondition: () => {\n return {disabled: true, reason: 'disabled for test'};\n },\n });\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n assert.isNotNull(component.shadowRoot);\n assert.deepEqual(\n getCleanTextContentFromElements(component.shadowRoot, 'main'),\n [\n 'Turn on Console insights in Settings to receive AI assistance for understanding and addressing console warnings and errors. Learn more',\n ],\n );\n\n setting.setRegistration({\n settingName: 'console-insights-enabled',\n settingType: Common.Settings.SettingType.BOOLEAN,\n defaultValue: false,\n });\n });\n\n it('shows reminder on first run of console insights', async () => {\n Common.Settings.settingForTest('console-insights-enabled').set(true);\n Common.Settings.settingForTest('console-insights-onboarding-finished').set(false);\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n assert.isNotNull(component.shadowRoot);\n assert.strictEqual(\n component.shadowRoot!.querySelector('h2')?.innerText, 'Understand console messages with Chrome AI');\n\n dispatchClickEvent(component.shadowRoot!.querySelector('.continue-button')!, {\n bubbles: true,\n composed: true,\n });\n await drainMicroTasks();\n // Rating buttons are shown.\n assert(component.shadowRoot!.querySelector('.rating'));\n });\n\n it('immediately renders insight on subsequent runs', async () => {\n Common.Settings.settingForTest('console-insights-enabled').set(true);\n Common.Settings.settingForTest('console-insights-onboarding-finished').set(true);\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n assert.isNotNull(component.shadowRoot);\n // Rating buttons are shown.\n assert(component.shadowRoot!.querySelector('.rating'));\n });\n });\n\n describe('consent onboarding', () => {\n afterEach(() => {\n Common.Settings.settingForTest('console-insights-onboarding-finished').set(false);\n });\n\n it('should show privacy notice first', async () => {\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n assert.strictEqual(component.shadowRoot!.querySelector('h2')?.innerText, 'Privacy notice');\n });\n\n it('should show legal notice second', async () => {\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n dispatchClickEvent(component.shadowRoot!.querySelector('.next-button')!);\n await drainMicroTasks();\n assert.strictEqual(component.shadowRoot!.querySelector('h2')?.innerText, 'Legal notice');\n });\n\n it('should not confirm legal notice without checkbox', async () => {\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n dispatchClickEvent(component.shadowRoot!.querySelector('.next-button')!);\n await drainMicroTasks();\n dispatchClickEvent(component.shadowRoot!.querySelector('.continue-button')!);\n await drainMicroTasks();\n assert.strictEqual(component.shadowRoot!.querySelector('h2')?.innerText, 'Legal notice');\n });\n\n it('should confirm legal notice if checkbox is pressed', async () => {\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n dispatchClickEvent(component.shadowRoot!.querySelector('.next-button')!);\n await drainMicroTasks();\n dispatchClickEvent(component.shadowRoot!.querySelector('input')!);\n await drainMicroTasks();\n dispatchClickEvent(component.shadowRoot!.querySelector('.continue-button')!);\n await drainMicroTasks();\n assert.strictEqual(component.shadowRoot!.querySelector('h2')?.innerText, 'Data used to understand this message');\n await drainMicroTasks();\n assert.strictEqual(Common.Settings.settingForTest('console-insights-onboarding-finished').get(), true);\n });\n\n it('can cancel the onboarding flow', async () => {\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n dispatchClickEvent(component.shadowRoot!.querySelector('.cancel-button')!);\n await drainMicroTasks();\n assert(component.getAttribute('class')?.includes('closing'));\n });\n\n it('can disable the feature', async () => {\n Common.Settings.settingForTest('console-insights-enabled').set(true);\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n dispatchClickEvent(component.shadowRoot!.querySelector('.disable-button')!);\n await drainMicroTasks();\n assert.strictEqual(Common.Settings.settingForTest('console-insights-enabled').get(), false);\n });\n });\n\n describe('with consent onboarding finished', () => {\n skipConsentOnboarding();\n\n it('shows the consent reminder flow for signed-in users', async () => {\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n assert.strictEqual(component.shadowRoot!.querySelector('h2')?.innerText, 'Data used to understand this message');\n // Continue button is present.\n assert(component.shadowRoot!.querySelector('.continue-button'));\n });\n\n it('consent reminder can be accepted', async () => {\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n dispatchClickEvent(component.shadowRoot!.querySelector('.continue-button')!, {\n bubbles: true,\n composed: true,\n });\n // Expected to be rendered in the next task.\n await new Promise(resolve => setTimeout(resolve, 0));\n // Rating buttons are shown.\n assert(component.shadowRoot!.querySelector('.rating'));\n });\n\n const renderInsight = async(aidaClient = getTestAidaClient()): Promise => {\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), aidaClient, Host.AidaClient.AidaAccessPreconditions.AVAILABLE);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n dispatchClickEvent(component.shadowRoot!.querySelector('.continue-button')!, {\n bubbles: true,\n composed: true,\n });\n // Expected to be rendered in the next task.\n await new Promise(resolve => setTimeout(resolve, 0));\n return component;\n };\n\n const reportsRating = (positive: boolean) => async () => {\n const stub = getGetHostConfigStub({});\n const actionTaken = sinon.stub(Host.userMetrics, 'actionTaken');\n const aidaClient = getTestAidaClient();\n const component = await renderInsight(aidaClient);\n dispatchClickEvent(component.shadowRoot!.querySelector(`.rating [data-rating=${positive}]`)!, {\n bubbles: true,\n composed: true,\n });\n\n assert(aidaClient.registerClientEvent.calledOnce);\n sinon.assert.match(aidaClient.registerClientEvent.firstCall.firstArg, sinon.match({\n corresponding_aida_rpc_global_id: 0,\n do_conversation_client_event: {\n user_feedback: {sentiment: positive ? 'POSITIVE' : 'NEGATIVE'},\n },\n }));\n assert(actionTaken.calledWith(\n positive ? Host.UserMetrics.Action.InsightRatedPositive : Host.UserMetrics.Action.InsightRatedNegative));\n\n dispatchClickEvent(component.shadowRoot!.querySelector(`.rating [data-rating=${positive}]`)!, {\n bubbles: true,\n composed: true,\n });\n // Can only rate once.\n assert(aidaClient.registerClientEvent.calledOnce);\n stub.restore();\n };\n\n it('reports positive rating', reportsRating(true));\n it('reports negative rating', reportsRating(false));\n\n it('has no thumbs up/down buttons if logging is disabled', async () => {\n const stub = getGetHostConfigStub({\n aidaAvailability: {\n disallowLogging: true,\n },\n devToolsConsoleInsights: {\n enabled: true,\n },\n });\n const component = await renderInsight();\n const thumbsUpButton = component.shadowRoot!.querySelector('.rating [data-rating=\"true\"]');\n assert.isNull(thumbsUpButton);\n const thumbsDownButton = component.shadowRoot!.querySelector('.rating [data-rating=\"false\"]');\n assert.isNull(thumbsDownButton);\n\n stub.restore();\n });\n });\n\n it('report if the user is not logged in', async () => {\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.NO_ACCOUNT_EMAIL);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n const content = component.shadowRoot!.querySelector('main')!.innerText.trim();\n assert.strictEqual(content, 'This feature is only available when you sign into Chrome with your Google account.');\n });\n\n it('report if the sync is not enabled', async () => {\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.NO_ACTIVE_SYNC);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n const content = component.shadowRoot!.querySelector('main')!.innerText.trim();\n assert.strictEqual(content, 'This feature requires you to turn on Chrome sync.');\n });\n\n it('report if the navigator is offline', async () => {\n const component = new Explain.ConsoleInsight(\n getTestPromptBuilder(), getTestAidaClient(), Host.AidaClient.AidaAccessPreconditions.NO_INTERNET);\n renderElementIntoDOM(component);\n await drainMicroTasks();\n const content = component.shadowRoot!.querySelector('main')!.innerText.trim();\n assert.strictEqual(content, 'Check your internet connection and try again.');\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/explain/components/consoleInsight.css.js b/public/panels/explain/components/consoleInsight.css.js index 675fa0f9d..4ccd5146b 100644 --- a/public/panels/explain/components/consoleInsight.css.js +++ b/public/panels/explain/components/consoleInsight.css.js @@ -214,10 +214,15 @@ textarea { .buttons { display: flex; - flex-wrap: wrap; gap: 5px; } +@media (max-width: 500px) { + .buttons { + flex-wrap: wrap; + } +} + main .buttons { margin-top: 12px; } @@ -229,7 +234,6 @@ main .buttons { font-size: 11px; align-items: flex-start; flex-direction: column; - max-width: 360px; } .link { diff --git a/public/panels/explain/explain-meta.js b/public/panels/explain/explain-meta.js index 6c5832d63..985b1bbb8 100644 --- a/public/panels/explain/explain-meta.js +++ b/public/panels/explain/explain-meta.js @@ -95,13 +95,13 @@ function isFeatureEnabled(config) { return (config?.aidaAvailability?.enabled && config?.devToolsConsoleInsights?.enabled) === true; } Common.Settings.registerSettingExtension({ - // TODO(crbug.com/350668580) SettingCategory.NONE once experiment GEN_AI_SETTINGS_PANEL is enabled + // TODO(crbug.com/350668580) SettingCategory.NONE once experiment GEN_AI_SETTINGS_PANEL is removed category: "CONSOLE" /* Common.Settings.SettingCategory.CONSOLE */, settingName: setting, settingType: "boolean" /* Common.Settings.SettingType.BOOLEAN */, title: i18nLazyString(UIStrings.enableConsoleInsights), - defaultValue: true, - // TODO(crbug.com/350668580) set to false once experiment GEN_AI_SETTINGS_PANEL is enabled + defaultValue: false, + // TODO(crbug.com/350668580) set to false once experiment GEN_AI_SETTINGS_PANEL is removed reloadRequired: true, condition: config => isFeatureEnabled(config), disabledCondition: config => { diff --git a/public/panels/explain/explain-meta.js.map b/public/panels/explain/explain-meta.js.map index bbfed6c44..c82845b02 100644 --- a/public/panels/explain/explain-meta.js.map +++ b/public/panels/explain/explain-meta.js.map @@ -1 +1 @@ -{"version":3,"file":"explain-meta.js","sourceRoot":"","sources":["../../../../../../front_end/panels/explain/explain-meta.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Root from '../../core/root/root.js';\nimport * as Console from '../../panels/console/console.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nconst UIStrings = {\n /**\n *@description Message to offer insights for a console error message\n */\n explainThisError: 'Understand this error',\n /**\n *@description Message to offer insights for a console warning message\n */\n explainThisWarning: 'Understand this warning',\n /**\n *@description Message to offer insights for a console message\n */\n explainThisMessage: 'Understand this message',\n /**\n * @description The setting title to enable the console insights feature via\n * the settings tab.\n */\n enableConsoleInsights: 'Understand console messages with AI',\n /**\n * @description Message shown to the user if the DevTools locale is not\n * supported.\n */\n wrongLocale: 'To use this feature, update your Language preference in DevTools Settings to English',\n /**\n * @description Message shown to the user if the age check is not successful.\n */\n ageRestricted: 'This feature is only available to users who are 18 years of age or older',\n /**\n * @description Message shown to the user if the user's region is not\n * supported.\n */\n geoRestricted: 'This feature is unavailable in your region',\n /**\n * @description Message shown to the user if the enterprise policy does\n * not allow this feature.\n */\n policyRestricted: 'Your organization turned off this feature. Contact your administrators for more information.',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/explain/explain-meta.ts', UIStrings);\nconst i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nconst setting = 'console-insights-enabled';\n\nconst actions = [\n {\n actionId: 'explain.console-message.hover',\n title: i18nLazyString(UIStrings.explainThisMessage),\n contextTypes(): [typeof Console.ConsoleViewMessage.ConsoleViewMessage] {\n return [Console.ConsoleViewMessage.ConsoleViewMessage];\n },\n },\n {\n actionId: 'explain.console-message.context.error',\n title: i18nLazyString(UIStrings.explainThisError),\n contextTypes(): [] {\n return [];\n },\n },\n {\n actionId: 'explain.console-message.context.warning',\n title: i18nLazyString(UIStrings.explainThisWarning),\n contextTypes(): [] {\n return [];\n },\n },\n {\n actionId: 'explain.console-message.context.other',\n title: i18nLazyString(UIStrings.explainThisMessage),\n contextTypes(): [] {\n return [];\n },\n },\n];\n\nfunction isLocaleRestricted(): boolean {\n const devtoolsLocale = i18n.DevToolsLocale.DevToolsLocale.instance();\n return !devtoolsLocale.locale.startsWith('en-');\n}\n\nfunction isAgeRestricted(config?: Root.Runtime.HostConfig): boolean {\n return config?.aidaAvailability?.blockedByAge === true;\n}\n\nfunction isGeoRestricted(config?: Root.Runtime.HostConfig): boolean {\n return config?.aidaAvailability?.blockedByGeo === true;\n}\n\nfunction isPolicyRestricted(config?: Root.Runtime.HostConfig): boolean {\n return config?.aidaAvailability?.blockedByEnterprisePolicy === true;\n}\n\nfunction isFeatureEnabled(config?: Root.Runtime.HostConfig): boolean {\n return (config?.aidaAvailability?.enabled && config?.devToolsConsoleInsights?.enabled) === true;\n}\n\nCommon.Settings.registerSettingExtension({\n // TODO(crbug.com/350668580) SettingCategory.NONE once experiment GEN_AI_SETTINGS_PANEL is enabled\n category: Common.Settings.SettingCategory.CONSOLE,\n settingName: setting,\n settingType: Common.Settings.SettingType.BOOLEAN,\n title: i18nLazyString(UIStrings.enableConsoleInsights),\n defaultValue: true,\n // TODO(crbug.com/350668580) set to false once experiment GEN_AI_SETTINGS_PANEL is enabled\n reloadRequired: true,\n condition: config => isFeatureEnabled(config),\n disabledCondition: config => {\n if (isLocaleRestricted()) {\n return {disabled: true, reason: i18nString(UIStrings.wrongLocale)};\n }\n if (isAgeRestricted(config)) {\n return {disabled: true, reason: i18nString(UIStrings.ageRestricted)};\n }\n if (isGeoRestricted(config)) {\n return {disabled: true, reason: i18nString(UIStrings.geoRestricted)};\n }\n if (isPolicyRestricted(config)) {\n return {disabled: true, reason: i18nString(UIStrings.policyRestricted)};\n }\n return {disabled: false};\n },\n});\n\nfunction getConsoleInsightsEnabledSetting(): Common.Settings.Setting|undefined {\n try {\n return Common.Settings.moduleSetting('console-insights-enabled');\n } catch {\n return;\n }\n}\n\nfor (const action of actions) {\n UI.ActionRegistration.registerActionExtension({\n ...action,\n category: UI.ActionRegistration.ActionCategory.CONSOLE,\n async loadActionDelegate() {\n const Explain = await import('./explain.js');\n return new Explain.ActionDelegate();\n },\n condition: config => {\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n return isFeatureEnabled(config) && !isPolicyRestricted(config);\n }\n const consoleInsightsSetting = getConsoleInsightsEnabledSetting();\n return (consoleInsightsSetting?.getIfNotDisabled() === true) && isFeatureEnabled(config) &&\n !isAgeRestricted(config) && !isGeoRestricted(config) && !isLocaleRestricted() && !isPolicyRestricted(config);\n },\n });\n}\n"]} \ No newline at end of file +{"version":3,"file":"explain-meta.js","sourceRoot":"","sources":["../../../../../../front_end/panels/explain/explain-meta.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Root from '../../core/root/root.js';\nimport * as Console from '../../panels/console/console.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nconst UIStrings = {\n /**\n *@description Message to offer insights for a console error message\n */\n explainThisError: 'Understand this error',\n /**\n *@description Message to offer insights for a console warning message\n */\n explainThisWarning: 'Understand this warning',\n /**\n *@description Message to offer insights for a console message\n */\n explainThisMessage: 'Understand this message',\n /**\n * @description The setting title to enable the console insights feature via\n * the settings tab.\n */\n enableConsoleInsights: 'Understand console messages with AI',\n /**\n * @description Message shown to the user if the DevTools locale is not\n * supported.\n */\n wrongLocale: 'To use this feature, update your Language preference in DevTools Settings to English',\n /**\n * @description Message shown to the user if the age check is not successful.\n */\n ageRestricted: 'This feature is only available to users who are 18 years of age or older',\n /**\n * @description Message shown to the user if the user's region is not\n * supported.\n */\n geoRestricted: 'This feature is unavailable in your region',\n /**\n * @description Message shown to the user if the enterprise policy does\n * not allow this feature.\n */\n policyRestricted: 'Your organization turned off this feature. Contact your administrators for more information.',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/explain/explain-meta.ts', UIStrings);\nconst i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nconst setting = 'console-insights-enabled';\n\nconst actions = [\n {\n actionId: 'explain.console-message.hover',\n title: i18nLazyString(UIStrings.explainThisMessage),\n contextTypes(): [typeof Console.ConsoleViewMessage.ConsoleViewMessage] {\n return [Console.ConsoleViewMessage.ConsoleViewMessage];\n },\n },\n {\n actionId: 'explain.console-message.context.error',\n title: i18nLazyString(UIStrings.explainThisError),\n contextTypes(): [] {\n return [];\n },\n },\n {\n actionId: 'explain.console-message.context.warning',\n title: i18nLazyString(UIStrings.explainThisWarning),\n contextTypes(): [] {\n return [];\n },\n },\n {\n actionId: 'explain.console-message.context.other',\n title: i18nLazyString(UIStrings.explainThisMessage),\n contextTypes(): [] {\n return [];\n },\n },\n];\n\nfunction isLocaleRestricted(): boolean {\n const devtoolsLocale = i18n.DevToolsLocale.DevToolsLocale.instance();\n return !devtoolsLocale.locale.startsWith('en-');\n}\n\nfunction isAgeRestricted(config?: Root.Runtime.HostConfig): boolean {\n return config?.aidaAvailability?.blockedByAge === true;\n}\n\nfunction isGeoRestricted(config?: Root.Runtime.HostConfig): boolean {\n return config?.aidaAvailability?.blockedByGeo === true;\n}\n\nfunction isPolicyRestricted(config?: Root.Runtime.HostConfig): boolean {\n return config?.aidaAvailability?.blockedByEnterprisePolicy === true;\n}\n\nfunction isFeatureEnabled(config?: Root.Runtime.HostConfig): boolean {\n return (config?.aidaAvailability?.enabled && config?.devToolsConsoleInsights?.enabled) === true;\n}\n\nCommon.Settings.registerSettingExtension({\n // TODO(crbug.com/350668580) SettingCategory.NONE once experiment GEN_AI_SETTINGS_PANEL is removed\n category: Common.Settings.SettingCategory.CONSOLE,\n settingName: setting,\n settingType: Common.Settings.SettingType.BOOLEAN,\n title: i18nLazyString(UIStrings.enableConsoleInsights),\n defaultValue: false,\n // TODO(crbug.com/350668580) set to false once experiment GEN_AI_SETTINGS_PANEL is removed\n reloadRequired: true,\n condition: config => isFeatureEnabled(config),\n disabledCondition: config => {\n if (isLocaleRestricted()) {\n return {disabled: true, reason: i18nString(UIStrings.wrongLocale)};\n }\n if (isAgeRestricted(config)) {\n return {disabled: true, reason: i18nString(UIStrings.ageRestricted)};\n }\n if (isGeoRestricted(config)) {\n return {disabled: true, reason: i18nString(UIStrings.geoRestricted)};\n }\n if (isPolicyRestricted(config)) {\n return {disabled: true, reason: i18nString(UIStrings.policyRestricted)};\n }\n return {disabled: false};\n },\n});\n\nfunction getConsoleInsightsEnabledSetting(): Common.Settings.Setting|undefined {\n try {\n return Common.Settings.moduleSetting('console-insights-enabled');\n } catch {\n return;\n }\n}\n\nfor (const action of actions) {\n UI.ActionRegistration.registerActionExtension({\n ...action,\n category: UI.ActionRegistration.ActionCategory.CONSOLE,\n async loadActionDelegate() {\n const Explain = await import('./explain.js');\n return new Explain.ActionDelegate();\n },\n condition: config => {\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL)) {\n return isFeatureEnabled(config) && !isPolicyRestricted(config);\n }\n const consoleInsightsSetting = getConsoleInsightsEnabledSetting();\n return (consoleInsightsSetting?.getIfNotDisabled() === true) && isFeatureEnabled(config) &&\n !isAgeRestricted(config) && !isGeoRestricted(config) && !isLocaleRestricted() && !isPolicyRestricted(config);\n },\n });\n}\n"]} \ No newline at end of file diff --git a/public/panels/freestyler/DrJonesNetworkAgent.d.ts b/public/panels/freestyler/DrJonesNetworkAgent.d.ts index c750afdfa..b1a74c000 100644 --- a/public/panels/freestyler/DrJonesNetworkAgent.d.ts +++ b/public/panels/freestyler/DrJonesNetworkAgent.d.ts @@ -47,5 +47,7 @@ export declare class DrJonesNetworkAgent { }): AsyncGenerator; } export declare function allowHeader(header: SDK.NetworkRequest.NameValue): boolean; -export declare function formatNetworkRequest(request: Pick): string; +export declare function formatHeaders(title: string, headers: SDK.NetworkRequest.NameValue[]): string; +export declare function formatNetworkRequestTiming(request: SDK.NetworkRequest.NetworkRequest): string; +export declare function formatNetworkRequest(request: SDK.NetworkRequest.NetworkRequest): string; export {}; diff --git a/public/panels/freestyler/DrJonesNetworkAgent.js b/public/panels/freestyler/DrJonesNetworkAgent.js index 18df3ad17..c1dac2020 100644 --- a/public/panels/freestyler/DrJonesNetworkAgent.js +++ b/public/panels/freestyler/DrJonesNetworkAgent.js @@ -3,11 +3,13 @@ // found in the LICENSE file. import * as Common from '../../core/common/common.js'; import * as Host from '../../core/host/host.js'; +import * as Logs from '../../models/logs/logs.js'; /* clang-format off */ const preamble = `You are the most advanced network request debugging assistant integrated into Chrome DevTools. The user selected a network request in the browser's DevTools Network Panel and sends a query to understand the request. Provide a comprehensive analysis of the network request, focusing on areas crucial for a software engineer. Your analysis should include: * Briefly explain the purpose of the request based on the URL, method, and any relevant headers or payload. +* Analyze timing information to identify potential bottlenecks or areas for optimization. * Highlight potential issues indicated by the status code. # Considerations @@ -52,14 +54,13 @@ export class DrJonesNetworkAgent { chat_history: opts.chatHistory, client: Host.AidaClient.CLIENT_NAME, options: { - temperature: config.devToolsFreestylerDogfood?.temperature ?? 0, - model_id: config.devToolsFreestylerDogfood?.modelId ?? undefined, + temperature: config.devToolsExplainThisResourceDogfood?.temperature ?? 0, + model_id: config.devToolsExplainThisResourceDogfood?.modelId ?? undefined, }, metadata: { // TODO: disable logging based on query params. disable_user_content_logging: !(opts.serverSideLoggingEnabled ?? false), string_session_id: opts.sessionId, - user_tier: Host.AidaClient.convertToUserTierEnum(config.devToolsFreestylerDogfood?.userTier), }, // eslint-disable-next-line @typescript-eslint/naming-convention functionality_type: Host.AidaClient.FunctionalityType.CHAT, @@ -151,7 +152,7 @@ export class DrJonesNetworkAgent { ]); }; const currentRunEntries = this.#chatHistory.get(currentRunId) ?? []; - addToHistory(`ANSWER: ${response}`); + addToHistory(response); yield { type: DrJonesNetworkAgentResponseType.ANSWER, text: response, @@ -207,6 +208,52 @@ export function allowHeader(header) { } return true; } +export function formatHeaders(title, headers) { + return formatLines(title, headers.filter(allowHeader).map(header => header.name + ': ' + header.value + '\n'), MAX_HEADERS_SIZE); +} +export function formatNetworkRequestTiming(request) { + const timing = request.timing; + return ` +Request start time: ${request.startTime} +Request end time: ${request.endTime} +Receiving response headers start time: ${timing?.receiveHeadersStart} +Receiving response headers end time: ${timing?.receiveHeadersEnd} +Proxy negotiation start time: ${timing?.proxyStart} +Proxy negotiation end time: ${timing?.proxyEnd} +DNS lookup start time: ${timing?.dnsStart} +DNS lookup end time: ${timing?.dnsEnd} +TCP start time: ${timing?.connectStart} +TCP end time: ${timing?.connectEnd} +SSL start time: ${timing?.sslStart} +SSL end time: ${timing?.sslEnd} +Sending start: ${timing?.sendStart} +Sending end: ${timing?.sendEnd} + `; +} +function formatRequestInitiated(request, initiatorChain, lineStart) { + const initiated = Logs.NetworkLog.NetworkLog.instance().initiatorGraphForRequest(request).initiated; + initiated.forEach((k, initiatedRequest) => { + if (request === k) { + initiatorChain = initiatorChain + lineStart + initiatedRequest.url() + '\n'; + initiatorChain = formatRequestInitiated(initiatedRequest, initiatorChain, '\t' + lineStart); + } + }); + return initiatorChain; +} +function formatRequestInitiatorChain(request) { + let initiatorChain = ''; + let lineStart = '- URL: '; + const initiators = Logs.NetworkLog.NetworkLog.instance().initiatorGraphForRequest(request).initiators; + for (const initator of Array.from(initiators).reverse()) { + initiatorChain = initiatorChain + lineStart + initator.url() + '\n'; + lineStart = '\t' + lineStart; + if (initator === request) { + initiatorChain = formatRequestInitiated(initator, initiatorChain, lineStart); + break; + } + } + return initiatorChain; +} export function formatNetworkRequest(request) { const formatHeaders = (title, headers) => formatLines(title, headers.filter(allowHeader).map(header => header.name + ': ' + header.value + '\n'), MAX_HEADERS_SIZE); // TODO: anything else that might be relavant? @@ -217,7 +264,11 @@ ${formatHeaders('Request headers:', request.requestHeaders())} ${formatHeaders('Response headers:', request.responseHeaders)} -Response status: ${request.statusCode} ${request.statusText}`; +Response status: ${request.statusCode} ${request.statusText} + +Request Timing:\n ${formatNetworkRequestTiming(request)} + +Request Initiator Chain:\n ${formatRequestInitiatorChain(request)}`; } // @ts-ignore globalThis.setDebugFreestylerEnabled = setDebugFreestylerEnabled; diff --git a/public/panels/freestyler/DrJonesNetworkAgent.js.map b/public/panels/freestyler/DrJonesNetworkAgent.js.map index 67c27d743..878e4ef9b 100644 --- a/public/panels/freestyler/DrJonesNetworkAgent.js.map +++ b/public/panels/freestyler/DrJonesNetworkAgent.js.map @@ -1 +1 @@ -{"version":3,"file":"DrJonesNetworkAgent.js","sourceRoot":"","sources":["../../../../../../front_end/panels/freestyler/DrJonesNetworkAgent.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as Host from '../../core/host/host.js';\nimport type * as SDK from '../../core/sdk/sdk.js';\n\n/* clang-format off */\nconst preamble = `You are the most advanced network request debugging assistant integrated into Chrome DevTools.\nThe user selected a network request in the browser's DevTools Network Panel and sends a query to understand the request.\nProvide a comprehensive analysis of the network request, focusing on areas crucial for a software engineer. Your analysis should include:\n* Briefly explain the purpose of the request based on the URL, method, and any relevant headers or payload.\n* Highlight potential issues indicated by the status code.\n\n# Considerations\n* If the response payload or request payload contains sensitive data, redact or generalize it in your analysis to ensure privacy.\n* Tailor your explanations and suggestions to the specific context of the request and the technologies involved (if discernible from the provided details).\n* Keep your analysis concise and focused, highlighting only the most critical aspects for a software engineer.\n\n## Example session\n\nExplain this network request\nRequest: https://api.example.com/products/search?q=laptop&category=electronics\nResponse Headers:\n Content-Type: application/json\n Cache-Control: max-age=300\n...\nRequest Headers:\n User-Agent: Mozilla/5.0\n...\nRequest Status: 200 OK\n\n\nThis request aims to retrieve a list of products matching the search query \"laptop\" within the \"electronics\" category. The successful 200 OK status confirms that the server fulfilled the request and returned the relevant data.\n`;\n/* clang-format on */\n\nconst MAX_HEADERS_SIZE = 1000;\n\nexport enum DrJonesNetworkAgentResponseType {\n ANSWER = 'answer',\n ERROR = 'error',\n}\n\nexport interface AnswerResponse {\n type: DrJonesNetworkAgentResponseType.ANSWER;\n text: string;\n rpcId?: number;\n}\n\nexport interface ErrorResponse {\n type: DrJonesNetworkAgentResponseType.ERROR;\n rpcId?: number;\n}\n\nexport type ResponseData = AnswerResponse|ErrorResponse;\n\ntype HistoryChunk = {\n text: string,\n entity: Host.AidaClient.Entity,\n};\n\ntype AgentOptions = {\n aidaClient: Host.AidaClient.AidaClient,\n serverSideLoggingEnabled?: boolean,\n};\n\ninterface AidaRequestOptions {\n input: string;\n preamble?: string;\n chatHistory?: Host.AidaClient.Chunk[];\n /**\n * @default false\n */\n serverSideLoggingEnabled?: boolean;\n sessionId?: string;\n}\n\n/**\n * One agent instance handles one conversation. Create a new agent\n * instance for a new conversation.\n */\nexport class DrJonesNetworkAgent {\n static buildRequest(opts: AidaRequestOptions): Host.AidaClient.AidaRequest {\n const config = Common.Settings.Settings.instance().getHostConfig();\n const request: Host.AidaClient.AidaRequest = {\n input: opts.input,\n preamble: opts.preamble,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n chat_history: opts.chatHistory,\n client: Host.AidaClient.CLIENT_NAME,\n options: {\n temperature: config.devToolsFreestylerDogfood?.temperature ?? 0,\n model_id: config.devToolsFreestylerDogfood?.modelId ?? undefined,\n },\n metadata: {\n // TODO: disable logging based on query params.\n disable_user_content_logging: !(opts.serverSideLoggingEnabled ?? false),\n string_session_id: opts.sessionId,\n user_tier: Host.AidaClient.convertToUserTierEnum(config.devToolsFreestylerDogfood?.userTier),\n },\n // eslint-disable-next-line @typescript-eslint/naming-convention\n functionality_type: Host.AidaClient.FunctionalityType.CHAT,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n client_feature: Host.AidaClient.ClientFeature.CHROME_FREESTYLER,\n };\n return request;\n }\n\n #aidaClient: Host.AidaClient.AidaClient;\n #chatHistory: Map = new Map();\n #serverSideLoggingEnabled: boolean;\n\n readonly #sessionId = crypto.randomUUID();\n\n constructor(opts: AgentOptions) {\n this.#aidaClient = opts.aidaClient;\n this.#serverSideLoggingEnabled = opts.serverSideLoggingEnabled ?? false;\n }\n\n get #getHistoryEntry(): Array {\n return [...this.#chatHistory.values()].flat();\n }\n\n get chatHistoryForTesting(): Array {\n return this.#getHistoryEntry;\n }\n\n async #aidaFetch(request: Host.AidaClient.AidaRequest): Promise<{response: string, rpcId: number|undefined}> {\n let response = '';\n let rpcId;\n for await (const lastResult of this.#aidaClient.fetch(request)) {\n response = lastResult.explanation;\n rpcId = lastResult.metadata.rpcGlobalId ?? rpcId;\n if (lastResult.metadata.attributionMetadata?.some(\n meta => meta.attributionAction === Host.AidaClient.RecitationAction.BLOCK)) {\n throw new Error('Attribution action does not allow providing the response');\n }\n }\n return {response, rpcId};\n }\n\n #runId = 0;\n async * run(query: string, options: {\n signal?: AbortSignal, selectedNetworkRequest: SDK.NetworkRequest.NetworkRequest|null,\n }): AsyncGenerator {\n const structuredLog = [];\n query = `${\n options.selectedNetworkRequest ?\n `# Selected network request \\n${\n formatNetworkRequest(options.selectedNetworkRequest)}\\n\\n# User request\\n\\n` :\n ''}${query}`;\n const currentRunId = ++this.#runId;\n\n options.signal?.addEventListener('abort', () => {\n this.#chatHistory.delete(currentRunId);\n });\n\n const request = DrJonesNetworkAgent.buildRequest({\n input: query,\n preamble,\n chatHistory: this.#chatHistory.size ? this.#getHistoryEntry : undefined,\n serverSideLoggingEnabled: this.#serverSideLoggingEnabled,\n sessionId: this.#sessionId,\n });\n let response: string;\n let rpcId: number|undefined;\n try {\n const fetchResult = await this.#aidaFetch(request);\n response = fetchResult.response;\n rpcId = fetchResult.rpcId;\n } catch (err) {\n debugLog('Error calling the AIDA API', err);\n\n if (options.signal?.aborted) {\n return;\n }\n\n yield {\n type: DrJonesNetworkAgentResponseType.ERROR,\n rpcId,\n };\n return;\n }\n\n if (options.signal?.aborted) {\n return;\n }\n\n debugLog('Request', request, 'Response', response);\n\n structuredLog.push({\n request: structuredClone(request),\n response,\n });\n\n const addToHistory = (text: string): void => {\n this.#chatHistory.set(currentRunId, [\n ...currentRunEntries,\n {\n text: query,\n entity: Host.AidaClient.Entity.USER,\n },\n {\n text,\n entity: Host.AidaClient.Entity.SYSTEM,\n },\n ]);\n };\n const currentRunEntries = this.#chatHistory.get(currentRunId) ?? [];\n addToHistory(`ANSWER: ${response}`);\n yield {\n type: DrJonesNetworkAgentResponseType.ANSWER,\n text: response,\n rpcId,\n };\n if (isDebugMode()) {\n localStorage.setItem('freestylerStructuredLog', JSON.stringify(structuredLog));\n window.dispatchEvent(new CustomEvent('freestylerdone'));\n }\n }\n}\n\nfunction isDebugMode(): boolean {\n return Boolean(localStorage.getItem('debugFreestylerEnabled'));\n}\n\nfunction debugLog(...log: unknown[]): void {\n if (!isDebugMode()) {\n return;\n }\n\n // eslint-disable-next-line no-console\n console.log(...log);\n}\n\nfunction setDebugFreestylerEnabled(enabled: boolean): void {\n if (enabled) {\n localStorage.setItem('debugFreestylerEnabled', 'true');\n } else {\n localStorage.removeItem('debugFreestylerEnabled');\n }\n}\n\nfunction formatLines(title: string, lines: string[], maxLength: number): string {\n let result = '';\n for (const line of lines) {\n if (result.length + line.length > maxLength) {\n break;\n }\n result += line;\n }\n result = result.trim();\n return result && title ? title + '\\n' + result : result;\n}\n\nexport function allowHeader(header: SDK.NetworkRequest.NameValue): boolean {\n const normalizedName = header.name.toLowerCase().trim();\n // Skip custom headers.\n if (normalizedName.startsWith('x-')) {\n return false;\n }\n // Skip cookies as they might contain auth.\n if (normalizedName === 'cookie' || normalizedName === 'set-cookie') {\n return false;\n }\n if (normalizedName === 'authorization') {\n return false;\n }\n return true;\n}\n\nexport function formatNetworkRequest(\n request:\n Pick):\n string {\n const formatHeaders = (title: string, headers: SDK.NetworkRequest.NameValue[]): string => formatLines(\n title, headers.filter(allowHeader).map(header => header.name + ': ' + header.value + '\\n'), MAX_HEADERS_SIZE);\n // TODO: anything else that might be relavant?\n // TODO: handle missing headers\n return `Request: ${request.url()}\n\n${formatHeaders('Request headers:', request.requestHeaders())}\n\n${formatHeaders('Response headers:', request.responseHeaders)}\n\nResponse status: ${request.statusCode} ${request.statusText}`;\n}\n\n// @ts-ignore\nglobalThis.setDebugFreestylerEnabled = setDebugFreestylerEnabled;\n"]} \ No newline at end of file +{"version":3,"file":"DrJonesNetworkAgent.js","sourceRoot":"","sources":["../../../../../../front_end/panels/freestyler/DrJonesNetworkAgent.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as Host from '../../core/host/host.js';\nimport type * as SDK from '../../core/sdk/sdk.js';\nimport * as Logs from '../../models/logs/logs.js';\n\n/* clang-format off */\nconst preamble = `You are the most advanced network request debugging assistant integrated into Chrome DevTools.\nThe user selected a network request in the browser's DevTools Network Panel and sends a query to understand the request.\nProvide a comprehensive analysis of the network request, focusing on areas crucial for a software engineer. Your analysis should include:\n* Briefly explain the purpose of the request based on the URL, method, and any relevant headers or payload.\n* Analyze timing information to identify potential bottlenecks or areas for optimization.\n* Highlight potential issues indicated by the status code.\n\n# Considerations\n* If the response payload or request payload contains sensitive data, redact or generalize it in your analysis to ensure privacy.\n* Tailor your explanations and suggestions to the specific context of the request and the technologies involved (if discernible from the provided details).\n* Keep your analysis concise and focused, highlighting only the most critical aspects for a software engineer.\n\n## Example session\n\nExplain this network request\nRequest: https://api.example.com/products/search?q=laptop&category=electronics\nResponse Headers:\n Content-Type: application/json\n Cache-Control: max-age=300\n...\nRequest Headers:\n User-Agent: Mozilla/5.0\n...\nRequest Status: 200 OK\n\n\nThis request aims to retrieve a list of products matching the search query \"laptop\" within the \"electronics\" category. The successful 200 OK status confirms that the server fulfilled the request and returned the relevant data.\n`;\n/* clang-format on */\n\nconst MAX_HEADERS_SIZE = 1000;\n\nexport enum DrJonesNetworkAgentResponseType {\n ANSWER = 'answer',\n ERROR = 'error',\n}\n\nexport interface AnswerResponse {\n type: DrJonesNetworkAgentResponseType.ANSWER;\n text: string;\n rpcId?: number;\n}\n\nexport interface ErrorResponse {\n type: DrJonesNetworkAgentResponseType.ERROR;\n rpcId?: number;\n}\n\nexport type ResponseData = AnswerResponse|ErrorResponse;\n\ntype HistoryChunk = {\n text: string,\n entity: Host.AidaClient.Entity,\n};\n\ntype AgentOptions = {\n aidaClient: Host.AidaClient.AidaClient,\n serverSideLoggingEnabled?: boolean,\n};\n\ninterface AidaRequestOptions {\n input: string;\n preamble?: string;\n chatHistory?: Host.AidaClient.Chunk[];\n /**\n * @default false\n */\n serverSideLoggingEnabled?: boolean;\n sessionId?: string;\n}\n\n/**\n * One agent instance handles one conversation. Create a new agent\n * instance for a new conversation.\n */\nexport class DrJonesNetworkAgent {\n static buildRequest(opts: AidaRequestOptions): Host.AidaClient.AidaRequest {\n const config = Common.Settings.Settings.instance().getHostConfig();\n const request: Host.AidaClient.AidaRequest = {\n input: opts.input,\n preamble: opts.preamble,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n chat_history: opts.chatHistory,\n client: Host.AidaClient.CLIENT_NAME,\n options: {\n temperature: config.devToolsExplainThisResourceDogfood?.temperature ?? 0,\n model_id: config.devToolsExplainThisResourceDogfood?.modelId ?? undefined,\n },\n metadata: {\n // TODO: disable logging based on query params.\n disable_user_content_logging: !(opts.serverSideLoggingEnabled ?? false),\n string_session_id: opts.sessionId,\n },\n // eslint-disable-next-line @typescript-eslint/naming-convention\n functionality_type: Host.AidaClient.FunctionalityType.CHAT,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n client_feature: Host.AidaClient.ClientFeature.CHROME_FREESTYLER,\n };\n return request;\n }\n\n #aidaClient: Host.AidaClient.AidaClient;\n #chatHistory: Map = new Map();\n #serverSideLoggingEnabled: boolean;\n\n readonly #sessionId = crypto.randomUUID();\n\n constructor(opts: AgentOptions) {\n this.#aidaClient = opts.aidaClient;\n this.#serverSideLoggingEnabled = opts.serverSideLoggingEnabled ?? false;\n }\n\n get #getHistoryEntry(): Array {\n return [...this.#chatHistory.values()].flat();\n }\n\n get chatHistoryForTesting(): Array {\n return this.#getHistoryEntry;\n }\n\n async #aidaFetch(request: Host.AidaClient.AidaRequest): Promise<{response: string, rpcId: number|undefined}> {\n let response = '';\n let rpcId;\n for await (const lastResult of this.#aidaClient.fetch(request)) {\n response = lastResult.explanation;\n rpcId = lastResult.metadata.rpcGlobalId ?? rpcId;\n if (lastResult.metadata.attributionMetadata?.some(\n meta => meta.attributionAction === Host.AidaClient.RecitationAction.BLOCK)) {\n throw new Error('Attribution action does not allow providing the response');\n }\n }\n return {response, rpcId};\n }\n\n #runId = 0;\n async * run(query: string, options: {\n signal?: AbortSignal, selectedNetworkRequest: SDK.NetworkRequest.NetworkRequest|null,\n }): AsyncGenerator {\n const structuredLog = [];\n query = `${\n options.selectedNetworkRequest ?\n `# Selected network request \\n${\n formatNetworkRequest(options.selectedNetworkRequest)}\\n\\n# User request\\n\\n` :\n ''}${query}`;\n const currentRunId = ++this.#runId;\n\n options.signal?.addEventListener('abort', () => {\n this.#chatHistory.delete(currentRunId);\n });\n\n const request = DrJonesNetworkAgent.buildRequest({\n input: query,\n preamble,\n chatHistory: this.#chatHistory.size ? this.#getHistoryEntry : undefined,\n serverSideLoggingEnabled: this.#serverSideLoggingEnabled,\n sessionId: this.#sessionId,\n });\n let response: string;\n let rpcId: number|undefined;\n try {\n const fetchResult = await this.#aidaFetch(request);\n response = fetchResult.response;\n rpcId = fetchResult.rpcId;\n } catch (err) {\n debugLog('Error calling the AIDA API', err);\n\n if (options.signal?.aborted) {\n return;\n }\n\n yield {\n type: DrJonesNetworkAgentResponseType.ERROR,\n rpcId,\n };\n return;\n }\n\n if (options.signal?.aborted) {\n return;\n }\n\n debugLog('Request', request, 'Response', response);\n\n structuredLog.push({\n request: structuredClone(request),\n response,\n });\n\n const addToHistory = (text: string): void => {\n this.#chatHistory.set(currentRunId, [\n ...currentRunEntries,\n {\n text: query,\n entity: Host.AidaClient.Entity.USER,\n },\n {\n text,\n entity: Host.AidaClient.Entity.SYSTEM,\n },\n ]);\n };\n const currentRunEntries = this.#chatHistory.get(currentRunId) ?? [];\n addToHistory(response);\n yield {\n type: DrJonesNetworkAgentResponseType.ANSWER,\n text: response,\n rpcId,\n };\n if (isDebugMode()) {\n localStorage.setItem('freestylerStructuredLog', JSON.stringify(structuredLog));\n window.dispatchEvent(new CustomEvent('freestylerdone'));\n }\n }\n}\n\nfunction isDebugMode(): boolean {\n return Boolean(localStorage.getItem('debugFreestylerEnabled'));\n}\n\nfunction debugLog(...log: unknown[]): void {\n if (!isDebugMode()) {\n return;\n }\n\n // eslint-disable-next-line no-console\n console.log(...log);\n}\n\nfunction setDebugFreestylerEnabled(enabled: boolean): void {\n if (enabled) {\n localStorage.setItem('debugFreestylerEnabled', 'true');\n } else {\n localStorage.removeItem('debugFreestylerEnabled');\n }\n}\n\nfunction formatLines(title: string, lines: string[], maxLength: number): string {\n let result = '';\n for (const line of lines) {\n if (result.length + line.length > maxLength) {\n break;\n }\n result += line;\n }\n result = result.trim();\n return result && title ? title + '\\n' + result : result;\n}\n\nexport function allowHeader(header: SDK.NetworkRequest.NameValue): boolean {\n const normalizedName = header.name.toLowerCase().trim();\n // Skip custom headers.\n if (normalizedName.startsWith('x-')) {\n return false;\n }\n // Skip cookies as they might contain auth.\n if (normalizedName === 'cookie' || normalizedName === 'set-cookie') {\n return false;\n }\n if (normalizedName === 'authorization') {\n return false;\n }\n return true;\n}\n\nexport function formatHeaders(title: string, headers: SDK.NetworkRequest.NameValue[]): string {\n return formatLines(\n title, headers.filter(allowHeader).map(header => header.name + ': ' + header.value + '\\n'), MAX_HEADERS_SIZE);\n}\n\nexport function formatNetworkRequestTiming(request: SDK.NetworkRequest.NetworkRequest): string {\n const timing = request.timing;\n\n return `\nRequest start time: ${request.startTime}\nRequest end time: ${request.endTime}\nReceiving response headers start time: ${timing?.receiveHeadersStart}\nReceiving response headers end time: ${timing?.receiveHeadersEnd}\nProxy negotiation start time: ${timing?.proxyStart}\nProxy negotiation end time: ${timing?.proxyEnd}\nDNS lookup start time: ${timing?.dnsStart}\nDNS lookup end time: ${timing?.dnsEnd}\nTCP start time: ${timing?.connectStart}\nTCP end time: ${timing?.connectEnd}\nSSL start time: ${timing?.sslStart}\nSSL end time: ${timing?.sslEnd}\nSending start: ${timing?.sendStart}\nSending end: ${timing?.sendEnd}\n `;\n}\n\nfunction formatRequestInitiated(\n request: SDK.NetworkRequest.NetworkRequest, initiatorChain: string, lineStart: string): string {\n const initiated = Logs.NetworkLog.NetworkLog.instance().initiatorGraphForRequest(request).initiated;\n initiated.forEach((k, initiatedRequest) => {\n if (request === k) {\n initiatorChain = initiatorChain + lineStart + initiatedRequest.url() + '\\n';\n initiatorChain = formatRequestInitiated(initiatedRequest, initiatorChain, '\\t' + lineStart);\n }\n });\n return initiatorChain;\n}\n\nfunction formatRequestInitiatorChain(request: SDK.NetworkRequest.NetworkRequest): string {\n let initiatorChain = '';\n let lineStart = '- URL: ';\n const initiators = Logs.NetworkLog.NetworkLog.instance().initiatorGraphForRequest(request).initiators;\n\n for (const initator of Array.from(initiators).reverse()) {\n initiatorChain = initiatorChain + lineStart + initator.url() + '\\n';\n lineStart = '\\t' + lineStart;\n if (initator === request) {\n initiatorChain = formatRequestInitiated(initator, initiatorChain, lineStart);\n break;\n }\n }\n\n return initiatorChain;\n}\n\nexport function formatNetworkRequest(request: SDK.NetworkRequest.NetworkRequest): string {\n const formatHeaders = (title: string, headers: SDK.NetworkRequest.NameValue[]): string => formatLines(\n title, headers.filter(allowHeader).map(header => header.name + ': ' + header.value + '\\n'), MAX_HEADERS_SIZE);\n // TODO: anything else that might be relavant?\n // TODO: handle missing headers\n return `Request: ${request.url()}\n\n${formatHeaders('Request headers:', request.requestHeaders())}\n\n${formatHeaders('Response headers:', request.responseHeaders)}\n\nResponse status: ${request.statusCode} ${request.statusText}\n\nRequest Timing:\\n ${formatNetworkRequestTiming(request)}\n\nRequest Initiator Chain:\\n ${formatRequestInitiatorChain(request)}`;\n}\n\n// @ts-ignore\nglobalThis.setDebugFreestylerEnabled = setDebugFreestylerEnabled;\n"]} \ No newline at end of file diff --git a/public/panels/freestyler/ExtensionScope.d.ts b/public/panels/freestyler/ExtensionScope.d.ts index e5dd2765c..de1c69de4 100644 --- a/public/panels/freestyler/ExtensionScope.d.ts +++ b/public/panels/freestyler/ExtensionScope.d.ts @@ -1,3 +1,5 @@ +import * as SDK from '../../core/sdk/sdk.js'; +import type * as Protocol from '../../generated/protocol.js'; import { type ChangeManager } from './ChangeManager.js'; export declare const FREESTYLER_WORLD_NAME = "devtools_freestyler"; export declare const FREESTYLER_BINDING_NAME = "__freestyler"; @@ -7,6 +9,8 @@ export declare const FREESTYLER_BINDING_NAME = "__freestyler"; export declare class ExtensionScope { #private; constructor(changes: ChangeManager); + get target(): SDK.Target.Target; + get frameId(): Protocol.Page.FrameId; install(): Promise; uninstall(): Promise; } diff --git a/public/panels/freestyler/ExtensionScope.js b/public/panels/freestyler/ExtensionScope.js index 86b851059..14a504a46 100644 --- a/public/panels/freestyler/ExtensionScope.js +++ b/public/panels/freestyler/ExtensionScope.js @@ -21,19 +21,34 @@ export class ExtensionScope { const selectedNode = UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode); const frameId = selectedNode?.frameId(); const target = selectedNode?.domModel().target(); - if (!frameId || !target) { - throw new Error('Frame is not found'); - } this.#target = target; this.#frameId = frameId; } + get target() { + if (this.#target) { + return this.#target; + } + const target = UI.Context.Context.instance().flavor(SDK.Target.Target); + if (!target) { + throw new Error('Target is not found for executing code'); + } + return target; + } + get frameId() { + if (this.#frameId) { + return this.#frameId; + } + const resourceTreeModel = this.target.model(SDK.ResourceTreeModel.ResourceTreeModel); + if (!resourceTreeModel?.mainFrame) { + throw new Error('Main frame is not found for executing code'); + } + return resourceTreeModel.mainFrame.id; + } async install() { - const target = this.#target; - const frameId = this.#frameId; - const runtimeModel = target.model(SDK.RuntimeModel.RuntimeModel); - const pageAgent = target.pageAgent(); + const runtimeModel = this.target.model(SDK.RuntimeModel.RuntimeModel); + const pageAgent = this.target.pageAgent(); // This returns previously created world if it exists for the frame. - const { executionContextId } = await pageAgent.invoke_createIsolatedWorld({ frameId, worldName: FREESTYLER_WORLD_NAME }); + const { executionContextId } = await pageAgent.invoke_createIsolatedWorld({ frameId: this.frameId, worldName: FREESTYLER_WORLD_NAME }); const isolatedWorldContext = runtimeModel?.executionContext(executionContextId); if (!isolatedWorldContext) { throw new Error('Execution context is not found for executing code'); @@ -41,7 +56,7 @@ export class ExtensionScope { const handler = this.#bindingCalled.bind(this, isolatedWorldContext); runtimeModel?.addEventListener(SDK.RuntimeModel.Events.BindingCalled, handler); this.#listeners.push(handler); - await target.runtimeAgent().invoke_addBinding({ + await this.target.runtimeAgent().invoke_addBinding({ name: FREESTYLER_BINDING_NAME, executionContextId, }); @@ -49,12 +64,12 @@ export class ExtensionScope { await this.#simpleEval(isolatedWorldContext, functions); } async uninstall() { - const runtimeModel = this.#target.model(SDK.RuntimeModel.RuntimeModel); + const runtimeModel = this.target.model(SDK.RuntimeModel.RuntimeModel); for (const handler of this.#listeners) { runtimeModel?.removeEventListener(SDK.RuntimeModel.Events.BindingCalled, handler); } this.#listeners = []; - await this.#target.runtimeAgent().invoke_removeBinding({ + await this.target.runtimeAgent().invoke_removeBinding({ name: FREESTYLER_BINDING_NAME, }); } @@ -88,17 +103,16 @@ export class ExtensionScope { return; } await this.#bindingMutex.run(async () => { - const target = this.#target; const id = data.payload; const { object } = await this.#simpleEval(executionContext, `freestyler.getArgs(${id})`); const arg = JSON.parse(object.value); const selector = arg.selector; const className = arg.className; - const cssModel = target.model(SDK.CSSModel.CSSModel); + const cssModel = this.target.model(SDK.CSSModel.CSSModel); if (!cssModel) { throw new Error('CSSModel is not found'); } - await this.#changeManager.addChange(cssModel, this.#frameId, { + await this.#changeManager.addChange(cssModel, this.frameId, { selector, className, styles: arg.styles, diff --git a/public/panels/freestyler/ExtensionScope.js.map b/public/panels/freestyler/ExtensionScope.js.map index d276bf138..f8eba0a3a 100644 --- a/public/panels/freestyler/ExtensionScope.js.map +++ b/public/panels/freestyler/ExtensionScope.js.map @@ -1 +1 @@ -{"version":3,"file":"ExtensionScope.js","sourceRoot":"","sources":["../../../../../../front_end/panels/freestyler/ExtensionScope.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport type * as Protocol from '../../generated/protocol.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport {AI_ASSISTANT_CSS_CLASS_NAME, type ChangeManager} from './ChangeManager.js';\n\nexport const FREESTYLER_WORLD_NAME = 'devtools_freestyler';\nexport const FREESTYLER_BINDING_NAME = '__freestyler';\n\n/**\n * Injects Freestyler extension functions in to the isolated world.\n */\nexport class ExtensionScope {\n #listeners: Array<(event: {\n data: Protocol.Runtime.BindingCalledEvent,\n }) => Promise> = [];\n #changeManager: ChangeManager;\n #frameId: Protocol.Page.FrameId;\n #target: SDK.Target.Target;\n\n readonly #bindingMutex = new Common.Mutex.Mutex();\n\n constructor(changes: ChangeManager) {\n this.#changeManager = changes;\n const selectedNode = UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);\n\n const frameId = selectedNode?.frameId();\n const target = selectedNode?.domModel().target();\n\n if (!frameId || !target) {\n throw new Error('Frame is not found');\n }\n this.#target = target;\n this.#frameId = frameId;\n }\n\n async install(): Promise {\n const target = this.#target;\n const frameId = this.#frameId;\n const runtimeModel = target.model(SDK.RuntimeModel.RuntimeModel);\n const pageAgent = target.pageAgent();\n\n // This returns previously created world if it exists for the frame.\n const {executionContextId} =\n await pageAgent.invoke_createIsolatedWorld({frameId, worldName: FREESTYLER_WORLD_NAME});\n\n const isolatedWorldContext = runtimeModel?.executionContext(executionContextId);\n if (!isolatedWorldContext) {\n throw new Error('Execution context is not found for executing code');\n }\n\n const handler = this.#bindingCalled.bind(this, isolatedWorldContext);\n runtimeModel?.addEventListener(SDK.RuntimeModel.Events.BindingCalled, handler);\n this.#listeners.push(handler);\n await target.runtimeAgent().invoke_addBinding({\n name: FREESTYLER_BINDING_NAME,\n executionContextId,\n });\n await this.#simpleEval(isolatedWorldContext, freestylerBinding);\n await this.#simpleEval(isolatedWorldContext, functions);\n }\n\n async uninstall(): Promise {\n const runtimeModel = this.#target.model(SDK.RuntimeModel.RuntimeModel);\n\n for (const handler of this.#listeners) {\n runtimeModel?.removeEventListener(SDK.RuntimeModel.Events.BindingCalled, handler);\n }\n this.#listeners = [];\n\n await this.#target.runtimeAgent().invoke_removeBinding({\n name: FREESTYLER_BINDING_NAME,\n });\n }\n\n async #simpleEval(context: SDK.RuntimeModel.ExecutionContext, expression: string): Promise<{\n object: SDK.RemoteObject.RemoteObject,\n exceptionDetails?: Protocol.Runtime.ExceptionDetails,\n }> {\n const response = await context.evaluate(\n {\n expression,\n replMode: true,\n includeCommandLineAPI: false,\n returnByValue: true,\n silent: false,\n generatePreview: false,\n allowUnsafeEvalBlockedByCSP: true,\n throwOnSideEffect: false,\n },\n /* userGesture */ false, /* awaitPromise */ true);\n\n if (!response) {\n throw new Error('Response is not found');\n }\n if ('error' in response) {\n throw new Error(response.error);\n }\n if (response.exceptionDetails) {\n const exceptionDescription = response.exceptionDetails.exception?.description;\n throw new Error(exceptionDescription || 'JS exception');\n }\n return response;\n }\n\n async #bindingCalled(executionContext: SDK.RuntimeModel.ExecutionContext, event: {\n data: Protocol.Runtime.BindingCalledEvent,\n }): Promise {\n const {data} = event;\n if (data.name !== FREESTYLER_BINDING_NAME) {\n return;\n }\n await this.#bindingMutex.run(async () => {\n const target = this.#target;\n const id = data.payload;\n const {object} = await this.#simpleEval(executionContext, `freestyler.getArgs(${id})`);\n const arg = JSON.parse(object.value);\n const selector = arg.selector;\n const className = arg.className;\n const cssModel = target.model(SDK.CSSModel.CSSModel);\n if (!cssModel) {\n throw new Error('CSSModel is not found');\n }\n await this.#changeManager.addChange(cssModel, this.#frameId, {\n selector,\n className,\n styles: arg.styles,\n });\n\n await this.#simpleEval(executionContext, `freestyler.respond(${id})`);\n });\n }\n}\n\nconst freestylerBinding = `globalThis.freestyler = (args) => {\n let resolver;\n let rejecter;\n const p = new Promise((resolve, reject) => {\n resolver = resolve;\n rejecter = reject;\n });\n freestyler.callbacks.set(freestyler.id , {\n args: JSON.stringify(args),\n callbackId: freestyler.id,\n resolver,\n rejecter\n });\n ${FREESTYLER_BINDING_NAME}(String(freestyler.id));\n freestyler.id++;\n return p;\n}\nfreestyler.id = 1;\nfreestyler.callbacks = new Map();\nfreestyler.getArgs = (callbackId) => {\n return freestyler.callbacks.get(callbackId).args;\n}\nfreestyler.respond = (callbackId) => {\n freestyler.callbacks.get(callbackId).resolver();\n freestyler.callbacks.delete(callbackId);\n}`;\n\nconst functions = `async function setElementStyles(el, styles) {\n let selector = el.tagName.toLowerCase();\n if (el.id) {\n selector = '#' + el.id;\n } else if (el.classList.length) {\n const parts = [];\n for (const cls of el.classList) {\n if (cls.startsWith('${AI_ASSISTANT_CSS_CLASS_NAME}')) {\n continue;\n }\n parts.push('.' + cls);\n }\n if (parts.length) {\n selector = parts.join('');\n }\n }\n\n // __freestylerClassName is not exposed to the page due to this being\n // run in the isolated world.\n const className = el.__freestylerClassName ?? '${AI_ASSISTANT_CSS_CLASS_NAME}-' + freestyler.id;\n el.__freestylerClassName = className;\n el.classList.add(className);\n\n // Remove inline styles with the same keys so that the edit applies.\n for (const [key, value] of Object.entries(styles)) {\n // if it's kebap case.\n el.style.removeProperty(key);\n // If it's camel case.\n el.style[key] = '';\n }\n\n await freestyler({\n method: 'setElementStyles',\n selector: selector,\n className,\n styles\n });\n}`;\n"]} \ No newline at end of file +{"version":3,"file":"ExtensionScope.js","sourceRoot":"","sources":["../../../../../../front_end/panels/freestyler/ExtensionScope.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport type * as Protocol from '../../generated/protocol.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport {AI_ASSISTANT_CSS_CLASS_NAME, type ChangeManager} from './ChangeManager.js';\n\nexport const FREESTYLER_WORLD_NAME = 'devtools_freestyler';\nexport const FREESTYLER_BINDING_NAME = '__freestyler';\n\n/**\n * Injects Freestyler extension functions in to the isolated world.\n */\nexport class ExtensionScope {\n #listeners: Array<(event: {\n data: Protocol.Runtime.BindingCalledEvent,\n }) => Promise> = [];\n #changeManager: ChangeManager;\n #frameId?: Protocol.Page.FrameId|null;\n #target?: SDK.Target.Target;\n\n readonly #bindingMutex = new Common.Mutex.Mutex();\n\n constructor(changes: ChangeManager) {\n this.#changeManager = changes;\n const selectedNode = UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);\n\n const frameId = selectedNode?.frameId();\n const target = selectedNode?.domModel().target();\n this.#target = target;\n this.#frameId = frameId;\n }\n\n get target(): SDK.Target.Target {\n if (this.#target) {\n return this.#target;\n }\n\n const target = UI.Context.Context.instance().flavor(SDK.Target.Target);\n if (!target) {\n throw new Error('Target is not found for executing code');\n }\n\n return target;\n }\n\n get frameId(): Protocol.Page.FrameId {\n if (this.#frameId) {\n return this.#frameId;\n }\n\n const resourceTreeModel = this.target.model(SDK.ResourceTreeModel.ResourceTreeModel);\n if (!resourceTreeModel?.mainFrame) {\n throw new Error('Main frame is not found for executing code');\n }\n\n return resourceTreeModel.mainFrame.id;\n }\n\n async install(): Promise {\n const runtimeModel = this.target.model(SDK.RuntimeModel.RuntimeModel);\n const pageAgent = this.target.pageAgent();\n\n // This returns previously created world if it exists for the frame.\n const {executionContextId} =\n await pageAgent.invoke_createIsolatedWorld({frameId: this.frameId, worldName: FREESTYLER_WORLD_NAME});\n\n const isolatedWorldContext = runtimeModel?.executionContext(executionContextId);\n if (!isolatedWorldContext) {\n throw new Error('Execution context is not found for executing code');\n }\n\n const handler = this.#bindingCalled.bind(this, isolatedWorldContext);\n runtimeModel?.addEventListener(SDK.RuntimeModel.Events.BindingCalled, handler);\n this.#listeners.push(handler);\n await this.target.runtimeAgent().invoke_addBinding({\n name: FREESTYLER_BINDING_NAME,\n executionContextId,\n });\n await this.#simpleEval(isolatedWorldContext, freestylerBinding);\n await this.#simpleEval(isolatedWorldContext, functions);\n }\n\n async uninstall(): Promise {\n const runtimeModel = this.target.model(SDK.RuntimeModel.RuntimeModel);\n\n for (const handler of this.#listeners) {\n runtimeModel?.removeEventListener(SDK.RuntimeModel.Events.BindingCalled, handler);\n }\n this.#listeners = [];\n\n await this.target.runtimeAgent().invoke_removeBinding({\n name: FREESTYLER_BINDING_NAME,\n });\n }\n\n async #simpleEval(context: SDK.RuntimeModel.ExecutionContext, expression: string): Promise<{\n object: SDK.RemoteObject.RemoteObject,\n exceptionDetails?: Protocol.Runtime.ExceptionDetails,\n }> {\n const response = await context.evaluate(\n {\n expression,\n replMode: true,\n includeCommandLineAPI: false,\n returnByValue: true,\n silent: false,\n generatePreview: false,\n allowUnsafeEvalBlockedByCSP: true,\n throwOnSideEffect: false,\n },\n /* userGesture */ false, /* awaitPromise */ true);\n\n if (!response) {\n throw new Error('Response is not found');\n }\n if ('error' in response) {\n throw new Error(response.error);\n }\n if (response.exceptionDetails) {\n const exceptionDescription = response.exceptionDetails.exception?.description;\n throw new Error(exceptionDescription || 'JS exception');\n }\n return response;\n }\n\n async #bindingCalled(executionContext: SDK.RuntimeModel.ExecutionContext, event: {\n data: Protocol.Runtime.BindingCalledEvent,\n }): Promise {\n const {data} = event;\n if (data.name !== FREESTYLER_BINDING_NAME) {\n return;\n }\n await this.#bindingMutex.run(async () => {\n const id = data.payload;\n const {object} = await this.#simpleEval(executionContext, `freestyler.getArgs(${id})`);\n const arg = JSON.parse(object.value);\n const selector = arg.selector;\n const className = arg.className;\n const cssModel = this.target.model(SDK.CSSModel.CSSModel);\n if (!cssModel) {\n throw new Error('CSSModel is not found');\n }\n await this.#changeManager.addChange(cssModel, this.frameId, {\n selector,\n className,\n styles: arg.styles,\n });\n\n await this.#simpleEval(executionContext, `freestyler.respond(${id})`);\n });\n }\n}\n\nconst freestylerBinding = `globalThis.freestyler = (args) => {\n let resolver;\n let rejecter;\n const p = new Promise((resolve, reject) => {\n resolver = resolve;\n rejecter = reject;\n });\n freestyler.callbacks.set(freestyler.id , {\n args: JSON.stringify(args),\n callbackId: freestyler.id,\n resolver,\n rejecter\n });\n ${FREESTYLER_BINDING_NAME}(String(freestyler.id));\n freestyler.id++;\n return p;\n}\nfreestyler.id = 1;\nfreestyler.callbacks = new Map();\nfreestyler.getArgs = (callbackId) => {\n return freestyler.callbacks.get(callbackId).args;\n}\nfreestyler.respond = (callbackId) => {\n freestyler.callbacks.get(callbackId).resolver();\n freestyler.callbacks.delete(callbackId);\n}`;\n\nconst functions = `async function setElementStyles(el, styles) {\n let selector = el.tagName.toLowerCase();\n if (el.id) {\n selector = '#' + el.id;\n } else if (el.classList.length) {\n const parts = [];\n for (const cls of el.classList) {\n if (cls.startsWith('${AI_ASSISTANT_CSS_CLASS_NAME}')) {\n continue;\n }\n parts.push('.' + cls);\n }\n if (parts.length) {\n selector = parts.join('');\n }\n }\n\n // __freestylerClassName is not exposed to the page due to this being\n // run in the isolated world.\n const className = el.__freestylerClassName ?? '${AI_ASSISTANT_CSS_CLASS_NAME}-' + freestyler.id;\n el.__freestylerClassName = className;\n el.classList.add(className);\n\n // Remove inline styles with the same keys so that the edit applies.\n for (const [key, value] of Object.entries(styles)) {\n // if it's kebap case.\n el.style.removeProperty(key);\n // If it's camel case.\n el.style[key] = '';\n }\n\n await freestyler({\n method: 'setElementStyles',\n selector: selector,\n className,\n styles\n });\n}`;\n"]} \ No newline at end of file diff --git a/public/panels/freestyler/FreestylerAgent.d.ts b/public/panels/freestyler/FreestylerAgent.d.ts index 68cbd5b3a..f5a7a27cd 100644 --- a/public/panels/freestyler/FreestylerAgent.d.ts +++ b/public/panels/freestyler/FreestylerAgent.d.ts @@ -3,6 +3,7 @@ import * as SDK from '../../core/sdk/sdk.js'; import { ChangeManager } from './ChangeManager.js'; export declare const FIX_THIS_ISSUE_PROMPT = "Fix this issue using JavaScript code execution"; export declare enum ResponseType { + TITLE = "title", THOUGHT = "thought", ACTION = "action", SIDE_EFFECT = "side-effect", @@ -18,6 +19,7 @@ export interface AnswerResponse { } export declare const enum ErrorType { UNKNOWN = "unknown", + ABORT = "abort", MAX_STEPS = "max-steps" } export interface ErrorResponse { @@ -25,10 +27,14 @@ export interface ErrorResponse { error: ErrorType; rpcId?: number; } +export interface TitleResponse { + type: ResponseType.TITLE; + title: string; + rpcId?: number; +} export interface ThoughtResponse { type: ResponseType.THOUGHT; thought: string; - title?: string; rpcId?: number; } export interface SideEffectResponse { @@ -47,7 +53,7 @@ export interface ActionResponse { export interface QueryResponse { type: ResponseType.QUERYING; } -export type ResponseData = AnswerResponse | ErrorResponse | ActionResponse | SideEffectResponse | ThoughtResponse | QueryResponse; +export type ResponseData = AnswerResponse | ErrorResponse | ActionResponse | SideEffectResponse | ThoughtResponse | TitleResponse | QueryResponse; declare function executeJsCode(code: string, { throwOnSideEffect }: { throwOnSideEffect: boolean; }): Promise; diff --git a/public/panels/freestyler/FreestylerAgent.js b/public/panels/freestyler/FreestylerAgent.js index 275a0b231..52f61b449 100644 --- a/public/panels/freestyler/FreestylerAgent.js +++ b/public/panels/freestyler/FreestylerAgent.js @@ -22,18 +22,11 @@ The user selected a DOM element in the browser's DevTools and sends a query abou * When presenting solutions, clearly distinguish between the primary cause and contributing factors. * Please answer only if you are sure about the answer. Otherwise, explain why you're not able to answer. * When answering, always consider MULTIPLE possible solutions. +* Use \`window.getComputedStyle\` to gather **rendered** styles and make sure that you take the distinction between authored styles and computed styles into account. +* **CRITICAL** Use \`window.getComputedStyle\` ALWAYS with property access, like \`window.getComputedStyle($0.parentElement)['color']\`. * **CRITICAL** Never assume a selector for the elements unless you verified your knowledge. -* **Prioritize Modern Layout Techniques:** Whenever possible, favor CSS Grid and Flexbox for layout solutions. Avoid using \`position: absolute\` unless it's absolutely necessary or specifically requested by the user. -* Utilize \`window.getComputedStyle\` to gather **rendered** styles and make sure that you take the distinction between authored styles and computed styles into account. -* While giving suggestions, consider that \`setElementStyles\` function is not available in user's environment. -* **CRITICAL** Use \`window.getComputedStyle\` ALWAYS with property access, like \`window.getComputedStyle($0.parentElement)['color']\` * **CRITICAL** Consider that \`data\` variable from the previous ACTION blocks are not available in a different ACTION block. -# Abstract rules -P = "problem" -multilevel(P) = p₁ v p₂ v p₃ ... pₙ -P ∈ multilevel(P) → collect_data_for(p₁, p₂, p₃, ... pₙ) - # Instructions You are going to answer to the query in these steps: * THOUGHT @@ -112,6 +105,7 @@ FIXABLE: true export const FIX_THIS_ISSUE_PROMPT = 'Fix this issue using JavaScript code execution'; export var ResponseType; (function (ResponseType) { + ResponseType["TITLE"] = "title"; ResponseType["THOUGHT"] = "thought"; ResponseType["ACTION"] = "action"; ResponseType["SIDE_EFFECT"] = "side-effect"; @@ -119,21 +113,21 @@ export var ResponseType; ResponseType["ERROR"] = "error"; ResponseType["QUERYING"] = "querying"; })(ResponseType || (ResponseType = {})); -// TODO: this should use the current execution context pased on the -// node. async function executeJsCode(code, { throwOnSideEffect }) { - const target = UI.Context.Context.instance().flavor(SDK.Target.Target); + const selectedNode = UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode); + const target = selectedNode?.domModel().target() ?? UI.Context.Context.instance().flavor(SDK.Target.Target); if (!target) { throw new Error('Target is not found for executing code'); } const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel); - const runtimeModel = target.model(SDK.RuntimeModel.RuntimeModel); - const pageAgent = target.pageAgent(); - if (!resourceTreeModel?.mainFrame) { + const frameId = selectedNode?.frameId() ?? resourceTreeModel?.mainFrame?.id; + if (!frameId) { throw new Error('Main frame is not found for executing code'); } + const runtimeModel = target.model(SDK.RuntimeModel.RuntimeModel); + const pageAgent = target.pageAgent(); // This returns previously created world if it exists for the frame. - const { executionContextId } = await pageAgent.invoke_createIsolatedWorld({ frameId: resourceTreeModel.mainFrame.id, worldName: FREESTYLER_WORLD_NAME }); + const { executionContextId } = await pageAgent.invoke_createIsolatedWorld({ frameId, worldName: FREESTYLER_WORLD_NAME }); const executionContext = runtimeModel?.executionContext(executionContextId); if (!executionContext) { throw new Error('Execution context is not found for executing code'); @@ -284,17 +278,18 @@ export class FreestylerAgent { get chatHistoryForTesting() { return this.#getHistoryEntry; } - async #aidaFetch(request) { + async #aidaFetch(request, options) { + let rawResponse = undefined; let response = ''; let rpcId; - for await (const lastResult of this.#aidaClient.fetch(request)) { - response = lastResult.explanation; - rpcId = lastResult.metadata.rpcGlobalId ?? rpcId; - if (lastResult.metadata.attributionMetadata?.some(meta => meta.attributionAction === Host.AidaClient.RecitationAction.BLOCK)) { + for await (rawResponse of this.#aidaClient.fetch(request, options)) { + response = rawResponse.explanation; + rpcId = rawResponse.metadata.rpcGlobalId ?? rpcId; + if (rawResponse.metadata.attributionMetadata?.some(meta => meta.attributionAction === Host.AidaClient.RecitationAction.BLOCK)) { throw new Error('Attribution action does not allow providing the response'); } } - return { response, rpcId }; + return { response, rpcId, rawResponse }; } async #generateObservation(action, { throwOnSideEffect, confirmExecJs: confirm, }) { const actionExpression = `{ @@ -340,7 +335,7 @@ export class FreestylerAgent { } } static async describeElement(element) { - let output = `\n* Its selector is \`${element.simpleSelector()}\``; + let output = `* Its selector is \`${element.simpleSelector()}\``; const childNodes = await element.getChildNodesPromise(); if (childNodes) { const textChildNodes = childNodes.filter(childNode => childNode.nodeType() === Node.TEXT_NODE); @@ -408,9 +403,10 @@ export class FreestylerAgent { #runId = 0; async *run(query, options) { const structuredLog = []; - query = `${options.selectedElement ? - `# Inspected element\n${await FreestylerAgent.describeElement(options.selectedElement)}\n\n# User request\n\n` : - ''}QUERY: ${query}`; + const elementEnchantmentQuery = options.selectedElement ? + `# Inspected element\n\n${await FreestylerAgent.describeElement(options.selectedElement)}\n\n# User request\n\n` : + ''; + query = `${elementEnchantmentQuery}QUERY: ${query}`; const currentRunId = ++this.#runId; options.signal?.addEventListener('abort', () => { this.#chatHistory.delete(currentRunId); @@ -428,14 +424,21 @@ export class FreestylerAgent { }); let response; let rpcId; + let rawResponse; try { - const fetchResult = await this.#aidaFetch(request); + const fetchResult = await this.#aidaFetch(request, { signal: options.signal }); response = fetchResult.response; rpcId = fetchResult.rpcId; + rawResponse = fetchResult.rawResponse; } catch (err) { debugLog('Error calling the AIDA API', err); - if (options.signal?.aborted) { + if (err instanceof Host.AidaClient.AidaAbortError) { + yield { + type: ResponseType.ERROR, + error: "abort" /* ErrorType.ABORT */, + rpcId, + }; break; } yield { @@ -448,7 +451,11 @@ export class FreestylerAgent { if (options.signal?.aborted) { break; } - debugLog(`Iteration: ${i}`, 'Request', request, 'Response', response); + debugLog({ + iteration: i, + request, + response: rawResponse, + }); structuredLog.push({ request: structuredClone(request), response, @@ -473,6 +480,13 @@ export class FreestylerAgent { // since the answer is not based on the observation resulted from // the action. if (action) { + if (title) { + yield { + type: ResponseType.TITLE, + title, + rpcId, + }; + } if (thought) { addToHistory(`THOUGHT: ${thought} TITLE: ${title} @@ -482,7 +496,6 @@ STOP`); yield { type: ResponseType.THOUGHT, thought, - title, rpcId, }; } diff --git a/public/panels/freestyler/FreestylerAgent.js.map b/public/panels/freestyler/FreestylerAgent.js.map index 891f9130b..41f0a100c 100644 --- a/public/panels/freestyler/FreestylerAgent.js.map +++ b/public/panels/freestyler/FreestylerAgent.js.map @@ -1 +1 @@ -{"version":3,"file":"FreestylerAgent.js","sourceRoot":"","sources":["../../../../../../front_end/panels/freestyler/FreestylerAgent.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as Host from '../../core/host/host.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport {ChangeManager} from './ChangeManager.js';\nimport {ExtensionScope, FREESTYLER_WORLD_NAME} from './ExtensionScope.js';\nimport {ExecutionError, FreestylerEvaluateAction, SideEffectError} from './FreestylerEvaluateAction.js';\n\n/* clang-format off */\nconst preamble = `You are the most advanced CSS debugging assistant integrated into Chrome DevTools.\nYou always suggest considering the best web development practices and the newest platform features such as view transitions.\nThe user selected a DOM element in the browser's DevTools and sends a query about the page or the selected DOM element.\n\n# Considerations\n* After applying a fix, please ask the user to confirm if the fix worked or not.\n* Meticulously investigate all potential causes for the observed behavior before moving on. Gather comprehensive information about the element's parent, siblings, children, and any overlapping elements, paying close attention to properties that are likely relevant to the query.\n* Avoid making assumptions without sufficient evidence, and always seek further clarification if needed.\n* Always explore multiple possible explanations for the observed behavior before settling on a conclusion.\n* When presenting solutions, clearly distinguish between the primary cause and contributing factors.\n* Please answer only if you are sure about the answer. Otherwise, explain why you're not able to answer.\n* When answering, always consider MULTIPLE possible solutions.\n* **CRITICAL** Never assume a selector for the elements unless you verified your knowledge.\n* **Prioritize Modern Layout Techniques:** Whenever possible, favor CSS Grid and Flexbox for layout solutions. Avoid using \\`position: absolute\\` unless it's absolutely necessary or specifically requested by the user.\n* Utilize \\`window.getComputedStyle\\` to gather **rendered** styles and make sure that you take the distinction between authored styles and computed styles into account.\n* While giving suggestions, consider that \\`setElementStyles\\` function is not available in user's environment.\n* **CRITICAL** Use \\`window.getComputedStyle\\` ALWAYS with property access, like \\`window.getComputedStyle($0.parentElement)['color']\\`\n* **CRITICAL** Consider that \\`data\\` variable from the previous ACTION blocks are not available in a different ACTION block.\n\n# Abstract rules\nP = \"problem\"\nmultilevel(P) = p₁ v p₂ v p₃ ... pₙ\nP ∈ multilevel(P) → collect_data_for(p₁, p₂, p₃, ... pₙ)\n\n# Instructions\nYou are going to answer to the query in these steps:\n* THOUGHT\n* TITLE\n* ACTION\n* ANSWER\n* FIXABLE\nUse THOUGHT to explain why you take the ACTION. Use TITLE to provide a short summary of the thought.\nUse ACTION to evaluate JavaScript code on the page to gather all the data needed to answer the query and put it inside the data variable - then return STOP.\nYou have access to a special $0 variable referencing the current element in the scope of the JavaScript code.\nOBSERVATION will be the result of running the JS code on the page.\nAfter that, you can answer the question with ANSWER or run another ACTION query.\nPlease run ACTION again if the information you received is not enough to answer the query.\nPlease answer only if you are sure about the answer. Otherwise, explain why you're not able to answer.\nWhen answering, remember to consider CSS concepts such as the CSS cascade, explicit and implicit stacking contexts and various CSS layout types.\nWhen answering, always consider MULTIPLE possible solutions.\nAfter the ANSWER, output FIXABLE: true if the user request needs a fix using JavaScript or Web APIs and it has not been fixed previously.\n\nIf you need to set styles on an HTML element, always call the \\`async setElementStyles(el: Element, styles: object)\\` function.\n\n## Example session\n\nQUERY: Why am I not able to see the popup in this case?\n\nTHOUGHT: There are a few reasons why a popup might not be visible. It could be related to its positioning, its z-index, its display property, or overlapping elements. Let's gather information about these properties for the popup, its parent, and any potentially overlapping elements.\nTITLE: Analyzing popup, container, and overlaps\nACTION\nconst computedStyles = window.getComputedStyle($0);\nconst parentComputedStyles = window.getComputedStyle($0.parentElement);\nconst data = {\n numberOfChildren: $0.children.length,\n numberOfSiblings: $0.parentElement.children.length,\n hasPreviousSibling: !!$0.previousElementSibling,\n hasNextSibling: !!$0.nextElementSibling,\n elementStyles: {\n display: computedStyles['display'],\n visibility: computedStyles['visibility'],\n position: computedStyles['position'],\n clipPath: computedStyles['clip-path'],\n zIndex: computedStyles['z-index']\n },\n parentStyles: {\n display: parentComputedStyles['display'],\n visibility: parentComputedStyles['visibility'],\n position: parentComputedStyles['position'],\n clipPath: parentComputedStyles['clip-path'],\n zIndex: parentComputedStyles['z-index']\n },\n overlappingElements: Array.from(document.querySelectorAll('*'))\n .filter(el => {\n const rect = el.getBoundingClientRect();\n const popupRect = $0.getBoundingClientRect();\n return (\n el !== $0 &&\n rect.left < popupRect.right &&\n rect.right > popupRect.left &&\n rect.top < popupRect.bottom &&\n rect.bottom > popupRect.top\n );\n })\n .map(el => ({\n tagName: el.tagName,\n id: el.id,\n className: el.className,\n zIndex: window.getComputedStyle(el)['z-index']\n }))\n};\nSTOP\n\nOBSERVATION: {\"elementStyles\":{\"display\":\"block\",\"visibility\":\"visible\",\"position\":\"absolute\",\"zIndex\":\"3\",\"opacity\":\"1\"},\"parentStyles\":{\"display\":\"block\",\"visibility\":\"visible\",\"position\":\"relative\",\"zIndex\":\"1\",\"opacity\":\"1\"},\"overlappingElements\":[{\"tagName\":\"HTML\",\"id\":\"\",\"className\":\"\",\"zIndex\":\"auto\"},{\"tagName\":\"BODY\",\"id\":\"\",\"className\":\"\",\"zIndex\":\"auto\"},{\"tagName\":\"DIV\",\"id\":\"\",\"className\":\"container\",\"zIndex\":\"auto\"},{\"tagName\":\"DIV\",\"id\":\"\",\"className\":\"background\",\"zIndex\":\"2\"}]}\"\n\nANSWER: Even though the popup itself has a z-index of 3, its parent container has position: relative and z-index: 1. This creates a new stacking context for the popup. Because the \"background\" div has a z-index of 2, which is higher than the stacking context of the popup, it is rendered on top, obscuring the popup.\nFIXABLE: true\n`;\n/* clang-format on */\n\nexport const FIX_THIS_ISSUE_PROMPT = 'Fix this issue using JavaScript code execution';\n\nexport enum ResponseType {\n THOUGHT = 'thought',\n ACTION = 'action',\n SIDE_EFFECT = 'side-effect',\n ANSWER = 'answer',\n ERROR = 'error',\n QUERYING = 'querying',\n}\n\nexport interface AnswerResponse {\n type: ResponseType.ANSWER;\n text: string;\n rpcId?: number;\n fixable: boolean;\n}\n\nexport const enum ErrorType {\n UNKNOWN = 'unknown',\n MAX_STEPS = 'max-steps',\n}\n\nexport interface ErrorResponse {\n type: ResponseType.ERROR;\n error: ErrorType;\n rpcId?: number;\n}\n\nexport interface ThoughtResponse {\n type: ResponseType.THOUGHT;\n thought: string;\n title?: string;\n rpcId?: number;\n}\n\nexport interface SideEffectResponse {\n type: ResponseType.SIDE_EFFECT;\n code: string;\n confirm: (confirm: boolean) => void;\n rpcId?: number;\n}\n\nexport interface ActionResponse {\n type: ResponseType.ACTION;\n code: string;\n output: string;\n canceled: boolean;\n rpcId?: number;\n}\n\nexport interface QueryResponse {\n type: ResponseType.QUERYING;\n}\n\nexport type ResponseData = AnswerResponse|ErrorResponse|ActionResponse|SideEffectResponse|ThoughtResponse|QueryResponse;\n\n// TODO: this should use the current execution context pased on the\n// node.\nasync function executeJsCode(code: string, {throwOnSideEffect}: {throwOnSideEffect: boolean}): Promise {\n const target = UI.Context.Context.instance().flavor(SDK.Target.Target);\n if (!target) {\n throw new Error('Target is not found for executing code');\n }\n\n const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel);\n const runtimeModel = target.model(SDK.RuntimeModel.RuntimeModel);\n const pageAgent = target.pageAgent();\n if (!resourceTreeModel?.mainFrame) {\n throw new Error('Main frame is not found for executing code');\n }\n\n // This returns previously created world if it exists for the frame.\n const {executionContextId} = await pageAgent.invoke_createIsolatedWorld(\n {frameId: resourceTreeModel.mainFrame.id, worldName: FREESTYLER_WORLD_NAME});\n const executionContext = runtimeModel?.executionContext(executionContextId);\n if (!executionContext) {\n throw new Error('Execution context is not found for executing code');\n }\n\n try {\n return await FreestylerEvaluateAction.execute(code, executionContext, {throwOnSideEffect});\n } catch (err) {\n if (err instanceof ExecutionError) {\n return `Error: ${err.message}`;\n }\n\n throw err;\n }\n}\n\ntype HistoryChunk = {\n text: string,\n entity: Host.AidaClient.Entity,\n};\n\nconst MAX_STEPS = 10;\nconst MAX_OBSERVATION_BYTE_LENGTH = 25_000;\n\ntype CreateExtensionScopeFunction = (changes: ChangeManager) => {\n install(): Promise, uninstall(): Promise,\n};\n\ntype AgentOptions = {\n aidaClient: Host.AidaClient.AidaClient,\n changeManager?: ChangeManager,\n confirmSideEffectForTest?: typeof Promise.withResolvers,\n serverSideLoggingEnabled?: boolean,\n createExtensionScope?: CreateExtensionScopeFunction,\n execJs?: typeof executeJsCode,\n};\n\ninterface AidaRequestOptions {\n input: string;\n preamble?: string;\n chatHistory?: Host.AidaClient.Chunk[];\n /**\n * @default false\n */\n serverSideLoggingEnabled?: boolean;\n sessionId?: string;\n}\n\n/**\n * One agent instance handles one conversation. Create a new agent\n * instance for a new conversation.\n */\nexport class FreestylerAgent {\n static buildRequest(opts: AidaRequestOptions): Host.AidaClient.AidaRequest {\n const config = Common.Settings.Settings.instance().getHostConfig();\n const request: Host.AidaClient.AidaRequest = {\n input: opts.input,\n preamble: opts.preamble,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n chat_history: opts.chatHistory,\n client: Host.AidaClient.CLIENT_NAME,\n options: {\n temperature: config.devToolsFreestylerDogfood?.temperature ?? 0,\n model_id: config.devToolsFreestylerDogfood?.modelId ?? undefined,\n },\n metadata: {\n // TODO: disable logging based on query params.\n disable_user_content_logging: !(opts.serverSideLoggingEnabled ?? false),\n string_session_id: opts.sessionId,\n user_tier: Host.AidaClient.convertToUserTierEnum(config.devToolsFreestylerDogfood?.userTier),\n },\n // eslint-disable-next-line @typescript-eslint/naming-convention\n functionality_type: Host.AidaClient.FunctionalityType.CHAT,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n client_feature: Host.AidaClient.ClientFeature.CHROME_FREESTYLER,\n };\n return request;\n }\n\n static parseResponse(response: string):\n {thought?: string, title?: string, action?: string, answer?: string, fixable: boolean} {\n const lines = response.split('\\n');\n let thought: string|undefined;\n let title: string|undefined;\n let action: string|undefined;\n let answer: string|undefined;\n let fixable = false;\n let i = 0;\n const isInstructionStart = (line: string): boolean => {\n const trimmed = line.trim();\n return trimmed.startsWith('THOUGHT:') || trimmed.startsWith('OBSERVATION:') || trimmed.startsWith('TITLE:') ||\n trimmed.startsWith('ACTION') || trimmed.startsWith('ANSWER:') || trimmed.startsWith('FIXABLE:');\n };\n while (i < lines.length) {\n const trimmed = lines[i].trim();\n if (trimmed.startsWith('THOUGHT:') && !thought) {\n // TODO: multiline thoughts.\n thought = trimmed.substring('THOUGHT:'.length).trim();\n i++;\n } else if (trimmed.startsWith('TITLE:')) {\n title = trimmed.substring('TITLE:'.length).trim();\n i++;\n } else if (trimmed.startsWith('ACTION') && !action) {\n const actionLines = [];\n i++;\n while (i < lines.length) {\n if (lines[i].trim() === 'STOP') {\n i++;\n break;\n }\n if (isInstructionStart(lines[i])) {\n break;\n }\n // Sometimes the code block is in the form of \"`````\\njs\\n{code}`````\"\n if (lines[i].trim() !== 'js') {\n actionLines.push(lines[i]);\n }\n i++;\n }\n // TODO: perhaps trying to parse with a Markdown parser would\n // yield more reliable results.\n action = actionLines.join('\\n').replaceAll('```', '').replaceAll('``', '').trim();\n } else if (trimmed.startsWith('ANSWER:') && !answer) {\n const answerLines = [\n trimmed.substring('ANSWER:'.length).trim(),\n ];\n let j = i + 1;\n while (j < lines.length) {\n const line = lines[j].trim();\n if (isInstructionStart(line)) {\n break;\n }\n answerLines.push(lines[j]);\n j++;\n }\n answer = answerLines.join('\\n').trim();\n i = j;\n } else if (trimmed.startsWith('FIXABLE: true')) {\n fixable = true;\n i++;\n } else {\n i++;\n }\n }\n // If we could not parse the parts, consider the response to be an\n // answer.\n if (!answer && !thought && !action) {\n answer = response;\n }\n return {thought, title, action, answer, fixable};\n }\n\n #aidaClient: Host.AidaClient.AidaClient;\n #chatHistory: Map = new Map();\n #serverSideLoggingEnabled: boolean;\n\n #execJs: typeof executeJsCode;\n\n #confirmSideEffect: typeof Promise.withResolvers;\n readonly #sessionId = crypto.randomUUID();\n #changes: ChangeManager;\n #createExtensionScope: CreateExtensionScopeFunction;\n\n constructor(opts: AgentOptions) {\n this.#aidaClient = opts.aidaClient;\n this.#changes = opts.changeManager || new ChangeManager();\n this.#execJs = opts.execJs ?? executeJsCode;\n this.#createExtensionScope = opts.createExtensionScope ?? ((changes: ChangeManager) => {\n return new ExtensionScope(changes);\n });\n this.#serverSideLoggingEnabled = opts.serverSideLoggingEnabled ?? false;\n this.#confirmSideEffect = opts.confirmSideEffectForTest ?? (() => Promise.withResolvers());\n SDK.TargetManager.TargetManager.instance().addModelListener(\n SDK.ResourceTreeModel.ResourceTreeModel, SDK.ResourceTreeModel.Events.PrimaryPageChanged,\n this.onPrimaryPageChanged, this);\n }\n\n onPrimaryPageChanged(): void {\n void this.#changes.clear();\n }\n\n get #getHistoryEntry(): Array {\n return [...this.#chatHistory.values()].flat();\n }\n\n get chatHistoryForTesting(): Array {\n return this.#getHistoryEntry;\n }\n\n async #aidaFetch(request: Host.AidaClient.AidaRequest): Promise<{response: string, rpcId: number|undefined}> {\n let response = '';\n let rpcId;\n for await (const lastResult of this.#aidaClient.fetch(request)) {\n response = lastResult.explanation;\n rpcId = lastResult.metadata.rpcGlobalId ?? rpcId;\n if (lastResult.metadata.attributionMetadata?.some(\n meta => meta.attributionAction === Host.AidaClient.RecitationAction.BLOCK)) {\n throw new Error('Attribution action does not allow providing the response');\n }\n }\n\n return {response, rpcId};\n }\n\n async #generateObservation(\n action: string,\n {\n throwOnSideEffect,\n confirmExecJs: confirm,\n }: {\n throwOnSideEffect: boolean,\n confirmExecJs?: Promise,\n },\n ): Promise<{\n observation: string,\n sideEffect: boolean,\n canceled: boolean,\n }> {\n const actionExpression = `{\n const scope = {$0, $1, getEventListeners};\n with (scope) {\n ${action}\n ;((typeof data !== \"undefined\") ? data : undefined)\n }\n }`;\n try {\n const runConfirmed = await confirm ?? Promise.resolve(true);\n if (!runConfirmed) {\n return {\n observation: 'Error: User denied code execution with side effects.',\n sideEffect: false,\n canceled: true,\n };\n }\n const result = await this.#execJs(\n actionExpression,\n {throwOnSideEffect},\n );\n const byteCount = Platform.StringUtilities.countWtf8Bytes(result);\n if (byteCount > MAX_OBSERVATION_BYTE_LENGTH) {\n throw new Error('Output exceeded the maximum allowed length.');\n }\n return {\n observation: result,\n sideEffect: false,\n canceled: false,\n };\n } catch (error) {\n if (error instanceof SideEffectError) {\n return {\n observation: error.message,\n sideEffect: true,\n canceled: false,\n };\n }\n\n return {\n observation: `Error: ${error.message}`,\n sideEffect: false,\n canceled: false,\n };\n }\n }\n\n static async describeElement(element: SDK.DOMModel.DOMNode): Promise {\n let output = `\\n* Its selector is \\`${element.simpleSelector()}\\``;\n const childNodes = await element.getChildNodesPromise();\n if (childNodes) {\n const textChildNodes = childNodes.filter(childNode => childNode.nodeType() === Node.TEXT_NODE);\n const elementChildNodes = childNodes.filter(childNode => childNode.nodeType() === Node.ELEMENT_NODE);\n switch (elementChildNodes.length) {\n case 0:\n output += '\\n* It doesn\\'t have any child element nodes';\n break;\n case 1:\n output += `\\n* It only has 1 child element node: \\`${elementChildNodes[0].simpleSelector()}\\``;\n break;\n default:\n output += `\\n* It has ${elementChildNodes.length} child element nodes: ${\n elementChildNodes.map(node => `\\`${node.simpleSelector()}\\``).join(', ')}`;\n }\n\n switch (textChildNodes.length) {\n case 0:\n output += '\\n* It doesn\\'t have any child text nodes';\n break;\n case 1:\n output += '\\n* It only has 1 child text node';\n break;\n default:\n output += `\\n* It has ${textChildNodes.length} child text nodes`;\n }\n }\n\n if (element.nextSibling) {\n const elementOrNodeElementNodeText =\n element.nextSibling.nodeType() === Node.ELEMENT_NODE ? 'an element' : 'a non element';\n output += `\\n* It has a next sibling and it is ${elementOrNodeElementNodeText} node`;\n }\n\n if (element.previousSibling) {\n const elementOrNodeElementNodeText =\n element.previousSibling.nodeType() === Node.ELEMENT_NODE ? 'an element' : 'a non element';\n output += `\\n* It has a previous sibling and it is ${elementOrNodeElementNodeText} node`;\n }\n\n const parentNode = element.parentNode;\n if (parentNode) {\n const parentChildrenNodes = await parentNode.getChildNodesPromise();\n output += `\\n* Its parent's selector is \\`${parentNode.simpleSelector()}\\``;\n if (parentChildrenNodes) {\n const childElementNodes =\n parentChildrenNodes.filter(siblingNode => siblingNode.nodeType() === Node.ELEMENT_NODE);\n switch (childElementNodes.length) {\n case 0:\n break;\n case 1:\n output += '\\n* Its parent has only 1 child element node';\n break;\n default:\n output += `\\n* Its parent has ${childElementNodes.length} child element nodes: ${\n childElementNodes.map(node => `\\`${node.simpleSelector()}\\``).join(', ')}`;\n break;\n }\n\n const siblingTextNodes = parentChildrenNodes.filter(siblingNode => siblingNode.nodeType() === Node.TEXT_NODE);\n switch (siblingTextNodes.length) {\n case 0:\n break;\n case 1:\n output += '\\n* Its parent has only 1 child text node';\n break;\n default:\n output += `\\n* Its parent has ${siblingTextNodes.length} child text nodes: ${\n siblingTextNodes.map(node => `\\`${node.simpleSelector()}\\``).join(', ')}`;\n break;\n }\n }\n }\n\n return output;\n }\n\n #runId = 0;\n async * run(query: string, options: {\n signal?: AbortSignal, selectedElement: SDK.DOMModel.DOMNode|null, isFixQuery: boolean,\n }): AsyncGenerator {\n const structuredLog = [];\n query = `${\n options.selectedElement ?\n `# Inspected element\\n${\n await FreestylerAgent.describeElement(options.selectedElement)}\\n\\n# User request\\n\\n` :\n ''}QUERY: ${query}`;\n const currentRunId = ++this.#runId;\n\n options.signal?.addEventListener('abort', () => {\n this.#chatHistory.delete(currentRunId);\n });\n\n for (let i = 0; i < MAX_STEPS; i++) {\n yield {\n type: ResponseType.QUERYING,\n };\n\n const request = FreestylerAgent.buildRequest({\n input: query,\n preamble,\n chatHistory: this.#chatHistory.size ? this.#getHistoryEntry : undefined,\n serverSideLoggingEnabled: this.#serverSideLoggingEnabled,\n sessionId: this.#sessionId,\n });\n let response: string;\n let rpcId: number|undefined;\n try {\n const fetchResult = await this.#aidaFetch(request);\n response = fetchResult.response;\n rpcId = fetchResult.rpcId;\n } catch (err) {\n debugLog('Error calling the AIDA API', err);\n\n if (options.signal?.aborted) {\n break;\n }\n\n yield {\n type: ResponseType.ERROR,\n error: ErrorType.UNKNOWN,\n rpcId,\n };\n break;\n }\n\n if (options.signal?.aborted) {\n break;\n }\n\n debugLog(`Iteration: ${i}`, 'Request', request, 'Response', response);\n structuredLog.push({\n request: structuredClone(request),\n response,\n });\n\n const addToHistory = (text: string): void => {\n this.#chatHistory.set(currentRunId, [\n ...currentRunEntries,\n {\n text: query,\n entity: Host.AidaClient.Entity.USER,\n },\n {\n text,\n entity: Host.AidaClient.Entity.SYSTEM,\n },\n ]);\n };\n const currentRunEntries = this.#chatHistory.get(currentRunId) ?? [];\n const {thought, title, action, answer, fixable} = FreestylerAgent.parseResponse(response);\n // Sometimes the answer will follow an action and a thought. In\n // that case, we only use the action and the thought (if present)\n // since the answer is not based on the observation resulted from\n // the action.\n if (action) {\n if (thought) {\n addToHistory(`THOUGHT: ${thought}\nTITLE: ${title}\nACTION\n${action}\nSTOP`);\n yield {\n type: ResponseType.THOUGHT,\n thought,\n title,\n rpcId,\n };\n } else {\n addToHistory(`ACTION\n${action}\nSTOP`);\n }\n debugLog(`Action to execute: ${action}`);\n const scope = this.#createExtensionScope(this.#changes);\n await scope.install();\n try {\n let result = await this.#generateObservation(action, {throwOnSideEffect: !options.isFixQuery});\n debugLog(`Action result: ${JSON.stringify(result)}`);\n if (result.sideEffect) {\n const sideEffectConfirmationPromiseWithResolvers = this.#confirmSideEffect();\n if (isDebugMode()) {\n window.dispatchEvent(new CustomEvent(\n 'freestylersideeffect', {detail: {confirm: sideEffectConfirmationPromiseWithResolvers.resolve}}));\n }\n\n yield {\n type: ResponseType.SIDE_EFFECT,\n code: action,\n confirm: sideEffectConfirmationPromiseWithResolvers.resolve,\n rpcId,\n };\n\n result = await this.#generateObservation(action, {\n throwOnSideEffect: false,\n confirmExecJs: sideEffectConfirmationPromiseWithResolvers.promise,\n });\n }\n yield {\n type: ResponseType.ACTION,\n code: action,\n output: result.observation,\n canceled: result.canceled,\n rpcId,\n };\n\n query = `OBSERVATION: ${result.observation}`;\n } finally {\n await scope.uninstall();\n }\n } else if (answer) {\n addToHistory(`ANSWER: ${answer}`);\n yield {\n type: ResponseType.ANSWER,\n text: answer,\n rpcId,\n fixable,\n };\n break;\n } else {\n addToHistory(response);\n yield {\n type: ResponseType.ERROR,\n error: ErrorType.UNKNOWN,\n rpcId,\n };\n break;\n }\n\n if (i === MAX_STEPS - 1) {\n yield {\n type: ResponseType.ERROR,\n error: ErrorType.MAX_STEPS,\n };\n break;\n }\n }\n if (isDebugMode()) {\n localStorage.setItem('freestylerStructuredLog', JSON.stringify(structuredLog));\n window.dispatchEvent(new CustomEvent('freestylerdone'));\n }\n }\n}\n\nfunction isDebugMode(): boolean {\n return Boolean(localStorage.getItem('debugFreestylerEnabled'));\n}\n\nfunction debugLog(...log: unknown[]): void {\n if (!isDebugMode()) {\n return;\n }\n\n // eslint-disable-next-line no-console\n console.log(...log);\n}\n\nfunction setDebugFreestylerEnabled(enabled: boolean): void {\n if (enabled) {\n localStorage.setItem('debugFreestylerEnabled', 'true');\n } else {\n localStorage.removeItem('debugFreestylerEnabled');\n }\n}\n\n// @ts-ignore\nglobalThis.setDebugFreestylerEnabled = setDebugFreestylerEnabled;\n"]} \ No newline at end of file +{"version":3,"file":"FreestylerAgent.js","sourceRoot":"","sources":["../../../../../../front_end/panels/freestyler/FreestylerAgent.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as Host from '../../core/host/host.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport {ChangeManager} from './ChangeManager.js';\nimport {ExtensionScope, FREESTYLER_WORLD_NAME} from './ExtensionScope.js';\nimport {ExecutionError, FreestylerEvaluateAction, SideEffectError} from './FreestylerEvaluateAction.js';\n\n/* clang-format off */\nconst preamble = `You are the most advanced CSS debugging assistant integrated into Chrome DevTools.\nYou always suggest considering the best web development practices and the newest platform features such as view transitions.\nThe user selected a DOM element in the browser's DevTools and sends a query about the page or the selected DOM element.\n\n# Considerations\n* After applying a fix, please ask the user to confirm if the fix worked or not.\n* Meticulously investigate all potential causes for the observed behavior before moving on. Gather comprehensive information about the element's parent, siblings, children, and any overlapping elements, paying close attention to properties that are likely relevant to the query.\n* Avoid making assumptions without sufficient evidence, and always seek further clarification if needed.\n* Always explore multiple possible explanations for the observed behavior before settling on a conclusion.\n* When presenting solutions, clearly distinguish between the primary cause and contributing factors.\n* Please answer only if you are sure about the answer. Otherwise, explain why you're not able to answer.\n* When answering, always consider MULTIPLE possible solutions.\n* Use \\`window.getComputedStyle\\` to gather **rendered** styles and make sure that you take the distinction between authored styles and computed styles into account.\n* **CRITICAL** Use \\`window.getComputedStyle\\` ALWAYS with property access, like \\`window.getComputedStyle($0.parentElement)['color']\\`.\n* **CRITICAL** Never assume a selector for the elements unless you verified your knowledge.\n* **CRITICAL** Consider that \\`data\\` variable from the previous ACTION blocks are not available in a different ACTION block.\n\n# Instructions\nYou are going to answer to the query in these steps:\n* THOUGHT\n* TITLE\n* ACTION\n* ANSWER\n* FIXABLE\nUse THOUGHT to explain why you take the ACTION. Use TITLE to provide a short summary of the thought.\nUse ACTION to evaluate JavaScript code on the page to gather all the data needed to answer the query and put it inside the data variable - then return STOP.\nYou have access to a special $0 variable referencing the current element in the scope of the JavaScript code.\nOBSERVATION will be the result of running the JS code on the page.\nAfter that, you can answer the question with ANSWER or run another ACTION query.\nPlease run ACTION again if the information you received is not enough to answer the query.\nPlease answer only if you are sure about the answer. Otherwise, explain why you're not able to answer.\nWhen answering, remember to consider CSS concepts such as the CSS cascade, explicit and implicit stacking contexts and various CSS layout types.\nWhen answering, always consider MULTIPLE possible solutions.\nAfter the ANSWER, output FIXABLE: true if the user request needs a fix using JavaScript or Web APIs and it has not been fixed previously.\n\nIf you need to set styles on an HTML element, always call the \\`async setElementStyles(el: Element, styles: object)\\` function.\n\n## Example session\n\nQUERY: Why am I not able to see the popup in this case?\n\nTHOUGHT: There are a few reasons why a popup might not be visible. It could be related to its positioning, its z-index, its display property, or overlapping elements. Let's gather information about these properties for the popup, its parent, and any potentially overlapping elements.\nTITLE: Analyzing popup, container, and overlaps\nACTION\nconst computedStyles = window.getComputedStyle($0);\nconst parentComputedStyles = window.getComputedStyle($0.parentElement);\nconst data = {\n numberOfChildren: $0.children.length,\n numberOfSiblings: $0.parentElement.children.length,\n hasPreviousSibling: !!$0.previousElementSibling,\n hasNextSibling: !!$0.nextElementSibling,\n elementStyles: {\n display: computedStyles['display'],\n visibility: computedStyles['visibility'],\n position: computedStyles['position'],\n clipPath: computedStyles['clip-path'],\n zIndex: computedStyles['z-index']\n },\n parentStyles: {\n display: parentComputedStyles['display'],\n visibility: parentComputedStyles['visibility'],\n position: parentComputedStyles['position'],\n clipPath: parentComputedStyles['clip-path'],\n zIndex: parentComputedStyles['z-index']\n },\n overlappingElements: Array.from(document.querySelectorAll('*'))\n .filter(el => {\n const rect = el.getBoundingClientRect();\n const popupRect = $0.getBoundingClientRect();\n return (\n el !== $0 &&\n rect.left < popupRect.right &&\n rect.right > popupRect.left &&\n rect.top < popupRect.bottom &&\n rect.bottom > popupRect.top\n );\n })\n .map(el => ({\n tagName: el.tagName,\n id: el.id,\n className: el.className,\n zIndex: window.getComputedStyle(el)['z-index']\n }))\n};\nSTOP\n\nOBSERVATION: {\"elementStyles\":{\"display\":\"block\",\"visibility\":\"visible\",\"position\":\"absolute\",\"zIndex\":\"3\",\"opacity\":\"1\"},\"parentStyles\":{\"display\":\"block\",\"visibility\":\"visible\",\"position\":\"relative\",\"zIndex\":\"1\",\"opacity\":\"1\"},\"overlappingElements\":[{\"tagName\":\"HTML\",\"id\":\"\",\"className\":\"\",\"zIndex\":\"auto\"},{\"tagName\":\"BODY\",\"id\":\"\",\"className\":\"\",\"zIndex\":\"auto\"},{\"tagName\":\"DIV\",\"id\":\"\",\"className\":\"container\",\"zIndex\":\"auto\"},{\"tagName\":\"DIV\",\"id\":\"\",\"className\":\"background\",\"zIndex\":\"2\"}]}\"\n\nANSWER: Even though the popup itself has a z-index of 3, its parent container has position: relative and z-index: 1. This creates a new stacking context for the popup. Because the \"background\" div has a z-index of 2, which is higher than the stacking context of the popup, it is rendered on top, obscuring the popup.\nFIXABLE: true\n`;\n/* clang-format on */\n\nexport const FIX_THIS_ISSUE_PROMPT = 'Fix this issue using JavaScript code execution';\n\nexport enum ResponseType {\n TITLE = 'title',\n THOUGHT = 'thought',\n ACTION = 'action',\n SIDE_EFFECT = 'side-effect',\n ANSWER = 'answer',\n ERROR = 'error',\n QUERYING = 'querying',\n}\n\nexport interface AnswerResponse {\n type: ResponseType.ANSWER;\n text: string;\n rpcId?: number;\n fixable: boolean;\n}\n\nexport const enum ErrorType {\n UNKNOWN = 'unknown',\n ABORT = 'abort',\n MAX_STEPS = 'max-steps',\n}\n\nexport interface ErrorResponse {\n type: ResponseType.ERROR;\n error: ErrorType;\n rpcId?: number;\n}\n\nexport interface TitleResponse {\n type: ResponseType.TITLE;\n title: string;\n rpcId?: number;\n}\n\nexport interface ThoughtResponse {\n type: ResponseType.THOUGHT;\n thought: string;\n rpcId?: number;\n}\n\nexport interface SideEffectResponse {\n type: ResponseType.SIDE_EFFECT;\n code: string;\n confirm: (confirm: boolean) => void;\n rpcId?: number;\n}\n\nexport interface ActionResponse {\n type: ResponseType.ACTION;\n code: string;\n output: string;\n canceled: boolean;\n rpcId?: number;\n}\n\nexport interface QueryResponse {\n type: ResponseType.QUERYING;\n}\n\nexport type ResponseData =\n AnswerResponse|ErrorResponse|ActionResponse|SideEffectResponse|ThoughtResponse|TitleResponse|QueryResponse;\n\nasync function executeJsCode(code: string, {throwOnSideEffect}: {throwOnSideEffect: boolean}): Promise {\n const selectedNode = UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);\n const target = selectedNode?.domModel().target() ?? UI.Context.Context.instance().flavor(SDK.Target.Target);\n\n if (!target) {\n throw new Error('Target is not found for executing code');\n }\n\n const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel);\n const frameId = selectedNode?.frameId() ?? resourceTreeModel?.mainFrame?.id;\n\n if (!frameId) {\n throw new Error('Main frame is not found for executing code');\n }\n\n const runtimeModel = target.model(SDK.RuntimeModel.RuntimeModel);\n const pageAgent = target.pageAgent();\n\n // This returns previously created world if it exists for the frame.\n const {executionContextId} = await pageAgent.invoke_createIsolatedWorld({frameId, worldName: FREESTYLER_WORLD_NAME});\n const executionContext = runtimeModel?.executionContext(executionContextId);\n if (!executionContext) {\n throw new Error('Execution context is not found for executing code');\n }\n\n try {\n return await FreestylerEvaluateAction.execute(code, executionContext, {throwOnSideEffect});\n } catch (err) {\n if (err instanceof ExecutionError) {\n return `Error: ${err.message}`;\n }\n\n throw err;\n }\n}\n\ntype HistoryChunk = {\n text: string,\n entity: Host.AidaClient.Entity,\n};\n\nconst MAX_STEPS = 10;\nconst MAX_OBSERVATION_BYTE_LENGTH = 25_000;\n\ntype CreateExtensionScopeFunction = (changes: ChangeManager) => {\n install(): Promise, uninstall(): Promise,\n};\n\ntype AgentOptions = {\n aidaClient: Host.AidaClient.AidaClient,\n changeManager?: ChangeManager,\n confirmSideEffectForTest?: typeof Promise.withResolvers,\n serverSideLoggingEnabled?: boolean,\n createExtensionScope?: CreateExtensionScopeFunction,\n execJs?: typeof executeJsCode,\n};\n\ninterface AidaRequestOptions {\n input: string;\n preamble?: string;\n chatHistory?: Host.AidaClient.Chunk[];\n /**\n * @default false\n */\n serverSideLoggingEnabled?: boolean;\n sessionId?: string;\n}\n\n/**\n * One agent instance handles one conversation. Create a new agent\n * instance for a new conversation.\n */\nexport class FreestylerAgent {\n static buildRequest(opts: AidaRequestOptions): Host.AidaClient.AidaRequest {\n const config = Common.Settings.Settings.instance().getHostConfig();\n const request: Host.AidaClient.AidaRequest = {\n input: opts.input,\n preamble: opts.preamble,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n chat_history: opts.chatHistory,\n client: Host.AidaClient.CLIENT_NAME,\n options: {\n temperature: config.devToolsFreestylerDogfood?.temperature ?? 0,\n model_id: config.devToolsFreestylerDogfood?.modelId ?? undefined,\n },\n metadata: {\n // TODO: disable logging based on query params.\n disable_user_content_logging: !(opts.serverSideLoggingEnabled ?? false),\n string_session_id: opts.sessionId,\n user_tier: Host.AidaClient.convertToUserTierEnum(config.devToolsFreestylerDogfood?.userTier),\n },\n // eslint-disable-next-line @typescript-eslint/naming-convention\n functionality_type: Host.AidaClient.FunctionalityType.CHAT,\n // eslint-disable-next-line @typescript-eslint/naming-convention\n client_feature: Host.AidaClient.ClientFeature.CHROME_FREESTYLER,\n };\n return request;\n }\n\n static parseResponse(response: string):\n {thought?: string, title?: string, action?: string, answer?: string, fixable: boolean} {\n const lines = response.split('\\n');\n let thought: string|undefined;\n let title: string|undefined;\n let action: string|undefined;\n let answer: string|undefined;\n let fixable = false;\n let i = 0;\n const isInstructionStart = (line: string): boolean => {\n const trimmed = line.trim();\n return trimmed.startsWith('THOUGHT:') || trimmed.startsWith('OBSERVATION:') || trimmed.startsWith('TITLE:') ||\n trimmed.startsWith('ACTION') || trimmed.startsWith('ANSWER:') || trimmed.startsWith('FIXABLE:');\n };\n while (i < lines.length) {\n const trimmed = lines[i].trim();\n if (trimmed.startsWith('THOUGHT:') && !thought) {\n // TODO: multiline thoughts.\n thought = trimmed.substring('THOUGHT:'.length).trim();\n i++;\n } else if (trimmed.startsWith('TITLE:')) {\n title = trimmed.substring('TITLE:'.length).trim();\n i++;\n } else if (trimmed.startsWith('ACTION') && !action) {\n const actionLines = [];\n i++;\n while (i < lines.length) {\n if (lines[i].trim() === 'STOP') {\n i++;\n break;\n }\n if (isInstructionStart(lines[i])) {\n break;\n }\n // Sometimes the code block is in the form of \"`````\\njs\\n{code}`````\"\n if (lines[i].trim() !== 'js') {\n actionLines.push(lines[i]);\n }\n i++;\n }\n // TODO: perhaps trying to parse with a Markdown parser would\n // yield more reliable results.\n action = actionLines.join('\\n').replaceAll('```', '').replaceAll('``', '').trim();\n } else if (trimmed.startsWith('ANSWER:') && !answer) {\n const answerLines = [\n trimmed.substring('ANSWER:'.length).trim(),\n ];\n let j = i + 1;\n while (j < lines.length) {\n const line = lines[j].trim();\n if (isInstructionStart(line)) {\n break;\n }\n answerLines.push(lines[j]);\n j++;\n }\n answer = answerLines.join('\\n').trim();\n i = j;\n } else if (trimmed.startsWith('FIXABLE: true')) {\n fixable = true;\n i++;\n } else {\n i++;\n }\n }\n // If we could not parse the parts, consider the response to be an\n // answer.\n if (!answer && !thought && !action) {\n answer = response;\n }\n return {thought, title, action, answer, fixable};\n }\n\n #aidaClient: Host.AidaClient.AidaClient;\n #chatHistory: Map = new Map();\n #serverSideLoggingEnabled: boolean;\n\n #execJs: typeof executeJsCode;\n\n #confirmSideEffect: typeof Promise.withResolvers;\n readonly #sessionId = crypto.randomUUID();\n #changes: ChangeManager;\n #createExtensionScope: CreateExtensionScopeFunction;\n\n constructor(opts: AgentOptions) {\n this.#aidaClient = opts.aidaClient;\n this.#changes = opts.changeManager || new ChangeManager();\n this.#execJs = opts.execJs ?? executeJsCode;\n this.#createExtensionScope = opts.createExtensionScope ?? ((changes: ChangeManager) => {\n return new ExtensionScope(changes);\n });\n this.#serverSideLoggingEnabled = opts.serverSideLoggingEnabled ?? false;\n this.#confirmSideEffect = opts.confirmSideEffectForTest ?? (() => Promise.withResolvers());\n SDK.TargetManager.TargetManager.instance().addModelListener(\n SDK.ResourceTreeModel.ResourceTreeModel, SDK.ResourceTreeModel.Events.PrimaryPageChanged,\n this.onPrimaryPageChanged, this);\n }\n\n onPrimaryPageChanged(): void {\n void this.#changes.clear();\n }\n\n get #getHistoryEntry(): Array {\n return [...this.#chatHistory.values()].flat();\n }\n\n get chatHistoryForTesting(): Array {\n return this.#getHistoryEntry;\n }\n\n async #aidaFetch(\n request: Host.AidaClient.AidaRequest,\n options?: {signal?: AbortSignal},\n ): Promise<{\n response: string,\n rpcId: number|undefined,\n rawResponse: Host.AidaClient.AidaResponse|undefined,\n }> {\n let rawResponse: Host.AidaClient.AidaResponse|undefined = undefined;\n let response = '';\n let rpcId;\n for await (rawResponse of this.#aidaClient.fetch(request, options)) {\n response = rawResponse.explanation;\n rpcId = rawResponse.metadata.rpcGlobalId ?? rpcId;\n if (rawResponse.metadata.attributionMetadata?.some(\n meta => meta.attributionAction === Host.AidaClient.RecitationAction.BLOCK)) {\n throw new Error('Attribution action does not allow providing the response');\n }\n }\n\n return {response, rpcId, rawResponse};\n }\n\n async #generateObservation(\n action: string,\n {\n throwOnSideEffect,\n confirmExecJs: confirm,\n }: {\n throwOnSideEffect: boolean,\n confirmExecJs?: Promise,\n },\n ): Promise<{\n observation: string,\n sideEffect: boolean,\n canceled: boolean,\n }> {\n const actionExpression = `{\n const scope = {$0, $1, getEventListeners};\n with (scope) {\n ${action}\n ;((typeof data !== \"undefined\") ? data : undefined)\n }\n }`;\n try {\n const runConfirmed = await confirm ?? Promise.resolve(true);\n if (!runConfirmed) {\n return {\n observation: 'Error: User denied code execution with side effects.',\n sideEffect: false,\n canceled: true,\n };\n }\n const result = await this.#execJs(\n actionExpression,\n {throwOnSideEffect},\n );\n const byteCount = Platform.StringUtilities.countWtf8Bytes(result);\n if (byteCount > MAX_OBSERVATION_BYTE_LENGTH) {\n throw new Error('Output exceeded the maximum allowed length.');\n }\n return {\n observation: result,\n sideEffect: false,\n canceled: false,\n };\n } catch (error) {\n if (error instanceof SideEffectError) {\n return {\n observation: error.message,\n sideEffect: true,\n canceled: false,\n };\n }\n\n return {\n observation: `Error: ${error.message}`,\n sideEffect: false,\n canceled: false,\n };\n }\n }\n\n static async describeElement(element: SDK.DOMModel.DOMNode): Promise {\n let output = `* Its selector is \\`${element.simpleSelector()}\\``;\n const childNodes = await element.getChildNodesPromise();\n if (childNodes) {\n const textChildNodes = childNodes.filter(childNode => childNode.nodeType() === Node.TEXT_NODE);\n const elementChildNodes = childNodes.filter(childNode => childNode.nodeType() === Node.ELEMENT_NODE);\n switch (elementChildNodes.length) {\n case 0:\n output += '\\n* It doesn\\'t have any child element nodes';\n break;\n case 1:\n output += `\\n* It only has 1 child element node: \\`${elementChildNodes[0].simpleSelector()}\\``;\n break;\n default:\n output += `\\n* It has ${elementChildNodes.length} child element nodes: ${\n elementChildNodes.map(node => `\\`${node.simpleSelector()}\\``).join(', ')}`;\n }\n\n switch (textChildNodes.length) {\n case 0:\n output += '\\n* It doesn\\'t have any child text nodes';\n break;\n case 1:\n output += '\\n* It only has 1 child text node';\n break;\n default:\n output += `\\n* It has ${textChildNodes.length} child text nodes`;\n }\n }\n\n if (element.nextSibling) {\n const elementOrNodeElementNodeText =\n element.nextSibling.nodeType() === Node.ELEMENT_NODE ? 'an element' : 'a non element';\n output += `\\n* It has a next sibling and it is ${elementOrNodeElementNodeText} node`;\n }\n\n if (element.previousSibling) {\n const elementOrNodeElementNodeText =\n element.previousSibling.nodeType() === Node.ELEMENT_NODE ? 'an element' : 'a non element';\n output += `\\n* It has a previous sibling and it is ${elementOrNodeElementNodeText} node`;\n }\n\n const parentNode = element.parentNode;\n if (parentNode) {\n const parentChildrenNodes = await parentNode.getChildNodesPromise();\n output += `\\n* Its parent's selector is \\`${parentNode.simpleSelector()}\\``;\n if (parentChildrenNodes) {\n const childElementNodes =\n parentChildrenNodes.filter(siblingNode => siblingNode.nodeType() === Node.ELEMENT_NODE);\n switch (childElementNodes.length) {\n case 0:\n break;\n case 1:\n output += '\\n* Its parent has only 1 child element node';\n break;\n default:\n output += `\\n* Its parent has ${childElementNodes.length} child element nodes: ${\n childElementNodes.map(node => `\\`${node.simpleSelector()}\\``).join(', ')}`;\n break;\n }\n\n const siblingTextNodes = parentChildrenNodes.filter(siblingNode => siblingNode.nodeType() === Node.TEXT_NODE);\n switch (siblingTextNodes.length) {\n case 0:\n break;\n case 1:\n output += '\\n* Its parent has only 1 child text node';\n break;\n default:\n output += `\\n* Its parent has ${siblingTextNodes.length} child text nodes: ${\n siblingTextNodes.map(node => `\\`${node.simpleSelector()}\\``).join(', ')}`;\n break;\n }\n }\n }\n\n return output;\n }\n\n #runId = 0;\n async * run(query: string, options: {\n signal?: AbortSignal, selectedElement: SDK.DOMModel.DOMNode|null, isFixQuery: boolean,\n }): AsyncGenerator {\n const structuredLog = [];\n const elementEnchantmentQuery = options.selectedElement ?\n `# Inspected element\\n\\n${\n await FreestylerAgent.describeElement(options.selectedElement)}\\n\\n# User request\\n\\n` :\n '';\n query = `${elementEnchantmentQuery}QUERY: ${query}`;\n const currentRunId = ++this.#runId;\n\n options.signal?.addEventListener('abort', () => {\n this.#chatHistory.delete(currentRunId);\n });\n\n for (let i = 0; i < MAX_STEPS; i++) {\n yield {\n type: ResponseType.QUERYING,\n };\n\n const request = FreestylerAgent.buildRequest({\n input: query,\n preamble,\n chatHistory: this.#chatHistory.size ? this.#getHistoryEntry : undefined,\n serverSideLoggingEnabled: this.#serverSideLoggingEnabled,\n sessionId: this.#sessionId,\n });\n let response: string;\n let rpcId: number|undefined;\n let rawResponse: Host.AidaClient.AidaResponse|undefined;\n try {\n const fetchResult = await this.#aidaFetch(\n request,\n {signal: options.signal},\n );\n response = fetchResult.response;\n rpcId = fetchResult.rpcId;\n rawResponse = fetchResult.rawResponse;\n } catch (err) {\n debugLog('Error calling the AIDA API', err);\n\n if (err instanceof Host.AidaClient.AidaAbortError) {\n yield {\n type: ResponseType.ERROR,\n error: ErrorType.ABORT,\n rpcId,\n };\n break;\n }\n\n yield {\n type: ResponseType.ERROR,\n error: ErrorType.UNKNOWN,\n rpcId,\n };\n break;\n }\n\n if (options.signal?.aborted) {\n break;\n }\n\n debugLog({\n iteration: i,\n request,\n response: rawResponse,\n });\n\n structuredLog.push({\n request: structuredClone(request),\n response,\n });\n\n const addToHistory = (text: string): void => {\n this.#chatHistory.set(currentRunId, [\n ...currentRunEntries,\n {\n text: query,\n entity: Host.AidaClient.Entity.USER,\n },\n {\n text,\n entity: Host.AidaClient.Entity.SYSTEM,\n },\n ]);\n };\n const currentRunEntries = this.#chatHistory.get(currentRunId) ?? [];\n const {thought, title, action, answer, fixable} = FreestylerAgent.parseResponse(response);\n // Sometimes the answer will follow an action and a thought. In\n // that case, we only use the action and the thought (if present)\n // since the answer is not based on the observation resulted from\n // the action.\n if (action) {\n if (title) {\n yield {\n type: ResponseType.TITLE,\n title,\n rpcId,\n };\n }\n\n if (thought) {\n addToHistory(`THOUGHT: ${thought}\nTITLE: ${title}\nACTION\n${action}\nSTOP`);\n yield {\n type: ResponseType.THOUGHT,\n thought,\n rpcId,\n };\n } else {\n addToHistory(`ACTION\n${action}\nSTOP`);\n }\n debugLog(`Action to execute: ${action}`);\n const scope = this.#createExtensionScope(this.#changes);\n await scope.install();\n try {\n let result = await this.#generateObservation(action, {throwOnSideEffect: !options.isFixQuery});\n debugLog(`Action result: ${JSON.stringify(result)}`);\n if (result.sideEffect) {\n const sideEffectConfirmationPromiseWithResolvers = this.#confirmSideEffect();\n if (isDebugMode()) {\n window.dispatchEvent(new CustomEvent(\n 'freestylersideeffect', {detail: {confirm: sideEffectConfirmationPromiseWithResolvers.resolve}}));\n }\n\n yield {\n type: ResponseType.SIDE_EFFECT,\n code: action,\n confirm: sideEffectConfirmationPromiseWithResolvers.resolve,\n rpcId,\n };\n\n result = await this.#generateObservation(action, {\n throwOnSideEffect: false,\n confirmExecJs: sideEffectConfirmationPromiseWithResolvers.promise,\n });\n }\n yield {\n type: ResponseType.ACTION,\n code: action,\n output: result.observation,\n canceled: result.canceled,\n rpcId,\n };\n\n query = `OBSERVATION: ${result.observation}`;\n } finally {\n await scope.uninstall();\n }\n } else if (answer) {\n addToHistory(`ANSWER: ${answer}`);\n yield {\n type: ResponseType.ANSWER,\n text: answer,\n rpcId,\n fixable,\n };\n break;\n } else {\n addToHistory(response);\n yield {\n type: ResponseType.ERROR,\n error: ErrorType.UNKNOWN,\n rpcId,\n };\n break;\n }\n\n if (i === MAX_STEPS - 1) {\n yield {\n type: ResponseType.ERROR,\n error: ErrorType.MAX_STEPS,\n };\n break;\n }\n }\n if (isDebugMode()) {\n localStorage.setItem('freestylerStructuredLog', JSON.stringify(structuredLog));\n window.dispatchEvent(new CustomEvent('freestylerdone'));\n }\n }\n}\n\nfunction isDebugMode(): boolean {\n return Boolean(localStorage.getItem('debugFreestylerEnabled'));\n}\n\nfunction debugLog(...log: unknown[]): void {\n if (!isDebugMode()) {\n return;\n }\n\n // eslint-disable-next-line no-console\n console.log(...log);\n}\n\nfunction setDebugFreestylerEnabled(enabled: boolean): void {\n if (enabled) {\n localStorage.setItem('debugFreestylerEnabled', 'true');\n } else {\n localStorage.removeItem('debugFreestylerEnabled');\n }\n}\n\n// @ts-ignore\nglobalThis.setDebugFreestylerEnabled = setDebugFreestylerEnabled;\n"]} \ No newline at end of file diff --git a/public/panels/freestyler/FreestylerAgent.test.js b/public/panels/freestyler/FreestylerAgent.test.js index 4af9e718a..6411a1f2e 100644 --- a/public/panels/freestyler/FreestylerAgent.test.js +++ b/public/panels/freestyler/FreestylerAgent.test.js @@ -221,7 +221,7 @@ c`; element.simpleSelector.returns('div#myElement'); element.getChildNodesPromise.resolves(null); const result = await FreestylerAgent.describeElement(element); - assert.strictEqual(result, '\n* Its selector is `div#myElement`'); + assert.strictEqual(result, '* Its selector is `div#myElement`'); }); it('should describe an element with child element and text nodes', async () => { const childNodes = [ @@ -240,8 +240,7 @@ c`; element.previousSibling = null; element.parentNode = null; const result = await FreestylerAgent.describeElement(element); - const expectedOutput = ` -* Its selector is \`div#parentElement\` + const expectedOutput = `* Its selector is \`div#parentElement\` * It has 2 child element nodes: \`span.child1\`, \`span.child2\` * It only has 1 child text node`; assert.strictEqual(result, expectedOutput); @@ -267,8 +266,7 @@ c`; element.previousSibling = previousSibling; element.parentNode = parentNode; const result = await FreestylerAgent.describeElement(element); - const expectedOutput = ` -* Its selector is \`div#parentElement\` + const expectedOutput = `* Its selector is \`div#parentElement\` * It has a next sibling and it is an element node * It has a previous sibling and it is a non element node * Its parent's selector is \`div#grandparentElement\` @@ -376,7 +374,7 @@ c`; metadata: { disable_user_content_logging: false, string_session_id: 'sessionId', - user_tier: 1, + user_tier: 2, }, options: { model_id: 'test model', @@ -777,7 +775,6 @@ ANSWER: this is the answer`, { type: Freestyler.ResponseType.THOUGHT, thought: 'I am thinking.', - title: undefined, rpcId: undefined, }, { diff --git a/public/panels/freestyler/FreestylerAgent.test.js.map b/public/panels/freestyler/FreestylerAgent.test.js.map index 379aad76d..7cd57eaa2 100644 --- a/public/panels/freestyler/FreestylerAgent.test.js.map +++ b/public/panels/freestyler/FreestylerAgent.test.js.map @@ -1 +1 @@ -{"version":3,"file":"FreestylerAgent.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/freestyler/FreestylerAgent.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Host from '../../core/host/host.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport {\n describeWithEnvironment,\n getGetHostConfigStub,\n} from '../../testing/EnvironmentHelpers.js';\n\nimport * as Freestyler from './freestyler.js';\n\nconst {FreestylerAgent} = Freestyler;\n\ndescribeWithEnvironment('FreestylerAgent', () => {\n function mockHostConfig(modelId?: string) {\n getGetHostConfigStub({\n devToolsFreestylerDogfood: {\n modelId,\n },\n });\n }\n\n function createExtensionScope() {\n return {\n async install() {\n\n },\n async uninstall() {\n\n },\n };\n }\n describe('parseResponse', () => {\n it('parses a thought', async () => {\n const payload = 'some response';\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(`THOUGHT: ${payload}`),\n {\n action: undefined,\n title: undefined,\n thought: payload,\n answer: undefined,\n fixable: false,\n },\n );\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(` THOUGHT: ${payload}`),\n {\n action: undefined,\n title: undefined,\n thought: payload,\n answer: undefined,\n fixable: false,\n },\n );\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(`Something\\n THOUGHT: ${payload}`),\n {\n action: undefined,\n title: undefined,\n thought: payload,\n answer: undefined,\n fixable: false,\n },\n );\n });\n it('parses a answer', async () => {\n const payload = 'some response';\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(`ANSWER: ${payload}`),\n {\n action: undefined,\n title: undefined,\n thought: undefined,\n answer: payload,\n fixable: false,\n },\n );\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(` ANSWER: ${payload}`),\n {\n action: undefined,\n title: undefined,\n thought: undefined,\n answer: payload,\n fixable: false,\n },\n );\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(`Something\\n ANSWER: ${payload}`),\n {\n action: undefined,\n title: undefined,\n thought: undefined,\n answer: payload,\n fixable: false,\n },\n );\n });\n it('parses a multiline answer', async () => {\n const payload = `a\nb\nc`;\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(`ANSWER: ${payload}`),\n {\n action: undefined,\n title: undefined,\n thought: undefined,\n answer: payload,\n fixable: false,\n },\n );\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(` ANSWER: ${payload}`),\n {\n action: undefined,\n title: undefined,\n thought: undefined,\n answer: payload,\n fixable: false,\n },\n );\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(`Something\\n ANSWER: ${payload}`),\n {\n action: undefined,\n title: undefined,\n thought: undefined,\n answer: payload,\n fixable: false,\n },\n );\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(`ANSWER: ${payload}\\nTHOUGHT: thought`),\n {\n action: undefined,\n title: undefined,\n thought: 'thought',\n answer: payload,\n fixable: false,\n },\n );\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(\n `ANSWER: ${payload}\\nOBSERVATION: observation`,\n ),\n {\n action: undefined,\n title: undefined,\n thought: undefined,\n answer: payload,\n fixable: false,\n },\n );\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(\n `ANSWER: ${payload}\\nACTION\\naction\\nSTOP`,\n ),\n {\n action: 'action',\n title: undefined,\n thought: undefined,\n answer: payload,\n fixable: false,\n },\n );\n });\n it('parses an action', async () => {\n const payload = `const data = {\n someKey: \"value\",\n}`;\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(`ACTION\\n${payload}\\nSTOP`),\n {\n action: payload,\n title: undefined,\n thought: undefined,\n answer: undefined,\n fixable: false,\n },\n );\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(`ACTION\\n${payload}`),\n {\n action: payload,\n title: undefined,\n thought: undefined,\n answer: undefined,\n fixable: false,\n },\n );\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(`ACTION\\n\\n${payload}\\n\\nSTOP`),\n {\n action: payload,\n title: undefined,\n thought: undefined,\n answer: undefined,\n fixable: false,\n },\n );\n\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(`ACTION\\n\\n${payload}\\n\\nANSWER: answer`),\n {\n action: payload,\n title: undefined,\n thought: undefined,\n answer: 'answer',\n fixable: false,\n },\n );\n });\n it('parses a thought and title', async () => {\n const payload = 'some response';\n const title = 'this is the title';\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(`THOUGHT: ${payload}\\nTITLE: ${title}`),\n {\n action: undefined,\n thought: payload,\n title,\n answer: undefined,\n fixable: false,\n },\n );\n });\n\n it('parses an action with backticks in the code', async () => {\n const payload = `const data = {\n someKey: \"value\",\n}`;\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(\n `ACTION\\n\\`\\`\\`\\n${payload}\\n\\`\\`\\`\\nSTOP`,\n ),\n {\n action: payload,\n title: undefined,\n thought: undefined,\n answer: undefined,\n fixable: false,\n },\n );\n });\n\n it('parses an action with 5 backticks in the code and `js` text in the prelude', async () => {\n const payload = `const data = {\n someKey: \"value\",\n}`;\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(\n `ACTION\\n\\`\\`\\`\\`\\`\\njs\\n${payload}\\n\\`\\`\\`\\`\\`\\nSTOP`,\n ),\n {\n action: payload,\n title: undefined,\n thought: undefined,\n answer: undefined,\n fixable: false,\n },\n );\n });\n\n it('parses a thought and an action', async () => {\n const actionPayload = `const data = {\n someKey: \"value\",\n}`;\n const thoughtPayload = 'thought';\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(\n `THOUGHT:${thoughtPayload}\\nACTION\\n${actionPayload}\\nSTOP`,\n ),\n {\n action: actionPayload,\n title: undefined,\n thought: thoughtPayload,\n answer: undefined,\n fixable: false,\n },\n );\n });\n\n it('parses a response as an answer', async () => {\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(\n 'This is also an answer',\n ),\n {\n action: undefined,\n title: undefined,\n thought: undefined,\n answer: 'This is also an answer',\n fixable: false,\n },\n );\n });\n });\n\n describe('describeElement', () => {\n let element: sinon.SinonStubbedInstance;\n\n beforeEach(() => {\n element = sinon.createStubInstance(SDK.DOMModel.DOMNode);\n });\n\n afterEach(() => {\n sinon.restore();\n });\n\n it('should describe an element with no children, siblings, or parent', async () => {\n element.simpleSelector.returns('div#myElement');\n element.getChildNodesPromise.resolves(null);\n\n const result = await FreestylerAgent.describeElement(element);\n\n assert.strictEqual(result, '\\n* Its selector is `div#myElement`');\n });\n\n it('should describe an element with child element and text nodes', async () => {\n const childNodes: sinon.SinonStubbedInstance[] = [\n sinon.createStubInstance(SDK.DOMModel.DOMNode),\n sinon.createStubInstance(SDK.DOMModel.DOMNode),\n sinon.createStubInstance(SDK.DOMModel.DOMNode),\n ];\n childNodes[0].nodeType.returns(Node.ELEMENT_NODE);\n childNodes[0].simpleSelector.returns('span.child1');\n childNodes[1].nodeType.returns(Node.TEXT_NODE);\n childNodes[2].nodeType.returns(Node.ELEMENT_NODE);\n childNodes[2].simpleSelector.returns('span.child2');\n\n element.simpleSelector.returns('div#parentElement');\n element.getChildNodesPromise.resolves(childNodes);\n element.nextSibling = null;\n element.previousSibling = null;\n element.parentNode = null;\n\n const result = await FreestylerAgent.describeElement(element);\n const expectedOutput = `\n* Its selector is \\`div#parentElement\\`\n* It has 2 child element nodes: \\`span.child1\\`, \\`span.child2\\`\n* It only has 1 child text node`;\n\n assert.strictEqual(result, expectedOutput);\n });\n\n it('should describe an element with siblings and a parent', async () => {\n const nextSibling = sinon.createStubInstance(SDK.DOMModel.DOMNode);\n nextSibling.nodeType.returns(Node.ELEMENT_NODE);\n const previousSibling = sinon.createStubInstance(SDK.DOMModel.DOMNode);\n previousSibling.nodeType.returns(Node.TEXT_NODE);\n\n const parentNode = sinon.createStubInstance(SDK.DOMModel.DOMNode);\n parentNode.simpleSelector.returns('div#grandparentElement');\n const parentChildNodes: sinon.SinonStubbedInstance[] = [\n sinon.createStubInstance(SDK.DOMModel.DOMNode),\n sinon.createStubInstance(SDK.DOMModel.DOMNode),\n ];\n parentChildNodes[0].nodeType.returns(Node.ELEMENT_NODE);\n parentChildNodes[0].simpleSelector.returns('span.sibling1');\n parentChildNodes[1].nodeType.returns(Node.TEXT_NODE);\n parentNode.getChildNodesPromise.resolves(parentChildNodes);\n\n element.simpleSelector.returns('div#parentElement');\n element.getChildNodesPromise.resolves(null);\n element.nextSibling = nextSibling;\n element.previousSibling = previousSibling;\n element.parentNode = parentNode;\n\n const result = await FreestylerAgent.describeElement(element);\n const expectedOutput = `\n* Its selector is \\`div#parentElement\\`\n* It has a next sibling and it is an element node\n* It has a previous sibling and it is a non element node\n* Its parent's selector is \\`div#grandparentElement\\`\n* Its parent has only 1 child element node\n* Its parent has only 1 child text node`;\n\n assert.strictEqual(result, expectedOutput);\n });\n });\n\n describe('buildRequest', () => {\n beforeEach(() => {\n sinon.restore();\n });\n\n it('builds a request with a model id', async () => {\n mockHostConfig('test model');\n assert.strictEqual(\n FreestylerAgent.buildRequest({input: 'test input'}).options?.model_id,\n 'test model',\n );\n });\n\n it('builds a request with logging', async () => {\n mockHostConfig('test model');\n assert.strictEqual(\n FreestylerAgent.buildRequest({input: 'test input', serverSideLoggingEnabled: true})\n .metadata?.disable_user_content_logging,\n false,\n );\n });\n\n it('builds a request without logging', async () => {\n mockHostConfig('test model');\n assert.strictEqual(\n FreestylerAgent.buildRequest({input: 'test input', serverSideLoggingEnabled: false})\n .metadata?.disable_user_content_logging,\n true,\n );\n });\n\n it('builds a request with input', async () => {\n mockHostConfig();\n const request = FreestylerAgent.buildRequest({input: 'test input'});\n assert.strictEqual(request.input, 'test input');\n assert.strictEqual(request.preamble, undefined);\n assert.strictEqual(request.chat_history, undefined);\n });\n\n it('builds a request with a sessionId', async () => {\n mockHostConfig();\n const request = FreestylerAgent.buildRequest({input: 'test input', sessionId: 'sessionId'});\n assert.strictEqual(request.metadata?.string_session_id, 'sessionId');\n });\n\n it('builds a request with preamble', async () => {\n mockHostConfig();\n const request = FreestylerAgent.buildRequest({input: 'test input', preamble: 'preamble'});\n assert.strictEqual(request.input, 'test input');\n assert.strictEqual(request.preamble, 'preamble');\n assert.strictEqual(request.chat_history, undefined);\n });\n\n it('builds a request with chat history', async () => {\n mockHostConfig();\n const request = FreestylerAgent.buildRequest({\n input: 'test input',\n chatHistory: [\n {\n text: 'test',\n entity: Host.AidaClient.Entity.USER,\n },\n ],\n });\n assert.strictEqual(request.input, 'test input');\n assert.strictEqual(request.preamble, undefined);\n assert.deepStrictEqual(request.chat_history, [\n {\n text: 'test',\n entity: 1,\n },\n ]);\n });\n\n it('structure matches the snapshot', () => {\n mockHostConfig('test model');\n assert.deepStrictEqual(\n FreestylerAgent.buildRequest({\n input: 'test input',\n preamble: 'preamble',\n chatHistory: [\n {\n text: 'first',\n entity: Host.AidaClient.Entity.UNKNOWN,\n },\n {\n text: 'second',\n entity: Host.AidaClient.Entity.SYSTEM,\n },\n {\n text: 'third',\n entity: Host.AidaClient.Entity.USER,\n },\n ],\n serverSideLoggingEnabled: true,\n sessionId: 'sessionId',\n }),\n {\n input: 'test input',\n client: 'CHROME_DEVTOOLS',\n preamble: 'preamble',\n chat_history: [\n {\n entity: 0,\n text: 'first',\n },\n {\n entity: 2,\n text: 'second',\n },\n {\n entity: 1,\n text: 'third',\n },\n ],\n metadata: {\n disable_user_content_logging: false,\n string_session_id: 'sessionId',\n user_tier: 1,\n },\n options: {\n model_id: 'test model',\n temperature: 0,\n },\n client_feature: 2,\n functionality_type: 1,\n },\n );\n });\n });\n\n describe('run', () => {\n let element: sinon.SinonStubbedInstance;\n beforeEach(() => {\n mockHostConfig();\n element = sinon.createStubInstance(SDK.DOMModel.DOMNode);\n });\n\n function mockAidaClient(\n fetch: () => AsyncGenerator,\n ): Host.AidaClient.AidaClient {\n return {\n fetch,\n registerClientEvent: () => Promise.resolve({}),\n };\n }\n\n describe('side effect handling', () => {\n it('calls confirmSideEffect when the code execution contains a side effect', async () => {\n const promise = Promise.withResolvers();\n const stub = sinon.stub().returns(promise);\n\n let count = 0;\n async function* generateActionAndAnswer() {\n if (count === 0) {\n yield {\n explanation: `ACTION\n $0.style.backgroundColor = 'red'\n STOP`,\n metadata: {},\n completed: true,\n };\n } else {\n yield {\n explanation: 'ANSWER: This is the answer',\n metadata: {},\n completed: true,\n };\n }\n\n count++;\n }\n const execJs =\n sinon.mock().throws(new Freestyler.SideEffectError('EvalError: Possible side-effect in debug-evaluate'));\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateActionAndAnswer),\n createExtensionScope,\n confirmSideEffectForTest: stub,\n execJs,\n\n });\n\n promise.resolve(true);\n await Array.fromAsync(agent.run('test', {selectedElement: element, isFixQuery: false}));\n\n sinon.assert.match(execJs.getCall(0).args[1], sinon.match({throwOnSideEffect: true}));\n });\n\n it('calls execJs with allowing side effects when confirmSideEffect resolves to true', async () => {\n const promise = Promise.withResolvers();\n const stub = sinon.stub().returns(promise);\n let count = 0;\n async function* generateActionAndAnswer() {\n if (count === 0) {\n yield {\n explanation: `ACTION\n $0.style.backgroundColor = 'red'\n STOP`,\n metadata: {},\n completed: true,\n };\n } else {\n yield {\n explanation: 'ANSWER: This is the answer',\n metadata: {},\n completed: true,\n };\n }\n\n count++;\n }\n const execJs = sinon.mock().twice();\n execJs.onCall(0).throws(new Freestyler.SideEffectError('EvalError: Possible side-effect in debug-evaluate'));\n execJs.onCall(1).resolves('value');\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateActionAndAnswer),\n createExtensionScope,\n confirmSideEffectForTest: stub,\n execJs,\n\n });\n promise.resolve(true);\n await Array.fromAsync(agent.run('test', {selectedElement: element, isFixQuery: false}));\n\n assert.strictEqual(execJs.getCalls().length, 2);\n sinon.assert.match(execJs.getCall(1).args[1], sinon.match({throwOnSideEffect: false}));\n });\n\n it('returns side effect error when confirmSideEffect resolves to false', async () => {\n const promise = Promise.withResolvers();\n const stub = sinon.stub().returns(promise);\n let count = 0;\n async function* generateActionAndAnswer() {\n if (count === 0) {\n yield {\n explanation: `ACTION\n $0.style.backgroundColor = 'red'\n STOP`,\n metadata: {},\n completed: true,\n };\n } else {\n yield {\n explanation: 'ANSWER: This is the answer',\n metadata: {},\n completed: true,\n };\n }\n\n count++;\n }\n const execJs = sinon.mock().twice();\n execJs.onCall(0).throws(new Freestyler.SideEffectError('EvalError: Possible side-effect in debug-evaluate'));\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateActionAndAnswer),\n createExtensionScope,\n confirmSideEffectForTest: stub,\n execJs,\n\n });\n promise.resolve(false);\n const responses = await Array.fromAsync(agent.run('test', {selectedElement: element, isFixQuery: false}));\n\n const actionStep = responses.find(response => response.type === Freestyler.ResponseType.ACTION)!;\n\n assert.strictEqual(actionStep.output, 'Error: User denied code execution with side effects.');\n assert.strictEqual(execJs.getCalls().length, 1);\n });\n\n it('calls execJs with allowing side effects when the query includes \"Fix this issue\" prompt', async () => {\n let count = 0;\n async function* generateActionAndAnswer() {\n if (count === 0) {\n yield {\n explanation: `ACTION\n $0.style.backgroundColor = 'red'\n STOP`,\n metadata: {},\n completed: true,\n };\n } else {\n yield {\n explanation: 'ANSWER: This is the answer',\n metadata: {},\n completed: true,\n };\n }\n\n count++;\n }\n const execJs = sinon.mock().once();\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateActionAndAnswer),\n createExtensionScope,\n execJs,\n\n });\n\n await Array.fromAsync(\n agent.run(Freestyler.FIX_THIS_ISSUE_PROMPT, {selectedElement: element, isFixQuery: true}));\n\n const optionsArg = execJs.lastCall.args[1];\n sinon.assert.match(optionsArg, sinon.match({throwOnSideEffect: false}));\n });\n });\n\n describe('long `Observation` text handling', () => {\n it('errors with too long input', async () => {\n let count = 0;\n async function* generateActionAndAnswer() {\n if (count === 0) {\n yield {\n explanation: `ACTION\n $0.style.backgroundColor = 'red'\n STOP`,\n metadata: {},\n completed: true,\n };\n } else {\n yield {\n explanation: 'ANSWER: This is the answer',\n metadata: {},\n completed: true,\n };\n }\n count++;\n }\n const execJs = sinon.mock().returns(new Array(10_000).fill('
...
').join());\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateActionAndAnswer),\n createExtensionScope,\n execJs,\n\n });\n\n const result = await Array.fromAsync(agent.run('test', {selectedElement: element, isFixQuery: false}));\n const actionSteps = result.filter(step => {\n return step.type === Freestyler.ResponseType.ACTION;\n });\n assert(actionSteps.length === 1, 'Found non or multiple action steps');\n const actionStep = actionSteps.at(0)!;\n assert(actionStep.output.includes('Error: Output exceeded the maximum allowed length.'));\n });\n });\n\n it('generates an answer immediately', async () => {\n async function* generateAnswer() {\n yield {\n explanation: 'ANSWER: this is the answer',\n metadata: {},\n completed: true,\n };\n }\n\n const execJs = sinon.spy();\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateAnswer),\n execJs,\n\n });\n\n const responses = await Array.fromAsync(agent.run('test', {selectedElement: element, isFixQuery: false}));\n assert.deepStrictEqual(responses, [\n {\n type: Freestyler.ResponseType.QUERYING,\n },\n {\n type: Freestyler.ResponseType.ANSWER,\n text: 'this is the answer',\n rpcId: undefined,\n fixable: false,\n },\n ]);\n sinon.assert.notCalled(execJs);\n assert.deepStrictEqual(agent.chatHistoryForTesting, [\n {\n entity: 1,\n text: '# Inspected element\\n\\n* Its selector is `undefined`\\n\\n# User request\\n\\nQUERY: test',\n },\n {\n entity: 2,\n text: 'ANSWER: this is the answer',\n },\n ]);\n });\n\n it('generates an rpcId for the answer', async () => {\n async function* generateAnswer() {\n yield {\n explanation: 'ANSWER: this is the answer',\n metadata: {\n rpcGlobalId: 123,\n },\n completed: true,\n };\n }\n\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateAnswer),\n execJs: sinon.spy(),\n\n });\n\n const responses = await Array.fromAsync(agent.run('test', {selectedElement: element, isFixQuery: false}));\n assert.deepStrictEqual(responses, [\n {\n type: Freestyler.ResponseType.QUERYING,\n },\n {\n type: Freestyler.ResponseType.ANSWER,\n text: 'this is the answer',\n rpcId: 123,\n fixable: false,\n },\n ]);\n });\n\n it('throws an error based on the attribution metadata including RecitationAction.BLOCK', async () => {\n async function* generateAnswer() {\n yield {\n explanation: 'ANSWER: this is the answer',\n metadata: {\n rpcGlobalId: 123,\n attributionMetadata: [{\n attributionAction: Host.AidaClient.RecitationAction.BLOCK,\n citations: [],\n }],\n },\n completed: true,\n };\n }\n\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateAnswer),\n execJs: sinon.spy(),\n\n });\n\n const responses = await Array.fromAsync(agent.run('test', {selectedElement: element, isFixQuery: false}));\n assert.deepStrictEqual(responses, [\n {\n type: Freestyler.ResponseType.QUERYING,\n },\n {\n rpcId: undefined,\n type: Freestyler.ResponseType.ERROR,\n error: Freestyler.ErrorType.UNKNOWN,\n },\n ]);\n });\n\n it('does not throw an error based on attribution metadata not including RecitationAction.BLOCK', async () => {\n async function* generateAnswer() {\n yield {\n explanation: 'ANSWER: this is the answer',\n metadata: {\n rpcGlobalId: 123,\n attributionMetadata: [{\n attributionAction: Host.AidaClient.RecitationAction.ACTION_UNSPECIFIED,\n citations: [],\n }],\n },\n completed: true,\n };\n }\n\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateAnswer),\n execJs: sinon.spy(),\n\n });\n\n const responses = await Array.fromAsync(agent.run('test', {selectedElement: element, isFixQuery: false}));\n assert.deepStrictEqual(responses, [\n {\n type: Freestyler.ResponseType.QUERYING,\n },\n {\n type: Freestyler.ResponseType.ANSWER,\n text: 'this is the answer',\n rpcId: 123,\n fixable: false,\n },\n ]);\n });\n\n it('generates a response if nothing is returned', async () => {\n async function* generateNothing() {\n yield {\n explanation: '',\n metadata: {},\n completed: true,\n };\n }\n\n const execJs = sinon.spy();\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateNothing),\n execJs,\n\n });\n const responses = await Array.fromAsync(agent.run('test', {selectedElement: element, isFixQuery: false}));\n assert.deepStrictEqual(responses, [\n {\n type: Freestyler.ResponseType.QUERYING,\n },\n {\n type: Freestyler.ResponseType.ERROR,\n error: Freestyler.ErrorType.UNKNOWN,\n rpcId: undefined,\n },\n ]);\n sinon.assert.notCalled(execJs);\n assert.deepStrictEqual(agent.chatHistoryForTesting, [\n {\n entity: 1,\n text: '# Inspected element\\n\\n* Its selector is `undefined`\\n\\n# User request\\n\\nQUERY: test',\n },\n {\n entity: 2,\n text: '',\n },\n ]);\n });\n\n it('generates an action response if action and answer both present', async () => {\n let i = 0;\n async function* generateNothing() {\n if (i !== 0) {\n yield {\n explanation: 'ANSWER: this is the actual answer',\n metadata: {},\n completed: true,\n };\n return;\n }\n yield {\n explanation: `THOUGHT: I am thinking.\n\nACTION\nconsole.log('hello');\nSTOP\n\nANSWER: this is the answer`,\n metadata: {},\n completed: false,\n };\n i++;\n }\n\n const execJs = sinon.mock().once();\n execJs.onCall(0).returns('hello');\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateNothing),\n createExtensionScope,\n execJs,\n\n });\n const responses = await Array.fromAsync(agent.run('test', {selectedElement: element, isFixQuery: false}));\n assert.deepStrictEqual(responses, [\n {\n type: Freestyler.ResponseType.QUERYING,\n },\n {\n type: Freestyler.ResponseType.THOUGHT,\n thought: 'I am thinking.',\n title: undefined,\n rpcId: undefined,\n },\n {\n type: Freestyler.ResponseType.ACTION,\n code: 'console.log(\\'hello\\');',\n output: 'hello',\n canceled: false,\n rpcId: undefined,\n },\n {\n type: Freestyler.ResponseType.QUERYING,\n },\n {\n type: Freestyler.ResponseType.ANSWER,\n text: 'this is the actual answer',\n rpcId: undefined,\n fixable: false,\n },\n ]);\n sinon.assert.calledOnce(execJs);\n });\n\n it('generates history for multiple actions', async () => {\n let count = 0;\n async function* generateMultipleTimes() {\n if (count === 3) {\n yield {\n explanation: 'ANSWER: this is the answer',\n metadata: {},\n completed: true,\n };\n return;\n }\n count++;\n yield {\n explanation: `THOUGHT: thought ${count}\\nTITLE:test\\nACTION\\nconsole.log('test')\\nSTOP\\n`,\n metadata: {},\n completed: false,\n };\n }\n\n const execJs = sinon.spy(async () => 'undefined');\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateMultipleTimes),\n createExtensionScope,\n execJs,\n\n });\n\n await Array.fromAsync(agent.run('test', {selectedElement: element, isFixQuery: false}));\n\n assert.deepStrictEqual(agent.chatHistoryForTesting, [\n {\n entity: 1,\n text: '# Inspected element\\n\\n* Its selector is `undefined`\\n\\n# User request\\n\\nQUERY: test',\n },\n {\n entity: 2,\n text: 'THOUGHT: thought 1\\nTITLE: test\\nACTION\\nconsole.log(\\'test\\')\\nSTOP',\n },\n {\n entity: 1,\n text: 'OBSERVATION: undefined',\n },\n {\n entity: 2,\n text: 'THOUGHT: thought 2\\nTITLE: test\\nACTION\\nconsole.log(\\'test\\')\\nSTOP',\n },\n {\n entity: 1,\n text: 'OBSERVATION: undefined',\n },\n {\n entity: 2,\n text: 'THOUGHT: thought 3\\nTITLE: test\\nACTION\\nconsole.log(\\'test\\')\\nSTOP',\n },\n {\n entity: 1,\n text: 'OBSERVATION: undefined',\n },\n {\n entity: 2,\n text: 'ANSWER: this is the answer',\n },\n ]);\n });\n\n it('stops when aborted', async () => {\n let count = 0;\n async function* generateMultipleTimes() {\n if (count === 3) {\n yield {\n explanation: 'ANSWER: this is the answer',\n metadata: {},\n completed: true,\n };\n return;\n }\n count++;\n yield {\n explanation: `THOUGHT: thought ${count}\\nACTION\\nconsole.log('test')\\nSTOP\\n`,\n metadata: {},\n completed: false,\n };\n }\n\n const execJs = sinon.spy();\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateMultipleTimes),\n createExtensionScope,\n execJs,\n\n });\n\n const controller = new AbortController();\n controller.abort();\n await Array.fromAsync(\n agent.run('test', {selectedElement: element, signal: controller.signal, isFixQuery: false}));\n\n assert.deepStrictEqual(agent.chatHistoryForTesting, []);\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"FreestylerAgent.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/freestyler/FreestylerAgent.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Host from '../../core/host/host.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport {\n describeWithEnvironment,\n getGetHostConfigStub,\n} from '../../testing/EnvironmentHelpers.js';\n\nimport * as Freestyler from './freestyler.js';\n\nconst {FreestylerAgent} = Freestyler;\n\ndescribeWithEnvironment('FreestylerAgent', () => {\n function mockHostConfig(modelId?: string) {\n getGetHostConfigStub({\n devToolsFreestylerDogfood: {\n modelId,\n },\n });\n }\n\n function createExtensionScope() {\n return {\n async install() {\n\n },\n async uninstall() {\n\n },\n };\n }\n describe('parseResponse', () => {\n it('parses a thought', async () => {\n const payload = 'some response';\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(`THOUGHT: ${payload}`),\n {\n action: undefined,\n title: undefined,\n thought: payload,\n answer: undefined,\n fixable: false,\n },\n );\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(` THOUGHT: ${payload}`),\n {\n action: undefined,\n title: undefined,\n thought: payload,\n answer: undefined,\n fixable: false,\n },\n );\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(`Something\\n THOUGHT: ${payload}`),\n {\n action: undefined,\n title: undefined,\n thought: payload,\n answer: undefined,\n fixable: false,\n },\n );\n });\n it('parses a answer', async () => {\n const payload = 'some response';\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(`ANSWER: ${payload}`),\n {\n action: undefined,\n title: undefined,\n thought: undefined,\n answer: payload,\n fixable: false,\n },\n );\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(` ANSWER: ${payload}`),\n {\n action: undefined,\n title: undefined,\n thought: undefined,\n answer: payload,\n fixable: false,\n },\n );\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(`Something\\n ANSWER: ${payload}`),\n {\n action: undefined,\n title: undefined,\n thought: undefined,\n answer: payload,\n fixable: false,\n },\n );\n });\n it('parses a multiline answer', async () => {\n const payload = `a\nb\nc`;\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(`ANSWER: ${payload}`),\n {\n action: undefined,\n title: undefined,\n thought: undefined,\n answer: payload,\n fixable: false,\n },\n );\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(` ANSWER: ${payload}`),\n {\n action: undefined,\n title: undefined,\n thought: undefined,\n answer: payload,\n fixable: false,\n },\n );\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(`Something\\n ANSWER: ${payload}`),\n {\n action: undefined,\n title: undefined,\n thought: undefined,\n answer: payload,\n fixable: false,\n },\n );\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(`ANSWER: ${payload}\\nTHOUGHT: thought`),\n {\n action: undefined,\n title: undefined,\n thought: 'thought',\n answer: payload,\n fixable: false,\n },\n );\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(\n `ANSWER: ${payload}\\nOBSERVATION: observation`,\n ),\n {\n action: undefined,\n title: undefined,\n thought: undefined,\n answer: payload,\n fixable: false,\n },\n );\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(\n `ANSWER: ${payload}\\nACTION\\naction\\nSTOP`,\n ),\n {\n action: 'action',\n title: undefined,\n thought: undefined,\n answer: payload,\n fixable: false,\n },\n );\n });\n it('parses an action', async () => {\n const payload = `const data = {\n someKey: \"value\",\n}`;\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(`ACTION\\n${payload}\\nSTOP`),\n {\n action: payload,\n title: undefined,\n thought: undefined,\n answer: undefined,\n fixable: false,\n },\n );\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(`ACTION\\n${payload}`),\n {\n action: payload,\n title: undefined,\n thought: undefined,\n answer: undefined,\n fixable: false,\n },\n );\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(`ACTION\\n\\n${payload}\\n\\nSTOP`),\n {\n action: payload,\n title: undefined,\n thought: undefined,\n answer: undefined,\n fixable: false,\n },\n );\n\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(`ACTION\\n\\n${payload}\\n\\nANSWER: answer`),\n {\n action: payload,\n title: undefined,\n thought: undefined,\n answer: 'answer',\n fixable: false,\n },\n );\n });\n it('parses a thought and title', async () => {\n const payload = 'some response';\n const title = 'this is the title';\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(`THOUGHT: ${payload}\\nTITLE: ${title}`),\n {\n action: undefined,\n thought: payload,\n title,\n answer: undefined,\n fixable: false,\n },\n );\n });\n\n it('parses an action with backticks in the code', async () => {\n const payload = `const data = {\n someKey: \"value\",\n}`;\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(\n `ACTION\\n\\`\\`\\`\\n${payload}\\n\\`\\`\\`\\nSTOP`,\n ),\n {\n action: payload,\n title: undefined,\n thought: undefined,\n answer: undefined,\n fixable: false,\n },\n );\n });\n\n it('parses an action with 5 backticks in the code and `js` text in the prelude', async () => {\n const payload = `const data = {\n someKey: \"value\",\n}`;\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(\n `ACTION\\n\\`\\`\\`\\`\\`\\njs\\n${payload}\\n\\`\\`\\`\\`\\`\\nSTOP`,\n ),\n {\n action: payload,\n title: undefined,\n thought: undefined,\n answer: undefined,\n fixable: false,\n },\n );\n });\n\n it('parses a thought and an action', async () => {\n const actionPayload = `const data = {\n someKey: \"value\",\n}`;\n const thoughtPayload = 'thought';\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(\n `THOUGHT:${thoughtPayload}\\nACTION\\n${actionPayload}\\nSTOP`,\n ),\n {\n action: actionPayload,\n title: undefined,\n thought: thoughtPayload,\n answer: undefined,\n fixable: false,\n },\n );\n });\n\n it('parses a response as an answer', async () => {\n assert.deepStrictEqual(\n FreestylerAgent.parseResponse(\n 'This is also an answer',\n ),\n {\n action: undefined,\n title: undefined,\n thought: undefined,\n answer: 'This is also an answer',\n fixable: false,\n },\n );\n });\n });\n\n describe('describeElement', () => {\n let element: sinon.SinonStubbedInstance;\n\n beforeEach(() => {\n element = sinon.createStubInstance(SDK.DOMModel.DOMNode);\n });\n\n afterEach(() => {\n sinon.restore();\n });\n\n it('should describe an element with no children, siblings, or parent', async () => {\n element.simpleSelector.returns('div#myElement');\n element.getChildNodesPromise.resolves(null);\n\n const result = await FreestylerAgent.describeElement(element);\n\n assert.strictEqual(result, '* Its selector is `div#myElement`');\n });\n\n it('should describe an element with child element and text nodes', async () => {\n const childNodes: sinon.SinonStubbedInstance[] = [\n sinon.createStubInstance(SDK.DOMModel.DOMNode),\n sinon.createStubInstance(SDK.DOMModel.DOMNode),\n sinon.createStubInstance(SDK.DOMModel.DOMNode),\n ];\n childNodes[0].nodeType.returns(Node.ELEMENT_NODE);\n childNodes[0].simpleSelector.returns('span.child1');\n childNodes[1].nodeType.returns(Node.TEXT_NODE);\n childNodes[2].nodeType.returns(Node.ELEMENT_NODE);\n childNodes[2].simpleSelector.returns('span.child2');\n\n element.simpleSelector.returns('div#parentElement');\n element.getChildNodesPromise.resolves(childNodes);\n element.nextSibling = null;\n element.previousSibling = null;\n element.parentNode = null;\n\n const result = await FreestylerAgent.describeElement(element);\n const expectedOutput = `* Its selector is \\`div#parentElement\\`\n* It has 2 child element nodes: \\`span.child1\\`, \\`span.child2\\`\n* It only has 1 child text node`;\n\n assert.strictEqual(result, expectedOutput);\n });\n\n it('should describe an element with siblings and a parent', async () => {\n const nextSibling = sinon.createStubInstance(SDK.DOMModel.DOMNode);\n nextSibling.nodeType.returns(Node.ELEMENT_NODE);\n const previousSibling = sinon.createStubInstance(SDK.DOMModel.DOMNode);\n previousSibling.nodeType.returns(Node.TEXT_NODE);\n\n const parentNode = sinon.createStubInstance(SDK.DOMModel.DOMNode);\n parentNode.simpleSelector.returns('div#grandparentElement');\n const parentChildNodes: sinon.SinonStubbedInstance[] = [\n sinon.createStubInstance(SDK.DOMModel.DOMNode),\n sinon.createStubInstance(SDK.DOMModel.DOMNode),\n ];\n parentChildNodes[0].nodeType.returns(Node.ELEMENT_NODE);\n parentChildNodes[0].simpleSelector.returns('span.sibling1');\n parentChildNodes[1].nodeType.returns(Node.TEXT_NODE);\n parentNode.getChildNodesPromise.resolves(parentChildNodes);\n\n element.simpleSelector.returns('div#parentElement');\n element.getChildNodesPromise.resolves(null);\n element.nextSibling = nextSibling;\n element.previousSibling = previousSibling;\n element.parentNode = parentNode;\n\n const result = await FreestylerAgent.describeElement(element);\n const expectedOutput = `* Its selector is \\`div#parentElement\\`\n* It has a next sibling and it is an element node\n* It has a previous sibling and it is a non element node\n* Its parent's selector is \\`div#grandparentElement\\`\n* Its parent has only 1 child element node\n* Its parent has only 1 child text node`;\n\n assert.strictEqual(result, expectedOutput);\n });\n });\n\n describe('buildRequest', () => {\n beforeEach(() => {\n sinon.restore();\n });\n\n it('builds a request with a model id', async () => {\n mockHostConfig('test model');\n assert.strictEqual(\n FreestylerAgent.buildRequest({input: 'test input'}).options?.model_id,\n 'test model',\n );\n });\n\n it('builds a request with logging', async () => {\n mockHostConfig('test model');\n assert.strictEqual(\n FreestylerAgent.buildRequest({input: 'test input', serverSideLoggingEnabled: true})\n .metadata?.disable_user_content_logging,\n false,\n );\n });\n\n it('builds a request without logging', async () => {\n mockHostConfig('test model');\n assert.strictEqual(\n FreestylerAgent.buildRequest({input: 'test input', serverSideLoggingEnabled: false})\n .metadata?.disable_user_content_logging,\n true,\n );\n });\n\n it('builds a request with input', async () => {\n mockHostConfig();\n const request = FreestylerAgent.buildRequest({input: 'test input'});\n assert.strictEqual(request.input, 'test input');\n assert.strictEqual(request.preamble, undefined);\n assert.strictEqual(request.chat_history, undefined);\n });\n\n it('builds a request with a sessionId', async () => {\n mockHostConfig();\n const request = FreestylerAgent.buildRequest({input: 'test input', sessionId: 'sessionId'});\n assert.strictEqual(request.metadata?.string_session_id, 'sessionId');\n });\n\n it('builds a request with preamble', async () => {\n mockHostConfig();\n const request = FreestylerAgent.buildRequest({input: 'test input', preamble: 'preamble'});\n assert.strictEqual(request.input, 'test input');\n assert.strictEqual(request.preamble, 'preamble');\n assert.strictEqual(request.chat_history, undefined);\n });\n\n it('builds a request with chat history', async () => {\n mockHostConfig();\n const request = FreestylerAgent.buildRequest({\n input: 'test input',\n chatHistory: [\n {\n text: 'test',\n entity: Host.AidaClient.Entity.USER,\n },\n ],\n });\n assert.strictEqual(request.input, 'test input');\n assert.strictEqual(request.preamble, undefined);\n assert.deepStrictEqual(request.chat_history, [\n {\n text: 'test',\n entity: 1,\n },\n ]);\n });\n\n it('structure matches the snapshot', () => {\n mockHostConfig('test model');\n assert.deepStrictEqual(\n FreestylerAgent.buildRequest({\n input: 'test input',\n preamble: 'preamble',\n chatHistory: [\n {\n text: 'first',\n entity: Host.AidaClient.Entity.UNKNOWN,\n },\n {\n text: 'second',\n entity: Host.AidaClient.Entity.SYSTEM,\n },\n {\n text: 'third',\n entity: Host.AidaClient.Entity.USER,\n },\n ],\n serverSideLoggingEnabled: true,\n sessionId: 'sessionId',\n }),\n {\n input: 'test input',\n client: 'CHROME_DEVTOOLS',\n preamble: 'preamble',\n chat_history: [\n {\n entity: 0,\n text: 'first',\n },\n {\n entity: 2,\n text: 'second',\n },\n {\n entity: 1,\n text: 'third',\n },\n ],\n metadata: {\n disable_user_content_logging: false,\n string_session_id: 'sessionId',\n user_tier: 2,\n },\n options: {\n model_id: 'test model',\n temperature: 0,\n },\n client_feature: 2,\n functionality_type: 1,\n },\n );\n });\n });\n\n describe('run', () => {\n let element: sinon.SinonStubbedInstance;\n beforeEach(() => {\n mockHostConfig();\n element = sinon.createStubInstance(SDK.DOMModel.DOMNode);\n });\n\n function mockAidaClient(\n fetch: () => AsyncGenerator,\n ): Host.AidaClient.AidaClient {\n return {\n fetch,\n registerClientEvent: () => Promise.resolve({}),\n };\n }\n\n describe('side effect handling', () => {\n it('calls confirmSideEffect when the code execution contains a side effect', async () => {\n const promise = Promise.withResolvers();\n const stub = sinon.stub().returns(promise);\n\n let count = 0;\n async function* generateActionAndAnswer() {\n if (count === 0) {\n yield {\n explanation: `ACTION\n $0.style.backgroundColor = 'red'\n STOP`,\n metadata: {},\n completed: true,\n };\n } else {\n yield {\n explanation: 'ANSWER: This is the answer',\n metadata: {},\n completed: true,\n };\n }\n\n count++;\n }\n const execJs =\n sinon.mock().throws(new Freestyler.SideEffectError('EvalError: Possible side-effect in debug-evaluate'));\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateActionAndAnswer),\n createExtensionScope,\n confirmSideEffectForTest: stub,\n execJs,\n\n });\n\n promise.resolve(true);\n await Array.fromAsync(agent.run('test', {selectedElement: element, isFixQuery: false}));\n\n sinon.assert.match(execJs.getCall(0).args[1], sinon.match({throwOnSideEffect: true}));\n });\n\n it('calls execJs with allowing side effects when confirmSideEffect resolves to true', async () => {\n const promise = Promise.withResolvers();\n const stub = sinon.stub().returns(promise);\n let count = 0;\n async function* generateActionAndAnswer() {\n if (count === 0) {\n yield {\n explanation: `ACTION\n $0.style.backgroundColor = 'red'\n STOP`,\n metadata: {},\n completed: true,\n };\n } else {\n yield {\n explanation: 'ANSWER: This is the answer',\n metadata: {},\n completed: true,\n };\n }\n\n count++;\n }\n const execJs = sinon.mock().twice();\n execJs.onCall(0).throws(new Freestyler.SideEffectError('EvalError: Possible side-effect in debug-evaluate'));\n execJs.onCall(1).resolves('value');\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateActionAndAnswer),\n createExtensionScope,\n confirmSideEffectForTest: stub,\n execJs,\n\n });\n promise.resolve(true);\n await Array.fromAsync(agent.run('test', {selectedElement: element, isFixQuery: false}));\n\n assert.strictEqual(execJs.getCalls().length, 2);\n sinon.assert.match(execJs.getCall(1).args[1], sinon.match({throwOnSideEffect: false}));\n });\n\n it('returns side effect error when confirmSideEffect resolves to false', async () => {\n const promise = Promise.withResolvers();\n const stub = sinon.stub().returns(promise);\n let count = 0;\n async function* generateActionAndAnswer() {\n if (count === 0) {\n yield {\n explanation: `ACTION\n $0.style.backgroundColor = 'red'\n STOP`,\n metadata: {},\n completed: true,\n };\n } else {\n yield {\n explanation: 'ANSWER: This is the answer',\n metadata: {},\n completed: true,\n };\n }\n\n count++;\n }\n const execJs = sinon.mock().twice();\n execJs.onCall(0).throws(new Freestyler.SideEffectError('EvalError: Possible side-effect in debug-evaluate'));\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateActionAndAnswer),\n createExtensionScope,\n confirmSideEffectForTest: stub,\n execJs,\n\n });\n promise.resolve(false);\n const responses = await Array.fromAsync(agent.run('test', {selectedElement: element, isFixQuery: false}));\n\n const actionStep = responses.find(response => response.type === Freestyler.ResponseType.ACTION)!;\n\n assert.strictEqual(actionStep.output, 'Error: User denied code execution with side effects.');\n assert.strictEqual(execJs.getCalls().length, 1);\n });\n\n it('calls execJs with allowing side effects when the query includes \"Fix this issue\" prompt', async () => {\n let count = 0;\n async function* generateActionAndAnswer() {\n if (count === 0) {\n yield {\n explanation: `ACTION\n $0.style.backgroundColor = 'red'\n STOP`,\n metadata: {},\n completed: true,\n };\n } else {\n yield {\n explanation: 'ANSWER: This is the answer',\n metadata: {},\n completed: true,\n };\n }\n\n count++;\n }\n const execJs = sinon.mock().once();\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateActionAndAnswer),\n createExtensionScope,\n execJs,\n\n });\n\n await Array.fromAsync(\n agent.run(Freestyler.FIX_THIS_ISSUE_PROMPT, {selectedElement: element, isFixQuery: true}));\n\n const optionsArg = execJs.lastCall.args[1];\n sinon.assert.match(optionsArg, sinon.match({throwOnSideEffect: false}));\n });\n });\n\n describe('long `Observation` text handling', () => {\n it('errors with too long input', async () => {\n let count = 0;\n async function* generateActionAndAnswer() {\n if (count === 0) {\n yield {\n explanation: `ACTION\n $0.style.backgroundColor = 'red'\n STOP`,\n metadata: {},\n completed: true,\n };\n } else {\n yield {\n explanation: 'ANSWER: This is the answer',\n metadata: {},\n completed: true,\n };\n }\n count++;\n }\n const execJs = sinon.mock().returns(new Array(10_000).fill('
...
').join());\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateActionAndAnswer),\n createExtensionScope,\n execJs,\n\n });\n\n const result = await Array.fromAsync(agent.run('test', {selectedElement: element, isFixQuery: false}));\n const actionSteps = result.filter(step => {\n return step.type === Freestyler.ResponseType.ACTION;\n });\n assert(actionSteps.length === 1, 'Found non or multiple action steps');\n const actionStep = actionSteps.at(0)!;\n assert(actionStep.output.includes('Error: Output exceeded the maximum allowed length.'));\n });\n });\n\n it('generates an answer immediately', async () => {\n async function* generateAnswer() {\n yield {\n explanation: 'ANSWER: this is the answer',\n metadata: {},\n completed: true,\n };\n }\n\n const execJs = sinon.spy();\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateAnswer),\n execJs,\n\n });\n\n const responses = await Array.fromAsync(agent.run('test', {selectedElement: element, isFixQuery: false}));\n assert.deepStrictEqual(responses, [\n {\n type: Freestyler.ResponseType.QUERYING,\n },\n {\n type: Freestyler.ResponseType.ANSWER,\n text: 'this is the answer',\n rpcId: undefined,\n fixable: false,\n },\n ]);\n sinon.assert.notCalled(execJs);\n assert.deepStrictEqual(agent.chatHistoryForTesting, [\n {\n entity: 1,\n text: '# Inspected element\\n\\n* Its selector is `undefined`\\n\\n# User request\\n\\nQUERY: test',\n },\n {\n entity: 2,\n text: 'ANSWER: this is the answer',\n },\n ]);\n });\n\n it('generates an rpcId for the answer', async () => {\n async function* generateAnswer() {\n yield {\n explanation: 'ANSWER: this is the answer',\n metadata: {\n rpcGlobalId: 123,\n },\n completed: true,\n };\n }\n\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateAnswer),\n execJs: sinon.spy(),\n\n });\n\n const responses = await Array.fromAsync(agent.run('test', {selectedElement: element, isFixQuery: false}));\n assert.deepStrictEqual(responses, [\n {\n type: Freestyler.ResponseType.QUERYING,\n },\n {\n type: Freestyler.ResponseType.ANSWER,\n text: 'this is the answer',\n rpcId: 123,\n fixable: false,\n },\n ]);\n });\n\n it('throws an error based on the attribution metadata including RecitationAction.BLOCK', async () => {\n async function* generateAnswer() {\n yield {\n explanation: 'ANSWER: this is the answer',\n metadata: {\n rpcGlobalId: 123,\n attributionMetadata: [{\n attributionAction: Host.AidaClient.RecitationAction.BLOCK,\n citations: [],\n }],\n },\n completed: true,\n };\n }\n\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateAnswer),\n execJs: sinon.spy(),\n\n });\n\n const responses = await Array.fromAsync(agent.run('test', {selectedElement: element, isFixQuery: false}));\n assert.deepStrictEqual(responses, [\n {\n type: Freestyler.ResponseType.QUERYING,\n },\n {\n rpcId: undefined,\n type: Freestyler.ResponseType.ERROR,\n error: Freestyler.ErrorType.UNKNOWN,\n },\n ]);\n });\n\n it('does not throw an error based on attribution metadata not including RecitationAction.BLOCK', async () => {\n async function* generateAnswer() {\n yield {\n explanation: 'ANSWER: this is the answer',\n metadata: {\n rpcGlobalId: 123,\n attributionMetadata: [{\n attributionAction: Host.AidaClient.RecitationAction.ACTION_UNSPECIFIED,\n citations: [],\n }],\n },\n completed: true,\n };\n }\n\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateAnswer),\n execJs: sinon.spy(),\n\n });\n\n const responses = await Array.fromAsync(agent.run('test', {selectedElement: element, isFixQuery: false}));\n assert.deepStrictEqual(responses, [\n {\n type: Freestyler.ResponseType.QUERYING,\n },\n {\n type: Freestyler.ResponseType.ANSWER,\n text: 'this is the answer',\n rpcId: 123,\n fixable: false,\n },\n ]);\n });\n\n it('generates a response if nothing is returned', async () => {\n async function* generateNothing() {\n yield {\n explanation: '',\n metadata: {},\n completed: true,\n };\n }\n\n const execJs = sinon.spy();\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateNothing),\n execJs,\n\n });\n const responses = await Array.fromAsync(agent.run('test', {selectedElement: element, isFixQuery: false}));\n assert.deepStrictEqual(responses, [\n {\n type: Freestyler.ResponseType.QUERYING,\n },\n {\n type: Freestyler.ResponseType.ERROR,\n error: Freestyler.ErrorType.UNKNOWN,\n rpcId: undefined,\n },\n ]);\n sinon.assert.notCalled(execJs);\n assert.deepStrictEqual(agent.chatHistoryForTesting, [\n {\n entity: 1,\n text: '# Inspected element\\n\\n* Its selector is `undefined`\\n\\n# User request\\n\\nQUERY: test',\n },\n {\n entity: 2,\n text: '',\n },\n ]);\n });\n\n it('generates an action response if action and answer both present', async () => {\n let i = 0;\n async function* generateNothing() {\n if (i !== 0) {\n yield {\n explanation: 'ANSWER: this is the actual answer',\n metadata: {},\n completed: true,\n };\n return;\n }\n yield {\n explanation: `THOUGHT: I am thinking.\n\nACTION\nconsole.log('hello');\nSTOP\n\nANSWER: this is the answer`,\n metadata: {},\n completed: false,\n };\n i++;\n }\n\n const execJs = sinon.mock().once();\n execJs.onCall(0).returns('hello');\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateNothing),\n createExtensionScope,\n execJs,\n\n });\n const responses = await Array.fromAsync(agent.run('test', {selectedElement: element, isFixQuery: false}));\n assert.deepStrictEqual(responses, [\n {\n type: Freestyler.ResponseType.QUERYING,\n },\n {\n type: Freestyler.ResponseType.THOUGHT,\n thought: 'I am thinking.',\n rpcId: undefined,\n },\n {\n type: Freestyler.ResponseType.ACTION,\n code: 'console.log(\\'hello\\');',\n output: 'hello',\n canceled: false,\n rpcId: undefined,\n },\n {\n type: Freestyler.ResponseType.QUERYING,\n },\n {\n type: Freestyler.ResponseType.ANSWER,\n text: 'this is the actual answer',\n rpcId: undefined,\n fixable: false,\n },\n ]);\n sinon.assert.calledOnce(execJs);\n });\n\n it('generates history for multiple actions', async () => {\n let count = 0;\n async function* generateMultipleTimes() {\n if (count === 3) {\n yield {\n explanation: 'ANSWER: this is the answer',\n metadata: {},\n completed: true,\n };\n return;\n }\n count++;\n yield {\n explanation: `THOUGHT: thought ${count}\\nTITLE:test\\nACTION\\nconsole.log('test')\\nSTOP\\n`,\n metadata: {},\n completed: false,\n };\n }\n\n const execJs = sinon.spy(async () => 'undefined');\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateMultipleTimes),\n createExtensionScope,\n execJs,\n\n });\n\n await Array.fromAsync(agent.run('test', {selectedElement: element, isFixQuery: false}));\n\n assert.deepStrictEqual(agent.chatHistoryForTesting, [\n {\n entity: 1,\n text: '# Inspected element\\n\\n* Its selector is `undefined`\\n\\n# User request\\n\\nQUERY: test',\n },\n {\n entity: 2,\n text: 'THOUGHT: thought 1\\nTITLE: test\\nACTION\\nconsole.log(\\'test\\')\\nSTOP',\n },\n {\n entity: 1,\n text: 'OBSERVATION: undefined',\n },\n {\n entity: 2,\n text: 'THOUGHT: thought 2\\nTITLE: test\\nACTION\\nconsole.log(\\'test\\')\\nSTOP',\n },\n {\n entity: 1,\n text: 'OBSERVATION: undefined',\n },\n {\n entity: 2,\n text: 'THOUGHT: thought 3\\nTITLE: test\\nACTION\\nconsole.log(\\'test\\')\\nSTOP',\n },\n {\n entity: 1,\n text: 'OBSERVATION: undefined',\n },\n {\n entity: 2,\n text: 'ANSWER: this is the answer',\n },\n ]);\n });\n\n it('stops when aborted', async () => {\n let count = 0;\n async function* generateMultipleTimes() {\n if (count === 3) {\n yield {\n explanation: 'ANSWER: this is the answer',\n metadata: {},\n completed: true,\n };\n return;\n }\n count++;\n yield {\n explanation: `THOUGHT: thought ${count}\\nACTION\\nconsole.log('test')\\nSTOP\\n`,\n metadata: {},\n completed: false,\n };\n }\n\n const execJs = sinon.spy();\n const agent = new FreestylerAgent({\n aidaClient: mockAidaClient(generateMultipleTimes),\n createExtensionScope,\n execJs,\n\n });\n\n const controller = new AbortController();\n controller.abort();\n await Array.fromAsync(\n agent.run('test', {selectedElement: element, signal: controller.signal, isFixQuery: false}));\n\n assert.deepStrictEqual(agent.chatHistoryForTesting, []);\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/freestyler/FreestylerPanel.js b/public/panels/freestyler/FreestylerPanel.js index 296e13b47..1c6dfa32d 100644 --- a/public/panels/freestyler/FreestylerPanel.js +++ b/public/panels/freestyler/FreestylerPanel.js @@ -5,11 +5,12 @@ import * as Common from '../../core/common/common.js'; import * as Host from '../../core/host/host.js'; import * as i18n from '../../core/i18n/i18n.js'; import * as SDK from '../../core/sdk/sdk.js'; +import * as NetworkForward from '../../panels/network/forward/forward.js'; import * as UI from '../../ui/legacy/legacy.js'; import * as LitHtml from '../../ui/lit-html/lit-html.js'; import { ChangeManager } from './ChangeManager.js'; import { DOGFOOD_INFO, FreestylerChatUi, } from './components/FreestylerChatUi.js'; -import { DrJonesNetworkAgent, DrJonesNetworkAgentResponseType, } from './DrJonesNetworkAgent.js'; +import { DrJonesNetworkAgent, DrJonesNetworkAgentResponseType, formatHeaders, formatNetworkRequestTiming, } from './DrJonesNetworkAgent.js'; import { FIX_THIS_ISSUE_PROMPT, FreestylerAgent, ResponseType } from './FreestylerAgent.js'; import freestylerPanelStyles from './freestylerPanel.css.js'; /* @@ -19,13 +20,49 @@ import freestylerPanelStyles from './freestylerPanel.css.js'; */ const UIStringsTemp = { /** - *@description Freestyler UI text for clearing messages. + *@description AI assistant UI text for clearing messages. */ clearMessages: 'Clear messages', /** - *@description Freestyler UI text for sending feedback. + *@description AI assistant UI tooltip text for the help button. */ - sendFeedback: 'Send feedback', + help: 'Help', + /** + *@description Title text for thinking step of DrJones Network agent. + */ + inspectingNetworkData: 'Inspecting network data', + /** + *@description Thought text for thinking step of DrJones Network agent. + */ + dataUsedToGenerateThisResponse: 'Data used to generate this response', + /** + *@description Heading text for the block that shows the network request details. + */ + request: 'Request', + /** + *@description Heading text for the block that shows the network response details. + */ + response: 'Response', + /** + *@description Prefix text for request URL. + */ + requestUrl: 'Request URL', + /** + *@description Title text for request headers. + */ + requestHeaders: 'Request Headers', + /** + *@description Title text for request timing details. + */ + timing: 'Timing', + /** + *@description Title text for response headers. + */ + responseHeaders: 'Response Headers', + /** + *@description Prefix text for response status. + */ + responseStatus: 'Response Status', }; // TODO(nvitkov): b/346933425 // const str_ = i18n.i18n.registerUIStrings('panels/freestyler/FreestylerPanel.ts', UIStrings); @@ -41,7 +78,7 @@ function createToolbar(target, { onClearClick }) { clearButton.addEventListener("Click" /* UI.Toolbar.ToolbarButton.Events.CLICK */, onClearClick); leftToolbar.appendToolbarItem(clearButton); rightToolbar.appendSeparator(); - const helpButton = new UI.Toolbar.ToolbarButton(i18nString(UIStringsTemp.sendFeedback), 'help', undefined, 'freestyler.feedback'); + const helpButton = new UI.Toolbar.ToolbarButton(i18nString(UIStringsTemp.help), 'help', undefined, 'freestyler.help'); helpButton.addEventListener("Click" /* UI.Toolbar.ToolbarButton.Events.CLICK */, () => { Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(DOGFOOD_INFO); }); @@ -102,6 +139,7 @@ export class FreestylerPanel extends UI.Panel.Panel { onFixThisIssueClick: () => { void this.#startConversation(FIX_THIS_ISSUE_PROMPT, true); }, + onSelectedNetworkRequestClick: this.#handleSelectedNetworkRequestClick.bind(this), canShowFeedbackForm: this.#serverSideLoggingEnabled, userInfo: { accountImage: syncInfo.accountImage, @@ -184,6 +222,12 @@ export class FreestylerPanel extends UI.Panel.Panel { this.#viewProps.state = "chat-view" /* FreestylerChatUiState.CHAT_VIEW */; this.doUpdate(); } + #handleSelectedNetworkRequestClick() { + if (this.#viewProps.selectedNetworkRequest) { + const requestLocation = NetworkForward.UIRequestLocation.UIRequestLocation.tab(this.#viewProps.selectedNetworkRequest, "headers-component" /* NetworkForward.UIRequestLocation.UIRequestTabs.HEADERS_COMPONENT */); + return Common.Revealer.reveal(requestLocation); + } + } handleAction(actionId) { switch (actionId) { case 'freestyler.element-panel-context': { @@ -224,7 +268,6 @@ export class FreestylerPanel extends UI.Panel.Panel { this.#viewProps.isLoading = true; const systemMessage = { entity: "model" /* ChatMessageEntity.MODEL */, - aborted: false, suggestingFix: false, steps: [], }; @@ -232,19 +275,6 @@ export class FreestylerPanel extends UI.Panel.Panel { this.doUpdate(); this.#runAbortController = new AbortController(); const signal = this.#runAbortController.signal; - signal.addEventListener('abort', () => { - systemMessage.rpcId = undefined; - systemMessage.aborted = true; - systemMessage.suggestingFix = false; - const lastStep = systemMessage.steps.at(-1); - // Mark the last step as cancelled to make the UI feel better. - if (lastStep) { - lastStep.canceled = true; - } - this.#viewProps.isLoading = false; - this.doUpdate(); - this.#viewOutput.freestylerChatUi?.scrollToLastMessage(); - }); if (this.#viewProps.agentType === "freestyler" /* AgentType.FREESTYLER */) { await this.#conversationStepsForFreestylerAgent(text, isFixQuery, signal, systemMessage); } @@ -264,10 +294,16 @@ export class FreestylerPanel extends UI.Panel.Panel { } break; } + case ResponseType.TITLE: { + step.title = data.title; + if (systemMessage.steps.at(-1) !== step) { + systemMessage.steps.push(step); + } + break; + } case ResponseType.THOUGHT: { step.isLoading = false; step.thought = data.thought; - step.title = data.title; if (systemMessage.steps.at(-1) !== step) { systemMessage.steps.push(step); } @@ -309,7 +345,16 @@ export class FreestylerPanel extends UI.Panel.Panel { case ResponseType.ERROR: { step.isLoading = false; systemMessage.error = data.error; + systemMessage.suggestingFix = false; + systemMessage.rpcId = undefined; this.#viewProps.isLoading = false; + if (data.error === "abort" /* ErrorType.ABORT */) { + const lastStep = systemMessage.steps.at(-1); + // Mark the last step as cancelled to make the UI feel better. + if (lastStep) { + lastStep.canceled = true; + } + } } } this.doUpdate(); @@ -317,8 +362,13 @@ export class FreestylerPanel extends UI.Panel.Panel { } } async #conversationStepsForDrJonesNetworkAgent(text, signal, systemMessage) { - // TODO(samiyac): Improve loading generator - const step = { isLoading: true }; + // TODO(samiyac): Only display the thinking step with context details when it is the first message + const step = { + isLoading: true, + title: UIStringsTemp.inspectingNetworkData, + thought: UIStringsTemp.dataUsedToGenerateThisResponse, + contextDetails: this.#createContextDetailsForDrJonesNetworkAgent(), + }; if (!systemMessage.steps.length) { systemMessage.steps.push(step); } @@ -329,10 +379,6 @@ export class FreestylerPanel extends UI.Panel.Panel { case DrJonesNetworkAgentResponseType.ANSWER: { systemMessage.answer = data.text; systemMessage.rpcId = data.rpcId; - // When there is an answer without any thinking steps, we don't want to show the thinking step. - if (systemMessage.steps.length === 1 && systemMessage.steps[0].isLoading) { - systemMessage.steps.pop(); - } step.isLoading = false; this.#viewProps.isLoading = false; break; @@ -347,6 +393,31 @@ export class FreestylerPanel extends UI.Panel.Panel { this.#viewOutput.freestylerChatUi?.scrollToLastMessage(); } } + #createContextDetailsForDrJonesNetworkAgent() { + if (this.#viewProps.selectedNetworkRequest) { + const requestContextDetail = { + title: UIStringsTemp.request, + text: UIStringsTemp.requestUrl + ': ' + this.#viewProps.selectedNetworkRequest.url() + '\n\n' + + formatHeaders(UIStringsTemp.requestHeaders, this.#viewProps.selectedNetworkRequest.requestHeaders()), + }; + const responseContextDetail = { + title: UIStringsTemp.response, + text: UIStringsTemp.responseStatus + ': ' + this.#viewProps.selectedNetworkRequest.statusCode + ' ' + + this.#viewProps.selectedNetworkRequest.statusText + '\n\n' + + formatHeaders(UIStringsTemp.responseHeaders, this.#viewProps.selectedNetworkRequest.responseHeaders), + }; + const timingContextDetail = { + title: UIStringsTemp.timing, + text: formatNetworkRequestTiming(this.#viewProps.selectedNetworkRequest), + }; + return [ + requestContextDetail, + responseContextDetail, + timingContextDetail, + ]; + } + return []; + } } export class ActionDelegate { handleAction(_context, actionId) { diff --git a/public/panels/freestyler/FreestylerPanel.js.map b/public/panels/freestyler/FreestylerPanel.js.map index 0bd8e0591..3903d25f0 100644 --- a/public/panels/freestyler/FreestylerPanel.js.map +++ b/public/panels/freestyler/FreestylerPanel.js.map @@ -1 +1 @@ -{"version":3,"file":"FreestylerPanel.js","sourceRoot":"","sources":["../../../../../../front_end/panels/freestyler/FreestylerPanel.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as Common from '../../core/common/common.js';\nimport * as Host from '../../core/host/host.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as LitHtml from '../../ui/lit-html/lit-html.js';\n\nimport {ChangeManager} from './ChangeManager.js';\nimport {\n AgentType,\n ChatMessageEntity,\n DOGFOOD_INFO,\n FreestylerChatUi,\n type ModelChatMessage,\n type Props as FreestylerChatUiProps,\n State as FreestylerChatUiState,\n type Step,\n} from './components/FreestylerChatUi.js';\nimport {\n DrJonesNetworkAgent,\n DrJonesNetworkAgentResponseType,\n} from './DrJonesNetworkAgent.js';\nimport {ErrorType, FIX_THIS_ISSUE_PROMPT, FreestylerAgent, ResponseType} from './FreestylerAgent.js';\nimport freestylerPanelStyles from './freestylerPanel.css.js';\n\n/*\n * TODO(nvitkov): b/346933425\n * Temporary string that should not be translated\n * as they may change often during development.\n */\nconst UIStringsTemp = {\n /**\n *@description Freestyler UI text for clearing messages.\n */\n clearMessages: 'Clear messages',\n /**\n *@description Freestyler UI text for sending feedback.\n */\n sendFeedback: 'Send feedback',\n};\n\n// TODO(nvitkov): b/346933425\n// const str_ = i18n.i18n.registerUIStrings('panels/freestyler/FreestylerPanel.ts', UIStrings);\n// const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n/* eslint-disable rulesdir/l10n_i18nString_call_only_with_uistrings */\nconst i18nString = i18n.i18n.lockedString;\n\ntype ViewOutput = {\n freestylerChatUi?: FreestylerChatUi,\n};\ntype View = (input: FreestylerChatUiProps, output: ViewOutput, target: HTMLElement) => void;\n\n// TODO(ergunsh): Use the WidgetElement instead of separately creating the toolbar.\nfunction createToolbar(target: HTMLElement, {onClearClick}: {onClearClick: () => void}): void {\n const toolbarContainer = target.createChild('div', 'freestyler-toolbar-container');\n const leftToolbar = new UI.Toolbar.Toolbar('', toolbarContainer);\n const rightToolbar = new UI.Toolbar.Toolbar('freestyler-right-toolbar', toolbarContainer);\n\n const clearButton =\n new UI.Toolbar.ToolbarButton(i18nString(UIStringsTemp.clearMessages), 'clear', undefined, 'freestyler.clear');\n clearButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, onClearClick);\n leftToolbar.appendToolbarItem(clearButton);\n\n rightToolbar.appendSeparator();\n const helpButton =\n new UI.Toolbar.ToolbarButton(i18nString(UIStringsTemp.sendFeedback), 'help', undefined, 'freestyler.feedback');\n helpButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, () => {\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(DOGFOOD_INFO);\n });\n rightToolbar.appendToolbarItem(helpButton);\n}\n\nfunction defaultView(input: FreestylerChatUiProps, output: ViewOutput, target: HTMLElement): void {\n // clang-format off\n LitHtml.render(LitHtml.html`\n <${FreestylerChatUi.litTagName} .props=${input} ${LitHtml.Directives.ref((el: Element|undefined) => {\n if (!el || !(el instanceof FreestylerChatUi)) {\n return;\n }\n\n output.freestylerChatUi = el;\n })}>\n `, target, {host: input}); // eslint-disable-line rulesdir/lit_html_host_this\n // clang-format on\n}\n\nlet freestylerPanelInstance: FreestylerPanel;\nexport class FreestylerPanel extends UI.Panel.Panel {\n static panelName = 'freestyler';\n\n #toggleSearchElementAction: UI.ActionRegistration.Action;\n #selectedElement: SDK.DOMModel.DOMNode|null;\n #selectedNetworkRequest: SDK.NetworkRequest.NetworkRequest|null;\n #contentContainer: HTMLElement;\n #aidaClient: Host.AidaClient.AidaClient;\n #freestylerAgent: FreestylerAgent;\n #drJonesNetworkAgent: DrJonesNetworkAgent;\n #viewProps: FreestylerChatUiProps;\n #viewOutput: ViewOutput = {};\n #serverSideLoggingEnabled = isFreestylerServerSideLoggingEnabled();\n #consentViewAcceptedSetting =\n Common.Settings.Settings.instance().createLocalSetting('freestyler-dogfood-consent-onboarding-finished', false);\n #changeManager = new ChangeManager();\n\n constructor(private view: View = defaultView, {aidaClient, aidaAvailability, syncInfo}: {\n aidaClient: Host.AidaClient.AidaClient,\n aidaAvailability: Host.AidaClient.AidaAccessPreconditions,\n syncInfo: Host.InspectorFrontendHostAPI.SyncInformation,\n }) {\n super(FreestylerPanel.panelName);\n\n createToolbar(this.contentElement, {onClearClick: this.#clearMessages.bind(this)});\n this.#toggleSearchElementAction =\n UI.ActionRegistry.ActionRegistry.instance().getAction('elements.toggle-element-search');\n this.#aidaClient = aidaClient;\n this.#contentContainer = this.contentElement.createChild('div', 'freestyler-chat-ui-container');\n\n this.#selectedElement = UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);\n this.#selectedNetworkRequest = UI.Context.Context.instance().flavor(SDK.NetworkRequest.NetworkRequest);\n this.#viewProps = {\n state: this.#consentViewAcceptedSetting.get() ? FreestylerChatUiState.CHAT_VIEW :\n FreestylerChatUiState.CONSENT_VIEW,\n aidaAvailability,\n messages: [],\n inspectElementToggled: this.#toggleSearchElementAction.toggled(),\n selectedElement: this.#selectedElement,\n selectedNetworkRequest: this.#selectedNetworkRequest,\n isLoading: false,\n onTextSubmit: this.#startConversation.bind(this),\n onInspectElementClick: this.#handleSelectElementClick.bind(this),\n onFeedbackSubmit: this.#handleFeedbackSubmit.bind(this),\n onAcceptConsentClick: this.#handleAcceptConsentClick.bind(this),\n onCancelClick: this.#cancel.bind(this),\n onFixThisIssueClick: () => {\n void this.#startConversation(FIX_THIS_ISSUE_PROMPT, true);\n },\n canShowFeedbackForm: this.#serverSideLoggingEnabled,\n userInfo: {\n accountImage: syncInfo.accountImage,\n accountFullName: syncInfo.accountFullName,\n },\n agentType: AgentType.FREESTYLER,\n };\n this.#toggleSearchElementAction.addEventListener(UI.ActionRegistration.Events.TOGGLED, ev => {\n this.#viewProps.inspectElementToggled = ev.data;\n this.doUpdate();\n });\n\n this.#freestylerAgent = this.#createFreestylerAgent();\n this.#drJonesNetworkAgent = this.#createDrJonesNetworkAgent();\n\n UI.Context.Context.instance().addFlavorChangeListener(SDK.DOMModel.DOMNode, ev => {\n if (this.#viewProps.selectedElement === ev.data) {\n return;\n }\n\n this.#viewProps.selectedElement = Boolean(ev.data) && ev.data.nodeType() === Node.ELEMENT_NODE ? ev.data : null;\n this.doUpdate();\n });\n UI.Context.Context.instance().addFlavorChangeListener(SDK.NetworkRequest.NetworkRequest, ev => {\n if (this.#viewProps.selectedNetworkRequest === ev.data) {\n return;\n }\n\n this.#viewProps.selectedNetworkRequest = Boolean(ev.data) ? ev.data : null;\n this.doUpdate();\n });\n this.doUpdate();\n }\n\n #createFreestylerAgent(): FreestylerAgent {\n return new FreestylerAgent({\n aidaClient: this.#aidaClient,\n changeManager: this.#changeManager,\n serverSideLoggingEnabled: this.#serverSideLoggingEnabled,\n });\n }\n\n #createDrJonesNetworkAgent(): DrJonesNetworkAgent {\n return new DrJonesNetworkAgent({\n aidaClient: this.#aidaClient,\n serverSideLoggingEnabled: this.#serverSideLoggingEnabled,\n });\n }\n\n static async instance(opts: {\n forceNew: boolean|null,\n }|undefined = {forceNew: null}): Promise {\n const {forceNew} = opts;\n if (!freestylerPanelInstance || forceNew) {\n const aidaAvailability = await Host.AidaClient.AidaClient.checkAccessPreconditions();\n const aidaClient = new Host.AidaClient.AidaClient();\n const syncInfo = await new Promise(\n resolve => Host.InspectorFrontendHost.InspectorFrontendHostInstance.getSyncInformation(\n syncInfo => resolve(syncInfo)));\n freestylerPanelInstance = new FreestylerPanel(defaultView, {aidaClient, aidaAvailability, syncInfo});\n }\n\n return freestylerPanelInstance;\n }\n\n override wasShown(): void {\n this.registerCSSFiles([freestylerPanelStyles]);\n this.#viewOutput.freestylerChatUi?.restoreScrollPosition();\n this.#viewOutput.freestylerChatUi?.focusTextInput();\n }\n\n doUpdate(): void {\n this.view(this.#viewProps, this.#viewOutput, this.#contentContainer);\n }\n\n #handleSelectElementClick(): void {\n void this.#toggleSearchElementAction.execute();\n }\n\n #handleFeedbackSubmit(rpcId: number, rating: Host.AidaClient.Rating, feedback?: string): void {\n void this.#aidaClient.registerClientEvent({\n corresponding_aida_rpc_global_id: rpcId,\n disable_user_content_logging: !this.#serverSideLoggingEnabled,\n do_conversation_client_event: {\n user_feedback: {\n sentiment: rating,\n user_input: {\n comment: feedback,\n },\n },\n },\n });\n }\n\n #handleAcceptConsentClick(): void {\n this.#consentViewAcceptedSetting.set(true);\n this.#viewProps.state = FreestylerChatUiState.CHAT_VIEW;\n this.doUpdate();\n }\n\n handleAction(actionId: string): void {\n switch (actionId) {\n case 'freestyler.element-panel-context': {\n this.#viewOutput.freestylerChatUi?.focusTextInput();\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.FreestylerOpenedFromElementsPanel);\n this.#viewProps.agentType = AgentType.FREESTYLER;\n this.doUpdate();\n break;\n }\n case 'drjones.network-panel-context': {\n // TODO(samiyac): Add UMA\n this.#viewOutput.freestylerChatUi?.focusTextInput();\n this.#viewProps.agentType = AgentType.DRJONES_NETWORK_REQUEST;\n this.doUpdate();\n break;\n }\n }\n }\n\n #clearMessages(): void {\n this.#viewProps.messages = [];\n this.#viewProps.isLoading = false;\n this.#cancel();\n this.doUpdate();\n }\n\n #runAbortController = new AbortController();\n #cancel(): void {\n this.#runAbortController.abort();\n this.#runAbortController = new AbortController();\n this.#viewProps.isLoading = false;\n this.doUpdate();\n }\n\n async #startConversation(text: string, isFixQuery: boolean = false): Promise {\n // TODO(samiyac): Refactor startConversation\n this.#viewProps.messages.push({\n entity: ChatMessageEntity.USER,\n text,\n });\n this.#viewProps.isLoading = true;\n const systemMessage: ModelChatMessage = {\n entity: ChatMessageEntity.MODEL,\n aborted: false,\n suggestingFix: false,\n steps: [],\n };\n this.#viewProps.messages.push(systemMessage);\n this.doUpdate();\n\n this.#runAbortController = new AbortController();\n\n const signal = this.#runAbortController.signal;\n signal.addEventListener('abort', () => {\n systemMessage.rpcId = undefined;\n systemMessage.aborted = true;\n systemMessage.suggestingFix = false;\n const lastStep = systemMessage.steps.at(-1);\n // Mark the last step as cancelled to make the UI feel better.\n if (lastStep) {\n lastStep.canceled = true;\n }\n this.#viewProps.isLoading = false;\n this.doUpdate();\n this.#viewOutput.freestylerChatUi?.scrollToLastMessage();\n });\n\n if (this.#viewProps.agentType === AgentType.FREESTYLER) {\n await this.#conversationStepsForFreestylerAgent(text, isFixQuery, signal, systemMessage);\n } else if (this.#viewProps.agentType === AgentType.DRJONES_NETWORK_REQUEST) {\n await this.#conversationStepsForDrJonesNetworkAgent(text, signal, systemMessage);\n }\n }\n\n async #conversationStepsForFreestylerAgent(\n text: string, isFixQuery: boolean = false, signal: AbortSignal, systemMessage: ModelChatMessage): Promise {\n let step: Step = {isLoading: true};\n\n for await (const data of this.#freestylerAgent.run(\n text, {signal, selectedElement: this.#viewProps.selectedElement, isFixQuery})) {\n step.sideEffect = undefined;\n switch (data.type) {\n case ResponseType.QUERYING: {\n step = {isLoading: true};\n if (!systemMessage.steps.length) {\n systemMessage.steps.push(step);\n }\n\n break;\n }\n case ResponseType.THOUGHT: {\n step.isLoading = false;\n step.thought = data.thought;\n step.title = data.title;\n if (systemMessage.steps.at(-1) !== step) {\n systemMessage.steps.push(step);\n }\n break;\n }\n case ResponseType.SIDE_EFFECT: {\n step.isLoading = false;\n step.code = data.code;\n step.sideEffect = {\n onAnswer: data.confirm,\n };\n if (systemMessage.steps.at(-1) !== step) {\n systemMessage.steps.push(step);\n }\n break;\n }\n case ResponseType.ACTION: {\n step.isLoading = false;\n step.code = data.code;\n step.output = data.output;\n step.canceled = data.canceled;\n if (systemMessage.steps.at(-1) !== step) {\n systemMessage.steps.push(step);\n }\n break;\n }\n case ResponseType.ANSWER: {\n systemMessage.suggestingFix = data.fixable;\n systemMessage.answer = data.text;\n systemMessage.rpcId = data.rpcId;\n // When there is an answer without any thinking steps, we don't want to show the thinking step.\n if (systemMessage.steps.length === 1 && systemMessage.steps[0].isLoading) {\n systemMessage.steps.pop();\n }\n step.isLoading = false;\n this.#viewProps.isLoading = false;\n break;\n }\n\n case ResponseType.ERROR: {\n step.isLoading = false;\n systemMessage.error = data.error;\n this.#viewProps.isLoading = false;\n }\n }\n\n this.doUpdate();\n this.#viewOutput.freestylerChatUi?.scrollToLastMessage();\n }\n }\n\n async #conversationStepsForDrJonesNetworkAgent(text: string, signal: AbortSignal, systemMessage: ModelChatMessage):\n Promise {\n // TODO(samiyac): Improve loading generator\n const step: Step = {isLoading: true};\n if (!systemMessage.steps.length) {\n systemMessage.steps.push(step);\n }\n this.doUpdate();\n this.#viewOutput.freestylerChatUi?.scrollToLastMessage();\n\n for await (const data of this.#drJonesNetworkAgent.run(\n text, {signal, selectedNetworkRequest: this.#viewProps.selectedNetworkRequest})) {\n switch (data.type) {\n case DrJonesNetworkAgentResponseType.ANSWER: {\n systemMessage.answer = data.text;\n systemMessage.rpcId = data.rpcId;\n // When there is an answer without any thinking steps, we don't want to show the thinking step.\n if (systemMessage.steps.length === 1 && systemMessage.steps[0].isLoading) {\n systemMessage.steps.pop();\n }\n step.isLoading = false;\n this.#viewProps.isLoading = false;\n break;\n }\n\n case DrJonesNetworkAgentResponseType.ERROR: {\n step.isLoading = false;\n systemMessage.error = ErrorType.UNKNOWN;\n this.#viewProps.isLoading = false;\n }\n }\n\n this.doUpdate();\n this.#viewOutput.freestylerChatUi?.scrollToLastMessage();\n }\n }\n}\n\nexport class ActionDelegate implements UI.ActionRegistration.ActionDelegate {\n handleAction(\n _context: UI.Context.Context,\n actionId: string,\n ): boolean {\n switch (actionId) {\n case 'freestyler.element-panel-context':\n case 'drjones.network-panel-context': {\n void (async () => {\n const view = UI.ViewManager.ViewManager.instance().view(\n FreestylerPanel.panelName,\n );\n\n if (view) {\n await UI.ViewManager.ViewManager.instance().showView(\n FreestylerPanel.panelName,\n );\n const widget = (await view.widget()) as FreestylerPanel;\n widget.handleAction(actionId);\n }\n })();\n return true;\n }\n }\n\n return false;\n }\n}\n\nfunction setFreestylerServerSideLoggingEnabled(enabled: boolean): void {\n if (enabled) {\n localStorage.setItem('freestyler_enableServerSideLogging', 'true');\n } else {\n localStorage.setItem('freestyler_enableServerSideLogging', 'false');\n }\n}\n\nfunction isFreestylerServerSideLoggingEnabled(): boolean {\n const config = Common.Settings.Settings.instance().getHostConfig();\n if (config.aidaAvailability?.disallowLogging) {\n return false;\n }\n return localStorage.getItem('freestyler_enableServerSideLogging') !== 'false';\n}\n\n// @ts-ignore\nglobalThis.setFreestylerServerSideLoggingEnabled = setFreestylerServerSideLoggingEnabled;\n"]} \ No newline at end of file +{"version":3,"file":"FreestylerPanel.js","sourceRoot":"","sources":["../../../../../../front_end/panels/freestyler/FreestylerPanel.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as Common from '../../core/common/common.js';\nimport * as Host from '../../core/host/host.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as NetworkForward from '../../panels/network/forward/forward.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as LitHtml from '../../ui/lit-html/lit-html.js';\n\nimport {ChangeManager} from './ChangeManager.js';\nimport {\n AgentType,\n ChatMessageEntity,\n type ContextDetail,\n DOGFOOD_INFO,\n FreestylerChatUi,\n type ModelChatMessage,\n type Props as FreestylerChatUiProps,\n State as FreestylerChatUiState,\n type Step,\n} from './components/FreestylerChatUi.js';\nimport {\n DrJonesNetworkAgent,\n DrJonesNetworkAgentResponseType,\n formatHeaders,\n formatNetworkRequestTiming,\n} from './DrJonesNetworkAgent.js';\nimport {ErrorType, FIX_THIS_ISSUE_PROMPT, FreestylerAgent, ResponseType} from './FreestylerAgent.js';\nimport freestylerPanelStyles from './freestylerPanel.css.js';\n\n/*\n * TODO(nvitkov): b/346933425\n * Temporary string that should not be translated\n * as they may change often during development.\n */\nconst UIStringsTemp = {\n /**\n *@description AI assistant UI text for clearing messages.\n */\n clearMessages: 'Clear messages',\n /**\n *@description AI assistant UI tooltip text for the help button.\n */\n help: 'Help',\n /**\n *@description Title text for thinking step of DrJones Network agent.\n */\n inspectingNetworkData: 'Inspecting network data',\n /**\n *@description Thought text for thinking step of DrJones Network agent.\n */\n dataUsedToGenerateThisResponse: 'Data used to generate this response',\n /**\n *@description Heading text for the block that shows the network request details.\n */\n request: 'Request',\n /**\n *@description Heading text for the block that shows the network response details.\n */\n response: 'Response',\n /**\n *@description Prefix text for request URL.\n */\n requestUrl: 'Request URL',\n /**\n *@description Title text for request headers.\n */\n requestHeaders: 'Request Headers',\n /**\n *@description Title text for request timing details.\n */\n timing: 'Timing',\n /**\n *@description Title text for response headers.\n */\n responseHeaders: 'Response Headers',\n /**\n *@description Prefix text for response status.\n */\n responseStatus: 'Response Status',\n\n};\n\n// TODO(nvitkov): b/346933425\n// const str_ = i18n.i18n.registerUIStrings('panels/freestyler/FreestylerPanel.ts', UIStrings);\n// const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n/* eslint-disable rulesdir/l10n_i18nString_call_only_with_uistrings */\nconst i18nString = i18n.i18n.lockedString;\n\ntype ViewOutput = {\n freestylerChatUi?: FreestylerChatUi,\n};\ntype View = (input: FreestylerChatUiProps, output: ViewOutput, target: HTMLElement) => void;\n\n// TODO(ergunsh): Use the WidgetElement instead of separately creating the toolbar.\nfunction createToolbar(target: HTMLElement, {onClearClick}: {onClearClick: () => void}): void {\n const toolbarContainer = target.createChild('div', 'freestyler-toolbar-container');\n const leftToolbar = new UI.Toolbar.Toolbar('', toolbarContainer);\n const rightToolbar = new UI.Toolbar.Toolbar('freestyler-right-toolbar', toolbarContainer);\n\n const clearButton =\n new UI.Toolbar.ToolbarButton(i18nString(UIStringsTemp.clearMessages), 'clear', undefined, 'freestyler.clear');\n clearButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, onClearClick);\n leftToolbar.appendToolbarItem(clearButton);\n\n rightToolbar.appendSeparator();\n const helpButton = new UI.Toolbar.ToolbarButton(i18nString(UIStringsTemp.help), 'help', undefined, 'freestyler.help');\n helpButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, () => {\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(DOGFOOD_INFO);\n });\n rightToolbar.appendToolbarItem(helpButton);\n}\n\nfunction defaultView(input: FreestylerChatUiProps, output: ViewOutput, target: HTMLElement): void {\n // clang-format off\n LitHtml.render(LitHtml.html`\n <${FreestylerChatUi.litTagName} .props=${input} ${LitHtml.Directives.ref((el: Element|undefined) => {\n if (!el || !(el instanceof FreestylerChatUi)) {\n return;\n }\n\n output.freestylerChatUi = el;\n })}>\n `, target, {host: input}); // eslint-disable-line rulesdir/lit_html_host_this\n // clang-format on\n}\n\nlet freestylerPanelInstance: FreestylerPanel;\nexport class FreestylerPanel extends UI.Panel.Panel {\n static panelName = 'freestyler';\n\n #toggleSearchElementAction: UI.ActionRegistration.Action;\n #selectedElement: SDK.DOMModel.DOMNode|null;\n #selectedNetworkRequest: SDK.NetworkRequest.NetworkRequest|null;\n #contentContainer: HTMLElement;\n #aidaClient: Host.AidaClient.AidaClient;\n #freestylerAgent: FreestylerAgent;\n #drJonesNetworkAgent: DrJonesNetworkAgent;\n #viewProps: FreestylerChatUiProps;\n #viewOutput: ViewOutput = {};\n #serverSideLoggingEnabled = isFreestylerServerSideLoggingEnabled();\n #consentViewAcceptedSetting =\n Common.Settings.Settings.instance().createLocalSetting('freestyler-dogfood-consent-onboarding-finished', false);\n #changeManager = new ChangeManager();\n\n constructor(private view: View = defaultView, {aidaClient, aidaAvailability, syncInfo}: {\n aidaClient: Host.AidaClient.AidaClient,\n aidaAvailability: Host.AidaClient.AidaAccessPreconditions,\n syncInfo: Host.InspectorFrontendHostAPI.SyncInformation,\n }) {\n super(FreestylerPanel.panelName);\n\n createToolbar(this.contentElement, {onClearClick: this.#clearMessages.bind(this)});\n this.#toggleSearchElementAction =\n UI.ActionRegistry.ActionRegistry.instance().getAction('elements.toggle-element-search');\n this.#aidaClient = aidaClient;\n this.#contentContainer = this.contentElement.createChild('div', 'freestyler-chat-ui-container');\n\n this.#selectedElement = UI.Context.Context.instance().flavor(SDK.DOMModel.DOMNode);\n this.#selectedNetworkRequest = UI.Context.Context.instance().flavor(SDK.NetworkRequest.NetworkRequest);\n this.#viewProps = {\n state: this.#consentViewAcceptedSetting.get() ? FreestylerChatUiState.CHAT_VIEW :\n FreestylerChatUiState.CONSENT_VIEW,\n aidaAvailability,\n messages: [],\n inspectElementToggled: this.#toggleSearchElementAction.toggled(),\n selectedElement: this.#selectedElement,\n selectedNetworkRequest: this.#selectedNetworkRequest,\n isLoading: false,\n onTextSubmit: this.#startConversation.bind(this),\n onInspectElementClick: this.#handleSelectElementClick.bind(this),\n onFeedbackSubmit: this.#handleFeedbackSubmit.bind(this),\n onAcceptConsentClick: this.#handleAcceptConsentClick.bind(this),\n onCancelClick: this.#cancel.bind(this),\n onFixThisIssueClick: () => {\n void this.#startConversation(FIX_THIS_ISSUE_PROMPT, true);\n },\n onSelectedNetworkRequestClick: this.#handleSelectedNetworkRequestClick.bind(this),\n canShowFeedbackForm: this.#serverSideLoggingEnabled,\n userInfo: {\n accountImage: syncInfo.accountImage,\n accountFullName: syncInfo.accountFullName,\n },\n agentType: AgentType.FREESTYLER,\n };\n this.#toggleSearchElementAction.addEventListener(UI.ActionRegistration.Events.TOGGLED, ev => {\n this.#viewProps.inspectElementToggled = ev.data;\n this.doUpdate();\n });\n\n this.#freestylerAgent = this.#createFreestylerAgent();\n this.#drJonesNetworkAgent = this.#createDrJonesNetworkAgent();\n\n UI.Context.Context.instance().addFlavorChangeListener(SDK.DOMModel.DOMNode, ev => {\n if (this.#viewProps.selectedElement === ev.data) {\n return;\n }\n\n this.#viewProps.selectedElement = Boolean(ev.data) && ev.data.nodeType() === Node.ELEMENT_NODE ? ev.data : null;\n this.doUpdate();\n });\n UI.Context.Context.instance().addFlavorChangeListener(SDK.NetworkRequest.NetworkRequest, ev => {\n if (this.#viewProps.selectedNetworkRequest === ev.data) {\n return;\n }\n\n this.#viewProps.selectedNetworkRequest = Boolean(ev.data) ? ev.data : null;\n this.doUpdate();\n });\n this.doUpdate();\n }\n\n #createFreestylerAgent(): FreestylerAgent {\n return new FreestylerAgent({\n aidaClient: this.#aidaClient,\n changeManager: this.#changeManager,\n serverSideLoggingEnabled: this.#serverSideLoggingEnabled,\n });\n }\n\n #createDrJonesNetworkAgent(): DrJonesNetworkAgent {\n return new DrJonesNetworkAgent({\n aidaClient: this.#aidaClient,\n serverSideLoggingEnabled: this.#serverSideLoggingEnabled,\n });\n }\n\n static async instance(opts: {\n forceNew: boolean|null,\n }|undefined = {forceNew: null}): Promise {\n const {forceNew} = opts;\n if (!freestylerPanelInstance || forceNew) {\n const aidaAvailability = await Host.AidaClient.AidaClient.checkAccessPreconditions();\n const aidaClient = new Host.AidaClient.AidaClient();\n const syncInfo = await new Promise(\n resolve => Host.InspectorFrontendHost.InspectorFrontendHostInstance.getSyncInformation(\n syncInfo => resolve(syncInfo)));\n freestylerPanelInstance = new FreestylerPanel(defaultView, {aidaClient, aidaAvailability, syncInfo});\n }\n\n return freestylerPanelInstance;\n }\n\n override wasShown(): void {\n this.registerCSSFiles([freestylerPanelStyles]);\n this.#viewOutput.freestylerChatUi?.restoreScrollPosition();\n this.#viewOutput.freestylerChatUi?.focusTextInput();\n }\n\n doUpdate(): void {\n this.view(this.#viewProps, this.#viewOutput, this.#contentContainer);\n }\n\n #handleSelectElementClick(): void {\n void this.#toggleSearchElementAction.execute();\n }\n\n #handleFeedbackSubmit(rpcId: number, rating: Host.AidaClient.Rating, feedback?: string): void {\n void this.#aidaClient.registerClientEvent({\n corresponding_aida_rpc_global_id: rpcId,\n disable_user_content_logging: !this.#serverSideLoggingEnabled,\n do_conversation_client_event: {\n user_feedback: {\n sentiment: rating,\n user_input: {\n comment: feedback,\n },\n },\n },\n });\n }\n\n #handleAcceptConsentClick(): void {\n this.#consentViewAcceptedSetting.set(true);\n this.#viewProps.state = FreestylerChatUiState.CHAT_VIEW;\n this.doUpdate();\n }\n\n #handleSelectedNetworkRequestClick(): void|Promise {\n if (this.#viewProps.selectedNetworkRequest) {\n const requestLocation = NetworkForward.UIRequestLocation.UIRequestLocation.tab(\n this.#viewProps.selectedNetworkRequest, NetworkForward.UIRequestLocation.UIRequestTabs.HEADERS_COMPONENT);\n return Common.Revealer.reveal(requestLocation);\n }\n }\n\n handleAction(actionId: string): void {\n switch (actionId) {\n case 'freestyler.element-panel-context': {\n this.#viewOutput.freestylerChatUi?.focusTextInput();\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.FreestylerOpenedFromElementsPanel);\n this.#viewProps.agentType = AgentType.FREESTYLER;\n this.doUpdate();\n break;\n }\n case 'drjones.network-panel-context': {\n // TODO(samiyac): Add UMA\n this.#viewOutput.freestylerChatUi?.focusTextInput();\n this.#viewProps.agentType = AgentType.DRJONES_NETWORK_REQUEST;\n this.doUpdate();\n break;\n }\n }\n }\n\n #clearMessages(): void {\n this.#viewProps.messages = [];\n this.#viewProps.isLoading = false;\n this.#cancel();\n this.doUpdate();\n }\n\n #runAbortController = new AbortController();\n #cancel(): void {\n this.#runAbortController.abort();\n this.#runAbortController = new AbortController();\n this.#viewProps.isLoading = false;\n this.doUpdate();\n }\n\n async #startConversation(text: string, isFixQuery: boolean = false): Promise {\n // TODO(samiyac): Refactor startConversation\n this.#viewProps.messages.push({\n entity: ChatMessageEntity.USER,\n text,\n });\n this.#viewProps.isLoading = true;\n const systemMessage: ModelChatMessage = {\n entity: ChatMessageEntity.MODEL,\n suggestingFix: false,\n steps: [],\n };\n this.#viewProps.messages.push(systemMessage);\n this.doUpdate();\n\n this.#runAbortController = new AbortController();\n\n const signal = this.#runAbortController.signal;\n\n if (this.#viewProps.agentType === AgentType.FREESTYLER) {\n await this.#conversationStepsForFreestylerAgent(text, isFixQuery, signal, systemMessage);\n } else if (this.#viewProps.agentType === AgentType.DRJONES_NETWORK_REQUEST) {\n await this.#conversationStepsForDrJonesNetworkAgent(text, signal, systemMessage);\n }\n }\n\n async #conversationStepsForFreestylerAgent(\n text: string, isFixQuery: boolean = false, signal: AbortSignal, systemMessage: ModelChatMessage): Promise {\n let step: Step = {isLoading: true};\n\n for await (const data of this.#freestylerAgent.run(\n text, {signal, selectedElement: this.#viewProps.selectedElement, isFixQuery})) {\n step.sideEffect = undefined;\n switch (data.type) {\n case ResponseType.QUERYING: {\n step = {isLoading: true};\n if (!systemMessage.steps.length) {\n systemMessage.steps.push(step);\n }\n\n break;\n }\n case ResponseType.TITLE: {\n step.title = data.title;\n if (systemMessage.steps.at(-1) !== step) {\n systemMessage.steps.push(step);\n }\n break;\n }\n case ResponseType.THOUGHT: {\n step.isLoading = false;\n step.thought = data.thought;\n if (systemMessage.steps.at(-1) !== step) {\n systemMessage.steps.push(step);\n }\n break;\n }\n case ResponseType.SIDE_EFFECT: {\n step.isLoading = false;\n step.code = data.code;\n step.sideEffect = {\n onAnswer: data.confirm,\n };\n if (systemMessage.steps.at(-1) !== step) {\n systemMessage.steps.push(step);\n }\n break;\n }\n case ResponseType.ACTION: {\n step.isLoading = false;\n step.code = data.code;\n step.output = data.output;\n step.canceled = data.canceled;\n if (systemMessage.steps.at(-1) !== step) {\n systemMessage.steps.push(step);\n }\n break;\n }\n case ResponseType.ANSWER: {\n systemMessage.suggestingFix = data.fixable;\n systemMessage.answer = data.text;\n systemMessage.rpcId = data.rpcId;\n // When there is an answer without any thinking steps, we don't want to show the thinking step.\n if (systemMessage.steps.length === 1 && systemMessage.steps[0].isLoading) {\n systemMessage.steps.pop();\n }\n step.isLoading = false;\n this.#viewProps.isLoading = false;\n break;\n }\n\n case ResponseType.ERROR: {\n step.isLoading = false;\n systemMessage.error = data.error;\n systemMessage.suggestingFix = false;\n systemMessage.rpcId = undefined;\n this.#viewProps.isLoading = false;\n if (data.error === ErrorType.ABORT) {\n const lastStep = systemMessage.steps.at(-1);\n // Mark the last step as cancelled to make the UI feel better.\n if (lastStep) {\n lastStep.canceled = true;\n }\n }\n }\n }\n\n this.doUpdate();\n this.#viewOutput.freestylerChatUi?.scrollToLastMessage();\n }\n }\n\n async #conversationStepsForDrJonesNetworkAgent(text: string, signal: AbortSignal, systemMessage: ModelChatMessage):\n Promise {\n // TODO(samiyac): Only display the thinking step with context details when it is the first message\n const step: Step = {\n isLoading: true,\n title: UIStringsTemp.inspectingNetworkData,\n thought: UIStringsTemp.dataUsedToGenerateThisResponse,\n contextDetails: this.#createContextDetailsForDrJonesNetworkAgent(),\n };\n\n if (!systemMessage.steps.length) {\n systemMessage.steps.push(step);\n }\n this.doUpdate();\n this.#viewOutput.freestylerChatUi?.scrollToLastMessage();\n\n for await (const data of this.#drJonesNetworkAgent.run(\n text, {signal, selectedNetworkRequest: this.#viewProps.selectedNetworkRequest})) {\n switch (data.type) {\n case DrJonesNetworkAgentResponseType.ANSWER: {\n systemMessage.answer = data.text;\n systemMessage.rpcId = data.rpcId;\n step.isLoading = false;\n this.#viewProps.isLoading = false;\n break;\n }\n\n case DrJonesNetworkAgentResponseType.ERROR: {\n step.isLoading = false;\n systemMessage.error = ErrorType.UNKNOWN;\n this.#viewProps.isLoading = false;\n }\n }\n\n this.doUpdate();\n this.#viewOutput.freestylerChatUi?.scrollToLastMessage();\n }\n }\n\n #createContextDetailsForDrJonesNetworkAgent(): ContextDetail[] {\n if (this.#viewProps.selectedNetworkRequest) {\n const requestContextDetail: ContextDetail = {\n title: UIStringsTemp.request,\n text: UIStringsTemp.requestUrl + ': ' + this.#viewProps.selectedNetworkRequest.url() + '\\n\\n' +\n formatHeaders(UIStringsTemp.requestHeaders, this.#viewProps.selectedNetworkRequest.requestHeaders()),\n };\n const responseContextDetail: ContextDetail = {\n title: UIStringsTemp.response,\n text: UIStringsTemp.responseStatus + ': ' + this.#viewProps.selectedNetworkRequest.statusCode + ' ' +\n this.#viewProps.selectedNetworkRequest.statusText + '\\n\\n' +\n formatHeaders(UIStringsTemp.responseHeaders, this.#viewProps.selectedNetworkRequest.responseHeaders),\n };\n const timingContextDetail: ContextDetail = {\n title: UIStringsTemp.timing,\n text: formatNetworkRequestTiming(this.#viewProps.selectedNetworkRequest),\n };\n return [\n requestContextDetail,\n responseContextDetail,\n timingContextDetail,\n ];\n }\n return [];\n }\n}\n\nexport class ActionDelegate implements UI.ActionRegistration.ActionDelegate {\n handleAction(\n _context: UI.Context.Context,\n actionId: string,\n ): boolean {\n switch (actionId) {\n case 'freestyler.element-panel-context':\n case 'drjones.network-panel-context': {\n void (async () => {\n const view = UI.ViewManager.ViewManager.instance().view(\n FreestylerPanel.panelName,\n );\n\n if (view) {\n await UI.ViewManager.ViewManager.instance().showView(\n FreestylerPanel.panelName,\n );\n const widget = (await view.widget()) as FreestylerPanel;\n widget.handleAction(actionId);\n }\n })();\n return true;\n }\n }\n\n return false;\n }\n}\n\nfunction setFreestylerServerSideLoggingEnabled(enabled: boolean): void {\n if (enabled) {\n localStorage.setItem('freestyler_enableServerSideLogging', 'true');\n } else {\n localStorage.setItem('freestyler_enableServerSideLogging', 'false');\n }\n}\n\nfunction isFreestylerServerSideLoggingEnabled(): boolean {\n const config = Common.Settings.Settings.instance().getHostConfig();\n if (config.aidaAvailability?.disallowLogging) {\n return false;\n }\n return localStorage.getItem('freestyler_enableServerSideLogging') !== 'false';\n}\n\n// @ts-ignore\nglobalThis.setFreestylerServerSideLoggingEnabled = setFreestylerServerSideLoggingEnabled;\n"]} \ No newline at end of file diff --git a/public/panels/freestyler/components/FreestylerChatUi.d.ts b/public/panels/freestyler/components/FreestylerChatUi.d.ts index d74230e27..fd1179870 100644 --- a/public/panels/freestyler/components/FreestylerChatUi.d.ts +++ b/public/panels/freestyler/components/FreestylerChatUi.d.ts @@ -14,10 +14,15 @@ export interface Step { output?: string; canceled?: boolean; sideEffect?: ConfirmSideEffectDialog; + contextDetails?: ContextDetail[]; } interface ConfirmSideEffectDialog { onAnswer: (result: boolean) => void; } +export interface ContextDetail { + title: string; + text: string; +} export declare const enum ChatMessageEntity { MODEL = "model", USER = "user" @@ -32,7 +37,6 @@ export interface ModelChatMessage { steps: Step[]; answer?: string; error?: ErrorType; - aborted: boolean; rpcId?: number; } export type ChatMessage = UserChatMessage | ModelChatMessage; @@ -51,6 +55,7 @@ export interface Props { onAcceptConsentClick: () => void; onCancelClick: () => void; onFixThisIssueClick: () => void; + onSelectedNetworkRequestClick: () => void | Promise; inspectElementToggled: boolean; state: State; aidaAvailability: Host.AidaClient.AidaAccessPreconditions; diff --git a/public/panels/freestyler/components/FreestylerChatUi.js b/public/panels/freestyler/components/FreestylerChatUi.js index cad582841..8261d02ef 100644 --- a/public/panels/freestyler/components/FreestylerChatUi.js +++ b/public/panels/freestyler/components/FreestylerChatUi.js @@ -54,19 +54,9 @@ const UIStringsTemp = { */ noElementSelected: 'No element selected', /** - *@description Text for the empty state of the Freestyler panel. + *@description Text for the empty state of the AI assistant panel. */ emptyStateText: 'How can I help you?', - /** - * @description The title of the button that allows submitting positive - * feedback about the response for freestyler. - */ - thumbsUp: 'Thumbs up', - /** - * @description The title of the button that allows submitting negative - * feedback about the response for freestyler. - */ - thumbsDown: 'Thumbs down', /** * @description The error message when the user is not logged in into Chrome. */ @@ -253,6 +243,19 @@ export class FreestylerChatUi extends HTMLElement { } message.scrollIntoViewIfNeeded(); } + #isTextInputDisabled = () => { + const isAidaAvailable = this.#props.aidaAvailability === "available" /* Host.AidaClient.AidaAccessPreconditions.AVAILABLE */; + const showsSideEffects = this.#props.messages.some(message => { + return message.entity === "model" /* ChatMessageEntity.MODEL */ && message.steps.some(step => { + return Boolean(step.sideEffect); + }); + }); + const isInputDisabledCheckForFreestylerAgent = !Boolean(this.#props.selectedElement) || showsSideEffects; + const isInputDisabledCheckForDrJonesNetworkAgent = !Boolean(this.#props.selectedNetworkRequest); + return (this.#props.agentType === "freestyler" /* AgentType.FREESTYLER */ && isInputDisabledCheckForFreestylerAgent) || + (this.#props.agentType === "drjones-network-request" /* AgentType.DRJONES_NETWORK_REQUEST */ && isInputDisabledCheckForDrJonesNetworkAgent) || + !isAidaAvailable; + }; #handleScroll = (ev) => { if (!ev.target || !(ev.target instanceof HTMLElement)) { return; @@ -365,11 +368,27 @@ export class FreestylerChatUi extends HTMLElement { }} > ` : LitHtml.nothing; + const contextDetails = step.contextDetails && step.contextDetails?.length > 0 ? + LitHtml.html `${LitHtml.Directives.repeat(step.contextDetails, contextDetail => { + return LitHtml.html `
+ <${MarkdownView.CodeBlock.CodeBlock.litTagName} + .code=${contextDetail.text} + .codeLang=${'js'} + .displayToolbar=${false} + .displayNotice=${false} + .heading=${{ + text: i18nString(contextDetail.title), + showCopyButton: true, + }} + > +
`; + })}` : LitHtml.nothing; return LitHtml.html `
${thought} ${code} ${sideEffects} ${output} + ${contextDetails}
`; // clang-format on } @@ -398,7 +417,9 @@ export class FreestylerChatUi extends HTMLElement { }); // clang-format off return LitHtml.html ` -
+
${this.#renderStepBadge(step, options)} @@ -447,9 +468,6 @@ export class FreestylerChatUi extends HTMLElement { // clang-format on } #renderError(message) { - if (message.aborted) { - return LitHtml.html `

${i18nString(UIStringsTemp.stoppedResponse)}

`; - } if (message.error) { let errorMessage; switch (message.error) { @@ -459,8 +477,10 @@ export class FreestylerChatUi extends HTMLElement { case "max-steps" /* ErrorType.MAX_STEPS */: errorMessage = UIStringsTemp.maxStepsError; break; + case "abort" /* ErrorType.ABORT */: + return LitHtml.html `

${i18nString(UIStringsTemp.stoppedResponse)}

`; } - return LitHtml.html `

${i18nString(errorMessage)}

`; + return LitHtml.html `

${i18nString(errorMessage)}

`; } return LitHtml.nothing; } @@ -484,7 +504,7 @@ export class FreestylerChatUi extends HTMLElement { ${name}
-
${message.text}
+
${this.#renderTextAsMarkdown(message.text)}
`; // clang-format on } @@ -512,7 +532,7 @@ export class FreestylerChatUi extends HTMLElement { ${message.rpcId !== undefined ? this.#renderRateButtons(message.rpcId) : LitHtml.nothing} - ${message.suggestingFix + ${message.suggestingFix && isLast ? LitHtml.html `<${Buttons.Button.Button.litTagName} .data=${{ variant: "outlined" /* Buttons.Button.Variant.OUTLINED */, @@ -541,7 +561,8 @@ export class FreestylerChatUi extends HTMLElement { }); // clang-format off return LitHtml.html `
-
+
<${IconButton.Icon.Icon.litTagName} name="file-script"> ${this.#props.selectedNetworkRequest?.name()}
`; @@ -604,13 +625,9 @@ export class FreestylerChatUi extends HTMLElement { // clang-format on }; #renderEmptyState = () => { - const suggestions = [ - 'Why is the element not visible?', - 'Why is this element overlapping another element?', - 'How can I center this element?', - ]; + const suggestions = this.#getSuggestions(); // clang-format off - return LitHtml.html `
+ return LitHtml.html `
<${IconButton.Icon.Icon.litTagName} @@ -629,7 +646,7 @@ export class FreestylerChatUi extends HTMLElement { size: "REGULAR" /* Buttons.Button.Size.REGULAR */, title: suggestion, jslogContext: 'suggestion', - disabled: this.#props.aidaAvailability !== "available" /* Host.AidaClient.AidaAccessPreconditions.AVAILABLE */, + disabled: this.#isTextInputDisabled(), }} >${suggestion}`; })} @@ -637,24 +654,26 @@ export class FreestylerChatUi extends HTMLElement {
`; // clang-format on }; + #getSuggestions = () => { + switch (this.#props.agentType) { + case "freestyler" /* AgentType.FREESTYLER */: + return [ + 'Why is the element not visible?', + 'Why is this element overlapping another element?', + 'How can I center this element?', + ]; + case "drjones-network-request" /* AgentType.DRJONES_NETWORK_REQUEST */: + return [ + 'Why is this network request taking longer to complete?', + ]; + } + }; #renderChatInput = () => { - // TODO(ergunsh): Show a better UI for the states where Aida client is not available. - const isAidaAvailable = this.#props.aidaAvailability === "available" /* Host.AidaClient.AidaAccessPreconditions.AVAILABLE */; - const showsSideEffects = this.#props.messages.some(message => { - return message.entity === "model" /* ChatMessageEntity.MODEL */ && message.steps.some(step => { - return Boolean(step.sideEffect); - }); - }); - const isInputDisabledCheckForFreestylerAgent = !Boolean(this.#props.selectedElement) || showsSideEffects; - const isInputDisabledCheckForDrJonesNetworkAgent = !Boolean(this.#props.selectedNetworkRequest); - const isInputDisabled = (this.#props.agentType === "freestyler" /* AgentType.FREESTYLER */ && isInputDisabledCheckForFreestylerAgent) || - (this.#props.agentType === "drjones-network-request" /* AgentType.DRJONES_NETWORK_REQUEST */ && isInputDisabledCheckForDrJonesNetworkAgent) || - !isAidaAvailable; // clang-format off return LitHtml.html `
\n ${this.#props.isLoading\n ? LitHtml.html`<${Buttons.Button.Button.litTagName}\n class=\"chat-input-button\"\n aria-label=${i18nString(UIStringsTemp.cancelButtonTitle)}\n @click=${this.#handleCancel}\n .data=${\n {\n variant: Buttons.Button.Variant.PRIMARY,\n size: Buttons.Button.Size.SMALL,\n disabled: isInputDisabled,\n iconName: 'stop',\n title: i18nString(UIStringsTemp.cancelButtonTitle),\n jslogContext: 'stop',\n } as Buttons.Button.ButtonData\n }\n >`\n : LitHtml.html`<${Buttons.Button.Button.litTagName}\n class=\"chat-input-button\"\n aria-label=${i18nString(UIStringsTemp.sendButtonTitle)}\n .data=${\n {\n type: 'submit',\n variant: Buttons.Button.Variant.ICON,\n size: Buttons.Button.Size.SMALL,\n disabled: isInputDisabled,\n iconName: 'send',\n title: i18nString(UIStringsTemp.sendButtonTitle),\n jslogContext: 'send',\n } as Buttons.Button.ButtonData\n }\n >`}\n
`;\n // clang-format on\n };\n\n #getDisclaimerText = (): string => {\n switch (this.#props.agentType) {\n case AgentType.FREESTYLER:\n return UIStringsTemp.inputDisclaimerForFreestylerAgent;\n case AgentType.DRJONES_NETWORK_REQUEST:\n return UIStringsTemp.inputDisclaimerForDrJonesNetworkAgent;\n }\n };\n\n #renderChatUi = (): LitHtml.TemplateResult => {\n // clang-format off\n return LitHtml.html`\n
\n ${\n this.#props.messages.length > 0\n ? this.#renderMessages()\n : this.#renderEmptyState()\n }\n
\n
\n \n \n
\n ${this.#renderChatInput()}\n
\n
\n
${i18nString(\n this.#getDisclaimerText(),\n )} See dogfood terms.\n
\n
\n
\n `;\n // clang-format on\n };\n\n #renderConsentView = (): LitHtml.TemplateResult => {\n // clang-format off\n return LitHtml.html`\n
\n

\n ${i18nString(UIStringsTemp.consentScreenHeading)}\n

\n
\n ${i18nString(UIStringsTemp.consentTextAiDisclaimer)}\n
    \n
  • ${i18nString(UIStringsTemp.consentTextDataDisclaimer)}
  • \n
  • ${i18nString(UIStringsTemp.consentTextVisibilityDisclaimer)}
  • \n
  • ${i18nString(UIStringsTemp.consentTextDoNotUseDisclaimer)}
  • \n
  • See dogfood terms.
  • \n
\n <${Buttons.Button.Button.litTagName}\n class=\"accept-button\"\n @click=${this.#props.onAcceptConsentClick}\n .data=${{\n variant: Buttons.Button.Variant.PRIMARY,\n jslogContext: 'accept',\n } as Buttons.Button.ButtonData}\n >${\n i18nString(UIStringsTemp.acceptButtonTitle)\n }\n
\n
\n `;\n // clang-format on\n };\n\n #render(): void {\n switch (this.#props.state) {\n case State.CHAT_VIEW:\n LitHtml.render(this.#renderChatUi(), this.#shadow, {host: this});\n break;\n case State.CONSENT_VIEW:\n LitHtml.render(this.#renderConsentView(), this.#shadow, {host: this});\n break;\n }\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-freestyler-chat-ui': FreestylerChatUi;\n }\n}\n\nexport const FOR_TEST = {\n MarkdownRendererWithCodeBlock,\n};\n\ncustomElements.define('devtools-freestyler-chat-ui', FreestylerChatUi);\n"]} \ No newline at end of file +{"version":3,"file":"FreestylerChatUi.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/freestyler/components/FreestylerChatUi.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../../core/common/common.js';\nimport * as Host from '../../../core/host/host.js';\nimport * as i18n from '../../../core/i18n/i18n.js';\nimport type * as Platform from '../../../core/platform/platform.js';\nimport type * as SDK from '../../../core/sdk/sdk.js';\nimport * as Marked from '../../../third_party/marked/marked.js';\nimport * as Buttons from '../../../ui/components/buttons/buttons.js';\nimport * as IconButton from '../../../ui/components/icon_button/icon_button.js';\nimport * as MarkdownView from '../../../ui/components/markdown_view/markdown_view.js';\nimport * as Spinners from '../../../ui/components/spinners/spinners.js';\nimport * as LitHtml from '../../../ui/lit-html/lit-html.js';\nimport * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';\nimport {ErrorType} from '../FreestylerAgent.js';\n\nimport freestylerChatUiStyles from './freestylerChatUi.css.js';\nimport {ProvideFeedback, type ProvideFeedbackProps} from './ProvideFeedback.js';\n\nconst DOGFOOD_FEEDBACK_URL = 'https://goo.gle/freestyler-feedback' as Platform.DevToolsPath.UrlString;\nexport const DOGFOOD_INFO = 'https://goo.gle/freestyler-dogfood' as Platform.DevToolsPath.UrlString;\n\n/*\n * TODO(nvitkov): b/346933425\n * Temporary string that should not be translated\n * as they may change often during development.\n */\nconst UIStringsTemp = {\n /**\n *@description Placeholder text for the chat UI input.\n */\n inputPlaceholderForFreestylerAgent: 'Ask a question about the selected element',\n /**\n *@description Placeholder text for the chat UI input.\n */\n inputPlaceholderForDrJonesNetworkAgent: 'Ask a question about the selected network request',\n /**\n *@description Disclaimer text right after the chat input.\n */\n inputDisclaimerForFreestylerAgent:\n 'Chat messages and any data the inspected page can access via Web APIs are sent to Google and may be seen by human reviewers to improve this feature. This is an experimental AI feature and won\\'t always get it right.',\n /**\n *@description Disclaimer text right after the chat input.\n */\n inputDisclaimerForDrJonesNetworkAgent:\n 'Chat messages and the selected network request are sent to Google and may be seen by human reviewers to improve this feature. This is an experimental AI feature and won\\'t always get it right.',\n /**\n *@description Title for the send icon button.\n */\n sendButtonTitle: 'Send',\n /**\n *@description Title for the cancel icon button.\n */\n cancelButtonTitle: 'Cancel',\n /**\n *@description Label for the \"select an element\" button.\n */\n selectAnElement: 'Select an element',\n /**\n *@description Label for the \"select an element\" button.\n */\n noElementSelected: 'No element selected',\n /**\n *@description Text for the empty state of the AI assistant panel.\n */\n emptyStateText: 'How can I help you?',\n /**\n * @description The error message when the user is not logged in into Chrome.\n */\n notLoggedIn: 'This feature is only available when you sign into Chrome with your Google account',\n /**\n * @description The error message when the user is not logged in into Chrome.\n */\n syncIsOff: 'This feature requires you to turn on Chrome sync',\n /**\n * @description The error message when the LLM loop is stopped for some reason (Max steps reached or request to LLM failed)\n */\n systemError:\n 'Something unforeseen happened and I can no longer continue. Try your request again and see if that resolves the issue.',\n /**\n * @description The error message when the LLM loop is stopped for some reason (Max steps reached or request to LLM failed)\n */\n maxStepsError: 'Seems like I am stuck with the investigation. It would be better if you start over.',\n /**\n *@description Displayed when the user stop the response\n */\n stoppedResponse: 'You stopped this response',\n /**\n * @description Message shown when the user is offline.\n */\n offline: 'Check your internet connection and try again',\n /**\n *@description Heading for the consent view.\n */\n consentScreenHeading: 'Things to consider',\n /**\n *@description Title of the button for accepting in the consent screen.\n */\n acceptButtonTitle: 'Accept',\n /**\n *@description Consent view main text\n */\n consentTextAiDisclaimer: 'This feature uses AI and might produce inaccurate information.',\n /**\n *@description Consent view data collection text\n */\n consentTextDataDisclaimer:\n 'Your inputs and the information from the page you are using this feature for are sent to Google.',\n /**\n *@description Consent view data collection text\n */\n consentTextDoNotUseDisclaimer: 'Do not use on pages with personal or sensitive information.',\n /**\n *@description Consent view data visibility text\n */\n consentTextVisibilityDisclaimer: 'Data may be seen by human reviewers and can be used to improve this feature.',\n /**\n * @description Side effect confirmation text\n */\n sideEffectConfirmationDescription: 'The code contains side effects. Do you wish to continue?',\n /**\n * @description Side effect confirmation text for the button that says \"Continue\"\n */\n positiveSideEffectConfirmation: 'Continue',\n /**\n * @description Side effect confirmation text for the button that says \"Cancel\"\n */\n negativeSideEffectConfirmation: 'Cancel',\n /**\n *@description Name of the dogfood program.\n */\n dogfood: 'Dogfood',\n /**\n *@description Link text for redirecting to feedback form\n */\n feedbackLink: 'Send feedback',\n /**\n *@description Button text for \"Fix this issue\" button\n */\n fixThisIssue: 'Fix this issue',\n /**\n *@description The generic name of the AI Assistant (do not translate)\n */\n aiAssistant: 'AI assistant',\n /**\n *@description The fallback text when we can't find the user full name\n */\n you: 'You',\n /**\n *@description The fallback text when a step has no title yet\n */\n investigating: 'Investigating',\n /**\n *@description Prefix to the title of each thinking step of a user action is required to continue\n */\n paused: 'Paused',\n /**\n *@description Heading text for the code block that shows the executed code.\n */\n codeExecuted: 'Code executed',\n /**\n *@description Heading text for the code block that shows the code to be executed after side effect confirmation.\n */\n codeToExecute: 'Code to execute',\n /**\n *@description Heading text for the code block that shows the returned data.\n */\n dataReturned: 'Data returned',\n};\n// const str_ = i18n.i18n.registerUIStrings('panels/freestyler/components/FreestylerChatUi.ts', UIStrings);\n// const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n/* eslint-disable rulesdir/l10n_i18nString_call_only_with_uistrings */\nconst i18nString = i18n.i18n.lockedString;\n\nfunction getInputPlaceholderString(\n aidaAvailability: Host.AidaClient.AidaAccessPreconditions, agentType: AgentType): string {\n switch (aidaAvailability) {\n case Host.AidaClient.AidaAccessPreconditions.AVAILABLE:\n switch (agentType) {\n case AgentType.FREESTYLER:\n return i18nString(UIStringsTemp.inputPlaceholderForFreestylerAgent);\n case AgentType.DRJONES_NETWORK_REQUEST:\n return i18nString(UIStringsTemp.inputPlaceholderForDrJonesNetworkAgent);\n }\n case Host.AidaClient.AidaAccessPreconditions.NO_ACCOUNT_EMAIL:\n return i18nString(UIStringsTemp.notLoggedIn);\n case Host.AidaClient.AidaAccessPreconditions.NO_ACTIVE_SYNC:\n return i18nString(UIStringsTemp.syncIsOff);\n case Host.AidaClient.AidaAccessPreconditions.NO_INTERNET:\n return i18nString(UIStringsTemp.offline);\n }\n}\n\nexport interface Step {\n isLoading: boolean;\n thought?: string;\n title?: string;\n code?: string;\n output?: string;\n canceled?: boolean;\n sideEffect?: ConfirmSideEffectDialog;\n contextDetails?: ContextDetail[];\n}\n\ninterface ConfirmSideEffectDialog {\n onAnswer: (result: boolean) => void;\n}\n\nexport interface ContextDetail {\n title: string;\n text: string;\n}\n\nexport const enum ChatMessageEntity {\n MODEL = 'model',\n USER = 'user',\n}\n\nexport interface UserChatMessage {\n entity: ChatMessageEntity.USER;\n text: string;\n}\nexport interface ModelChatMessage {\n entity: ChatMessageEntity.MODEL;\n suggestingFix: boolean;\n steps: Step[];\n answer?: string;\n error?: ErrorType;\n rpcId?: number;\n}\n\nexport type ChatMessage = UserChatMessage|ModelChatMessage;\n\nexport const enum State {\n CONSENT_VIEW = 'consent-view',\n CHAT_VIEW = 'chat-view',\n}\n\nexport const enum AgentType {\n FREESTYLER = 'freestyler',\n DRJONES_NETWORK_REQUEST = 'drjones-network-request',\n}\n\nexport interface Props {\n onTextSubmit: (text: string) => void;\n onInspectElementClick: () => void;\n onFeedbackSubmit: (rpcId: number, rate: Host.AidaClient.Rating, feedback?: string) => void;\n onAcceptConsentClick: () => void;\n onCancelClick: () => void;\n onFixThisIssueClick: () => void;\n onSelectedNetworkRequestClick: () => void | Promise;\n inspectElementToggled: boolean;\n state: State;\n aidaAvailability: Host.AidaClient.AidaAccessPreconditions;\n messages: ChatMessage[];\n selectedElement: SDK.DOMModel.DOMNode|null;\n selectedNetworkRequest: SDK.NetworkRequest.NetworkRequest|null;\n isLoading: boolean;\n canShowFeedbackForm: boolean;\n userInfo: Pick;\n agentType: AgentType;\n}\n\n// The model returns multiline code blocks in an erroneous way with the language being in new line.\n// This renderer takes that into account and correctly updates the parsed multiline token with the language\n// correctly identified and stripped from the content.\n// Example:\n// ```\n// css <-- This should have been on the first line.\n// * {\n// color: red;\n// }\n// ```\nclass MarkdownRendererWithCodeBlock extends MarkdownView.MarkdownView.MarkdownInsightRenderer {\n override templateForToken(token: Marked.Marked.Token): LitHtml.TemplateResult|null {\n if (token.type === 'code') {\n const lines = (token.text as string).split('\\n');\n if (lines[0]?.trim() === 'css') {\n token.lang = 'css';\n token.text = lines.slice(1).join('\\n');\n }\n }\n\n return super.templateForToken(token);\n }\n}\n\nexport class FreestylerChatUi extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-freestyler-chat-ui`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n readonly #markdownRenderer = new MarkdownRendererWithCodeBlock();\n #scrollTop?: number;\n #props: Props;\n\n constructor(props: Props) {\n super();\n this.#props = props;\n }\n\n set props(props: Props) {\n this.#props = props;\n this.#render();\n }\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [freestylerChatUiStyles];\n this.#render();\n }\n\n focusTextInput(): void {\n const textArea = this.#shadow.querySelector('.chat-input') as HTMLTextAreaElement;\n if (!textArea) {\n return;\n }\n\n textArea.focus();\n }\n\n restoreScrollPosition(): void {\n if (this.#scrollTop === undefined) {\n return;\n }\n\n const scrollContainer = this.#shadow.querySelector('.messages-scroll-container') as HTMLElement;\n if (!scrollContainer) {\n return;\n }\n\n scrollContainer.scrollTop = this.#scrollTop;\n }\n\n scrollToLastMessage(): void {\n const message = this.#shadow.querySelector('.chat-message:last-child') as HTMLDivElement;\n if (!message) {\n return;\n }\n message.scrollIntoViewIfNeeded();\n }\n\n #isTextInputDisabled = (): boolean => {\n const isAidaAvailable = this.#props.aidaAvailability === Host.AidaClient.AidaAccessPreconditions.AVAILABLE;\n const showsSideEffects = this.#props.messages.some(message => {\n return message.entity === ChatMessageEntity.MODEL && message.steps.some(step => {\n return Boolean(step.sideEffect);\n });\n });\n const isInputDisabledCheckForFreestylerAgent = !Boolean(this.#props.selectedElement) || showsSideEffects;\n const isInputDisabledCheckForDrJonesNetworkAgent = !Boolean(this.#props.selectedNetworkRequest);\n return (this.#props.agentType === AgentType.FREESTYLER && isInputDisabledCheckForFreestylerAgent) ||\n (this.#props.agentType === AgentType.DRJONES_NETWORK_REQUEST && isInputDisabledCheckForDrJonesNetworkAgent) ||\n !isAidaAvailable;\n };\n\n #handleScroll = (ev: Event): void => {\n if (!ev.target || !(ev.target instanceof HTMLElement)) {\n return;\n }\n\n this.#scrollTop = ev.target.scrollTop;\n };\n\n #handleSubmit = (ev: SubmitEvent): void => {\n ev.preventDefault();\n const textArea = this.#shadow.querySelector('.chat-input') as HTMLTextAreaElement;\n if (!textArea || !textArea.value) {\n return;\n }\n this.#props.onTextSubmit(textArea.value);\n textArea.value = '';\n };\n\n #handleTextAreaKeyDown = (ev: KeyboardEvent): void => {\n if (!ev.target || !(ev.target instanceof HTMLTextAreaElement)) {\n return;\n }\n\n if (ev.key === 'Enter' && !ev.shiftKey) {\n // Do not go to a new line whenver Shift + Enter is pressed.\n ev.preventDefault();\n // Only submit the text when there isn't a request already in flight.\n if (!this.#props.isLoading) {\n this.#props.onTextSubmit(ev.target.value);\n ev.target.value = '';\n }\n }\n };\n\n #handleCancel = (ev: SubmitEvent): void => {\n ev.preventDefault();\n\n if (!this.#props.isLoading) {\n return;\n }\n\n this.#props.onCancelClick();\n };\n\n #renderRateButtons(rpcId: number): LitHtml.TemplateResult {\n // clang-format off\n return LitHtml.html`<${ProvideFeedback.litTagName}\n .props=${{\n onFeedbackSubmit: (rating, feedback) => {\n this.#props.onFeedbackSubmit(rpcId, rating, feedback);\n },\n canShowFeedbackForm: this.#props.canShowFeedbackForm,\n } as ProvideFeedbackProps}\n >`;\n // clang-format on\n }\n\n #renderTextAsMarkdown(text: string): LitHtml.TemplateResult {\n let tokens = [];\n try {\n tokens = Marked.Marked.lexer(text);\n for (const token of tokens) {\n // Try to render all the tokens to make sure that\n // they all have a template defined for them. If there\n // isn't any template defined for a token, we'll fallback\n // to rendering the text as plain text instead of markdown.\n this.#markdownRenderer.renderToken(token);\n }\n } catch (err) {\n // The tokens were not parsed correctly or\n // one of the tokens are not supported, so we\n // continue to render this as text.\n return LitHtml.html`${text}`;\n }\n\n // clang-format off\n return LitHtml.html`<${MarkdownView.MarkdownView.MarkdownView.litTagName}\n .data=${{tokens, renderer: this.#markdownRenderer} as MarkdownView.MarkdownView.MarkdownViewData}>\n `;\n // clang-format on\n }\n\n #renderTitle(step: Step): LitHtml.LitTemplate {\n const paused = step.sideEffect ? LitHtml.html`${i18nString(UIStringsTemp.paused)}: ` :\n LitHtml.nothing;\n const actionTitle = step.title ?? `${i18nString(UIStringsTemp.investigating)}…`;\n\n return LitHtml.html`${paused}${actionTitle}`;\n }\n\n #renderStepDetails(step: Step, options: {isLast: boolean}): LitHtml.LitTemplate {\n const sideEffects =\n options.isLast && step.sideEffect ? this.#renderSideEffectConfirmationUi(step) : LitHtml.nothing;\n const thought = step.thought ? LitHtml.html`

${this.#renderTextAsMarkdown(step.thought)}

` : LitHtml.nothing;\n // If there is no \"output\" yet, it means we didn't execute the code yet (e.g. maybe it is still waiting for confirmation from the user)\n // thus we show \"Code to execute\" text rather than \"Code executed\" text on the heading of the code block.\n const codeHeadingText = (step.output && !step.canceled) ? i18nString(UIStringsTemp.codeExecuted) :\n i18nString(UIStringsTemp.codeToExecute);\n // If there is output, we don't show notice on this code block and instead show\n // it in the data returned code block.\n // clang-format off\n const code = step.code ? LitHtml.html`
\n <${MarkdownView.CodeBlock.CodeBlock.litTagName}\n .code=${step.code.trim()}\n .codeLang=${'js'}\n .displayToolbar=${false}\n .displayNotice=${!Boolean(step.output)}\n .heading=${{\n text: codeHeadingText,\n showCopyButton: true,\n }}\n >\n
` : LitHtml.nothing;\n const output = step.output ? LitHtml.html`
\n <${MarkdownView.CodeBlock.CodeBlock.litTagName}\n .code=${step.output}\n .codeLang=${'js'}\n .displayToolbar=${false}\n .displayNotice=${true}\n .heading=${{\n text: i18nString(UIStringsTemp.dataReturned),\n showCopyButton: false,\n }}\n >\n
` : LitHtml.nothing;\n const contextDetails = step.contextDetails && step.contextDetails?.length > 0 ?\n LitHtml.html`${LitHtml.Directives.repeat(\n step.contextDetails,\n contextDetail => {\n return LitHtml.html`
\n <${MarkdownView.CodeBlock.CodeBlock.litTagName}\n .code=${contextDetail.text}\n .codeLang=${'js'}\n .displayToolbar=${false}\n .displayNotice=${false}\n .heading=${{\n text: i18nString(contextDetail.title),\n showCopyButton: true,\n }}\n >\n
`;\n },\n )}` : LitHtml.nothing;\n\n return LitHtml.html`
\n ${thought}\n ${code}\n ${sideEffects}\n ${output}\n ${contextDetails}\n
`;\n // clang-format on\n }\n\n #renderStepBadge(step: Step, options: {isLast: boolean}): LitHtml.LitTemplate {\n if (this.#props.isLoading && options.isLast && !step.sideEffect) {\n return LitHtml.html`<${Spinners.Spinner.Spinner.litTagName}>`;\n }\n\n let iconName: string = 'checkmark';\n if (options.isLast && step.sideEffect) {\n iconName = 'pause-circle';\n } else if (step.canceled) {\n iconName = 'cross';\n }\n\n return LitHtml.html`<${IconButton.Icon.Icon.litTagName}\n class=\"indicator\"\n .name=${iconName}\n >`;\n }\n\n #renderStep(step: Step, options: {isLast: boolean}): LitHtml.LitTemplate {\n const stepClasses = LitHtml.Directives.classMap({\n step: true,\n empty: !step.thought && !step.code,\n paused: Boolean(step.sideEffect),\n canceled: Boolean(step.canceled),\n });\n // clang-format off\n return LitHtml.html`\n
\n \n
\n ${this.#renderStepBadge(step, options)}\n ${this.#renderTitle(step)}\n <${IconButton.Icon.Icon.litTagName}\n class=\"arrow\"\n .name=${'chevron-down'}\n >\n
\n
\n ${this.#renderStepDetails(step, {\n isLast: options.isLast,\n })}\n
`;\n // clang-format on\n }\n\n #renderSideEffectConfirmationUi(step: Step): LitHtml.LitTemplate {\n if (!step.sideEffect) {\n return LitHtml.nothing;\n }\n const sideEffectAction = step.sideEffect.onAnswer;\n\n // clang-format off\n return LitHtml.html`\n

${i18nString(UIStringsTemp.sideEffectConfirmationDescription)}

\n
\n <${Buttons.Button.Button.litTagName}\n .data=${\n {\n variant: Buttons.Button.Variant.OUTLINED,\n jslogContext: 'decline-execute-code',\n } as Buttons.Button.ButtonData\n }\n @click=${() => sideEffectAction(false)}\n >${i18nString(\n UIStringsTemp.negativeSideEffectConfirmation,\n )}\n <${Buttons.Button.Button.litTagName}\n .data=${\n {\n variant: Buttons.Button.Variant.PRIMARY,\n jslogContext: 'accept-execute-code',\n iconName: 'play',\n } as Buttons.Button.ButtonData\n }\n @click=${() => sideEffectAction(true)}\n >${\n i18nString(UIStringsTemp.positiveSideEffectConfirmation)\n }\n
\n
`;\n // clang-format on\n }\n\n #renderError(message: ModelChatMessage): LitHtml.LitTemplate {\n if (message.error) {\n let errorMessage;\n switch (message.error) {\n case ErrorType.UNKNOWN:\n errorMessage = UIStringsTemp.systemError;\n break;\n case ErrorType.MAX_STEPS:\n errorMessage = UIStringsTemp.maxStepsError;\n break;\n case ErrorType.ABORT:\n return LitHtml.html`

${\n i18nString(UIStringsTemp.stoppedResponse)}

`;\n }\n\n return LitHtml.html`

${i18nString(errorMessage)}

`;\n }\n\n return LitHtml.nothing;\n }\n\n #renderChatMessage = (message: ChatMessage, {isLast}: {isLast: boolean}): LitHtml.TemplateResult => {\n // TODO(b/365068104): Render user's message as markdown too.\n if (message.entity === ChatMessageEntity.USER) {\n const name = this.#props.userInfo.accountFullName || i18nString(UIStringsTemp.you);\n const image = this.#props.userInfo.accountImage ?\n LitHtml.html`\"Account` :\n LitHtml.html`<${IconButton.Icon.Icon.litTagName}\n .name=${'profile'}\n >`;\n // clang-format off\n return LitHtml.html`\n
\n ${image}\n
\n ${name}\n
\n
\n
${this.#renderTextAsMarkdown(message.text)}
\n
`;\n // clang-format on\n }\n\n // clang-format off\n return LitHtml.html`\n
\n
\n <${IconButton.Icon.Icon.litTagName}\n name=\"smart-assistant\"\n >\n
\n ${i18nString(UIStringsTemp.aiAssistant)}\n
\n
\n ${LitHtml.Directives.repeat(\n message.steps,\n (_, index) => index,\n step => {\n return this.#renderStep(step, {\n isLast: [...message.steps.values()].at(-1) === step && isLast,\n });\n },\n )}\n ${\n message.answer\n ? LitHtml.html`

${this.#renderTextAsMarkdown(message.answer)}

`\n : LitHtml.nothing\n }\n ${this.#renderError(message)}\n
\n ${\n message.rpcId !== undefined\n ? this.#renderRateButtons(message.rpcId)\n : LitHtml.nothing\n }\n ${\n message.suggestingFix && isLast\n ? LitHtml.html`<${Buttons.Button.Button.litTagName}\n .data=${{\n variant: Buttons.Button.Variant.OUTLINED,\n jslogContext: 'fix-this-issue',\n } as Buttons.Button.ButtonData}\n @click=${this.#props.onFixThisIssueClick}\n >${i18nString(\n UIStringsTemp.fixThisIssue,\n )}`\n : LitHtml.nothing\n }\n
\n
\n `;\n // clang-format on\n };\n\n #renderSelection(): LitHtml.TemplateResult {\n switch (this.#props.agentType) {\n case AgentType.FREESTYLER:\n return this.#renderSelectAnElement();\n case AgentType.DRJONES_NETWORK_REQUEST:\n return this.#renderSelectedNetworkRequest();\n }\n }\n\n #renderSelectedNetworkRequest = (): LitHtml.TemplateResult => {\n const resourceClass = LitHtml.Directives.classMap({\n 'not-selected': !this.#props.selectedNetworkRequest,\n 'resource-link': true,\n });\n\n // clang-format off\n return LitHtml.html`
\n
\n <${IconButton.Icon.Icon.litTagName} name=\"file-script\">\n ${this.#props.selectedNetworkRequest?.name()}\n
`;\n // clang-format on\n };\n\n #renderSelectAnElement = (): LitHtml.TemplateResult => {\n const resourceClass = LitHtml.Directives.classMap({\n 'not-selected': !this.#props.selectedElement,\n 'resource-link': true,\n });\n\n // clang-format off\n return LitHtml.html`\n
\n <${Buttons.Button.Button.litTagName}\n .data=${{\n variant: Buttons.Button.Variant.ICON_TOGGLE,\n size: Buttons.Button.Size.REGULAR,\n iconName: 'select-element',\n toggledIconName: 'select-element',\n toggleType: Buttons.Button.ToggleType.PRIMARY,\n toggled: this.#props.inspectElementToggled,\n title: i18nString(UIStringsTemp.selectAnElement),\n jslogContext: 'select-element',\n } as Buttons.Button.ButtonData}\n @click=${this.#props.onInspectElementClick}\n >\n
${\n this.#props.selectedElement\n ? LitHtml.Directives.until(\n Common.Linkifier.Linkifier.linkify(this.#props.selectedElement),\n )\n : LitHtml.html`${\n i18nString(UIStringsTemp.noElementSelected)\n }`\n }
\n
`;\n // clang-format on\n };\n\n #renderFeedbackLink = (): LitHtml.TemplateResult => {\n // clang-format off\n return LitHtml.html`\n <${IconButton.Icon.Icon.litTagName}\n name=\"dog-paw\"\n class=\"feedback-icon\"\n >\n ${i18nString(UIStringsTemp.dogfood)}\n -\n ${\n i18nString(UIStringsTemp.feedbackLink)\n }`;\n // clang-format on\n };\n\n #renderMessages = (): LitHtml.TemplateResult => {\n // clang-format off\n return LitHtml.html`\n
\n
\n ${this.#props.messages.map((message, _, array) =>\n this.#renderChatMessage(message, {\n isLast: array.at(-1) === message,\n }),\n )}\n
\n
\n `;\n // clang-format on\n };\n\n #renderEmptyState = (): LitHtml.TemplateResult => {\n const suggestions: string[] = this.#getSuggestions();\n\n // clang-format off\n return LitHtml.html`
\n
\n
\n <${IconButton.Icon.Icon.litTagName}\n name=\"smart-assistant\"\n >\n
\n ${i18nString(UIStringsTemp.emptyStateText)}\n
\n
\n ${suggestions.map(suggestion => {\n return LitHtml.html`<${Buttons.Button.Button.litTagName}\n class=\"suggestion\"\n @click=${() => this.#props.onTextSubmit(suggestion)}\n .data=${\n {\n variant: Buttons.Button.Variant.OUTLINED,\n size: Buttons.Button.Size.REGULAR,\n title: suggestion,\n jslogContext: 'suggestion',\n disabled: this.#isTextInputDisabled(),\n } as Buttons.Button.ButtonData\n }\n >${suggestion}`;\n })}\n
\n
`;\n // clang-format on\n };\n\n #getSuggestions = (): string[] => {\n switch (this.#props.agentType) {\n case AgentType.FREESTYLER:\n return [\n 'Why is the element not visible?',\n 'Why is this element overlapping another element?',\n 'How can I center this element?',\n ];\n case AgentType.DRJONES_NETWORK_REQUEST:\n return [\n 'Why is this network request taking longer to complete?',\n ];\n }\n };\n\n #renderChatInput = (): LitHtml.TemplateResult => {\n // clang-format off\n return LitHtml.html`\n
\n \n ${this.#props.isLoading\n ? LitHtml.html`<${Buttons.Button.Button.litTagName}\n class=\"chat-input-button\"\n aria-label=${i18nString(UIStringsTemp.cancelButtonTitle)}\n @click=${this.#handleCancel}\n .data=${\n {\n variant: Buttons.Button.Variant.PRIMARY,\n size: Buttons.Button.Size.SMALL,\n disabled: this.#isTextInputDisabled(),\n iconName: 'stop',\n title: i18nString(UIStringsTemp.cancelButtonTitle),\n jslogContext: 'stop',\n } as Buttons.Button.ButtonData\n }\n >`\n : LitHtml.html`<${Buttons.Button.Button.litTagName}\n class=\"chat-input-button\"\n aria-label=${i18nString(UIStringsTemp.sendButtonTitle)}\n .data=${\n {\n type: 'submit',\n variant: Buttons.Button.Variant.ICON,\n size: Buttons.Button.Size.SMALL,\n disabled: this.#isTextInputDisabled(),\n iconName: 'send',\n title: i18nString(UIStringsTemp.sendButtonTitle),\n jslogContext: 'send',\n } as Buttons.Button.ButtonData\n }\n >`}\n
`;\n // clang-format on\n };\n\n #getDisclaimerText = (): string => {\n switch (this.#props.agentType) {\n case AgentType.FREESTYLER:\n return UIStringsTemp.inputDisclaimerForFreestylerAgent;\n case AgentType.DRJONES_NETWORK_REQUEST:\n return UIStringsTemp.inputDisclaimerForDrJonesNetworkAgent;\n }\n };\n\n #renderChatUi = (): LitHtml.TemplateResult => {\n // clang-format off\n return LitHtml.html`\n
\n ${\n this.#props.messages.length > 0\n ? this.#renderMessages()\n : this.#renderEmptyState()\n }\n
\n
\n \n \n
\n ${this.#renderChatInput()}\n
\n
\n

${i18nString(\n this.#getDisclaimerText(),\n )} See dogfood terms.\n

\n
\n
\n `;\n // clang-format on\n };\n\n #renderConsentView = (): LitHtml.TemplateResult => {\n // clang-format off\n return LitHtml.html`\n
\n

\n ${i18nString(UIStringsTemp.consentScreenHeading)}\n

\n
\n ${i18nString(UIStringsTemp.consentTextAiDisclaimer)}\n
    \n
  • ${i18nString(UIStringsTemp.consentTextDataDisclaimer)}
  • \n
  • ${i18nString(UIStringsTemp.consentTextVisibilityDisclaimer)}
  • \n
  • ${i18nString(UIStringsTemp.consentTextDoNotUseDisclaimer)}
  • \n
  • See dogfood terms.
  • \n
\n <${Buttons.Button.Button.litTagName}\n class=\"accept-button\"\n @click=${this.#props.onAcceptConsentClick}\n .data=${{\n variant: Buttons.Button.Variant.PRIMARY,\n jslogContext: 'accept',\n } as Buttons.Button.ButtonData}\n >${\n i18nString(UIStringsTemp.acceptButtonTitle)\n }\n
\n
\n `;\n // clang-format on\n };\n\n #render(): void {\n switch (this.#props.state) {\n case State.CHAT_VIEW:\n LitHtml.render(this.#renderChatUi(), this.#shadow, {host: this});\n break;\n case State.CONSENT_VIEW:\n LitHtml.render(this.#renderConsentView(), this.#shadow, {host: this});\n break;\n }\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-freestyler-chat-ui': FreestylerChatUi;\n }\n}\n\nexport const FOR_TEST = {\n MarkdownRendererWithCodeBlock,\n};\n\ncustomElements.define('devtools-freestyler-chat-ui', FreestylerChatUi);\n"]} \ No newline at end of file diff --git a/public/panels/freestyler/components/FreestylerChatUi.test.js b/public/panels/freestyler/components/FreestylerChatUi.test.js index c544bb88c..ece9ac79f 100644 --- a/public/panels/freestyler/components/FreestylerChatUi.test.js +++ b/public/panels/freestyler/components/FreestylerChatUi.test.js @@ -40,6 +40,7 @@ css onAcceptConsentClick: noop, onCancelClick: noop, onFixThisIssueClick: noop, + onSelectedNetworkRequestClick: noop, inspectElementToggled: false, state: "chat-view" /* Freestyler.State.CHAT_VIEW */, agentType: "freestyler" /* Freestyler.AgentType.FREESTYLER */, @@ -60,7 +61,6 @@ css { entity: "model" /* Freestyler.ChatMessageEntity.MODEL */, suggestingFix: false, - aborted: false, steps: [ { isLoading: false, diff --git a/public/panels/freestyler/components/FreestylerChatUi.test.js.map b/public/panels/freestyler/components/FreestylerChatUi.test.js.map index 679253edf..0605f678b 100644 --- a/public/panels/freestyler/components/FreestylerChatUi.test.js.map +++ b/public/panels/freestyler/components/FreestylerChatUi.test.js.map @@ -1 +1 @@ -{"version":3,"file":"FreestylerChatUi.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/freestyler/components/FreestylerChatUi.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Host from '../../../core/host/host.js';\nimport type * as SDK from '../../../core/sdk/sdk.js';\nimport {renderElementIntoDOM} from '../../../testing/DOMHelpers.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport * as Marked from '../../../third_party/marked/marked.js';\nimport * as MarkdownView from '../../../ui/components/markdown_view/markdown_view.js';\nimport * as Freestyler from '../freestyler.js';\n\nconst {MarkdownRendererWithCodeBlock} = Freestyler.FOR_TEST;\n\ndescribeWithEnvironment('FreestylerChatUi', () => {\n describe('MarkdownRendererWithCodeBlock', () => {\n it('should transform code token for multiline code blocks with `css` language written in the first line', () => {\n const renderer = new MarkdownRendererWithCodeBlock();\n const templateForTokenStub =\n sinon.stub(MarkdownView.MarkdownView.MarkdownInsightRenderer.prototype, 'templateForToken');\n const codeBlock = `\\`\\`\\`\ncss\n* {\n color: red;\n}\n\\`\\`\\``;\n const codeToken = Marked.Marked.lexer(codeBlock)[0] as Marked.Marked.Tokens.Code;\n assert.isEmpty(codeToken.lang);\n renderer.renderToken(codeToken);\n\n sinon.assert.calledWith(templateForTokenStub, sinon.match({\n lang: 'css',\n text: `* {\n color: red;\n}`,\n }));\n });\n });\n\n function getProp(options: Partial): Freestyler.Props {\n const noop = () => {};\n const messages: Freestyler.ChatMessage[] = options.messages ?? [];\n return {\n onTextSubmit: noop,\n onInspectElementClick: noop,\n onFeedbackSubmit: noop,\n onAcceptConsentClick: noop,\n onCancelClick: noop,\n onFixThisIssueClick: noop,\n inspectElementToggled: false,\n state: Freestyler.State.CHAT_VIEW,\n agentType: Freestyler.AgentType.FREESTYLER,\n aidaAvailability: Host.AidaClient.AidaAccessPreconditions.AVAILABLE,\n messages,\n selectedElement: {} as unknown as SDK.DOMModel.DOMNode,\n selectedNetworkRequest: {} as unknown as SDK.NetworkRequest.NetworkRequest,\n isLoading: false,\n canShowFeedbackForm: false,\n userInfo: {},\n ...options,\n };\n }\n\n describe('SideEffects', () => {\n it('should show SideEffects when the step contains \"sideEffect\" object', async () => {\n const props = getProp({\n messages: [\n {\n entity: Freestyler.ChatMessageEntity.MODEL,\n suggestingFix: false,\n aborted: false,\n steps: [\n {\n isLoading: false,\n title: 'Updating element styles',\n thought: 'Updating element styles',\n code: '$0.style.background = \"blue\";',\n sideEffect: {\n onAnswer: () => {},\n },\n },\n ],\n },\n ],\n });\n const chat = new Freestyler.FreestylerChatUi(props);\n renderElementIntoDOM(chat);\n\n const sideEffect = chat.shadowRoot!.querySelector('.side-effect-confirmation');\n assert.exists(sideEffect);\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"FreestylerChatUi.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/freestyler/components/FreestylerChatUi.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Host from '../../../core/host/host.js';\nimport type * as SDK from '../../../core/sdk/sdk.js';\nimport {renderElementIntoDOM} from '../../../testing/DOMHelpers.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport * as Marked from '../../../third_party/marked/marked.js';\nimport * as MarkdownView from '../../../ui/components/markdown_view/markdown_view.js';\nimport * as Freestyler from '../freestyler.js';\n\nconst {MarkdownRendererWithCodeBlock} = Freestyler.FOR_TEST;\n\ndescribeWithEnvironment('FreestylerChatUi', () => {\n describe('MarkdownRendererWithCodeBlock', () => {\n it('should transform code token for multiline code blocks with `css` language written in the first line', () => {\n const renderer = new MarkdownRendererWithCodeBlock();\n const templateForTokenStub =\n sinon.stub(MarkdownView.MarkdownView.MarkdownInsightRenderer.prototype, 'templateForToken');\n const codeBlock = `\\`\\`\\`\ncss\n* {\n color: red;\n}\n\\`\\`\\``;\n const codeToken = Marked.Marked.lexer(codeBlock)[0] as Marked.Marked.Tokens.Code;\n assert.isEmpty(codeToken.lang);\n renderer.renderToken(codeToken);\n\n sinon.assert.calledWith(templateForTokenStub, sinon.match({\n lang: 'css',\n text: `* {\n color: red;\n}`,\n }));\n });\n });\n\n function getProp(options: Partial): Freestyler.Props {\n const noop = () => {};\n const messages: Freestyler.ChatMessage[] = options.messages ?? [];\n return {\n onTextSubmit: noop,\n onInspectElementClick: noop,\n onFeedbackSubmit: noop,\n onAcceptConsentClick: noop,\n onCancelClick: noop,\n onFixThisIssueClick: noop,\n onSelectedNetworkRequestClick: noop,\n inspectElementToggled: false,\n state: Freestyler.State.CHAT_VIEW,\n agentType: Freestyler.AgentType.FREESTYLER,\n aidaAvailability: Host.AidaClient.AidaAccessPreconditions.AVAILABLE,\n messages,\n selectedElement: {} as unknown as SDK.DOMModel.DOMNode,\n selectedNetworkRequest: {} as unknown as SDK.NetworkRequest.NetworkRequest,\n isLoading: false,\n canShowFeedbackForm: false,\n userInfo: {},\n ...options,\n };\n }\n\n describe('SideEffects', () => {\n it('should show SideEffects when the step contains \"sideEffect\" object', async () => {\n const props = getProp({\n messages: [\n {\n entity: Freestyler.ChatMessageEntity.MODEL,\n suggestingFix: false,\n steps: [\n {\n isLoading: false,\n title: 'Updating element styles',\n thought: 'Updating element styles',\n code: '$0.style.background = \"blue\";',\n sideEffect: {\n onAnswer: () => {},\n },\n },\n ],\n },\n ],\n });\n const chat = new Freestyler.FreestylerChatUi(props);\n renderElementIntoDOM(chat);\n\n const sideEffect = chat.shadowRoot!.querySelector('.side-effect-confirmation');\n assert.exists(sideEffect);\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/freestyler/components/ProvideFeedback.js b/public/panels/freestyler/components/ProvideFeedback.js index 81113d608..ee762fa50 100644 --- a/public/panels/freestyler/components/ProvideFeedback.js +++ b/public/panels/freestyler/components/ProvideFeedback.js @@ -16,12 +16,12 @@ import provideFeedbackStyles from './provideFeedback.css.js'; const UIStringsTemp = { /** * @description The title of the button that allows submitting positive - * feedback about the response for freestyler. + * feedback about the response for AI assistant. */ thumbsUp: 'Thumbs up', /** * @description The title of the button that allows submitting negative - * feedback about the response for freestyler. + * feedback about the response for AI assistant. */ thumbsDown: 'Thumbs down', /** @@ -47,7 +47,7 @@ const UIStringsTemp = { close: 'Close', /** * @description The title of the button that opens a page to report a legal - * issue with the Freestyler message. + * issue with the AI assistant message. */ report: 'Report legal issue', }; @@ -108,7 +108,7 @@ export class ProvideFeedback extends HTMLElement { variant: "icon" /* Buttons.Button.Variant.ICON */, size: "SMALL" /* Buttons.Button.Size.SMALL */, iconName: 'thumb-up', - toggledIconName: 'thumb-up', + toggledIconName: 'thumb-up-filled', toggled: this.#currentRating === "POSITIVE" /* Host.AidaClient.Rating.POSITIVE */, toggleType: "primary-toggle" /* Buttons.Button.ToggleType.PRIMARY */, title: i18nString(UIStringsTemp.thumbsUp), @@ -121,7 +121,7 @@ export class ProvideFeedback extends HTMLElement { variant: "icon" /* Buttons.Button.Variant.ICON */, size: "SMALL" /* Buttons.Button.Size.SMALL */, iconName: 'thumb-down', - toggledIconName: 'thumb-down', + toggledIconName: 'thumb-down-filled', toggled: this.#currentRating === "NEGATIVE" /* Host.AidaClient.Rating.NEGATIVE */, toggleType: "primary-toggle" /* Buttons.Button.ToggleType.PRIMARY */, title: i18nString(UIStringsTemp.thumbsDown), diff --git a/public/panels/freestyler/components/ProvideFeedback.js.map b/public/panels/freestyler/components/ProvideFeedback.js.map index 8b55fb686..08a9d6c05 100644 --- a/public/panels/freestyler/components/ProvideFeedback.js.map +++ b/public/panels/freestyler/components/ProvideFeedback.js.map @@ -1 +1 @@ -{"version":3,"file":"ProvideFeedback.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/freestyler/components/ProvideFeedback.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Host from '../../../core/host/host.js';\nimport * as i18n from '../../../core/i18n/i18n.js';\nimport type * as Platform from '../../../core/platform/platform.js';\nimport * as Buttons from '../../../ui/components/buttons/buttons.js';\nimport * as Input from '../../../ui/components/input/input.js';\nimport * as LitHtml from '../../../ui/lit-html/lit-html.js';\nimport * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';\n\nimport provideFeedbackStyles from './provideFeedback.css.js';\n\n/*\n * TODO(nvitkov): b/346933425\n * Temporary string that should not be translated\n * as they may change often during development.\n */\nconst UIStringsTemp = {\n\n /**\n * @description The title of the button that allows submitting positive\n * feedback about the response for freestyler.\n */\n thumbsUp: 'Thumbs up',\n /**\n * @description The title of the button that allows submitting negative\n * feedback about the response for freestyler.\n */\n thumbsDown: 'Thumbs down',\n /**\n * @description The placeholder text for the feedback input.\n */\n provideFeedbackPlaceholder: 'Provide additional feedback',\n /**\n * @description The disclaimer text that tells the user what will be shared\n * and what will be stored.\n */\n disclaimer: 'Feedback submitted will also include your conversation',\n /**\n * @description The button text for the action of submitting feedback.\n */\n submit: 'Submit',\n /**\n * @description The header of the feedback form asking.\n */\n whyThisRating: 'Why did you choose this rating? (optional)',\n /**\n * @description The button text for the action that hides the feedback form.\n */\n close: 'Close',\n /**\n * @description The title of the button that opens a page to report a legal\n * issue with the Freestyler message.\n */\n report: 'Report legal issue',\n};\n// const str_ = i18n.i18n.registerUIStrings('panels/freestyler/components/AiRatings.ts', UIStrings);\n// const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n/* eslint-disable rulesdir/l10n_i18nString_call_only_with_uistrings */\nconst i18nString = i18n.i18n.lockedString;\n\nconst REPORT_URL = 'https://support.google.com/legal/troubleshooter/1114905?hl=en#ts=1115658%2C13380504' as\n Platform.DevToolsPath.UrlString;\nexport interface ProvideFeedbackProps {\n onFeedbackSubmit: (rate: Host.AidaClient.Rating, feedback?: string) => void;\n canShowFeedbackForm: boolean;\n}\n\nexport class ProvideFeedback extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-provide-feedback`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n #props: ProvideFeedbackProps;\n #isShowingFeedbackForm = false;\n #currentRating?: Host.AidaClient.Rating;\n\n constructor(props: ProvideFeedbackProps) {\n super();\n this.#props = props;\n }\n\n set props(props: ProvideFeedbackProps) {\n this.#props = props;\n this.#render();\n }\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [provideFeedbackStyles, Input.textInputStyles];\n this.#render();\n }\n\n #handleRateClick(rating: Host.AidaClient.Rating): void {\n if (this.#currentRating === rating) {\n return;\n }\n\n this.#currentRating = rating;\n this.#isShowingFeedbackForm = this.#props.canShowFeedbackForm;\n this.#props.onFeedbackSubmit(this.#currentRating);\n this.#render();\n }\n\n #handleClose = (): void => {\n this.#isShowingFeedbackForm = false;\n this.#render();\n };\n\n #handleSubmit = (ev: SubmitEvent): void => {\n ev.preventDefault();\n const input = this.#shadow.querySelector('.feedback-input') as HTMLInputElement;\n if (!this.#currentRating || !input || !input.value) {\n return;\n }\n this.#props.onFeedbackSubmit(this.#currentRating, input.value);\n this.#isShowingFeedbackForm = false;\n this.#render();\n };\n\n #handleReportClick = (): void => {\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(REPORT_URL);\n };\n\n #renderButtons(): LitHtml.TemplateResult {\n // clang-format off\n return LitHtml.html`\n <${Buttons.Button.Button.litTagName}\n .data=${{\n variant: Buttons.Button.Variant.ICON,\n size: Buttons.Button.Size.SMALL,\n iconName: 'thumb-up',\n toggledIconName: 'thumb-up',\n toggled: this.#currentRating === Host.AidaClient.Rating.POSITIVE,\n toggleType: Buttons.Button.ToggleType.PRIMARY,\n title: i18nString(UIStringsTemp.thumbsUp),\n jslogContext: 'thumbs-up',\n } as Buttons.Button.ButtonData}\n @click=${() => this.#handleRateClick(Host.AidaClient.Rating.POSITIVE)}\n >\n <${Buttons.Button.Button.litTagName}\n .data=${{\n variant: Buttons.Button.Variant.ICON,\n size: Buttons.Button.Size.SMALL,\n iconName: 'thumb-down',\n toggledIconName: 'thumb-down',\n toggled: this.#currentRating === Host.AidaClient.Rating.NEGATIVE,\n toggleType: Buttons.Button.ToggleType.PRIMARY,\n title: i18nString(UIStringsTemp.thumbsDown),\n jslogContext: 'thumbs-down',\n } as Buttons.Button.ButtonData}\n @click=${() => this.#handleRateClick(Host.AidaClient.Rating.NEGATIVE)}\n >\n
\n <${Buttons.Button.Button.litTagName}\n .data=${\n {\n variant: Buttons.Button.Variant.ICON,\n size: Buttons.Button.Size.SMALL,\n title: i18nString(UIStringsTemp.report),\n iconName: 'report',\n jslogContext: 'report',\n } as Buttons.Button.ButtonData\n }\n @click=${this.#handleReportClick}\n >\n `;\n // clang-format on\n }\n\n #renderFeedbackForm(): LitHtml.LitTemplate {\n // clang-format off\n return LitHtml.html`\n
\n
\n

${i18nString(\n UIStringsTemp.whyThisRating,\n )}

\n <${Buttons.Button.Button.litTagName}\n aria-label=${i18nString(UIStringsTemp.close)}\n @click=${this.#handleClose}\n .data=${\n {\n variant: Buttons.Button.Variant.ICON,\n iconName: 'cross',\n size: Buttons.Button.Size.SMALL,\n title: i18nString(UIStringsTemp.close),\n jslogContext: 'close',\n } as Buttons.Button.ButtonData\n }\n >\n
\n \n ${\n i18nString(UIStringsTemp.disclaimer)\n }\n <${Buttons.Button.Button.litTagName}\n aria-label=${i18nString(UIStringsTemp.submit)}\n .data=${\n {\n type: 'submit',\n variant: Buttons.Button.Variant.OUTLINED,\n size: Buttons.Button.Size.SMALL,\n title: i18nString(UIStringsTemp.submit),\n jslogContext: 'send',\n } as Buttons.Button.ButtonData\n }\n >${\n i18nString(UIStringsTemp.submit)\n }\n
\n `;\n // clang-format on\n }\n\n #render(): void {\n // clang-format off\n LitHtml.render(\n LitHtml.html`\n
\n
\n ${this.#renderButtons()}\n
\n ${this.#isShowingFeedbackForm\n ? this.#renderFeedbackForm()\n : LitHtml.nothing\n }\n
`,\n this.#shadow,\n {host: this},\n );\n // clang-format on\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-provide-feedback': ProvideFeedback;\n }\n}\n\ncustomElements.define('devtools-provide-feedback', ProvideFeedback);\n"]} \ No newline at end of file +{"version":3,"file":"ProvideFeedback.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/freestyler/components/ProvideFeedback.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Host from '../../../core/host/host.js';\nimport * as i18n from '../../../core/i18n/i18n.js';\nimport type * as Platform from '../../../core/platform/platform.js';\nimport * as Buttons from '../../../ui/components/buttons/buttons.js';\nimport * as Input from '../../../ui/components/input/input.js';\nimport * as LitHtml from '../../../ui/lit-html/lit-html.js';\nimport * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';\n\nimport provideFeedbackStyles from './provideFeedback.css.js';\n\n/*\n * TODO(nvitkov): b/346933425\n * Temporary string that should not be translated\n * as they may change often during development.\n */\nconst UIStringsTemp = {\n\n /**\n * @description The title of the button that allows submitting positive\n * feedback about the response for AI assistant.\n */\n thumbsUp: 'Thumbs up',\n /**\n * @description The title of the button that allows submitting negative\n * feedback about the response for AI assistant.\n */\n thumbsDown: 'Thumbs down',\n /**\n * @description The placeholder text for the feedback input.\n */\n provideFeedbackPlaceholder: 'Provide additional feedback',\n /**\n * @description The disclaimer text that tells the user what will be shared\n * and what will be stored.\n */\n disclaimer: 'Feedback submitted will also include your conversation',\n /**\n * @description The button text for the action of submitting feedback.\n */\n submit: 'Submit',\n /**\n * @description The header of the feedback form asking.\n */\n whyThisRating: 'Why did you choose this rating? (optional)',\n /**\n * @description The button text for the action that hides the feedback form.\n */\n close: 'Close',\n /**\n * @description The title of the button that opens a page to report a legal\n * issue with the AI assistant message.\n */\n report: 'Report legal issue',\n};\n// const str_ = i18n.i18n.registerUIStrings('panels/freestyler/components/AiRatings.ts', UIStrings);\n// const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n/* eslint-disable rulesdir/l10n_i18nString_call_only_with_uistrings */\nconst i18nString = i18n.i18n.lockedString;\n\nconst REPORT_URL = 'https://support.google.com/legal/troubleshooter/1114905?hl=en#ts=1115658%2C13380504' as\n Platform.DevToolsPath.UrlString;\nexport interface ProvideFeedbackProps {\n onFeedbackSubmit: (rate: Host.AidaClient.Rating, feedback?: string) => void;\n canShowFeedbackForm: boolean;\n}\n\nexport class ProvideFeedback extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-provide-feedback`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n #props: ProvideFeedbackProps;\n #isShowingFeedbackForm = false;\n #currentRating?: Host.AidaClient.Rating;\n\n constructor(props: ProvideFeedbackProps) {\n super();\n this.#props = props;\n }\n\n set props(props: ProvideFeedbackProps) {\n this.#props = props;\n this.#render();\n }\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [provideFeedbackStyles, Input.textInputStyles];\n this.#render();\n }\n\n #handleRateClick(rating: Host.AidaClient.Rating): void {\n if (this.#currentRating === rating) {\n return;\n }\n\n this.#currentRating = rating;\n this.#isShowingFeedbackForm = this.#props.canShowFeedbackForm;\n this.#props.onFeedbackSubmit(this.#currentRating);\n this.#render();\n }\n\n #handleClose = (): void => {\n this.#isShowingFeedbackForm = false;\n this.#render();\n };\n\n #handleSubmit = (ev: SubmitEvent): void => {\n ev.preventDefault();\n const input = this.#shadow.querySelector('.feedback-input') as HTMLInputElement;\n if (!this.#currentRating || !input || !input.value) {\n return;\n }\n this.#props.onFeedbackSubmit(this.#currentRating, input.value);\n this.#isShowingFeedbackForm = false;\n this.#render();\n };\n\n #handleReportClick = (): void => {\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(REPORT_URL);\n };\n\n #renderButtons(): LitHtml.TemplateResult {\n // clang-format off\n return LitHtml.html`\n <${Buttons.Button.Button.litTagName}\n .data=${{\n variant: Buttons.Button.Variant.ICON,\n size: Buttons.Button.Size.SMALL,\n iconName: 'thumb-up',\n toggledIconName: 'thumb-up-filled',\n toggled: this.#currentRating === Host.AidaClient.Rating.POSITIVE,\n toggleType: Buttons.Button.ToggleType.PRIMARY,\n title: i18nString(UIStringsTemp.thumbsUp),\n jslogContext: 'thumbs-up',\n } as Buttons.Button.ButtonData}\n @click=${() => this.#handleRateClick(Host.AidaClient.Rating.POSITIVE)}\n >\n <${Buttons.Button.Button.litTagName}\n .data=${{\n variant: Buttons.Button.Variant.ICON,\n size: Buttons.Button.Size.SMALL,\n iconName: 'thumb-down',\n toggledIconName: 'thumb-down-filled',\n toggled: this.#currentRating === Host.AidaClient.Rating.NEGATIVE,\n toggleType: Buttons.Button.ToggleType.PRIMARY,\n title: i18nString(UIStringsTemp.thumbsDown),\n jslogContext: 'thumbs-down',\n } as Buttons.Button.ButtonData}\n @click=${() => this.#handleRateClick(Host.AidaClient.Rating.NEGATIVE)}\n >\n
\n <${Buttons.Button.Button.litTagName}\n .data=${\n {\n variant: Buttons.Button.Variant.ICON,\n size: Buttons.Button.Size.SMALL,\n title: i18nString(UIStringsTemp.report),\n iconName: 'report',\n jslogContext: 'report',\n } as Buttons.Button.ButtonData\n }\n @click=${this.#handleReportClick}\n >\n `;\n // clang-format on\n }\n\n #renderFeedbackForm(): LitHtml.LitTemplate {\n // clang-format off\n return LitHtml.html`\n \n
\n

${i18nString(\n UIStringsTemp.whyThisRating,\n )}

\n <${Buttons.Button.Button.litTagName}\n aria-label=${i18nString(UIStringsTemp.close)}\n @click=${this.#handleClose}\n .data=${\n {\n variant: Buttons.Button.Variant.ICON,\n iconName: 'cross',\n size: Buttons.Button.Size.SMALL,\n title: i18nString(UIStringsTemp.close),\n jslogContext: 'close',\n } as Buttons.Button.ButtonData\n }\n >\n
\n \n ${\n i18nString(UIStringsTemp.disclaimer)\n }\n <${Buttons.Button.Button.litTagName}\n aria-label=${i18nString(UIStringsTemp.submit)}\n .data=${\n {\n type: 'submit',\n variant: Buttons.Button.Variant.OUTLINED,\n size: Buttons.Button.Size.SMALL,\n title: i18nString(UIStringsTemp.submit),\n jslogContext: 'send',\n } as Buttons.Button.ButtonData\n }\n >${\n i18nString(UIStringsTemp.submit)\n }\n
\n `;\n // clang-format on\n }\n\n #render(): void {\n // clang-format off\n LitHtml.render(\n LitHtml.html`\n
\n
\n ${this.#renderButtons()}\n
\n ${this.#isShowingFeedbackForm\n ? this.#renderFeedbackForm()\n : LitHtml.nothing\n }\n
`,\n this.#shadow,\n {host: this},\n );\n // clang-format on\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-provide-feedback': ProvideFeedback;\n }\n}\n\ncustomElements.define('devtools-provide-feedback', ProvideFeedback);\n"]} \ No newline at end of file diff --git a/public/panels/freestyler/components/freestylerChatUi.css.js b/public/panels/freestyler/components/freestylerChatUi.css.js index afa54101c..05d3be4e5 100644 --- a/public/panels/freestyler/components/freestylerChatUi.css.js +++ b/public/panels/freestyler/components/freestylerChatUi.css.js @@ -73,17 +73,14 @@ styles.replaceSync( } .chat-input-container { - margin: var(--sys-size-3) 0; + margin: var(--sys-size-4) 0; width: 100%; display: flex; position: relative; } .chat-input { - --right-padding: - calc( - var(--sys-size-5) + 26px + var(--sys-size-4) - ); /* Gap between the button and the edge + icon's width + gap between icon and the textarea */ + --right-padding: calc(var(--sys-size-4) + 26px); /* Gap between the button and the edge + icon's width */ field-sizing: content; /* stylelint-disable-line property-no-unknown */ resize: none; @@ -95,8 +92,10 @@ styles.replaceSync( line-height: 18px; min-height: var(--sys-size-11); padding: - var(--sys-size-3) var(--right-padding) var(--sys-size-3) - var(--sys-size-5); + var(--sys-size-4) + var(--right-padding) + var(--sys-size-4) + var(--sys-size-4); color: var(--sys-color-on-surface); background-color: var(--sys-color-cdt-base-container); @@ -119,7 +118,7 @@ styles.replaceSync( position: absolute; right: 0; bottom: 0; - padding: var(--sys-size-3) var(--sys-size-5); + padding: var(--sys-size-4) var(--sys-size-4); } .disclaimer { @@ -132,7 +131,7 @@ styles.replaceSync( color: var(--sys-color-on-surface-subtle); font: var(--sys-typescale-body5-regular); text-wrap: pretty; - padding: var(--sys-size-5); + padding: var(--sys-size-2) var(--sys-size-5); } } @@ -166,9 +165,8 @@ styles.replaceSync( &.query { .message-content { - line-height: 18px; - white-space: pre; - text-wrap: wrap; + /* devtools-markdown-view's paragraphs add 10px bottom margin. This negative margin is here to offset that. */ + margin-bottom: -10px; } } @@ -311,16 +309,24 @@ styles.replaceSync( justify-content: space-between; margin-bottom: 2px; line-height: 20px; + gap: var(--sys-size-8); & .feedback-icon { width: var(--sys-size-8); height: var(--sys-size-8); } + & .header-link-container:first-of-type { + flex-shrink: 1; + flex-basis: 100%; + min-width: 0; + } + & .header-link-container { display: inline-flex; align-items: center; gap: var(--sys-size-2); + flex-shrink: 0; } } @@ -334,13 +340,13 @@ styles.replaceSync( } .empty-state-container { - display: flex; - flex-direction: column; + display: grid; align-items: center; justify-content: center; font: var(--sys-typescale-headline4); gap: var(--sys-size-11); height: 100%; + padding: var(--sys-size-3); .header { display: flex; @@ -348,6 +354,7 @@ styles.replaceSync( width: 100%; align-items: center; justify-content: center; + align-self: end; gap: var(--sys-size-5); .icon { @@ -372,6 +379,7 @@ styles.replaceSync( gap: var(--sys-size-5); align-items: center; justify-content: center; + align-self: start; } } @@ -387,6 +395,12 @@ styles.replaceSync( } } +.context-details { + devtools-code-block { + --max-code-height: 80px; + } +} + .error-step { color: var(--sys-color-error); } diff --git a/public/panels/freestyler/freestyler-meta.js b/public/panels/freestyler/freestyler-meta.js index 41e49c432..21019db76 100644 --- a/public/panels/freestyler/freestyler-meta.js +++ b/public/panels/freestyler/freestyler-meta.js @@ -11,7 +11,7 @@ import * as UI from '../../ui/legacy/legacy.js'; */ const UIStringsTemp = { /** - * @description The title of the command menu action for showing the Freestyler panel. + * @description The title of the command menu action for showing the AI assistant panel. */ showAiAssistant: 'Show AI assistant', /** @@ -19,10 +19,10 @@ const UIStringsTemp = { */ aiAssistant: 'AI assistant', /** - * @description The setting title to enable the freestyler via + * @description The setting title to enable the AI assistant via * the settings tab. */ - enableFreestyler: 'Enable AI assistant', + enableAiAssistant: 'Enable AI assistant', /** *@description Text of a tooltip to redirect to the AI assistant panel with *the current element as context @@ -102,7 +102,7 @@ Common.Settings.registerSettingExtension({ category: "GLOBAL" /* Common.Settings.SettingCategory.GLOBAL */, settingName: setting, settingType: "boolean" /* Common.Settings.SettingType.BOOLEAN */, - title: i18nLazyString(UIStringsTemp.enableFreestyler), + title: i18nLazyString(UIStringsTemp.enableAiAssistant), defaultValue: isFeatureAvailable, reloadRequired: true, condition: isFeatureAvailable, diff --git a/public/panels/freestyler/freestyler-meta.js.map b/public/panels/freestyler/freestyler-meta.js.map index 7d609f206..9fcda1b1f 100644 --- a/public/panels/freestyler/freestyler-meta.js.map +++ b/public/panels/freestyler/freestyler-meta.js.map @@ -1 +1 @@ -{"version":3,"file":"freestyler-meta.js","sourceRoot":"","sources":["../../../../../../front_end/panels/freestyler/freestyler-meta.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport type * as Root from '../../core/root/root.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport type * as Freestyler from './freestyler.js';\n\n/*\n * TODO(nvitkov): b/346933425\n * Temporary string that should not be translated\n * as they may change often during development.\n */\nconst UIStringsTemp = {\n /**\n * @description The title of the command menu action for showing the Freestyler panel.\n */\n showAiAssistant: 'Show AI assistant',\n /**\n * @description The title of the AI assistant panel.\n */\n aiAssistant: 'AI assistant',\n /**\n * @description The setting title to enable the freestyler via\n * the settings tab.\n */\n enableFreestyler: 'Enable AI assistant',\n /**\n *@description Text of a tooltip to redirect to the AI assistant panel with\n *the current element as context\n */\n askAiAssistant: 'Ask AI assistant',\n /**\n * @description Message shown to the user if the DevTools locale is not\n * supported.\n */\n wrongLocale: 'To use this feature, update your Language preference in DevTools Settings to English',\n /**\n * @description Message shown to the user if the age check is not successful.\n */\n ageRestricted: 'This feature is only available to users who are 18 years of age or older',\n /**\n * @description Message shown to the user if the user's region is not\n * supported.\n */\n geoRestricted: 'This feature is unavailable in your region',\n /**\n * @description Message shown to the user if the enterprise policy does\n * not allow this feature.\n */\n policyRestricted: 'Your organization turned off this feature. Contact your administrators for more information',\n};\n\n// TODO(nvitkov): b/346933425\n// const str_ = i18n.i18n.registerUIStrings('panels/freestyler/freestyler-meta.ts', UIStrings);\n// const i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_);\n/* eslint-disable rulesdir/l10n_i18nString_call_only_with_uistrings */\nconst i18nLazyString = i18n.i18n.lockedLazyString;\nconst i18nString = i18n.i18n.lockedString;\n\nconst setting = 'freestyler-enabled';\n\nfunction isLocaleRestricted(): boolean {\n const devtoolsLocale = i18n.DevToolsLocale.DevToolsLocale.instance();\n return !devtoolsLocale.locale.startsWith('en-');\n}\n\nfunction isAgeRestricted(config?: Root.Runtime.HostConfig): boolean {\n return config?.aidaAvailability?.blockedByAge === true;\n}\n\nfunction isGeoRestricted(config?: Root.Runtime.HostConfig): boolean {\n return config?.aidaAvailability?.blockedByGeo === true;\n}\n\nfunction isPolicyRestricted(config?: Root.Runtime.HostConfig): boolean {\n return config?.aidaAvailability?.blockedByEnterprisePolicy === true;\n}\n\nlet loadedFreestylerModule: (typeof Freestyler|undefined);\nasync function loadFreestylerModule(): Promise {\n if (!loadedFreestylerModule) {\n loadedFreestylerModule = await import('./freestyler.js');\n }\n return loadedFreestylerModule;\n}\n\nfunction isFeatureAvailable(config?: Root.Runtime.HostConfig): boolean {\n return (config?.aidaAvailability?.enabled && config?.devToolsFreestylerDogfood?.enabled) === true;\n}\n\nfunction isDrJonesFeatureAvailable(config?: Root.Runtime.HostConfig): boolean {\n return (config?.aidaAvailability?.enabled && config?.devToolsFreestylerDogfood?.enabled &&\n config?.devToolsExplainThisResourceDogfood?.enabled) === true;\n}\n\nUI.ViewManager.registerViewExtension({\n location: UI.ViewManager.ViewLocationValues.DRAWER_VIEW,\n id: 'freestyler',\n commandPrompt: i18nLazyString(UIStringsTemp.showAiAssistant),\n title: i18nLazyString(UIStringsTemp.aiAssistant),\n order: 10,\n isPreviewFeature: true,\n persistence: UI.ViewManager.ViewPersistence.CLOSEABLE,\n hasToolbar: false,\n condition: config => isFeatureAvailable(config) && !isPolicyRestricted(config) &&\n Common.Settings.Settings.instance().moduleSetting(setting).get(),\n async loadView() {\n const Freestyler = await loadFreestylerModule();\n return Freestyler.FreestylerPanel.instance();\n },\n});\n\nCommon.Settings.registerSettingExtension({\n category: Common.Settings.SettingCategory.GLOBAL,\n settingName: setting,\n settingType: Common.Settings.SettingType.BOOLEAN,\n title: i18nLazyString(UIStringsTemp.enableFreestyler),\n defaultValue: isFeatureAvailable,\n reloadRequired: true,\n condition: isFeatureAvailable,\n disabledCondition: config => {\n if (isLocaleRestricted()) {\n return {disabled: true, reason: i18nString(UIStringsTemp.wrongLocale)};\n }\n if (isAgeRestricted(config)) {\n return {disabled: true, reason: i18nString(UIStringsTemp.ageRestricted)};\n }\n if (isGeoRestricted(config)) {\n return {disabled: true, reason: i18nString(UIStringsTemp.geoRestricted)};\n }\n if (isPolicyRestricted(config)) {\n return {disabled: true, reason: i18nString(UIStringsTemp.policyRestricted)};\n }\n\n return {disabled: false};\n },\n});\n\nUI.ActionRegistration.registerActionExtension({\n actionId: 'freestyler.element-panel-context',\n contextTypes(): [] {\n return [];\n },\n setting,\n category: UI.ActionRegistration.ActionCategory.GLOBAL,\n title: i18nLazyString(UIStringsTemp.askAiAssistant),\n async loadActionDelegate() {\n const Freestyler = await loadFreestylerModule();\n return new Freestyler.ActionDelegate();\n },\n condition: config => isFeatureAvailable(config) && !isPolicyRestricted(config),\n});\n\nUI.ActionRegistration.registerActionExtension({\n actionId: 'drjones.network-panel-context',\n contextTypes(): [] {\n return [];\n },\n setting,\n category: UI.ActionRegistration.ActionCategory.GLOBAL,\n title: i18nLazyString(UIStringsTemp.askAiAssistant),\n async loadActionDelegate() {\n const Freestyler = await loadFreestylerModule();\n return new Freestyler.ActionDelegate();\n },\n condition: config => isDrJonesFeatureAvailable(config) && !isPolicyRestricted(config),\n});\n"]} \ No newline at end of file +{"version":3,"file":"freestyler-meta.js","sourceRoot":"","sources":["../../../../../../front_end/panels/freestyler/freestyler-meta.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport type * as Root from '../../core/root/root.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport type * as Freestyler from './freestyler.js';\n\n/*\n * TODO(nvitkov): b/346933425\n * Temporary string that should not be translated\n * as they may change often during development.\n */\nconst UIStringsTemp = {\n /**\n * @description The title of the command menu action for showing the AI assistant panel.\n */\n showAiAssistant: 'Show AI assistant',\n /**\n * @description The title of the AI assistant panel.\n */\n aiAssistant: 'AI assistant',\n /**\n * @description The setting title to enable the AI assistant via\n * the settings tab.\n */\n enableAiAssistant: 'Enable AI assistant',\n /**\n *@description Text of a tooltip to redirect to the AI assistant panel with\n *the current element as context\n */\n askAiAssistant: 'Ask AI assistant',\n /**\n * @description Message shown to the user if the DevTools locale is not\n * supported.\n */\n wrongLocale: 'To use this feature, update your Language preference in DevTools Settings to English',\n /**\n * @description Message shown to the user if the age check is not successful.\n */\n ageRestricted: 'This feature is only available to users who are 18 years of age or older',\n /**\n * @description Message shown to the user if the user's region is not\n * supported.\n */\n geoRestricted: 'This feature is unavailable in your region',\n /**\n * @description Message shown to the user if the enterprise policy does\n * not allow this feature.\n */\n policyRestricted: 'Your organization turned off this feature. Contact your administrators for more information',\n};\n\n// TODO(nvitkov): b/346933425\n// const str_ = i18n.i18n.registerUIStrings('panels/freestyler/freestyler-meta.ts', UIStrings);\n// const i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_);\n/* eslint-disable rulesdir/l10n_i18nString_call_only_with_uistrings */\nconst i18nLazyString = i18n.i18n.lockedLazyString;\nconst i18nString = i18n.i18n.lockedString;\n\nconst setting = 'freestyler-enabled';\n\nfunction isLocaleRestricted(): boolean {\n const devtoolsLocale = i18n.DevToolsLocale.DevToolsLocale.instance();\n return !devtoolsLocale.locale.startsWith('en-');\n}\n\nfunction isAgeRestricted(config?: Root.Runtime.HostConfig): boolean {\n return config?.aidaAvailability?.blockedByAge === true;\n}\n\nfunction isGeoRestricted(config?: Root.Runtime.HostConfig): boolean {\n return config?.aidaAvailability?.blockedByGeo === true;\n}\n\nfunction isPolicyRestricted(config?: Root.Runtime.HostConfig): boolean {\n return config?.aidaAvailability?.blockedByEnterprisePolicy === true;\n}\n\nlet loadedFreestylerModule: (typeof Freestyler|undefined);\nasync function loadFreestylerModule(): Promise {\n if (!loadedFreestylerModule) {\n loadedFreestylerModule = await import('./freestyler.js');\n }\n return loadedFreestylerModule;\n}\n\nfunction isFeatureAvailable(config?: Root.Runtime.HostConfig): boolean {\n return (config?.aidaAvailability?.enabled && config?.devToolsFreestylerDogfood?.enabled) === true;\n}\n\nfunction isDrJonesFeatureAvailable(config?: Root.Runtime.HostConfig): boolean {\n return (config?.aidaAvailability?.enabled && config?.devToolsFreestylerDogfood?.enabled &&\n config?.devToolsExplainThisResourceDogfood?.enabled) === true;\n}\n\nUI.ViewManager.registerViewExtension({\n location: UI.ViewManager.ViewLocationValues.DRAWER_VIEW,\n id: 'freestyler',\n commandPrompt: i18nLazyString(UIStringsTemp.showAiAssistant),\n title: i18nLazyString(UIStringsTemp.aiAssistant),\n order: 10,\n isPreviewFeature: true,\n persistence: UI.ViewManager.ViewPersistence.CLOSEABLE,\n hasToolbar: false,\n condition: config => isFeatureAvailable(config) && !isPolicyRestricted(config) &&\n Common.Settings.Settings.instance().moduleSetting(setting).get(),\n async loadView() {\n const Freestyler = await loadFreestylerModule();\n return Freestyler.FreestylerPanel.instance();\n },\n});\n\nCommon.Settings.registerSettingExtension({\n category: Common.Settings.SettingCategory.GLOBAL,\n settingName: setting,\n settingType: Common.Settings.SettingType.BOOLEAN,\n title: i18nLazyString(UIStringsTemp.enableAiAssistant),\n defaultValue: isFeatureAvailable,\n reloadRequired: true,\n condition: isFeatureAvailable,\n disabledCondition: config => {\n if (isLocaleRestricted()) {\n return {disabled: true, reason: i18nString(UIStringsTemp.wrongLocale)};\n }\n if (isAgeRestricted(config)) {\n return {disabled: true, reason: i18nString(UIStringsTemp.ageRestricted)};\n }\n if (isGeoRestricted(config)) {\n return {disabled: true, reason: i18nString(UIStringsTemp.geoRestricted)};\n }\n if (isPolicyRestricted(config)) {\n return {disabled: true, reason: i18nString(UIStringsTemp.policyRestricted)};\n }\n\n return {disabled: false};\n },\n});\n\nUI.ActionRegistration.registerActionExtension({\n actionId: 'freestyler.element-panel-context',\n contextTypes(): [] {\n return [];\n },\n setting,\n category: UI.ActionRegistration.ActionCategory.GLOBAL,\n title: i18nLazyString(UIStringsTemp.askAiAssistant),\n async loadActionDelegate() {\n const Freestyler = await loadFreestylerModule();\n return new Freestyler.ActionDelegate();\n },\n condition: config => isFeatureAvailable(config) && !isPolicyRestricted(config),\n});\n\nUI.ActionRegistration.registerActionExtension({\n actionId: 'drjones.network-panel-context',\n contextTypes(): [] {\n return [];\n },\n setting,\n category: UI.ActionRegistration.ActionCategory.GLOBAL,\n title: i18nLazyString(UIStringsTemp.askAiAssistant),\n async loadActionDelegate() {\n const Freestyler = await loadFreestylerModule();\n return new Freestyler.ActionDelegate();\n },\n condition: config => isDrJonesFeatureAvailable(config) && !isPolicyRestricted(config),\n});\n"]} \ No newline at end of file diff --git a/public/panels/freestyler/freestyler-tsconfig.json b/public/panels/freestyler/freestyler-tsconfig.json index e8c55030d..e77a40dd9 100644 --- a/public/panels/freestyler/freestyler-tsconfig.json +++ b/public/panels/freestyler/freestyler-tsconfig.json @@ -54,6 +54,12 @@ { "path": "../../core/i18n/bundle-tsconfig.json" }, + { + "path": "../../models/logs/bundle-tsconfig.json" + }, + { + "path": "../network/forward/bundle-tsconfig.json" + }, { "path": "../../third_party/marked/bundle-tsconfig.json" }, diff --git a/public/panels/lighthouse/LighthouseReporterTypes.d.ts b/public/panels/lighthouse/LighthouseReporterTypes.d.ts index c986d2597..a2545c898 100644 --- a/public/panels/lighthouse/LighthouseReporterTypes.d.ts +++ b/public/panels/lighthouse/LighthouseReporterTypes.d.ts @@ -1,5 +1,5 @@ import type * as Platform from '../../core/platform/platform.js'; -import type * as TraceEngine from '../../models/trace/trace.js'; +import type * as Trace from '../../models/trace/trace.js'; export declare class LighthouseReportGenerator { generateReportHtml(_lhr: ReportJSON): string; } @@ -73,7 +73,7 @@ export interface DetailsJSON { export interface RunnerResultArtifacts { traces: { defaultPass: { - traceEvents: TraceEngine.Types.TraceEvents.TraceEventData[]; + traceEvents: Trace.Types.Events.Event[]; }; }; settings: { diff --git a/public/panels/lighthouse/LighthouseReporterTypes.js.map b/public/panels/lighthouse/LighthouseReporterTypes.js.map index d863203a6..7f29b6d9a 100644 --- a/public/panels/lighthouse/LighthouseReporterTypes.js.map +++ b/public/panels/lighthouse/LighthouseReporterTypes.js.map @@ -1 +1 @@ -{"version":3,"file":"LighthouseReporterTypes.js","sourceRoot":"","sources":["../../../../../../front_end/panels/lighthouse/LighthouseReporterTypes.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAK7B,MAAM,OAAO,yBAAyB;IACpC,kBAAkB,CAAC,IAAgB;QACjC,OAAO,EAAE,CAAC;IACZ,CAAC;CACF","sourcesContent":["// Copyright 2020 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Platform from '../../core/platform/platform.js';\nimport type * as TraceEngine from '../../models/trace/trace.js';\n\nexport class LighthouseReportGenerator {\n generateReportHtml(_lhr: ReportJSON): string {\n return '';\n }\n}\nexport interface AuditResultJSON {\n rawValue?: number|boolean;\n id: string;\n title: string;\n description: string;\n explanation?: string;\n errorMessage?: string;\n displayValue?: string|(string|number)[];\n scoreDisplayMode: string;\n error: boolean;\n score: number|null;\n details?: DetailsJSON;\n}\nexport interface AuditJSON {\n id: string;\n score: number|null;\n weight: number;\n group?: string;\n result: AuditResultJSON;\n}\nexport interface CategoryJSON {\n title: string;\n id: string;\n score: number|null;\n description?: string;\n manualDescription: string;\n auditRefs: AuditJSON[];\n}\nexport interface GroupJSON {\n title: string;\n description?: string;\n}\nexport interface ReportJSON {\n lighthouseVersion: string;\n userAgent: string;\n fetchTime: string;\n timing: {total: number};\n requestedUrl?: string;\n finalDisplayedUrl: string;\n finalUrl?: string;\n runWarnings?: string[];\n artifacts: {traces: {defaultPass: {traceEvents: Array}}};\n audits: {[x: string]: AuditResultJSON};\n categories: {[x: string]: CategoryJSON};\n categoryGroups: {[x: string]: GroupJSON};\n}\nexport interface DetailsJSON {\n type: string;\n value?: string|number;\n summary?: OpportunitySummary;\n granularity?: number;\n displayUnit?: string;\n}\nexport interface RunnerResultArtifacts {\n traces: {defaultPass: {traceEvents: TraceEngine.Types.TraceEvents.TraceEventData[]}};\n settings: {throttlingMethod: string};\n}\nexport interface RunnerResult {\n lhr: ReportJSON;\n artifacts: RunnerResultArtifacts;\n report: string;\n stack: string;\n fatal: boolean;\n message?: string;\n}\nexport interface NodeDetailsJSON {\n type: string;\n path?: string;\n selector?: string;\n snippet?: string;\n}\nexport interface SourceLocationDetailsJSON {\n sourceUrl?: Platform.DevToolsPath.UrlString;\n sourceLine?: string;\n sourceColumn?: string;\n}\nexport interface OpportunitySummary {\n wastedMs?: number;\n wastedBytes?: number;\n}\n"]} \ No newline at end of file +{"version":3,"file":"LighthouseReporterTypes.js","sourceRoot":"","sources":["../../../../../../front_end/panels/lighthouse/LighthouseReporterTypes.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAK7B,MAAM,OAAO,yBAAyB;IACpC,kBAAkB,CAAC,IAAgB;QACjC,OAAO,EAAE,CAAC;IACZ,CAAC;CACF","sourcesContent":["// Copyright 2020 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Platform from '../../core/platform/platform.js';\nimport type * as Trace from '../../models/trace/trace.js';\n\nexport class LighthouseReportGenerator {\n generateReportHtml(_lhr: ReportJSON): string {\n return '';\n }\n}\nexport interface AuditResultJSON {\n rawValue?: number|boolean;\n id: string;\n title: string;\n description: string;\n explanation?: string;\n errorMessage?: string;\n displayValue?: string|(string|number)[];\n scoreDisplayMode: string;\n error: boolean;\n score: number|null;\n details?: DetailsJSON;\n}\nexport interface AuditJSON {\n id: string;\n score: number|null;\n weight: number;\n group?: string;\n result: AuditResultJSON;\n}\nexport interface CategoryJSON {\n title: string;\n id: string;\n score: number|null;\n description?: string;\n manualDescription: string;\n auditRefs: AuditJSON[];\n}\nexport interface GroupJSON {\n title: string;\n description?: string;\n}\nexport interface ReportJSON {\n lighthouseVersion: string;\n userAgent: string;\n fetchTime: string;\n timing: {total: number};\n requestedUrl?: string;\n finalDisplayedUrl: string;\n finalUrl?: string;\n runWarnings?: string[];\n artifacts: {traces: {defaultPass: {traceEvents: Array}}};\n audits: {[x: string]: AuditResultJSON};\n categories: {[x: string]: CategoryJSON};\n categoryGroups: {[x: string]: GroupJSON};\n}\nexport interface DetailsJSON {\n type: string;\n value?: string|number;\n summary?: OpportunitySummary;\n granularity?: number;\n displayUnit?: string;\n}\nexport interface RunnerResultArtifacts {\n traces: {defaultPass: {traceEvents: Trace.Types.Events.Event[]}};\n settings: {throttlingMethod: string};\n}\nexport interface RunnerResult {\n lhr: ReportJSON;\n artifacts: RunnerResultArtifacts;\n report: string;\n stack: string;\n fatal: boolean;\n message?: string;\n}\nexport interface NodeDetailsJSON {\n type: string;\n path?: string;\n selector?: string;\n snippet?: string;\n}\nexport interface SourceLocationDetailsJSON {\n sourceUrl?: Platform.DevToolsPath.UrlString;\n sourceLine?: string;\n sourceColumn?: string;\n}\nexport interface OpportunitySummary {\n wastedMs?: number;\n wastedBytes?: number;\n}\n"]} \ No newline at end of file diff --git a/public/panels/network/NetworkOverview.js b/public/panels/network/NetworkOverview.js index a02b746ef..06b30edee 100644 --- a/public/panels/network/NetworkOverview.js +++ b/public/panels/network/NetworkOverview.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as SDK from '../../core/sdk/sdk.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as Coordinator from '../../ui/components/render_coordinator/render_coordinator.js'; import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; import * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js'; @@ -117,7 +117,7 @@ export class NetworkOverview extends PerfUI.TimelineOverviewPane.TimelineOvervie while (this.span < span) { this.span *= 1.25; } - calculator.setBounds(calculator.minimumBoundary(), TraceEngine.Types.Timing.MilliSeconds(calculator.minimumBoundary() + this.span)); + calculator.setBounds(calculator.minimumBoundary(), Trace.Types.Timing.MilliSeconds(calculator.minimumBoundary() + this.span)); this.lastBoundary = new NetworkTimeBoundary(calculator.minimumBoundary(), calculator.maximumBoundary()); } const context = this.context(); @@ -140,8 +140,8 @@ export class NetworkOverview extends PerfUI.TimelineOverviewPane.TimelineOvervie if (endTime === Number.MAX_VALUE) { endTime = calculator.maximumBoundary(); } - const startX = calculator.computePosition(TraceEngine.Types.Timing.MilliSeconds(startTime)); - const endX = calculator.computePosition(TraceEngine.Types.Timing.MilliSeconds(endTime)) + 1; + const startX = calculator.computePosition(Trace.Types.Timing.MilliSeconds(startTime)); + const endX = calculator.computePosition(Trace.Types.Timing.MilliSeconds(endTime)) + 1; context.fillRect(startX, y, Math.max(endX - startX, MIN_BAND_WIDTH), BAND_HEIGHT); context.strokeRect(startX, y, Math.max(endX - startX, MIN_BAND_WIDTH), BAND_HEIGHT); } @@ -195,8 +195,8 @@ export class NetworkOverview extends PerfUI.TimelineOverviewPane.TimelineOvervie context.fillStyle = ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-tonal-container'); // The network overview works in seconds, but the calcululator deals in // milliseconds, hence the multiplication by 1000. - const start = TraceEngine.Types.Timing.MilliSeconds(timeRanges[0].start * 1000); - const end = TraceEngine.Types.Timing.MilliSeconds(timeRanges[0].end * 1000); + const start = Trace.Types.Timing.MilliSeconds(timeRanges[0].start * 1000); + const end = Trace.Types.Timing.MilliSeconds(timeRanges[0].end * 1000); context.fillRect(calculator.computePosition(start) - borderSize, y - size / 2 - borderSize, calculator.computePosition(end) - calculator.computePosition(start) + 1 + 2 * borderSize, size * borderSize); for (let j = 0; j < timeRanges.length; ++j) { const type = timeRanges[j].name; @@ -205,8 +205,8 @@ export class NetworkOverview extends PerfUI.TimelineOverviewPane.TimelineOvervie context.strokeStyle = ThemeSupport.ThemeSupport.instance().getComputedValue(RequestTimeRangeNameToColor[type]); context.lineWidth = size; - const start = TraceEngine.Types.Timing.MilliSeconds(timeRanges[j].start * 1000); - const end = TraceEngine.Types.Timing.MilliSeconds(timeRanges[j].end * 1000); + const start = Trace.Types.Timing.MilliSeconds(timeRanges[j].start * 1000); + const end = Trace.Types.Timing.MilliSeconds(timeRanges[j].end * 1000); context.moveTo(calculator.computePosition(start) - 0, y); context.lineTo(calculator.computePosition(end) + 1, y); context.stroke(); @@ -218,7 +218,7 @@ export class NetworkOverview extends PerfUI.TimelineOverviewPane.TimelineOvervie context.beginPath(); context.strokeStyle = ThemeSupport.ThemeSupport.instance().getComputedValue(NetworkLogView.getDCLEventColor()); for (let i = this.domContentLoadedEvents.length - 1; i >= 0; --i) { - const position = calculator.computePosition(TraceEngine.Types.Timing.MilliSeconds(this.domContentLoadedEvents[i])); + const position = calculator.computePosition(Trace.Types.Timing.MilliSeconds(this.domContentLoadedEvents[i])); const x = Math.round(position) + 0.5; context.moveTo(x, 0); context.lineTo(x, height); @@ -227,7 +227,7 @@ export class NetworkOverview extends PerfUI.TimelineOverviewPane.TimelineOvervie context.beginPath(); context.strokeStyle = ThemeSupport.ThemeSupport.instance().getComputedValue(NetworkLogView.getLoadEventColor()); for (let i = this.loadEvents.length - 1; i >= 0; --i) { - const position = calculator.computePosition(TraceEngine.Types.Timing.MilliSeconds(this.loadEvents[i])); + const position = calculator.computePosition(Trace.Types.Timing.MilliSeconds(this.loadEvents[i])); const x = Math.round(position) + 0.5; context.moveTo(x, 0); context.lineTo(x, height); @@ -237,7 +237,7 @@ export class NetworkOverview extends PerfUI.TimelineOverviewPane.TimelineOvervie context.lineWidth = 2; context.beginPath(); context.strokeStyle = ThemeSupport.ThemeSupport.instance().getComputedValue('--network-frame-divider-color'); - const timeInMilliseconds = TraceEngine.Types.Timing.MilliSeconds(this.selectedFilmStripTime); + const timeInMilliseconds = Trace.Types.Timing.MilliSeconds(this.selectedFilmStripTime); const x = Math.round(calculator.computePosition(timeInMilliseconds)); context.moveTo(x, 0); context.lineTo(x, height); diff --git a/public/panels/network/NetworkOverview.js.map b/public/panels/network/NetworkOverview.js.map index ca3d1573d..9dca75eb5 100644 --- a/public/panels/network/NetworkOverview.js.map +++ b/public/panels/network/NetworkOverview.js.map @@ -1 +1 @@ -{"version":3,"file":"NetworkOverview.js","sourceRoot":"","sources":["../../../../../../front_end/panels/network/NetworkOverview.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAG7B,OAAO,KAAK,GAAG,MAAM,uBAAuB,CAAC;AAC7C,OAAO,KAAK,WAAW,MAAM,6BAA6B,CAAC;AAC3D,OAAO,KAAK,WAAW,MAAM,8DAA8D,CAAC;AAC5F,OAAO,KAAK,MAAM,MAAM,+CAA+C,CAAC;AACxE,OAAO,KAAK,YAAY,MAAM,gDAAgD,CAAC;AAE/E,OAAO,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAC,mBAAmB,EAAC,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAwB,iBAAiB,EAAC,MAAM,wBAAwB,CAAC;AAEhF,MAAM,WAAW,GAAG,WAAW,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC;AAE/E,MAAM,OAAO,eAAgB,SAAQ,MAAM,CAAC,oBAAoB,CAAC,oBAAoB;IAC3E,qBAAqB,CAAS;IAC9B,QAAQ,CAAS;IACjB,kBAAkB,CAAyC;IAC3D,UAAU,CAAY;IACtB,sBAAsB,CAAY;IAClC,QAAQ,CAAU;IAClB,OAAO,CAAuB;IAC9B,YAAY,CAAuC;IACnD,WAAW,CAA0C;IACrD,IAAI,CAAU;IACd,YAAY,CAA4B;IAEhD;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,qBAAqB,GAAG,CAAC,CAAC,CAAC;QAChC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QAE/C,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;QAClB,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;QAE/B,GAAG,CAAC,aAAa,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,gBAAgB,CACvD,GAAG,CAAC,iBAAiB,CAAC,iBAAiB,EAAE,GAAG,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,cAAc,EAAE,IAAI,EACrG,EAAC,MAAM,EAAE,IAAI,EAAC,CAAC,CAAC;QACpB,GAAG,CAAC,aAAa,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,gBAAgB,CACvD,GAAG,CAAC,iBAAiB,CAAC,iBAAiB,EAAE,GAAG,CAAC,iBAAiB,CAAC,MAAM,CAAC,gBAAgB,EACtF,IAAI,CAAC,0BAA0B,EAAE,IAAI,EAAE,EAAC,MAAM,EAAE,IAAI,EAAC,CAAC,CAAC;QAE3D,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IAED,qBAAqB,CAAC,OAA+C;QACnE,IAAI,CAAC,kBAAkB,GAAG,OAAO,CAAC;QAClC,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAED,oBAAoB,CAAC,IAAY;QAC/B,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC;QAClC,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAED,mBAAmB;QACjB,IAAI,CAAC,qBAAqB,GAAG,CAAC,CAAC,CAAC;QAChC,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAEO,cAAc,CAClB,KACqG;QACvG,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;QACjC,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;QACpC,CAAC;QACD,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAEO,0BAA0B,CAAC,KAAkD;QACnF,MAAM,EAAC,IAAI,EAAC,GAAG,KAAK,CAAC;QACrB,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;QAChD,CAAC;QACD,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAEO,MAAM,CAAC,YAAoB;QACjC,IAAI,CAAC,YAAY,IAAI,YAAY,KAAK,GAAG,EAAE,CAAC;YAC1C,OAAO,CAAC,CAAC,CAAC;QACZ,CAAC;QACD,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAW,CAAC;QAClD,CAAC;QACD,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC/B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QACvC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,aAAa,CAAC,OAA0C;QACtD,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;YACnC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC9B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAClC,CAAC;QACD,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAEQ,QAAQ;QACf,IAAI,CAAC,QAAQ,EAAE,CAAC;IAClB,CAAC;IAEQ,UAAU;QACjB,OAAO,KAAK,CAAC,UAAU,EAAkE,CAAC;IAC5F,CAAC;IAEQ,QAAQ;QACf,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;QACzC,IAAI,CAAC,UAAU,EAAE,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;QACzC,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,MAAM,QAAQ,GAAG,CAAC,CAAC,CAAC,MAAM,GAAG,OAAO,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;QAClE,IAAI,CAAC,QAAQ,GAAG,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAEQ,KAAK;QACZ,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QACd,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;QAClB,IAAI,CAAC,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC,YAAY,GAAG,EAAE,CAAC;QACvB,IAAI,CAAC,WAAW,GAAG,IAAI,GAAG,EAAE,CAAC;QAC7B,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;QACrB,IAAI,CAAC,sBAAsB,GAAG,EAAE,CAAC;QAEjC,gBAAgB;QAChB,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAED,cAAc;QACZ,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QACD,KAAK,WAAW,CAAC,KAAK,CAAC,wBAAwB,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3E,CAAC;IAEQ,MAAM;QACb,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;QAErC,MAAM,WAAW,GAAG,IAAI,mBAAmB,CAAC,UAAU,CAAC,eAAe,EAAE,EAAE,UAAU,CAAC,eAAe,EAAE,CAAC,CAAC;QACxG,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;YACjE,MAAM,IAAI,GAAG,UAAU,CAAC,YAAY,EAAE,CAAC;YACvC,OAAO,IAAI,CAAC,IAAI,GAAG,IAAI,EAAE,CAAC;gBACxB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;YACpB,CAAC;YAED,UAAU,CAAC,SAAS,CAChB,UAAU,CAAC,eAAe,EAAE,EAC5B,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,eAAe,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAErF,IAAI,CAAC,YAAY,GAAG,IAAI,mBAAmB,CAAC,UAAU,CAAC,eAAe,EAAE,EAAE,UAAU,CAAC,eAAe,EAAE,CAAC,CAAC;QAC1G,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QAC/B,MAAM,WAAW,GAAG,IAAI,GAAG,EAAoB,CAAC;QAChD,MAAM,UAAU,GAAG,OAAO,CAAC;QAE3B,SAAS,SAAS,CAAC,IAAY;YAC7B,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACpC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO;YACT,CAAC;YACD,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;YACvB,OAAO,CAAC,SAAS,EAAE,CAAC;YACpB,OAAO,CAAC,WAAW,GAAG,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,gBAAgB,CAAC,+BAA+B,CAAC,CAAC;YAC7G,OAAO,CAAC,SAAS,GAAG,YAAY,CAAC;YACjC,OAAO,CAAC,SAAS,GAAG,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,gBAAgB,CAAC,2BAA2B,CAAC,IAAI,CAAC,CAAC,CAAC;YAC7G,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC;gBACvB,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,WAAW,GAAG,UAAU,CAAC;gBAChD,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;gBAC7B,IAAI,OAAO,GAAW,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;gBACjC,IAAI,OAAO,KAAK,MAAM,CAAC,SAAS,EAAE,CAAC;oBACjC,OAAO,GAAG,UAAU,CAAC,eAAe,EAAE,CAAC;gBACzC,CAAC;gBACD,MAAM,MAAM,GAAG,UAAU,CAAC,eAAe,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC;gBAC5F,MAAM,IAAI,GAAG,UAAU,CAAC,eAAe,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC;gBAC5F,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,MAAM,EAAE,cAAc,CAAC,EAAE,WAAW,CAAC,CAAC;gBAClF,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,MAAM,EAAE,cAAc,CAAC,EAAE,WAAW,CAAC,CAAC;YACtF,CAAC;QACH,CAAC;QAED,SAAS,OAAO,CAAC,IAAY,EAAE,CAAS,EAAE,KAAa,EAAE,GAAW;YAClE,IAAI,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAClC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,KAAK,GAAG,EAAE,CAAC;gBACX,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC/B,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QAC5B,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC;QACnC,MAAM,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC;QAC1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;YAC3B,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YAC/C,MAAM,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;YACzD,MAAM,UAAU,GAAG,iBAAiB,CAAC,0BAA0B,CAAC,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,eAAe,EAAE,CAAC,CAAC;YAC9G,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;gBAC3C,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;gBAChC,IAAI,IAAI,KAAK,CAAC,CAAC,IAAI,IAAI,8CAAgC,EAAE,CAAC;oBACxD,OAAO,CAAC,IAAI,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;gBACzE,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACrD,OAAO,CAAC,IAAI,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,gBAAgB,CAAC,CAAC;QAChE,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC;QACtB,SAAS,2CAA6B,CAAC;QACvC,SAAS,iDAAgC,CAAC;QAC1C,SAAS,qDAAkC,CAAC;QAC5C,SAAS,4DAAsC,CAAC;QAChD,SAAS,oFAAkD,CAAC;QAC5D,SAAS,qFAAmD,CAAC;QAC7D,SAAS,yCAA4B,CAAC;QACtC,SAAS,2CAA6B,CAAC;QACvC,SAAS,uCAA2B,CAAC;QACrC,SAAS,uCAA2B,CAAC;QACrC,SAAS,+CAA+B,CAAC;QACzC,SAAS,+CAA+B,CAAC;QACzC,SAAS,mDAAiC,CAAC;QAE3C,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,CAAC,CAAC;YACf,MAAM,UAAU,GAAG,CAAC,CAAC;YAErB,MAAM,OAAO,GAAG,IAAI,CAAC,kBAAkB,CAAC;YACxC,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;YAC/C,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,GAAG,WAAW,GAAG,UAAU,CAAC;YACtF,MAAM,UAAU,GAAG,iBAAiB,CAAC,0BAA0B,CAAC,OAAO,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,eAAe,EAAE,CAAC,CAAC;YAE9G,OAAO,CAAC,SAAS,GAAG,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,gBAAgB,CAAC,6BAA6B,CAAC,CAAC;YAEzG,uEAAuE;YACvE,kDAAkD;YAClD,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;YAChF,MAAM,GAAG,GAAG,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;YAC5E,OAAO,CAAC,QAAQ,CACZ,UAAU,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,UAAU,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,UAAU,EACzE,UAAU,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,UAAU,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,UAAU,EAAE,IAAI,GAAG,UAAU,CAAC,CAAC;YAEjH,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;gBAC3C,MAAM,IAAI,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;gBAChC,IAAI,IAAI,KAAK,CAAC,CAAC,IAAI,IAAI,8CAAgC,EAAE,CAAC;oBACxD,OAAO,CAAC,SAAS,EAAE,CAAC;oBACpB,OAAO,CAAC,WAAW;wBACf,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,gBAAgB,CAAC,2BAA2B,CAAC,IAAI,CAAC,CAAC,CAAC;oBAC7F,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;oBAEzB,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;oBAChF,MAAM,GAAG,GAAG,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;oBAC5E,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;oBACzD,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;oBACvD,OAAO,CAAC,MAAM,EAAE,CAAC;gBACnB,CAAC;YACH,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;QACzC,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC;QACtB,OAAO,CAAC,SAAS,EAAE,CAAC;QACpB,OAAO,CAAC,WAAW,GAAG,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,gBAAgB,CAAC,cAAc,CAAC,gBAAgB,EAAE,CAAC,CAAC;QAC/G,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,sBAAsB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;YACjE,MAAM,QAAQ,GACV,UAAU,CAAC,eAAe,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACtG,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC;YACrC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACrB,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QAC5B,CAAC;QACD,OAAO,CAAC,MAAM,EAAE,CAAC;QAEjB,OAAO,CAAC,SAAS,EAAE,CAAC;QACpB,OAAO,CAAC,WAAW,GAAG,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,gBAAgB,CAAC,cAAc,CAAC,iBAAiB,EAAE,CAAC,CAAC;QAChH,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;YACrD,MAAM,QAAQ,GAAG,UAAU,CAAC,eAAe,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACvG,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,GAAG,CAAC;YACrC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACrB,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QAC5B,CAAC;QACD,OAAO,CAAC,MAAM,EAAE,CAAC;QAEjB,IAAI,IAAI,CAAC,qBAAqB,KAAK,CAAC,CAAC,EAAE,CAAC;YACtC,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC;YACtB,OAAO,CAAC,SAAS,EAAE,CAAC;YACpB,OAAO,CAAC,WAAW,GAAG,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,gBAAgB,CAAC,+BAA+B,CAAC,CAAC;YAC7G,MAAM,kBAAkB,GAAG,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;YAC7F,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,eAAe,CAAC,kBAAkB,CAAC,CAAC,CAAC;YACrE,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACrB,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;YAC1B,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,CAAC;QACD,OAAO,CAAC,OAAO,EAAE,CAAC;IACpB,CAAC;CACF;AAED,MAAM,CAAC,MAAM,2BAA2B,GAAG;IACzC,2CAA6B,EAAE,0BAA0B;IACzD,iDAAgC,EAAE,6BAA6B;IAC/D,qDAAkC,EAAE,+BAA+B;IACnE,4DAAsC,EAAE,mCAAmC;IAC3E,oFAAkD,EAAE,mCAAmC;IACvF,qFAAmD,EAAE,gDAAgD;IACrG,yCAA4B,EAAE,yBAAyB;IACvD,2CAA6B,EAAE,mCAAmC;IAClE,uCAA2B,EAAE,wBAAwB;IACrD,uCAA2B,EAAE,wBAAwB;IACrD,+CAA+B,EAAE,qCAAqC;IACtE,+CAA+B,EAAE,4BAA4B;IAC7D,mDAAiC,EAAE,8BAA8B;IACjE,iDAAgC,EAAE,6BAA6B;CACrC,CAAC;AAE7B,MAAM,WAAW,GAAG,CAAC,CAAC;AACtB,MAAM,OAAO,GAAG,CAAC,CAAC;AAElB,mDAAmD;AACnD,MAAM,cAAc,GAAG,EAAE,CAAC;AAE1B,mEAAmE;AACnE,MAAM,YAAY,GAAG,CAAC,CAAC","sourcesContent":["// Copyright 2015 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Common from '../../core/common/common.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as Coordinator from '../../ui/components/render_coordinator/render_coordinator.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\n\nimport {NetworkLogView} from './NetworkLogView.js';\nimport {NetworkTimeBoundary} from './NetworkTimeCalculator.js';\nimport {RequestTimeRangeNames, RequestTimingView} from './RequestTimingView.js';\n\nconst coordinator = Coordinator.RenderCoordinator.RenderCoordinator.instance();\n\nexport class NetworkOverview extends PerfUI.TimelineOverviewPane.TimelineOverviewBase {\n private selectedFilmStripTime: number;\n private numBands: number;\n private highlightedRequest: SDK.NetworkRequest.NetworkRequest|null;\n private loadEvents!: number[];\n private domContentLoadedEvents!: number[];\n private nextBand!: number;\n private bandMap!: Map;\n private requestsList!: SDK.NetworkRequest.NetworkRequest[];\n private requestsSet!: Set;\n private span!: number;\n private lastBoundary?: NetworkTimeBoundary|null;\n\n constructor() {\n super();\n this.selectedFilmStripTime = -1;\n this.element.classList.add('network-overview');\n\n this.numBands = 1;\n this.highlightedRequest = null;\n\n SDK.TargetManager.TargetManager.instance().addModelListener(\n SDK.ResourceTreeModel.ResourceTreeModel, SDK.ResourceTreeModel.Events.Load, this.loadEventFired, this,\n {scoped: true});\n SDK.TargetManager.TargetManager.instance().addModelListener(\n SDK.ResourceTreeModel.ResourceTreeModel, SDK.ResourceTreeModel.Events.DOMContentLoaded,\n this.domContentLoadedEventFired, this, {scoped: true});\n\n this.reset();\n }\n\n setHighlightedRequest(request: SDK.NetworkRequest.NetworkRequest|null): void {\n this.highlightedRequest = request;\n this.scheduleUpdate();\n }\n\n selectFilmStripFrame(time: number): void {\n this.selectedFilmStripTime = time;\n this.scheduleUpdate();\n }\n\n clearFilmStripFrame(): void {\n this.selectedFilmStripTime = -1;\n this.scheduleUpdate();\n }\n\n private loadEventFired(\n event: Common.EventTarget\n .EventTargetEvent<{resourceTreeModel: SDK.ResourceTreeModel.ResourceTreeModel, loadTime: number}>): void {\n const time = event.data.loadTime;\n if (time) {\n this.loadEvents.push(time * 1000);\n }\n this.scheduleUpdate();\n }\n\n private domContentLoadedEventFired(event: Common.EventTarget.EventTargetEvent): void {\n const {data} = event;\n if (data) {\n this.domContentLoadedEvents.push(data * 1000);\n }\n this.scheduleUpdate();\n }\n\n private bandId(connectionId: string): number {\n if (!connectionId || connectionId === '0') {\n return -1;\n }\n if (this.bandMap.has(connectionId)) {\n return this.bandMap.get(connectionId) as number;\n }\n const result = this.nextBand++;\n this.bandMap.set(connectionId, result);\n return result;\n }\n\n updateRequest(request: SDK.NetworkRequest.NetworkRequest): void {\n if (!this.requestsSet.has(request)) {\n this.requestsSet.add(request);\n this.requestsList.push(request);\n }\n this.scheduleUpdate();\n }\n\n override wasShown(): void {\n this.onResize();\n }\n\n override calculator(): PerfUI.TimelineOverviewCalculator.TimelineOverviewCalculator {\n return super.calculator() as PerfUI.TimelineOverviewCalculator.TimelineOverviewCalculator;\n }\n\n override onResize(): void {\n const width = this.element.offsetWidth;\n const height = this.element.offsetHeight;\n this.calculator().setDisplayWidth(width);\n this.resetCanvas();\n const numBands = (((height - PADDING - 1) / BAND_HEIGHT) - 1) | 0;\n this.numBands = (numBands > 0) ? numBands : 1;\n this.scheduleUpdate();\n }\n\n override reset(): void {\n this.span = 1;\n this.lastBoundary = null;\n this.nextBand = 0;\n this.bandMap = new Map();\n this.requestsList = [];\n this.requestsSet = new Set();\n this.loadEvents = [];\n this.domContentLoadedEvents = [];\n\n // Clear screen.\n this.resetCanvas();\n }\n\n scheduleUpdate(): void {\n if (!this.isShowing()) {\n return;\n }\n void coordinator.write('NetworkOverview.render', this.update.bind(this));\n }\n\n override update(): void {\n const calculator = this.calculator();\n\n const newBoundary = new NetworkTimeBoundary(calculator.minimumBoundary(), calculator.maximumBoundary());\n if (!this.lastBoundary || !newBoundary.equals(this.lastBoundary)) {\n const span = calculator.boundarySpan();\n while (this.span < span) {\n this.span *= 1.25;\n }\n\n calculator.setBounds(\n calculator.minimumBoundary(),\n TraceEngine.Types.Timing.MilliSeconds(calculator.minimumBoundary() + this.span));\n\n this.lastBoundary = new NetworkTimeBoundary(calculator.minimumBoundary(), calculator.maximumBoundary());\n }\n\n const context = this.context();\n const linesByType = new Map();\n const paddingTop = PADDING;\n\n function drawLines(type: string): void {\n const lines = linesByType.get(type);\n if (!lines) {\n return;\n }\n const n = lines.length;\n context.beginPath();\n context.strokeStyle = ThemeSupport.ThemeSupport.instance().getComputedValue('--color-background-opacity-80');\n context.lineWidth = BORDER_WIDTH;\n context.fillStyle = ThemeSupport.ThemeSupport.instance().getComputedValue(RequestTimeRangeNameToColor[type]);\n for (let i = 0; i < n;) {\n const y = lines[i++] * BAND_HEIGHT + paddingTop;\n const startTime = lines[i++];\n let endTime: number = lines[i++];\n if (endTime === Number.MAX_VALUE) {\n endTime = calculator.maximumBoundary();\n }\n const startX = calculator.computePosition(TraceEngine.Types.Timing.MilliSeconds(startTime));\n const endX = calculator.computePosition(TraceEngine.Types.Timing.MilliSeconds(endTime)) + 1;\n context.fillRect(startX, y, Math.max(endX - startX, MIN_BAND_WIDTH), BAND_HEIGHT);\n context.strokeRect(startX, y, Math.max(endX - startX, MIN_BAND_WIDTH), BAND_HEIGHT);\n }\n }\n\n function addLine(type: string, y: number, start: number, end: number): void {\n let lines = linesByType.get(type);\n if (!lines) {\n lines = [];\n linesByType.set(type, lines);\n }\n lines.push(y, start, end);\n }\n\n const requests = this.requestsList;\n const n = requests.length;\n for (let i = 0; i < n; ++i) {\n const request = requests[i];\n const band = this.bandId(request.connectionId);\n const y = (band === -1) ? 0 : (band % this.numBands + 1);\n const timeRanges = RequestTimingView.calculateRequestTimeRanges(request, this.calculator().minimumBoundary());\n for (let j = 0; j < timeRanges.length; ++j) {\n const type = timeRanges[j].name;\n if (band !== -1 || type === RequestTimeRangeNames.TOTAL) {\n addLine(type, y, timeRanges[j].start * 1000, timeRanges[j].end * 1000);\n }\n }\n }\n\n context.clearRect(0, 0, this.width(), this.height());\n context.save();\n context.scale(window.devicePixelRatio, window.devicePixelRatio);\n context.lineWidth = 2;\n drawLines(RequestTimeRangeNames.TOTAL);\n drawLines(RequestTimeRangeNames.BLOCKING);\n drawLines(RequestTimeRangeNames.CONNECTING);\n drawLines(RequestTimeRangeNames.SERVICE_WORKER);\n drawLines(RequestTimeRangeNames.SERVICE_WORKER_PREPARATION);\n drawLines(RequestTimeRangeNames.SERVICE_WORKER_RESPOND_WITH);\n drawLines(RequestTimeRangeNames.PUSH);\n drawLines(RequestTimeRangeNames.PROXY);\n drawLines(RequestTimeRangeNames.DNS);\n drawLines(RequestTimeRangeNames.SSL);\n drawLines(RequestTimeRangeNames.SENDING);\n drawLines(RequestTimeRangeNames.WAITING);\n drawLines(RequestTimeRangeNames.RECEIVING);\n\n if (this.highlightedRequest) {\n const size = 5;\n const borderSize = 2;\n\n const request = this.highlightedRequest;\n const band = this.bandId(request.connectionId);\n const y = ((band === -1) ? 0 : (band % this.numBands + 1)) * BAND_HEIGHT + paddingTop;\n const timeRanges = RequestTimingView.calculateRequestTimeRanges(request, this.calculator().minimumBoundary());\n\n context.fillStyle = ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-tonal-container');\n\n // The network overview works in seconds, but the calcululator deals in\n // milliseconds, hence the multiplication by 1000.\n const start = TraceEngine.Types.Timing.MilliSeconds(timeRanges[0].start * 1000);\n const end = TraceEngine.Types.Timing.MilliSeconds(timeRanges[0].end * 1000);\n context.fillRect(\n calculator.computePosition(start) - borderSize, y - size / 2 - borderSize,\n calculator.computePosition(end) - calculator.computePosition(start) + 1 + 2 * borderSize, size * borderSize);\n\n for (let j = 0; j < timeRanges.length; ++j) {\n const type = timeRanges[j].name;\n if (band !== -1 || type === RequestTimeRangeNames.TOTAL) {\n context.beginPath();\n context.strokeStyle =\n ThemeSupport.ThemeSupport.instance().getComputedValue(RequestTimeRangeNameToColor[type]);\n context.lineWidth = size;\n\n const start = TraceEngine.Types.Timing.MilliSeconds(timeRanges[j].start * 1000);\n const end = TraceEngine.Types.Timing.MilliSeconds(timeRanges[j].end * 1000);\n context.moveTo(calculator.computePosition(start) - 0, y);\n context.lineTo(calculator.computePosition(end) + 1, y);\n context.stroke();\n }\n }\n }\n\n const height = this.element.offsetHeight;\n context.lineWidth = 1;\n context.beginPath();\n context.strokeStyle = ThemeSupport.ThemeSupport.instance().getComputedValue(NetworkLogView.getDCLEventColor());\n for (let i = this.domContentLoadedEvents.length - 1; i >= 0; --i) {\n const position =\n calculator.computePosition(TraceEngine.Types.Timing.MilliSeconds(this.domContentLoadedEvents[i]));\n const x = Math.round(position) + 0.5;\n context.moveTo(x, 0);\n context.lineTo(x, height);\n }\n context.stroke();\n\n context.beginPath();\n context.strokeStyle = ThemeSupport.ThemeSupport.instance().getComputedValue(NetworkLogView.getLoadEventColor());\n for (let i = this.loadEvents.length - 1; i >= 0; --i) {\n const position = calculator.computePosition(TraceEngine.Types.Timing.MilliSeconds(this.loadEvents[i]));\n const x = Math.round(position) + 0.5;\n context.moveTo(x, 0);\n context.lineTo(x, height);\n }\n context.stroke();\n\n if (this.selectedFilmStripTime !== -1) {\n context.lineWidth = 2;\n context.beginPath();\n context.strokeStyle = ThemeSupport.ThemeSupport.instance().getComputedValue('--network-frame-divider-color');\n const timeInMilliseconds = TraceEngine.Types.Timing.MilliSeconds(this.selectedFilmStripTime);\n const x = Math.round(calculator.computePosition(timeInMilliseconds));\n context.moveTo(x, 0);\n context.lineTo(x, height);\n context.stroke();\n }\n context.restore();\n }\n}\n\nexport const RequestTimeRangeNameToColor = {\n [RequestTimeRangeNames.TOTAL]: '--network-overview-total',\n [RequestTimeRangeNames.BLOCKING]: '--network-overview-blocking',\n [RequestTimeRangeNames.CONNECTING]: '--network-overview-connecting',\n [RequestTimeRangeNames.SERVICE_WORKER]: '--network-overview-service-worker',\n [RequestTimeRangeNames.SERVICE_WORKER_PREPARATION]: '--network-overview-service-worker',\n [RequestTimeRangeNames.SERVICE_WORKER_RESPOND_WITH]: '--network-overview-service-worker-respond-with',\n [RequestTimeRangeNames.PUSH]: '--network-overview-push',\n [RequestTimeRangeNames.PROXY]: '--override-network-overview-proxy',\n [RequestTimeRangeNames.DNS]: '--network-overview-dns',\n [RequestTimeRangeNames.SSL]: '--network-overview-ssl',\n [RequestTimeRangeNames.SENDING]: '--override-network-overview-sending',\n [RequestTimeRangeNames.WAITING]: '--network-overview-waiting',\n [RequestTimeRangeNames.RECEIVING]: '--network-overview-receiving',\n [RequestTimeRangeNames.QUEUEING]: '--network-overview-queueing',\n} as {[key: string]: string};\n\nconst BAND_HEIGHT = 3;\nconst PADDING = 5;\n\n// Minimum rectangle width for very short requests.\nconst MIN_BAND_WIDTH = 10;\n\n// Border between bars in network overview panel for accessibility.\nconst BORDER_WIDTH = 1;\n"]} \ No newline at end of file +{"version":3,"file":"NetworkOverview.js","sourceRoot":"","sources":["../../../../../../front_end/panels/network/NetworkOverview.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2015 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Common from '../../core/common/common.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as Coordinator from '../../ui/components/render_coordinator/render_coordinator.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\n\nimport {NetworkLogView} from './NetworkLogView.js';\nimport {NetworkTimeBoundary} from './NetworkTimeCalculator.js';\nimport {RequestTimeRangeNames, RequestTimingView} from './RequestTimingView.js';\n\nconst coordinator = Coordinator.RenderCoordinator.RenderCoordinator.instance();\n\nexport class NetworkOverview extends PerfUI.TimelineOverviewPane.TimelineOverviewBase {\n private selectedFilmStripTime: number;\n private numBands: number;\n private highlightedRequest: SDK.NetworkRequest.NetworkRequest|null;\n private loadEvents!: number[];\n private domContentLoadedEvents!: number[];\n private nextBand!: number;\n private bandMap!: Map;\n private requestsList!: SDK.NetworkRequest.NetworkRequest[];\n private requestsSet!: Set;\n private span!: number;\n private lastBoundary?: NetworkTimeBoundary|null;\n\n constructor() {\n super();\n this.selectedFilmStripTime = -1;\n this.element.classList.add('network-overview');\n\n this.numBands = 1;\n this.highlightedRequest = null;\n\n SDK.TargetManager.TargetManager.instance().addModelListener(\n SDK.ResourceTreeModel.ResourceTreeModel, SDK.ResourceTreeModel.Events.Load, this.loadEventFired, this,\n {scoped: true});\n SDK.TargetManager.TargetManager.instance().addModelListener(\n SDK.ResourceTreeModel.ResourceTreeModel, SDK.ResourceTreeModel.Events.DOMContentLoaded,\n this.domContentLoadedEventFired, this, {scoped: true});\n\n this.reset();\n }\n\n setHighlightedRequest(request: SDK.NetworkRequest.NetworkRequest|null): void {\n this.highlightedRequest = request;\n this.scheduleUpdate();\n }\n\n selectFilmStripFrame(time: number): void {\n this.selectedFilmStripTime = time;\n this.scheduleUpdate();\n }\n\n clearFilmStripFrame(): void {\n this.selectedFilmStripTime = -1;\n this.scheduleUpdate();\n }\n\n private loadEventFired(\n event: Common.EventTarget\n .EventTargetEvent<{resourceTreeModel: SDK.ResourceTreeModel.ResourceTreeModel, loadTime: number}>): void {\n const time = event.data.loadTime;\n if (time) {\n this.loadEvents.push(time * 1000);\n }\n this.scheduleUpdate();\n }\n\n private domContentLoadedEventFired(event: Common.EventTarget.EventTargetEvent): void {\n const {data} = event;\n if (data) {\n this.domContentLoadedEvents.push(data * 1000);\n }\n this.scheduleUpdate();\n }\n\n private bandId(connectionId: string): number {\n if (!connectionId || connectionId === '0') {\n return -1;\n }\n if (this.bandMap.has(connectionId)) {\n return this.bandMap.get(connectionId) as number;\n }\n const result = this.nextBand++;\n this.bandMap.set(connectionId, result);\n return result;\n }\n\n updateRequest(request: SDK.NetworkRequest.NetworkRequest): void {\n if (!this.requestsSet.has(request)) {\n this.requestsSet.add(request);\n this.requestsList.push(request);\n }\n this.scheduleUpdate();\n }\n\n override wasShown(): void {\n this.onResize();\n }\n\n override calculator(): PerfUI.TimelineOverviewCalculator.TimelineOverviewCalculator {\n return super.calculator() as PerfUI.TimelineOverviewCalculator.TimelineOverviewCalculator;\n }\n\n override onResize(): void {\n const width = this.element.offsetWidth;\n const height = this.element.offsetHeight;\n this.calculator().setDisplayWidth(width);\n this.resetCanvas();\n const numBands = (((height - PADDING - 1) / BAND_HEIGHT) - 1) | 0;\n this.numBands = (numBands > 0) ? numBands : 1;\n this.scheduleUpdate();\n }\n\n override reset(): void {\n this.span = 1;\n this.lastBoundary = null;\n this.nextBand = 0;\n this.bandMap = new Map();\n this.requestsList = [];\n this.requestsSet = new Set();\n this.loadEvents = [];\n this.domContentLoadedEvents = [];\n\n // Clear screen.\n this.resetCanvas();\n }\n\n scheduleUpdate(): void {\n if (!this.isShowing()) {\n return;\n }\n void coordinator.write('NetworkOverview.render', this.update.bind(this));\n }\n\n override update(): void {\n const calculator = this.calculator();\n\n const newBoundary = new NetworkTimeBoundary(calculator.minimumBoundary(), calculator.maximumBoundary());\n if (!this.lastBoundary || !newBoundary.equals(this.lastBoundary)) {\n const span = calculator.boundarySpan();\n while (this.span < span) {\n this.span *= 1.25;\n }\n\n calculator.setBounds(\n calculator.minimumBoundary(), Trace.Types.Timing.MilliSeconds(calculator.minimumBoundary() + this.span));\n\n this.lastBoundary = new NetworkTimeBoundary(calculator.minimumBoundary(), calculator.maximumBoundary());\n }\n\n const context = this.context();\n const linesByType = new Map();\n const paddingTop = PADDING;\n\n function drawLines(type: string): void {\n const lines = linesByType.get(type);\n if (!lines) {\n return;\n }\n const n = lines.length;\n context.beginPath();\n context.strokeStyle = ThemeSupport.ThemeSupport.instance().getComputedValue('--color-background-opacity-80');\n context.lineWidth = BORDER_WIDTH;\n context.fillStyle = ThemeSupport.ThemeSupport.instance().getComputedValue(RequestTimeRangeNameToColor[type]);\n for (let i = 0; i < n;) {\n const y = lines[i++] * BAND_HEIGHT + paddingTop;\n const startTime = lines[i++];\n let endTime: number = lines[i++];\n if (endTime === Number.MAX_VALUE) {\n endTime = calculator.maximumBoundary();\n }\n const startX = calculator.computePosition(Trace.Types.Timing.MilliSeconds(startTime));\n const endX = calculator.computePosition(Trace.Types.Timing.MilliSeconds(endTime)) + 1;\n context.fillRect(startX, y, Math.max(endX - startX, MIN_BAND_WIDTH), BAND_HEIGHT);\n context.strokeRect(startX, y, Math.max(endX - startX, MIN_BAND_WIDTH), BAND_HEIGHT);\n }\n }\n\n function addLine(type: string, y: number, start: number, end: number): void {\n let lines = linesByType.get(type);\n if (!lines) {\n lines = [];\n linesByType.set(type, lines);\n }\n lines.push(y, start, end);\n }\n\n const requests = this.requestsList;\n const n = requests.length;\n for (let i = 0; i < n; ++i) {\n const request = requests[i];\n const band = this.bandId(request.connectionId);\n const y = (band === -1) ? 0 : (band % this.numBands + 1);\n const timeRanges = RequestTimingView.calculateRequestTimeRanges(request, this.calculator().minimumBoundary());\n for (let j = 0; j < timeRanges.length; ++j) {\n const type = timeRanges[j].name;\n if (band !== -1 || type === RequestTimeRangeNames.TOTAL) {\n addLine(type, y, timeRanges[j].start * 1000, timeRanges[j].end * 1000);\n }\n }\n }\n\n context.clearRect(0, 0, this.width(), this.height());\n context.save();\n context.scale(window.devicePixelRatio, window.devicePixelRatio);\n context.lineWidth = 2;\n drawLines(RequestTimeRangeNames.TOTAL);\n drawLines(RequestTimeRangeNames.BLOCKING);\n drawLines(RequestTimeRangeNames.CONNECTING);\n drawLines(RequestTimeRangeNames.SERVICE_WORKER);\n drawLines(RequestTimeRangeNames.SERVICE_WORKER_PREPARATION);\n drawLines(RequestTimeRangeNames.SERVICE_WORKER_RESPOND_WITH);\n drawLines(RequestTimeRangeNames.PUSH);\n drawLines(RequestTimeRangeNames.PROXY);\n drawLines(RequestTimeRangeNames.DNS);\n drawLines(RequestTimeRangeNames.SSL);\n drawLines(RequestTimeRangeNames.SENDING);\n drawLines(RequestTimeRangeNames.WAITING);\n drawLines(RequestTimeRangeNames.RECEIVING);\n\n if (this.highlightedRequest) {\n const size = 5;\n const borderSize = 2;\n\n const request = this.highlightedRequest;\n const band = this.bandId(request.connectionId);\n const y = ((band === -1) ? 0 : (band % this.numBands + 1)) * BAND_HEIGHT + paddingTop;\n const timeRanges = RequestTimingView.calculateRequestTimeRanges(request, this.calculator().minimumBoundary());\n\n context.fillStyle = ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-tonal-container');\n\n // The network overview works in seconds, but the calcululator deals in\n // milliseconds, hence the multiplication by 1000.\n const start = Trace.Types.Timing.MilliSeconds(timeRanges[0].start * 1000);\n const end = Trace.Types.Timing.MilliSeconds(timeRanges[0].end * 1000);\n context.fillRect(\n calculator.computePosition(start) - borderSize, y - size / 2 - borderSize,\n calculator.computePosition(end) - calculator.computePosition(start) + 1 + 2 * borderSize, size * borderSize);\n\n for (let j = 0; j < timeRanges.length; ++j) {\n const type = timeRanges[j].name;\n if (band !== -1 || type === RequestTimeRangeNames.TOTAL) {\n context.beginPath();\n context.strokeStyle =\n ThemeSupport.ThemeSupport.instance().getComputedValue(RequestTimeRangeNameToColor[type]);\n context.lineWidth = size;\n\n const start = Trace.Types.Timing.MilliSeconds(timeRanges[j].start * 1000);\n const end = Trace.Types.Timing.MilliSeconds(timeRanges[j].end * 1000);\n context.moveTo(calculator.computePosition(start) - 0, y);\n context.lineTo(calculator.computePosition(end) + 1, y);\n context.stroke();\n }\n }\n }\n\n const height = this.element.offsetHeight;\n context.lineWidth = 1;\n context.beginPath();\n context.strokeStyle = ThemeSupport.ThemeSupport.instance().getComputedValue(NetworkLogView.getDCLEventColor());\n for (let i = this.domContentLoadedEvents.length - 1; i >= 0; --i) {\n const position = calculator.computePosition(Trace.Types.Timing.MilliSeconds(this.domContentLoadedEvents[i]));\n const x = Math.round(position) + 0.5;\n context.moveTo(x, 0);\n context.lineTo(x, height);\n }\n context.stroke();\n\n context.beginPath();\n context.strokeStyle = ThemeSupport.ThemeSupport.instance().getComputedValue(NetworkLogView.getLoadEventColor());\n for (let i = this.loadEvents.length - 1; i >= 0; --i) {\n const position = calculator.computePosition(Trace.Types.Timing.MilliSeconds(this.loadEvents[i]));\n const x = Math.round(position) + 0.5;\n context.moveTo(x, 0);\n context.lineTo(x, height);\n }\n context.stroke();\n\n if (this.selectedFilmStripTime !== -1) {\n context.lineWidth = 2;\n context.beginPath();\n context.strokeStyle = ThemeSupport.ThemeSupport.instance().getComputedValue('--network-frame-divider-color');\n const timeInMilliseconds = Trace.Types.Timing.MilliSeconds(this.selectedFilmStripTime);\n const x = Math.round(calculator.computePosition(timeInMilliseconds));\n context.moveTo(x, 0);\n context.lineTo(x, height);\n context.stroke();\n }\n context.restore();\n }\n}\n\nexport const RequestTimeRangeNameToColor = {\n [RequestTimeRangeNames.TOTAL]: '--network-overview-total',\n [RequestTimeRangeNames.BLOCKING]: '--network-overview-blocking',\n [RequestTimeRangeNames.CONNECTING]: '--network-overview-connecting',\n [RequestTimeRangeNames.SERVICE_WORKER]: '--network-overview-service-worker',\n [RequestTimeRangeNames.SERVICE_WORKER_PREPARATION]: '--network-overview-service-worker',\n [RequestTimeRangeNames.SERVICE_WORKER_RESPOND_WITH]: '--network-overview-service-worker-respond-with',\n [RequestTimeRangeNames.PUSH]: '--network-overview-push',\n [RequestTimeRangeNames.PROXY]: '--override-network-overview-proxy',\n [RequestTimeRangeNames.DNS]: '--network-overview-dns',\n [RequestTimeRangeNames.SSL]: '--network-overview-ssl',\n [RequestTimeRangeNames.SENDING]: '--override-network-overview-sending',\n [RequestTimeRangeNames.WAITING]: '--network-overview-waiting',\n [RequestTimeRangeNames.RECEIVING]: '--network-overview-receiving',\n [RequestTimeRangeNames.QUEUEING]: '--network-overview-queueing',\n} as {[key: string]: string};\n\nconst BAND_HEIGHT = 3;\nconst PADDING = 5;\n\n// Minimum rectangle width for very short requests.\nconst MIN_BAND_WIDTH = 10;\n\n// Border between bars in network overview panel for accessibility.\nconst BORDER_WIDTH = 1;\n"]} \ No newline at end of file diff --git a/public/panels/network/NetworkPanel.d.ts b/public/panels/network/NetworkPanel.d.ts index 34ce5a110..fb4b455d8 100644 --- a/public/panels/network/NetworkPanel.d.ts +++ b/public/panels/network/NetworkPanel.d.ts @@ -1,7 +1,7 @@ import * as Common from '../../core/common/common.js'; import * as SDK from '../../core/sdk/sdk.js'; import type * as Extensions from '../../models/extensions/extensions.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as Workspace from '../../models/workspace/workspace.js'; import * as NetworkForward from '../../panels/network/forward/forward.js'; import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; @@ -102,7 +102,7 @@ export declare class NetworkLogWithFilterRevealer implements Common.Revealer .Revealer { reveal(request: Extensions.ExtensionServer.RevealableNetworkRequestFilter | NetworkForward.UIFilter.UIRequestFilter): Promise; } -export declare class FilmStripRecorder implements TraceEngine.TracingManager.TracingManagerClient { +export declare class FilmStripRecorder implements Trace.TracingManager.TracingManagerClient { #private; private tracingManager; private resourceTreeModel; @@ -110,13 +110,13 @@ export declare class FilmStripRecorder implements TraceEngine.TracingManager.Tra private readonly filmStripView; private callback; constructor(timeCalculator: NetworkTimeCalculator, filmStripView: PerfUI.FilmStripView.FilmStripView); - traceEventsCollected(events: TraceEngine.Types.TraceEvents.TraceEventData[]): void; + traceEventsCollected(events: Trace.Types.Events.Event[]): void; tracingComplete(): Promise; tracingBufferUsage(): void; eventsRetrievalProgress(_progress: number): void; startRecording(): void; isRecording(): boolean; - stopRecording(callback: (filmStrip: TraceEngine.Extras.FilmStrip.Data) => void): void; + stopRecording(callback: (filmStrip: Trace.Extras.FilmStrip.Data) => void): void; } export declare class ActionDelegate implements UI.ActionRegistration.ActionDelegate { handleAction(context: UI.Context.Context, actionId: string): boolean; diff --git a/public/panels/network/NetworkPanel.js b/public/panels/network/NetworkPanel.js index 5f5944671..5fcd8eeae 100644 --- a/public/panels/network/NetworkPanel.js +++ b/public/panels/network/NetworkPanel.js @@ -37,7 +37,7 @@ import * as Platform from '../../core/platform/platform.js'; import * as SDK from '../../core/sdk/sdk.js'; import * as Bindings from '../../models/bindings/bindings.js'; import * as Logs from '../../models/logs/logs.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as Workspace from '../../models/workspace/workspace.js'; import * as NetworkForward from '../../panels/network/forward/forward.js'; import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; @@ -86,7 +86,7 @@ const UIStrings = { */ showMoreInformationInRequestRows: 'Show more information in request rows', /** - *@description Text in Network Panel of the Network panel + *@description Text in Network Panel used to toggle the "big request rows" setting. */ useLargeRequestRows: 'Big request rows', /** @@ -94,7 +94,7 @@ const UIStrings = { */ showOverviewOfNetworkRequests: 'Show overview of network requests', /** - *@description Text in Network Panel of the Network panel + *@description Text in Network Panel used to show the overview for a given network request. */ showOverview: 'Overview', /** @@ -102,7 +102,7 @@ const UIStrings = { */ groupRequestsByTopLevelRequest: 'Group requests by top level request frame', /** - *@description Text in Network Panel of the Network panel + *@description Text for group by frame network setting */ groupByFrame: 'Group by frame', /** @@ -136,7 +136,7 @@ const UIStrings = { */ throttling: 'Throttling', /** - *@description Text in Network Panel of the Network panel + *@description Text in Network Panel to tell the user to reload the page to capture screenshots. *@example {Ctrl + R} PH1 */ hitSToReloadAndCaptureFilmstrip: 'Hit {PH1} to reload and capture filmstrip.', @@ -145,11 +145,11 @@ const UIStrings = { */ revealInNetworkPanel: 'Reveal in Network panel', /** - *@description Text in Network Panel of the Network panel + *@description Text in Network Panel that is displayed whilst the recording is in progress. */ recordingFrames: 'Recording frames...', /** - *@description Text in Network Panel of the Network panel + *@description Text in Network Panel that is displayed when frames are being fetched. */ fetchingFrames: 'Fetching frames...', /** @@ -440,7 +440,7 @@ export class NetworkPanel extends UI.Panel.Panel { } const timestamps = filmStrip.frames.map(frame => { // The network view works in seconds. - return TraceEngine.Helpers.Timing.microSecondsToSeconds(frame.screenshotEvent.ts); + return Trace.Helpers.Timing.microSecondsToSeconds(frame.screenshotEvent.ts); }); this.networkLogView.addFilmStripFrames(timestamps); } @@ -562,6 +562,7 @@ export class NetworkPanel extends UI.Panel.Panel { this.currentRequest = request; this.networkOverview.setHighlightedRequest(request); this.updateNetworkItemView(); + UI.Context.Context.instance().setFlavor(SDK.NetworkRequest.NetworkRequest, request); } onRequestActivated(event) { const { showPanel, tab, takeFocus } = event.data; @@ -678,7 +679,7 @@ export class NetworkPanel extends UI.Panel.Panel { const { request } = event.data; this.calculator.updateBoundaries(request); // FIXME: Unify all time units across the frontend! - this.overviewPane.setBounds(TraceEngine.Types.Timing.MilliSeconds(this.calculator.minimumBoundary() * 1000), TraceEngine.Types.Timing.MilliSeconds(this.calculator.maximumBoundary() * 1000)); + this.overviewPane.setBounds(Trace.Types.Timing.MilliSeconds(this.calculator.minimumBoundary() * 1000), Trace.Types.Timing.MilliSeconds(this.calculator.maximumBoundary() * 1000)); this.networkOverview.updateRequest(request); } resolveLocation(locationName) { @@ -718,8 +719,8 @@ export class FilmStripRecorder { #traceEngine; #collectedTraceEvents = []; constructor(timeCalculator, filmStripView) { - this.#traceEngine = TraceEngine.TraceModel.Model.createWithSubsetOfHandlers({ - Screenshots: TraceEngine.Handlers.ModelHandlers.Screenshots, + this.#traceEngine = Trace.TraceModel.Model.createWithSubsetOfHandlers({ + Screenshots: Trace.Handlers.ModelHandlers.Screenshots, }); this.tracingManager = null; this.resourceTreeModel = null; @@ -736,12 +737,12 @@ export class FilmStripRecorder { } this.tracingManager = null; await this.#traceEngine.parse(this.#collectedTraceEvents); - const data = this.#traceEngine.traceParsedData(this.#traceEngine.size() - 1); + const data = this.#traceEngine.parsedTrace(this.#traceEngine.size() - 1); if (!data) { return; } - const zeroTimeInSeconds = TraceEngine.Types.Timing.Seconds(this.timeCalculator.minimumBoundary()); - const filmStrip = TraceEngine.Extras.FilmStrip.fromTraceData(data, TraceEngine.Helpers.Timing.secondsToMicroseconds(zeroTimeInSeconds)); + const zeroTimeInSeconds = Trace.Types.Timing.Seconds(this.timeCalculator.minimumBoundary()); + const filmStrip = Trace.Extras.FilmStrip.fromParsedTrace(data, Trace.Helpers.Timing.secondsToMicroseconds(zeroTimeInSeconds)); if (this.callback) { this.callback(filmStrip); } @@ -763,7 +764,7 @@ export class FilmStripRecorder { this.#collectedTraceEvents = []; this.filmStripView.reset(); this.filmStripView.setStatusText(i18nString(UIStrings.recordingFrames)); - const tracingManager = SDK.TargetManager.TargetManager.instance().scopeTarget()?.model(TraceEngine.TracingManager.TracingManager); + const tracingManager = SDK.TargetManager.TargetManager.instance().scopeTarget()?.model(Trace.TracingManager.TracingManager); if (this.tracingManager || !tracingManager) { return; } diff --git a/public/panels/network/NetworkPanel.js.map b/public/panels/network/NetworkPanel.js.map index a91f916b4..0ba16a478 100644 --- a/public/panels/network/NetworkPanel.js.map +++ b/public/panels/network/NetworkPanel.js.map @@ -1 +1 @@ -{"version":3,"file":"NetworkPanel.js","sourceRoot":"","sources":["../../../../../../front_end/panels/network/NetworkPanel.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2021 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/*\n * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.\n * Copyright (C) 2008, 2009 Anthony Ricaud \n * Copyright (C) 2011 Google Inc. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. Neither the name of Apple Computer, Inc. (\"Apple\") nor the names of\n * its contributors may be used to endorse or promote products derived\n * from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport * as Common from '../../core/common/common.js';\nimport * as Host from '../../core/host/host.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as Bindings from '../../models/bindings/bindings.js';\nimport type * as Extensions from '../../models/extensions/extensions.js';\nimport * as Logs from '../../models/logs/logs.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as Workspace from '../../models/workspace/workspace.js';\nimport * as NetworkForward from '../../panels/network/forward/forward.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\nimport * as MobileThrottling from '../mobile_throttling/mobile_throttling.js';\nimport * as Search from '../search/search.js';\nimport * as TimelineUtils from '../timeline/utils/utils.js';\n\nimport {Events, type RequestActivatedEvent} from './NetworkDataGridNode.js';\nimport {NetworkItemView} from './NetworkItemView.js';\nimport {NetworkLogView} from './NetworkLogView.js';\nimport {NetworkOverview} from './NetworkOverview.js';\nimport networkPanelStyles from './networkPanel.css.js';\nimport {NetworkSearchScope} from './NetworkSearchScope.js';\nimport {type NetworkTimeCalculator, NetworkTransferTimeCalculator} from './NetworkTimeCalculator.js';\n\nconst UIStrings = {\n /**\n *@description Text to close something\n */\n close: 'Close',\n /**\n *@description Title of a search bar or tool\n */\n search: 'Search',\n /**\n *@description Tooltip text that appears on the setting to preserve log when hovering over the item\n */\n doNotClearLogOnPageReload: 'Do not clear log on page reload / navigation',\n /**\n *@description Text to preserve the log after refreshing\n */\n preserveLog: 'Preserve log',\n /**\n *@description Text to disable cache while DevTools is open\n */\n disableCacheWhileDevtoolsIsOpen: 'Disable cache (while DevTools is open)',\n /**\n *@description Text in Network Config View of the Network panel\n */\n disableCache: 'Disable cache',\n /**\n *@description Tooltip text that appears when hovering over the largeicon settings gear in show settings pane setting in network panel of the network panel\n */\n networkSettings: 'Network settings',\n /**\n *@description Tooltip for expanding network request row setting\n */\n showMoreInformationInRequestRows: 'Show more information in request rows',\n /**\n *@description Text in Network Panel of the Network panel\n */\n useLargeRequestRows: 'Big request rows',\n /**\n *@description Tooltip text for network request overview setting\n */\n showOverviewOfNetworkRequests: 'Show overview of network requests',\n /**\n *@description Text in Network Panel of the Network panel\n */\n showOverview: 'Overview',\n /**\n *@description Tooltip for group by frame network setting\n */\n groupRequestsByTopLevelRequest: 'Group requests by top level request frame',\n /**\n *@description Text in Network Panel of the Network panel\n */\n groupByFrame: 'Group by frame',\n /**\n *@description Tooltip for capture screenshot network setting\n */\n captureScreenshotsWhenLoadingA: 'Capture screenshots when loading a page',\n /**\n *@description Text to take screenshots\n */\n captureScreenshots: 'Screenshots',\n /**\n * @description Tooltip text that appears when hovering over the largeicon load button in the\n * Network Panel. This action prompts the user to select a HAR file to upload to DevTools.\n */\n importHarFile: 'Import `HAR` file...',\n /**\n * @description Tooltip text that appears when hovering over the largeicon download button in the\n * Network Panel. HAR is a file format (HTTP Archive) and should not be translated. This action\n * triggers the download of a HAR file.\n */\n exportHarSanitized: 'Export `HAR` (sanitized)...',\n /**\n * @description Context menu item in the export long click button of the Network panel, which is\n * only available when the Network setting to allow generating HAR with sensitive data is active.\n * HAR is a file format (HTTP Archive) and should not be translated. This action triggers the\n * download of a HAR file with sensitive data included.\n */\n exportHarWithSensitiveData: 'Export `HAR` (with sensitive data)...',\n /**\n *@description Text for throttling the network\n */\n throttling: 'Throttling',\n /**\n *@description Text in Network Panel of the Network panel\n *@example {Ctrl + R} PH1\n */\n hitSToReloadAndCaptureFilmstrip: 'Hit {PH1} to reload and capture filmstrip.',\n /**\n *@description A context menu item in the Network Panel of the Network panel\n */\n revealInNetworkPanel: 'Reveal in Network panel',\n /**\n *@description Text in Network Panel of the Network panel\n */\n recordingFrames: 'Recording frames...',\n /**\n *@description Text in Network Panel of the Network panel\n */\n fetchingFrames: 'Fetching frames...',\n /**\n * @description Text of a button in the Network panel's toolbar that open Network Conditions panel in the drawer.\n */\n moreNetworkConditions: 'More network conditions…',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/network/NetworkPanel.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nlet networkPanelInstance: NetworkPanel;\n\nexport class NetworkPanel extends UI.Panel.Panel implements\n UI.ContextMenu\n .Provider,\n UI.View.ViewLocationResolver {\n private readonly networkLogShowOverviewSetting: Common.Settings.Setting;\n private readonly networkLogLargeRowsSetting: Common.Settings.Setting;\n private readonly networkRecordFilmStripSetting: Common.Settings.Setting;\n private readonly toggleRecordAction: UI.ActionRegistration.Action;\n private pendingStopTimer!: number|undefined;\n networkItemView: NetworkItemView|null;\n private filmStripView: PerfUI.FilmStripView.FilmStripView|null;\n private filmStripRecorder: FilmStripRecorder|null;\n private currentRequest: SDK.NetworkRequest.NetworkRequest|null;\n private readonly panelToolbar: UI.Toolbar.Toolbar;\n private readonly rightToolbar: UI.Toolbar.Toolbar;\n private readonly filterBar: UI.FilterBar.FilterBar;\n private readonly settingsPane: UI.Widget.HBox;\n private showSettingsPaneSetting: Common.Settings.Setting;\n private readonly filmStripPlaceholderElement: HTMLElement;\n private readonly overviewPane: PerfUI.TimelineOverviewPane.TimelineOverviewPane;\n private readonly networkOverview: NetworkOverview;\n private readonly overviewPlaceholderElement: HTMLElement;\n private readonly calculator: NetworkTransferTimeCalculator;\n private splitWidget: UI.SplitWidget.SplitWidget;\n private readonly sidebarLocation: UI.View.TabbedViewLocation;\n private readonly progressBarContainer: HTMLDivElement;\n networkLogView: NetworkLogView;\n private readonly fileSelectorElement: HTMLElement;\n private readonly detailsWidget: UI.Widget.VBox;\n private readonly closeButtonElement: HTMLDivElement;\n private preserveLogSetting: Common.Settings.Setting;\n recordLogSetting: Common.Settings.Setting;\n private readonly throttlingSelect: UI.Toolbar.ToolbarComboBox;\n private readonly displayScreenshotDelay: number;\n\n constructor(displayScreenshotDelay: number) {\n super('network');\n\n this.displayScreenshotDelay = displayScreenshotDelay;\n this.networkLogShowOverviewSetting =\n Common.Settings.Settings.instance().createSetting('network-log-show-overview', true);\n this.networkLogLargeRowsSetting =\n Common.Settings.Settings.instance().createSetting('network-log-large-rows', false);\n this.networkRecordFilmStripSetting =\n Common.Settings.Settings.instance().createSetting('network-record-film-strip-setting', false);\n this.toggleRecordAction = UI.ActionRegistry.ActionRegistry.instance().getAction('network.toggle-recording');\n this.networkItemView = null;\n this.filmStripView = null;\n this.filmStripRecorder = null;\n this.currentRequest = null;\n\n const panel = new UI.Widget.VBox();\n\n const networkToolbarContainer = panel.contentElement.createChild('div', 'network-toolbar-container');\n this.panelToolbar = new UI.Toolbar.Toolbar('', networkToolbarContainer);\n this.panelToolbar.makeWrappable(true);\n this.panelToolbar.element.setAttribute('jslog', `${VisualLogging.toolbar('network-main')}`);\n this.rightToolbar = new UI.Toolbar.Toolbar('', networkToolbarContainer);\n\n this.filterBar = new UI.FilterBar.FilterBar('network-panel', true);\n this.filterBar.show(panel.contentElement);\n this.filterBar.addEventListener(UI.FilterBar.FilterBarEvents.CHANGED, this.handleFilterChanged.bind(this));\n\n this.settingsPane = new UI.Widget.HBox();\n this.settingsPane.element.classList.add('network-settings-pane');\n this.settingsPane.show(panel.contentElement);\n this.showSettingsPaneSetting =\n Common.Settings.Settings.instance().createSetting('network-show-settings-toolbar', false);\n this.showSettingsPaneSetting.addChangeListener(this.updateSettingsPaneVisibility.bind(this));\n this.updateSettingsPaneVisibility();\n\n this.filmStripPlaceholderElement = panel.contentElement.createChild('div', 'network-film-strip-placeholder');\n\n // Create top overview component.\n this.overviewPane = new PerfUI.TimelineOverviewPane.TimelineOverviewPane('network');\n this.overviewPane.addEventListener(\n PerfUI.TimelineOverviewPane.Events.OVERVIEW_PANE_WINDOW_CHANGED, this.onWindowChanged.bind(this));\n this.overviewPane.element.id = 'network-overview-panel';\n this.networkOverview = new NetworkOverview();\n this.overviewPane.setOverviewControls([this.networkOverview]);\n this.overviewPlaceholderElement = panel.contentElement.createChild('div');\n\n this.calculator = new NetworkTransferTimeCalculator();\n\n this.splitWidget = new UI.SplitWidget.SplitWidget(true, false, 'network-panel-split-view-state');\n this.splitWidget.hideMain();\n this.splitWidget.show(panel.contentElement);\n\n panel.setDefaultFocusedChild(this.filterBar);\n\n const initialSidebarWidth = 225;\n const splitWidget = new UI.SplitWidget.SplitWidget(true, false, 'network-panel-sidebar-state', initialSidebarWidth);\n splitWidget.hideSidebar();\n splitWidget.enableShowModeSaving();\n splitWidget.show(this.element);\n this.sidebarLocation = UI.ViewManager.ViewManager.instance().createTabbedLocation(async () => {\n void UI.ViewManager.ViewManager.instance().showView('network');\n splitWidget.showBoth();\n }, 'network-sidebar', true);\n const tabbedPane = this.sidebarLocation.tabbedPane();\n tabbedPane.setMinimumSize(100, 25);\n tabbedPane.element.classList.add('network-tabbed-pane');\n tabbedPane.element.addEventListener('keydown', event => {\n if (event.key !== Platform.KeyboardUtilities.ESCAPE_KEY) {\n return;\n }\n splitWidget.hideSidebar();\n event.consume();\n void VisualLogging.logKeyDown(event.currentTarget, event, 'hide-sidebar');\n });\n const closeSidebar = new UI.Toolbar.ToolbarButton(i18nString(UIStrings.close), 'cross');\n closeSidebar.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, () => splitWidget.hideSidebar());\n closeSidebar.element.setAttribute('jslog', `${VisualLogging.close().track({click: true})}`);\n tabbedPane.rightToolbar().appendToolbarItem(closeSidebar);\n splitWidget.setSidebarWidget(tabbedPane);\n splitWidget.setMainWidget(panel);\n splitWidget.setDefaultFocusedChild(panel);\n this.setDefaultFocusedChild(splitWidget);\n\n this.progressBarContainer = document.createElement('div');\n\n this.networkLogView =\n new NetworkLogView(this.filterBar, this.progressBarContainer, this.networkLogLargeRowsSetting);\n this.splitWidget.setSidebarWidget(this.networkLogView);\n this.fileSelectorElement =\n (UI.UIUtils.createFileSelectorElement(this.networkLogView.onLoadFromFile.bind(this.networkLogView)) as\n HTMLElement);\n panel.element.appendChild(this.fileSelectorElement);\n\n this.detailsWidget = new UI.Widget.VBox();\n this.detailsWidget.element.classList.add('network-details-view');\n this.splitWidget.setMainWidget(this.detailsWidget);\n\n this.closeButtonElement = document.createElement('div', {is: 'dt-close-button'});\n this.closeButtonElement.addEventListener('click', async () => {\n const action = UI.ActionRegistry.ActionRegistry.instance().getAction('network.hide-request-details');\n await action.execute();\n }, false);\n this.closeButtonElement.style.margin = '0 5px';\n\n this.networkLogShowOverviewSetting.addChangeListener(this.toggleShowOverview, this);\n this.networkLogLargeRowsSetting.addChangeListener(this.toggleLargerRequests, this);\n this.networkRecordFilmStripSetting.addChangeListener(this.toggleRecordFilmStrip, this);\n\n this.preserveLogSetting = Common.Settings.Settings.instance().moduleSetting('network-log.preserve-log');\n this.recordLogSetting = Common.Settings.Settings.instance().moduleSetting('network-log.record-log');\n this.recordLogSetting.addChangeListener(({data}) => this.toggleRecord(data));\n\n this.throttlingSelect = this.createThrottlingConditionsSelect();\n this.setupToolbarButtons(splitWidget);\n\n this.toggleRecord(this.recordLogSetting.get());\n this.toggleShowOverview();\n this.toggleLargerRequests();\n this.toggleRecordFilmStrip();\n this.updateUI();\n\n SDK.TargetManager.TargetManager.instance().addModelListener(\n SDK.ResourceTreeModel.ResourceTreeModel, SDK.ResourceTreeModel.Events.WillReloadPage, this.willReloadPage, this,\n {scoped: true});\n SDK.TargetManager.TargetManager.instance().addModelListener(\n SDK.ResourceTreeModel.ResourceTreeModel, SDK.ResourceTreeModel.Events.Load, this.load, this, {scoped: true});\n this.networkLogView.addEventListener(Events.RequestSelected, this.onRequestSelected, this);\n this.networkLogView.addEventListener(Events.RequestActivated, this.onRequestActivated, this);\n Logs.NetworkLog.NetworkLog.instance().addEventListener(\n Logs.NetworkLog.Events.RequestAdded, this.onUpdateRequest, this);\n Logs.NetworkLog.NetworkLog.instance().addEventListener(\n Logs.NetworkLog.Events.RequestUpdated, this.onUpdateRequest, this);\n Logs.NetworkLog.NetworkLog.instance().addEventListener(Logs.NetworkLog.Events.Reset, this.onNetworkLogReset, this);\n }\n\n static instance(opts?: {\n forceNew: boolean,\n displayScreenshotDelay?: number,\n }): NetworkPanel {\n if (!networkPanelInstance || opts?.forceNew) {\n networkPanelInstance = new NetworkPanel(opts?.displayScreenshotDelay ?? 1000);\n }\n\n return networkPanelInstance;\n }\n\n static revealAndFilter(filters: {\n filterType: NetworkForward.UIFilter.FilterType|null,\n filterValue: string,\n }[]): Promise {\n const panel = NetworkPanel.instance();\n let filterString = '';\n for (const filter of filters) {\n if (filter.filterType) {\n filterString += `${filter.filterType}:${filter.filterValue} `;\n } else {\n filterString += `${filter.filterValue} `;\n }\n }\n panel.networkLogView.setTextFilterValue(filterString);\n return UI.ViewManager.ViewManager.instance().showView('network');\n }\n\n static async selectAndShowRequest(\n request: SDK.NetworkRequest.NetworkRequest, tab: NetworkForward.UIRequestLocation.UIRequestTabs,\n options?: NetworkForward.UIRequestLocation.FilterOptions): Promise {\n const panel = NetworkPanel.instance();\n await panel.selectAndActivateRequest(request, tab, options);\n }\n\n throttlingSelectForTest(): UI.Toolbar.ToolbarComboBox {\n return this.throttlingSelect;\n }\n\n private onWindowChanged(\n event: Common.EventTarget.EventTargetEvent): void {\n const startTime = Math.max(this.calculator.minimumBoundary(), event.data.startTime / 1000);\n const endTime = Math.min(this.calculator.maximumBoundary(), event.data.endTime / 1000);\n if (startTime === this.calculator.minimumBoundary() && endTime === this.calculator.maximumBoundary()) {\n // Reset the filters for NetworkLogView when the window is reset\n // to its boundaries. This clears the filters and allows the users\n // to see the incoming requests after they have updated the curtains\n // to be in the edges. (ex: by double clicking on the overview grid)\n this.networkLogView.setWindow(0, 0);\n } else {\n this.networkLogView.setWindow(startTime, endTime);\n }\n }\n\n private async searchToggleClick(): Promise {\n const action = UI.ActionRegistry.ActionRegistry.instance().getAction('network.search');\n await action.execute();\n }\n\n private setupToolbarButtons(splitWidget: UI.SplitWidget.SplitWidget): void {\n const searchToggle = new UI.Toolbar.ToolbarToggle(i18nString(UIStrings.search), 'search', undefined, 'search');\n function updateSidebarToggle(): void {\n const isSidebarShowing = splitWidget.showMode() !== UI.SplitWidget.ShowMode.ONLY_MAIN;\n searchToggle.setToggled(isSidebarShowing);\n if (!isSidebarShowing) {\n (searchToggle.element as HTMLElement).focus();\n }\n }\n this.panelToolbar.appendToolbarItem(UI.Toolbar.Toolbar.createActionButton(this.toggleRecordAction));\n this.panelToolbar.appendToolbarItem(UI.Toolbar.Toolbar.createActionButtonForId('network.clear'));\n this.panelToolbar.appendSeparator();\n\n this.panelToolbar.appendToolbarItem(this.filterBar.filterButton());\n updateSidebarToggle();\n splitWidget.addEventListener(UI.SplitWidget.Events.SHOW_MODE_CHANGED, updateSidebarToggle);\n searchToggle.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, () => {\n void this.searchToggleClick();\n });\n this.panelToolbar.appendToolbarItem(searchToggle);\n this.panelToolbar.appendSeparator();\n\n this.panelToolbar.appendToolbarItem(new UI.Toolbar.ToolbarSettingCheckbox(\n this.preserveLogSetting, i18nString(UIStrings.doNotClearLogOnPageReload), i18nString(UIStrings.preserveLog)));\n\n this.panelToolbar.appendSeparator();\n const disableCacheCheckbox = new UI.Toolbar.ToolbarSettingCheckbox(\n Common.Settings.Settings.instance().moduleSetting('cache-disabled'),\n i18nString(UIStrings.disableCacheWhileDevtoolsIsOpen), i18nString(UIStrings.disableCache));\n this.panelToolbar.appendToolbarItem(disableCacheCheckbox);\n\n this.panelToolbar.appendToolbarItem(this.throttlingSelect);\n\n const networkConditionsButton = new UI.Toolbar.ToolbarButton(\n i18nString(UIStrings.moreNetworkConditions), 'network-settings', undefined, 'network-conditions');\n networkConditionsButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, () => {\n void UI.ViewManager.ViewManager.instance().showView('network.config');\n }, this);\n this.panelToolbar.appendToolbarItem(networkConditionsButton);\n\n this.rightToolbar.appendToolbarItem(new UI.Toolbar.ToolbarItem(this.progressBarContainer));\n this.rightToolbar.appendSeparator();\n this.rightToolbar.appendToolbarItem(new UI.Toolbar.ToolbarSettingToggle(\n this.showSettingsPaneSetting, 'gear', i18nString(UIStrings.networkSettings), 'gear-filled',\n 'network-settings'));\n\n const settingsToolbarLeft = new UI.Toolbar.Toolbar('', this.settingsPane.element);\n settingsToolbarLeft.makeVertical();\n settingsToolbarLeft.appendToolbarItem(new UI.Toolbar.ToolbarSettingCheckbox(\n this.networkLogLargeRowsSetting, i18nString(UIStrings.showMoreInformationInRequestRows),\n i18nString(UIStrings.useLargeRequestRows)));\n settingsToolbarLeft.appendToolbarItem(new UI.Toolbar.ToolbarSettingCheckbox(\n this.networkLogShowOverviewSetting, i18nString(UIStrings.showOverviewOfNetworkRequests),\n i18nString(UIStrings.showOverview)));\n\n const settingsToolbarRight = new UI.Toolbar.Toolbar('', this.settingsPane.element);\n settingsToolbarRight.makeVertical();\n settingsToolbarRight.appendToolbarItem(new UI.Toolbar.ToolbarSettingCheckbox(\n Common.Settings.Settings.instance().moduleSetting('network.group-by-frame'),\n i18nString(UIStrings.groupRequestsByTopLevelRequest), i18nString(UIStrings.groupByFrame)));\n settingsToolbarRight.appendToolbarItem(new UI.Toolbar.ToolbarSettingCheckbox(\n this.networkRecordFilmStripSetting, i18nString(UIStrings.captureScreenshotsWhenLoadingA),\n i18nString(UIStrings.captureScreenshots)));\n\n this.panelToolbar.appendSeparator();\n const importHarButton =\n new UI.Toolbar.ToolbarButton(i18nString(UIStrings.importHarFile), 'import', undefined, 'import-har');\n importHarButton.addEventListener(\n UI.Toolbar.ToolbarButton.Events.CLICK, () => this.fileSelectorElement.click(), this);\n this.panelToolbar.appendToolbarItem(importHarButton);\n const exportHarButton =\n new UI.Toolbar.ToolbarButton(i18nString(UIStrings.exportHarSanitized), 'download', undefined, 'export-har');\n exportHarButton.addEventListener(\n UI.Toolbar.ToolbarButton.Events.CLICK,\n this.networkLogView.exportAll.bind(this.networkItemView, {sanitize: true}), this);\n this.panelToolbar.appendToolbarItem(exportHarButton);\n\n // Support for exporting HAR (with sensitive data), which is added via a long-click\n // context menu on the Export button in the Network panel.\n // Checkout https://goo.gle/devtools-har-exclude-cookies-design for more details.\n const networkShowOptionsToGenerateHarWithSensitiveData = Common.Settings.Settings.instance().createSetting(\n 'network.show-options-to-generate-har-with-sensitive-data', false);\n let controller: UI.UIUtils.LongClickController|null = null;\n const updateShowOptionsToGenerateHarWithSensitiveData = (): void => {\n exportHarButton.setLongClickable(networkShowOptionsToGenerateHarWithSensitiveData.get());\n if (controller !== null) {\n controller.dispose();\n controller = null;\n }\n if (networkShowOptionsToGenerateHarWithSensitiveData.get()) {\n controller = new UI.UIUtils.LongClickController(exportHarButton.element, event => {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.exportHarSanitized),\n this.networkLogView.exportAll.bind(this.networkItemView, {sanitize: true}),\n {jslogContext: 'export-har'},\n );\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.exportHarWithSensitiveData),\n this.networkLogView.exportAll.bind(this.networkItemView, {sanitize: false}),\n {jslogContext: 'export-har-with-sensitive-data'},\n );\n void contextMenu.show();\n });\n }\n };\n networkShowOptionsToGenerateHarWithSensitiveData.addChangeListener(updateShowOptionsToGenerateHarWithSensitiveData);\n updateShowOptionsToGenerateHarWithSensitiveData();\n }\n\n private updateSettingsPaneVisibility(): void {\n this.settingsPane.element.classList.toggle('hidden', !this.showSettingsPaneSetting.get());\n }\n\n private createThrottlingConditionsSelect(): UI.Toolbar.ToolbarComboBox {\n const toolbarItem = new UI.Toolbar.ToolbarComboBox(null, i18nString(UIStrings.throttling));\n toolbarItem.setMaxWidth(160);\n MobileThrottling.ThrottlingManager.throttlingManager().decorateSelectWithNetworkThrottling(\n toolbarItem.selectElement());\n return toolbarItem;\n }\n\n toggleRecord(toggled: boolean): void {\n this.toggleRecordAction.setToggled(toggled);\n if (this.recordLogSetting.get() !== toggled) {\n this.recordLogSetting.set(toggled);\n }\n\n this.networkLogView.setRecording(toggled);\n if (!toggled && this.filmStripRecorder) {\n this.filmStripRecorder.stopRecording(this.filmStripAvailable.bind(this));\n }\n }\n\n private filmStripAvailable(filmStrip: TraceEngine.Extras.FilmStrip.Data): void {\n if (this.filmStripView) {\n this.filmStripView.setModel(filmStrip);\n }\n const timestamps = filmStrip.frames.map(frame => {\n // The network view works in seconds.\n return TraceEngine.Helpers.Timing.microSecondsToSeconds(frame.screenshotEvent.ts);\n });\n\n this.networkLogView.addFilmStripFrames(timestamps);\n }\n\n private onNetworkLogReset(event: Common.EventTarget.EventTargetEvent): void {\n const {clearIfPreserved} = event.data;\n if (!this.preserveLogSetting.get() || clearIfPreserved) {\n this.calculator.reset();\n this.overviewPane.reset();\n }\n if (this.filmStripView) {\n this.resetFilmStripView();\n }\n }\n\n private willReloadPage(): void {\n if (this.pendingStopTimer) {\n clearTimeout(this.pendingStopTimer);\n delete this.pendingStopTimer;\n }\n if (this.isShowing() && this.filmStripRecorder) {\n this.filmStripRecorder.startRecording();\n }\n }\n\n private load(): void {\n if (this.filmStripRecorder && this.filmStripRecorder.isRecording()) {\n if (this.pendingStopTimer) {\n window.clearTimeout(this.pendingStopTimer);\n }\n this.pendingStopTimer = window.setTimeout(this.stopFilmStripRecording.bind(this), this.displayScreenshotDelay);\n }\n }\n\n private stopFilmStripRecording(): void {\n if (this.filmStripRecorder) {\n this.filmStripRecorder.stopRecording(this.filmStripAvailable.bind(this));\n }\n delete this.pendingStopTimer;\n }\n\n private toggleLargerRequests(): void {\n this.updateUI();\n }\n\n private toggleShowOverview(): void {\n const toggled = this.networkLogShowOverviewSetting.get();\n if (toggled) {\n this.overviewPane.show(this.overviewPlaceholderElement);\n } else {\n this.overviewPane.detach();\n }\n this.doResize();\n }\n\n private toggleRecordFilmStrip(): void {\n const toggled = this.networkRecordFilmStripSetting.get();\n if (toggled && !this.filmStripRecorder) {\n this.filmStripView = new PerfUI.FilmStripView.FilmStripView();\n this.filmStripView.element.classList.add('network-film-strip');\n this.filmStripView.element.setAttribute('jslog', `${VisualLogging.section('film-strip')}`);\n this.filmStripRecorder = new FilmStripRecorder(this.networkLogView.timeCalculator(), this.filmStripView);\n this.filmStripView.show(this.filmStripPlaceholderElement);\n this.filmStripView.addEventListener(PerfUI.FilmStripView.Events.FRAME_SELECTED, this.onFilmFrameSelected, this);\n this.filmStripView.addEventListener(PerfUI.FilmStripView.Events.FRAME_ENTER, this.onFilmFrameEnter, this);\n this.filmStripView.addEventListener(PerfUI.FilmStripView.Events.FRAME_EXIT, this.onFilmFrameExit, this);\n this.resetFilmStripView();\n }\n\n if (!toggled && this.filmStripRecorder) {\n if (this.filmStripView) {\n this.filmStripView.detach();\n }\n this.filmStripView = null;\n this.filmStripRecorder = null;\n }\n }\n\n private resetFilmStripView(): void {\n const reloadShortcut =\n UI.ShortcutRegistry.ShortcutRegistry.instance().shortcutsForAction('inspector-main.reload')[0];\n\n if (this.filmStripView) {\n this.filmStripView.reset();\n if (reloadShortcut) {\n this.filmStripView.setStatusText(\n i18nString(UIStrings.hitSToReloadAndCaptureFilmstrip, {PH1: reloadShortcut.title()}));\n }\n }\n }\n\n override elementsToRestoreScrollPositionsFor(): Element[] {\n return this.networkLogView.elementsToRestoreScrollPositionsFor();\n }\n\n override wasShown(): void {\n UI.Context.Context.instance().setFlavor(NetworkPanel, this);\n this.registerCSSFiles([networkPanelStyles]);\n\n // Record the network tool load time after the panel has loaded.\n Host.userMetrics.panelLoaded('network', 'DevTools.Launch.Network');\n }\n\n override willHide(): void {\n UI.Context.Context.instance().setFlavor(NetworkPanel, null);\n }\n\n revealAndHighlightRequest(request: SDK.NetworkRequest.NetworkRequest): void {\n this.hideRequestPanel();\n if (request) {\n this.networkLogView.revealAndHighlightRequest(request);\n }\n }\n\n revealAndHighlightRequestWithId(request: NetworkForward.NetworkRequestId.NetworkRequestId): void {\n this.hideRequestPanel();\n if (request) {\n this.networkLogView.revealAndHighlightRequestWithId(request);\n }\n }\n\n async selectAndActivateRequest(\n request: SDK.NetworkRequest.NetworkRequest, shownTab?: NetworkForward.UIRequestLocation.UIRequestTabs,\n options?: NetworkForward.UIRequestLocation.FilterOptions): Promise {\n await UI.ViewManager.ViewManager.instance().showView('network');\n this.networkLogView.selectRequest(request, options);\n this.showRequestPanel(shownTab);\n this.networkLogView.revealAndHighlightRequest(request);\n return this.networkItemView;\n }\n\n private handleFilterChanged(): void {\n this.hideRequestPanel();\n }\n\n private onRowSizeChanged(): void {\n this.updateUI();\n }\n private onRequestSelected(event: Common.EventTarget.EventTargetEvent): void {\n const request = event.data;\n this.currentRequest = request;\n this.networkOverview.setHighlightedRequest(request);\n this.updateNetworkItemView();\n }\n\n private onRequestActivated(event: Common.EventTarget.EventTargetEvent): void {\n const {showPanel, tab, takeFocus} = event.data;\n if (showPanel) {\n this.showRequestPanel(tab, takeFocus);\n } else {\n this.hideRequestPanel();\n }\n }\n\n private showRequestPanel(shownTab?: NetworkForward.UIRequestLocation.UIRequestTabs, takeFocus?: boolean): void {\n if (this.splitWidget.showMode() === UI.SplitWidget.ShowMode.BOTH && !shownTab && !takeFocus) {\n // If panel is already shown, and we are not forcing a specific tab, return.\n return;\n }\n this.clearNetworkItemView();\n if (this.currentRequest) {\n const networkItemView = this.createNetworkItemView(shownTab);\n if (networkItemView && takeFocus) {\n networkItemView.focus();\n }\n }\n this.updateUI();\n }\n\n hideRequestPanel(): void {\n this.clearNetworkItemView();\n this.splitWidget.hideMain();\n this.updateUI();\n }\n\n private updateNetworkItemView(): void {\n if (this.splitWidget.showMode() === UI.SplitWidget.ShowMode.BOTH) {\n this.clearNetworkItemView();\n this.createNetworkItemView();\n this.updateUI();\n }\n }\n\n private clearNetworkItemView(): void {\n if (this.networkItemView) {\n this.networkItemView.detach();\n this.networkItemView = null;\n }\n }\n private createNetworkItemView(initialTab?: NetworkForward.UIRequestLocation.UIRequestTabs): NetworkItemView\n |undefined {\n if (!this.currentRequest) {\n return;\n }\n this.networkItemView = new NetworkItemView(this.currentRequest, this.networkLogView.timeCalculator(), initialTab);\n this.networkItemView.leftToolbar().appendToolbarItem(new UI.Toolbar.ToolbarItem(this.closeButtonElement));\n this.networkItemView.show(this.detailsWidget.element);\n this.splitWidget.showBoth();\n return this.networkItemView;\n }\n\n private updateUI(): void {\n if (this.detailsWidget) {\n this.detailsWidget.element.classList.toggle(\n 'network-details-view-tall-header', this.networkLogLargeRowsSetting.get());\n }\n if (this.networkLogView) {\n this.networkLogView.switchViewMode(!this.splitWidget.isResizable());\n }\n }\n\n appendApplicableItems(\n this: NetworkPanel, event: Event, contextMenu: UI.ContextMenu.ContextMenu,\n target: SDK.NetworkRequest.NetworkRequest|SDK.Resource.Resource|Workspace.UISourceCode.UISourceCode|\n TimelineUtils.NetworkRequest.TimelineNetworkRequest): void {\n const appendRevealItem = (request: SDK.NetworkRequest.NetworkRequest): void => {\n contextMenu.revealSection().appendItem(\n i18nString(UIStrings.revealInNetworkPanel),\n () => UI.ViewManager.ViewManager.instance()\n .showView('network')\n .then(this.networkLogView.resetFilter.bind(this.networkLogView))\n .then(this.revealAndHighlightRequest.bind(this, request)),\n {jslogContext: 'reveal-in-network'});\n };\n const appendRevealItemAndSelect = (request: TimelineUtils.NetworkRequest.TimelineNetworkRequest): void => {\n contextMenu.revealSection().appendItem(\n i18nString(UIStrings.revealInNetworkPanel),\n () => UI.ViewManager.ViewManager.instance()\n .showView('network')\n .then(this.networkLogView.resetFilter.bind(this.networkLogView))\n .then(this.selectAndActivateRequest.bind(\n this, request.request, NetworkForward.UIRequestLocation.UIRequestTabs.HEADERS_COMPONENT,\n /* FilterOptions= */ undefined)),\n {jslogContext: 'timeline.reveal-in-network'});\n };\n\n if ((event.target as Node).isSelfOrDescendant(this.element)) {\n return;\n }\n\n if (target instanceof SDK.Resource.Resource) {\n if (target.request) {\n appendRevealItem(target.request);\n }\n return;\n }\n if (target instanceof Workspace.UISourceCode.UISourceCode) {\n const resource = Bindings.ResourceUtils.resourceForURL(target.url());\n if (resource && resource.request) {\n appendRevealItem(resource.request);\n }\n return;\n }\n if (target instanceof TimelineUtils.NetworkRequest.TimelineNetworkRequest) {\n appendRevealItemAndSelect(target);\n return;\n }\n\n if (this.networkItemView && this.networkItemView.isShowing() && this.networkItemView.request() === target) {\n return;\n }\n\n appendRevealItem(target);\n }\n\n private onFilmFrameSelected(event: Common.EventTarget.EventTargetEvent): void {\n const timestamp = event.data;\n this.overviewPane.setWindowTimes(0, timestamp);\n }\n\n private onFilmFrameEnter(event: Common.EventTarget.EventTargetEvent): void {\n const timestamp = event.data;\n this.networkOverview.selectFilmStripFrame(timestamp);\n this.networkLogView.selectFilmStripFrame(timestamp / 1000);\n }\n\n private onFilmFrameExit(): void {\n this.networkOverview.clearFilmStripFrame();\n this.networkLogView.clearFilmStripFrame();\n }\n\n private onUpdateRequest(event: Common.EventTarget.EventTargetEvent<{request: SDK.NetworkRequest.NetworkRequest}>):\n void {\n const {request} = event.data;\n this.calculator.updateBoundaries(request);\n // FIXME: Unify all time units across the frontend!\n this.overviewPane.setBounds(\n TraceEngine.Types.Timing.MilliSeconds(this.calculator.minimumBoundary() * 1000),\n TraceEngine.Types.Timing.MilliSeconds(this.calculator.maximumBoundary() * 1000));\n this.networkOverview.updateRequest(request);\n }\n\n resolveLocation(locationName: string): UI.View.ViewLocation|null {\n if (locationName === 'network-sidebar') {\n return this.sidebarLocation;\n }\n return null;\n }\n}\n\nexport class RequestRevealer implements Common.Revealer.Revealer {\n reveal(request: SDK.NetworkRequest.NetworkRequest): Promise {\n const panel = NetworkPanel.instance();\n return UI.ViewManager.ViewManager.instance().showView('network').then(\n panel.revealAndHighlightRequest.bind(panel, request));\n }\n}\n\nexport class RequestIdRevealer implements Common.Revealer.Revealer {\n reveal(requestId: NetworkForward.NetworkRequestId.NetworkRequestId): Promise {\n const panel = NetworkPanel.instance();\n return UI.ViewManager.ViewManager.instance().showView('network').then(\n panel.revealAndHighlightRequestWithId.bind(panel, requestId));\n }\n}\n\nexport class NetworkLogWithFilterRevealer implements\n Common.Revealer\n .Revealer {\n reveal(request: Extensions.ExtensionServer.RevealableNetworkRequestFilter|\n NetworkForward.UIFilter.UIRequestFilter): Promise {\n if ('filters' in request) {\n return NetworkPanel.revealAndFilter(request.filters);\n }\n return NetworkPanel.revealAndFilter(request.filter ? [{filterType: null, filterValue: request.filter}] : []);\n }\n}\n\nexport class FilmStripRecorder implements TraceEngine.TracingManager.TracingManagerClient {\n private tracingManager: TraceEngine.TracingManager.TracingManager|null;\n private resourceTreeModel: SDK.ResourceTreeModel.ResourceTreeModel|null;\n private readonly timeCalculator: NetworkTimeCalculator;\n private readonly filmStripView: PerfUI.FilmStripView.FilmStripView;\n private callback: ((filmStrip: TraceEngine.Extras.FilmStrip.Data) => void)|null;\n // Used to fetch screenshots of the page load and show them in the panel.\n #traceEngine: TraceEngine.TraceModel.Model;\n #collectedTraceEvents: TraceEngine.Types.TraceEvents.TraceEventData[] = [];\n\n constructor(timeCalculator: NetworkTimeCalculator, filmStripView: PerfUI.FilmStripView.FilmStripView) {\n this.#traceEngine = TraceEngine.TraceModel.Model.createWithSubsetOfHandlers({\n Screenshots: TraceEngine.Handlers.ModelHandlers.Screenshots,\n });\n\n this.tracingManager = null;\n this.resourceTreeModel = null;\n this.timeCalculator = timeCalculator;\n this.filmStripView = filmStripView;\n this.callback = null;\n }\n\n traceEventsCollected(events: TraceEngine.Types.TraceEvents.TraceEventData[]): void {\n this.#collectedTraceEvents.push(...events);\n }\n\n async tracingComplete(): Promise {\n if (!this.tracingManager) {\n return;\n }\n this.tracingManager = null;\n await this.#traceEngine.parse(this.#collectedTraceEvents);\n\n const data = this.#traceEngine.traceParsedData(this.#traceEngine.size() - 1) as\n TraceEngine.Extras.FilmStrip.HandlerDataWithScreenshots;\n if (!data) {\n return;\n }\n const zeroTimeInSeconds = TraceEngine.Types.Timing.Seconds(this.timeCalculator.minimumBoundary());\n const filmStrip = TraceEngine.Extras.FilmStrip.fromTraceData(\n data, TraceEngine.Helpers.Timing.secondsToMicroseconds(zeroTimeInSeconds));\n\n if (this.callback) {\n this.callback(filmStrip);\n }\n this.callback = null;\n // Now we have created the film strip and stored the data, we need to reset\n // the trace processor so that it is ready to record again if the user\n // refreshes the page.\n this.#traceEngine.resetProcessor();\n\n if (this.resourceTreeModel) {\n this.resourceTreeModel.resumeReload();\n }\n this.resourceTreeModel = null;\n }\n\n tracingBufferUsage(): void {\n }\n\n eventsRetrievalProgress(_progress: number): void {\n }\n\n startRecording(): void {\n this.#collectedTraceEvents = [];\n this.filmStripView.reset();\n this.filmStripView.setStatusText(i18nString(UIStrings.recordingFrames));\n const tracingManager =\n SDK.TargetManager.TargetManager.instance().scopeTarget()?.model(TraceEngine.TracingManager.TracingManager);\n if (this.tracingManager || !tracingManager) {\n return;\n }\n\n this.tracingManager = tracingManager;\n this.resourceTreeModel = this.tracingManager.target().model(SDK.ResourceTreeModel.ResourceTreeModel);\n void this.tracingManager.start(this, '-*,disabled-by-default-devtools.screenshot', '');\n\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.FilmStripStartedRecording);\n }\n\n isRecording(): boolean {\n return Boolean(this.tracingManager);\n }\n\n stopRecording(callback: (filmStrip: TraceEngine.Extras.FilmStrip.Data) => void): void {\n if (!this.tracingManager) {\n return;\n }\n\n this.tracingManager.stop();\n if (this.resourceTreeModel) {\n this.resourceTreeModel.suspendReload();\n }\n this.callback = callback;\n this.filmStripView.setStatusText(i18nString(UIStrings.fetchingFrames));\n }\n}\n\nexport class ActionDelegate implements UI.ActionRegistration.ActionDelegate {\n handleAction(context: UI.Context.Context, actionId: string): boolean {\n const panel = context.flavor(NetworkPanel);\n if (panel === null) {\n return false;\n }\n switch (actionId) {\n case 'network.toggle-recording': {\n panel.toggleRecord(!panel.recordLogSetting.get());\n return true;\n }\n case 'network.hide-request-details': {\n if (!panel.networkItemView) {\n return false;\n }\n panel.hideRequestPanel();\n panel.networkLogView.resetFocus();\n return true;\n }\n case 'network.search': {\n const selection = UI.InspectorView.InspectorView.instance().element.window().getSelection();\n if (!selection) {\n return false;\n }\n let queryCandidate = '';\n if (selection.rangeCount) {\n queryCandidate = selection.toString().replace(/\\r?\\n.*/, '');\n }\n void SearchNetworkView.openSearch(queryCandidate);\n return true;\n }\n case 'network.clear': {\n Logs.NetworkLog.NetworkLog.instance().reset(true);\n return true;\n }\n }\n return false;\n }\n}\n\nexport class RequestLocationRevealer implements\n Common.Revealer.Revealer {\n async reveal(location: NetworkForward.UIRequestLocation.UIRequestLocation): Promise {\n const view =\n await NetworkPanel.instance().selectAndActivateRequest(location.request, location.tab, location.filterOptions);\n if (!view) {\n return;\n }\n if (location.searchMatch) {\n const {lineNumber, columnNumber, matchLength} = location.searchMatch;\n const revealPosition = {\n from: {lineNumber, columnNumber},\n to: {lineNumber, columnNumber: columnNumber + matchLength},\n };\n await view.revealResponseBody(revealPosition);\n }\n if (location.header) {\n view.revealHeader(location.header.section, location.header.header?.name);\n }\n }\n}\n\nlet searchNetworkViewInstance: SearchNetworkView;\n\nexport class SearchNetworkView extends Search.SearchView.SearchView {\n private constructor() {\n super('network', new Common.Throttler.Throttler(/* timeoutMs */ 200));\n }\n\n static instance(opts: {\n forceNew: boolean|null,\n } = {forceNew: null}): SearchNetworkView {\n const {forceNew} = opts;\n if (!searchNetworkViewInstance || forceNew) {\n searchNetworkViewInstance = new SearchNetworkView();\n }\n\n return searchNetworkViewInstance;\n }\n\n static async openSearch(query: string, searchImmediately?: boolean): Promise {\n await UI.ViewManager.ViewManager.instance().showView('network.search-network-tab');\n const searchView = SearchNetworkView.instance();\n searchView.toggle(query, Boolean(searchImmediately));\n return searchView;\n }\n\n override createScope(): Search.SearchScope.SearchScope {\n return new NetworkSearchScope(Logs.NetworkLog.NetworkLog.instance());\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"NetworkPanel.js","sourceRoot":"","sources":["../../../../../../front_end/panels/network/NetworkPanel.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2021 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/*\n * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.\n * Copyright (C) 2008, 2009 Anthony Ricaud \n * Copyright (C) 2011 Google Inc. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in the\n * documentation and/or other materials provided with the distribution.\n * 3. Neither the name of Apple Computer, Inc. (\"Apple\") nor the names of\n * its contributors may be used to endorse or promote products derived\n * from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS \"AS IS\" AND ANY\n * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY\n * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\n * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\n * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport * as Common from '../../core/common/common.js';\nimport * as Host from '../../core/host/host.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as Bindings from '../../models/bindings/bindings.js';\nimport type * as Extensions from '../../models/extensions/extensions.js';\nimport * as Logs from '../../models/logs/logs.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as Workspace from '../../models/workspace/workspace.js';\nimport * as NetworkForward from '../../panels/network/forward/forward.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\nimport * as MobileThrottling from '../mobile_throttling/mobile_throttling.js';\nimport * as Search from '../search/search.js';\nimport * as TimelineUtils from '../timeline/utils/utils.js';\n\nimport {Events, type RequestActivatedEvent} from './NetworkDataGridNode.js';\nimport {NetworkItemView} from './NetworkItemView.js';\nimport {NetworkLogView} from './NetworkLogView.js';\nimport {NetworkOverview} from './NetworkOverview.js';\nimport networkPanelStyles from './networkPanel.css.js';\nimport {NetworkSearchScope} from './NetworkSearchScope.js';\nimport {type NetworkTimeCalculator, NetworkTransferTimeCalculator} from './NetworkTimeCalculator.js';\n\nconst UIStrings = {\n /**\n *@description Text to close something\n */\n close: 'Close',\n /**\n *@description Title of a search bar or tool\n */\n search: 'Search',\n /**\n *@description Tooltip text that appears on the setting to preserve log when hovering over the item\n */\n doNotClearLogOnPageReload: 'Do not clear log on page reload / navigation',\n /**\n *@description Text to preserve the log after refreshing\n */\n preserveLog: 'Preserve log',\n /**\n *@description Text to disable cache while DevTools is open\n */\n disableCacheWhileDevtoolsIsOpen: 'Disable cache (while DevTools is open)',\n /**\n *@description Text in Network Config View of the Network panel\n */\n disableCache: 'Disable cache',\n /**\n *@description Tooltip text that appears when hovering over the largeicon settings gear in show settings pane setting in network panel of the network panel\n */\n networkSettings: 'Network settings',\n /**\n *@description Tooltip for expanding network request row setting\n */\n showMoreInformationInRequestRows: 'Show more information in request rows',\n /**\n *@description Text in Network Panel used to toggle the \"big request rows\" setting.\n */\n useLargeRequestRows: 'Big request rows',\n /**\n *@description Tooltip text for network request overview setting\n */\n showOverviewOfNetworkRequests: 'Show overview of network requests',\n /**\n *@description Text in Network Panel used to show the overview for a given network request.\n */\n showOverview: 'Overview',\n /**\n *@description Tooltip for group by frame network setting\n */\n groupRequestsByTopLevelRequest: 'Group requests by top level request frame',\n /**\n *@description Text for group by frame network setting\n */\n groupByFrame: 'Group by frame',\n /**\n *@description Tooltip for capture screenshot network setting\n */\n captureScreenshotsWhenLoadingA: 'Capture screenshots when loading a page',\n /**\n *@description Text to take screenshots\n */\n captureScreenshots: 'Screenshots',\n /**\n * @description Tooltip text that appears when hovering over the largeicon load button in the\n * Network Panel. This action prompts the user to select a HAR file to upload to DevTools.\n */\n importHarFile: 'Import `HAR` file...',\n /**\n * @description Tooltip text that appears when hovering over the largeicon download button in the\n * Network Panel. HAR is a file format (HTTP Archive) and should not be translated. This action\n * triggers the download of a HAR file.\n */\n exportHarSanitized: 'Export `HAR` (sanitized)...',\n /**\n * @description Context menu item in the export long click button of the Network panel, which is\n * only available when the Network setting to allow generating HAR with sensitive data is active.\n * HAR is a file format (HTTP Archive) and should not be translated. This action triggers the\n * download of a HAR file with sensitive data included.\n */\n exportHarWithSensitiveData: 'Export `HAR` (with sensitive data)...',\n /**\n *@description Text for throttling the network\n */\n throttling: 'Throttling',\n /**\n *@description Text in Network Panel to tell the user to reload the page to capture screenshots.\n *@example {Ctrl + R} PH1\n */\n hitSToReloadAndCaptureFilmstrip: 'Hit {PH1} to reload and capture filmstrip.',\n /**\n *@description A context menu item in the Network Panel of the Network panel\n */\n revealInNetworkPanel: 'Reveal in Network panel',\n /**\n *@description Text in Network Panel that is displayed whilst the recording is in progress.\n */\n recordingFrames: 'Recording frames...',\n /**\n *@description Text in Network Panel that is displayed when frames are being fetched.\n */\n fetchingFrames: 'Fetching frames...',\n /**\n * @description Text of a button in the Network panel's toolbar that open Network Conditions panel in the drawer.\n */\n moreNetworkConditions: 'More network conditions…',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/network/NetworkPanel.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nlet networkPanelInstance: NetworkPanel;\n\nexport class NetworkPanel extends UI.Panel.Panel implements\n UI.ContextMenu\n .Provider,\n UI.View.ViewLocationResolver {\n private readonly networkLogShowOverviewSetting: Common.Settings.Setting;\n private readonly networkLogLargeRowsSetting: Common.Settings.Setting;\n private readonly networkRecordFilmStripSetting: Common.Settings.Setting;\n private readonly toggleRecordAction: UI.ActionRegistration.Action;\n private pendingStopTimer!: number|undefined;\n networkItemView: NetworkItemView|null;\n private filmStripView: PerfUI.FilmStripView.FilmStripView|null;\n private filmStripRecorder: FilmStripRecorder|null;\n private currentRequest: SDK.NetworkRequest.NetworkRequest|null;\n private readonly panelToolbar: UI.Toolbar.Toolbar;\n private readonly rightToolbar: UI.Toolbar.Toolbar;\n private readonly filterBar: UI.FilterBar.FilterBar;\n private readonly settingsPane: UI.Widget.HBox;\n private showSettingsPaneSetting: Common.Settings.Setting;\n private readonly filmStripPlaceholderElement: HTMLElement;\n private readonly overviewPane: PerfUI.TimelineOverviewPane.TimelineOverviewPane;\n private readonly networkOverview: NetworkOverview;\n private readonly overviewPlaceholderElement: HTMLElement;\n private readonly calculator: NetworkTransferTimeCalculator;\n private splitWidget: UI.SplitWidget.SplitWidget;\n private readonly sidebarLocation: UI.View.TabbedViewLocation;\n private readonly progressBarContainer: HTMLDivElement;\n networkLogView: NetworkLogView;\n private readonly fileSelectorElement: HTMLElement;\n private readonly detailsWidget: UI.Widget.VBox;\n private readonly closeButtonElement: HTMLDivElement;\n private preserveLogSetting: Common.Settings.Setting;\n recordLogSetting: Common.Settings.Setting;\n private readonly throttlingSelect: UI.Toolbar.ToolbarComboBox;\n private readonly displayScreenshotDelay: number;\n\n constructor(displayScreenshotDelay: number) {\n super('network');\n\n this.displayScreenshotDelay = displayScreenshotDelay;\n this.networkLogShowOverviewSetting =\n Common.Settings.Settings.instance().createSetting('network-log-show-overview', true);\n this.networkLogLargeRowsSetting =\n Common.Settings.Settings.instance().createSetting('network-log-large-rows', false);\n this.networkRecordFilmStripSetting =\n Common.Settings.Settings.instance().createSetting('network-record-film-strip-setting', false);\n this.toggleRecordAction = UI.ActionRegistry.ActionRegistry.instance().getAction('network.toggle-recording');\n this.networkItemView = null;\n this.filmStripView = null;\n this.filmStripRecorder = null;\n this.currentRequest = null;\n\n const panel = new UI.Widget.VBox();\n\n const networkToolbarContainer = panel.contentElement.createChild('div', 'network-toolbar-container');\n this.panelToolbar = new UI.Toolbar.Toolbar('', networkToolbarContainer);\n this.panelToolbar.makeWrappable(true);\n this.panelToolbar.element.setAttribute('jslog', `${VisualLogging.toolbar('network-main')}`);\n this.rightToolbar = new UI.Toolbar.Toolbar('', networkToolbarContainer);\n\n this.filterBar = new UI.FilterBar.FilterBar('network-panel', true);\n this.filterBar.show(panel.contentElement);\n this.filterBar.addEventListener(UI.FilterBar.FilterBarEvents.CHANGED, this.handleFilterChanged.bind(this));\n\n this.settingsPane = new UI.Widget.HBox();\n this.settingsPane.element.classList.add('network-settings-pane');\n this.settingsPane.show(panel.contentElement);\n this.showSettingsPaneSetting =\n Common.Settings.Settings.instance().createSetting('network-show-settings-toolbar', false);\n this.showSettingsPaneSetting.addChangeListener(this.updateSettingsPaneVisibility.bind(this));\n this.updateSettingsPaneVisibility();\n\n this.filmStripPlaceholderElement = panel.contentElement.createChild('div', 'network-film-strip-placeholder');\n\n // Create top overview component.\n this.overviewPane = new PerfUI.TimelineOverviewPane.TimelineOverviewPane('network');\n this.overviewPane.addEventListener(\n PerfUI.TimelineOverviewPane.Events.OVERVIEW_PANE_WINDOW_CHANGED, this.onWindowChanged.bind(this));\n this.overviewPane.element.id = 'network-overview-panel';\n this.networkOverview = new NetworkOverview();\n this.overviewPane.setOverviewControls([this.networkOverview]);\n this.overviewPlaceholderElement = panel.contentElement.createChild('div');\n\n this.calculator = new NetworkTransferTimeCalculator();\n\n this.splitWidget = new UI.SplitWidget.SplitWidget(true, false, 'network-panel-split-view-state');\n this.splitWidget.hideMain();\n this.splitWidget.show(panel.contentElement);\n\n panel.setDefaultFocusedChild(this.filterBar);\n\n const initialSidebarWidth = 225;\n const splitWidget = new UI.SplitWidget.SplitWidget(true, false, 'network-panel-sidebar-state', initialSidebarWidth);\n splitWidget.hideSidebar();\n splitWidget.enableShowModeSaving();\n splitWidget.show(this.element);\n this.sidebarLocation = UI.ViewManager.ViewManager.instance().createTabbedLocation(async () => {\n void UI.ViewManager.ViewManager.instance().showView('network');\n splitWidget.showBoth();\n }, 'network-sidebar', true);\n const tabbedPane = this.sidebarLocation.tabbedPane();\n tabbedPane.setMinimumSize(100, 25);\n tabbedPane.element.classList.add('network-tabbed-pane');\n tabbedPane.element.addEventListener('keydown', event => {\n if (event.key !== Platform.KeyboardUtilities.ESCAPE_KEY) {\n return;\n }\n splitWidget.hideSidebar();\n event.consume();\n void VisualLogging.logKeyDown(event.currentTarget, event, 'hide-sidebar');\n });\n const closeSidebar = new UI.Toolbar.ToolbarButton(i18nString(UIStrings.close), 'cross');\n closeSidebar.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, () => splitWidget.hideSidebar());\n closeSidebar.element.setAttribute('jslog', `${VisualLogging.close().track({click: true})}`);\n tabbedPane.rightToolbar().appendToolbarItem(closeSidebar);\n splitWidget.setSidebarWidget(tabbedPane);\n splitWidget.setMainWidget(panel);\n splitWidget.setDefaultFocusedChild(panel);\n this.setDefaultFocusedChild(splitWidget);\n\n this.progressBarContainer = document.createElement('div');\n\n this.networkLogView =\n new NetworkLogView(this.filterBar, this.progressBarContainer, this.networkLogLargeRowsSetting);\n this.splitWidget.setSidebarWidget(this.networkLogView);\n this.fileSelectorElement =\n (UI.UIUtils.createFileSelectorElement(this.networkLogView.onLoadFromFile.bind(this.networkLogView)) as\n HTMLElement);\n panel.element.appendChild(this.fileSelectorElement);\n\n this.detailsWidget = new UI.Widget.VBox();\n this.detailsWidget.element.classList.add('network-details-view');\n this.splitWidget.setMainWidget(this.detailsWidget);\n\n this.closeButtonElement = document.createElement('div', {is: 'dt-close-button'});\n this.closeButtonElement.addEventListener('click', async () => {\n const action = UI.ActionRegistry.ActionRegistry.instance().getAction('network.hide-request-details');\n await action.execute();\n }, false);\n this.closeButtonElement.style.margin = '0 5px';\n\n this.networkLogShowOverviewSetting.addChangeListener(this.toggleShowOverview, this);\n this.networkLogLargeRowsSetting.addChangeListener(this.toggleLargerRequests, this);\n this.networkRecordFilmStripSetting.addChangeListener(this.toggleRecordFilmStrip, this);\n\n this.preserveLogSetting = Common.Settings.Settings.instance().moduleSetting('network-log.preserve-log');\n this.recordLogSetting = Common.Settings.Settings.instance().moduleSetting('network-log.record-log');\n this.recordLogSetting.addChangeListener(({data}) => this.toggleRecord(data));\n\n this.throttlingSelect = this.createThrottlingConditionsSelect();\n this.setupToolbarButtons(splitWidget);\n\n this.toggleRecord(this.recordLogSetting.get());\n this.toggleShowOverview();\n this.toggleLargerRequests();\n this.toggleRecordFilmStrip();\n this.updateUI();\n\n SDK.TargetManager.TargetManager.instance().addModelListener(\n SDK.ResourceTreeModel.ResourceTreeModel, SDK.ResourceTreeModel.Events.WillReloadPage, this.willReloadPage, this,\n {scoped: true});\n SDK.TargetManager.TargetManager.instance().addModelListener(\n SDK.ResourceTreeModel.ResourceTreeModel, SDK.ResourceTreeModel.Events.Load, this.load, this, {scoped: true});\n this.networkLogView.addEventListener(Events.RequestSelected, this.onRequestSelected, this);\n this.networkLogView.addEventListener(Events.RequestActivated, this.onRequestActivated, this);\n Logs.NetworkLog.NetworkLog.instance().addEventListener(\n Logs.NetworkLog.Events.RequestAdded, this.onUpdateRequest, this);\n Logs.NetworkLog.NetworkLog.instance().addEventListener(\n Logs.NetworkLog.Events.RequestUpdated, this.onUpdateRequest, this);\n Logs.NetworkLog.NetworkLog.instance().addEventListener(Logs.NetworkLog.Events.Reset, this.onNetworkLogReset, this);\n }\n\n static instance(opts?: {\n forceNew: boolean,\n displayScreenshotDelay?: number,\n }): NetworkPanel {\n if (!networkPanelInstance || opts?.forceNew) {\n networkPanelInstance = new NetworkPanel(opts?.displayScreenshotDelay ?? 1000);\n }\n\n return networkPanelInstance;\n }\n\n static revealAndFilter(filters: {\n filterType: NetworkForward.UIFilter.FilterType|null,\n filterValue: string,\n }[]): Promise {\n const panel = NetworkPanel.instance();\n let filterString = '';\n for (const filter of filters) {\n if (filter.filterType) {\n filterString += `${filter.filterType}:${filter.filterValue} `;\n } else {\n filterString += `${filter.filterValue} `;\n }\n }\n panel.networkLogView.setTextFilterValue(filterString);\n return UI.ViewManager.ViewManager.instance().showView('network');\n }\n\n static async selectAndShowRequest(\n request: SDK.NetworkRequest.NetworkRequest, tab: NetworkForward.UIRequestLocation.UIRequestTabs,\n options?: NetworkForward.UIRequestLocation.FilterOptions): Promise {\n const panel = NetworkPanel.instance();\n await panel.selectAndActivateRequest(request, tab, options);\n }\n\n throttlingSelectForTest(): UI.Toolbar.ToolbarComboBox {\n return this.throttlingSelect;\n }\n\n private onWindowChanged(\n event: Common.EventTarget.EventTargetEvent): void {\n const startTime = Math.max(this.calculator.minimumBoundary(), event.data.startTime / 1000);\n const endTime = Math.min(this.calculator.maximumBoundary(), event.data.endTime / 1000);\n if (startTime === this.calculator.minimumBoundary() && endTime === this.calculator.maximumBoundary()) {\n // Reset the filters for NetworkLogView when the window is reset\n // to its boundaries. This clears the filters and allows the users\n // to see the incoming requests after they have updated the curtains\n // to be in the edges. (ex: by double clicking on the overview grid)\n this.networkLogView.setWindow(0, 0);\n } else {\n this.networkLogView.setWindow(startTime, endTime);\n }\n }\n\n private async searchToggleClick(): Promise {\n const action = UI.ActionRegistry.ActionRegistry.instance().getAction('network.search');\n await action.execute();\n }\n\n private setupToolbarButtons(splitWidget: UI.SplitWidget.SplitWidget): void {\n const searchToggle = new UI.Toolbar.ToolbarToggle(i18nString(UIStrings.search), 'search', undefined, 'search');\n function updateSidebarToggle(): void {\n const isSidebarShowing = splitWidget.showMode() !== UI.SplitWidget.ShowMode.ONLY_MAIN;\n searchToggle.setToggled(isSidebarShowing);\n if (!isSidebarShowing) {\n (searchToggle.element as HTMLElement).focus();\n }\n }\n this.panelToolbar.appendToolbarItem(UI.Toolbar.Toolbar.createActionButton(this.toggleRecordAction));\n this.panelToolbar.appendToolbarItem(UI.Toolbar.Toolbar.createActionButtonForId('network.clear'));\n this.panelToolbar.appendSeparator();\n\n this.panelToolbar.appendToolbarItem(this.filterBar.filterButton());\n updateSidebarToggle();\n splitWidget.addEventListener(UI.SplitWidget.Events.SHOW_MODE_CHANGED, updateSidebarToggle);\n searchToggle.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, () => {\n void this.searchToggleClick();\n });\n this.panelToolbar.appendToolbarItem(searchToggle);\n this.panelToolbar.appendSeparator();\n\n this.panelToolbar.appendToolbarItem(new UI.Toolbar.ToolbarSettingCheckbox(\n this.preserveLogSetting, i18nString(UIStrings.doNotClearLogOnPageReload), i18nString(UIStrings.preserveLog)));\n\n this.panelToolbar.appendSeparator();\n const disableCacheCheckbox = new UI.Toolbar.ToolbarSettingCheckbox(\n Common.Settings.Settings.instance().moduleSetting('cache-disabled'),\n i18nString(UIStrings.disableCacheWhileDevtoolsIsOpen), i18nString(UIStrings.disableCache));\n this.panelToolbar.appendToolbarItem(disableCacheCheckbox);\n\n this.panelToolbar.appendToolbarItem(this.throttlingSelect);\n\n const networkConditionsButton = new UI.Toolbar.ToolbarButton(\n i18nString(UIStrings.moreNetworkConditions), 'network-settings', undefined, 'network-conditions');\n networkConditionsButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, () => {\n void UI.ViewManager.ViewManager.instance().showView('network.config');\n }, this);\n this.panelToolbar.appendToolbarItem(networkConditionsButton);\n\n this.rightToolbar.appendToolbarItem(new UI.Toolbar.ToolbarItem(this.progressBarContainer));\n this.rightToolbar.appendSeparator();\n this.rightToolbar.appendToolbarItem(new UI.Toolbar.ToolbarSettingToggle(\n this.showSettingsPaneSetting, 'gear', i18nString(UIStrings.networkSettings), 'gear-filled',\n 'network-settings'));\n\n const settingsToolbarLeft = new UI.Toolbar.Toolbar('', this.settingsPane.element);\n settingsToolbarLeft.makeVertical();\n settingsToolbarLeft.appendToolbarItem(new UI.Toolbar.ToolbarSettingCheckbox(\n this.networkLogLargeRowsSetting, i18nString(UIStrings.showMoreInformationInRequestRows),\n i18nString(UIStrings.useLargeRequestRows)));\n settingsToolbarLeft.appendToolbarItem(new UI.Toolbar.ToolbarSettingCheckbox(\n this.networkLogShowOverviewSetting, i18nString(UIStrings.showOverviewOfNetworkRequests),\n i18nString(UIStrings.showOverview)));\n\n const settingsToolbarRight = new UI.Toolbar.Toolbar('', this.settingsPane.element);\n settingsToolbarRight.makeVertical();\n settingsToolbarRight.appendToolbarItem(new UI.Toolbar.ToolbarSettingCheckbox(\n Common.Settings.Settings.instance().moduleSetting('network.group-by-frame'),\n i18nString(UIStrings.groupRequestsByTopLevelRequest), i18nString(UIStrings.groupByFrame)));\n settingsToolbarRight.appendToolbarItem(new UI.Toolbar.ToolbarSettingCheckbox(\n this.networkRecordFilmStripSetting, i18nString(UIStrings.captureScreenshotsWhenLoadingA),\n i18nString(UIStrings.captureScreenshots)));\n\n this.panelToolbar.appendSeparator();\n const importHarButton =\n new UI.Toolbar.ToolbarButton(i18nString(UIStrings.importHarFile), 'import', undefined, 'import-har');\n importHarButton.addEventListener(\n UI.Toolbar.ToolbarButton.Events.CLICK, () => this.fileSelectorElement.click(), this);\n this.panelToolbar.appendToolbarItem(importHarButton);\n const exportHarButton =\n new UI.Toolbar.ToolbarButton(i18nString(UIStrings.exportHarSanitized), 'download', undefined, 'export-har');\n exportHarButton.addEventListener(\n UI.Toolbar.ToolbarButton.Events.CLICK,\n this.networkLogView.exportAll.bind(this.networkItemView, {sanitize: true}), this);\n this.panelToolbar.appendToolbarItem(exportHarButton);\n\n // Support for exporting HAR (with sensitive data), which is added via a long-click\n // context menu on the Export button in the Network panel.\n // Checkout https://goo.gle/devtools-har-exclude-cookies-design for more details.\n const networkShowOptionsToGenerateHarWithSensitiveData = Common.Settings.Settings.instance().createSetting(\n 'network.show-options-to-generate-har-with-sensitive-data', false);\n let controller: UI.UIUtils.LongClickController|null = null;\n const updateShowOptionsToGenerateHarWithSensitiveData = (): void => {\n exportHarButton.setLongClickable(networkShowOptionsToGenerateHarWithSensitiveData.get());\n if (controller !== null) {\n controller.dispose();\n controller = null;\n }\n if (networkShowOptionsToGenerateHarWithSensitiveData.get()) {\n controller = new UI.UIUtils.LongClickController(exportHarButton.element, event => {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.exportHarSanitized),\n this.networkLogView.exportAll.bind(this.networkItemView, {sanitize: true}),\n {jslogContext: 'export-har'},\n );\n contextMenu.defaultSection().appendItem(\n i18nString(UIStrings.exportHarWithSensitiveData),\n this.networkLogView.exportAll.bind(this.networkItemView, {sanitize: false}),\n {jslogContext: 'export-har-with-sensitive-data'},\n );\n void contextMenu.show();\n });\n }\n };\n networkShowOptionsToGenerateHarWithSensitiveData.addChangeListener(updateShowOptionsToGenerateHarWithSensitiveData);\n updateShowOptionsToGenerateHarWithSensitiveData();\n }\n\n private updateSettingsPaneVisibility(): void {\n this.settingsPane.element.classList.toggle('hidden', !this.showSettingsPaneSetting.get());\n }\n\n private createThrottlingConditionsSelect(): UI.Toolbar.ToolbarComboBox {\n const toolbarItem = new UI.Toolbar.ToolbarComboBox(null, i18nString(UIStrings.throttling));\n toolbarItem.setMaxWidth(160);\n MobileThrottling.ThrottlingManager.throttlingManager().decorateSelectWithNetworkThrottling(\n toolbarItem.selectElement());\n return toolbarItem;\n }\n\n toggleRecord(toggled: boolean): void {\n this.toggleRecordAction.setToggled(toggled);\n if (this.recordLogSetting.get() !== toggled) {\n this.recordLogSetting.set(toggled);\n }\n\n this.networkLogView.setRecording(toggled);\n if (!toggled && this.filmStripRecorder) {\n this.filmStripRecorder.stopRecording(this.filmStripAvailable.bind(this));\n }\n }\n\n private filmStripAvailable(filmStrip: Trace.Extras.FilmStrip.Data): void {\n if (this.filmStripView) {\n this.filmStripView.setModel(filmStrip);\n }\n const timestamps = filmStrip.frames.map(frame => {\n // The network view works in seconds.\n return Trace.Helpers.Timing.microSecondsToSeconds(frame.screenshotEvent.ts);\n });\n\n this.networkLogView.addFilmStripFrames(timestamps);\n }\n\n private onNetworkLogReset(event: Common.EventTarget.EventTargetEvent): void {\n const {clearIfPreserved} = event.data;\n if (!this.preserveLogSetting.get() || clearIfPreserved) {\n this.calculator.reset();\n this.overviewPane.reset();\n }\n if (this.filmStripView) {\n this.resetFilmStripView();\n }\n }\n\n private willReloadPage(): void {\n if (this.pendingStopTimer) {\n clearTimeout(this.pendingStopTimer);\n delete this.pendingStopTimer;\n }\n if (this.isShowing() && this.filmStripRecorder) {\n this.filmStripRecorder.startRecording();\n }\n }\n\n private load(): void {\n if (this.filmStripRecorder && this.filmStripRecorder.isRecording()) {\n if (this.pendingStopTimer) {\n window.clearTimeout(this.pendingStopTimer);\n }\n this.pendingStopTimer = window.setTimeout(this.stopFilmStripRecording.bind(this), this.displayScreenshotDelay);\n }\n }\n\n private stopFilmStripRecording(): void {\n if (this.filmStripRecorder) {\n this.filmStripRecorder.stopRecording(this.filmStripAvailable.bind(this));\n }\n delete this.pendingStopTimer;\n }\n\n private toggleLargerRequests(): void {\n this.updateUI();\n }\n\n private toggleShowOverview(): void {\n const toggled = this.networkLogShowOverviewSetting.get();\n if (toggled) {\n this.overviewPane.show(this.overviewPlaceholderElement);\n } else {\n this.overviewPane.detach();\n }\n this.doResize();\n }\n\n private toggleRecordFilmStrip(): void {\n const toggled = this.networkRecordFilmStripSetting.get();\n if (toggled && !this.filmStripRecorder) {\n this.filmStripView = new PerfUI.FilmStripView.FilmStripView();\n this.filmStripView.element.classList.add('network-film-strip');\n this.filmStripView.element.setAttribute('jslog', `${VisualLogging.section('film-strip')}`);\n this.filmStripRecorder = new FilmStripRecorder(this.networkLogView.timeCalculator(), this.filmStripView);\n this.filmStripView.show(this.filmStripPlaceholderElement);\n this.filmStripView.addEventListener(PerfUI.FilmStripView.Events.FRAME_SELECTED, this.onFilmFrameSelected, this);\n this.filmStripView.addEventListener(PerfUI.FilmStripView.Events.FRAME_ENTER, this.onFilmFrameEnter, this);\n this.filmStripView.addEventListener(PerfUI.FilmStripView.Events.FRAME_EXIT, this.onFilmFrameExit, this);\n this.resetFilmStripView();\n }\n\n if (!toggled && this.filmStripRecorder) {\n if (this.filmStripView) {\n this.filmStripView.detach();\n }\n this.filmStripView = null;\n this.filmStripRecorder = null;\n }\n }\n\n private resetFilmStripView(): void {\n const reloadShortcut =\n UI.ShortcutRegistry.ShortcutRegistry.instance().shortcutsForAction('inspector-main.reload')[0];\n\n if (this.filmStripView) {\n this.filmStripView.reset();\n if (reloadShortcut) {\n this.filmStripView.setStatusText(\n i18nString(UIStrings.hitSToReloadAndCaptureFilmstrip, {PH1: reloadShortcut.title()}));\n }\n }\n }\n\n override elementsToRestoreScrollPositionsFor(): Element[] {\n return this.networkLogView.elementsToRestoreScrollPositionsFor();\n }\n\n override wasShown(): void {\n UI.Context.Context.instance().setFlavor(NetworkPanel, this);\n this.registerCSSFiles([networkPanelStyles]);\n\n // Record the network tool load time after the panel has loaded.\n Host.userMetrics.panelLoaded('network', 'DevTools.Launch.Network');\n }\n\n override willHide(): void {\n UI.Context.Context.instance().setFlavor(NetworkPanel, null);\n }\n\n revealAndHighlightRequest(request: SDK.NetworkRequest.NetworkRequest): void {\n this.hideRequestPanel();\n if (request) {\n this.networkLogView.revealAndHighlightRequest(request);\n }\n }\n\n revealAndHighlightRequestWithId(request: NetworkForward.NetworkRequestId.NetworkRequestId): void {\n this.hideRequestPanel();\n if (request) {\n this.networkLogView.revealAndHighlightRequestWithId(request);\n }\n }\n\n async selectAndActivateRequest(\n request: SDK.NetworkRequest.NetworkRequest, shownTab?: NetworkForward.UIRequestLocation.UIRequestTabs,\n options?: NetworkForward.UIRequestLocation.FilterOptions): Promise {\n await UI.ViewManager.ViewManager.instance().showView('network');\n this.networkLogView.selectRequest(request, options);\n this.showRequestPanel(shownTab);\n this.networkLogView.revealAndHighlightRequest(request);\n return this.networkItemView;\n }\n\n private handleFilterChanged(): void {\n this.hideRequestPanel();\n }\n\n private onRowSizeChanged(): void {\n this.updateUI();\n }\n private onRequestSelected(event: Common.EventTarget.EventTargetEvent): void {\n const request = event.data;\n this.currentRequest = request;\n this.networkOverview.setHighlightedRequest(request);\n this.updateNetworkItemView();\n UI.Context.Context.instance().setFlavor(SDK.NetworkRequest.NetworkRequest, request);\n }\n\n private onRequestActivated(event: Common.EventTarget.EventTargetEvent): void {\n const {showPanel, tab, takeFocus} = event.data;\n if (showPanel) {\n this.showRequestPanel(tab, takeFocus);\n } else {\n this.hideRequestPanel();\n }\n }\n\n private showRequestPanel(shownTab?: NetworkForward.UIRequestLocation.UIRequestTabs, takeFocus?: boolean): void {\n if (this.splitWidget.showMode() === UI.SplitWidget.ShowMode.BOTH && !shownTab && !takeFocus) {\n // If panel is already shown, and we are not forcing a specific tab, return.\n return;\n }\n this.clearNetworkItemView();\n if (this.currentRequest) {\n const networkItemView = this.createNetworkItemView(shownTab);\n if (networkItemView && takeFocus) {\n networkItemView.focus();\n }\n }\n this.updateUI();\n }\n\n hideRequestPanel(): void {\n this.clearNetworkItemView();\n this.splitWidget.hideMain();\n this.updateUI();\n }\n\n private updateNetworkItemView(): void {\n if (this.splitWidget.showMode() === UI.SplitWidget.ShowMode.BOTH) {\n this.clearNetworkItemView();\n this.createNetworkItemView();\n this.updateUI();\n }\n }\n\n private clearNetworkItemView(): void {\n if (this.networkItemView) {\n this.networkItemView.detach();\n this.networkItemView = null;\n }\n }\n private createNetworkItemView(initialTab?: NetworkForward.UIRequestLocation.UIRequestTabs): NetworkItemView\n |undefined {\n if (!this.currentRequest) {\n return;\n }\n this.networkItemView = new NetworkItemView(this.currentRequest, this.networkLogView.timeCalculator(), initialTab);\n this.networkItemView.leftToolbar().appendToolbarItem(new UI.Toolbar.ToolbarItem(this.closeButtonElement));\n this.networkItemView.show(this.detailsWidget.element);\n this.splitWidget.showBoth();\n return this.networkItemView;\n }\n\n private updateUI(): void {\n if (this.detailsWidget) {\n this.detailsWidget.element.classList.toggle(\n 'network-details-view-tall-header', this.networkLogLargeRowsSetting.get());\n }\n if (this.networkLogView) {\n this.networkLogView.switchViewMode(!this.splitWidget.isResizable());\n }\n }\n\n appendApplicableItems(\n this: NetworkPanel, event: Event, contextMenu: UI.ContextMenu.ContextMenu,\n target: SDK.NetworkRequest.NetworkRequest|SDK.Resource.Resource|Workspace.UISourceCode.UISourceCode|\n TimelineUtils.NetworkRequest.TimelineNetworkRequest): void {\n const appendRevealItem = (request: SDK.NetworkRequest.NetworkRequest): void => {\n contextMenu.revealSection().appendItem(\n i18nString(UIStrings.revealInNetworkPanel),\n () => UI.ViewManager.ViewManager.instance()\n .showView('network')\n .then(this.networkLogView.resetFilter.bind(this.networkLogView))\n .then(this.revealAndHighlightRequest.bind(this, request)),\n {jslogContext: 'reveal-in-network'});\n };\n const appendRevealItemAndSelect = (request: TimelineUtils.NetworkRequest.TimelineNetworkRequest): void => {\n contextMenu.revealSection().appendItem(\n i18nString(UIStrings.revealInNetworkPanel),\n () => UI.ViewManager.ViewManager.instance()\n .showView('network')\n .then(this.networkLogView.resetFilter.bind(this.networkLogView))\n .then(this.selectAndActivateRequest.bind(\n this, request.request, NetworkForward.UIRequestLocation.UIRequestTabs.HEADERS_COMPONENT,\n /* FilterOptions= */ undefined)),\n {jslogContext: 'timeline.reveal-in-network'});\n };\n\n if ((event.target as Node).isSelfOrDescendant(this.element)) {\n return;\n }\n\n if (target instanceof SDK.Resource.Resource) {\n if (target.request) {\n appendRevealItem(target.request);\n }\n return;\n }\n if (target instanceof Workspace.UISourceCode.UISourceCode) {\n const resource = Bindings.ResourceUtils.resourceForURL(target.url());\n if (resource && resource.request) {\n appendRevealItem(resource.request);\n }\n return;\n }\n if (target instanceof TimelineUtils.NetworkRequest.TimelineNetworkRequest) {\n appendRevealItemAndSelect(target);\n return;\n }\n\n if (this.networkItemView && this.networkItemView.isShowing() && this.networkItemView.request() === target) {\n return;\n }\n\n appendRevealItem(target);\n }\n\n private onFilmFrameSelected(event: Common.EventTarget.EventTargetEvent): void {\n const timestamp = event.data;\n this.overviewPane.setWindowTimes(0, timestamp);\n }\n\n private onFilmFrameEnter(event: Common.EventTarget.EventTargetEvent): void {\n const timestamp = event.data;\n this.networkOverview.selectFilmStripFrame(timestamp);\n this.networkLogView.selectFilmStripFrame(timestamp / 1000);\n }\n\n private onFilmFrameExit(): void {\n this.networkOverview.clearFilmStripFrame();\n this.networkLogView.clearFilmStripFrame();\n }\n\n private onUpdateRequest(event: Common.EventTarget.EventTargetEvent<{request: SDK.NetworkRequest.NetworkRequest}>):\n void {\n const {request} = event.data;\n this.calculator.updateBoundaries(request);\n // FIXME: Unify all time units across the frontend!\n this.overviewPane.setBounds(\n Trace.Types.Timing.MilliSeconds(this.calculator.minimumBoundary() * 1000),\n Trace.Types.Timing.MilliSeconds(this.calculator.maximumBoundary() * 1000));\n this.networkOverview.updateRequest(request);\n }\n\n resolveLocation(locationName: string): UI.View.ViewLocation|null {\n if (locationName === 'network-sidebar') {\n return this.sidebarLocation;\n }\n return null;\n }\n}\n\nexport class RequestRevealer implements Common.Revealer.Revealer {\n reveal(request: SDK.NetworkRequest.NetworkRequest): Promise {\n const panel = NetworkPanel.instance();\n return UI.ViewManager.ViewManager.instance().showView('network').then(\n panel.revealAndHighlightRequest.bind(panel, request));\n }\n}\n\nexport class RequestIdRevealer implements Common.Revealer.Revealer {\n reveal(requestId: NetworkForward.NetworkRequestId.NetworkRequestId): Promise {\n const panel = NetworkPanel.instance();\n return UI.ViewManager.ViewManager.instance().showView('network').then(\n panel.revealAndHighlightRequestWithId.bind(panel, requestId));\n }\n}\n\nexport class NetworkLogWithFilterRevealer implements\n Common.Revealer\n .Revealer {\n reveal(request: Extensions.ExtensionServer.RevealableNetworkRequestFilter|\n NetworkForward.UIFilter.UIRequestFilter): Promise {\n if ('filters' in request) {\n return NetworkPanel.revealAndFilter(request.filters);\n }\n return NetworkPanel.revealAndFilter(request.filter ? [{filterType: null, filterValue: request.filter}] : []);\n }\n}\n\nexport class FilmStripRecorder implements Trace.TracingManager.TracingManagerClient {\n private tracingManager: Trace.TracingManager.TracingManager|null;\n private resourceTreeModel: SDK.ResourceTreeModel.ResourceTreeModel|null;\n private readonly timeCalculator: NetworkTimeCalculator;\n private readonly filmStripView: PerfUI.FilmStripView.FilmStripView;\n private callback: ((filmStrip: Trace.Extras.FilmStrip.Data) => void)|null;\n // Used to fetch screenshots of the page load and show them in the panel.\n #traceEngine: Trace.TraceModel.Model;\n #collectedTraceEvents: Trace.Types.Events.Event[] = [];\n\n constructor(timeCalculator: NetworkTimeCalculator, filmStripView: PerfUI.FilmStripView.FilmStripView) {\n this.#traceEngine = Trace.TraceModel.Model.createWithSubsetOfHandlers({\n Screenshots: Trace.Handlers.ModelHandlers.Screenshots,\n });\n\n this.tracingManager = null;\n this.resourceTreeModel = null;\n this.timeCalculator = timeCalculator;\n this.filmStripView = filmStripView;\n this.callback = null;\n }\n\n traceEventsCollected(events: Trace.Types.Events.Event[]): void {\n this.#collectedTraceEvents.push(...events);\n }\n\n async tracingComplete(): Promise {\n if (!this.tracingManager) {\n return;\n }\n this.tracingManager = null;\n await this.#traceEngine.parse(this.#collectedTraceEvents);\n\n const data = this.#traceEngine.parsedTrace(this.#traceEngine.size() - 1) as\n Trace.Extras.FilmStrip.HandlerDataWithScreenshots;\n if (!data) {\n return;\n }\n const zeroTimeInSeconds = Trace.Types.Timing.Seconds(this.timeCalculator.minimumBoundary());\n const filmStrip =\n Trace.Extras.FilmStrip.fromParsedTrace(data, Trace.Helpers.Timing.secondsToMicroseconds(zeroTimeInSeconds));\n\n if (this.callback) {\n this.callback(filmStrip);\n }\n this.callback = null;\n // Now we have created the film strip and stored the data, we need to reset\n // the trace processor so that it is ready to record again if the user\n // refreshes the page.\n this.#traceEngine.resetProcessor();\n\n if (this.resourceTreeModel) {\n this.resourceTreeModel.resumeReload();\n }\n this.resourceTreeModel = null;\n }\n\n tracingBufferUsage(): void {\n }\n\n eventsRetrievalProgress(_progress: number): void {\n }\n\n startRecording(): void {\n this.#collectedTraceEvents = [];\n this.filmStripView.reset();\n this.filmStripView.setStatusText(i18nString(UIStrings.recordingFrames));\n const tracingManager =\n SDK.TargetManager.TargetManager.instance().scopeTarget()?.model(Trace.TracingManager.TracingManager);\n if (this.tracingManager || !tracingManager) {\n return;\n }\n\n this.tracingManager = tracingManager;\n this.resourceTreeModel = this.tracingManager.target().model(SDK.ResourceTreeModel.ResourceTreeModel);\n void this.tracingManager.start(this, '-*,disabled-by-default-devtools.screenshot', '');\n\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.FilmStripStartedRecording);\n }\n\n isRecording(): boolean {\n return Boolean(this.tracingManager);\n }\n\n stopRecording(callback: (filmStrip: Trace.Extras.FilmStrip.Data) => void): void {\n if (!this.tracingManager) {\n return;\n }\n\n this.tracingManager.stop();\n if (this.resourceTreeModel) {\n this.resourceTreeModel.suspendReload();\n }\n this.callback = callback;\n this.filmStripView.setStatusText(i18nString(UIStrings.fetchingFrames));\n }\n}\n\nexport class ActionDelegate implements UI.ActionRegistration.ActionDelegate {\n handleAction(context: UI.Context.Context, actionId: string): boolean {\n const panel = context.flavor(NetworkPanel);\n if (panel === null) {\n return false;\n }\n switch (actionId) {\n case 'network.toggle-recording': {\n panel.toggleRecord(!panel.recordLogSetting.get());\n return true;\n }\n case 'network.hide-request-details': {\n if (!panel.networkItemView) {\n return false;\n }\n panel.hideRequestPanel();\n panel.networkLogView.resetFocus();\n return true;\n }\n case 'network.search': {\n const selection = UI.InspectorView.InspectorView.instance().element.window().getSelection();\n if (!selection) {\n return false;\n }\n let queryCandidate = '';\n if (selection.rangeCount) {\n queryCandidate = selection.toString().replace(/\\r?\\n.*/, '');\n }\n void SearchNetworkView.openSearch(queryCandidate);\n return true;\n }\n case 'network.clear': {\n Logs.NetworkLog.NetworkLog.instance().reset(true);\n return true;\n }\n }\n return false;\n }\n}\n\nexport class RequestLocationRevealer implements\n Common.Revealer.Revealer {\n async reveal(location: NetworkForward.UIRequestLocation.UIRequestLocation): Promise {\n const view =\n await NetworkPanel.instance().selectAndActivateRequest(location.request, location.tab, location.filterOptions);\n if (!view) {\n return;\n }\n if (location.searchMatch) {\n const {lineNumber, columnNumber, matchLength} = location.searchMatch;\n const revealPosition = {\n from: {lineNumber, columnNumber},\n to: {lineNumber, columnNumber: columnNumber + matchLength},\n };\n await view.revealResponseBody(revealPosition);\n }\n if (location.header) {\n view.revealHeader(location.header.section, location.header.header?.name);\n }\n }\n}\n\nlet searchNetworkViewInstance: SearchNetworkView;\n\nexport class SearchNetworkView extends Search.SearchView.SearchView {\n private constructor() {\n super('network', new Common.Throttler.Throttler(/* timeoutMs */ 200));\n }\n\n static instance(opts: {\n forceNew: boolean|null,\n } = {forceNew: null}): SearchNetworkView {\n const {forceNew} = opts;\n if (!searchNetworkViewInstance || forceNew) {\n searchNetworkViewInstance = new SearchNetworkView();\n }\n\n return searchNetworkViewInstance;\n }\n\n static async openSearch(query: string, searchImmediately?: boolean): Promise {\n await UI.ViewManager.ViewManager.instance().showView('network.search-network-tab');\n const searchView = SearchNetworkView.instance();\n searchView.toggle(query, Boolean(searchImmediately));\n return searchView;\n }\n\n override createScope(): Search.SearchScope.SearchScope {\n return new NetworkSearchScope(Logs.NetworkLog.NetworkLog.instance());\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/network/NetworkPanel.test.js b/public/panels/network/NetworkPanel.test.js index aa1e32c3d..42bc54396 100644 --- a/public/panels/network/NetworkPanel.test.js +++ b/public/panels/network/NetworkPanel.test.js @@ -4,7 +4,7 @@ import * as Common from '../../core/common/common.js'; import * as SDK from '../../core/sdk/sdk.js'; import * as Logs from '../../models/logs/logs.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import { createTarget, registerNoopActions } from '../../testing/EnvironmentHelpers.js'; import { describeWithMockConnection } from '../../testing/MockConnection.js'; import * as Coordinator from '../../ui/components/render_coordinator/render_coordinator.js'; @@ -46,7 +46,7 @@ describeWithMockConnection('NetworkPanel', () => { Common.Settings.Settings.instance().moduleSetting('network-record-film-strip-setting').set(true); const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel); assert.exists(resourceTreeModel); - const tracingManager = target.model(TraceEngine.TracingManager.TracingManager); + const tracingManager = target.model(Trace.TracingManager.TracingManager); assert.exists(tracingManager); const tracingStart = sinon.spy(tracingManager, 'start'); resourceTreeModel.dispatchEventToListeners(SDK.ResourceTreeModel.Events.WillReloadPage); @@ -57,7 +57,7 @@ describeWithMockConnection('NetworkPanel', () => { Common.Settings.Settings.instance().moduleSetting('network-record-film-strip-setting').set(true); const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel); assert.exists(resourceTreeModel); - const tracingManager = target.model(TraceEngine.TracingManager.TracingManager); + const tracingManager = target.model(Trace.TracingManager.TracingManager); assert.exists(tracingManager); resourceTreeModel.dispatchEventToListeners(SDK.ResourceTreeModel.Events.WillReloadPage); SDK.TargetManager.TargetManager.instance().setScopeTarget(inScope ? target : null); diff --git a/public/panels/network/NetworkPanel.test.js.map b/public/panels/network/NetworkPanel.test.js.map index 0e375249b..9cadf3659 100644 --- a/public/panels/network/NetworkPanel.test.js.map +++ b/public/panels/network/NetworkPanel.test.js.map @@ -1 +1 @@ -{"version":3,"file":"NetworkPanel.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/network/NetworkPanel.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as Logs from '../../models/logs/logs.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport {createTarget, registerNoopActions} from '../../testing/EnvironmentHelpers.js';\nimport {describeWithMockConnection} from '../../testing/MockConnection.js';\nimport * as Coordinator from '../../ui/components/render_coordinator/render_coordinator.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport * as Network from './network.js';\n\nconst coordinator = Coordinator.RenderCoordinator.RenderCoordinator.instance();\n\ndescribeWithMockConnection('NetworkPanel', () => {\n let target: SDK.Target.Target;\n let networkPanel: Network.NetworkPanel.NetworkPanel;\n\n beforeEach(async () => {\n registerNoopActions(['network.toggle-recording', 'network.clear']);\n\n target = createTarget();\n const dummyStorage = new Common.Settings.SettingsStorage({});\n for (const settingName\n of ['network-color-code-resource-types', 'network.group-by-frame', 'network-record-film-strip-setting']) {\n Common.Settings.registerSettingExtension({\n settingName,\n settingType: Common.Settings.SettingType.BOOLEAN,\n defaultValue: false,\n });\n }\n Common.Settings.Settings.instance({\n forceNew: true,\n syncedStorage: dummyStorage,\n globalStorage: dummyStorage,\n localStorage: dummyStorage,\n });\n networkPanel = Network.NetworkPanel.NetworkPanel.instance({forceNew: true, displayScreenshotDelay: 0});\n networkPanel.markAsRoot();\n networkPanel.show(document.body);\n await coordinator.done();\n });\n\n afterEach(async () => {\n await coordinator.done();\n networkPanel.detach();\n });\n\n const tracingTests = (inScope: boolean) => () => {\n it('starts recording on page reload', async () => {\n SDK.TargetManager.TargetManager.instance().setScopeTarget(inScope ? target : null);\n Common.Settings.Settings.instance().moduleSetting('network-record-film-strip-setting').set(true);\n const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel);\n assert.exists(resourceTreeModel);\n const tracingManager = target.model(TraceEngine.TracingManager.TracingManager);\n assert.exists(tracingManager);\n const tracingStart = sinon.spy(tracingManager, 'start');\n resourceTreeModel.dispatchEventToListeners(SDK.ResourceTreeModel.Events.WillReloadPage);\n assert.strictEqual(tracingStart.called, inScope);\n });\n\n it('stops recording on page load', async () => {\n SDK.TargetManager.TargetManager.instance().setScopeTarget(target);\n Common.Settings.Settings.instance().moduleSetting('network-record-film-strip-setting').set(true);\n const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel);\n assert.exists(resourceTreeModel);\n const tracingManager = target.model(TraceEngine.TracingManager.TracingManager);\n assert.exists(tracingManager);\n resourceTreeModel.dispatchEventToListeners(SDK.ResourceTreeModel.Events.WillReloadPage);\n SDK.TargetManager.TargetManager.instance().setScopeTarget(inScope ? target : null);\n\n const tracingStop = sinon.spy(tracingManager, 'stop');\n resourceTreeModel.dispatchEventToListeners(SDK.ResourceTreeModel.Events.Load, {resourceTreeModel, loadTime: 42});\n await new Promise(resolve => setTimeout(resolve, 0));\n assert.strictEqual(tracingStop.called, inScope);\n });\n };\n\n describe('in scope', tracingTests(true));\n describe('out of scpe', tracingTests(false));\n});\n\ndescribeWithMockConnection('NetworkPanel', () => {\n let networkPanel: Network.NetworkPanel.NetworkPanel;\n\n beforeEach(async () => {\n UI.ActionRegistration.maybeRemoveActionExtension('network.toggle-recording');\n UI.ActionRegistration.maybeRemoveActionExtension('network.clear');\n await import('./network-meta.js');\n createTarget();\n const dummyStorage = new Common.Settings.SettingsStorage({});\n Common.Settings.Settings.instance({\n forceNew: true,\n syncedStorage: dummyStorage,\n globalStorage: dummyStorage,\n localStorage: dummyStorage,\n });\n const actionRegistryInstance = UI.ActionRegistry.ActionRegistry.instance({forceNew: true});\n UI.ShortcutRegistry.ShortcutRegistry.instance({forceNew: true, actionRegistry: actionRegistryInstance});\n\n networkPanel = Network.NetworkPanel.NetworkPanel.instance({forceNew: true, displayScreenshotDelay: 0});\n networkPanel.markAsRoot();\n networkPanel.show(document.body);\n await coordinator.done();\n });\n\n afterEach(async () => {\n await coordinator.done();\n networkPanel.detach();\n });\n\n it('clears network log on button click', async () => {\n const networkLogResetSpy = sinon.spy(Logs.NetworkLog.NetworkLog.instance(), 'reset');\n const toolbar = networkPanel.element.querySelector('.network-toolbar-container .toolbar');\n const button = toolbar!.shadowRoot!.querySelector('[aria-label=\"Clear network log\"]');\n assert.instanceOf(button, HTMLElement);\n button.click();\n await coordinator.done({waitForWork: true});\n assert.isTrue(networkLogResetSpy.called);\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"NetworkPanel.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/network/NetworkPanel.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as Logs from '../../models/logs/logs.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport {createTarget, registerNoopActions} from '../../testing/EnvironmentHelpers.js';\nimport {describeWithMockConnection} from '../../testing/MockConnection.js';\nimport * as Coordinator from '../../ui/components/render_coordinator/render_coordinator.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport * as Network from './network.js';\n\nconst coordinator = Coordinator.RenderCoordinator.RenderCoordinator.instance();\n\ndescribeWithMockConnection('NetworkPanel', () => {\n let target: SDK.Target.Target;\n let networkPanel: Network.NetworkPanel.NetworkPanel;\n\n beforeEach(async () => {\n registerNoopActions(['network.toggle-recording', 'network.clear']);\n\n target = createTarget();\n const dummyStorage = new Common.Settings.SettingsStorage({});\n for (const settingName\n of ['network-color-code-resource-types', 'network.group-by-frame', 'network-record-film-strip-setting']) {\n Common.Settings.registerSettingExtension({\n settingName,\n settingType: Common.Settings.SettingType.BOOLEAN,\n defaultValue: false,\n });\n }\n Common.Settings.Settings.instance({\n forceNew: true,\n syncedStorage: dummyStorage,\n globalStorage: dummyStorage,\n localStorage: dummyStorage,\n });\n networkPanel = Network.NetworkPanel.NetworkPanel.instance({forceNew: true, displayScreenshotDelay: 0});\n networkPanel.markAsRoot();\n networkPanel.show(document.body);\n await coordinator.done();\n });\n\n afterEach(async () => {\n await coordinator.done();\n networkPanel.detach();\n });\n\n const tracingTests = (inScope: boolean) => () => {\n it('starts recording on page reload', async () => {\n SDK.TargetManager.TargetManager.instance().setScopeTarget(inScope ? target : null);\n Common.Settings.Settings.instance().moduleSetting('network-record-film-strip-setting').set(true);\n const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel);\n assert.exists(resourceTreeModel);\n const tracingManager = target.model(Trace.TracingManager.TracingManager);\n assert.exists(tracingManager);\n const tracingStart = sinon.spy(tracingManager, 'start');\n resourceTreeModel.dispatchEventToListeners(SDK.ResourceTreeModel.Events.WillReloadPage);\n assert.strictEqual(tracingStart.called, inScope);\n });\n\n it('stops recording on page load', async () => {\n SDK.TargetManager.TargetManager.instance().setScopeTarget(target);\n Common.Settings.Settings.instance().moduleSetting('network-record-film-strip-setting').set(true);\n const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel);\n assert.exists(resourceTreeModel);\n const tracingManager = target.model(Trace.TracingManager.TracingManager);\n assert.exists(tracingManager);\n resourceTreeModel.dispatchEventToListeners(SDK.ResourceTreeModel.Events.WillReloadPage);\n SDK.TargetManager.TargetManager.instance().setScopeTarget(inScope ? target : null);\n\n const tracingStop = sinon.spy(tracingManager, 'stop');\n resourceTreeModel.dispatchEventToListeners(SDK.ResourceTreeModel.Events.Load, {resourceTreeModel, loadTime: 42});\n await new Promise(resolve => setTimeout(resolve, 0));\n assert.strictEqual(tracingStop.called, inScope);\n });\n };\n\n describe('in scope', tracingTests(true));\n describe('out of scpe', tracingTests(false));\n});\n\ndescribeWithMockConnection('NetworkPanel', () => {\n let networkPanel: Network.NetworkPanel.NetworkPanel;\n\n beforeEach(async () => {\n UI.ActionRegistration.maybeRemoveActionExtension('network.toggle-recording');\n UI.ActionRegistration.maybeRemoveActionExtension('network.clear');\n await import('./network-meta.js');\n createTarget();\n const dummyStorage = new Common.Settings.SettingsStorage({});\n Common.Settings.Settings.instance({\n forceNew: true,\n syncedStorage: dummyStorage,\n globalStorage: dummyStorage,\n localStorage: dummyStorage,\n });\n const actionRegistryInstance = UI.ActionRegistry.ActionRegistry.instance({forceNew: true});\n UI.ShortcutRegistry.ShortcutRegistry.instance({forceNew: true, actionRegistry: actionRegistryInstance});\n\n networkPanel = Network.NetworkPanel.NetworkPanel.instance({forceNew: true, displayScreenshotDelay: 0});\n networkPanel.markAsRoot();\n networkPanel.show(document.body);\n await coordinator.done();\n });\n\n afterEach(async () => {\n await coordinator.done();\n networkPanel.detach();\n });\n\n it('clears network log on button click', async () => {\n const networkLogResetSpy = sinon.spy(Logs.NetworkLog.NetworkLog.instance(), 'reset');\n const toolbar = networkPanel.element.querySelector('.network-toolbar-container .toolbar');\n const button = toolbar!.shadowRoot!.querySelector('[aria-label=\"Clear network log\"]');\n assert.instanceOf(button, HTMLElement);\n button.click();\n await coordinator.done({waitForWork: true});\n assert.isTrue(networkLogResetSpy.called);\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/recorder/RecorderController.js.map b/public/panels/recorder/RecorderController.js.map index 55dad4fa5..2a7ce9f52 100644 --- a/public/panels/recorder/RecorderController.js.map +++ b/public/panels/recorder/RecorderController.js.map @@ -1 +1 @@ -{"version":3,"file":"RecorderController.js","sourceRoot":"","sources":["../../../../../../front_end/panels/recorder/RecorderController.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;;;;;;;AAE7B,OAAO,KAAK,MAAM,MAAM,6BAA6B,CAAC;AACtD,OAAO,KAAK,IAAI,MAAM,yBAAyB,CAAC;AAChD,OAAO,KAAK,IAAI,MAAM,yBAAyB,CAAC;AAChD,OAAO,KAAK,QAAQ,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,GAAG,MAAM,uBAAuB,CAAC;AAC7C,OAAO,KAAK,QAAQ,MAAM,mCAAmC,CAAC;AAC9D,OAAO,KAAK,gBAAgB,MAAM,uCAAuC,CAAC;AAE1E,OAAO,KAAK,SAAS,MAAM,qCAAqC,CAAC;AACjE,OAAO,KAAK,QAAQ,MAAM,mCAAmC,CAAC;AAC9D,OAAO,KAAK,OAAO,MAAM,mCAAmC,CAAC;AAC7D,OAAO,KAAK,OAAO,MAAM,wCAAwC,CAAC;AAClE,OAAO,KAAK,OAAO,MAAM,wCAAwC,CAAC;AAClE,OAAO,KAAK,gBAAgB,MAAM,wCAAwC,CAAC;AAC3E,OAAO,KAAK,KAAK,MAAM,oCAAoC,CAAC;AAC5D,OAAO,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAChD,OAAO,KAAK,OAAO,MAAM,+BAA+B,CAAC;AACzD,OAAO,KAAK,aAAa,MAAM,2CAA2C,CAAC;AAE3E,OAAO,KAAK,UAAU,MAAM,4BAA4B,CAAC;AAGzD,OAAO,KAAK,UAAU,MAAM,4BAA4B,CAAC;AACzD,OAAO,KAAK,UAAU,MAAM,4BAA4B,CAAC;AACzD,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAC;AAE7C,OAAO,wBAAwB,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,MAAM,MAAM,qBAAqB,CAAC;AAE9C,MAAM,EAAC,IAAI,EAAE,UAAU,EAAE,UAAU,EAAC,GAAG,OAAO,CAAC;AAC/C,MAAM,EAAC,aAAa,EAAE,KAAK,EAAC,GAAG,UAAU,CAAC;AAE1C,MAAM,SAAS,GAAG;IAChB;;OAEG;IACH,eAAe,EAAE,wBAAwB;IACzC;;OAEG;IACH,eAAe,EAAE,kBAAkB;IACnC;;OAEG;IACH,eAAe,EAAE,kBAAkB;IACnC;;OAEG;IACH,YAAY,EAAE,eAAe;IAC7B;;;OAGG;IACH,kBAAkB,EAAE,cAAc;IAClC;;OAEG;IACH,cAAc,EAAE,UAAU;IAC1B;;OAEG;IACH,cAAc,EAAE,kBAAkB;IAClC;;OAEG;IACH,eAAe,EAAE,QAAQ;IACzB;;OAEG;IACH,kBAAkB,EAAE,sBAAsB;IAC1C;;OAEG;IACH,eAAe,EAAE,kBAAkB;IACnC;;OAEG;IACH,YAAY,EAAE,iCAAiC;IAC/C;;OAEG;IACH,UAAU,EAAE,kBAAkB;IAC9B;;;OAGG;IACH,MAAM,EAAE,QAAQ;IAChB;;;;OAIG;IACH,mBAAmB,EAAE,uBAAuB;IAC5C;;;OAGG;IACH,aAAa,EAAE,iBAAiB;IAChC;;OAEG;IACH,YAAY,EAAE,eAAe;CAC9B,CAAC;AACF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,uCAAuC,EAAE,SAAS,CAAC,CAAC;AAC7F,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAEtE,MAAM,wBAAwB,GAAG,qBAAqB,CAAC;AACvD,MAAM,kBAAkB,GAAG,yCAA4E,CAAC;AA4CxG,MAAM,sBAAsB,GAAiE;IAC3F,oDAAuC,oDAA4C;IACnF,mEAAyC,gEAAwD;IACjG,8DAA4C,yDAAiD;IAC7F,8EAAoD,yDAAiD;IACrG,gEAA6C,0DAAkD;CAChG,CAAC;AAGK,IAAM,kBAAkB,GAAxB,MAAM,kBAAmB,SAAQ,UAAU;IAChD,MAAM,CAAmB,MAAM,GAAG,CAAC,wBAAwB,CAAC,CAAC;IAO7D,QAAQ,GAAG,MAAM,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC;IAC/D,kBAAkB,GAAG,MAAM,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC;IAK3E,wFAAwF;IACxF,+EAA+E;IAC/E,cAAc,GAAG,IAAI,CAAC;IAGb,YAAY,GAAyC,EAAC,SAAS,EAAE,KAAK,EAAE,oBAAoB,EAAE,KAAK,EAAC,CAAC;IAI9G,aAAa,CAAoB;IAQjC,iBAAiB,CAAkC;IAEnD,sBAAsB,GAAgB,IAAI,GAAG,EAAE,CAAC;IAEhD,kBAAkB,CAA6C;IAM/D,iBAAiB,GAAG,IAAI,MAAM,CAAC,gBAAgB,CAAC,gBAAgB,EAAE,CAAC;IACnE,eAAe,GAAG,IAAI,MAAM,CAAC,sBAAsB,CAAC,sBAAsB,EAAE,CAAC;IAE7E;QACE,KAAK,EAAE,CAAC;QAER,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;QACzB,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,IAAI,CAAC,kBAAkB,GAAG,KAAK,CAAC;QAEhC,IAAI,CAAC,WAAW,qCAAmB,CAAC;QACpC,IAAI,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC,MAAM,EAAE,CAAC;YACzC,IAAI,CAAC,eAAe,qDAA2B,CAAC;QAClD,CAAC;QAED,MAAM,gBAAgB,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,oBAAoB,CAAC,CAAC,GAAG,EAAE,CAAC;QACvG,IAAI,CAAC,kBAAkB,GAAG,MAAM,CAAC,MAAM,CAAC;YACtC,IAAI,UAAU,CAAC,aAAa,CAAC,aAAa,CAAC,gBAAgB,CAAC;YAC5D,IAAI,UAAU,CAAC,wBAAwB,CAAC,wBAAwB,CAAC,gBAAgB,CAAC;YAClF,IAAI,UAAU,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,gBAAgB,CAAC;YACtE,IAAI,UAAU,CAAC,yBAAyB,CAAC,yBAAyB,CAAC,gBAAgB,CAAC;YACpF,IAAI,UAAU,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,gBAAgB,CAAC;SACzE,CAAC,CAAC;QAEH,MAAM,gBAAgB,GAAG,UAAU,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC;QACjF,IAAI,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,UAAU,EAAE,CAAC,CAAC;QACtD,gBAAgB,CAAC,gBAAgB,kFAAwD,KAAK,CAAC,EAAE;YAC/F,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;QAEH,0BAA0B;QAC1B,IAAI,CAAC,gBAAgB,CAAC,cAAc,EAAE,CAAC,KAAY,EAAE,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC;IACvF,CAAC;IAEQ,oBAAoB;QAC3B,KAAK,CAAC,oBAAoB,EAAE,CAAC;QAE7B,IAAI,IAAI,CAAC,uBAAuB,EAAE,CAAC;YACjC,KAAK,IAAI,CAAC,uBAAuB,CAAC,IAAI,EAAE,CAAC;QAC3C,CAAC;IACH,CAAC;IAED,iBAAiB,CAAC,UAAmD;QACnE,IAAI,CAAC,mBAAmB;YACpB,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,eAAe,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE;gBACpG,OAAO,IAAI,UAAU,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YAC9E,CAAC,CAAC,CAAC;QACP,IAAI,CAAC,gBAAgB,GAAG,UAAU,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,eAAe,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;IACzG,CAAC;IAED,6BAA6B,CAAC,WAAoB;QAChD,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;IAED,2BAA2B,CAAC,KAA2C;QACrE,IAAI,CAAC,YAAY,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC;QAC9C,IAAI,CAAC,YAAY,CAAC,oBAAoB,GAAG,KAAK,CAAC,oBAAoB,CAAC;IACtE,CAAC;IAED,wBAAwB,CAAC,IAAW;QAClC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,wBAAwB;QACtB,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,6BAA6B;QAC3B,OAAO,IAAI,CAAC,gBAAgB,CAAC;IAC/B,CAAC;IAED,kCAAkC;QAChC,OAAO,CAAC,GAAG,IAAI,CAAC,sBAAsB,CAAC,MAAM,EAAE,CAAC,CAAC;IACnD,CAAC;IAED;;;;OAIG;IACH,WAAW;QACT,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,IAAU;QAC1B,MAAM,YAAY,GAAG,IAAI,MAAM,CAAC,kBAAkB,CAAC,kBAAkB,EAAE,CAAC;QACxE,MAAM,MAAM,GAAG,IAAI,QAAQ,CAAC,SAAS,CAAC,iBAAiB,CACnD,IAAI;QACJ,eAAe,CAAC,QAAQ,CAAC,CAAC;QAC9B,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAChD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;QAED,IAAI,IAAsC,CAAC;QAC3C,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACnE,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;YACzB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,oBAAoB,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC;QACnE,IAAI,CAAC,eAAe,4CAAsB,CAAC;QAC3C,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAED,6BAA6B,CAAC,SAAoC;QAChE,IAAI,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC;IACvC,CAAC;IAED,qBAAqB;QACnB,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,oBAAoB,CAAC,SAAoC,EAAE,OAA4C,EAAE;QACvG,MAAM,EAAC,eAAe,GAAG,KAAK,EAAE,aAAa,GAAG,KAAK,EAAC,GAAG,IAAI,CAAC;QAC9D,IAAI,CAAC,eAAe,EAAE,KAAK,EAAE,CAAC;QAC9B,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;QAC7B,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;QAChC,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAC;QAClC,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;QACjC,IAAI,CAAC,YAAY,CAAC,SAAS,GAAG,KAAK,CAAC;QACpC,IAAI,CAAC,YAAY,CAAC,oBAAoB,GAAG,KAAK,CAAC;QAC/C,IAAI,CAAC,sBAAsB,GAAG,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC;QAExF,IAAI,SAAS,EAAE,CAAC;YACd,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAC;YAClC,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnE,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YACpD,IAAI,aAAa,IAAI,IAAI,CAAC,uBAAuB,EAAE,CAAC;gBAClD,IAAI,CAAC,uBAAuB,CAAC,iBAAiB,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAC;YAClC,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;YAC1B,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;QAC5B,CAAC;QAED,IAAI,CAAC,6BAA6B,EAAE,CAAC;IACvC,CAAC;IAED,eAAe,CAAC,IAAW;QACzB,IAAI,IAAI,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;YAC9B,OAAO;QACT,CAAC;QAED,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,WAAW,CAAC;QACrC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;IAC1B,CAAC;IAED,cAAc,CAAC,IAA4B;QACzC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACzB,MAAM,eAAe,GAAG,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;QAC1E,MAAM,QAAQ,GAA+C,EAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAC,CAAC;QACrF,KAAK,IAAI,CAAC,GAAG,eAAe,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC9C,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YACtB,IAAI,CAAC,QAAQ,CAAC,gBAAgB,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;gBAC9D,QAAQ,CAAC,gBAAgB,GAAG,IAAI,CAAC;YACnC,CAAC;YACD,IAAI,CAAC,QAAQ,CAAC,yBAAyB,IAAI,IAAI,CAAC,IAAI,KAAK,0BAA0B,EAAE,CAAC;gBACpF,QAAQ,CAAC,yBAAyB,GAAG,EAAC,GAAG,IAAI,EAAC,CAAC;gBAC/C,KAAK,MAAM,MAAM,IACL,CAAC,GAAG,CAAC,cAAc,CAAC,iBAAiB,EAAE,GAAG,CAAC,cAAc,CAAC,gBAAgB;oBACzE,GAAG,CAAC,cAAc,CAAC,gBAAgB,EAAE,GAAG,CAAC,cAAc,CAAC,gBAAgB,CAAC,EAAE,CAAC;oBACvF,+GAA+G;oBAC/G,IAAI,GAAG,CAAC,cAAc,CAAC,sBAAsB,CACrC,EAAC,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,YAAY,IAAI,EAAE,EAAC,EAAE,EAAC,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,YAAY,IAAI,EAAE,EAAC,CAAC,EAAE,CAAC;wBACpG,QAAQ,CAAC,yBAAyB,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,YAAY,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;wBAC5G,QAAQ,CAAC,yBAAyB,CAAC,YAAY,GAAG,MAAM,CAAC,YAAY,CAAC;oBACxE,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,cAAc;QACZ,MAAM,MAAM,GAAG,GAAG,CAAC,aAAa,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,iBAAiB,EAAE,CAAC;QAC9E,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC9C,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,mBAAmB,CAAC,IAAwB;QAC1C,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;YACnB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YACpC,IAAI,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;gBACvC,OAAO,OAAO,CAAC;YACjB,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED,6BAA6B;QAC3B,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC7C,OAAO;QACT,CAAC;QACD,MAAM,WAAW,GAAG,IAAI,CAAC,gBAAgB,CAAC,WAAW,CAAC;QACtD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,kBAAkB,CAAC,uBAAuB,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;YACnF,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,UAAU,GAAG,UAAU,IAAI,SAAS,CAAC;QACxD,CAAC;QACD,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC;IAED,cAAc;QACZ,IAAI,CAAC,eAAe,EAAE,KAAK,EAAE,CAAC;IAChC,CAAC;IAED,KAAK,CAAC,mBAAmB,CAAC,SAAgD;QACxE,IAAI,CAAC,IAAI,CAAC,gBAAgB,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACnD,OAAO;QACT,CAAC;QACD,MAAM,aAAa,GAAG,gBAAgB,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,QAAQ,EAAE,CAAC;QAC9F,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,6FAAmE,CAAC;QACtG,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAC7C,MAAM,UAAU,GAAG,MAAM,OAAO,CAAC;QACjC,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC;QACjC,IAAI,CAAC,WAAW,CAAC,sBAAsB,sEAA8D,CAAC;IACxG,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,KAAkD;QACvE,IAAI,CAAC,IAAI,CAAC,gBAAgB,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACnD,OAAO;QACT,CAAC;QACD,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;QAClC,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACzB,OAAO,IAAI,CAAC,mBAAmB,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxD,CAAC;QACD,IAAI,CAAC,WAAW,CAAC,sBAAsB,CACnC,KAAK,CAAC,IAAI,CAAC,WAAW,yEAAiD,CAAC,CAAC;4FACG,CAAC;uEACtB,CAAC,CAAC;QAC7D,IAAI,CAAC,YAAY,CAAC,SAAS,GAAG,IAAI,CAAC;QACnC,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;QAC7B,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;QAChC,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAC;QAClC,MAAM,gBAAgB,GAAG,IAAI,CAAC,gBAAgB,CAAC;QAC/C,IAAI,CAAC,WAAW,EAAE,CAAC;QAEnB,MAAM,IAAI,CAAC,2BAA2B,EAAE,CAAC;QAEzC,IAAI,CAAC,eAAe,GAAG,IAAI,MAAM,CAAC,eAAe,CAAC,eAAe,CAC7D,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,EAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,iBAAiB,EAAE,IAAI,CAAC,sBAAsB,EAAC,CAAC,CAAC;QAE3G,MAAM,oBAAoB,GAAG,KAAK,CAAC,IAAI,CAAC,WAAW,4EAA2D,CAAC;QAC/G,MAAM,sBAAsB,GAAG,IAAI,GAAG,EAAE,CAAC;QACzC,IAAI,CAAC,eAAe,CAAC,gBAAgB,kDAAqC,KAAK,EAAE,EAAC,IAAI,EAAE,EAAC,IAAI,EAAE,OAAO,EAAC,EAAC,EAAE,EAAE;YAC1G,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;YACxB,MAAM,cAAc,GAAG,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC;YACtD,IAAI,IAAI,CAAC,QAAQ,IAAI,cAAc,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,cAAc,CAAC,EAAE,CAAC;gBACnF,sBAAsB,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;gBAC3C,MAAM,mBAAmB,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;gBAClE,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,cAAc,EAAE,CAAC;gBACjE,cAAc,CAAC,UAAU,GAAG,UAAU,CAAC;gBACvC,MAAM,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC,yBAAyB,CAC3E,gBAAgB,CAAC,WAAW,EAAE,mBAAmB,EAAE,UAAU,CAAC,CAAC;YACrE,CAAC;YACD,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,eAAe,CAAC,gBAAgB,kDAAqC,GAAG,EAAE;YAC7E,IAAI,CAAC,YAAY,CAAC,oBAAoB,GAAG,IAAI,CAAC;YAC9C,IAAI,CAAC,aAAa,EAAE,CAAC;QACvB,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,eAAe,CAAC,gBAAgB,0DAAyC,GAAG,EAAE;YACjF,IAAI,CAAC,YAAY,CAAC,oBAAoB,GAAG,KAAK,CAAC;YAC/C,IAAI,CAAC,aAAa,EAAE,CAAC;QACvB,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,eAAe,CAAC,gBAAgB,oDAAsC,CAAC,EAAC,IAAI,EAAE,KAAK,EAAC,EAAE,EAAE;YAC3F,IAAI,CAAC,cAAc,GAAG,KAAK,CAAC;YAC5B,IAAI,CAAC,oBAAoB,EAAE,CAAC;gBAC1B,IAAI,CAAC,YAAY,CAAC,SAAS,GAAG,KAAK,CAAC;gBACpC,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;YACnC,CAAC;YACD,IAAI,CAAC,gBAAgB,8DAA8C,CAAC;YACpE,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;YACjD,IAAI,YAAY,CAAC,UAAU,CAAC,wBAAwB,CAAC,EAAE,CAAC;gBACtD,IAAI,CAAC,WAAW,CAAC,uBAAuB,0EAAkE,CAAC;YAC7G,CAAC;iBAAM,IAAI,YAAY,CAAC,UAAU,CAAC,2BAA2B,CAAC,EAAE,CAAC;gBAChE,IAAI,CAAC,WAAW,CAAC,uBAAuB,uEAA+D,CAAC;YAC1G,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,WAAW,CAAC,uBAAuB,8DAAsD,CAAC;YACjG,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,eAAe,CAAC,gBAAgB,kDAAqC,GAAG,EAAE;YAC7E,IAAI,CAAC,oBAAoB,EAAE,CAAC;gBAC1B,IAAI,CAAC,YAAY,CAAC,SAAS,GAAG,KAAK,CAAC;gBACpC,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;YACnC,CAAC;YACD,IAAI,CAAC,gBAAgB,8DAA8C,CAAC;YACpE,qCAAqC;YACrC,IAAI,CAAC,aAAa,CAAC,IAAI,MAAM,CAAC,mBAAmB,EAAE,CAAC,CAAC;YACrD,IAAI,CAAC,WAAW,CAAC,uBAAuB,0DAAkD,CAAC;QAC7F,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,eAAe,CAAC,gBAAgB,oDAAsC,GAAG,EAAE;YAC9E,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;YAC7B,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;YAChC,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAC;YAClC,IAAI,CAAC,YAAY,CAAC,SAAS,GAAG,KAAK,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH,IAAI,iBAAiB,GAAG,CAAC,OAAiB,EAAQ,EAAE,GAAE,CAAC,CAAC;QACxD,MAAM,aAAa,GAAG,IAAI,OAAO,CAAW,CAAC,OAAO,EAAQ,EAAE;YAC5D,iBAAiB,GAAG,OAAO,CAAC;QAC9B,CAAC,CAAC,CAAC;QAEH,IAAI,kBAAkB,GAAG,IAAI,CAAC;QAC9B,QAAQ,KAAK,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC;YAChC;gBACE,kBAAkB,GAAG,IAAI,OAAO,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE;oBAC5F,kBAAkB,KAAS,CAAC;oBAC5B,uBAAuB,KAAS,CAAC;oBACjC,eAAe,CAAC,MAAgB;wBAC9B,iBAAiB,CAAC,MAAM,CAAC,CAAC;oBAC5B,CAAC;iBACF,CAAC,CAAC;gBACH,MAAM;QACV,CAAC;QAED,IAAI,kBAAkB,EAAE,CAAC;YACvB,MAAM,kBAAkB,CAAC,KAAK,EAAE,CAAC;QACnC,CAAC;QAED,IAAI,CAAC,yBAAyB,CAAC,KAAK,CAAC,CAAC;QACtC,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC;QAClC,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,CAAC;QAErC,IAAI,kBAAkB,EAAE,CAAC;YACvB,MAAM,kBAAkB,CAAC,IAAI,EAAE,CAAC;YAChC,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC;YACnC,IAAI,CAAC,YAAY,CAAC,SAAS,GAAG,KAAK,CAAC;YACpC,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;YACjC,MAAM,EAAE,CAAC,aAAa,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,WAAqB,CAAC,CAAC;YAC7F,QAAQ,KAAK,CAAC,IAAI,EAAE,WAAW,EAAE,CAAC;gBAChC;oBACE,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,cAAc,CAC1D,MAAwD,CAAC,CAAC;oBAC9D,MAAM;YACV,CAAC;QACH,CAAC;IACH,CAAC;IAED,KAAK,CAAC,2BAA2B;QAC/B,IAAI,CAAC;YACH,MAAM,iBAAiB,GAAG,SAAS,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC;YACnF,IAAI,iBAAiB,CAAC,cAAc,EAAE,EAAE,CAAC;gBACvC,iBAAiB,CAAC,gBAAgB,EAAE,CAAC;gBACrC,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;gBACtF,MAAM,cAAc,EAAE,aAAa,CAAC,IAAI,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,oEAAoE;YACpE,8EAA8E;QAChF,CAAC;IACH,CAAC;IAED,yBAAyB,CAAC,qBAA8B;QACtD,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;QACtF,cAAc,EAAE,wBAAwB,CAAC,qBAAqB,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,KAAY;QAChC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAE,KAAqB,CAAC,MAAM,CAAC,CAAC;QACvD,IAAI,CAAC,oBAAoB,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC7F,IAAI,CAAC,eAAe,4CAAsB,CAAC;QAC3C,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAED,sDAAsD;IACtD,WAAW;QACT,OAAO,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,uBAAuB,CAAC,KAAsC;QAClE,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,SAAS,GAAG;YAChB,GAAG,IAAI,CAAC,gBAAgB;YACxB,IAAI,EAAE;gBACJ,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI;gBAC7B,KAAK,EAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;aACvG;SACF,CAAC;QACF,IAAI,CAAC,oBAAoB,CACrB,MAAM,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC,WAAW,EAAE,SAAS,CAAC,IAAI,CAAC,EAC1E,EAAC,eAAe,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAC,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,KAAkC;QACvD,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,aAAa,GAAG,KAAK,CAAC,aAAa,CAAC;QAC1C,IAAI,IAAI,CAAC;QACT,IAAI,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAC9B,IAAI,OAAO,IAAI,aAAa,EAAE,CAAC;YAC7B,UAAU;YACV,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;YACzD,IAAI,UAAU,KAAK,SAAS,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;gBAClD,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;YAC1D,CAAC;YACD,IAAI,KAAK,CAAC,QAAQ,4DAA8C,EAAE,CAAC;gBACjE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;oBAC7C,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;oBAC5C,QAAQ,4DAA6C,CAAC;gBACxD,CAAC;qBAAM,CAAC;oBACN,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,CAAC,WAAW,CAAC;oBAC/C,QAAQ,0DAA4C,CAAC;gBACvD,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,IAAI,UAAU,IAAI,CAAC,EAAE,CAAC;oBACpB,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;gBAC1D,CAAC;gBACD,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,EAAE,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC;gBACpD,IAAI,GAAG,WAAW,EAAE,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;gBACxD,QAAQ,0DAA4C,CAAC;YACvD,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO;YACP,IAAI,GAAG,aAAa,CAAC;QACvB,CAAC;QACD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACjE,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC;QAC/C,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,eAAe,GAAG,YAAY,GAAG,CAAC,QAAQ,8DAA+C,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACzG,KAAK,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC,EAAE,EAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,EAAE,SAAS,EAAE,CAAC,MAAM,CAAC,EAAC,CAAC,CAAC;QACrG,MAAM,SAAS,GAAG,EAAC,GAAG,IAAI,CAAC,gBAAgB,EAAE,IAAI,EAAE,EAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,KAAK,EAAC,EAAC,CAAC;QAC3F,IAAI,CAAC,WAAW,CAAC,eAAe,qDAA6C,CAAC;QAC9E,IAAI,CAAC,sBAAsB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,sBAAsB,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,EAAE;YACpG,IAAI,eAAe,GAAG,eAAe,EAAE,CAAC;gBACtC,OAAO,eAAe,CAAC;YACzB,CAAC;YAED,OAAO,eAAe,GAAG,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC,CAAC;QACJ,IAAI,CAAC,oBAAoB,CACrB,MAAM,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC,WAAW,EAAE,SAAS,CAAC,IAAI,CAAC,EAC1E,EAAC,eAAe,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAC,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,4BAA4B,CAAC,KAA0D;QAC3F,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;QAED,MAAM,IAAI,GAAG,EAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAC,CAAC;QACjE,IAAI,CAAC,oBAAoB,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC;IAC1G,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,KAAqC;QAC5D,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC;QAC/C,MAAM,YAAY,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/C,KAAK,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;QAC9B,MAAM,IAAI,GAAG,EAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,EAAE,KAAK,EAAC,CAAC;QACpD,IAAI,CAAC,WAAW,CAAC,eAAe,uDAA+C,CAAC;QAChF,IAAI,CAAC,sBAAsB,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,sBAAsB,CAAC,MAAM,EAAE,CAAC;aACpC,GAAG,CAAC,eAAe,CAAC,EAAE;YACrB,IAAI,YAAY,GAAG,eAAe,EAAE,CAAC;gBACnC,OAAO,eAAe,CAAC;YACzB,CAAC;YAED,IAAI,YAAY,KAAK,eAAe,EAAE,CAAC;gBACrC,OAAO,CAAC,CAAC,CAAC;YACZ,CAAC;YAED,OAAO,eAAe,GAAG,CAAC,CAAC;QAC7B,CAAC,CAAC;aACD,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC;QACxE,IAAI,CAAC,oBAAoB,CACrB,MAAM,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,EAC5E,EAAC,eAAe,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAC,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,2BAA2B,CAAC,KAAwD;QACxF,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,WAAW,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;QACjG,IAAI,WAAW,KAAK,CAAC,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACrE,CAAC;QACD,MAAM,2BAA2B,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;YAC3F,IAAI,GAAG,IAAI,WAAW,EAAE,CAAC;gBACvB,OAAO,KAAK,CAAC;YACf,CAAC;YACD,OAAO,IAAI,CAAC,IAAI,KAAK,0BAA0B,CAAC;QAClD,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YAChB,0BAA0B;YAC1B,IAAI,2BAA2B,KAAK,CAAC,CAAC,EAAE,CAAC;gBACvC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,2BAA2B,EAAE,CAAC,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC;aAAM,IAAI,2BAA2B,KAAK,CAAC,CAAC,EAAE,CAAC;YAC9C,gCAAgC;YAChC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CACnC,CAAC,EAAE,CAAC,EACJ,MAAM,CAAC,WAAW,CAAC,kCAAkC,CACjD,EAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,OAAO,EAAC,CAAC,CAAC,CAAC;QACpG,CAAC;aAAM,CAAC;YACN,wBAAwB;YACxB,MAAM,IAAI,GACN,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,2BAA2B,CAA+C,CAAC;YAChH,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;YACpC,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;YAChC,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC;QACpC,CAAC;QACD,IAAI,CAAC,oBAAoB,CACrB,MAAM,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1G,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,KAA8C;QACpE,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;QACD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC;QAChD,IAAI,CAAC,oBAAoB,CACrB,MAAM,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1G,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,KAAY;QACnC,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,IAAI,KAAK,YAAY,UAAU,CAAC,iBAAiB,CAAC,oBAAoB,EAAE,CAAC;YACvE,MAAM,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YACvD,IAAI,CAAC,kBAAkB,CAAC,6BAA6B,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;YACzE,IAAI,CAAC,aAAa,EAAE,CAAC;QACvB,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBAC3B,OAAO;YACT,CAAC;YACD,MAAM,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;YACvE,IAAI,CAAC,kBAAkB,CAAC,6BAA6B,CAAC,IAAI,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;QAC3F,CAAC;QACD,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;YACjD,IAAI,CAAC,eAAe,qDAA2B,CAAC;QAClD,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,eAAe,oCAAkB,CAAC;QACzC,CAAC;QACD,IAAI,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC;QACrC,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAED,qBAAqB,CAAC,KAAa;QACjC,KAAK,EAAE,eAAe,EAAE,CAAC;QACzB,IAAI,CAAC,eAAe,yDAA6B,CAAC;QAClD,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,mBAAmB,CAAC,KAA2D;QACnF,6CAA6C;QAC7C,MAAM,IAAI,CAAC,2BAA2B,EAAE,CAAC;QAEzC,gFAAgF;QAChF,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,WAAW,EAAE,CAAC;QAEnB,oCAAoC;QACpC,IAAI,CAAC,WAAW,CAAC,gBAAgB,6DAAqD,CAAC;QACvF,IAAI,CAAC,uBAAuB,GAAG,IAAI,MAAM,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE;YACjG,KAAK,EAAE,KAAK,CAAC,IAAI;YACjB,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;YAC1C,qBAAqB,EAAE,KAAK,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;gBAC7B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;SACtG,CAAC,CAAC;QACH,IAAI,CAAC,oBAAoB,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,CAAC,uBAAuB,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;QAE3G,IAAI,oBAAoB,GAAG,CAAC,CAAC,CAAC;QAC9B,IAAI,iBAAyE,CAAC;QAC9E,MAAM,cAAc,GAAG,KAAK,EAAC,gBAAiC,EAAiB,EAAE;YAC/E,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACnB,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;YAC9C,CAAC;YAED,MAAM,mBAAmB,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;YACrD,MAAM,cAAc,GAAG,IAAI,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;YAC1D,IAAI,iBAAiB,IAAI,oBAAoB,KAAK,mBAAmB,EAAE,CAAC;gBACtE,OAAO;YACT,CAAC;YAED,iBAAiB,GAAG,MAAM,CAAC,eAAe,CAAC,cAAc,EAAE,CAAC;YAC5D,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC;YAC3C,iBAAiB,GAAG,SAAS,CAAC;YAC9B,cAAc,CAAC,UAAU,GAAG,UAAU,CAAC;YACvC,MAAM,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC,yBAAyB,CAC3E,gBAAgB,CAAC,WAAW,EAAE,mBAAmB,EAAE,UAAU,CAAC,CAAC;YACnE,oBAAoB,GAAG,mBAAmB,CAAC;YAC3C,IAAI,CAAC,6BAA6B,EAAE,CAAC;QACvC,CAAC,CAAC;QAEF,IAAI,CAAC,uBAAuB,CAAC,gBAAgB,4EACS,KAAK,EAAE,EAAC,IAAI,EAAiC,EAAE,EAAE;YACjG,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBAC3B,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;YAChD,CAAC;YACD,IAAI,CAAC,oBAAoB,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC;YACxG,MAAM,aAAa,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,yBAAyB,CAAC,CAAC;YAChF,aAAa,EAAE,cAAc,EAAE,CAAC;YAEhC,MAAM,cAAc,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QAEP,IAAI,CAAC,uBAAuB,CAAC,gBAAgB,4EACS,KAAK,EAAE,EAAC,IAAI,EAAiC,EAAE,EAAE;YACjG,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBAC3B,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;YAChD,CAAC;YACD,IAAI,CAAC,WAAW,CAAC,qBAAqB,iFAAyC,CAAC;YAChF,IAAI,CAAC,oBAAoB,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC;YACxG,MAAM,IAAI,CAAC,oBAAoB,EAAE,CAAC;QACpC,CAAC,CAAC,CAAC;QAEP,MAAM,IAAI,CAAC,uBAAuB,CAAC,KAAK,EAAE,CAAC;QAC3C,kCAAkC;QAElC,+EAA+E;QAC/E,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,eAAe,4CAAsB,CAAC;QAE3C,qCAAqC;QACrC,IAAI,CAAC,aAAa,CAAC,IAAI,MAAM,CAAC,0BAA0B,CAAE,IAAI,CAAC,gBAAoC,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7G,CAAC;IAED,KAAK,CAAC,oBAAoB;QACxB,IAAI,CAAC,IAAI,CAAC,gBAAgB,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,CAAC;YAC5D,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACjD,CAAC;QAED,8EAA8E;QAC9E,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,WAAW,EAAE,CAAC;QAEnB,oCAAoC;QACpC,IAAI,CAAC,WAAW,CAAC,gBAAgB,8DAAsD,CAAC;QACxF,MAAM,IAAI,CAAC,uBAAuB,CAAC,IAAI,EAAE,CAAC;QAC1C,IAAI,CAAC,uBAAuB,GAAG,SAAS,CAAC;QACzC,kCAAkC;QAElC,2EAA2E;QAC3E,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;QACxB,IAAI,CAAC,WAAW,GAAG,KAAK,CAAC;QAEzB,qCAAqC;QACrC,IAAI,CAAC,aAAa,CAAC,IAAI,MAAM,CAAC,0BAA0B,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;IACxF,CAAC;IAED,KAAK,CAAC,qBAAqB;QACzB,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACtB,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,KAAY;QACrC,MAAM,WAAW,GAAG,KAAK,YAAY,UAAU,CAAC,iBAAiB,CAAC,kBAAkB;YAC5E,KAAK,YAAY,UAAU,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAAC;YACtE,KAAK,CAAC,WAAW,CAAC,CAAC;YACjB,KAAoB,CAAC,MAA4B,EAAE,KAAK,CAAC;QAC/D,IAAI,CAAC,oBAAoB,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC;QACzE,IAAI,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC1B,IAAI,CAAC,eAAe,4CAAsB,CAAC;QAC7C,CAAC;aAAM,IAAI,WAAW,uCAAqB,EAAE,CAAC;YAC5C,IAAI,CAAC,eAAe,oCAAkB,CAAC;QACzC,CAAC;aAAM,IAAI,WAAW,wDAA8B,EAAE,CAAC;YACrD,IAAI,CAAC,eAAe,qDAA2B,CAAC;QAClD,CAAC;IACH,CAAC;IAED,KAAK,CAAC,uBAAuB,CAAC,KAAmD;QAC/E,IAAI,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACjD,CAAC;QACD,IAAI,KAAK,CAAC,SAAS,KAAK,wBAAwB,EAAE,CAAC;YACjD,IAAI,CAAC,qBAAqB,CAAC,6BAA6B,CAAC,YAAY,CAAC,kBAAkB,CAAC,CAAC;YAC1F,OAAO;QACT,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAC3C,CAAC;QACD,MAAM,EAAE,GAAG,KAAK,CAAC,SAAS,CAAC;QAC3B,MAAM,IAAI,GAAG,CAAC,SAAyC,EAAW,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC;QAC9F,MAAM,SAAS,GAAG,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5F,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAC3C,CAAC;QACD,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACxE,MAAM,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;QACtF,MAAM,aAAa,GAAG,sBAAsB,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC;QAChE,IAAI,aAAa,EAAE,CAAC;YAClB,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC,aAAa,CAAC,CAAC;QACpD,CAAC;aAAM,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACxF,IAAI,CAAC,WAAW,CAAC,iBAAiB,yDAAiD,CAAC;QACtF,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CAAC,0DAA0D,GAAG,EAAE,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,aAAqB,EAAE,IAAY;QACtD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,EAAC,aAAa,EAAC,CAAC,CAAC;YAChE,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,cAAc,EAAE,CAAC;YAC/C,MAAM,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC3B,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,oEAAoE;YACpE,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;gBAChC,OAAO;YACT,CAAC;YAED,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,wBAAwB;QAC5B,IAAI,CAAC,IAAI,CAAC,uBAAuB,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC5D,OAAO;QACT,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,CAAC,uBAAuB,CAAC,aAAa,EAAE,CAAC;QAC1D,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAC,IAAI,EAAE,gBAAyD,EAAE,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAC,CAAC,CAAC;QAC1G,IAAI,CAAC,oBAAoB,CACrB,MAAM,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,EAC5E,EAAC,eAAe,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAC,CAAC,CAAC;QAClD,IAAI,CAAC,WAAW,CAAC,kBAAkB,6DAAqD,CAAC;QACzF,MAAM,IAAI,CAAC,cAAc,CAAC;QAC1B,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,yBAAyB,CAAC;YACpD,EAAE,UAAU,EAAE,aAAa,CAAC,qDAAqD,CAAC;YAClF,EAAE,UAAU,EAAE,aAAa,CAAc,SAAS,CAAC;YACnD,EAAE,KAAK,EAAE,CAAC;IAChB,CAAC;IAED,kBAAkB,CAAC,KAAY;QAC7B,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC,OAAO,CAAC,yBAAyB,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACvF,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,sBAAsB,CAAC,KAAsD;QACjF,MAAM,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;QACvC,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,UAAU,CAAC,aAAa,CAAC,kBAAkB,CACvE,EAAC,WAAW,sEAA8C,EAAE,KAAK,EAAE,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAC,CAAC,CAAC,CAAC;IACzG,CAAC;IAED,gBAAgB,GAAG,CAAC,KAAyB,EAAQ,EAAE;QACrD,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC7C,IAAI,CAAC,eAAe,EAAE,uBAAuB,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QAC3E,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC,CAAC;IAEF,mBAAmB,GAAG,CAAC,KAA4B,EAAQ,EAAE;QAC3D,IAAI,CAAC,sBAAsB,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAChD,IAAI,CAAC,eAAe,EAAE,uBAAuB,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QAC3E,IAAI,CAAC,aAAa,EAAE,CAAC;IACvB,CAAC,CAAC;IAEF,sBAAsB;QACpB,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;IAClC,CAAC;IAED,aAAa,CAAC,QAAiC;QAC7C,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,EAAE,CAAC;YACrC,OAAO;QACT,CAAC;QAED,QAAQ,QAAQ,EAAE,CAAC;YACjB;gBACE,IAAI,CAAC,qBAAqB,EAAE,CAAC;gBAC7B,OAAO;YAET;gBACE,IAAI,IAAI,CAAC,WAAW,4DAAgC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;oBAC1E,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAC7D,IAAI,EACJ,IAAI,UAAU,CAAC,mBAAmB,CAAC,qBAAqB,CACpD,IAAI,CAAC,iBAAiB,CAAC,YAAY,EAAE,IAAI,CAAC,iBAAiB,CAAC,gBAAgB,EAC5E,IAAI,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC;gBACtD,CAAC;qBAAM,IAAI,IAAI,CAAC,WAAW,4DAAgC,EAAE,CAAC;oBAC5D,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,gCAAgC,CAAC,CAAC;oBAC7E,IAAI,IAAI,EAAE,CAAC;wBACT,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;oBACtE,CAAC;gBACH,CAAC;qBAAM,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;oBAC5B,KAAK,IAAI,CAAC,oBAAoB,EAAE,CAAC;gBACnC,CAAC;gBACD,OAAO;YAET;gBACE,KAAK,IAAI,CAAC,gBAAgB,CAAC,IAAI,UAAU,CAAC,aAAa,CAAC,kBAAkB,CACtE,EAAC,WAAW,sEAA8C,EAAE,KAAK,EAAE,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAC,CAAC,CAAC,CAAC;gBACvG,OAAO;YAET,sFAA6C,CAAC,CAAC,CAAC;gBAC9C,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,yBAAyB,CAAC,CAAC;gBACtE,IAAI,IAAI,EAAE,CAAC;oBACT,IAAI,CAAC,cAAc,EAAE,CAAC;gBACxB,CAAC;gBACD,OAAO;YACT,CAAC;QACH,CAAC;IACH,CAAC;IAED,gBAAgB,CAAC,QAAiC;QAChD,QAAQ,QAAQ,EAAE,CAAC;YACjB;gBACE,OAAO,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC;YAC3D;gBACE,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC;YACtC;gBACE,OAAO,CAAC,IAAI,CAAC,WAAW,+CAAyB,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;YACrF;gBACE,OAAO,IAAI,CAAC,WAAW,+CAAyB,CAAC;YACnD;gBACE,8CAA8C;gBAC9C,qCAAqC;gBACrC,OAAO,KAAK,CAAC;QACjB,CAAC;IACH,CAAC;IAED,iBAAiB;QACf,MAAM,mBAAmB,GAAG,CAAC,MAA+B,EAAY,EAAE;YACxE,MAAM,SAAS,GAAG,EAAE,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,QAAQ,EAAE,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;YAE7F,OAAO,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC;QACrD,CAAC,CAAC;QAEF,OAAO;YACL;gBACE,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC,kBAAkB,CAAC;gBAC/C,QAAQ,EAAE,mBAAmB,iFAAyC;aACvE;YACD;gBACE,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC,eAAe,CAAC;gBAC5C,QAAQ,EAAE,mBAAmB,mFAA0C;aACxE;YACD,EAAC,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,EAAC;YACtG;gBACE,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC,UAAU,CAAC;gBACvC,QAAQ,EAAE,mBAAmB,mFAA0C;aACxE;SACF,CAAC;IACJ,CAAC;IAED,kBAAkB;QAChB,QAAQ,IAAI,CAAC,WAAW,EAAE,CAAC;YACzB;gBACE,OAAO,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACjC;gBACE,OAAO,IAAI,CAAC,wBAAwB,EAAE,CAAC;YACzC;gBACE,OAAO,IAAI,CAAC,oBAAoB,EAAE,CAAC;YACrC;gBACE,OAAO,IAAI,CAAC,0BAA0B,EAAE,CAAC;QAC7C,CAAC;IACH,CAAC;IAED,wBAAwB;QACtB,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QACjD,mBAAmB;QACnB,OAAO,IAAI,CAAA;SACN,UAAU,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,UAAU;sBAC5C,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;YACzC,WAAW,EAAE,SAAS,CAAC,WAAW;YAClC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,KAAK;SAC3B,CAAC,CAAC;yBACc,IAAI,CAAC,cAAc;2BACjB,IAAI,CAAC,qBAAqB;2BAC1B,IAAI,CAAC,kBAAkB;yBACzB,IAAI,CAAC,oBAAoB;yBACzB,IAAI,CAAC,sBAAsB;;UAE1C,UAAU,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,UAAU;KAC9D,CAAC;QACF,kBAAkB;IACpB,CAAC;IAED,gBAAgB;QACd,mBAAmB;QACnB,OAAO,IAAI,CAAA;SACN,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,UAAU;2BACvB,IAAI,CAAC,qBAAqB;WAC1C,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,UAAU;KAC/C,CAAC;QACF,kBAAkB;IACpB,CAAC;IAED,oBAAoB;QAClB,mBAAmB;QACnB,OAAO,IAAI,CAAA;SACN,UAAU,CAAC,aAAa,CAAC,aAAa,CAAC,UAAU;gBAEhD;YACE,SAAS,EAAE,IAAI,CAAC,gBAAgB,EAAE,IAAI;YACtC,WAAW,EAAE,IAAI,CAAC,YAAY;YAC9B,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,2BAA2B,EAAE,IAAI,CAAC,UAAU;YAC5C,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,YAAY,EAAE,IAAI,CAAC,cAAc;YACjC,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,gBAAgB,EAAE,IAAI,CAAC,iBAAiB;YACxC,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;YACvC,aAAa,EAAE,IAAI,CAAC,cAAc;YAClC,iBAAiB,EAAE,IAAI,CAAC,sBAAsB;YAC9C,iBAAiB,EAAE,IAAI,CAAC,kBAAkB;YAC1C,mBAAmB,EAAE,IAAI,CAAC,mBAAmB;YAC7C,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;YACvC,mBAAmB,EAAE,IAAI,CAAC,cAAc;SAE5C;oCAC4B,IAAI,CAAC,2BAA2B;0BAC1C,IAAI,CAAC,iBAAiB;oCACZ,CAC1B,KAA+D,EAC/D,EAAE;YACF,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC5D,CAAC;6BACoB,IAAI,CAAC,oBAAoB;uBAC/B,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC;iCAC7B,IAAI,CAAC,4BAA4B,CAAC,IAAI,CAAC,IAAI,CAAC;mBAC1D,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC;sBAC7B,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC;yBAC/B,IAAI,CAAC,gBAAgB;4BAClB,IAAI,CAAC,mBAAmB;yBAC3B,IAAI,CAAC,gBAAgB;uBACvB,IAAI,CAAC,cAAc;uCACH,IAAI,CAAC,sBAAsB;wBAC1C,IAAI,CAAC,wBAAwB;WAC1C,UAAU,CAAC,aAAa,CAAC,aAAa,CAAC,UAAU;KACvD,CAAC;QACF,kBAAkB;IACpB,CAAC;IAED,0BAA0B;QACxB,mBAAmB;QACnB,OAAO,IAAI,CAAA;SACN,UAAU,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,UAAU;gBAE5D;YACE,gBAAgB,EAAE,IAAI,CAAC,iBAAiB;SAE5C;4BACoB,IAAI,CAAC,mBAAmB;8BACtB,IAAI,CAAC,qBAAqB;WAC7C,UAAU,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,UAAU;KACnE,CAAC;QACF,kBAAkB;IACpB,CAAC;IAED,oBAAoB,GAAG,GAA0B,EAAE;QACjD,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACjD,CAAC;QACD,OAAO,IAAI,CAAC,iBAAiB,CAAC;IAChC,CAAC,CAAC;IAEF,kBAAkB,CAAC,KAAY;QAC7B,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,kBAAkB,GAAG,CAAC,IAAI,CAAC,kBAAkB,CAAC;IACrD,CAAC;IAED,mBAAmB;QACjB,IAAI,CAAC,kBAAkB,GAAG,KAAK,CAAC;IAClC,CAAC;IAEkB,MAAM;QACvB,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;QACjD,MAAM,WAAW,GAAW,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC;QACzG,mBAAmB;QACnB,MAAM,MAAM,GAAG;YACb,UAAU,CAAC,MAAM,KAAK,CAAC;gBACrB,CAAC,CAAC;oBACE,KAAK,oCAAkB;oBACvB,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,YAAY,CAAC;oBACxC,QAAQ,EAAE,WAAW,uCAAqB;iBAC3C;gBACH,CAAC,CAAC;oBACE,KAAK,qDAA2B;oBAChC,IAAI,EAAE,GAAG,UAAU,CAAC,MAAM,IAAI,UAAU,CAAC,SAAS,CAAC,kBAAkB,CAAC,EAAE;oBACxE,QAAQ,EAAE,WAAW,wDAA8B;iBACpD;YACL,GAAG,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;gBAC9B,KAAK,EAAE,SAAS,CAAC,WAAW;gBAC5B,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,KAAK;gBAC1B,QAAQ,EAAE,WAAW,KAAK,SAAS,CAAC,WAAW;aAChD,CAAC,CAAC;SACJ,CAAC;QAEF,OAAO,IAAI,CAAA;;sCAEuB,aAAa,CAAC,OAAO,EAAE;eAC9C,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;uBACxB,IAAI,CAAC,qBAAqB;sBAEjC;YACE,OAAO,gDAAgC;YACvC,QAAQ,EAAE,MAAM;YAChB,QAAQ,EACN,IAAI,CAAC,YAAY,CAAC,SAAS;gBAC3B,IAAI,CAAC,WAAW;gBAChB,IAAI,CAAC,UAAU;YACjB,KAAK,EAAE,MAAM,CAAC,OAAO,CAAC,oBAAoB,CACxC,UAAU,CAAC,SAAS,CAAC,eAAe,CAAC,oFAEtC;YACD,YAAY,mFAA0C;SAE1D;iBACG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;;;0BAIjC,UAAU,CAAC,MAAM,KAAK,CAAC;YACvB,IAAI,CAAC,YAAY,CAAC,SAAS;YAC3B,IAAI,CAAC,WAAW;YAChB,IAAI,CAAC,UACP;uBACS,CAAC,CAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,EAAE;wBAChC,IAAI,CAAC,oBAAoB;sBAC3B,aAAa,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,EAAC,MAAM,EAAE,IAAI,EAAC,CAAC;;gBAEhE,OAAO,CAAC,UAAU,CAAC,MAAM,CACzB,MAAM,EACN,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,EAClB,IAAI,CAAC,EAAE;YACL,OAAO,IAAI,CAAA,qBAAqB,IAAI,CAAC,QAAQ,UAAU,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,WAAW,CAAC;QAC5F,CAAC,CACF;;;eAGA,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;uBACxB,IAAI,CAAC,kBAAkB;sBAE9B;YACE,OAAO,gDAAgC;YACvC,QAAQ,EAAE,QAAQ;YAClB,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC,eAAe,CAAC;YAC5C,YAAY,EAAE,kBAAkB;SAEpC;iBACG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;eAClC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;;uBAExB,IAAI,CAAC,kBAAkB;0BACpB,gBAAgB,CAAC,UAAU,CAAC,oBAAoB,CAC1D,IAAI,CAAC,EAAE;YACL,IAAI,CAAC,iBAAiB,GAAG,IAA6B,CAAC;QACzD,CAAC,CACF;sBAEC;YACE,OAAO,gDAAgC;YACvC,QAAQ,EAAE,UAAU;YACpB,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC,eAAe,CAAC;YAC5C,QAAQ,EAAE,CAAC,IAAI,CAAC,gBAAgB;SAEpC;sBACQ,aAAa,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC,KAAK,CAAC,EAAC,KAAK,EAAE,IAAI,EAAC,CAAC;iBACpE,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;eAClC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU;kCACP,IAAI,CAAC,mBAAmB;kCACxB,IAAI,CAAC,uBAAuB;wBACtC,IAAI,CAAC,oBAAoB;6BACpB,KAAK;kCACA,KAAK;+BACR,KAAK;sBACd,IAAI,CAAC,kBAAkB;;iBAE5B,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,UAAU,UAAU,CAC9D,SAAS,CAAC,MAAM,CACjB;kBACa,OAAO,CAAC,UAAU,CAAC,MAAM,CACzB,IAAI,CAAC,kBAAkB,EACvB,SAAS,CAAC,EAAE;YACV,OAAO,IAAI,CAAA;uBAET,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,UACtB,WAAW,SAAS,CAAC,KAAK,EAAE;8BAClB,aAAa,CAAC,IAAI,CAAC,aAAa,QAAQ,CAAC,eAAe,CAAC,WAAW,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,EAAC,KAAK,EAAE,IAAI,EAAC,CAAC;wBACrH,SAAS,CAAC,aAAa,EAAE;wBACzB,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU;mBACnC,CAAC;QACF,CAAC,CACF;kBACC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU;iBAChC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU,UAAU,UAAU,CAC9D,SAAS,CAAC,mBAAmB,CAC9B;kBACa,OAAO,CAAC,UAAU,CAAC,MAAM,CACzB,IAAI,CAAC,mBAAmB,EACxB,SAAS,CAAC,EAAE;YACV,OAAO,IAAI,CAAA;uBAET,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,UACtB,WAAW,SAAS,CAAC,KAAK,EAAE;8BAClB,aAAa,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,KAAK,CAAC,EAAC,KAAK,EAAE,IAAI,EAAC,CAAC;sBACtE,SAAS,CAAC,aAAa,EAAE;wBACvB,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU;mBACnC,CAAC;QACF,CAAC,CACF;mBAEC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,UACtB,WAAW,wBAAwB;oBAC/B,UAAU,CAAC,SAAS,CAAC,aAAa,CAAC;oBACnC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU;kBAChC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,UAAU;gBACjC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU;eAC3B,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;uBACxB,IAAI,CAAC,kBAAkB;sBAE9B;YACE,OAAO,gDAAgC;YACvC,QAAQ,EAAE,KAAK;YACf,QAAQ,EACN,CAAC,IAAI,CAAC,gBAAgB;gBACtB,IAAI,CAAC,YAAY,CAAC,SAAS;gBAC3B,IAAI,CAAC,WAAW;gBAChB,IAAI,CAAC,UAAU;YACjB,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC,eAAe,CAAC;YAC5C,YAAY,EAAE,kBAAkB;SAEpC;iBACG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;;eAElC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;uBACxB,GAAG,EAAE,CAAC,IAAI,CAAC,eAAe,EAAE,QAAQ,EAAE;sBAE7C;YACE,OAAO,gEAAwC;YAC/C,QAAQ,EAAE,QAAQ;YAClB,QAAQ,EACN,CAAC,IAAI,CAAC,eAAe;gBACrB,CAAC,IAAI,CAAC,YAAY,CAAC,oBAAoB;YACzC,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC,cAAc,CAAC;YAC3C,YAAY,EAAE,iBAAiB;SAEnC;iBACG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;eAClC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;uBACxB,GAAG,EAAE,CAAC,IAAI,CAAC,eAAe,EAAE,QAAQ,EAAE;sBAE7C;YACE,OAAO,gDAAgC;YACvC,QAAQ,EAAE,WAAW;YACrB,QAAQ,EACN,CAAC,IAAI,CAAC,eAAe;gBACrB,CAAC,IAAI,CAAC,YAAY,CAAC,oBAAoB;YACzC,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC,cAAc,CAAC;YAC3C,YAAY,EAAE,WAAW;SAE7B;iBACG,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;;4CAGjC,UAAU,CAAC,SAAS,CAAC,YACvB,UAAU,aAAa,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,EAAC,KAAK,EAAE,IAAI,EAAC,CAAC,IAAI,UAAU,CAAC,SAAS,CAAC,YAAY,CAAC;;;eAGlG,OAAO,CAAC,cAAc,CAAC,cAAc,CAAC,UAAU;sBAE/C;YACE,SAAS,EAAE,IAAI,CAAC,iBAAiB,EAAE;SAEvC,UAAU,aAAa,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,KAAK,CAAC,EAAC,KAAK,EAAE,IAAI,EAAC,CAAC;iBAClE,OAAO,CAAC,cAAc,CAAC,cAAc,CAAC,UAAU;;YAGrD,IAAI,CAAC,WAAW;YACd,CAAC,CAAC,IAAI,CAAA,oCACF,IAAI,CAAC,WAAW,CAAC,OACnB,QAAQ;YACV,CAAC,CAAC,EACN;YACE,IAAI,CAAC,kBAAkB,EAAE;;OAE9B,CAAC;QACJ,kBAAkB;IACpB,CAAC;;AAjtCwB;IAAxB,KAAK,EAAE;mEAAoF;AACnE;IAAxB,KAAK,EAAE;4DAA6D;AAC5C;IAAxB,KAAK,EAAE;uDAAkD;AACjC;IAAxB,KAAK,EAAE;0DAAwC;AAKvB;IAAxB,KAAK,EAAE;uDAAsC;AACrB;IAAxB,KAAK,EAAE;sDAAqC;AAKpB;IAAxB,KAAK,EAAE;2DAA0E;AACzD;IAAxB,KAAK,EAAE;4DAAwE;AAGvD;IAAxB,KAAK,EAAE;uDAAoC;AACnB;IAAxB,KAAK,EAAE;wDAAsC;AAGrB;IAAxB,KAAK,EAAE;oDAAqD;AACpC;IAAxB,KAAK,EAAE;oDAAuE;AAEtD;IAAxB,KAAK,EAAE;uDAAqC;AAEpB;IAAxB,KAAK,EAAE;8DAA6C;AAM5B;IAAxB,KAAK,EAAE;+DAAuE;AACtD;IAAxB,KAAK,EAAE;4DAA2E;AAE1D;IAAxB,KAAK,EAAE;0DAAwF;AAvCrF,kBAAkB;IAD9B,aAAa,CAAC,8BAA8B,CAAC;GACjC,kBAAkB,CAqtC9B","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as Host from '../../core/host/host.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as Bindings from '../../models/bindings/bindings.js';\nimport * as PublicExtensions from '../../models/extensions/extensions.js';\nimport type * as TraceEngine from '../../models/trace/trace.js';\nimport * as Emulation from '../../panels/emulation/emulation.js';\nimport * as Timeline from '../../panels/timeline/timeline.js';\nimport * as Tracing from '../../services/tracing/tracing.js';\nimport * as Buttons from '../../ui/components/buttons/buttons.js';\nimport * as Dialogs from '../../ui/components/dialogs/dialogs.js';\nimport * as ComponentHelpers from '../../ui/components/helpers/helpers.js';\nimport * as Menus from '../../ui/components/menus/menus.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as LitHtml from '../../ui/lit-html/lit-html.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport * as Components from './components/components.js';\nimport {type AddBreakpointEvent, type RemoveBreakpointEvent} from './components/StepView.js';\nimport type * as Controllers from './controllers/controllers.js';\nimport * as Converters from './converters/converters.js';\nimport * as Extensions from './extensions/extensions.js';\nimport * as Models from './models/models.js';\nimport * as Actions from './recorder-actions/recorder-actions.js';\nimport recorderControllerStyles from './recorderController.css.js';\nimport * as Events from './RecorderEvents.js';\n\nconst {html, Decorators, LitElement} = LitHtml;\nconst {customElement, state} = Decorators;\n\nconst UIStrings = {\n /**\n * @description The title of the button that leads to a page for creating a new recording.\n */\n createRecording: 'Create a new recording',\n /**\n * @description The title of the button that allows importing a recording.\n */\n importRecording: 'Import recording',\n /**\n * @description The title of the button that deletes the recording\n */\n deleteRecording: 'Delete recording',\n /**\n * @description The title of the select if user has no saved recordings\n */\n noRecordings: 'No recordings',\n /**\n * @description The title of the select option for one or more recording\n * number followed by this text - `1 recording(s)` or `4 recording(s)`\n */\n numberOfRecordings: 'recording(s)',\n /**\n * @description The title of the button that continues the replay\n */\n continueReplay: 'Continue',\n /**\n * @description The title of the button that executes only one step in the replay\n */\n stepOverReplay: 'Execute one step',\n /**\n * @description The title of the button that opens a menu with various options of exporting a recording to file.\n */\n exportRecording: 'Export',\n /**\n * @description The title of shortcut for starting and stopping recording.\n */\n startStopRecording: 'Start/Stop recording',\n /**\n * @description The title of shortcut for replaying recording.\n */\n replayRecording: 'Replay recording',\n /**\n * @description The title of shortcut for copying a recording or selected step.\n */\n copyShortcut: 'Copy recording or selected step',\n /**\n * @description The title of shortcut for toggling code view.\n */\n toggleCode: 'Toggle code view',\n /**\n * @description The title of the menu group in the export menu of the Recorder\n * panel that is followed by the list of built-in export formats.\n */\n export: 'Export',\n /**\n * @description The title of the menu group in the export menu of the Recorder\n * panel that is followed by the list of export formats available via browser\n * extensions.\n */\n exportViaExtensions: 'Export via extensions',\n /**\n * @description The title of the menu option that leads to a page that lists\n * all browsers extensions available for Recorder.\n */\n getExtensions: 'Get extensions…',\n /**\n * @description The button label that leads to the feedback form for Recorder.\n */\n sendFeedback: 'Send feedback',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/recorder/RecorderController.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nconst GET_EXTENSIONS_MENU_ITEM = 'get-extensions-link';\nconst GET_EXTENSIONS_URL = 'https://goo.gle/recorder-extension-list' as Platform.DevToolsPath.UrlString;\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-recorder-controller': RecorderController;\n }\n\n interface FileSystemWritableFileStream extends WritableStream {\n write(data: unknown): Promise;\n close(): Promise;\n }\n\n interface FileSystemHandle {\n createWritable(): Promise;\n }\n\n interface Window {\n showSaveFilePicker(opts: unknown): Promise;\n }\n}\n\ninterface StoredRecording {\n storageName: string;\n flow: Models.Schema.UserFlow;\n}\n\ninterface SetCurrentRecordingOptions {\n /**\n * Whether to keep breakpoints in the recording.\n */\n keepBreakpoints: boolean;\n /**\n * Whether to upstream the recording to a recording session if it exists.\n */\n updateSession: boolean;\n}\n\nexport const enum Pages {\n START_PAGE = 'StartPage',\n ALL_RECORDINGS_PAGE = 'AllRecordingsPage',\n CREATE_RECORDING_PAGE = 'CreateRecordingPage',\n RECORDING_PAGE = 'RecordingPage',\n}\n\nconst CONVERTER_ID_TO_METRIC: Record = {\n [Models.ConverterIds.ConverterIds.JSON]: Host.UserMetrics.RecordingExported.TO_JSON,\n [Models.ConverterIds.ConverterIds.REPLAY]: Host.UserMetrics.RecordingExported.TO_PUPPETEER_REPLAY,\n [Models.ConverterIds.ConverterIds.PUPPETEER]: Host.UserMetrics.RecordingExported.TO_PUPPETEER,\n [Models.ConverterIds.ConverterIds.PUPPETEER_FIREFOX]: Host.UserMetrics.RecordingExported.TO_PUPPETEER,\n [Models.ConverterIds.ConverterIds.LIGHTHOUSE]: Host.UserMetrics.RecordingExported.TO_LIGHTHOUSE,\n};\n\n@customElement('devtools-recorder-controller')\nexport class RecorderController extends LitElement {\n static override readonly styles = [recorderControllerStyles];\n\n @state() declare private currentRecordingSession?: Models.RecordingSession.RecordingSession;\n @state() declare private currentRecording: StoredRecording|undefined;\n @state() declare private currentStep?: Models.Schema.Step;\n @state() declare private recordingError?: Error;\n\n #storage = Models.RecordingStorage.RecordingStorage.instance();\n #screenshotStorage = Models.ScreenshotStorage.ScreenshotStorage.instance();\n\n @state() declare private isRecording: boolean;\n @state() declare private isToggling: boolean;\n\n // TODO: we keep the functionality to allow/disallow replay but right now it's not used.\n // It can be used to decide if we allow replay on a certain target for example.\n #replayAllowed = true;\n @state() declare private recordingPlayer?: Models.RecordingPlayer.RecordingPlayer;\n @state() declare private lastReplayResult?: Models.RecordingPlayer.ReplayResult;\n readonly #replayState: Components.RecordingView.ReplayState = {isPlaying: false, isPausedOnBreakpoint: false};\n\n @state() declare private currentPage: Pages;\n @state() declare private previousPage?: Pages;\n #fileSelector?: HTMLInputElement;\n\n @state() declare private sections?: Models.Section.Section[];\n @state() declare private settings?: Models.RecordingSettings.RecordingSettings;\n\n @state() declare private importError?: Error;\n\n @state() declare private exportMenuExpanded: boolean;\n #exportMenuButton: Buttons.Button.Button|undefined;\n\n #stepBreakpointIndexes: Set = new Set();\n\n #builtInConverters: Readonly;\n @state() declare private extensionConverters: Converters.Converter.Converter[];\n @state() declare private replayExtensions: Extensions.ExtensionManager.Extension[];\n\n @state() declare private viewDescriptor?: PublicExtensions.RecorderPluginManager.ViewDescriptor;\n\n #recorderSettings = new Models.RecorderSettings.RecorderSettings();\n #shortcutHelper = new Models.RecorderShortcutHelper.RecorderShortcutHelper();\n\n constructor() {\n super();\n\n this.isRecording = false;\n this.isToggling = false;\n this.exportMenuExpanded = false;\n\n this.currentPage = Pages.START_PAGE;\n if (this.#storage.getRecordings().length) {\n this.#setCurrentPage(Pages.ALL_RECORDINGS_PAGE);\n }\n\n const textEditorIndent = Common.Settings.Settings.instance().moduleSetting('text-editor-indent').get();\n this.#builtInConverters = Object.freeze([\n new Converters.JSONConverter.JSONConverter(textEditorIndent),\n new Converters.PuppeteerReplayConverter.PuppeteerReplayConverter(textEditorIndent),\n new Converters.PuppeteerConverter.PuppeteerConverter(textEditorIndent),\n new Converters.PuppeteerFirefoxConverter.PuppeteerFirefoxConverter(textEditorIndent),\n new Converters.LighthouseConverter.LighthouseConverter(textEditorIndent),\n ]);\n\n const extensionManager = Extensions.ExtensionManager.ExtensionManager.instance();\n this.#updateExtensions(extensionManager.extensions());\n extensionManager.addEventListener(Extensions.ExtensionManager.Events.EXTENSIONS_UPDATED, event => {\n this.#updateExtensions(event.data);\n });\n\n // used in e2e tests only.\n this.addEventListener('setrecording', (event: Event) => this.#onSetRecording(event));\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n\n if (this.currentRecordingSession) {\n void this.currentRecordingSession.stop();\n }\n }\n\n #updateExtensions(extensions: Extensions.ExtensionManager.Extension[]): void {\n this.extensionConverters =\n extensions.filter(extension => extension.getCapabilities().includes('export')).map((extension, idx) => {\n return new Converters.ExtensionConverter.ExtensionConverter(idx, extension);\n });\n this.replayExtensions = extensions.filter(extension => extension.getCapabilities().includes('replay'));\n }\n\n setIsRecordingStateForTesting(isRecording: boolean): void {\n this.isRecording = isRecording;\n }\n\n setRecordingStateForTesting(state: Components.RecordingView.ReplayState): void {\n this.#replayState.isPlaying = state.isPlaying;\n this.#replayState.isPausedOnBreakpoint = state.isPausedOnBreakpoint;\n }\n\n setCurrentPageForTesting(page: Pages): void {\n this.#setCurrentPage(page);\n }\n\n getCurrentPageForTesting(): Pages {\n return this.currentPage;\n }\n\n getCurrentRecordingForTesting(): StoredRecording|undefined {\n return this.currentRecording;\n }\n\n getStepBreakpointIndexesForTesting(): number[] {\n return [...this.#stepBreakpointIndexes.values()];\n }\n\n /**\n * We should clear errors on every new action in the controller.\n * TODO: think how to make handle this centrally so that in no case\n * the error remains shown for longer than needed. Maybe a timer?\n */\n #clearError(): void {\n this.importError = undefined;\n }\n\n async #importFile(file: File): Promise {\n const outputStream = new Common.StringOutputStream.StringOutputStream();\n const reader = new Bindings.FileUtils.ChunkedFileReader(\n file,\n /* chunkSize */ 10000000);\n const success = await reader.read(outputStream);\n if (!success) {\n throw reader.error();\n }\n\n let flow: Models.Schema.UserFlow|undefined;\n try {\n flow = Models.SchemaUtils.parse(JSON.parse(outputStream.data()));\n } catch (error) {\n this.importError = error;\n return;\n }\n this.#setCurrentRecording(await this.#storage.saveRecording(flow));\n this.#setCurrentPage(Pages.RECORDING_PAGE);\n this.#clearError();\n }\n\n setCurrentRecordingForTesting(recording: StoredRecording|undefined): void {\n this.#setCurrentRecording(recording);\n }\n\n getSectionsForTesting(): Array|undefined {\n return this.sections;\n }\n\n #setCurrentRecording(recording: StoredRecording|undefined, opts: Partial = {}): void {\n const {keepBreakpoints = false, updateSession = false} = opts;\n this.recordingPlayer?.abort();\n this.currentStep = undefined;\n this.recordingError = undefined;\n this.lastReplayResult = undefined;\n this.recordingPlayer = undefined;\n this.#replayState.isPlaying = false;\n this.#replayState.isPausedOnBreakpoint = false;\n this.#stepBreakpointIndexes = keepBreakpoints ? this.#stepBreakpointIndexes : new Set();\n\n if (recording) {\n this.currentRecording = recording;\n this.sections = Models.Section.buildSections(recording.flow.steps);\n this.settings = this.#buildSettings(recording.flow);\n if (updateSession && this.currentRecordingSession) {\n this.currentRecordingSession.overwriteUserFlow(recording.flow);\n }\n } else {\n this.currentRecording = undefined;\n this.sections = undefined;\n this.settings = undefined;\n }\n\n this.#updateScreenshotsForSections();\n }\n\n #setCurrentPage(page: Pages): void {\n if (page === this.currentPage) {\n return;\n }\n\n this.previousPage = this.currentPage;\n this.currentPage = page;\n }\n\n #buildSettings(flow: Models.Schema.UserFlow): Models.RecordingSettings.RecordingSettings {\n const steps = flow.steps;\n const navigateStepIdx = steps.findIndex(step => step.type === 'navigate');\n const settings: Models.RecordingSettings.RecordingSettings = {timeout: flow.timeout};\n for (let i = navigateStepIdx - 1; i >= 0; i--) {\n const step = steps[i];\n if (!settings.viewportSettings && step.type === 'setViewport') {\n settings.viewportSettings = step;\n }\n if (!settings.networkConditionsSettings && step.type === 'emulateNetworkConditions') {\n settings.networkConditionsSettings = {...step};\n for (const preset\n of [SDK.NetworkManager.OfflineConditions, SDK.NetworkManager.Slow3GConditions,\n SDK.NetworkManager.Slow4GConditions, SDK.NetworkManager.Fast4GConditions]) {\n // Using i18nTitleKey as a title here because we only want to compare the parameters of the network conditions.\n if (SDK.NetworkManager.networkConditionsEqual(\n {...preset, title: preset.i18nTitleKey || ''}, {...step, title: preset.i18nTitleKey || ''})) {\n settings.networkConditionsSettings.title = preset.title instanceof Function ? preset.title() : preset.title;\n settings.networkConditionsSettings.i18nTitleKey = preset.i18nTitleKey;\n }\n }\n }\n }\n return settings;\n }\n\n #getMainTarget(): SDK.Target.Target {\n const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n if (!target) {\n throw new Error('Missing main page target');\n }\n return target;\n }\n\n #getSectionFromStep(step: Models.Schema.Step): Models.Section.Section|null {\n if (!this.sections) {\n return null;\n }\n\n for (const section of this.sections) {\n if (section.steps.indexOf(step) !== -1) {\n return section;\n }\n }\n\n return null;\n }\n\n #updateScreenshotsForSections(): void {\n if (!this.sections || !this.currentRecording) {\n return;\n }\n const storageName = this.currentRecording.storageName;\n for (let i = 0; i < this.sections.length; i++) {\n const screenshot = this.#screenshotStorage.getScreenshotForSection(storageName, i);\n this.sections[i].screenshot = screenshot || undefined;\n }\n this.requestUpdate();\n }\n\n #onAbortReplay(): void {\n this.recordingPlayer?.abort();\n }\n\n async #onPlayViaExtension(extension: Extensions.ExtensionManager.Extension): Promise {\n if (!this.currentRecording || !this.#replayAllowed) {\n return;\n }\n const pluginManager = PublicExtensions.RecorderPluginManager.RecorderPluginManager.instance();\n const promise = pluginManager.once(PublicExtensions.RecorderPluginManager.Events.SHOW_VIEW_REQUESTED);\n extension.replay(this.currentRecording.flow);\n const descriptor = await promise;\n this.viewDescriptor = descriptor;\n Host.userMetrics.recordingReplayStarted(Host.UserMetrics.RecordingReplayStarted.REPLAY_VIA_EXTENSION);\n }\n\n async #onPlayRecording(event: Components.RecordingView.PlayRecordingEvent): Promise {\n if (!this.currentRecording || !this.#replayAllowed) {\n return;\n }\n if (this.viewDescriptor) {\n this.viewDescriptor = undefined;\n }\n if (event.data.extension) {\n return this.#onPlayViaExtension(event.data.extension);\n }\n Host.userMetrics.recordingReplayStarted(\n event.data.targetPanel !== Components.RecordingView.TargetPanel.DEFAULT ?\n Host.UserMetrics.RecordingReplayStarted.REPLAY_WITH_PERFORMANCE_TRACING :\n Host.UserMetrics.RecordingReplayStarted.REPLAY_ONLY);\n this.#replayState.isPlaying = true;\n this.currentStep = undefined;\n this.recordingError = undefined;\n this.lastReplayResult = undefined;\n const currentRecording = this.currentRecording;\n this.#clearError();\n\n await this.#disableDeviceModeIfEnabled();\n\n this.recordingPlayer = new Models.RecordingPlayer.RecordingPlayer(\n this.currentRecording.flow, {speed: event.data.speed, breakpointIndexes: this.#stepBreakpointIndexes});\n\n const withPerformanceTrace = event.data.targetPanel === Components.RecordingView.TargetPanel.PERFORMANCE_PANEL;\n const sectionsWithScreenshot = new Set();\n this.recordingPlayer.addEventListener(Models.RecordingPlayer.Events.STEP, async ({data: {step, resolve}}) => {\n this.currentStep = step;\n const currentSection = this.#getSectionFromStep(step);\n if (this.sections && currentSection && !sectionsWithScreenshot.has(currentSection)) {\n sectionsWithScreenshot.add(currentSection);\n const currentSectionIndex = this.sections.indexOf(currentSection);\n const screenshot = await Models.ScreenshotUtils.takeScreenshot();\n currentSection.screenshot = screenshot;\n Models.ScreenshotStorage.ScreenshotStorage.instance().storeScreenshotForSection(\n currentRecording.storageName, currentSectionIndex, screenshot);\n }\n resolve();\n });\n\n this.recordingPlayer.addEventListener(Models.RecordingPlayer.Events.STOP, () => {\n this.#replayState.isPausedOnBreakpoint = true;\n this.requestUpdate();\n });\n\n this.recordingPlayer.addEventListener(Models.RecordingPlayer.Events.CONTINUE, () => {\n this.#replayState.isPausedOnBreakpoint = false;\n this.requestUpdate();\n });\n\n this.recordingPlayer.addEventListener(Models.RecordingPlayer.Events.ERROR, ({data: error}) => {\n this.recordingError = error;\n if (!withPerformanceTrace) {\n this.#replayState.isPlaying = false;\n this.recordingPlayer = undefined;\n }\n this.lastReplayResult = Models.RecordingPlayer.ReplayResult.FAILURE;\n const errorMessage = error.message.toLowerCase();\n if (errorMessage.startsWith('could not find element')) {\n Host.userMetrics.recordingReplayFinished(Host.UserMetrics.RecordingReplayFinished.TIMEOUT_ERROR_SELECTORS);\n } else if (errorMessage.startsWith('waiting for target failed')) {\n Host.userMetrics.recordingReplayFinished(Host.UserMetrics.RecordingReplayFinished.TIMEOUT_ERROR_TARGET);\n } else {\n Host.userMetrics.recordingReplayFinished(Host.UserMetrics.RecordingReplayFinished.OTHER_ERROR);\n }\n });\n\n this.recordingPlayer.addEventListener(Models.RecordingPlayer.Events.DONE, () => {\n if (!withPerformanceTrace) {\n this.#replayState.isPlaying = false;\n this.recordingPlayer = undefined;\n }\n this.lastReplayResult = Models.RecordingPlayer.ReplayResult.SUCCESS;\n // Dispatch an event for e2e testing.\n this.dispatchEvent(new Events.ReplayFinishedEvent());\n Host.userMetrics.recordingReplayFinished(Host.UserMetrics.RecordingReplayFinished.SUCCESS);\n });\n\n this.recordingPlayer.addEventListener(Models.RecordingPlayer.Events.ABORT, () => {\n this.currentStep = undefined;\n this.recordingError = undefined;\n this.lastReplayResult = undefined;\n this.#replayState.isPlaying = false;\n });\n\n let resolveWithEvents = (_events: Object[]): void => {};\n const eventsPromise = new Promise((resolve): void => {\n resolveWithEvents = resolve;\n });\n\n let performanceTracing = null;\n switch (event.data?.targetPanel) {\n case Components.RecordingView.TargetPanel.PERFORMANCE_PANEL:\n performanceTracing = new Tracing.PerformanceTracing.PerformanceTracing(this.#getMainTarget(), {\n tracingBufferUsage(): void{},\n eventsRetrievalProgress(): void{},\n tracingComplete(events: Object[]): void {\n resolveWithEvents(events);\n },\n });\n break;\n }\n\n if (performanceTracing) {\n await performanceTracing.start();\n }\n\n this.#setTouchEmulationAllowed(false);\n await this.recordingPlayer.play();\n this.#setTouchEmulationAllowed(true);\n\n if (performanceTracing) {\n await performanceTracing.stop();\n const events = await eventsPromise;\n this.#replayState.isPlaying = false;\n this.recordingPlayer = undefined;\n await UI.InspectorView.InspectorView.instance().showPanel(event.data?.targetPanel as string);\n switch (event.data?.targetPanel) {\n case Components.RecordingView.TargetPanel.PERFORMANCE_PANEL:\n Timeline.TimelinePanel.TimelinePanel.instance().loadFromEvents(\n events as TraceEngine.Types.TraceEvents.TraceEventData[]);\n break;\n }\n }\n }\n\n async #disableDeviceModeIfEnabled(): Promise {\n try {\n const deviceModeWrapper = Emulation.DeviceModeWrapper.DeviceModeWrapper.instance();\n if (deviceModeWrapper.isDeviceModeOn()) {\n deviceModeWrapper.toggleDeviceMode();\n const emulationModel = this.#getMainTarget().model(SDK.EmulationModel.EmulationModel);\n await emulationModel?.emulateDevice(null);\n }\n } catch {\n // in the hosted mode, when the DeviceMode toolbar is not supported,\n // Emulation.DeviceModeWrapper.DeviceModeWrapper.instance throws an exception.\n }\n }\n\n #setTouchEmulationAllowed(touchEmulationAllowed: boolean): void {\n const emulationModel = this.#getMainTarget().model(SDK.EmulationModel.EmulationModel);\n emulationModel?.setTouchEmulationAllowed(touchEmulationAllowed);\n }\n\n async #onSetRecording(event: Event): Promise {\n const json = JSON.parse((event as CustomEvent).detail);\n this.#setCurrentRecording(await this.#storage.saveRecording(Models.SchemaUtils.parse(json)));\n this.#setCurrentPage(Pages.RECORDING_PAGE);\n this.#clearError();\n }\n\n // Used by e2e tests to inspect the current recording.\n getUserFlow(): Models.Schema.UserFlow|undefined {\n return this.currentRecording?.flow;\n }\n\n async #handleRecordingChanged(event: Components.StepView.StepChanged): Promise {\n if (!this.currentRecording) {\n throw new Error('Current recording expected to be defined.');\n }\n const recording = {\n ...this.currentRecording,\n flow: {\n ...this.currentRecording.flow,\n steps: this.currentRecording.flow.steps.map(step => step === event.currentStep ? event.newStep : step),\n },\n };\n this.#setCurrentRecording(\n await this.#storage.updateRecording(recording.storageName, recording.flow),\n {keepBreakpoints: true, updateSession: true});\n }\n\n async #handleStepAdded(event: Components.StepView.AddStep): Promise {\n if (!this.currentRecording) {\n throw new Error('Current recording expected to be defined.');\n }\n const stepOrSection = event.stepOrSection;\n let step;\n let position = event.position;\n if ('steps' in stepOrSection) {\n // section\n const sectionIdx = this.sections?.indexOf(stepOrSection);\n if (sectionIdx === undefined || sectionIdx === -1) {\n throw new Error('There is no section to add a step to');\n }\n if (event.position === Components.StepView.AddStepPosition.AFTER) {\n if (this.sections?.[sectionIdx].steps.length) {\n step = this.sections?.[sectionIdx].steps[0];\n position = Components.StepView.AddStepPosition.BEFORE;\n } else {\n step = this.sections?.[sectionIdx].causingStep;\n position = Components.StepView.AddStepPosition.AFTER;\n }\n } else {\n if (sectionIdx <= 0) {\n throw new Error('There is no section to add a step to');\n }\n const prevSection = this.sections?.[sectionIdx - 1];\n step = prevSection?.steps[prevSection.steps.length - 1];\n position = Components.StepView.AddStepPosition.AFTER;\n }\n } else {\n // step\n step = stepOrSection;\n }\n if (!step) {\n throw new Error('Anchor step is not found when adding a step');\n }\n const steps = this.currentRecording.flow.steps;\n const currentIndex = steps.indexOf(step);\n const indexToInsertAt = currentIndex + (position === Components.StepView.AddStepPosition.BEFORE ? 0 : 1);\n steps.splice(indexToInsertAt, 0, {type: Models.Schema.StepType.WaitForElement, selectors: ['body']});\n const recording = {...this.currentRecording, flow: {...this.currentRecording.flow, steps}};\n Host.userMetrics.recordingEdited(Host.UserMetrics.RecordingEdited.STEP_ADDED);\n this.#stepBreakpointIndexes = new Set([...this.#stepBreakpointIndexes.values()].map(breakpointIndex => {\n if (indexToInsertAt > breakpointIndex) {\n return breakpointIndex;\n }\n\n return breakpointIndex + 1;\n }));\n this.#setCurrentRecording(\n await this.#storage.updateRecording(recording.storageName, recording.flow),\n {keepBreakpoints: true, updateSession: true});\n }\n\n async #handleRecordingTitleChanged(event: Components.RecordingView.RecordingTitleChangedEvent): Promise {\n if (!this.currentRecording) {\n throw new Error('Current recording expected to be defined.');\n }\n\n const flow = {...this.currentRecording.flow, title: event.title};\n this.#setCurrentRecording(await this.#storage.updateRecording(this.currentRecording.storageName, flow));\n }\n\n async #handleStepRemoved(event: Components.StepView.RemoveStep): Promise {\n if (!this.currentRecording) {\n throw new Error('Current recording expected to be defined.');\n }\n\n const steps = this.currentRecording.flow.steps;\n const currentIndex = steps.indexOf(event.step);\n steps.splice(currentIndex, 1);\n const flow = {...this.currentRecording.flow, steps};\n Host.userMetrics.recordingEdited(Host.UserMetrics.RecordingEdited.STEP_REMOVED);\n this.#stepBreakpointIndexes = new Set([...this.#stepBreakpointIndexes.values()]\n .map(breakpointIndex => {\n if (currentIndex > breakpointIndex) {\n return breakpointIndex;\n }\n\n if (currentIndex === breakpointIndex) {\n return -1;\n }\n\n return breakpointIndex - 1;\n })\n .filter(index => index >= 0));\n this.#setCurrentRecording(\n await this.#storage.updateRecording(this.currentRecording.storageName, flow),\n {keepBreakpoints: true, updateSession: true});\n }\n\n async #onNetworkConditionsChanged(event: Components.RecordingView.NetworkConditionsChanged): Promise {\n if (!this.currentRecording) {\n throw new Error('Current recording expected to be defined.');\n }\n const navigateIdx = this.currentRecording.flow.steps.findIndex(step => step.type === 'navigate');\n if (navigateIdx === -1) {\n throw new Error('Current recording does not have a navigate step');\n }\n const emulateNetworkConditionsIdx = this.currentRecording.flow.steps.findIndex((step, idx) => {\n if (idx >= navigateIdx) {\n return false;\n }\n return step.type === 'emulateNetworkConditions';\n });\n if (!event.data) {\n // Delete step if present.\n if (emulateNetworkConditionsIdx !== -1) {\n this.currentRecording.flow.steps.splice(emulateNetworkConditionsIdx, 1);\n }\n } else if (emulateNetworkConditionsIdx === -1) {\n // Insert at the first position.\n this.currentRecording.flow.steps.splice(\n 0, 0,\n Models.SchemaUtils.createEmulateNetworkConditionsStep(\n {download: event.data.download, upload: event.data.upload, latency: event.data.latency}));\n } else {\n // Update existing step.\n const step =\n this.currentRecording.flow.steps[emulateNetworkConditionsIdx] as Models.Schema.EmulateNetworkConditionsStep;\n step.download = event.data.download;\n step.upload = event.data.upload;\n step.latency = event.data.latency;\n }\n this.#setCurrentRecording(\n await this.#storage.updateRecording(this.currentRecording.storageName, this.currentRecording.flow));\n }\n\n async #onTimeoutChanged(event: Components.RecordingView.TimeoutChanged): Promise {\n if (!this.currentRecording) {\n throw new Error('Current recording expected to be defined.');\n }\n this.currentRecording.flow.timeout = event.data;\n this.#setCurrentRecording(\n await this.#storage.updateRecording(this.currentRecording.storageName, this.currentRecording.flow));\n }\n\n async #onDeleteRecording(event: Event): Promise {\n event.stopPropagation();\n if (event instanceof Components.RecordingListView.DeleteRecordingEvent) {\n await this.#storage.deleteRecording(event.storageName);\n this.#screenshotStorage.deleteScreenshotsForRecording(event.storageName);\n this.requestUpdate();\n } else {\n if (!this.currentRecording) {\n return;\n }\n await this.#storage.deleteRecording(this.currentRecording.storageName);\n this.#screenshotStorage.deleteScreenshotsForRecording(this.currentRecording.storageName);\n }\n if ((await this.#storage.getRecordings()).length) {\n this.#setCurrentPage(Pages.ALL_RECORDINGS_PAGE);\n } else {\n this.#setCurrentPage(Pages.START_PAGE);\n }\n this.#setCurrentRecording(undefined);\n this.#clearError();\n }\n\n #onCreateNewRecording(event?: Event): void {\n event?.stopPropagation();\n this.#setCurrentPage(Pages.CREATE_RECORDING_PAGE);\n this.#clearError();\n }\n\n async #onRecordingStarted(event: Components.CreateRecordingView.RecordingStartedEvent): Promise {\n // Recording is not available in device mode.\n await this.#disableDeviceModeIfEnabled();\n\n // Setting up some variables to notify the user we are initializing a recording.\n this.isToggling = true;\n this.#clearError();\n\n // -- Recording logic starts here --\n Host.userMetrics.recordingToggled(Host.UserMetrics.RecordingToggled.RECORDING_STARTED);\n this.currentRecordingSession = new Models.RecordingSession.RecordingSession(this.#getMainTarget(), {\n title: event.name,\n selectorAttribute: event.selectorAttribute,\n selectorTypesToRecord: event.selectorTypesToRecord.length ? event.selectorTypesToRecord :\n Object.values(Models.Schema.SelectorType),\n });\n this.#setCurrentRecording(await this.#storage.saveRecording(this.currentRecordingSession.cloneUserFlow()));\n\n let previousSectionIndex = -1;\n let screenshotPromise:|Promise|undefined;\n const takeScreenshot = async(currentRecording: StoredRecording): Promise => {\n if (!this.sections) {\n throw new Error('Could not find sections.');\n }\n\n const currentSectionIndex = this.sections.length - 1;\n const currentSection = this.sections[currentSectionIndex];\n if (screenshotPromise || previousSectionIndex === currentSectionIndex) {\n return;\n }\n\n screenshotPromise = Models.ScreenshotUtils.takeScreenshot();\n const screenshot = await screenshotPromise;\n screenshotPromise = undefined;\n currentSection.screenshot = screenshot;\n Models.ScreenshotStorage.ScreenshotStorage.instance().storeScreenshotForSection(\n currentRecording.storageName, currentSectionIndex, screenshot);\n previousSectionIndex = currentSectionIndex;\n this.#updateScreenshotsForSections();\n };\n\n this.currentRecordingSession.addEventListener(\n Models.RecordingSession.Events.RECORDING_UPDATED, async ({data}: {data: Models.Schema.UserFlow}) => {\n if (!this.currentRecording) {\n throw new Error('No current recording found');\n }\n this.#setCurrentRecording(await this.#storage.updateRecording(this.currentRecording.storageName, data));\n const recordingView = this.shadowRoot?.querySelector('devtools-recording-view');\n recordingView?.scrollToBottom();\n\n await takeScreenshot(this.currentRecording);\n });\n\n this.currentRecordingSession.addEventListener(\n Models.RecordingSession.Events.RECORDING_STOPPED, async ({data}: {data: Models.Schema.UserFlow}) => {\n if (!this.currentRecording) {\n throw new Error('No current recording found');\n }\n Host.userMetrics.keyboardShortcutFired(Actions.RecorderActions.START_RECORDING);\n this.#setCurrentRecording(await this.#storage.updateRecording(this.currentRecording.storageName, data));\n await this.#onRecordingFinished();\n });\n\n await this.currentRecordingSession.start();\n // -- Recording logic ends here --\n\n // Setting up some variables to notify the user we are finished initialization.\n this.isToggling = false;\n this.isRecording = true;\n this.#setCurrentPage(Pages.RECORDING_PAGE);\n\n // Dispatch an event for e2e testing.\n this.dispatchEvent(new Events.RecordingStateChangedEvent((this.currentRecording as StoredRecording).flow));\n }\n\n async #onRecordingFinished(): Promise {\n if (!this.currentRecording || !this.currentRecordingSession) {\n throw new Error('Recording was never started');\n }\n\n // Setting up some variables to notify the user we are finalizing a recording.\n this.isToggling = true;\n this.#clearError();\n\n // -- Recording logic starts here --\n Host.userMetrics.recordingToggled(Host.UserMetrics.RecordingToggled.RECORDING_FINISHED);\n await this.currentRecordingSession.stop();\n this.currentRecordingSession = undefined;\n // -- Recording logic ends here --\n\n // Setting up some variables to notify the user we are finished finalizing.\n this.isToggling = false;\n this.isRecording = false;\n\n // Dispatch an event for e2e testing.\n this.dispatchEvent(new Events.RecordingStateChangedEvent(this.currentRecording.flow));\n }\n\n async #onRecordingCancelled(): Promise {\n if (this.previousPage) {\n this.#setCurrentPage(this.previousPage);\n }\n }\n\n async #onRecordingSelected(event: Event): Promise {\n const storageName = event instanceof Components.RecordingListView.OpenRecordingEvent ||\n event instanceof Components.RecordingListView.PlayRecordingEvent ?\n event.storageName :\n ((event as InputEvent).target as HTMLSelectElement)?.value;\n this.#setCurrentRecording(await this.#storage.getRecording(storageName));\n if (this.currentRecording) {\n this.#setCurrentPage(Pages.RECORDING_PAGE);\n } else if (storageName === Pages.START_PAGE) {\n this.#setCurrentPage(Pages.START_PAGE);\n } else if (storageName === Pages.ALL_RECORDINGS_PAGE) {\n this.#setCurrentPage(Pages.ALL_RECORDINGS_PAGE);\n }\n }\n\n async #onExportOptionSelected(event: Menus.SelectMenu.SelectMenuItemSelectedEvent): Promise {\n if (typeof event.itemValue !== 'string') {\n throw new Error('Invalid export option value');\n }\n if (event.itemValue === GET_EXTENSIONS_MENU_ITEM) {\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(GET_EXTENSIONS_URL);\n return;\n }\n if (!this.currentRecording) {\n throw new Error('No recording selected');\n }\n const id = event.itemValue;\n const byId = (converter: Converters.Converter.Converter): boolean => converter.getId() === id;\n const converter = this.#builtInConverters.find(byId) || this.extensionConverters.find(byId);\n if (!converter) {\n throw new Error('No recording selected');\n }\n const [content] = await converter.stringify(this.currentRecording.flow);\n await this.#exportContent(converter.getFilename(this.currentRecording.flow), content);\n const builtInMetric = CONVERTER_ID_TO_METRIC[converter.getId()];\n if (builtInMetric) {\n Host.userMetrics.recordingExported(builtInMetric);\n } else if (converter.getId().startsWith(Converters.ExtensionConverter.EXTENSION_PREFIX)) {\n Host.userMetrics.recordingExported(Host.UserMetrics.RecordingExported.TO_EXTENSION);\n } else {\n throw new Error('Could not find a metric for the export option with id = ' + id);\n }\n }\n\n async #exportContent(suggestedName: string, data: string): Promise {\n try {\n const handle = await window.showSaveFilePicker({suggestedName});\n const writable = await handle.createWritable();\n await writable.write(data);\n await writable.close();\n } catch (error) {\n // If the user aborts the action no need to report it, otherwise do.\n if (error.name === 'AbortError') {\n return;\n }\n\n throw error;\n }\n }\n\n async #handleAddAssertionEvent(): Promise {\n if (!this.currentRecordingSession || !this.currentRecording) {\n return;\n }\n const flow = this.currentRecordingSession.cloneUserFlow();\n flow.steps.push({type: 'waitForElement' as Models.Schema.StepType.WaitForElement, selectors: [['.cls']]});\n this.#setCurrentRecording(\n await this.#storage.updateRecording(this.currentRecording.storageName, flow),\n {keepBreakpoints: true, updateSession: true});\n Host.userMetrics.recordingAssertion(Host.UserMetrics.RecordingAssertion.ASSERTION_ADDED);\n await this.updateComplete;\n this.renderRoot.querySelector('devtools-recording-view')\n ?.shadowRoot?.querySelector('.section:last-child devtools-step-view:last-of-type')\n ?.shadowRoot?.querySelector('.action')\n ?.click();\n }\n\n #onImportRecording(event: Event): void {\n event.stopPropagation();\n this.#clearError();\n this.#fileSelector = UI.UIUtils.createFileSelectorElement(this.#importFile.bind(this));\n this.#fileSelector.click();\n }\n\n async #onPlayRecordingByName(event: Components.RecordingListView.PlayRecordingEvent): Promise {\n await this.#onRecordingSelected(event);\n await this.#onPlayRecording(new Components.RecordingView.PlayRecordingEvent(\n {targetPanel: Components.RecordingView.TargetPanel.DEFAULT, speed: this.#recorderSettings.speed}));\n }\n\n #onAddBreakpoint = (event: AddBreakpointEvent): void => {\n this.#stepBreakpointIndexes.add(event.index);\n this.recordingPlayer?.updateBreakpointIndexes(this.#stepBreakpointIndexes);\n this.requestUpdate();\n };\n\n #onRemoveBreakpoint = (event: RemoveBreakpointEvent): void => {\n this.#stepBreakpointIndexes.delete(event.index);\n this.recordingPlayer?.updateBreakpointIndexes(this.#stepBreakpointIndexes);\n this.requestUpdate();\n };\n\n #onExtensionViewClosed(): void {\n this.viewDescriptor = undefined;\n }\n\n handleActions(actionId: Actions.RecorderActions): void {\n if (!this.isActionPossible(actionId)) {\n return;\n }\n\n switch (actionId) {\n case Actions.RecorderActions.CREATE_RECORDING:\n this.#onCreateNewRecording();\n return;\n\n case Actions.RecorderActions.START_RECORDING:\n if (this.currentPage !== Pages.CREATE_RECORDING_PAGE && !this.isRecording) {\n this.#shortcutHelper.handleShortcut(this.#onRecordingStarted.bind(\n this,\n new Components.CreateRecordingView.RecordingStartedEvent(\n this.#recorderSettings.defaultTitle, this.#recorderSettings.defaultSelectors,\n this.#recorderSettings.selectorAttribute)));\n } else if (this.currentPage === Pages.CREATE_RECORDING_PAGE) {\n const view = this.renderRoot.querySelector('devtools-create-recording-view');\n if (view) {\n this.#shortcutHelper.handleShortcut(view.startRecording.bind(view));\n }\n } else if (this.isRecording) {\n void this.#onRecordingFinished();\n }\n return;\n\n case Actions.RecorderActions.REPLAY_RECORDING:\n void this.#onPlayRecording(new Components.RecordingView.PlayRecordingEvent(\n {targetPanel: Components.RecordingView.TargetPanel.DEFAULT, speed: this.#recorderSettings.speed}));\n return;\n\n case Actions.RecorderActions.TOGGLE_CODE_VIEW: {\n const view = this.renderRoot.querySelector('devtools-recording-view');\n if (view) {\n view.showCodeToggle();\n }\n return;\n }\n }\n }\n\n isActionPossible(actionId: Actions.RecorderActions): boolean {\n switch (actionId) {\n case Actions.RecorderActions.CREATE_RECORDING:\n return !this.isRecording && !this.#replayState.isPlaying;\n case Actions.RecorderActions.START_RECORDING:\n return !this.#replayState.isPlaying;\n case Actions.RecorderActions.REPLAY_RECORDING:\n return (this.currentPage === Pages.RECORDING_PAGE && !this.#replayState.isPlaying);\n case Actions.RecorderActions.TOGGLE_CODE_VIEW:\n return this.currentPage === Pages.RECORDING_PAGE;\n case Actions.RecorderActions.COPY_RECORDING_OR_STEP:\n // This action is handled in the RecordingView\n // It relies on browser `copy` event.\n return false;\n }\n }\n\n #getShortcutsInfo(): Dialogs.ShortcutDialog.Shortcut[] {\n const getBindingForAction = (action: Actions.RecorderActions): string[] => {\n const shortcuts = UI.ShortcutRegistry.ShortcutRegistry.instance().shortcutsForAction(action);\n\n return shortcuts.map(shortcut => shortcut.title());\n };\n\n return [\n {\n title: i18nString(UIStrings.startStopRecording),\n bindings: getBindingForAction(Actions.RecorderActions.START_RECORDING),\n },\n {\n title: i18nString(UIStrings.replayRecording),\n bindings: getBindingForAction(Actions.RecorderActions.REPLAY_RECORDING),\n },\n {title: i18nString(UIStrings.copyShortcut), bindings: [`${Host.Platform.isMac() ? '⌘ C' : 'Ctrl+C'}`]},\n {\n title: i18nString(UIStrings.toggleCode),\n bindings: getBindingForAction(Actions.RecorderActions.TOGGLE_CODE_VIEW),\n },\n ];\n }\n\n #renderCurrentPage(): LitHtml.TemplateResult {\n switch (this.currentPage) {\n case Pages.START_PAGE:\n return this.#renderStartPage();\n case Pages.ALL_RECORDINGS_PAGE:\n return this.#renderAllRecordingsPage();\n case Pages.RECORDING_PAGE:\n return this.#renderRecordingPage();\n case Pages.CREATE_RECORDING_PAGE:\n return this.#renderCreateRecordingPage();\n }\n }\n\n #renderAllRecordingsPage(): LitHtml.TemplateResult {\n const recordings = this.#storage.getRecordings();\n // clang-format off\n return html`\n <${Components.RecordingListView.RecordingListView.litTagName}\n .recordings=${recordings.map(recording => ({\n storageName: recording.storageName,\n name: recording.flow.title,\n }))}\n .replayAllowed=${this.#replayAllowed}\n @createrecording=${this.#onCreateNewRecording}\n @deleterecording=${this.#onDeleteRecording}\n @openrecording=${this.#onRecordingSelected}\n @playrecording=${this.#onPlayRecordingByName}\n >\n \n `;\n // clang-format on\n }\n\n #renderStartPage(): LitHtml.TemplateResult {\n // clang-format off\n return html`\n <${Components.StartView.StartView.litTagName}\n @createrecording=${this.#onCreateNewRecording}\n >\n `;\n // clang-format on\n }\n\n #renderRecordingPage(): LitHtml.TemplateResult {\n // clang-format off\n return html`\n <${Components.RecordingView.RecordingView.litTagName}\n .data=${\n {\n recording: this.currentRecording?.flow,\n replayState: this.#replayState,\n isRecording: this.isRecording,\n recordingTogglingInProgress: this.isToggling,\n currentStep: this.currentStep,\n currentError: this.recordingError,\n sections: this.sections,\n settings: this.settings,\n recorderSettings: this.#recorderSettings,\n lastReplayResult: this.lastReplayResult,\n replayAllowed: this.#replayAllowed,\n breakpointIndexes: this.#stepBreakpointIndexes,\n builtInConverters: this.#builtInConverters,\n extensionConverters: this.extensionConverters,\n replayExtensions: this.replayExtensions,\n extensionDescriptor: this.viewDescriptor,\n } as Components.RecordingView.RecordingViewData\n }\n @networkconditionschanged=${this.#onNetworkConditionsChanged}\n @timeoutchanged=${this.#onTimeoutChanged}\n @requestselectorattribute=${(\n event: Controllers.SelectorPicker.RequestSelectorAttributeEvent,\n ) => {\n event.send(this.currentRecording?.flow.selectorAttribute);\n }}\n @recordingfinished=${this.#onRecordingFinished}\n @stepchanged=${this.#handleRecordingChanged.bind(this)}\n @recordingtitlechanged=${this.#handleRecordingTitleChanged.bind(this)}\n @addstep=${this.#handleStepAdded.bind(this)}\n @removestep=${this.#handleStepRemoved.bind(this)}\n @addbreakpoint=${this.#onAddBreakpoint}\n @removebreakpoint=${this.#onRemoveBreakpoint}\n @playrecording=${this.#onPlayRecording}\n @abortreplay=${this.#onAbortReplay}\n @recorderextensionviewclosed=${this.#onExtensionViewClosed}\n @addassertion=${this.#handleAddAssertionEvent}\n >\n `;\n // clang-format on\n }\n\n #renderCreateRecordingPage(): LitHtml.TemplateResult {\n // clang-format off\n return html`\n <${Components.CreateRecordingView.CreateRecordingView.litTagName}\n .data=${\n {\n recorderSettings: this.#recorderSettings,\n } as Components.CreateRecordingView.CreateRecordingViewData\n }\n @recordingstarted=${this.#onRecordingStarted}\n @recordingcancelled=${this.#onRecordingCancelled}\n >\n `;\n // clang-format on\n }\n\n #getExportMenuButton = (): Buttons.Button.Button => {\n if (!this.#exportMenuButton) {\n throw new Error('#exportMenuButton not found');\n }\n return this.#exportMenuButton;\n };\n\n #onExportRecording(event: Event): void {\n event.stopPropagation();\n this.#clearError();\n this.exportMenuExpanded = !this.exportMenuExpanded;\n }\n\n #onExportMenuClosed(): void {\n this.exportMenuExpanded = false;\n }\n\n protected override render(): LitHtml.TemplateResult {\n const recordings = this.#storage.getRecordings();\n const selectValue: string = this.currentRecording ? this.currentRecording.storageName : this.currentPage;\n // clang-format off\n const values = [\n recordings.length === 0\n ? {\n value: Pages.START_PAGE,\n name: i18nString(UIStrings.noRecordings),\n selected: selectValue === Pages.START_PAGE,\n }\n : {\n value: Pages.ALL_RECORDINGS_PAGE,\n name: `${recordings.length} ${i18nString(UIStrings.numberOfRecordings)}`,\n selected: selectValue === Pages.ALL_RECORDINGS_PAGE,\n },\n ...recordings.map(recording => ({\n value: recording.storageName,\n name: recording.flow.title,\n selected: selectValue === recording.storageName,\n })),\n ];\n\n return html`\n
\n
\n <${Buttons.Button.Button.litTagName}\n @click=${this.#onCreateNewRecording}\n .data=${\n {\n variant: Buttons.Button.Variant.TOOLBAR,\n iconName: 'plus',\n disabled:\n this.#replayState.isPlaying ||\n this.isRecording ||\n this.isToggling,\n title: Models.Tooltip.getTooltipForActions(\n i18nString(UIStrings.createRecording),\n Actions.RecorderActions.CREATE_RECORDING,\n ),\n jslogContext: Actions.RecorderActions.CREATE_RECORDING,\n } as Buttons.Button.ButtonData\n }\n >\n
\n e.stopPropagation()}\n @change=${this.#onRecordingSelected}\n jslog=${VisualLogging.dropDown('recordings').track({change: true})}\n >\n ${LitHtml.Directives.repeat(\n values,\n item => item.value,\n item => {\n return html``;\n },\n )}\n \n
\n <${Buttons.Button.Button.litTagName}\n @click=${this.#onImportRecording}\n .data=${\n {\n variant: Buttons.Button.Variant.TOOLBAR,\n iconName: 'import',\n title: i18nString(UIStrings.importRecording),\n jslogContext: 'import-recording',\n } as Buttons.Button.ButtonData\n }\n >\n <${Buttons.Button.Button.litTagName}\n id='origin'\n @click=${this.#onExportRecording}\n on-render=${ComponentHelpers.Directives.nodeRenderedCallback(\n node => {\n this.#exportMenuButton = node as Buttons.Button.Button;\n },\n )}\n .data=${\n {\n variant: Buttons.Button.Variant.TOOLBAR,\n iconName: 'download',\n title: i18nString(UIStrings.exportRecording),\n disabled: !this.currentRecording,\n } as Buttons.Button.ButtonData\n }\n jslog=${VisualLogging.dropDown('export-recording').track({click: true})}\n >\n <${Menus.Menu.Menu.litTagName}\n @menucloserequest=${this.#onExportMenuClosed}\n @menuitemselected=${this.#onExportOptionSelected}\n .origin=${this.#getExportMenuButton}\n .showDivider=${false}\n .showSelectedItem=${false}\n .showConnector=${false}\n .open=${this.exportMenuExpanded}\n >\n <${Menus.Menu.MenuGroup.litTagName} .name=${i18nString(\n UIStrings.export,\n )}>\n ${LitHtml.Directives.repeat(\n this.#builtInConverters,\n converter => {\n return html`\n <${\n Menus.Menu.MenuItem.litTagName\n } .value=${converter.getId()}\n jslog=${VisualLogging.item(`converter-${Platform.StringUtilities.toKebabCase(converter.getId())}`).track({click: true})}>\n ${converter.getFormatName()}\n \n `;\n },\n )}\n \n <${Menus.Menu.MenuGroup.litTagName} .name=${i18nString(\n UIStrings.exportViaExtensions,\n )}>\n ${LitHtml.Directives.repeat(\n this.extensionConverters,\n converter => {\n return html`\n <${\n Menus.Menu.MenuItem.litTagName\n } .value=${converter.getId()}\n jslog=${VisualLogging.item('converter-extension').track({click: true})}>\n ${converter.getFormatName()}\n \n `;\n },\n )}\n <${\n Menus.Menu.MenuItem.litTagName\n } .value=${GET_EXTENSIONS_MENU_ITEM}>\n ${i18nString(UIStrings.getExtensions)}\n \n \n \n <${Buttons.Button.Button.litTagName}\n @click=${this.#onDeleteRecording}\n .data=${\n {\n variant: Buttons.Button.Variant.TOOLBAR,\n iconName: 'bin',\n disabled:\n !this.currentRecording ||\n this.#replayState.isPlaying ||\n this.isRecording ||\n this.isToggling,\n title: i18nString(UIStrings.deleteRecording),\n jslogContext: 'delete-recording',\n } as Buttons.Button.ButtonData\n }\n >\n
\n <${Buttons.Button.Button.litTagName}\n @click=${() => this.recordingPlayer?.continue()}\n .data=${\n {\n variant: Buttons.Button.Variant.PRIMARY_TOOLBAR,\n iconName: 'resume',\n disabled:\n !this.recordingPlayer ||\n !this.#replayState.isPausedOnBreakpoint,\n title: i18nString(UIStrings.continueReplay),\n jslogContext: 'continue-replay',\n } as Buttons.Button.ButtonData\n }\n >\n <${Buttons.Button.Button.litTagName}\n @click=${() => this.recordingPlayer?.stepOver()}\n .data=${\n {\n variant: Buttons.Button.Variant.TOOLBAR,\n iconName: 'step-over',\n disabled:\n !this.recordingPlayer ||\n !this.#replayState.isPausedOnBreakpoint,\n title: i18nString(UIStrings.stepOverReplay),\n jslogContext: 'step-over',\n } as Buttons.Button.ButtonData\n }\n >\n
\n ${i18nString(UIStrings.sendFeedback)}\n
\n
\n <${Dialogs.ShortcutDialog.ShortcutDialog.litTagName}\n .data=${\n {\n shortcuts: this.#getShortcutsInfo(),\n } as Dialogs.ShortcutDialog.ShortcutDialogData\n } jslog=${VisualLogging.action('show-shortcuts').track({click: true})}\n >\n
\n ${\n this.importError\n ? html`
Import error: ${\n this.importError.message\n }
`\n : ''\n }\n ${this.#renderCurrentPage()}\n
\n `;\n // clang-format on\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"RecorderController.js","sourceRoot":"","sources":["../../../../../../front_end/panels/recorder/RecorderController.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as Host from '../../core/host/host.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as Bindings from '../../models/bindings/bindings.js';\nimport * as PublicExtensions from '../../models/extensions/extensions.js';\nimport type * as Trace from '../../models/trace/trace.js';\nimport * as Emulation from '../../panels/emulation/emulation.js';\nimport * as Timeline from '../../panels/timeline/timeline.js';\nimport * as Tracing from '../../services/tracing/tracing.js';\nimport * as Buttons from '../../ui/components/buttons/buttons.js';\nimport * as Dialogs from '../../ui/components/dialogs/dialogs.js';\nimport * as ComponentHelpers from '../../ui/components/helpers/helpers.js';\nimport * as Menus from '../../ui/components/menus/menus.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as LitHtml from '../../ui/lit-html/lit-html.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport * as Components from './components/components.js';\nimport {type AddBreakpointEvent, type RemoveBreakpointEvent} from './components/StepView.js';\nimport type * as Controllers from './controllers/controllers.js';\nimport * as Converters from './converters/converters.js';\nimport * as Extensions from './extensions/extensions.js';\nimport * as Models from './models/models.js';\nimport * as Actions from './recorder-actions/recorder-actions.js';\nimport recorderControllerStyles from './recorderController.css.js';\nimport * as Events from './RecorderEvents.js';\n\nconst {html, Decorators, LitElement} = LitHtml;\nconst {customElement, state} = Decorators;\n\nconst UIStrings = {\n /**\n * @description The title of the button that leads to a page for creating a new recording.\n */\n createRecording: 'Create a new recording',\n /**\n * @description The title of the button that allows importing a recording.\n */\n importRecording: 'Import recording',\n /**\n * @description The title of the button that deletes the recording\n */\n deleteRecording: 'Delete recording',\n /**\n * @description The title of the select if user has no saved recordings\n */\n noRecordings: 'No recordings',\n /**\n * @description The title of the select option for one or more recording\n * number followed by this text - `1 recording(s)` or `4 recording(s)`\n */\n numberOfRecordings: 'recording(s)',\n /**\n * @description The title of the button that continues the replay\n */\n continueReplay: 'Continue',\n /**\n * @description The title of the button that executes only one step in the replay\n */\n stepOverReplay: 'Execute one step',\n /**\n * @description The title of the button that opens a menu with various options of exporting a recording to file.\n */\n exportRecording: 'Export',\n /**\n * @description The title of shortcut for starting and stopping recording.\n */\n startStopRecording: 'Start/Stop recording',\n /**\n * @description The title of shortcut for replaying recording.\n */\n replayRecording: 'Replay recording',\n /**\n * @description The title of shortcut for copying a recording or selected step.\n */\n copyShortcut: 'Copy recording or selected step',\n /**\n * @description The title of shortcut for toggling code view.\n */\n toggleCode: 'Toggle code view',\n /**\n * @description The title of the menu group in the export menu of the Recorder\n * panel that is followed by the list of built-in export formats.\n */\n export: 'Export',\n /**\n * @description The title of the menu group in the export menu of the Recorder\n * panel that is followed by the list of export formats available via browser\n * extensions.\n */\n exportViaExtensions: 'Export via extensions',\n /**\n * @description The title of the menu option that leads to a page that lists\n * all browsers extensions available for Recorder.\n */\n getExtensions: 'Get extensions…',\n /**\n * @description The button label that leads to the feedback form for Recorder.\n */\n sendFeedback: 'Send feedback',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/recorder/RecorderController.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nconst GET_EXTENSIONS_MENU_ITEM = 'get-extensions-link';\nconst GET_EXTENSIONS_URL = 'https://goo.gle/recorder-extension-list' as Platform.DevToolsPath.UrlString;\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-recorder-controller': RecorderController;\n }\n\n interface FileSystemWritableFileStream extends WritableStream {\n write(data: unknown): Promise;\n close(): Promise;\n }\n\n interface FileSystemHandle {\n createWritable(): Promise;\n }\n\n interface Window {\n showSaveFilePicker(opts: unknown): Promise;\n }\n}\n\ninterface StoredRecording {\n storageName: string;\n flow: Models.Schema.UserFlow;\n}\n\ninterface SetCurrentRecordingOptions {\n /**\n * Whether to keep breakpoints in the recording.\n */\n keepBreakpoints: boolean;\n /**\n * Whether to upstream the recording to a recording session if it exists.\n */\n updateSession: boolean;\n}\n\nexport const enum Pages {\n START_PAGE = 'StartPage',\n ALL_RECORDINGS_PAGE = 'AllRecordingsPage',\n CREATE_RECORDING_PAGE = 'CreateRecordingPage',\n RECORDING_PAGE = 'RecordingPage',\n}\n\nconst CONVERTER_ID_TO_METRIC: Record = {\n [Models.ConverterIds.ConverterIds.JSON]: Host.UserMetrics.RecordingExported.TO_JSON,\n [Models.ConverterIds.ConverterIds.REPLAY]: Host.UserMetrics.RecordingExported.TO_PUPPETEER_REPLAY,\n [Models.ConverterIds.ConverterIds.PUPPETEER]: Host.UserMetrics.RecordingExported.TO_PUPPETEER,\n [Models.ConverterIds.ConverterIds.PUPPETEER_FIREFOX]: Host.UserMetrics.RecordingExported.TO_PUPPETEER,\n [Models.ConverterIds.ConverterIds.LIGHTHOUSE]: Host.UserMetrics.RecordingExported.TO_LIGHTHOUSE,\n};\n\n@customElement('devtools-recorder-controller')\nexport class RecorderController extends LitElement {\n static override readonly styles = [recorderControllerStyles];\n\n @state() declare private currentRecordingSession?: Models.RecordingSession.RecordingSession;\n @state() declare private currentRecording: StoredRecording|undefined;\n @state() declare private currentStep?: Models.Schema.Step;\n @state() declare private recordingError?: Error;\n\n #storage = Models.RecordingStorage.RecordingStorage.instance();\n #screenshotStorage = Models.ScreenshotStorage.ScreenshotStorage.instance();\n\n @state() declare private isRecording: boolean;\n @state() declare private isToggling: boolean;\n\n // TODO: we keep the functionality to allow/disallow replay but right now it's not used.\n // It can be used to decide if we allow replay on a certain target for example.\n #replayAllowed = true;\n @state() declare private recordingPlayer?: Models.RecordingPlayer.RecordingPlayer;\n @state() declare private lastReplayResult?: Models.RecordingPlayer.ReplayResult;\n readonly #replayState: Components.RecordingView.ReplayState = {isPlaying: false, isPausedOnBreakpoint: false};\n\n @state() declare private currentPage: Pages;\n @state() declare private previousPage?: Pages;\n #fileSelector?: HTMLInputElement;\n\n @state() declare private sections?: Models.Section.Section[];\n @state() declare private settings?: Models.RecordingSettings.RecordingSettings;\n\n @state() declare private importError?: Error;\n\n @state() declare private exportMenuExpanded: boolean;\n #exportMenuButton: Buttons.Button.Button|undefined;\n\n #stepBreakpointIndexes: Set = new Set();\n\n #builtInConverters: Readonly;\n @state() declare private extensionConverters: Converters.Converter.Converter[];\n @state() declare private replayExtensions: Extensions.ExtensionManager.Extension[];\n\n @state() declare private viewDescriptor?: PublicExtensions.RecorderPluginManager.ViewDescriptor;\n\n #recorderSettings = new Models.RecorderSettings.RecorderSettings();\n #shortcutHelper = new Models.RecorderShortcutHelper.RecorderShortcutHelper();\n\n constructor() {\n super();\n\n this.isRecording = false;\n this.isToggling = false;\n this.exportMenuExpanded = false;\n\n this.currentPage = Pages.START_PAGE;\n if (this.#storage.getRecordings().length) {\n this.#setCurrentPage(Pages.ALL_RECORDINGS_PAGE);\n }\n\n const textEditorIndent = Common.Settings.Settings.instance().moduleSetting('text-editor-indent').get();\n this.#builtInConverters = Object.freeze([\n new Converters.JSONConverter.JSONConverter(textEditorIndent),\n new Converters.PuppeteerReplayConverter.PuppeteerReplayConverter(textEditorIndent),\n new Converters.PuppeteerConverter.PuppeteerConverter(textEditorIndent),\n new Converters.PuppeteerFirefoxConverter.PuppeteerFirefoxConverter(textEditorIndent),\n new Converters.LighthouseConverter.LighthouseConverter(textEditorIndent),\n ]);\n\n const extensionManager = Extensions.ExtensionManager.ExtensionManager.instance();\n this.#updateExtensions(extensionManager.extensions());\n extensionManager.addEventListener(Extensions.ExtensionManager.Events.EXTENSIONS_UPDATED, event => {\n this.#updateExtensions(event.data);\n });\n\n // used in e2e tests only.\n this.addEventListener('setrecording', (event: Event) => this.#onSetRecording(event));\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n\n if (this.currentRecordingSession) {\n void this.currentRecordingSession.stop();\n }\n }\n\n #updateExtensions(extensions: Extensions.ExtensionManager.Extension[]): void {\n this.extensionConverters =\n extensions.filter(extension => extension.getCapabilities().includes('export')).map((extension, idx) => {\n return new Converters.ExtensionConverter.ExtensionConverter(idx, extension);\n });\n this.replayExtensions = extensions.filter(extension => extension.getCapabilities().includes('replay'));\n }\n\n setIsRecordingStateForTesting(isRecording: boolean): void {\n this.isRecording = isRecording;\n }\n\n setRecordingStateForTesting(state: Components.RecordingView.ReplayState): void {\n this.#replayState.isPlaying = state.isPlaying;\n this.#replayState.isPausedOnBreakpoint = state.isPausedOnBreakpoint;\n }\n\n setCurrentPageForTesting(page: Pages): void {\n this.#setCurrentPage(page);\n }\n\n getCurrentPageForTesting(): Pages {\n return this.currentPage;\n }\n\n getCurrentRecordingForTesting(): StoredRecording|undefined {\n return this.currentRecording;\n }\n\n getStepBreakpointIndexesForTesting(): number[] {\n return [...this.#stepBreakpointIndexes.values()];\n }\n\n /**\n * We should clear errors on every new action in the controller.\n * TODO: think how to make handle this centrally so that in no case\n * the error remains shown for longer than needed. Maybe a timer?\n */\n #clearError(): void {\n this.importError = undefined;\n }\n\n async #importFile(file: File): Promise {\n const outputStream = new Common.StringOutputStream.StringOutputStream();\n const reader = new Bindings.FileUtils.ChunkedFileReader(\n file,\n /* chunkSize */ 10000000);\n const success = await reader.read(outputStream);\n if (!success) {\n throw reader.error();\n }\n\n let flow: Models.Schema.UserFlow|undefined;\n try {\n flow = Models.SchemaUtils.parse(JSON.parse(outputStream.data()));\n } catch (error) {\n this.importError = error;\n return;\n }\n this.#setCurrentRecording(await this.#storage.saveRecording(flow));\n this.#setCurrentPage(Pages.RECORDING_PAGE);\n this.#clearError();\n }\n\n setCurrentRecordingForTesting(recording: StoredRecording|undefined): void {\n this.#setCurrentRecording(recording);\n }\n\n getSectionsForTesting(): Array|undefined {\n return this.sections;\n }\n\n #setCurrentRecording(recording: StoredRecording|undefined, opts: Partial = {}): void {\n const {keepBreakpoints = false, updateSession = false} = opts;\n this.recordingPlayer?.abort();\n this.currentStep = undefined;\n this.recordingError = undefined;\n this.lastReplayResult = undefined;\n this.recordingPlayer = undefined;\n this.#replayState.isPlaying = false;\n this.#replayState.isPausedOnBreakpoint = false;\n this.#stepBreakpointIndexes = keepBreakpoints ? this.#stepBreakpointIndexes : new Set();\n\n if (recording) {\n this.currentRecording = recording;\n this.sections = Models.Section.buildSections(recording.flow.steps);\n this.settings = this.#buildSettings(recording.flow);\n if (updateSession && this.currentRecordingSession) {\n this.currentRecordingSession.overwriteUserFlow(recording.flow);\n }\n } else {\n this.currentRecording = undefined;\n this.sections = undefined;\n this.settings = undefined;\n }\n\n this.#updateScreenshotsForSections();\n }\n\n #setCurrentPage(page: Pages): void {\n if (page === this.currentPage) {\n return;\n }\n\n this.previousPage = this.currentPage;\n this.currentPage = page;\n }\n\n #buildSettings(flow: Models.Schema.UserFlow): Models.RecordingSettings.RecordingSettings {\n const steps = flow.steps;\n const navigateStepIdx = steps.findIndex(step => step.type === 'navigate');\n const settings: Models.RecordingSettings.RecordingSettings = {timeout: flow.timeout};\n for (let i = navigateStepIdx - 1; i >= 0; i--) {\n const step = steps[i];\n if (!settings.viewportSettings && step.type === 'setViewport') {\n settings.viewportSettings = step;\n }\n if (!settings.networkConditionsSettings && step.type === 'emulateNetworkConditions') {\n settings.networkConditionsSettings = {...step};\n for (const preset\n of [SDK.NetworkManager.OfflineConditions, SDK.NetworkManager.Slow3GConditions,\n SDK.NetworkManager.Slow4GConditions, SDK.NetworkManager.Fast4GConditions]) {\n // Using i18nTitleKey as a title here because we only want to compare the parameters of the network conditions.\n if (SDK.NetworkManager.networkConditionsEqual(\n {...preset, title: preset.i18nTitleKey || ''}, {...step, title: preset.i18nTitleKey || ''})) {\n settings.networkConditionsSettings.title = preset.title instanceof Function ? preset.title() : preset.title;\n settings.networkConditionsSettings.i18nTitleKey = preset.i18nTitleKey;\n }\n }\n }\n }\n return settings;\n }\n\n #getMainTarget(): SDK.Target.Target {\n const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n if (!target) {\n throw new Error('Missing main page target');\n }\n return target;\n }\n\n #getSectionFromStep(step: Models.Schema.Step): Models.Section.Section|null {\n if (!this.sections) {\n return null;\n }\n\n for (const section of this.sections) {\n if (section.steps.indexOf(step) !== -1) {\n return section;\n }\n }\n\n return null;\n }\n\n #updateScreenshotsForSections(): void {\n if (!this.sections || !this.currentRecording) {\n return;\n }\n const storageName = this.currentRecording.storageName;\n for (let i = 0; i < this.sections.length; i++) {\n const screenshot = this.#screenshotStorage.getScreenshotForSection(storageName, i);\n this.sections[i].screenshot = screenshot || undefined;\n }\n this.requestUpdate();\n }\n\n #onAbortReplay(): void {\n this.recordingPlayer?.abort();\n }\n\n async #onPlayViaExtension(extension: Extensions.ExtensionManager.Extension): Promise {\n if (!this.currentRecording || !this.#replayAllowed) {\n return;\n }\n const pluginManager = PublicExtensions.RecorderPluginManager.RecorderPluginManager.instance();\n const promise = pluginManager.once(PublicExtensions.RecorderPluginManager.Events.SHOW_VIEW_REQUESTED);\n extension.replay(this.currentRecording.flow);\n const descriptor = await promise;\n this.viewDescriptor = descriptor;\n Host.userMetrics.recordingReplayStarted(Host.UserMetrics.RecordingReplayStarted.REPLAY_VIA_EXTENSION);\n }\n\n async #onPlayRecording(event: Components.RecordingView.PlayRecordingEvent): Promise {\n if (!this.currentRecording || !this.#replayAllowed) {\n return;\n }\n if (this.viewDescriptor) {\n this.viewDescriptor = undefined;\n }\n if (event.data.extension) {\n return this.#onPlayViaExtension(event.data.extension);\n }\n Host.userMetrics.recordingReplayStarted(\n event.data.targetPanel !== Components.RecordingView.TargetPanel.DEFAULT ?\n Host.UserMetrics.RecordingReplayStarted.REPLAY_WITH_PERFORMANCE_TRACING :\n Host.UserMetrics.RecordingReplayStarted.REPLAY_ONLY);\n this.#replayState.isPlaying = true;\n this.currentStep = undefined;\n this.recordingError = undefined;\n this.lastReplayResult = undefined;\n const currentRecording = this.currentRecording;\n this.#clearError();\n\n await this.#disableDeviceModeIfEnabled();\n\n this.recordingPlayer = new Models.RecordingPlayer.RecordingPlayer(\n this.currentRecording.flow, {speed: event.data.speed, breakpointIndexes: this.#stepBreakpointIndexes});\n\n const withPerformanceTrace = event.data.targetPanel === Components.RecordingView.TargetPanel.PERFORMANCE_PANEL;\n const sectionsWithScreenshot = new Set();\n this.recordingPlayer.addEventListener(Models.RecordingPlayer.Events.STEP, async ({data: {step, resolve}}) => {\n this.currentStep = step;\n const currentSection = this.#getSectionFromStep(step);\n if (this.sections && currentSection && !sectionsWithScreenshot.has(currentSection)) {\n sectionsWithScreenshot.add(currentSection);\n const currentSectionIndex = this.sections.indexOf(currentSection);\n const screenshot = await Models.ScreenshotUtils.takeScreenshot();\n currentSection.screenshot = screenshot;\n Models.ScreenshotStorage.ScreenshotStorage.instance().storeScreenshotForSection(\n currentRecording.storageName, currentSectionIndex, screenshot);\n }\n resolve();\n });\n\n this.recordingPlayer.addEventListener(Models.RecordingPlayer.Events.STOP, () => {\n this.#replayState.isPausedOnBreakpoint = true;\n this.requestUpdate();\n });\n\n this.recordingPlayer.addEventListener(Models.RecordingPlayer.Events.CONTINUE, () => {\n this.#replayState.isPausedOnBreakpoint = false;\n this.requestUpdate();\n });\n\n this.recordingPlayer.addEventListener(Models.RecordingPlayer.Events.ERROR, ({data: error}) => {\n this.recordingError = error;\n if (!withPerformanceTrace) {\n this.#replayState.isPlaying = false;\n this.recordingPlayer = undefined;\n }\n this.lastReplayResult = Models.RecordingPlayer.ReplayResult.FAILURE;\n const errorMessage = error.message.toLowerCase();\n if (errorMessage.startsWith('could not find element')) {\n Host.userMetrics.recordingReplayFinished(Host.UserMetrics.RecordingReplayFinished.TIMEOUT_ERROR_SELECTORS);\n } else if (errorMessage.startsWith('waiting for target failed')) {\n Host.userMetrics.recordingReplayFinished(Host.UserMetrics.RecordingReplayFinished.TIMEOUT_ERROR_TARGET);\n } else {\n Host.userMetrics.recordingReplayFinished(Host.UserMetrics.RecordingReplayFinished.OTHER_ERROR);\n }\n });\n\n this.recordingPlayer.addEventListener(Models.RecordingPlayer.Events.DONE, () => {\n if (!withPerformanceTrace) {\n this.#replayState.isPlaying = false;\n this.recordingPlayer = undefined;\n }\n this.lastReplayResult = Models.RecordingPlayer.ReplayResult.SUCCESS;\n // Dispatch an event for e2e testing.\n this.dispatchEvent(new Events.ReplayFinishedEvent());\n Host.userMetrics.recordingReplayFinished(Host.UserMetrics.RecordingReplayFinished.SUCCESS);\n });\n\n this.recordingPlayer.addEventListener(Models.RecordingPlayer.Events.ABORT, () => {\n this.currentStep = undefined;\n this.recordingError = undefined;\n this.lastReplayResult = undefined;\n this.#replayState.isPlaying = false;\n });\n\n let resolveWithEvents = (_events: Object[]): void => {};\n const eventsPromise = new Promise((resolve): void => {\n resolveWithEvents = resolve;\n });\n\n let performanceTracing = null;\n switch (event.data?.targetPanel) {\n case Components.RecordingView.TargetPanel.PERFORMANCE_PANEL:\n performanceTracing = new Tracing.PerformanceTracing.PerformanceTracing(this.#getMainTarget(), {\n tracingBufferUsage(): void{},\n eventsRetrievalProgress(): void{},\n tracingComplete(events: Object[]): void {\n resolveWithEvents(events);\n },\n });\n break;\n }\n\n if (performanceTracing) {\n await performanceTracing.start();\n }\n\n this.#setTouchEmulationAllowed(false);\n await this.recordingPlayer.play();\n this.#setTouchEmulationAllowed(true);\n\n if (performanceTracing) {\n await performanceTracing.stop();\n const events = await eventsPromise;\n this.#replayState.isPlaying = false;\n this.recordingPlayer = undefined;\n await UI.InspectorView.InspectorView.instance().showPanel(event.data?.targetPanel as string);\n switch (event.data?.targetPanel) {\n case Components.RecordingView.TargetPanel.PERFORMANCE_PANEL:\n Timeline.TimelinePanel.TimelinePanel.instance().loadFromEvents(events as Trace.Types.Events.Event[]);\n break;\n }\n }\n }\n\n async #disableDeviceModeIfEnabled(): Promise {\n try {\n const deviceModeWrapper = Emulation.DeviceModeWrapper.DeviceModeWrapper.instance();\n if (deviceModeWrapper.isDeviceModeOn()) {\n deviceModeWrapper.toggleDeviceMode();\n const emulationModel = this.#getMainTarget().model(SDK.EmulationModel.EmulationModel);\n await emulationModel?.emulateDevice(null);\n }\n } catch {\n // in the hosted mode, when the DeviceMode toolbar is not supported,\n // Emulation.DeviceModeWrapper.DeviceModeWrapper.instance throws an exception.\n }\n }\n\n #setTouchEmulationAllowed(touchEmulationAllowed: boolean): void {\n const emulationModel = this.#getMainTarget().model(SDK.EmulationModel.EmulationModel);\n emulationModel?.setTouchEmulationAllowed(touchEmulationAllowed);\n }\n\n async #onSetRecording(event: Event): Promise {\n const json = JSON.parse((event as CustomEvent).detail);\n this.#setCurrentRecording(await this.#storage.saveRecording(Models.SchemaUtils.parse(json)));\n this.#setCurrentPage(Pages.RECORDING_PAGE);\n this.#clearError();\n }\n\n // Used by e2e tests to inspect the current recording.\n getUserFlow(): Models.Schema.UserFlow|undefined {\n return this.currentRecording?.flow;\n }\n\n async #handleRecordingChanged(event: Components.StepView.StepChanged): Promise {\n if (!this.currentRecording) {\n throw new Error('Current recording expected to be defined.');\n }\n const recording = {\n ...this.currentRecording,\n flow: {\n ...this.currentRecording.flow,\n steps: this.currentRecording.flow.steps.map(step => step === event.currentStep ? event.newStep : step),\n },\n };\n this.#setCurrentRecording(\n await this.#storage.updateRecording(recording.storageName, recording.flow),\n {keepBreakpoints: true, updateSession: true});\n }\n\n async #handleStepAdded(event: Components.StepView.AddStep): Promise {\n if (!this.currentRecording) {\n throw new Error('Current recording expected to be defined.');\n }\n const stepOrSection = event.stepOrSection;\n let step;\n let position = event.position;\n if ('steps' in stepOrSection) {\n // section\n const sectionIdx = this.sections?.indexOf(stepOrSection);\n if (sectionIdx === undefined || sectionIdx === -1) {\n throw new Error('There is no section to add a step to');\n }\n if (event.position === Components.StepView.AddStepPosition.AFTER) {\n if (this.sections?.[sectionIdx].steps.length) {\n step = this.sections?.[sectionIdx].steps[0];\n position = Components.StepView.AddStepPosition.BEFORE;\n } else {\n step = this.sections?.[sectionIdx].causingStep;\n position = Components.StepView.AddStepPosition.AFTER;\n }\n } else {\n if (sectionIdx <= 0) {\n throw new Error('There is no section to add a step to');\n }\n const prevSection = this.sections?.[sectionIdx - 1];\n step = prevSection?.steps[prevSection.steps.length - 1];\n position = Components.StepView.AddStepPosition.AFTER;\n }\n } else {\n // step\n step = stepOrSection;\n }\n if (!step) {\n throw new Error('Anchor step is not found when adding a step');\n }\n const steps = this.currentRecording.flow.steps;\n const currentIndex = steps.indexOf(step);\n const indexToInsertAt = currentIndex + (position === Components.StepView.AddStepPosition.BEFORE ? 0 : 1);\n steps.splice(indexToInsertAt, 0, {type: Models.Schema.StepType.WaitForElement, selectors: ['body']});\n const recording = {...this.currentRecording, flow: {...this.currentRecording.flow, steps}};\n Host.userMetrics.recordingEdited(Host.UserMetrics.RecordingEdited.STEP_ADDED);\n this.#stepBreakpointIndexes = new Set([...this.#stepBreakpointIndexes.values()].map(breakpointIndex => {\n if (indexToInsertAt > breakpointIndex) {\n return breakpointIndex;\n }\n\n return breakpointIndex + 1;\n }));\n this.#setCurrentRecording(\n await this.#storage.updateRecording(recording.storageName, recording.flow),\n {keepBreakpoints: true, updateSession: true});\n }\n\n async #handleRecordingTitleChanged(event: Components.RecordingView.RecordingTitleChangedEvent): Promise {\n if (!this.currentRecording) {\n throw new Error('Current recording expected to be defined.');\n }\n\n const flow = {...this.currentRecording.flow, title: event.title};\n this.#setCurrentRecording(await this.#storage.updateRecording(this.currentRecording.storageName, flow));\n }\n\n async #handleStepRemoved(event: Components.StepView.RemoveStep): Promise {\n if (!this.currentRecording) {\n throw new Error('Current recording expected to be defined.');\n }\n\n const steps = this.currentRecording.flow.steps;\n const currentIndex = steps.indexOf(event.step);\n steps.splice(currentIndex, 1);\n const flow = {...this.currentRecording.flow, steps};\n Host.userMetrics.recordingEdited(Host.UserMetrics.RecordingEdited.STEP_REMOVED);\n this.#stepBreakpointIndexes = new Set([...this.#stepBreakpointIndexes.values()]\n .map(breakpointIndex => {\n if (currentIndex > breakpointIndex) {\n return breakpointIndex;\n }\n\n if (currentIndex === breakpointIndex) {\n return -1;\n }\n\n return breakpointIndex - 1;\n })\n .filter(index => index >= 0));\n this.#setCurrentRecording(\n await this.#storage.updateRecording(this.currentRecording.storageName, flow),\n {keepBreakpoints: true, updateSession: true});\n }\n\n async #onNetworkConditionsChanged(event: Components.RecordingView.NetworkConditionsChanged): Promise {\n if (!this.currentRecording) {\n throw new Error('Current recording expected to be defined.');\n }\n const navigateIdx = this.currentRecording.flow.steps.findIndex(step => step.type === 'navigate');\n if (navigateIdx === -1) {\n throw new Error('Current recording does not have a navigate step');\n }\n const emulateNetworkConditionsIdx = this.currentRecording.flow.steps.findIndex((step, idx) => {\n if (idx >= navigateIdx) {\n return false;\n }\n return step.type === 'emulateNetworkConditions';\n });\n if (!event.data) {\n // Delete step if present.\n if (emulateNetworkConditionsIdx !== -1) {\n this.currentRecording.flow.steps.splice(emulateNetworkConditionsIdx, 1);\n }\n } else if (emulateNetworkConditionsIdx === -1) {\n // Insert at the first position.\n this.currentRecording.flow.steps.splice(\n 0, 0,\n Models.SchemaUtils.createEmulateNetworkConditionsStep(\n {download: event.data.download, upload: event.data.upload, latency: event.data.latency}));\n } else {\n // Update existing step.\n const step =\n this.currentRecording.flow.steps[emulateNetworkConditionsIdx] as Models.Schema.EmulateNetworkConditionsStep;\n step.download = event.data.download;\n step.upload = event.data.upload;\n step.latency = event.data.latency;\n }\n this.#setCurrentRecording(\n await this.#storage.updateRecording(this.currentRecording.storageName, this.currentRecording.flow));\n }\n\n async #onTimeoutChanged(event: Components.RecordingView.TimeoutChanged): Promise {\n if (!this.currentRecording) {\n throw new Error('Current recording expected to be defined.');\n }\n this.currentRecording.flow.timeout = event.data;\n this.#setCurrentRecording(\n await this.#storage.updateRecording(this.currentRecording.storageName, this.currentRecording.flow));\n }\n\n async #onDeleteRecording(event: Event): Promise {\n event.stopPropagation();\n if (event instanceof Components.RecordingListView.DeleteRecordingEvent) {\n await this.#storage.deleteRecording(event.storageName);\n this.#screenshotStorage.deleteScreenshotsForRecording(event.storageName);\n this.requestUpdate();\n } else {\n if (!this.currentRecording) {\n return;\n }\n await this.#storage.deleteRecording(this.currentRecording.storageName);\n this.#screenshotStorage.deleteScreenshotsForRecording(this.currentRecording.storageName);\n }\n if ((await this.#storage.getRecordings()).length) {\n this.#setCurrentPage(Pages.ALL_RECORDINGS_PAGE);\n } else {\n this.#setCurrentPage(Pages.START_PAGE);\n }\n this.#setCurrentRecording(undefined);\n this.#clearError();\n }\n\n #onCreateNewRecording(event?: Event): void {\n event?.stopPropagation();\n this.#setCurrentPage(Pages.CREATE_RECORDING_PAGE);\n this.#clearError();\n }\n\n async #onRecordingStarted(event: Components.CreateRecordingView.RecordingStartedEvent): Promise {\n // Recording is not available in device mode.\n await this.#disableDeviceModeIfEnabled();\n\n // Setting up some variables to notify the user we are initializing a recording.\n this.isToggling = true;\n this.#clearError();\n\n // -- Recording logic starts here --\n Host.userMetrics.recordingToggled(Host.UserMetrics.RecordingToggled.RECORDING_STARTED);\n this.currentRecordingSession = new Models.RecordingSession.RecordingSession(this.#getMainTarget(), {\n title: event.name,\n selectorAttribute: event.selectorAttribute,\n selectorTypesToRecord: event.selectorTypesToRecord.length ? event.selectorTypesToRecord :\n Object.values(Models.Schema.SelectorType),\n });\n this.#setCurrentRecording(await this.#storage.saveRecording(this.currentRecordingSession.cloneUserFlow()));\n\n let previousSectionIndex = -1;\n let screenshotPromise:|Promise|undefined;\n const takeScreenshot = async(currentRecording: StoredRecording): Promise => {\n if (!this.sections) {\n throw new Error('Could not find sections.');\n }\n\n const currentSectionIndex = this.sections.length - 1;\n const currentSection = this.sections[currentSectionIndex];\n if (screenshotPromise || previousSectionIndex === currentSectionIndex) {\n return;\n }\n\n screenshotPromise = Models.ScreenshotUtils.takeScreenshot();\n const screenshot = await screenshotPromise;\n screenshotPromise = undefined;\n currentSection.screenshot = screenshot;\n Models.ScreenshotStorage.ScreenshotStorage.instance().storeScreenshotForSection(\n currentRecording.storageName, currentSectionIndex, screenshot);\n previousSectionIndex = currentSectionIndex;\n this.#updateScreenshotsForSections();\n };\n\n this.currentRecordingSession.addEventListener(\n Models.RecordingSession.Events.RECORDING_UPDATED, async ({data}: {data: Models.Schema.UserFlow}) => {\n if (!this.currentRecording) {\n throw new Error('No current recording found');\n }\n this.#setCurrentRecording(await this.#storage.updateRecording(this.currentRecording.storageName, data));\n const recordingView = this.shadowRoot?.querySelector('devtools-recording-view');\n recordingView?.scrollToBottom();\n\n await takeScreenshot(this.currentRecording);\n });\n\n this.currentRecordingSession.addEventListener(\n Models.RecordingSession.Events.RECORDING_STOPPED, async ({data}: {data: Models.Schema.UserFlow}) => {\n if (!this.currentRecording) {\n throw new Error('No current recording found');\n }\n Host.userMetrics.keyboardShortcutFired(Actions.RecorderActions.START_RECORDING);\n this.#setCurrentRecording(await this.#storage.updateRecording(this.currentRecording.storageName, data));\n await this.#onRecordingFinished();\n });\n\n await this.currentRecordingSession.start();\n // -- Recording logic ends here --\n\n // Setting up some variables to notify the user we are finished initialization.\n this.isToggling = false;\n this.isRecording = true;\n this.#setCurrentPage(Pages.RECORDING_PAGE);\n\n // Dispatch an event for e2e testing.\n this.dispatchEvent(new Events.RecordingStateChangedEvent((this.currentRecording as StoredRecording).flow));\n }\n\n async #onRecordingFinished(): Promise {\n if (!this.currentRecording || !this.currentRecordingSession) {\n throw new Error('Recording was never started');\n }\n\n // Setting up some variables to notify the user we are finalizing a recording.\n this.isToggling = true;\n this.#clearError();\n\n // -- Recording logic starts here --\n Host.userMetrics.recordingToggled(Host.UserMetrics.RecordingToggled.RECORDING_FINISHED);\n await this.currentRecordingSession.stop();\n this.currentRecordingSession = undefined;\n // -- Recording logic ends here --\n\n // Setting up some variables to notify the user we are finished finalizing.\n this.isToggling = false;\n this.isRecording = false;\n\n // Dispatch an event for e2e testing.\n this.dispatchEvent(new Events.RecordingStateChangedEvent(this.currentRecording.flow));\n }\n\n async #onRecordingCancelled(): Promise {\n if (this.previousPage) {\n this.#setCurrentPage(this.previousPage);\n }\n }\n\n async #onRecordingSelected(event: Event): Promise {\n const storageName = event instanceof Components.RecordingListView.OpenRecordingEvent ||\n event instanceof Components.RecordingListView.PlayRecordingEvent ?\n event.storageName :\n ((event as InputEvent).target as HTMLSelectElement)?.value;\n this.#setCurrentRecording(await this.#storage.getRecording(storageName));\n if (this.currentRecording) {\n this.#setCurrentPage(Pages.RECORDING_PAGE);\n } else if (storageName === Pages.START_PAGE) {\n this.#setCurrentPage(Pages.START_PAGE);\n } else if (storageName === Pages.ALL_RECORDINGS_PAGE) {\n this.#setCurrentPage(Pages.ALL_RECORDINGS_PAGE);\n }\n }\n\n async #onExportOptionSelected(event: Menus.SelectMenu.SelectMenuItemSelectedEvent): Promise {\n if (typeof event.itemValue !== 'string') {\n throw new Error('Invalid export option value');\n }\n if (event.itemValue === GET_EXTENSIONS_MENU_ITEM) {\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.openInNewTab(GET_EXTENSIONS_URL);\n return;\n }\n if (!this.currentRecording) {\n throw new Error('No recording selected');\n }\n const id = event.itemValue;\n const byId = (converter: Converters.Converter.Converter): boolean => converter.getId() === id;\n const converter = this.#builtInConverters.find(byId) || this.extensionConverters.find(byId);\n if (!converter) {\n throw new Error('No recording selected');\n }\n const [content] = await converter.stringify(this.currentRecording.flow);\n await this.#exportContent(converter.getFilename(this.currentRecording.flow), content);\n const builtInMetric = CONVERTER_ID_TO_METRIC[converter.getId()];\n if (builtInMetric) {\n Host.userMetrics.recordingExported(builtInMetric);\n } else if (converter.getId().startsWith(Converters.ExtensionConverter.EXTENSION_PREFIX)) {\n Host.userMetrics.recordingExported(Host.UserMetrics.RecordingExported.TO_EXTENSION);\n } else {\n throw new Error('Could not find a metric for the export option with id = ' + id);\n }\n }\n\n async #exportContent(suggestedName: string, data: string): Promise {\n try {\n const handle = await window.showSaveFilePicker({suggestedName});\n const writable = await handle.createWritable();\n await writable.write(data);\n await writable.close();\n } catch (error) {\n // If the user aborts the action no need to report it, otherwise do.\n if (error.name === 'AbortError') {\n return;\n }\n\n throw error;\n }\n }\n\n async #handleAddAssertionEvent(): Promise {\n if (!this.currentRecordingSession || !this.currentRecording) {\n return;\n }\n const flow = this.currentRecordingSession.cloneUserFlow();\n flow.steps.push({type: 'waitForElement' as Models.Schema.StepType.WaitForElement, selectors: [['.cls']]});\n this.#setCurrentRecording(\n await this.#storage.updateRecording(this.currentRecording.storageName, flow),\n {keepBreakpoints: true, updateSession: true});\n Host.userMetrics.recordingAssertion(Host.UserMetrics.RecordingAssertion.ASSERTION_ADDED);\n await this.updateComplete;\n this.renderRoot.querySelector('devtools-recording-view')\n ?.shadowRoot?.querySelector('.section:last-child devtools-step-view:last-of-type')\n ?.shadowRoot?.querySelector('.action')\n ?.click();\n }\n\n #onImportRecording(event: Event): void {\n event.stopPropagation();\n this.#clearError();\n this.#fileSelector = UI.UIUtils.createFileSelectorElement(this.#importFile.bind(this));\n this.#fileSelector.click();\n }\n\n async #onPlayRecordingByName(event: Components.RecordingListView.PlayRecordingEvent): Promise {\n await this.#onRecordingSelected(event);\n await this.#onPlayRecording(new Components.RecordingView.PlayRecordingEvent(\n {targetPanel: Components.RecordingView.TargetPanel.DEFAULT, speed: this.#recorderSettings.speed}));\n }\n\n #onAddBreakpoint = (event: AddBreakpointEvent): void => {\n this.#stepBreakpointIndexes.add(event.index);\n this.recordingPlayer?.updateBreakpointIndexes(this.#stepBreakpointIndexes);\n this.requestUpdate();\n };\n\n #onRemoveBreakpoint = (event: RemoveBreakpointEvent): void => {\n this.#stepBreakpointIndexes.delete(event.index);\n this.recordingPlayer?.updateBreakpointIndexes(this.#stepBreakpointIndexes);\n this.requestUpdate();\n };\n\n #onExtensionViewClosed(): void {\n this.viewDescriptor = undefined;\n }\n\n handleActions(actionId: Actions.RecorderActions): void {\n if (!this.isActionPossible(actionId)) {\n return;\n }\n\n switch (actionId) {\n case Actions.RecorderActions.CREATE_RECORDING:\n this.#onCreateNewRecording();\n return;\n\n case Actions.RecorderActions.START_RECORDING:\n if (this.currentPage !== Pages.CREATE_RECORDING_PAGE && !this.isRecording) {\n this.#shortcutHelper.handleShortcut(this.#onRecordingStarted.bind(\n this,\n new Components.CreateRecordingView.RecordingStartedEvent(\n this.#recorderSettings.defaultTitle, this.#recorderSettings.defaultSelectors,\n this.#recorderSettings.selectorAttribute)));\n } else if (this.currentPage === Pages.CREATE_RECORDING_PAGE) {\n const view = this.renderRoot.querySelector('devtools-create-recording-view');\n if (view) {\n this.#shortcutHelper.handleShortcut(view.startRecording.bind(view));\n }\n } else if (this.isRecording) {\n void this.#onRecordingFinished();\n }\n return;\n\n case Actions.RecorderActions.REPLAY_RECORDING:\n void this.#onPlayRecording(new Components.RecordingView.PlayRecordingEvent(\n {targetPanel: Components.RecordingView.TargetPanel.DEFAULT, speed: this.#recorderSettings.speed}));\n return;\n\n case Actions.RecorderActions.TOGGLE_CODE_VIEW: {\n const view = this.renderRoot.querySelector('devtools-recording-view');\n if (view) {\n view.showCodeToggle();\n }\n return;\n }\n }\n }\n\n isActionPossible(actionId: Actions.RecorderActions): boolean {\n switch (actionId) {\n case Actions.RecorderActions.CREATE_RECORDING:\n return !this.isRecording && !this.#replayState.isPlaying;\n case Actions.RecorderActions.START_RECORDING:\n return !this.#replayState.isPlaying;\n case Actions.RecorderActions.REPLAY_RECORDING:\n return (this.currentPage === Pages.RECORDING_PAGE && !this.#replayState.isPlaying);\n case Actions.RecorderActions.TOGGLE_CODE_VIEW:\n return this.currentPage === Pages.RECORDING_PAGE;\n case Actions.RecorderActions.COPY_RECORDING_OR_STEP:\n // This action is handled in the RecordingView\n // It relies on browser `copy` event.\n return false;\n }\n }\n\n #getShortcutsInfo(): Dialogs.ShortcutDialog.Shortcut[] {\n const getBindingForAction = (action: Actions.RecorderActions): string[] => {\n const shortcuts = UI.ShortcutRegistry.ShortcutRegistry.instance().shortcutsForAction(action);\n\n return shortcuts.map(shortcut => shortcut.title());\n };\n\n return [\n {\n title: i18nString(UIStrings.startStopRecording),\n bindings: getBindingForAction(Actions.RecorderActions.START_RECORDING),\n },\n {\n title: i18nString(UIStrings.replayRecording),\n bindings: getBindingForAction(Actions.RecorderActions.REPLAY_RECORDING),\n },\n {title: i18nString(UIStrings.copyShortcut), bindings: [`${Host.Platform.isMac() ? '⌘ C' : 'Ctrl+C'}`]},\n {\n title: i18nString(UIStrings.toggleCode),\n bindings: getBindingForAction(Actions.RecorderActions.TOGGLE_CODE_VIEW),\n },\n ];\n }\n\n #renderCurrentPage(): LitHtml.TemplateResult {\n switch (this.currentPage) {\n case Pages.START_PAGE:\n return this.#renderStartPage();\n case Pages.ALL_RECORDINGS_PAGE:\n return this.#renderAllRecordingsPage();\n case Pages.RECORDING_PAGE:\n return this.#renderRecordingPage();\n case Pages.CREATE_RECORDING_PAGE:\n return this.#renderCreateRecordingPage();\n }\n }\n\n #renderAllRecordingsPage(): LitHtml.TemplateResult {\n const recordings = this.#storage.getRecordings();\n // clang-format off\n return html`\n <${Components.RecordingListView.RecordingListView.litTagName}\n .recordings=${recordings.map(recording => ({\n storageName: recording.storageName,\n name: recording.flow.title,\n }))}\n .replayAllowed=${this.#replayAllowed}\n @createrecording=${this.#onCreateNewRecording}\n @deleterecording=${this.#onDeleteRecording}\n @openrecording=${this.#onRecordingSelected}\n @playrecording=${this.#onPlayRecordingByName}\n >\n \n `;\n // clang-format on\n }\n\n #renderStartPage(): LitHtml.TemplateResult {\n // clang-format off\n return html`\n <${Components.StartView.StartView.litTagName}\n @createrecording=${this.#onCreateNewRecording}\n >\n `;\n // clang-format on\n }\n\n #renderRecordingPage(): LitHtml.TemplateResult {\n // clang-format off\n return html`\n <${Components.RecordingView.RecordingView.litTagName}\n .data=${\n {\n recording: this.currentRecording?.flow,\n replayState: this.#replayState,\n isRecording: this.isRecording,\n recordingTogglingInProgress: this.isToggling,\n currentStep: this.currentStep,\n currentError: this.recordingError,\n sections: this.sections,\n settings: this.settings,\n recorderSettings: this.#recorderSettings,\n lastReplayResult: this.lastReplayResult,\n replayAllowed: this.#replayAllowed,\n breakpointIndexes: this.#stepBreakpointIndexes,\n builtInConverters: this.#builtInConverters,\n extensionConverters: this.extensionConverters,\n replayExtensions: this.replayExtensions,\n extensionDescriptor: this.viewDescriptor,\n } as Components.RecordingView.RecordingViewData\n }\n @networkconditionschanged=${this.#onNetworkConditionsChanged}\n @timeoutchanged=${this.#onTimeoutChanged}\n @requestselectorattribute=${(\n event: Controllers.SelectorPicker.RequestSelectorAttributeEvent,\n ) => {\n event.send(this.currentRecording?.flow.selectorAttribute);\n }}\n @recordingfinished=${this.#onRecordingFinished}\n @stepchanged=${this.#handleRecordingChanged.bind(this)}\n @recordingtitlechanged=${this.#handleRecordingTitleChanged.bind(this)}\n @addstep=${this.#handleStepAdded.bind(this)}\n @removestep=${this.#handleStepRemoved.bind(this)}\n @addbreakpoint=${this.#onAddBreakpoint}\n @removebreakpoint=${this.#onRemoveBreakpoint}\n @playrecording=${this.#onPlayRecording}\n @abortreplay=${this.#onAbortReplay}\n @recorderextensionviewclosed=${this.#onExtensionViewClosed}\n @addassertion=${this.#handleAddAssertionEvent}\n >\n `;\n // clang-format on\n }\n\n #renderCreateRecordingPage(): LitHtml.TemplateResult {\n // clang-format off\n return html`\n <${Components.CreateRecordingView.CreateRecordingView.litTagName}\n .data=${\n {\n recorderSettings: this.#recorderSettings,\n } as Components.CreateRecordingView.CreateRecordingViewData\n }\n @recordingstarted=${this.#onRecordingStarted}\n @recordingcancelled=${this.#onRecordingCancelled}\n >\n `;\n // clang-format on\n }\n\n #getExportMenuButton = (): Buttons.Button.Button => {\n if (!this.#exportMenuButton) {\n throw new Error('#exportMenuButton not found');\n }\n return this.#exportMenuButton;\n };\n\n #onExportRecording(event: Event): void {\n event.stopPropagation();\n this.#clearError();\n this.exportMenuExpanded = !this.exportMenuExpanded;\n }\n\n #onExportMenuClosed(): void {\n this.exportMenuExpanded = false;\n }\n\n protected override render(): LitHtml.TemplateResult {\n const recordings = this.#storage.getRecordings();\n const selectValue: string = this.currentRecording ? this.currentRecording.storageName : this.currentPage;\n // clang-format off\n const values = [\n recordings.length === 0\n ? {\n value: Pages.START_PAGE,\n name: i18nString(UIStrings.noRecordings),\n selected: selectValue === Pages.START_PAGE,\n }\n : {\n value: Pages.ALL_RECORDINGS_PAGE,\n name: `${recordings.length} ${i18nString(UIStrings.numberOfRecordings)}`,\n selected: selectValue === Pages.ALL_RECORDINGS_PAGE,\n },\n ...recordings.map(recording => ({\n value: recording.storageName,\n name: recording.flow.title,\n selected: selectValue === recording.storageName,\n })),\n ];\n\n return html`\n
\n
\n <${Buttons.Button.Button.litTagName}\n @click=${this.#onCreateNewRecording}\n .data=${\n {\n variant: Buttons.Button.Variant.TOOLBAR,\n iconName: 'plus',\n disabled:\n this.#replayState.isPlaying ||\n this.isRecording ||\n this.isToggling,\n title: Models.Tooltip.getTooltipForActions(\n i18nString(UIStrings.createRecording),\n Actions.RecorderActions.CREATE_RECORDING,\n ),\n jslogContext: Actions.RecorderActions.CREATE_RECORDING,\n } as Buttons.Button.ButtonData\n }\n >\n
\n e.stopPropagation()}\n @change=${this.#onRecordingSelected}\n jslog=${VisualLogging.dropDown('recordings').track({change: true})}\n >\n ${LitHtml.Directives.repeat(\n values,\n item => item.value,\n item => {\n return html``;\n },\n )}\n \n
\n <${Buttons.Button.Button.litTagName}\n @click=${this.#onImportRecording}\n .data=${\n {\n variant: Buttons.Button.Variant.TOOLBAR,\n iconName: 'import',\n title: i18nString(UIStrings.importRecording),\n jslogContext: 'import-recording',\n } as Buttons.Button.ButtonData\n }\n >\n <${Buttons.Button.Button.litTagName}\n id='origin'\n @click=${this.#onExportRecording}\n on-render=${ComponentHelpers.Directives.nodeRenderedCallback(\n node => {\n this.#exportMenuButton = node as Buttons.Button.Button;\n },\n )}\n .data=${\n {\n variant: Buttons.Button.Variant.TOOLBAR,\n iconName: 'download',\n title: i18nString(UIStrings.exportRecording),\n disabled: !this.currentRecording,\n } as Buttons.Button.ButtonData\n }\n jslog=${VisualLogging.dropDown('export-recording').track({click: true})}\n >\n <${Menus.Menu.Menu.litTagName}\n @menucloserequest=${this.#onExportMenuClosed}\n @menuitemselected=${this.#onExportOptionSelected}\n .origin=${this.#getExportMenuButton}\n .showDivider=${false}\n .showSelectedItem=${false}\n .showConnector=${false}\n .open=${this.exportMenuExpanded}\n >\n <${Menus.Menu.MenuGroup.litTagName} .name=${i18nString(\n UIStrings.export,\n )}>\n ${LitHtml.Directives.repeat(\n this.#builtInConverters,\n converter => {\n return html`\n <${\n Menus.Menu.MenuItem.litTagName\n } .value=${converter.getId()}\n jslog=${VisualLogging.item(`converter-${Platform.StringUtilities.toKebabCase(converter.getId())}`).track({click: true})}>\n ${converter.getFormatName()}\n \n `;\n },\n )}\n \n <${Menus.Menu.MenuGroup.litTagName} .name=${i18nString(\n UIStrings.exportViaExtensions,\n )}>\n ${LitHtml.Directives.repeat(\n this.extensionConverters,\n converter => {\n return html`\n <${\n Menus.Menu.MenuItem.litTagName\n } .value=${converter.getId()}\n jslog=${VisualLogging.item('converter-extension').track({click: true})}>\n ${converter.getFormatName()}\n \n `;\n },\n )}\n <${\n Menus.Menu.MenuItem.litTagName\n } .value=${GET_EXTENSIONS_MENU_ITEM}>\n ${i18nString(UIStrings.getExtensions)}\n \n \n \n <${Buttons.Button.Button.litTagName}\n @click=${this.#onDeleteRecording}\n .data=${\n {\n variant: Buttons.Button.Variant.TOOLBAR,\n iconName: 'bin',\n disabled:\n !this.currentRecording ||\n this.#replayState.isPlaying ||\n this.isRecording ||\n this.isToggling,\n title: i18nString(UIStrings.deleteRecording),\n jslogContext: 'delete-recording',\n } as Buttons.Button.ButtonData\n }\n >\n
\n <${Buttons.Button.Button.litTagName}\n @click=${() => this.recordingPlayer?.continue()}\n .data=${\n {\n variant: Buttons.Button.Variant.PRIMARY_TOOLBAR,\n iconName: 'resume',\n disabled:\n !this.recordingPlayer ||\n !this.#replayState.isPausedOnBreakpoint,\n title: i18nString(UIStrings.continueReplay),\n jslogContext: 'continue-replay',\n } as Buttons.Button.ButtonData\n }\n >\n <${Buttons.Button.Button.litTagName}\n @click=${() => this.recordingPlayer?.stepOver()}\n .data=${\n {\n variant: Buttons.Button.Variant.TOOLBAR,\n iconName: 'step-over',\n disabled:\n !this.recordingPlayer ||\n !this.#replayState.isPausedOnBreakpoint,\n title: i18nString(UIStrings.stepOverReplay),\n jslogContext: 'step-over',\n } as Buttons.Button.ButtonData\n }\n >\n
\n ${i18nString(UIStrings.sendFeedback)}\n
\n
\n <${Dialogs.ShortcutDialog.ShortcutDialog.litTagName}\n .data=${\n {\n shortcuts: this.#getShortcutsInfo(),\n } as Dialogs.ShortcutDialog.ShortcutDialogData\n } jslog=${VisualLogging.action('show-shortcuts').track({click: true})}\n >\n
\n ${\n this.importError\n ? html`
Import error: ${\n this.importError.message\n }
`\n : ''\n }\n ${this.#renderCurrentPage()}\n
\n `;\n // clang-format on\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/security/security-meta.js b/public/panels/security/security-meta.js index 4a668d471..64702dc26 100644 --- a/public/panels/security/security-meta.js +++ b/public/panels/security/security-meta.js @@ -1,17 +1,26 @@ // Copyright 2020 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 * as Common from '../../core/common/common.js'; import * as i18n from '../../core/i18n/i18n.js'; import * as UI from '../../ui/legacy/legacy.js'; const UIStrings = { /** - *@description Title of the security panel + *@description Default Title of the security panel */ security: 'Security', /** - *@description Command to open the security panel + *@description Title of security and privacy panel. This is used when the kDevToolsPrivacyUI feature flag is enabled. + */ + securityAndPrivacy: 'Security & Privacy', + /** + *@description Default command to open the security panel */ showSecurity: 'Show Security', + /** + *@description Command to open the security and privacy panel. This is used when the kDevToolPrivacyUI feature flag is enabled + */ + showSecurityAndPrivacy: 'Show Security and Privacy', }; const str_ = i18n.i18n.registerUIStrings('panels/security/security-meta.ts', UIStrings); const i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_); @@ -25,8 +34,12 @@ async function loadSecurityModule() { UI.ViewManager.registerViewExtension({ location: "panel" /* UI.ViewManager.ViewLocationValues.PANEL */, id: 'security', - title: i18nLazyString(UIStrings.security), - commandPrompt: i18nLazyString(UIStrings.showSecurity), + title: () => Common.Settings.Settings.instance().getHostConfig().devToolsPrivacyUI?.enabled ? + i18nLazyString(UIStrings.securityAndPrivacy)() : + i18nLazyString(UIStrings.security)(), + commandPrompt: () => Common.Settings.Settings.instance().getHostConfig().devToolsPrivacyUI?.enabled ? + i18nLazyString(UIStrings.showSecurityAndPrivacy)() : + i18nLazyString(UIStrings.showSecurity)(), order: 80, persistence: "closeable" /* UI.ViewManager.ViewPersistence.CLOSEABLE */, async loadView() { diff --git a/public/panels/security/security-meta.js.map b/public/panels/security/security-meta.js.map index 669d0bb62..162f2f30f 100644 --- a/public/panels/security/security-meta.js.map +++ b/public/panels/security/security-meta.js.map @@ -1 +1 @@ -{"version":3,"file":"security-meta.js","sourceRoot":"","sources":["../../../../../../front_end/panels/security/security-meta.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,IAAI,MAAM,yBAAyB,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAIhD,MAAM,SAAS,GAAG;IAChB;;OAEG;IACH,QAAQ,EAAE,UAAU;IACpB;;OAEG;IACH,YAAY,EAAE,eAAe;CAC9B,CAAC;AACF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,kCAAkC,EAAE,SAAS,CAAC,CAAC;AACxF,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,gCAAgC,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAExF,IAAI,oBAAiD,CAAC;AAEtD,KAAK,UAAU,kBAAkB;IAC/B,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC1B,oBAAoB,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,oBAAoB,CAAC;AAC9B,CAAC;AAED,EAAE,CAAC,WAAW,CAAC,qBAAqB,CAAC;IACnC,QAAQ,uDAAyC;IACjD,EAAE,EAAE,UAAU;IACd,KAAK,EAAE,cAAc,CAAC,SAAS,CAAC,QAAQ,CAAC;IACzC,aAAa,EAAE,cAAc,CAAC,SAAS,CAAC,YAAY,CAAC;IACrD,KAAK,EAAE,EAAE;IACT,WAAW,4DAA0C;IACrD,KAAK,CAAC,QAAQ;QACZ,MAAM,QAAQ,GAAG,MAAM,kBAAkB,EAAE,CAAC;QAC5C,OAAO,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC;IACzD,CAAC;CACF,CAAC,CAAC","sourcesContent":["// Copyright 2020 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport type * as Security from './security.js';\n\nconst UIStrings = {\n /**\n *@description Title of the security panel\n */\n security: 'Security',\n /**\n *@description Command to open the security panel\n */\n showSecurity: 'Show Security',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/security/security-meta.ts', UIStrings);\nconst i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_);\n\nlet loadedSecurityModule: (typeof Security|undefined);\n\nasync function loadSecurityModule(): Promise {\n if (!loadedSecurityModule) {\n loadedSecurityModule = await import('./security.js');\n }\n return loadedSecurityModule;\n}\n\nUI.ViewManager.registerViewExtension({\n location: UI.ViewManager.ViewLocationValues.PANEL,\n id: 'security',\n title: i18nLazyString(UIStrings.security),\n commandPrompt: i18nLazyString(UIStrings.showSecurity),\n order: 80,\n persistence: UI.ViewManager.ViewPersistence.CLOSEABLE,\n async loadView() {\n const Security = await loadSecurityModule();\n return Security.SecurityPanel.SecurityPanel.instance();\n },\n});\n"]} \ No newline at end of file +{"version":3,"file":"security-meta.js","sourceRoot":"","sources":["../../../../../../front_end/panels/security/security-meta.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,MAAM,MAAM,6BAA6B,CAAC;AACtD,OAAO,KAAK,IAAI,MAAM,yBAAyB,CAAC;AAChD,OAAO,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAIhD,MAAM,SAAS,GAAG;IAChB;;OAEG;IACH,QAAQ,EAAE,UAAU;IACpB;;OAEG;IACH,kBAAkB,EAAE,oBAAoB;IACxC;;OAEG;IACH,YAAY,EAAE,eAAe;IAC7B;;OAEG;IACH,sBAAsB,EAAE,2BAA2B;CACpD,CAAC;AAEF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,kCAAkC,EAAE,SAAS,CAAC,CAAC;AACxF,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,gCAAgC,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAExF,IAAI,oBAAiD,CAAC;AAEtD,KAAK,UAAU,kBAAkB;IAC/B,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC1B,oBAAoB,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,oBAAoB,CAAC;AAC9B,CAAC;AAED,EAAE,CAAC,WAAW,CAAC,qBAAqB,CAAC;IACnC,QAAQ,uDAAyC;IACjD,EAAE,EAAE,UAAU;IACd,KAAK,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,aAAa,EAAE,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC;QACzF,cAAc,CAAC,SAAS,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC;QAChD,cAAc,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE;IACxC,aAAa,EAAE,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,aAAa,EAAE,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC;QACjG,cAAc,CAAC,SAAS,CAAC,sBAAsB,CAAC,EAAE,CAAC,CAAC;QACpD,cAAc,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE;IAC5C,KAAK,EAAE,EAAE;IACT,WAAW,4DAA0C;IACrD,KAAK,CAAC,QAAQ;QACZ,MAAM,QAAQ,GAAG,MAAM,kBAAkB,EAAE,CAAC;QAC5C,OAAO,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC;IACzD,CAAC;CACF,CAAC,CAAC","sourcesContent":["// Copyright 2020 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport type * as Security from './security.js';\n\nconst UIStrings = {\n /**\n *@description Default Title of the security panel\n */\n security: 'Security',\n /**\n *@description Title of security and privacy panel. This is used when the kDevToolsPrivacyUI feature flag is enabled.\n */\n securityAndPrivacy: 'Security & Privacy',\n /**\n *@description Default command to open the security panel\n */\n showSecurity: 'Show Security',\n /**\n *@description Command to open the security and privacy panel. This is used when the kDevToolPrivacyUI feature flag is enabled\n */\n showSecurityAndPrivacy: 'Show Security and Privacy',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/security/security-meta.ts', UIStrings);\nconst i18nLazyString = i18n.i18n.getLazilyComputedLocalizedString.bind(undefined, str_);\n\nlet loadedSecurityModule: (typeof Security|undefined);\n\nasync function loadSecurityModule(): Promise {\n if (!loadedSecurityModule) {\n loadedSecurityModule = await import('./security.js');\n }\n return loadedSecurityModule;\n}\n\nUI.ViewManager.registerViewExtension({\n location: UI.ViewManager.ViewLocationValues.PANEL,\n id: 'security',\n title: () => Common.Settings.Settings.instance().getHostConfig().devToolsPrivacyUI?.enabled ?\n i18nLazyString(UIStrings.securityAndPrivacy)() :\n i18nLazyString(UIStrings.security)(),\n commandPrompt: () => Common.Settings.Settings.instance().getHostConfig().devToolsPrivacyUI?.enabled ?\n i18nLazyString(UIStrings.showSecurityAndPrivacy)() :\n i18nLazyString(UIStrings.showSecurity)(),\n order: 80,\n persistence: UI.ViewManager.ViewPersistence.CLOSEABLE,\n async loadView() {\n const Security = await loadSecurityModule();\n return Security.SecurityPanel.SecurityPanel.instance();\n },\n});\n"]} \ No newline at end of file diff --git a/public/panels/settings/AISettingsTab.js b/public/panels/settings/AISettingsTab.js index 7e7202741..d01ad8038 100644 --- a/public/panels/settings/AISettingsTab.js +++ b/public/panels/settings/AISettingsTab.js @@ -76,7 +76,7 @@ const UIStrings = { */ generatedSnippets: 'Use generated code snippets with caution', /** - *@description Text describing the 'Freestyler' feature + *@description Text describing the 'AI assistant' feature */ helpUnderstandStyling: 'Helps you understand and fix styling issues', /** @@ -84,15 +84,15 @@ const UIStrings = { */ learnMore: 'Learn more', /** - *@description Description of the Freestyler feature + *@description Description of the AI assistant feature */ explainStyling: 'Get explanations and additional context for styling behaviors', /** - *@description Description of the Freestyler feature + *@description Description of the AI assistant feature */ receiveStylingSuggestions: 'Receive suggestions and code samples for fixing styling issues', /** - *@description Explainer for which data is being sent by the Freestyler feature + *@description Explainer for which data is being sent by the AI assistant feature */ freestylerSendsData: 'Any data the inspected page can access via Web APIs may be sent to Google to generate explanations. This data may be seen by human reviewers to improve this feature.', /** @@ -116,9 +116,9 @@ const UIStrings = { */ enableConsoleInsights: 'Enable Console Insights', /** - *@description Label for a toggle to enable the Freestyler feature + *@description Label for a toggle to enable the AI assistant feature */ - enableFreestyler: 'Enable Freestyler', + enableAiAssistant: 'Enable AI assistant', }; const str_ = i18n.i18n.registerUIStrings('panels/settings/AISettingsTab.ts', UIStrings); const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); @@ -344,7 +344,7 @@ export class AISettingsTab extends LegacyWrapper.LegacyWrapper.WrappableComponen <${IconButton.Icon.Icon.litTagName} name="pen-spark">
-

${i18n.i18n.lockedString('Freestyler')}

+

${i18n.i18n.lockedString('AI assistant')}

${i18nString(UIStrings.helpUnderstandStyling)}
diff --git a/public/panels/settings/AISettingsTab.js.map b/public/panels/settings/AISettingsTab.js.map index 4f010112e..1a788f7b8 100644 --- a/public/panels/settings/AISettingsTab.js.map +++ b/public/panels/settings/AISettingsTab.js.map @@ -1 +1 @@ -{"version":3,"file":"AISettingsTab.js","sourceRoot":"","sources":["../../../../../../front_end/panels/settings/AISettingsTab.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,MAAM,MAAM,6BAA6B,CAAC;AACtD,OAAO,KAAK,IAAI,MAAM,yBAAyB,CAAC;AAChD,OAAO,KAAK,OAAO,MAAM,wCAAwC,CAAC;AAClE,OAAO,KAAK,UAAU,MAAM,gDAAgD,CAAC;AAC7E,OAAO,KAAK,KAAK,MAAM,oCAAoC,CAAC;AAC5D,OAAO,KAAK,aAAa,MAAM,sDAAsD,CAAC;AACtF,OAAO,KAAK,MAAM,MAAM,sCAAsC,CAAC;AAC/D,OAAO,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAChD,OAAO,KAAK,OAAO,MAAM,+BAA+B,CAAC;AACzD,OAAO,KAAK,aAAa,MAAM,2CAA2C,CAAC;AAE3E,OAAO,mBAAmB,MAAM,wBAAwB,CAAC;AAEzD,MAAM,SAAS,GAAG;IAChB;;OAEG;IACH,qBAAqB,EAAE,wCAAwC;IAC/D;;OAEG;IACH,gBAAgB,EAAE,oBAAoB;IACtC;;OAEG;IACH,oBAAoB,EAChB,qJAAqJ;IACzJ;;OAEG;IACH,iBAAiB,EACb,oOAAoO;IACxO;;OAEG;IACH,UAAU,EACN,+GAA+G;IACnH;;OAEG;IACH,aAAa,EACT,+LAA+L;IACnM;;OAEG;IACH,qBAAqB,EAAE,0DAA0D;IACjF;;OAEG;IACH,QAAQ,EAAE,WAAW;IACrB;;OAEG;IACH,QAAQ,EAAE,WAAW;IACrB;;OAEG;IACH,MAAM,EAAE,SAAS;IACjB;;OAEG;IACH,cAAc,EAAE,kDAAkD;IAClE;;OAEG;IACH,kBAAkB,EAAE,8DAA8D;IAClF;;OAEG;IACH,wBAAwB,EACpB,qNAAqN;IACzN;;;;OAIG;IACH,2BAA2B,EAAE,uDAAuD;IACpF;;OAEG;IACH,iBAAiB,EAAE,0CAA0C;IAC7D;;OAEG;IACH,qBAAqB,EAAE,6CAA6C;IACpE;;OAEG;IACH,SAAS,EAAE,YAAY;IACvB;;OAEG;IACH,cAAc,EAAE,+DAA+D;IAC/E;;OAEG;IACH,yBAAyB,EAAE,gEAAgE;IAC3F;;OAEG;IACH,mBAAmB,EACf,uKAAuK;IAC3K;;OAEG;IACH,cAAc,EAAE,yBAAyB;IACzC;;OAEG;IACH,aAAa,EAAE,uBAAuB;IACtC;;OAEG;IACH,4BAA4B,EAAE,2EAA2E;IACzG;;OAEG;IACH,QAAQ,EAAE,WAAW;IACrB;;OAEG;IACH,qBAAqB,EAAE,yBAAyB;IAChD;;OAEG;IACH,gBAAgB,EAAE,mBAAmB;CACtC,CAAC;AACF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,kCAAkC,EAAE,SAAS,CAAC,CAAC;AACxF,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAEtE,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,+BAA+B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;AAChG,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,6BAA6B,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;AAE5F,MAAM,OAAO,aAAc,SAAQ,aAAa,CAAC,aAAa,CAAC,kBAAkB;IAC/E,MAAM,CAAU,UAAU,GAAG,OAAO,CAAC,OAAO,CAAA,mCAAmC,CAAC;IACvE,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,EAAC,IAAI,EAAE,MAAM,EAAC,CAAC,CAAC;IACrD,uBAAuB,CAAoC;IAC3D,kBAAkB,CAAoC;IACtD,iCAAiC,GAAG,KAAK,CAAC;IAC1C,4BAA4B,GAAG,KAAK,CAAC;IAErC;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC;YACH,IAAI,CAAC,uBAAuB,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,0BAA0B,CAAC,CAAC;QAC/G,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,uBAAuB,GAAG,SAAS,CAAC;QAC3C,CAAC;QACD,IAAI,CAAC;YACH,IAAI,CAAC,kBAAkB,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,aAAa,CAAC,oBAAoB,CAAC,CAAC;QACpG,CAAC;QAAC,MAAM,CAAC;YACP,IAAI,CAAC,kBAAkB,GAAG,SAAS,CAAC;QACtC,CAAC;IACH,CAAC;IAED,iBAAiB;QACf,IAAI,CAAC,OAAO,CAAC,kBAAkB,GAAG,CAAC,KAAK,CAAC,cAAc,EAAE,mBAAmB,CAAC,CAAC;IAChF,CAAC;IAED,6BAA6B;QAC3B,IAAI,CAAC,iCAAiC,GAAG,CAAC,IAAI,CAAC,iCAAiC,CAAC;QACjF,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;IACrB,CAAC;IAED,6BAA6B,CAAC,EAAS;QACrC,+DAA+D;QAC/D,oEAAoE;QACpE,IAAI,EAAE,CAAC,MAAM,YAAY,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,SAAS,EAAE,CAAC;YACvG,OAAO;QACT,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,CAAC;YAClC,OAAO;QACT,CAAC;QACD,MAAM,eAAe,GAAG,IAAI,CAAC,uBAAuB,CAAC,GAAG,EAAE,CAAC;QAC3D,IAAI,CAAC,uBAAuB,CAAC,GAAG,CAAC,CAAC,eAAe,CAAC,CAAC;QACnD,IAAI,CAAC,eAAe,IAAI,CAAC,IAAI,CAAC,iCAAiC,EAAE,CAAC;YAChE,IAAI,CAAC,iCAAiC,GAAG,IAAI,CAAC;QAChD,CAAC;QACD,IAAI,eAAe,KAAK,KAAK,EAAE,CAAC;YAC9B,2GAA2G;YAC3G,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE;iBAC9B,aAAa,CAAC,gCAAgC,EAAE,IAAI,6DAA6C;iBACjG,GAAG,CAAC,IAAI,CAAC,CAAC;QACjB,CAAC;QACD,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;IACrB,CAAC;IAED,wBAAwB;QACtB,IAAI,CAAC,4BAA4B,GAAG,CAAC,IAAI,CAAC,4BAA4B,CAAC;QACvE,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;IACrB,CAAC;IAED,wBAAwB,CAAC,EAAS;QAChC,+DAA+D;QAC/D,oEAAoE;QACpE,IAAI,EAAE,CAAC,MAAM,YAAY,MAAM,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,SAAS,EAAE,CAAC;YACvG,OAAO;QACT,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC7B,OAAO;QACT,CAAC;QACD,MAAM,eAAe,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,EAAE,CAAC;QACtD,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,eAAe,CAAC,CAAC;QAC9C,IAAI,CAAC,eAAe,IAAI,CAAC,IAAI,CAAC,4BAA4B,EAAE,CAAC;YAC3D,IAAI,CAAC,4BAA4B,GAAG,IAAI,CAAC;QAC3C,CAAC;QACD,EAAE,CAAC,aAAa,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,4BAA4B,CAClE,UAAU,CAAC,SAAS,CAAC,4BAA4B,CAAC,CAAC,CAAC;QACxD,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;IACrB,CAAC;IAED,2BAA2B,CAAC,IAAY,EAAE,IAAqC;QAC7E,qDAAqD;QACrD,mBAAmB;QACnB,OAAO,OAAO,CAAC,IAAI,CAAA;;WAEZ,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,UAAU;YAC1C,QAAQ,EAAE,IAAI;YACd,KAAK,EAAE,qBAAqB;YAC5B,KAAK,EAAE,mBAAmB;YAC1B,MAAM,EAAE,mBAAmB;SACA;YACzB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU;;aAE9B,IAAI;KACZ,CAAC;QACF,kBAAkB;IACpB,CAAC;IAED,uBAAuB;QACrB,MAAM,YAAY,GAAG;YACnB,EAAC,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,oBAAoB,CAAC,EAAC;YACtE,EAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,iBAAiB,CAAC,EAAC;YAC/D,EAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,UAAU,CAAC,EAAC;YAChE,EAAC,IAAI,EAAE,gBAAgB,EAAE,IAAI,EAAE,UAAU,CAAC,SAAS,CAAC,aAAa,CAAC,EAAC;SACpE,CAAC;QACF,OAAO,OAAO,CAAC,IAAI,CAAA;;cAET,UAAU,CAAC,SAAS,CAAC,qBAAqB,CAAC;6CACZ,UAAU,CAAC,SAAS,CAAC,gBAAgB,CAAC;;YAEvE,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,2BAA2B,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;;;KAGvF,CAAC;IACJ,CAAC;IAED,kBAAkB,CAAC,IAAY,EAAE,IAA4D;QAE3F,qDAAqD;QACrD,mBAAmB;QACnB,OAAO,OAAO,CAAC,IAAI,CAAA;;WAEZ,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,UAAU;YAC1C,QAAQ,EAAE,IAAI;YACd,KAAK,EAAE,mBAAmB;YAC1B,MAAM,EAAE,mBAAmB;SACA;YACzB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU;;4BAEf,IAAI;KAC3B,CAAC;QACF,kBAAkB;IACpB,CAAC;IAED,6BAA6B;QAC3B,MAAM,cAAc,GAAG;YACrB,WAAW,EAAE,IAAI;YACjB,IAAI,EAAE,IAAI,CAAC,iCAAiC;SAC7C,CAAC;QACF,MAAM,QAAQ,GAAG,IAAI,CAAC,iCAAiC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;QACrE,MAAM,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CACjC,mCAAmC,EAAE,UAAU,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,SAAS,EAAE,SAAS,EAC/F,kBAAkB,EAAE,QAAQ,CAAC,CAAC;QAClC,MAAM,iBAAiB,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAC3C,qCAAqC,EAAE,UAAU,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,SAAS,EAChG,gBAAgB,EAAE,QAAQ,CAAC,CAAC;QAEhC,qDAAqD;QACrD,mBAAmB;QACnB,OAAO,OAAO,CAAC,IAAI,CAAA;6CACsB,IAAI,CAAC,6BAA6B;;aAElE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,6BAA6B,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU;;;gBAGxF,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,kBAAkB,CAAC;6CACb,UAAU,CAAC,SAAS,CAAC,qBAAqB,CAAC;;;aAG3E,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;oBACzB;YACN,KAAK,EAAE,IAAI,CAAC,iCAAiC,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,QAAQ,CAAC;YAC/G,IAAI,yCAA2B;YAC/B,OAAO,EAAE,IAAI,CAAC,iCAAiC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,kBAAkB;YACvF,OAAO,0CAA6B;YACpC,YAAY,EAAE,4BAA4B;SACd;eAC3B,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;;;;sDAIO,IAAI,CAAC,6BAA6B,CAAC,IAAI,CAAC,IAAI,CAAC;WACxF,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;qBACrB,IAAI,CAAC,uBAAuB,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,QAAQ,EAAE;0BAC3E,IAAI,CAAC,uBAAuB,EAAE,IAAI;sBACtC,IAAI,CAAC,uBAAuB,EAAE,QAAQ,EAAE;kBAC5C,IAAI,CAAC,uBAAuB,EAAE,cAAc,EAAE;0BACtC,IAAI,CAAC,6BAA6B,CAAC,IAAI,CAAC,IAAI,CAAC;uBAChD,IAAI,CAAC,uBAAuB,EAAE,cAAc,EAAE,IAAI,UAAU,CAAC,SAAS,CAAC,qBAAqB,CAAC;aACvG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;;mBAEzB,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,cAAc,CAAC;;;mDAGX,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC;cACjE,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE,UAAU,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;cAC1E,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE,UAAU,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;mDACpC,UAAU,CAAC,SAAS,CAAC,gBAAgB,CAAC;cAC3E,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,UAAU,CAAC,SAAS,CAAC,wBAAwB,CAAC,CAAC;cACjF,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAA;gBAC5C,IAAI,CAAC,IAAI,CAAC,wBAAwB,CAAC,IAAI,EAAE,SAAS,CAAC,2BAA2B,EAAE;YAChF,GAAG,EAAE,OAAO;YACZ,GAAG,EAAE,iBAAiB;SACvB,CAAC;aACH,CAAC;cACA,IAAI,CAAC,kBAAkB,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,CAAA;;;;2BAIlC,QAAQ;wBACX,aAAa,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAC,KAAK,CAAC;YAC3E,KAAK,EAAE,IAAI;SACZ,CAAC;iBACD,UAAU,CAAC,SAAS,CAAC,iBAAiB,CAAC;aAC3C,CAAC;;;;;2BAKa,QAAQ;wBACX,aAAa,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC,KAAK,CAAC;YAC9D,KAAK,EAAE,IAAI;SACZ,CAAC;iBACD,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC;;;;;KAK3C,CAAC;QACF,kBAAkB;IACpB,CAAC;IAED,wBAAwB;QACtB,MAAM,cAAc,GAAG;YACrB,WAAW,EAAE,IAAI;YACjB,IAAI,EAAE,IAAI,CAAC,4BAA4B;SACxC,CAAC;QACF,MAAM,QAAQ,GAAG,IAAI,CAAC,4BAA4B,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;QAEhE,MAAM,OAAO,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CACjC,mCAAmC,EAAE,UAAU,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,SAAS,EAAE,SAAS,EAC/F,kBAAkB,EAAE,QAAQ,CAAC,CAAC;QAClC,MAAM,iBAAiB,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAC3C,qCAAqC,EAAE,UAAU,CAAC,SAAS,CAAC,aAAa,CAAC,EAAE,SAAS,EAAE,SAAS,EAChG,gBAAgB,EAAE,QAAQ,CAAC,CAAC;QAEhC,qDAAqD;QACrD,mBAAmB;QACnB,OAAO,OAAO,CAAC,IAAI,CAAA;6CACsB,IAAI,CAAC,wBAAwB;;aAE7D,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,uBAAuB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU;;;gBAGlF,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC;6CACP,UAAU,CAAC,SAAS,CAAC,qBAAqB,CAAC;;;aAG3E,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;oBACzB;YACN,KAAK,EAAE,IAAI,CAAC,4BAA4B,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,QAAQ,CAAC;YAC1G,IAAI,yCAA2B;YAC/B,OAAO,EAAE,IAAI,CAAC,4BAA4B,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,kBAAkB;YAClF,OAAO,0CAA6B;YACpC,YAAY,EAAE,sBAAsB;SACR;eAC3B,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;;;;sDAIO,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC;WACnF,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;qBACrB,IAAI,CAAC,kBAAkB,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,QAAQ,EAAE;0BACjE,IAAI,CAAC,kBAAkB,EAAE,IAAI;sBACjC,IAAI,CAAC,kBAAkB,EAAE,QAAQ,EAAE;kBACvC,IAAI,CAAC,kBAAkB,EAAE,cAAc,EAAE;0BACjC,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC;uBAC3C,IAAI,CAAC,kBAAkB,EAAE,cAAc,EAAE,IAAI,UAAU,CAAC,SAAS,CAAC,gBAAgB,CAAC;aAC7F,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU;;mBAEzB,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,cAAc,CAAC;;;mDAGX,UAAU,CAAC,SAAS,CAAC,MAAM,CAAC;cACjE,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE,UAAU,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;cAC1E,IAAI,CAAC,kBAAkB,CAAC,MAAM,EAAE,UAAU,CAAC,SAAS,CAAC,yBAAyB,CAAC,CAAC;mDAC3C,UAAU,CAAC,SAAS,CAAC,gBAAgB,CAAC;cAC3E,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,UAAU,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;cAC5E,IAAI,CAAC,kBAAkB,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAA;gBAC5C,IAAI,CAAC,IAAI,CAAC,wBAAwB,CAAC,IAAI,EAAE,SAAS,CAAC,2BAA2B,EAAE;YAChF,GAAG,EAAE,OAAO;YACZ,GAAG,EAAE,iBAAiB;SACvB,CAAC;aACH,CAAC;cACA,IAAI,CAAC,kBAAkB,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,CAAA;;;;2BAIlC,QAAQ;wBACX,aAAa,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAC,KAAK,CAAC;YACrE,KAAK,EAAE,IAAI;SACZ,CAAC;iBACD,UAAU,CAAC,SAAS,CAAC,iBAAiB,CAAC;aAC3C,CAAC;;;;KAIT,CAAC;QACF,kBAAkB;IACpB,CAAC;IAEQ,KAAK,CAAC,MAAM;QACnB,qDAAqD;QACrD,mBAAmB;QACnB,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAA;;cAEjB,UAAU,CAAC,SAAS,CAAC,QAAQ,CAAC;;sDAEU,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC;UAC3E,IAAI,CAAC,uBAAuB,EAAE;UAC9B,IAAI,CAAC,uBAAuB,IAAI,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAA;;cAElE,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC,IAAI,CAAC,6BAA6B,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO;cACrF,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,wBAAwB,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO;;SAEhF,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO;;KAEtB,EAAE,IAAI,CAAC,OAAO,EAAE,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC,CAAC;QAC/B,kBAAkB;IACpB,CAAC;;AAGH,cAAc,CAAC,MAAM,CAAC,mCAAmC,EAAE,aAAa,CAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Buttons from '../../ui/components/buttons/buttons.js';\nimport * as IconButton from '../../ui/components/icon_button/icon_button.js';\nimport * as Input from '../../ui/components/input/input.js';\nimport * as LegacyWrapper from '../../ui/components/legacy_wrapper/legacy_wrapper.js';\nimport * as Switch from '../../ui/components/switch/switch.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as LitHtml from '../../ui/lit-html/lit-html.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport aiSettingsTabStyles from './aiSettingsTab.css.js';\n\nconst UIStrings = {\n /**\n *@description Header text for for a list of things to consider in the context of generative AI features\n */\n boostYourProductivity: 'Boost your productivity with Chrome AI',\n /**\n *@description Text announcing a list of facts to consider (when using a GenAI feature)\n */\n thingsToConsider: 'Things to consider',\n /**\n *@description Text describing a fact to consider when using AI features\n */\n experimentalFeatures:\n 'These features are experimental. They use generative AI and may provide inaccurate or offensive information that does not represent Google’s views.',\n /**\n *@description Text describing a fact to consider when using AI features\n */\n sendsDataToGoogle:\n 'Using these features sends data relevant for the feature to Google. Google collects this data and feedback to improve its products and services with the help of human reviewers. Avoid sharing sensitive or personal information.',\n /**\n *@description Text describing a fact to consider when using AI features\n */\n retainData:\n 'Usage data will be retained for up to 18 months and stored in a way where Google cannot tell who provided it.',\n /**\n *@description Text describing a fact to consider when using AI features\n */\n adminSettings:\n 'Depending on your Google account management and/or region, Google may refrain from data collection. Depending on their organization’s settings, features available to managed users may vary.',\n /**\n *@description Text describing the 'Console Insights' feature\n */\n helpUnderstandConsole: 'Helps you understand and fix console warnings and errors',\n /**\n *@description Label for a button to expand an accordion\n */\n showMore: 'Show more',\n /**\n *@description Label for a button to collapse an accordion\n */\n showLess: 'Show less',\n /**\n *@description Header for a list of feature attributes. 'When (the feature is turned) on, you'll be able to ...'\n */\n whenOn: 'When on',\n /**\n *@description Description of the console insights feature\n */\n explainConsole: 'Get explanations for console warnings and errors',\n /**\n *@description Description of the console insights feature ('these issues' refers to console warnings and errors)\n */\n receiveSuggestions: 'Receive suggestions and code samples to address these issues',\n /**\n *@description Explainer for which data is being sent by the console insights feature\n */\n consoleInsightsSendsData:\n 'The console message, associated stack trace, related source code, and the associated network headers are sent to Google to generate explanations. This data may be seen by human reviewers to improve this feature.',\n /**\n *@description Reference to the terms of service and privacy notice\n *@example {Google Terms of Service} PH1\n *@example {Privacy Notice} PH2\n */\n termsOfServicePrivacyNotice: 'Use of this feature is subject to the {PH1} and {PH2}',\n /**\n *@description Label for a link to a URL, which asks to use generated code responsibly\n */\n generatedSnippets: 'Use generated code snippets with caution',\n /**\n *@description Text describing the 'Freestyler' feature\n */\n helpUnderstandStyling: 'Helps you understand and fix styling issues',\n /**\n *@description Text which is a hyperlink to more documentation\n */\n learnMore: 'Learn more',\n /**\n *@description Description of the Freestyler feature\n */\n explainStyling: 'Get explanations and additional context for styling behaviors',\n /**\n *@description Description of the Freestyler feature\n */\n receiveStylingSuggestions: 'Receive suggestions and code samples for fixing styling issues',\n /**\n *@description Explainer for which data is being sent by the Freestyler feature\n */\n freestylerSendsData:\n 'Any data the inspected page can access via Web APIs may be sent to Google to generate explanations. This data may be seen by human reviewers to improve this feature.',\n /**\n *@description Label for a link to the terms of service\n */\n termsOfService: 'Google Terms of Service',\n /**\n *@description Label for a link to the privacy notice\n */\n privacyNotice: 'Google Privacy Policy',\n /**\n *@description Message to display if a setting change requires a reload of DevTools\n */\n oneOrMoreSettingsHaveChanged: 'One or more settings have changed which requires a reload to take effect.',\n /**\n *@description Header for the Chrome AI settings page\n */\n chromeAi: 'Chrome AI',\n /**\n *@description Label for a toggle to enable the Console Insights feature\n */\n enableConsoleInsights: 'Enable Console Insights',\n /**\n *@description Label for a toggle to enable the Freestyler feature\n */\n enableFreestyler: 'Enable Freestyler',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/settings/AISettingsTab.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nconst chevronDownIconUrl = new URL('../../Images/chevron-down.svg', import.meta.url).toString();\nconst chevronUpIconUrl = new URL('../../Images/chevron-up.svg', import.meta.url).toString();\n\nexport class AISettingsTab extends LegacyWrapper.LegacyWrapper.WrappableComponent {\n static readonly litTagName = LitHtml.literal`devtools-settings-ai-settings-tab`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n #consoleInsightsSetting?: Common.Settings.Setting;\n #freestylerSetting?: Common.Settings.Setting;\n #isConsoleInsightsSettingExpanded = false;\n #isFreestylerSettingExpanded = false;\n\n constructor() {\n super();\n try {\n this.#consoleInsightsSetting = Common.Settings.Settings.instance().moduleSetting('console-insights-enabled');\n } catch {\n this.#consoleInsightsSetting = undefined;\n }\n try {\n this.#freestylerSetting = Common.Settings.Settings.instance().moduleSetting('freestyler-enabled');\n } catch {\n this.#freestylerSetting = undefined;\n }\n }\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [Input.checkboxStyles, aiSettingsTabStyles];\n }\n\n #expandConsoleInsightsSetting(): void {\n this.#isConsoleInsightsSettingExpanded = !this.#isConsoleInsightsSettingExpanded;\n void this.render();\n }\n\n #toggleConsoleInsightsSetting(ev: Event): void {\n // If the switch is being clicked, there is both a click- and a\n // change-event. Aborting on click avoids running this method twice.\n if (ev.target instanceof Switch.Switch.Switch && ev.type !== Switch.Switch.SwitchChangeEvent.eventName) {\n return;\n }\n if (!this.#consoleInsightsSetting) {\n return;\n }\n const oldSettingValue = this.#consoleInsightsSetting.get();\n this.#consoleInsightsSetting.set(!oldSettingValue);\n if (!oldSettingValue && !this.#isConsoleInsightsSettingExpanded) {\n this.#isConsoleInsightsSettingExpanded = true;\n }\n if (oldSettingValue === false) {\n // Allows skipping the consent reminder if the user enabled the feature via settings in the current session\n Common.Settings.Settings.instance()\n .createSetting('console-insights-skip-reminder', true, Common.Settings.SettingStorageType.SESSION)\n .set(true);\n }\n void this.render();\n }\n\n #expandFreestylerSetting(): void {\n this.#isFreestylerSettingExpanded = !this.#isFreestylerSettingExpanded;\n void this.render();\n }\n\n #toggleFreestylerSetting(ev: Event): void {\n // If the switch is being clicked, there is both a click- and a\n // change-event. Aborting on click avoids running this method twice.\n if (ev.target instanceof Switch.Switch.Switch && ev.type !== Switch.Switch.SwitchChangeEvent.eventName) {\n return;\n }\n if (!this.#freestylerSetting) {\n return;\n }\n const oldSettingValue = this.#freestylerSetting.get();\n this.#freestylerSetting.set(!oldSettingValue);\n if (!oldSettingValue && !this.#isFreestylerSettingExpanded) {\n this.#isFreestylerSettingExpanded = true;\n }\n UI.InspectorView.InspectorView.instance().displayReloadRequiredWarning(\n i18nString(UIStrings.oneOrMoreSettingsHaveChanged));\n void this.render();\n }\n\n #renderSharedDisclaimerItem(icon: string, text: Common.UIString.LocalizedString): LitHtml.TemplateResult {\n // Disabled until https://crbug.com/1079231 is fixed.\n // clang-format off\n return LitHtml.html`\n
\n <${IconButton.Icon.Icon.litTagName} .data=${{\n iconName: icon,\n color: 'var(--icon-default)',\n width: 'var(--sys-size-8)',\n height: 'var(--sys-size-8)',\n } as IconButton.Icon.IconData}>\n \n
\n
${text}
\n `;\n // clang-format on\n }\n\n #renderSharedDisclaimer(): LitHtml.TemplateResult {\n const bulletPoints = [\n {icon: 'psychiatry', text: i18nString(UIStrings.experimentalFeatures)},\n {icon: 'google', text: i18nString(UIStrings.sendsDataToGoogle)},\n {icon: 'calendar-today', text: i18nString(UIStrings.retainData)},\n {icon: 'corporate-fare', text: i18nString(UIStrings.adminSettings)},\n ];\n return LitHtml.html`\n
\n

${i18nString(UIStrings.boostYourProductivity)}

\n

${i18nString(UIStrings.thingsToConsider)}

\n
\n ${bulletPoints.map(item => this.#renderSharedDisclaimerItem(item.icon, item.text))}\n
\n
\n `;\n }\n\n #renderSettingItem(icon: string, text: Common.UIString.LocalizedString|LitHtml.TemplateResult):\n LitHtml.TemplateResult {\n // Disabled until https://crbug.com/1079231 is fixed.\n // clang-format off\n return LitHtml.html`\n
\n <${IconButton.Icon.Icon.litTagName} .data=${{\n iconName: icon,\n width: 'var(--sys-size-9)',\n height: 'var(--sys-size-9)',\n } as IconButton.Icon.IconData}>\n \n
\n
${text}
\n `;\n // clang-format on\n }\n\n #renderConsoleInsightsSetting(): LitHtml.TemplateResult {\n const detailsClasses = {\n 'whole-row': true,\n open: this.#isConsoleInsightsSettingExpanded,\n };\n const tabindex = this.#isConsoleInsightsSettingExpanded ? '0' : '-1';\n const tosLink = UI.XLink.XLink.create(\n 'https://policies.google.com/terms', i18nString(UIStrings.termsOfService), undefined, undefined,\n 'terms-of-service', tabindex);\n const privacyNoticeLink = UI.XLink.XLink.create(\n 'https://policies.google.com/privacy', i18nString(UIStrings.privacyNotice), undefined, undefined,\n 'privacy-notice', tabindex);\n\n // Disabled until https://crbug.com/1079231 is fixed.\n // clang-format off\n return LitHtml.html`\n
\n
\n <${IconButton.Icon.Icon.litTagName} name=\"lightbulb-spark\">\n
\n
\n

${i18n.i18n.lockedString('Console Insights')}

\n
${i18nString(UIStrings.helpUnderstandConsole)}
\n
\n
\n <${Buttons.Button.Button.litTagName}\n .data=${{\n title: this.#isConsoleInsightsSettingExpanded ? i18nString(UIStrings.showLess) : i18nString(UIStrings.showMore),\n size: Buttons.Button.Size.SMALL,\n iconUrl: this.#isConsoleInsightsSettingExpanded ? chevronUpIconUrl : chevronDownIconUrl,\n variant: Buttons.Button.Variant.ICON,\n jslogContext: 'console-insights.accordion',\n } as Buttons.Button.ButtonData}\n >\n
\n
\n
\n
\n <${Switch.Switch.Switch.litTagName}\n .checked=${this.#consoleInsightsSetting?.get() && !this.#consoleInsightsSetting?.disabled()}\n .jslogContext=${this.#consoleInsightsSetting?.name}\n .disabled=${this.#consoleInsightsSetting?.disabled()}\n title=${this.#consoleInsightsSetting?.disabledReason()}\n @switchchange=${this.#toggleConsoleInsightsSetting.bind(this)}\n aria-label=${this.#consoleInsightsSetting?.disabledReason() || i18nString(UIStrings.enableConsoleInsights)}\n >\n
\n
\n
\n
\n

${i18nString(UIStrings.whenOn)}

\n ${this.#renderSettingItem('lightbulb', i18nString(UIStrings.explainConsole))}\n ${this.#renderSettingItem('code', i18nString(UIStrings.receiveSuggestions))}\n

${i18nString(UIStrings.thingsToConsider)}

\n ${this.#renderSettingItem('google', i18nString(UIStrings.consoleInsightsSendsData))}\n ${this.#renderSettingItem('policy', LitHtml.html`\n ${i18n.i18n.getFormatLocalizedString(str_, UIStrings.termsOfServicePrivacyNotice, {\n PH1: tosLink,\n PH2: privacyNoticeLink,\n })}\n `)}\n ${this.#renderSettingItem('warning', LitHtml.html`\n ${i18nString(UIStrings.generatedSnippets)}\n `)}\n
\n ${i18nString(UIStrings.learnMore)}\n
\n
\n
\n
\n `;\n // clang-format on\n }\n\n #renderFreestylerSetting(): LitHtml.TemplateResult {\n const detailsClasses = {\n 'whole-row': true,\n open: this.#isFreestylerSettingExpanded,\n };\n const tabindex = this.#isFreestylerSettingExpanded ? '0' : '-1';\n\n const tosLink = UI.XLink.XLink.create(\n 'https://policies.google.com/terms', i18nString(UIStrings.termsOfService), undefined, undefined,\n 'terms-of-service', tabindex);\n const privacyNoticeLink = UI.XLink.XLink.create(\n 'https://policies.google.com/privacy', i18nString(UIStrings.privacyNotice), undefined, undefined,\n 'privacy-notice', tabindex);\n\n // Disabled until https://crbug.com/1079231 is fixed.\n // clang-format off\n return LitHtml.html`\n
\n
\n <${IconButton.Icon.Icon.litTagName} name=\"pen-spark\">\n
\n
\n

${i18n.i18n.lockedString('Freestyler')}

\n
${i18nString(UIStrings.helpUnderstandStyling)}
\n
\n
\n <${Buttons.Button.Button.litTagName}\n .data=${{\n title: this.#isFreestylerSettingExpanded ? i18nString(UIStrings.showLess) : i18nString(UIStrings.showMore),\n size: Buttons.Button.Size.SMALL,\n iconUrl: this.#isFreestylerSettingExpanded ? chevronUpIconUrl : chevronDownIconUrl,\n variant: Buttons.Button.Variant.ICON,\n jslogContext: 'freestyler.accordion',\n } as Buttons.Button.ButtonData}\n >\n
\n
\n
\n
\n <${Switch.Switch.Switch.litTagName}\n .checked=${this.#freestylerSetting?.get() && !this.#freestylerSetting?.disabled()}\n .jslogContext=${this.#freestylerSetting?.name}\n .disabled=${this.#freestylerSetting?.disabled()}\n title=${this.#freestylerSetting?.disabledReason()}\n @switchchange=${this.#toggleFreestylerSetting.bind(this)}\n aria-label=${this.#freestylerSetting?.disabledReason() || i18nString(UIStrings.enableFreestyler)}\n >\n
\n
\n
\n
\n

${i18nString(UIStrings.whenOn)}

\n ${this.#renderSettingItem('lightbulb', i18nString(UIStrings.explainStyling))}\n ${this.#renderSettingItem('code', i18nString(UIStrings.receiveStylingSuggestions))}\n

${i18nString(UIStrings.thingsToConsider)}

\n ${this.#renderSettingItem('google', i18nString(UIStrings.freestylerSendsData))}\n ${this.#renderSettingItem('policy', LitHtml.html`\n ${i18n.i18n.getFormatLocalizedString(str_, UIStrings.termsOfServicePrivacyNotice, {\n PH1: tosLink,\n PH2: privacyNoticeLink,\n })}\n `)}\n ${this.#renderSettingItem('warning', LitHtml.html`\n ${i18nString(UIStrings.generatedSnippets)}\n `)}\n
\n
\n
\n `;\n // clang-format on\n }\n\n override async render(): Promise {\n // Disabled until https://crbug.com/1079231 is fixed.\n // clang-format off\n LitHtml.render(LitHtml.html`\n
\n

${i18nString(UIStrings.chromeAi)}

\n
\n
\n ${this.#renderSharedDisclaimer()}\n ${this.#consoleInsightsSetting || this.#freestylerSetting ? LitHtml.html`\n
\n ${this.#consoleInsightsSetting ? this.#renderConsoleInsightsSetting() : LitHtml.nothing}\n ${this.#freestylerSetting ? this.#renderFreestylerSetting() : LitHtml.nothing}\n
\n ` : LitHtml.nothing}\n
\n `, this.#shadow, {host: this});\n // clang-format on\n }\n}\n\ncustomElements.define('devtools-settings-ai-settings-tab', AISettingsTab);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-settings-ai-settings-tab': AISettingsTab;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"AISettingsTab.js","sourceRoot":"","sources":["../../../../../../front_end/panels/settings/AISettingsTab.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Buttons from '../../ui/components/buttons/buttons.js';\nimport * as IconButton from '../../ui/components/icon_button/icon_button.js';\nimport * as Input from '../../ui/components/input/input.js';\nimport * as LegacyWrapper from '../../ui/components/legacy_wrapper/legacy_wrapper.js';\nimport * as Switch from '../../ui/components/switch/switch.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as LitHtml from '../../ui/lit-html/lit-html.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport aiSettingsTabStyles from './aiSettingsTab.css.js';\n\nconst UIStrings = {\n /**\n *@description Header text for for a list of things to consider in the context of generative AI features\n */\n boostYourProductivity: 'Boost your productivity with Chrome AI',\n /**\n *@description Text announcing a list of facts to consider (when using a GenAI feature)\n */\n thingsToConsider: 'Things to consider',\n /**\n *@description Text describing a fact to consider when using AI features\n */\n experimentalFeatures:\n 'These features are experimental. They use generative AI and may provide inaccurate or offensive information that does not represent Google’s views.',\n /**\n *@description Text describing a fact to consider when using AI features\n */\n sendsDataToGoogle:\n 'Using these features sends data relevant for the feature to Google. Google collects this data and feedback to improve its products and services with the help of human reviewers. Avoid sharing sensitive or personal information.',\n /**\n *@description Text describing a fact to consider when using AI features\n */\n retainData:\n 'Usage data will be retained for up to 18 months and stored in a way where Google cannot tell who provided it.',\n /**\n *@description Text describing a fact to consider when using AI features\n */\n adminSettings:\n 'Depending on your Google account management and/or region, Google may refrain from data collection. Depending on their organization’s settings, features available to managed users may vary.',\n /**\n *@description Text describing the 'Console Insights' feature\n */\n helpUnderstandConsole: 'Helps you understand and fix console warnings and errors',\n /**\n *@description Label for a button to expand an accordion\n */\n showMore: 'Show more',\n /**\n *@description Label for a button to collapse an accordion\n */\n showLess: 'Show less',\n /**\n *@description Header for a list of feature attributes. 'When (the feature is turned) on, you'll be able to ...'\n */\n whenOn: 'When on',\n /**\n *@description Description of the console insights feature\n */\n explainConsole: 'Get explanations for console warnings and errors',\n /**\n *@description Description of the console insights feature ('these issues' refers to console warnings and errors)\n */\n receiveSuggestions: 'Receive suggestions and code samples to address these issues',\n /**\n *@description Explainer for which data is being sent by the console insights feature\n */\n consoleInsightsSendsData:\n 'The console message, associated stack trace, related source code, and the associated network headers are sent to Google to generate explanations. This data may be seen by human reviewers to improve this feature.',\n /**\n *@description Reference to the terms of service and privacy notice\n *@example {Google Terms of Service} PH1\n *@example {Privacy Notice} PH2\n */\n termsOfServicePrivacyNotice: 'Use of this feature is subject to the {PH1} and {PH2}',\n /**\n *@description Label for a link to a URL, which asks to use generated code responsibly\n */\n generatedSnippets: 'Use generated code snippets with caution',\n /**\n *@description Text describing the 'AI assistant' feature\n */\n helpUnderstandStyling: 'Helps you understand and fix styling issues',\n /**\n *@description Text which is a hyperlink to more documentation\n */\n learnMore: 'Learn more',\n /**\n *@description Description of the AI assistant feature\n */\n explainStyling: 'Get explanations and additional context for styling behaviors',\n /**\n *@description Description of the AI assistant feature\n */\n receiveStylingSuggestions: 'Receive suggestions and code samples for fixing styling issues',\n /**\n *@description Explainer for which data is being sent by the AI assistant feature\n */\n freestylerSendsData:\n 'Any data the inspected page can access via Web APIs may be sent to Google to generate explanations. This data may be seen by human reviewers to improve this feature.',\n /**\n *@description Label for a link to the terms of service\n */\n termsOfService: 'Google Terms of Service',\n /**\n *@description Label for a link to the privacy notice\n */\n privacyNotice: 'Google Privacy Policy',\n /**\n *@description Message to display if a setting change requires a reload of DevTools\n */\n oneOrMoreSettingsHaveChanged: 'One or more settings have changed which requires a reload to take effect.',\n /**\n *@description Header for the Chrome AI settings page\n */\n chromeAi: 'Chrome AI',\n /**\n *@description Label for a toggle to enable the Console Insights feature\n */\n enableConsoleInsights: 'Enable Console Insights',\n /**\n *@description Label for a toggle to enable the AI assistant feature\n */\n enableAiAssistant: 'Enable AI assistant',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/settings/AISettingsTab.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nconst chevronDownIconUrl = new URL('../../Images/chevron-down.svg', import.meta.url).toString();\nconst chevronUpIconUrl = new URL('../../Images/chevron-up.svg', import.meta.url).toString();\n\nexport class AISettingsTab extends LegacyWrapper.LegacyWrapper.WrappableComponent {\n static readonly litTagName = LitHtml.literal`devtools-settings-ai-settings-tab`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n #consoleInsightsSetting?: Common.Settings.Setting;\n #freestylerSetting?: Common.Settings.Setting;\n #isConsoleInsightsSettingExpanded = false;\n #isFreestylerSettingExpanded = false;\n\n constructor() {\n super();\n try {\n this.#consoleInsightsSetting = Common.Settings.Settings.instance().moduleSetting('console-insights-enabled');\n } catch {\n this.#consoleInsightsSetting = undefined;\n }\n try {\n this.#freestylerSetting = Common.Settings.Settings.instance().moduleSetting('freestyler-enabled');\n } catch {\n this.#freestylerSetting = undefined;\n }\n }\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [Input.checkboxStyles, aiSettingsTabStyles];\n }\n\n #expandConsoleInsightsSetting(): void {\n this.#isConsoleInsightsSettingExpanded = !this.#isConsoleInsightsSettingExpanded;\n void this.render();\n }\n\n #toggleConsoleInsightsSetting(ev: Event): void {\n // If the switch is being clicked, there is both a click- and a\n // change-event. Aborting on click avoids running this method twice.\n if (ev.target instanceof Switch.Switch.Switch && ev.type !== Switch.Switch.SwitchChangeEvent.eventName) {\n return;\n }\n if (!this.#consoleInsightsSetting) {\n return;\n }\n const oldSettingValue = this.#consoleInsightsSetting.get();\n this.#consoleInsightsSetting.set(!oldSettingValue);\n if (!oldSettingValue && !this.#isConsoleInsightsSettingExpanded) {\n this.#isConsoleInsightsSettingExpanded = true;\n }\n if (oldSettingValue === false) {\n // Allows skipping the consent reminder if the user enabled the feature via settings in the current session\n Common.Settings.Settings.instance()\n .createSetting('console-insights-skip-reminder', true, Common.Settings.SettingStorageType.SESSION)\n .set(true);\n }\n void this.render();\n }\n\n #expandFreestylerSetting(): void {\n this.#isFreestylerSettingExpanded = !this.#isFreestylerSettingExpanded;\n void this.render();\n }\n\n #toggleFreestylerSetting(ev: Event): void {\n // If the switch is being clicked, there is both a click- and a\n // change-event. Aborting on click avoids running this method twice.\n if (ev.target instanceof Switch.Switch.Switch && ev.type !== Switch.Switch.SwitchChangeEvent.eventName) {\n return;\n }\n if (!this.#freestylerSetting) {\n return;\n }\n const oldSettingValue = this.#freestylerSetting.get();\n this.#freestylerSetting.set(!oldSettingValue);\n if (!oldSettingValue && !this.#isFreestylerSettingExpanded) {\n this.#isFreestylerSettingExpanded = true;\n }\n UI.InspectorView.InspectorView.instance().displayReloadRequiredWarning(\n i18nString(UIStrings.oneOrMoreSettingsHaveChanged));\n void this.render();\n }\n\n #renderSharedDisclaimerItem(icon: string, text: Common.UIString.LocalizedString): LitHtml.TemplateResult {\n // Disabled until https://crbug.com/1079231 is fixed.\n // clang-format off\n return LitHtml.html`\n
\n <${IconButton.Icon.Icon.litTagName} .data=${{\n iconName: icon,\n color: 'var(--icon-default)',\n width: 'var(--sys-size-8)',\n height: 'var(--sys-size-8)',\n } as IconButton.Icon.IconData}>\n \n
\n
${text}
\n `;\n // clang-format on\n }\n\n #renderSharedDisclaimer(): LitHtml.TemplateResult {\n const bulletPoints = [\n {icon: 'psychiatry', text: i18nString(UIStrings.experimentalFeatures)},\n {icon: 'google', text: i18nString(UIStrings.sendsDataToGoogle)},\n {icon: 'calendar-today', text: i18nString(UIStrings.retainData)},\n {icon: 'corporate-fare', text: i18nString(UIStrings.adminSettings)},\n ];\n return LitHtml.html`\n
\n

${i18nString(UIStrings.boostYourProductivity)}

\n

${i18nString(UIStrings.thingsToConsider)}

\n
\n ${bulletPoints.map(item => this.#renderSharedDisclaimerItem(item.icon, item.text))}\n
\n
\n `;\n }\n\n #renderSettingItem(icon: string, text: Common.UIString.LocalizedString|LitHtml.TemplateResult):\n LitHtml.TemplateResult {\n // Disabled until https://crbug.com/1079231 is fixed.\n // clang-format off\n return LitHtml.html`\n
\n <${IconButton.Icon.Icon.litTagName} .data=${{\n iconName: icon,\n width: 'var(--sys-size-9)',\n height: 'var(--sys-size-9)',\n } as IconButton.Icon.IconData}>\n \n
\n
${text}
\n `;\n // clang-format on\n }\n\n #renderConsoleInsightsSetting(): LitHtml.TemplateResult {\n const detailsClasses = {\n 'whole-row': true,\n open: this.#isConsoleInsightsSettingExpanded,\n };\n const tabindex = this.#isConsoleInsightsSettingExpanded ? '0' : '-1';\n const tosLink = UI.XLink.XLink.create(\n 'https://policies.google.com/terms', i18nString(UIStrings.termsOfService), undefined, undefined,\n 'terms-of-service', tabindex);\n const privacyNoticeLink = UI.XLink.XLink.create(\n 'https://policies.google.com/privacy', i18nString(UIStrings.privacyNotice), undefined, undefined,\n 'privacy-notice', tabindex);\n\n // Disabled until https://crbug.com/1079231 is fixed.\n // clang-format off\n return LitHtml.html`\n
\n
\n <${IconButton.Icon.Icon.litTagName} name=\"lightbulb-spark\">\n
\n
\n

${i18n.i18n.lockedString('Console Insights')}

\n
${i18nString(UIStrings.helpUnderstandConsole)}
\n
\n
\n <${Buttons.Button.Button.litTagName}\n .data=${{\n title: this.#isConsoleInsightsSettingExpanded ? i18nString(UIStrings.showLess) : i18nString(UIStrings.showMore),\n size: Buttons.Button.Size.SMALL,\n iconUrl: this.#isConsoleInsightsSettingExpanded ? chevronUpIconUrl : chevronDownIconUrl,\n variant: Buttons.Button.Variant.ICON,\n jslogContext: 'console-insights.accordion',\n } as Buttons.Button.ButtonData}\n >\n
\n
\n
\n
\n <${Switch.Switch.Switch.litTagName}\n .checked=${this.#consoleInsightsSetting?.get() && !this.#consoleInsightsSetting?.disabled()}\n .jslogContext=${this.#consoleInsightsSetting?.name}\n .disabled=${this.#consoleInsightsSetting?.disabled()}\n title=${this.#consoleInsightsSetting?.disabledReason()}\n @switchchange=${this.#toggleConsoleInsightsSetting.bind(this)}\n aria-label=${this.#consoleInsightsSetting?.disabledReason() || i18nString(UIStrings.enableConsoleInsights)}\n >\n
\n
\n
\n
\n

${i18nString(UIStrings.whenOn)}

\n ${this.#renderSettingItem('lightbulb', i18nString(UIStrings.explainConsole))}\n ${this.#renderSettingItem('code', i18nString(UIStrings.receiveSuggestions))}\n

${i18nString(UIStrings.thingsToConsider)}

\n ${this.#renderSettingItem('google', i18nString(UIStrings.consoleInsightsSendsData))}\n ${this.#renderSettingItem('policy', LitHtml.html`\n ${i18n.i18n.getFormatLocalizedString(str_, UIStrings.termsOfServicePrivacyNotice, {\n PH1: tosLink,\n PH2: privacyNoticeLink,\n })}\n `)}\n ${this.#renderSettingItem('warning', LitHtml.html`\n ${i18nString(UIStrings.generatedSnippets)}\n `)}\n
\n ${i18nString(UIStrings.learnMore)}\n
\n
\n
\n
\n `;\n // clang-format on\n }\n\n #renderFreestylerSetting(): LitHtml.TemplateResult {\n const detailsClasses = {\n 'whole-row': true,\n open: this.#isFreestylerSettingExpanded,\n };\n const tabindex = this.#isFreestylerSettingExpanded ? '0' : '-1';\n\n const tosLink = UI.XLink.XLink.create(\n 'https://policies.google.com/terms', i18nString(UIStrings.termsOfService), undefined, undefined,\n 'terms-of-service', tabindex);\n const privacyNoticeLink = UI.XLink.XLink.create(\n 'https://policies.google.com/privacy', i18nString(UIStrings.privacyNotice), undefined, undefined,\n 'privacy-notice', tabindex);\n\n // Disabled until https://crbug.com/1079231 is fixed.\n // clang-format off\n return LitHtml.html`\n
\n
\n <${IconButton.Icon.Icon.litTagName} name=\"pen-spark\">\n
\n
\n

${i18n.i18n.lockedString('AI assistant')}

\n
${i18nString(UIStrings.helpUnderstandStyling)}
\n
\n
\n <${Buttons.Button.Button.litTagName}\n .data=${{\n title: this.#isFreestylerSettingExpanded ? i18nString(UIStrings.showLess) : i18nString(UIStrings.showMore),\n size: Buttons.Button.Size.SMALL,\n iconUrl: this.#isFreestylerSettingExpanded ? chevronUpIconUrl : chevronDownIconUrl,\n variant: Buttons.Button.Variant.ICON,\n jslogContext: 'freestyler.accordion',\n } as Buttons.Button.ButtonData}\n >\n
\n
\n
\n
\n <${Switch.Switch.Switch.litTagName}\n .checked=${this.#freestylerSetting?.get() && !this.#freestylerSetting?.disabled()}\n .jslogContext=${this.#freestylerSetting?.name}\n .disabled=${this.#freestylerSetting?.disabled()}\n title=${this.#freestylerSetting?.disabledReason()}\n @switchchange=${this.#toggleFreestylerSetting.bind(this)}\n aria-label=${this.#freestylerSetting?.disabledReason() || i18nString(UIStrings.enableAiAssistant)}\n >\n
\n
\n
\n
\n

${i18nString(UIStrings.whenOn)}

\n ${this.#renderSettingItem('lightbulb', i18nString(UIStrings.explainStyling))}\n ${this.#renderSettingItem('code', i18nString(UIStrings.receiveStylingSuggestions))}\n

${i18nString(UIStrings.thingsToConsider)}

\n ${this.#renderSettingItem('google', i18nString(UIStrings.freestylerSendsData))}\n ${this.#renderSettingItem('policy', LitHtml.html`\n ${i18n.i18n.getFormatLocalizedString(str_, UIStrings.termsOfServicePrivacyNotice, {\n PH1: tosLink,\n PH2: privacyNoticeLink,\n })}\n `)}\n ${this.#renderSettingItem('warning', LitHtml.html`\n ${i18nString(UIStrings.generatedSnippets)}\n `)}\n
\n
\n
\n `;\n // clang-format on\n }\n\n override async render(): Promise {\n // Disabled until https://crbug.com/1079231 is fixed.\n // clang-format off\n LitHtml.render(LitHtml.html`\n
\n

${i18nString(UIStrings.chromeAi)}

\n
\n
\n ${this.#renderSharedDisclaimer()}\n ${this.#consoleInsightsSetting || this.#freestylerSetting ? LitHtml.html`\n
\n ${this.#consoleInsightsSetting ? this.#renderConsoleInsightsSetting() : LitHtml.nothing}\n ${this.#freestylerSetting ? this.#renderFreestylerSetting() : LitHtml.nothing}\n
\n ` : LitHtml.nothing}\n
\n `, this.#shadow, {host: this});\n // clang-format on\n }\n}\n\ncustomElements.define('devtools-settings-ai-settings-tab', AISettingsTab);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-settings-ai-settings-tab': AISettingsTab;\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/settings/AISettingsTab.test.js b/public/panels/settings/AISettingsTab.test.js index 52626f467..e565f3ede 100644 --- a/public/panels/settings/AISettingsTab.test.js +++ b/public/panels/settings/AISettingsTab.test.js @@ -36,7 +36,7 @@ describeWithEnvironment('AISettingsTab', () => { assert.strictEqual(sharedDisclaimerHeader?.textContent, 'Boost your productivity with Chrome AI'); const settingCards = view.shadowRoot.querySelectorAll('.setting-card h2'); const settingNames = Array.from(settingCards).map(element => element.textContent); - assert.deepEqual(settingNames, ['Console Insights', 'Freestyler']); + assert.deepEqual(settingNames, ['Console Insights', 'AI assistant']); }); it('can turn feature on, which automatically expands it', async () => { const { switches, details } = await renderAISettings(); diff --git a/public/panels/settings/AISettingsTab.test.js.map b/public/panels/settings/AISettingsTab.test.js.map index a2fd9bcfb..e20deece8 100644 --- a/public/panels/settings/AISettingsTab.test.js.map +++ b/public/panels/settings/AISettingsTab.test.js.map @@ -1 +1 @@ -{"version":3,"file":"AISettingsTab.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/settings/AISettingsTab.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport {renderElementIntoDOM} from '../../testing/DOMHelpers.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport * as Switch from '../../ui/components/switch/switch.js';\n\nimport * as Settings from './settings.js';\n\ndescribeWithEnvironment('AISettingsTab', () => {\n function isExpanded(details: Element): boolean {\n return details.classList.contains('open');\n }\n\n async function renderAISettings(): Promise<{\n switches: Switch.Switch.Switch[],\n details: Element[],\n dropdownButtons: HTMLElement[],\n }> {\n Common.Settings.moduleSetting('console-insights-enabled').set(false);\n Common.Settings.moduleSetting('freestyler-enabled').set(true);\n\n const view = new Settings.AISettingsTab.AISettingsTab();\n renderElementIntoDOM(view);\n await view.render();\n assert.isNotNull(view.shadowRoot);\n\n const switches = Array.from(view.shadowRoot.querySelectorAll('devtools-switch')) as Switch.Switch.Switch[];\n assert.strictEqual(switches.length, 2);\n const details = Array.from(view.shadowRoot.querySelectorAll('.whole-row'));\n assert.strictEqual(details.length, 2);\n const dropdownButtons = Array.from(view.shadowRoot.querySelectorAll('.dropdown devtools-button')) as HTMLElement[];\n assert.strictEqual(dropdownButtons.length, 2);\n return {switches, details, dropdownButtons};\n }\n\n it('renders', async () => {\n Common.Settings.moduleSetting('console-insights-enabled').set(true);\n Common.Settings.moduleSetting('freestyler-enabled').set(true);\n\n const view = new Settings.AISettingsTab.AISettingsTab();\n renderElementIntoDOM(view);\n await view.render();\n assert.isNotNull(view.shadowRoot);\n\n const sharedDisclaimerHeader = view.shadowRoot.querySelector('.shared-disclaimer h2');\n assert.strictEqual(sharedDisclaimerHeader?.textContent, 'Boost your productivity with Chrome AI');\n\n const settingCards = view.shadowRoot.querySelectorAll('.setting-card h2');\n const settingNames = Array.from(settingCards).map(element => element.textContent);\n assert.deepEqual(settingNames, ['Console Insights', 'Freestyler']);\n });\n\n it('can turn feature on, which automatically expands it', async () => {\n const {switches, details} = await renderAISettings();\n assert.isFalse(Common.Settings.moduleSetting('console-insights-enabled').get());\n assert.isFalse(isExpanded(details[0]));\n\n switches[0].dispatchEvent(new Switch.Switch.SwitchChangeEvent(true));\n assert.isTrue(Common.Settings.moduleSetting('console-insights-enabled').get());\n assert.isTrue(isExpanded(details[0]));\n });\n\n it('can expand and collaps details via click', async () => {\n const {details, dropdownButtons} = await renderAISettings();\n assert.isFalse(isExpanded(details[0]));\n assert.isFalse(Common.Settings.moduleSetting('console-insights-enabled').get());\n\n dropdownButtons[0].click();\n assert.isTrue(isExpanded(details[0]));\n assert.isFalse(Common.Settings.moduleSetting('console-insights-enabled').get());\n\n dropdownButtons[0].click();\n assert.isFalse(isExpanded(details[0]));\n assert.isFalse(Common.Settings.moduleSetting('console-insights-enabled').get());\n });\n\n it('can turn feature off without collapsing it', async () => {\n const {switches, details, dropdownButtons} = await renderAISettings();\n dropdownButtons[1].click();\n assert.isTrue(Common.Settings.moduleSetting('freestyler-enabled').get());\n assert.isTrue(isExpanded(details[1]));\n\n (switches[1].parentElement as HTMLElement).click();\n assert.isFalse(Common.Settings.moduleSetting('freestyler-enabled').get());\n assert.isTrue(isExpanded(details[1]));\n });\n\n it('renders disabled switch component with reason', async () => {\n Common.Settings.moduleSetting('console-insights-enabled').setRegistration({\n settingName: 'console-insights-enabled',\n settingType: Common.Settings.SettingType.BOOLEAN,\n defaultValue: false,\n disabledCondition: () => {\n return {disabled: true, reason: 'reason 1'};\n },\n });\n Common.Settings.moduleSetting('freestyler-enabled').setRegistration({\n settingName: 'freestyler-enabled',\n settingType: Common.Settings.SettingType.BOOLEAN,\n defaultValue: true,\n disabledCondition: () => {\n return {disabled: true, reason: 'reason 2'};\n },\n });\n const {switches} = await renderAISettings();\n assert.isTrue(switches[0].disabled);\n assert.strictEqual(switches[0].title, 'reason 1');\n assert.isTrue(switches[1].disabled);\n assert.strictEqual(switches[1].title, 'reason 2');\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"AISettingsTab.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/settings/AISettingsTab.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport {renderElementIntoDOM} from '../../testing/DOMHelpers.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport * as Switch from '../../ui/components/switch/switch.js';\n\nimport * as Settings from './settings.js';\n\ndescribeWithEnvironment('AISettingsTab', () => {\n function isExpanded(details: Element): boolean {\n return details.classList.contains('open');\n }\n\n async function renderAISettings(): Promise<{\n switches: Switch.Switch.Switch[],\n details: Element[],\n dropdownButtons: HTMLElement[],\n }> {\n Common.Settings.moduleSetting('console-insights-enabled').set(false);\n Common.Settings.moduleSetting('freestyler-enabled').set(true);\n\n const view = new Settings.AISettingsTab.AISettingsTab();\n renderElementIntoDOM(view);\n await view.render();\n assert.isNotNull(view.shadowRoot);\n\n const switches = Array.from(view.shadowRoot.querySelectorAll('devtools-switch')) as Switch.Switch.Switch[];\n assert.strictEqual(switches.length, 2);\n const details = Array.from(view.shadowRoot.querySelectorAll('.whole-row'));\n assert.strictEqual(details.length, 2);\n const dropdownButtons = Array.from(view.shadowRoot.querySelectorAll('.dropdown devtools-button')) as HTMLElement[];\n assert.strictEqual(dropdownButtons.length, 2);\n return {switches, details, dropdownButtons};\n }\n\n it('renders', async () => {\n Common.Settings.moduleSetting('console-insights-enabled').set(true);\n Common.Settings.moduleSetting('freestyler-enabled').set(true);\n\n const view = new Settings.AISettingsTab.AISettingsTab();\n renderElementIntoDOM(view);\n await view.render();\n assert.isNotNull(view.shadowRoot);\n\n const sharedDisclaimerHeader = view.shadowRoot.querySelector('.shared-disclaimer h2');\n assert.strictEqual(sharedDisclaimerHeader?.textContent, 'Boost your productivity with Chrome AI');\n\n const settingCards = view.shadowRoot.querySelectorAll('.setting-card h2');\n const settingNames = Array.from(settingCards).map(element => element.textContent);\n assert.deepEqual(settingNames, ['Console Insights', 'AI assistant']);\n });\n\n it('can turn feature on, which automatically expands it', async () => {\n const {switches, details} = await renderAISettings();\n assert.isFalse(Common.Settings.moduleSetting('console-insights-enabled').get());\n assert.isFalse(isExpanded(details[0]));\n\n switches[0].dispatchEvent(new Switch.Switch.SwitchChangeEvent(true));\n assert.isTrue(Common.Settings.moduleSetting('console-insights-enabled').get());\n assert.isTrue(isExpanded(details[0]));\n });\n\n it('can expand and collaps details via click', async () => {\n const {details, dropdownButtons} = await renderAISettings();\n assert.isFalse(isExpanded(details[0]));\n assert.isFalse(Common.Settings.moduleSetting('console-insights-enabled').get());\n\n dropdownButtons[0].click();\n assert.isTrue(isExpanded(details[0]));\n assert.isFalse(Common.Settings.moduleSetting('console-insights-enabled').get());\n\n dropdownButtons[0].click();\n assert.isFalse(isExpanded(details[0]));\n assert.isFalse(Common.Settings.moduleSetting('console-insights-enabled').get());\n });\n\n it('can turn feature off without collapsing it', async () => {\n const {switches, details, dropdownButtons} = await renderAISettings();\n dropdownButtons[1].click();\n assert.isTrue(Common.Settings.moduleSetting('freestyler-enabled').get());\n assert.isTrue(isExpanded(details[1]));\n\n (switches[1].parentElement as HTMLElement).click();\n assert.isFalse(Common.Settings.moduleSetting('freestyler-enabled').get());\n assert.isTrue(isExpanded(details[1]));\n });\n\n it('renders disabled switch component with reason', async () => {\n Common.Settings.moduleSetting('console-insights-enabled').setRegistration({\n settingName: 'console-insights-enabled',\n settingType: Common.Settings.SettingType.BOOLEAN,\n defaultValue: false,\n disabledCondition: () => {\n return {disabled: true, reason: 'reason 1'};\n },\n });\n Common.Settings.moduleSetting('freestyler-enabled').setRegistration({\n settingName: 'freestyler-enabled',\n settingType: Common.Settings.SettingType.BOOLEAN,\n defaultValue: true,\n disabledCondition: () => {\n return {disabled: true, reason: 'reason 2'};\n },\n });\n const {switches} = await renderAISettings();\n assert.isTrue(switches[0].disabled);\n assert.strictEqual(switches[0].title, 'reason 1');\n assert.isTrue(switches[1].disabled);\n assert.strictEqual(switches[1].title, 'reason 2');\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/settings/aiSettingsTab.css.js b/public/panels/settings/aiSettingsTab.css.js index 848ef6755..2b3ab7d69 100644 --- a/public/panels/settings/aiSettingsTab.css.js +++ b/public/panels/settings/aiSettingsTab.css.js @@ -19,6 +19,7 @@ header > h1 { font-size: 18px; font-weight: normal; margin: 0; + white-space: nowrap; } .shared-disclaimer { diff --git a/public/panels/sources/navigatorTree.css.js b/public/panels/sources/navigatorTree.css.js index 46f92848d..c78a39410 100644 --- a/public/panels/sources/navigatorTree.css.js +++ b/public/panels/sources/navigatorTree.css.js @@ -35,7 +35,10 @@ styles.replaceSync( */ .is-ignore-listed { - opacity: 40%; + .tree-element-title, + .leading-icons { + opacity: 40%; + } } .tree-outline li { diff --git a/public/panels/timeline/ActiveFilters.d.ts b/public/panels/timeline/ActiveFilters.d.ts index becc38b6f..37e22ca39 100644 --- a/public/panels/timeline/ActiveFilters.d.ts +++ b/public/panels/timeline/ActiveFilters.d.ts @@ -1,5 +1,5 @@ import type * as TimelineModel from '../../models/timeline_model/timeline_model.js'; -import type * as TraceEngine from '../../models/trace/trace.js'; +import type * as Trace from '../../models/trace/trace.js'; /** Singleton class that contains the set of active filters for the given trace * file. */ @@ -11,5 +11,5 @@ export declare class ActiveFilters { static removeInstance(): void; activeFilters(): readonly TimelineModel.TimelineModelFilter.TimelineModelFilter[]; setFilters(newFilters: TimelineModel.TimelineModelFilter.TimelineModelFilter[]): void; - isVisible(event: TraceEngine.Types.TraceEvents.TraceEventData): boolean; + isVisible(event: Trace.Types.Events.Event): boolean; } diff --git a/public/panels/timeline/ActiveFilters.js.map b/public/panels/timeline/ActiveFilters.js.map index 95a8c2ab8..5679fb938 100644 --- a/public/panels/timeline/ActiveFilters.js.map +++ b/public/panels/timeline/ActiveFilters.js.map @@ -1 +1 @@ -{"version":3,"file":"ActiveFilters.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/ActiveFilters.ts"],"names":[],"mappings":"AAMA,IAAI,QAAQ,GAAuB,IAAI,CAAC;AACxC;;GAEG;AACH,MAAM,OAAO,aAAa;IACxB,MAAM,CAAC,QAAQ,CAAC,OAEZ,EAAC,QAAQ,EAAE,IAAI,EAAC;QAClB,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,QAAQ,IAAI,QAAQ,EAAE,CAAC;YAC1B,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;QACjC,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,CAAC,cAAc;QACnB,QAAQ,GAAG,IAAI,CAAC;IAClB,CAAC;IAED,cAAc,GAA4D,EAAE,CAAC;IAE7E,aAAa;QACX,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,UAAU,CAAC,UAAmE;QAC5E,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC;IACnC,CAAC;IAED,SAAS,CAAC,KAAmD;QAC3D,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACzD,CAAC;CACF","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport type * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport type * as TraceEngine from '../../models/trace/trace.js';\n\nlet instance: ActiveFilters|null = null;\n/** Singleton class that contains the set of active filters for the given trace\n * file.\n */\nexport class ActiveFilters {\n static instance(opts: {\n forceNew: boolean|null,\n } = {forceNew: null}): ActiveFilters {\n const forceNew = Boolean(opts.forceNew);\n if (!instance || forceNew) {\n instance = new ActiveFilters();\n }\n return instance;\n }\n\n static removeInstance(): void {\n instance = null;\n }\n\n #activeFilters: TimelineModel.TimelineModelFilter.TimelineModelFilter[] = [];\n\n activeFilters(): readonly TimelineModel.TimelineModelFilter.TimelineModelFilter[] {\n return this.#activeFilters;\n }\n\n setFilters(newFilters: TimelineModel.TimelineModelFilter.TimelineModelFilter[]): void {\n this.#activeFilters = newFilters;\n }\n\n isVisible(event: TraceEngine.Types.TraceEvents.TraceEventData): boolean {\n return this.#activeFilters.every(f => f.accept(event));\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"ActiveFilters.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/ActiveFilters.ts"],"names":[],"mappings":"AAMA,IAAI,QAAQ,GAAuB,IAAI,CAAC;AACxC;;GAEG;AACH,MAAM,OAAO,aAAa;IACxB,MAAM,CAAC,QAAQ,CAAC,OAEZ,EAAC,QAAQ,EAAE,IAAI,EAAC;QAClB,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,CAAC,QAAQ,IAAI,QAAQ,EAAE,CAAC;YAC1B,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;QACjC,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,CAAC,cAAc;QACnB,QAAQ,GAAG,IAAI,CAAC;IAClB,CAAC;IAED,cAAc,GAA4D,EAAE,CAAC;IAE7E,aAAa;QACX,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,UAAU,CAAC,UAAmE;QAC5E,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC;IACnC,CAAC;IAED,SAAS,CAAC,KAA+B;QACvC,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACzD,CAAC;CACF","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport type * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport type * as Trace from '../../models/trace/trace.js';\n\nlet instance: ActiveFilters|null = null;\n/** Singleton class that contains the set of active filters for the given trace\n * file.\n */\nexport class ActiveFilters {\n static instance(opts: {\n forceNew: boolean|null,\n } = {forceNew: null}): ActiveFilters {\n const forceNew = Boolean(opts.forceNew);\n if (!instance || forceNew) {\n instance = new ActiveFilters();\n }\n return instance;\n }\n\n static removeInstance(): void {\n instance = null;\n }\n\n #activeFilters: TimelineModel.TimelineModelFilter.TimelineModelFilter[] = [];\n\n activeFilters(): readonly TimelineModel.TimelineModelFilter.TimelineModelFilter[] {\n return this.#activeFilters;\n }\n\n setFilters(newFilters: TimelineModel.TimelineModelFilter.TimelineModelFilter[]): void {\n this.#activeFilters = newFilters;\n }\n\n isVisible(event: Trace.Types.Events.Event): boolean {\n return this.#activeFilters.every(f => f.accept(event));\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/AnimationsTrackAppender.d.ts b/public/panels/timeline/AnimationsTrackAppender.d.ts index 1b3487d20..8406f765f 100644 --- a/public/panels/timeline/AnimationsTrackAppender.d.ts +++ b/public/panels/timeline/AnimationsTrackAppender.d.ts @@ -1,9 +1,11 @@ -import type * as TraceEngine from '../../models/trace/trace.js'; -import { type CompatibilityTracksAppender, type TrackAppender, type TrackAppenderName } from './CompatibilityTracksAppender.js'; +import type * as Trace from '../../models/trace/trace.js'; +import { type CompatibilityTracksAppender, type HighlightedEntryInfo, type TrackAppender, type TrackAppenderName } from './CompatibilityTracksAppender.js'; export declare class AnimationsTrackAppender implements TrackAppender { #private; readonly appenderName: TrackAppenderName; - constructor(compatibilityBuilder: CompatibilityTracksAppender, traceParsedData: TraceEngine.Handlers.Types.TraceParseData); + constructor(compatibilityBuilder: CompatibilityTracksAppender, parsedTrace: Trace.Handlers.Types.ParsedTrace); appendTrackAtLevel(trackStartLevel: number, expanded?: boolean | undefined): number; colorForEvent(): string; + titleForEvent(event: Trace.Types.Events.SyntheticAnimationPair): string; + highlightedEntryInfo(event: Trace.Types.Events.SyntheticAnimationPair): HighlightedEntryInfo; } diff --git a/public/panels/timeline/AnimationsTrackAppender.js b/public/panels/timeline/AnimationsTrackAppender.js index 5c4399c99..ecf75e2d3 100644 --- a/public/panels/timeline/AnimationsTrackAppender.js +++ b/public/panels/timeline/AnimationsTrackAppender.js @@ -3,7 +3,7 @@ // found in the LICENSE file. import * as i18n from '../../core/i18n/i18n.js'; import * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js'; -import { buildGroupStyle, buildTrackHeader } from './AppenderUtils.js'; +import { buildGroupStyle, buildTrackHeader, getFormattedTime } from './AppenderUtils.js'; const UIStrings = { /** *@description Text in Timeline Flame Chart Data Provider of the Performance panel @@ -15,13 +15,13 @@ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); export class AnimationsTrackAppender { appenderName = 'Animations'; #compatibilityBuilder; - #traceParsedData; - constructor(compatibilityBuilder, traceParsedData) { + #parsedTrace; + constructor(compatibilityBuilder, parsedTrace) { this.#compatibilityBuilder = compatibilityBuilder; - this.#traceParsedData = traceParsedData; + this.#parsedTrace = parsedTrace; } appendTrackAtLevel(trackStartLevel, expanded) { - const animations = this.#traceParsedData.Animations.animations; + const animations = this.#parsedTrace.Animations.animations; if (animations.length === 0) { return trackStartLevel; } @@ -37,5 +37,13 @@ export class AnimationsTrackAppender { colorForEvent() { return ThemeSupport.ThemeSupport.instance().getComputedValue('--app-color-rendering'); } + titleForEvent(event) { + const { displayName } = event.args.data.beginEvent.args.data; + return displayName || event.name; + } + highlightedEntryInfo(event) { + const title = this.titleForEvent(event); + return { title, formattedTime: getFormattedTime(event.dur) }; + } } //# sourceMappingURL=AnimationsTrackAppender.js.map \ No newline at end of file diff --git a/public/panels/timeline/AnimationsTrackAppender.js.map b/public/panels/timeline/AnimationsTrackAppender.js.map index 5dc1ef9a8..d3819da8c 100644 --- a/public/panels/timeline/AnimationsTrackAppender.js.map +++ b/public/panels/timeline/AnimationsTrackAppender.js.map @@ -1 +1 @@ -{"version":3,"file":"AnimationsTrackAppender.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/AnimationsTrackAppender.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,IAAI,MAAM,yBAAyB,CAAC;AAEhD,OAAO,KAAK,YAAY,MAAM,gDAAgD,CAAC;AAE/E,OAAO,EAAC,eAAe,EAAE,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AAQrE,MAAM,SAAS,GAAG;IAChB;;OAEG;IACH,UAAU,EAAE,YAAY;CACzB,CAAC;AAEF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,4CAA4C,EAAE,SAAS,CAAC,CAAC;AAClG,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAEtE,MAAM,OAAO,uBAAuB;IACzB,YAAY,GAAsB,YAAY,CAAC;IAExD,qBAAqB,CAA8B;IACnD,gBAAgB,CAAsD;IAEtE,YACI,oBAAiD,EAAE,eAA0D;QAC/G,IAAI,CAAC,qBAAqB,GAAG,oBAAoB,CAAC;QAClD,IAAI,CAAC,gBAAgB,GAAG,eAAe,CAAC;IAC1C,CAAC;IAED,kBAAkB,CAAC,eAAuB,EAAE,QAA4B;QACtE,MAAM,UAAU,GAAG,IAAI,CAAC,gBAAgB,CAAC,UAAU,CAAC,UAAU,CAAC;QAC/D,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,OAAO,eAAe,CAAC;QACzB,CAAC;QACD,IAAI,CAAC,yBAAyB,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC,qBAAqB,CAAC,mBAAmB,CAAC,UAAU,EAAE,eAAe,EAAE,IAAI,CAAC,CAAC;IAC3F,CAAC;IAED,yBAAyB,CAAC,YAAoB,EAAE,QAAkB;QAChE,MAAM,KAAK,GAAG,eAAe,CAAC,EAAC,uBAAuB,EAAE,KAAK,EAAC,CAAC,CAAC;QAChE,MAAM,KAAK,GAAG,gBAAgB,uDACS,YAAY,EAAE,UAAU,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,KAAK;QACxF,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACtC,IAAI,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAChE,CAAC;IAED,aAAa;QACX,OAAO,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,CAAC;IACxF,CAAC;CACF","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../core/i18n/i18n.js';\nimport type * as TraceEngine from '../../models/trace/trace.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\n\nimport {buildGroupStyle, buildTrackHeader} from './AppenderUtils.js';\nimport {\n type CompatibilityTracksAppender,\n type TrackAppender,\n type TrackAppenderName,\n VisualLoggingTrackName,\n} from './CompatibilityTracksAppender.js';\n\nconst UIStrings = {\n /**\n *@description Text in Timeline Flame Chart Data Provider of the Performance panel\n */\n animations: 'Animations',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/AnimationsTrackAppender.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport class AnimationsTrackAppender implements TrackAppender {\n readonly appenderName: TrackAppenderName = 'Animations';\n\n #compatibilityBuilder: CompatibilityTracksAppender;\n #traceParsedData: Readonly;\n\n constructor(\n compatibilityBuilder: CompatibilityTracksAppender, traceParsedData: TraceEngine.Handlers.Types.TraceParseData) {\n this.#compatibilityBuilder = compatibilityBuilder;\n this.#traceParsedData = traceParsedData;\n }\n\n appendTrackAtLevel(trackStartLevel: number, expanded?: boolean|undefined): number {\n const animations = this.#traceParsedData.Animations.animations;\n if (animations.length === 0) {\n return trackStartLevel;\n }\n this.#appendTrackHeaderAtLevel(trackStartLevel, expanded);\n return this.#compatibilityBuilder.appendEventsAtLevel(animations, trackStartLevel, this);\n }\n\n #appendTrackHeaderAtLevel(currentLevel: number, expanded?: boolean): void {\n const style = buildGroupStyle({useFirstLineForOverview: false});\n const group = buildTrackHeader(\n VisualLoggingTrackName.ANIMATIONS, currentLevel, i18nString(UIStrings.animations), style,\n /* selectable= */ true, expanded);\n this.#compatibilityBuilder.registerTrackForGroup(group, this);\n }\n\n colorForEvent(): string {\n return ThemeSupport.ThemeSupport.instance().getComputedValue('--app-color-rendering');\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"AnimationsTrackAppender.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/AnimationsTrackAppender.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,IAAI,MAAM,yBAAyB,CAAC;AAEhD,OAAO,KAAK,YAAY,MAAM,gDAAgD,CAAC;AAE/E,OAAO,EAAC,eAAe,EAAE,gBAAgB,EAAE,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AASvF,MAAM,SAAS,GAAG;IAChB;;OAEG;IACH,UAAU,EAAE,YAAY;CACzB,CAAC;AAEF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,4CAA4C,EAAE,SAAS,CAAC,CAAC;AAClG,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAEtE,MAAM,OAAO,uBAAuB;IACzB,YAAY,GAAsB,YAAY,CAAC;IAExD,qBAAqB,CAA8B;IACnD,YAAY,CAA6C;IAEzD,YAAY,oBAAiD,EAAE,WAA6C;QAC1G,IAAI,CAAC,qBAAqB,GAAG,oBAAoB,CAAC;QAClD,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC;IAClC,CAAC;IAED,kBAAkB,CAAC,eAAuB,EAAE,QAA4B;QACtE,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,UAAU,CAAC;QAC3D,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,OAAO,eAAe,CAAC;QACzB,CAAC;QACD,IAAI,CAAC,yBAAyB,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC,qBAAqB,CAAC,mBAAmB,CAAC,UAAU,EAAE,eAAe,EAAE,IAAI,CAAC,CAAC;IAC3F,CAAC;IAED,yBAAyB,CAAC,YAAoB,EAAE,QAAkB;QAChE,MAAM,KAAK,GAAG,eAAe,CAAC,EAAC,uBAAuB,EAAE,KAAK,EAAC,CAAC,CAAC;QAChE,MAAM,KAAK,GAAG,gBAAgB,uDACS,YAAY,EAAE,UAAU,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,KAAK;QACxF,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACtC,IAAI,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAChE,CAAC;IAED,aAAa;QACX,OAAO,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,CAAC;IACxF,CAAC;IAED,aAAa,CAAC,KAAgD;QAC5D,MAAM,EAAC,WAAW,EAAC,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;QAC3D,OAAO,WAAW,IAAI,KAAK,CAAC,IAAI,CAAC;IACnC,CAAC;IAED,oBAAoB,CAAC,KAAgD;QACnE,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACxC,OAAO,EAAC,KAAK,EAAE,aAAa,EAAE,gBAAgB,CAAC,KAAK,CAAC,GAAG,CAAC,EAAC,CAAC;IAC7D,CAAC;CACF","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../core/i18n/i18n.js';\nimport type * as Trace from '../../models/trace/trace.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\n\nimport {buildGroupStyle, buildTrackHeader, getFormattedTime} from './AppenderUtils.js';\nimport {\n type CompatibilityTracksAppender,\n type HighlightedEntryInfo,\n type TrackAppender,\n type TrackAppenderName,\n VisualLoggingTrackName,\n} from './CompatibilityTracksAppender.js';\n\nconst UIStrings = {\n /**\n *@description Text in Timeline Flame Chart Data Provider of the Performance panel\n */\n animations: 'Animations',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/AnimationsTrackAppender.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport class AnimationsTrackAppender implements TrackAppender {\n readonly appenderName: TrackAppenderName = 'Animations';\n\n #compatibilityBuilder: CompatibilityTracksAppender;\n #parsedTrace: Readonly;\n\n constructor(compatibilityBuilder: CompatibilityTracksAppender, parsedTrace: Trace.Handlers.Types.ParsedTrace) {\n this.#compatibilityBuilder = compatibilityBuilder;\n this.#parsedTrace = parsedTrace;\n }\n\n appendTrackAtLevel(trackStartLevel: number, expanded?: boolean|undefined): number {\n const animations = this.#parsedTrace.Animations.animations;\n if (animations.length === 0) {\n return trackStartLevel;\n }\n this.#appendTrackHeaderAtLevel(trackStartLevel, expanded);\n return this.#compatibilityBuilder.appendEventsAtLevel(animations, trackStartLevel, this);\n }\n\n #appendTrackHeaderAtLevel(currentLevel: number, expanded?: boolean): void {\n const style = buildGroupStyle({useFirstLineForOverview: false});\n const group = buildTrackHeader(\n VisualLoggingTrackName.ANIMATIONS, currentLevel, i18nString(UIStrings.animations), style,\n /* selectable= */ true, expanded);\n this.#compatibilityBuilder.registerTrackForGroup(group, this);\n }\n\n colorForEvent(): string {\n return ThemeSupport.ThemeSupport.instance().getComputedValue('--app-color-rendering');\n }\n\n titleForEvent(event: Trace.Types.Events.SyntheticAnimationPair): string {\n const {displayName} = event.args.data.beginEvent.args.data;\n return displayName || event.name;\n }\n\n highlightedEntryInfo(event: Trace.Types.Events.SyntheticAnimationPair): HighlightedEntryInfo {\n const title = this.titleForEvent(event);\n return {title, formattedTime: getFormattedTime(event.dur)};\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/AnnotationHelpers.d.ts b/public/panels/timeline/AnnotationHelpers.d.ts new file mode 100644 index 000000000..96fd1a6fb --- /dev/null +++ b/public/panels/timeline/AnnotationHelpers.d.ts @@ -0,0 +1,8 @@ +import * as Trace from '../../models/trace/trace.js'; +export declare function getAnnotationEntries(annotation: Trace.Types.File.Annotation): Trace.Types.Events.Event[]; +/** + * Gets a trace window that contains the given annotation. May return `null` + * if there is no valid window (an ENTRIES_LINK without a `to` entry for + * example.) + */ +export declare function getAnnotationWindow(annotation: Trace.Types.File.Annotation): Trace.Types.Timing.TraceWindowMicroSeconds | null; diff --git a/public/panels/timeline/AnnotationHelpers.js b/public/panels/timeline/AnnotationHelpers.js new file mode 100644 index 000000000..4a6dbe5d7 --- /dev/null +++ b/public/panels/timeline/AnnotationHelpers.js @@ -0,0 +1,63 @@ +// Copyright 2024 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 * as Platform from '../../core/platform/platform.js'; +import * as Trace from '../../models/trace/trace.js'; +export function getAnnotationEntries(annotation) { + const entries = []; + switch (annotation.type) { + case 'ENTRY_LABEL': + entries.push(annotation.entry); + break; + case 'TIME_RANGE': + break; + case 'ENTRIES_LINK': + entries.push(annotation.entryFrom); + if (annotation.entryTo) { + entries.push(annotation.entryTo); + } + break; + default: + Platform.assertNever(annotation, 'Unsupported annotation type'); + } + return entries; +} +/** + * Gets a trace window that contains the given annotation. May return `null` + * if there is no valid window (an ENTRIES_LINK without a `to` entry for + * example.) + */ +export function getAnnotationWindow(annotation) { + let annotationWindow = null; + const minVisibleEntryDuration = Trace.Types.Timing.MilliSeconds(1); + switch (annotation.type) { + case 'ENTRY_LABEL': { + const eventDuration = annotation.entry.dur ?? Trace.Helpers.Timing.millisecondsToMicroseconds(minVisibleEntryDuration); + annotationWindow = Trace.Helpers.Timing.traceWindowFromMicroSeconds(annotation.entry.ts, Trace.Types.Timing.MicroSeconds(annotation.entry.ts + eventDuration)); + break; + } + case 'TIME_RANGE': { + annotationWindow = annotation.bounds; + break; + } + case 'ENTRIES_LINK': { + // If entryTo does not exist, the annotation is in the process of being created. + // Do not allow to zoom into it in this case. + if (!annotation.entryTo) { + break; + } + const fromEventDuration = (annotation.entryFrom.dur) ?? minVisibleEntryDuration; + const toEventDuration = annotation.entryTo.dur ?? minVisibleEntryDuration; + // To choose window max, check which entry ends later + const fromEntryEndTS = (annotation.entryFrom.ts + fromEventDuration); + const toEntryEndTS = (annotation.entryTo.ts + toEventDuration); + const maxTimestamp = Math.max(fromEntryEndTS, toEntryEndTS); + annotationWindow = Trace.Helpers.Timing.traceWindowFromMicroSeconds(annotation.entryFrom.ts, Trace.Types.Timing.MicroSeconds(maxTimestamp)); + break; + } + default: + Platform.assertNever(annotation, 'Unsupported annotation type'); + } + return annotationWindow; +} +//# sourceMappingURL=AnnotationHelpers.js.map \ No newline at end of file diff --git a/public/panels/timeline/AnnotationHelpers.js.map b/public/panels/timeline/AnnotationHelpers.js.map new file mode 100644 index 000000000..7f23b4be8 --- /dev/null +++ b/public/panels/timeline/AnnotationHelpers.js.map @@ -0,0 +1 @@ +{"version":3,"file":"AnnotationHelpers.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/AnnotationHelpers.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,QAAQ,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,KAAK,MAAM,6BAA6B,CAAC;AAErD,MAAM,UAAU,oBAAoB,CAChC,UAAuC;IAEzC,MAAM,OAAO,GAA+B,EAAE,CAAC;IAC/C,QAAQ,UAAU,CAAC,IAAI,EAAE,CAAC;QACxB,KAAK,aAAa;YAChB,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;YAC/B,MAAM;QACR,KAAK,YAAY;YACf,MAAM;QACR,KAAK,cAAc;YACjB,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;YACnC,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;gBACvB,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YACnC,CAAC;YACD,MAAM;QACR;YACE,QAAQ,CAAC,WAAW,CAAC,UAAU,EAAE,6BAA6B,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAC/B,UAAuC;IAEzC,IAAI,gBAAgB,GAAoD,IAAI,CAAC;IAC7E,MAAM,uBAAuB,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAEnE,QAAQ,UAAU,CAAC,IAAI,EAAE,CAAC;QACxB,KAAK,aAAa,CAAC,CAAC,CAAC;YACnB,MAAM,aAAa,GACf,UAAU,CAAC,KAAK,CAAC,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,uBAAuB,CAAC,CAAC;YAErG,gBAAgB,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,2BAA2B,CAC/D,UAAU,CAAC,KAAK,CAAC,EAAE,EACnB,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,GAAG,aAAa,CAAC,CACvE,CAAC;YAEF,MAAM;QACR,CAAC;QACD,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,gBAAgB,GAAG,UAAU,CAAC,MAAM,CAAC;YACrC,MAAM;QACR,CAAC;QACD,KAAK,cAAc,CAAC,CAAC,CAAC;YACpB,gFAAgF;YAChF,6CAA6C;YAC7C,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;gBACxB,MAAM;YACR,CAAC;YAED,MAAM,iBAAiB,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,uBAAuB,CAAC;YAChF,MAAM,eAAe,GAAG,UAAU,CAAC,OAAO,CAAC,GAAG,IAAI,uBAAuB,CAAC;YAE1E,qDAAqD;YACrD,MAAM,cAAc,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,GAAG,iBAAiB,CAAC,CAAC;YACrE,MAAM,YAAY,GAAG,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,GAAG,eAAe,CAAC,CAAC;YAC/D,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;YAE5D,gBAAgB,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,2BAA2B,CAC/D,UAAU,CAAC,SAAS,CAAC,EAAE,EACvB,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,CAChD,CAAC;YACF,MAAM;QACR,CAAC;QACD;YACE,QAAQ,CAAC,WAAW,CAAC,UAAU,EAAE,6BAA6B,CAAC,CAAC;IACpE,CAAC;IAED,OAAO,gBAAgB,CAAC;AAC1B,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../core/platform/platform.js';\nimport * as Trace from '../../models/trace/trace.js';\n\nexport function getAnnotationEntries(\n annotation: Trace.Types.File.Annotation,\n ): Trace.Types.Events.Event[] {\n const entries: Trace.Types.Events.Event[] = [];\n switch (annotation.type) {\n case 'ENTRY_LABEL':\n entries.push(annotation.entry);\n break;\n case 'TIME_RANGE':\n break;\n case 'ENTRIES_LINK':\n entries.push(annotation.entryFrom);\n if (annotation.entryTo) {\n entries.push(annotation.entryTo);\n }\n break;\n default:\n Platform.assertNever(annotation, 'Unsupported annotation type');\n }\n return entries;\n}\n\n/**\n * Gets a trace window that contains the given annotation. May return `null`\n * if there is no valid window (an ENTRIES_LINK without a `to` entry for\n * example.)\n */\nexport function getAnnotationWindow(\n annotation: Trace.Types.File.Annotation,\n ): Trace.Types.Timing.TraceWindowMicroSeconds|null {\n let annotationWindow: Trace.Types.Timing.TraceWindowMicroSeconds|null = null;\n const minVisibleEntryDuration = Trace.Types.Timing.MilliSeconds(1);\n\n switch (annotation.type) {\n case 'ENTRY_LABEL': {\n const eventDuration =\n annotation.entry.dur ?? Trace.Helpers.Timing.millisecondsToMicroseconds(minVisibleEntryDuration);\n\n annotationWindow = Trace.Helpers.Timing.traceWindowFromMicroSeconds(\n annotation.entry.ts,\n Trace.Types.Timing.MicroSeconds(annotation.entry.ts + eventDuration),\n );\n\n break;\n }\n case 'TIME_RANGE': {\n annotationWindow = annotation.bounds;\n break;\n }\n case 'ENTRIES_LINK': {\n // If entryTo does not exist, the annotation is in the process of being created.\n // Do not allow to zoom into it in this case.\n if (!annotation.entryTo) {\n break;\n }\n\n const fromEventDuration = (annotation.entryFrom.dur) ?? minVisibleEntryDuration;\n const toEventDuration = annotation.entryTo.dur ?? minVisibleEntryDuration;\n\n // To choose window max, check which entry ends later\n const fromEntryEndTS = (annotation.entryFrom.ts + fromEventDuration);\n const toEntryEndTS = (annotation.entryTo.ts + toEventDuration);\n const maxTimestamp = Math.max(fromEntryEndTS, toEntryEndTS);\n\n annotationWindow = Trace.Helpers.Timing.traceWindowFromMicroSeconds(\n annotation.entryFrom.ts,\n Trace.Types.Timing.MicroSeconds(maxTimestamp),\n );\n break;\n }\n default:\n Platform.assertNever(annotation, 'Unsupported annotation type');\n }\n\n return annotationWindow;\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/AnnotationHelpers.test.d.ts b/public/panels/timeline/AnnotationHelpers.test.d.ts new file mode 100644 index 000000000..cb0ff5c3b --- /dev/null +++ b/public/panels/timeline/AnnotationHelpers.test.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/public/panels/timeline/AnnotationHelpers.test.js b/public/panels/timeline/AnnotationHelpers.test.js new file mode 100644 index 000000000..6fa013427 --- /dev/null +++ b/public/panels/timeline/AnnotationHelpers.test.js @@ -0,0 +1,83 @@ +// Copyright 2024 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 * as Trace from '../../models/trace/trace.js'; +import * as Timeline from './timeline.js'; +const { getAnnotationEntries, getAnnotationWindow, } = Timeline.AnnotationHelpers; +describe('AnnotationHelpers', () => { + describe('getAnnotationEntries', () => { + const FAKE_ENTRY_1 = {}; + const FAKE_ENTRY_2 = {}; + it('returns the entry for an ENTRY_LABEL', async () => { + const annotation = { + entry: FAKE_ENTRY_1, + label: 'Hello world', + type: 'ENTRY_LABEL', + }; + assert.deepEqual(getAnnotationEntries(annotation), [FAKE_ENTRY_1]); + }); + it('returns an empty array for a range', async () => { + const annotation = { + bounds: Trace.Helpers.Timing.traceWindowFromMicroSeconds(Trace.Types.Timing.MicroSeconds(0), Trace.Types.Timing.MicroSeconds(10)), + type: 'TIME_RANGE', + label: 'Hello world', + }; + assert.lengthOf(getAnnotationEntries(annotation), 0); + }); + it('returns both entries for a link', async () => { + const annotation = { + entryFrom: FAKE_ENTRY_1, + entryTo: FAKE_ENTRY_2, + type: 'ENTRIES_LINK', + }; + assert.deepEqual(getAnnotationEntries(annotation), [FAKE_ENTRY_1, FAKE_ENTRY_2]); + }); + }); + describe('getAnnotationWindow', () => { + const FAKE_ENTRY_1 = { + ts: 1, + dur: 10, + }; + const FAKE_ENTRY_2 = { + ts: 20, + dur: 5, + }; + it('returns the entry window for an ENTRY_LABEL', async () => { + const annotation = { + entry: FAKE_ENTRY_1, + label: 'Hello world', + type: 'ENTRY_LABEL', + }; + assert.deepEqual(getAnnotationWindow(annotation), { + min: 1, + max: 11, + range: 10, + }); + }); + it('returns the bounds for a TIME_RANGE', async () => { + const annotation = { + bounds: Trace.Helpers.Timing.traceWindowFromMicroSeconds(Trace.Types.Timing.MicroSeconds(0), Trace.Types.Timing.MicroSeconds(10)), + type: 'TIME_RANGE', + label: 'Hello world', + }; + assert.deepEqual(getAnnotationWindow(annotation), { + min: 0, + max: 10, + range: 10, + }); + }); + it('returns the bounds based on the start and end entry for an ENTRIES_LINK', async () => { + const annotation = { + entryFrom: FAKE_ENTRY_1, + entryTo: FAKE_ENTRY_2, + type: 'ENTRIES_LINK', + }; + assert.deepEqual(getAnnotationWindow(annotation), { + min: 1, + max: 25, + range: 24, + }); + }); + }); +}); +//# sourceMappingURL=AnnotationHelpers.test.js.map \ No newline at end of file diff --git a/public/panels/timeline/AnnotationHelpers.test.js.map b/public/panels/timeline/AnnotationHelpers.test.js.map new file mode 100644 index 000000000..1ecde433b --- /dev/null +++ b/public/panels/timeline/AnnotationHelpers.test.js.map @@ -0,0 +1 @@ +{"version":3,"file":"AnnotationHelpers.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/AnnotationHelpers.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../models/trace/trace.js';\n\nimport * as Timeline from './timeline.js';\n\nconst {\n getAnnotationEntries,\n getAnnotationWindow,\n} = Timeline.AnnotationHelpers;\n\ndescribe('AnnotationHelpers', () => {\n describe('getAnnotationEntries', () => {\n const FAKE_ENTRY_1 = {} as unknown as Trace.Types.Events.Event;\n const FAKE_ENTRY_2 = {} as unknown as Trace.Types.Events.Event;\n it('returns the entry for an ENTRY_LABEL', async () => {\n const annotation: Trace.Types.File.EntryLabelAnnotation = {\n entry: FAKE_ENTRY_1,\n label: 'Hello world',\n type: 'ENTRY_LABEL',\n };\n assert.deepEqual(getAnnotationEntries(annotation), [FAKE_ENTRY_1]);\n });\n\n it('returns an empty array for a range', async () => {\n const annotation: Trace.Types.File.TimeRangeAnnotation = {\n bounds: Trace.Helpers.Timing.traceWindowFromMicroSeconds(\n Trace.Types.Timing.MicroSeconds(0),\n Trace.Types.Timing.MicroSeconds(10),\n ),\n type: 'TIME_RANGE',\n label: 'Hello world',\n };\n assert.lengthOf(getAnnotationEntries(annotation), 0);\n });\n\n it('returns both entries for a link', async () => {\n const annotation: Trace.Types.File.EntriesLinkAnnotation = {\n entryFrom: FAKE_ENTRY_1,\n entryTo: FAKE_ENTRY_2,\n type: 'ENTRIES_LINK',\n };\n assert.deepEqual(getAnnotationEntries(annotation), [FAKE_ENTRY_1, FAKE_ENTRY_2]);\n });\n });\n\n describe('getAnnotationWindow', () => {\n const FAKE_ENTRY_1 = {\n ts: 1,\n dur: 10,\n } as unknown as Trace.Types.Events.Event;\n const FAKE_ENTRY_2 = {\n ts: 20,\n dur: 5,\n } as unknown as Trace.Types.Events.Event;\n\n it('returns the entry window for an ENTRY_LABEL', async () => {\n const annotation: Trace.Types.File.EntryLabelAnnotation = {\n entry: FAKE_ENTRY_1,\n label: 'Hello world',\n type: 'ENTRY_LABEL',\n };\n assert.deepEqual(getAnnotationWindow(annotation), {\n min: 1,\n max: 11,\n range: 10,\n });\n });\n\n it('returns the bounds for a TIME_RANGE', async () => {\n const annotation: Trace.Types.File.TimeRangeAnnotation = {\n bounds: Trace.Helpers.Timing.traceWindowFromMicroSeconds(\n Trace.Types.Timing.MicroSeconds(0),\n Trace.Types.Timing.MicroSeconds(10),\n ),\n type: 'TIME_RANGE',\n label: 'Hello world',\n };\n assert.deepEqual(getAnnotationWindow(annotation), {\n min: 0,\n max: 10,\n range: 10,\n });\n });\n\n it('returns the bounds based on the start and end entry for an ENTRIES_LINK', async () => {\n const annotation: Trace.Types.File.EntriesLinkAnnotation = {\n entryFrom: FAKE_ENTRY_1,\n entryTo: FAKE_ENTRY_2,\n type: 'ENTRIES_LINK',\n };\n assert.deepEqual(getAnnotationWindow(annotation), {\n min: 1,\n max: 25,\n range: 24,\n });\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/AppenderUtils.d.ts b/public/panels/timeline/AppenderUtils.d.ts index 9fa2f74a3..941941c45 100644 --- a/public/panels/timeline/AppenderUtils.d.ts +++ b/public/panels/timeline/AppenderUtils.d.ts @@ -1,4 +1,4 @@ -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import type * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; import { type VisualLoggingTrackName } from './CompatibilityTracksAppender.js'; /** An array, indexed by entry levels, where the values are the last timestamp (typically `endTime`) of data within that level. */ @@ -32,9 +32,9 @@ export declare function buildTrackHeader(jslogContext: VisualLoggingTrackName | * @param selfTime the self time of the hovered event. * @returns the formatted time string for highlightedEntryInfo */ -export declare function getFormattedTime(totalTime?: TraceEngine.Types.Timing.MicroSeconds, selfTime?: TraceEngine.Types.Timing.MicroSeconds): string; +export declare function getFormattedTime(totalTime?: Trace.Types.Timing.MicroSeconds, selfTime?: Trace.Types.Timing.MicroSeconds): string; /** * Returns the first level that is available for an event. */ -export declare function getEventLevel(event: TraceEngine.Types.TraceEvents.TraceEventData, lastTimestampByLevel: LastTimestampByLevel): number; +export declare function getEventLevel(event: Trace.Types.Events.Event, lastTimestampByLevel: LastTimestampByLevel): number; export declare function addDecorationToEvent(timelineData: PerfUI.FlameChart.FlameChartTimelineData, eventIndex: number, decoration: PerfUI.FlameChart.FlameChartDecoration): void; diff --git a/public/panels/timeline/AppenderUtils.js b/public/panels/timeline/AppenderUtils.js index 8f4f42691..5b60cb76b 100644 --- a/public/panels/timeline/AppenderUtils.js +++ b/public/panels/timeline/AppenderUtils.js @@ -1,5 +1,5 @@ import * as i18n from '../../core/i18n/i18n.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js'; const UIStrings = { /** @@ -68,11 +68,11 @@ export function buildTrackHeader(jslogContext, startLevel, name, style, selectab * @returns the formatted time string for highlightedEntryInfo */ export function getFormattedTime(totalTime, selfTime) { - const formattedTotalTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds((totalTime || 0)); - if (formattedTotalTime === TraceEngine.Types.Timing.MilliSeconds(0)) { + const formattedTotalTime = Trace.Helpers.Timing.microSecondsToMilliseconds((totalTime || 0)); + if (formattedTotalTime === Trace.Types.Timing.MilliSeconds(0)) { return ''; } - const formattedSelfTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds((selfTime || 0)); + const formattedSelfTime = Trace.Helpers.Timing.microSecondsToMilliseconds((selfTime || 0)); const minSelfTimeSignificance = 1e-6; const formattedTime = Math.abs(formattedTotalTime - formattedSelfTime) > minSelfTimeSignificance && formattedSelfTime > minSelfTimeSignificance ? diff --git a/public/panels/timeline/AppenderUtils.js.map b/public/panels/timeline/AppenderUtils.js.map index e302cd6e1..a3797efd2 100644 --- a/public/panels/timeline/AppenderUtils.js.map +++ b/public/panels/timeline/AppenderUtils.js.map @@ -1 +1 @@ -{"version":3,"file":"AppenderUtils.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/AppenderUtils.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport type * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport type * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\n\nimport {type VisualLoggingTrackName} from './CompatibilityTracksAppender.js';\n\nconst UIStrings = {\n /**\n * @description Text in the Performance panel to show how long was spent in a particular part of the code.\n * The first placeholder is the total time taken for this node and all children, the second is the self time\n * (time taken in this node, without children included).\n *@example {10ms} PH1\n *@example {10ms} PH2\n */\n sSelfS: '{PH1} (self {PH2})',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/AppenderUtils.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\n/** An array, indexed by entry levels, where the values are the last timestamp (typically `endTime`) of data within that level. */\nexport type LastTimestampByLevel = number[];\n\n/**\n * Builds the style for the group.\n * Each group has a predefined style and a reference to the definition of the legacy track (which should be removed in the future).\n * @param extra the customized fields with value.\n * @returns the built GroupStyle\n */\nexport function buildGroupStyle(extra?: Partial): PerfUI.FlameChart.GroupStyle {\n const defaultGroupStyle: PerfUI.FlameChart.GroupStyle = {\n padding: 4,\n height: 17,\n collapsible: true,\n color: ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-on-surface'),\n backgroundColor: ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-cdt-base-container'),\n nestingLevel: 0,\n shareHeaderLine: true,\n };\n return Object.assign(defaultGroupStyle, extra);\n}\n\n/**\n * Builds the header corresponding to the track. A header is added in the shape of a group in the flame chart data.\n * @param jslogContext the text that will be set as the logging context\n * for the Visual Elements logging framework. Pass\n * `null` to not set a context and consequently\n * cause this group not to be logged.\n * @param startLevel the flame chart level at which the track header is appended.\n * @param name the display name of the track.\n * @param style the GroupStyle for the track header.\n * @param selectable if the track is selectable.\n * @param expanded if the track is expanded.\n * @param track this is set only when `selectable` is true, and it is used for selecting a track in the details panel.\n * @param showStackContextMenu whether menu with options to merge/collapse entries in track is shown.\n * @returns the group that built from the give data\n */\nexport function buildTrackHeader(\n jslogContext: VisualLoggingTrackName|null, startLevel: number, name: string, style: PerfUI.FlameChart.GroupStyle,\n selectable: boolean, expanded?: boolean, showStackContextMenu?: boolean,\n legends?: PerfUI.FlameChart.Legend[]): PerfUI.FlameChart.Group {\n const group: PerfUI.FlameChart.Group = {\n startLevel,\n name: name as Common.UIString.LocalizedString,\n style,\n selectable,\n expanded,\n showStackContextMenu,\n legends,\n };\n if (jslogContext !== null) {\n group.jslogContext = jslogContext;\n }\n return group;\n}\n\n/**\n * Returns the time info shown when an event is hovered in the timeline.\n * @param totalTime the total time of the hovered event.\n * @param selfTime the self time of the hovered event.\n * @returns the formatted time string for highlightedEntryInfo\n */\nexport function getFormattedTime(\n totalTime?: TraceEngine.Types.Timing.MicroSeconds, selfTime?: TraceEngine.Types.Timing.MicroSeconds): string {\n const formattedTotalTime =\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds((totalTime || 0) as TraceEngine.Types.Timing.MicroSeconds);\n if (formattedTotalTime === TraceEngine.Types.Timing.MilliSeconds(0)) {\n return '';\n }\n\n const formattedSelfTime =\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds((selfTime || 0) as TraceEngine.Types.Timing.MicroSeconds);\n const minSelfTimeSignificance = 1e-6;\n const formattedTime = Math.abs(formattedTotalTime - formattedSelfTime) > minSelfTimeSignificance &&\n formattedSelfTime > minSelfTimeSignificance ?\n i18nString(UIStrings.sSelfS, {\n PH1: i18n.TimeUtilities.millisToString(formattedTotalTime, true),\n PH2: i18n.TimeUtilities.millisToString(formattedSelfTime, true),\n }) :\n i18n.TimeUtilities.millisToString(formattedTotalTime, true);\n return formattedTime;\n}\n\n/**\n * Returns the first level that is available for an event.\n */\nexport function getEventLevel(\n event: TraceEngine.Types.TraceEvents.TraceEventData, lastTimestampByLevel: LastTimestampByLevel): number {\n let level = 0;\n const startTime = event.ts;\n const endTime = event.ts + (event.dur || 0);\n // Look vertically for the first level where this event fits,\n // that is, where it wouldn't overlap with other events.\n while (level < lastTimestampByLevel.length && startTime < lastTimestampByLevel[level]) {\n // For each event, we look each level from top, and see if start timestamp of this\n // event is used by current level already. If yes, we will go to check next level.\n ++level;\n }\n lastTimestampByLevel[level] = endTime;\n return level;\n}\n\nexport function addDecorationToEvent(\n timelineData: PerfUI.FlameChart.FlameChartTimelineData, eventIndex: number,\n decoration: PerfUI.FlameChart.FlameChartDecoration): void {\n const decorationsForEvent = timelineData.entryDecorations[eventIndex] || [];\n decorationsForEvent.push(decoration);\n timelineData.entryDecorations[eventIndex] = decorationsForEvent;\n}\n"]} \ No newline at end of file +{"version":3,"file":"AppenderUtils.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/AppenderUtils.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport type * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport type * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\n\nimport {type VisualLoggingTrackName} from './CompatibilityTracksAppender.js';\n\nconst UIStrings = {\n /**\n * @description Text in the Performance panel to show how long was spent in a particular part of the code.\n * The first placeholder is the total time taken for this node and all children, the second is the self time\n * (time taken in this node, without children included).\n *@example {10ms} PH1\n *@example {10ms} PH2\n */\n sSelfS: '{PH1} (self {PH2})',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/AppenderUtils.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\n/** An array, indexed by entry levels, where the values are the last timestamp (typically `endTime`) of data within that level. */\nexport type LastTimestampByLevel = number[];\n\n/**\n * Builds the style for the group.\n * Each group has a predefined style and a reference to the definition of the legacy track (which should be removed in the future).\n * @param extra the customized fields with value.\n * @returns the built GroupStyle\n */\nexport function buildGroupStyle(extra?: Partial): PerfUI.FlameChart.GroupStyle {\n const defaultGroupStyle: PerfUI.FlameChart.GroupStyle = {\n padding: 4,\n height: 17,\n collapsible: true,\n color: ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-on-surface'),\n backgroundColor: ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-cdt-base-container'),\n nestingLevel: 0,\n shareHeaderLine: true,\n };\n return Object.assign(defaultGroupStyle, extra);\n}\n\n/**\n * Builds the header corresponding to the track. A header is added in the shape of a group in the flame chart data.\n * @param jslogContext the text that will be set as the logging context\n * for the Visual Elements logging framework. Pass\n * `null` to not set a context and consequently\n * cause this group not to be logged.\n * @param startLevel the flame chart level at which the track header is appended.\n * @param name the display name of the track.\n * @param style the GroupStyle for the track header.\n * @param selectable if the track is selectable.\n * @param expanded if the track is expanded.\n * @param track this is set only when `selectable` is true, and it is used for selecting a track in the details panel.\n * @param showStackContextMenu whether menu with options to merge/collapse entries in track is shown.\n * @returns the group that built from the give data\n */\nexport function buildTrackHeader(\n jslogContext: VisualLoggingTrackName|null, startLevel: number, name: string, style: PerfUI.FlameChart.GroupStyle,\n selectable: boolean, expanded?: boolean, showStackContextMenu?: boolean,\n legends?: PerfUI.FlameChart.Legend[]): PerfUI.FlameChart.Group {\n const group: PerfUI.FlameChart.Group = {\n startLevel,\n name: name as Common.UIString.LocalizedString,\n style,\n selectable,\n expanded,\n showStackContextMenu,\n legends,\n };\n if (jslogContext !== null) {\n group.jslogContext = jslogContext;\n }\n return group;\n}\n\n/**\n * Returns the time info shown when an event is hovered in the timeline.\n * @param totalTime the total time of the hovered event.\n * @param selfTime the self time of the hovered event.\n * @returns the formatted time string for highlightedEntryInfo\n */\nexport function getFormattedTime(\n totalTime?: Trace.Types.Timing.MicroSeconds, selfTime?: Trace.Types.Timing.MicroSeconds): string {\n const formattedTotalTime =\n Trace.Helpers.Timing.microSecondsToMilliseconds((totalTime || 0) as Trace.Types.Timing.MicroSeconds);\n if (formattedTotalTime === Trace.Types.Timing.MilliSeconds(0)) {\n return '';\n }\n\n const formattedSelfTime =\n Trace.Helpers.Timing.microSecondsToMilliseconds((selfTime || 0) as Trace.Types.Timing.MicroSeconds);\n const minSelfTimeSignificance = 1e-6;\n const formattedTime = Math.abs(formattedTotalTime - formattedSelfTime) > minSelfTimeSignificance &&\n formattedSelfTime > minSelfTimeSignificance ?\n i18nString(UIStrings.sSelfS, {\n PH1: i18n.TimeUtilities.millisToString(formattedTotalTime, true),\n PH2: i18n.TimeUtilities.millisToString(formattedSelfTime, true),\n }) :\n i18n.TimeUtilities.millisToString(formattedTotalTime, true);\n return formattedTime;\n}\n\n/**\n * Returns the first level that is available for an event.\n */\nexport function getEventLevel(event: Trace.Types.Events.Event, lastTimestampByLevel: LastTimestampByLevel): number {\n let level = 0;\n const startTime = event.ts;\n const endTime = event.ts + (event.dur || 0);\n // Look vertically for the first level where this event fits,\n // that is, where it wouldn't overlap with other events.\n while (level < lastTimestampByLevel.length && startTime < lastTimestampByLevel[level]) {\n // For each event, we look each level from top, and see if start timestamp of this\n // event is used by current level already. If yes, we will go to check next level.\n ++level;\n }\n lastTimestampByLevel[level] = endTime;\n return level;\n}\n\nexport function addDecorationToEvent(\n timelineData: PerfUI.FlameChart.FlameChartTimelineData, eventIndex: number,\n decoration: PerfUI.FlameChart.FlameChartDecoration): void {\n const decorationsForEvent = timelineData.entryDecorations[eventIndex] || [];\n decorationsForEvent.push(decoration);\n timelineData.entryDecorations[eventIndex] = decorationsForEvent;\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/BenchmarkEvents.d.ts b/public/panels/timeline/BenchmarkEvents.d.ts index f92341f7a..ccbaad0d4 100644 --- a/public/panels/timeline/BenchmarkEvents.d.ts +++ b/public/panels/timeline/BenchmarkEvents.d.ts @@ -1,8 +1,8 @@ -import type * as TraceEngine from '../../models/trace/trace.js'; +import type * as Trace from '../../models/trace/trace.js'; export declare class TraceLoadEvent extends Event { - duration: TraceEngine.Types.Timing.MilliSeconds; + duration: Trace.Types.Timing.MilliSeconds; static readonly eventName = "traceload"; - constructor(duration: TraceEngine.Types.Timing.MilliSeconds); + constructor(duration: Trace.Types.Timing.MilliSeconds); } declare global { interface HTMLElementEventMap { diff --git a/public/panels/timeline/BenchmarkEvents.js.map b/public/panels/timeline/BenchmarkEvents.js.map index b0e4e9d73..86672186a 100644 --- a/public/panels/timeline/BenchmarkEvents.js.map +++ b/public/panels/timeline/BenchmarkEvents.js.map @@ -1 +1 @@ -{"version":3,"file":"BenchmarkEvents.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/BenchmarkEvents.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAI7B,MAAM,OAAO,cAAe,SAAQ,KAAK;IAGpB;IAFnB,MAAM,CAAU,SAAS,GAAG,WAAW,CAAC;IAExC,YAAmB,QAA+C;QAChE,KAAK,CAAC,cAAc,CAAC,SAAS,EAAE,EAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAC,CAAC,CAAC;QADhD,aAAQ,GAAR,QAAQ,CAAuC;IAElE,CAAC","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as TraceEngine from '../../models/trace/trace.js';\n\nexport class TraceLoadEvent extends Event {\n static readonly eventName = 'traceload';\n\n constructor(public duration: TraceEngine.Types.Timing.MilliSeconds) {\n super(TraceLoadEvent.eventName, {bubbles: true, composed: true});\n }\n}\n\ndeclare global {\n interface HTMLElementEventMap {\n [TraceLoadEvent.eventName]: TraceLoadEvent;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"BenchmarkEvents.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/BenchmarkEvents.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAI7B,MAAM,OAAO,cAAe,SAAQ,KAAK;IAGpB;IAFnB,MAAM,CAAU,SAAS,GAAG,WAAW,CAAC;IAExC,YAAmB,QAAyC;QAC1D,KAAK,CAAC,cAAc,CAAC,SAAS,EAAE,EAAC,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAC,CAAC,CAAC;QADhD,aAAQ,GAAR,QAAQ,CAAiC;IAE5D,CAAC","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Trace from '../../models/trace/trace.js';\n\nexport class TraceLoadEvent extends Event {\n static readonly eventName = 'traceload';\n\n constructor(public duration: Trace.Types.Timing.MilliSeconds) {\n super(TraceLoadEvent.eventName, {bubbles: true, composed: true});\n }\n}\n\ndeclare global {\n interface HTMLElementEventMap {\n [TraceLoadEvent.eventName]: TraceLoadEvent;\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/Breadcrumbs.test.js b/public/panels/timeline/Breadcrumbs.test.js index 7b5737fdf..892b6211a 100644 --- a/public/panels/timeline/Breadcrumbs.test.js +++ b/public/panels/timeline/Breadcrumbs.test.js @@ -1,24 +1,24 @@ // 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 * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as TraceBounds from '../../services/trace_bounds/trace_bounds.js'; import * as TimelineComponents from './components/components.js'; function nestedBreadcrumbs() { const initialTraceWindow = { - min: TraceEngine.Types.Timing.MicroSeconds(1000), - max: TraceEngine.Types.Timing.MicroSeconds(10000), - range: TraceEngine.Types.Timing.MicroSeconds(9000), + min: Trace.Types.Timing.MicroSeconds(1000), + max: Trace.Types.Timing.MicroSeconds(10000), + range: Trace.Types.Timing.MicroSeconds(9000), }; const traceWindow1 = { - min: TraceEngine.Types.Timing.MicroSeconds(3000), - max: TraceEngine.Types.Timing.MicroSeconds(9000), - range: TraceEngine.Types.Timing.MicroSeconds(6000), + min: Trace.Types.Timing.MicroSeconds(3000), + max: Trace.Types.Timing.MicroSeconds(9000), + range: Trace.Types.Timing.MicroSeconds(6000), }; const traceWindow2 = { - min: TraceEngine.Types.Timing.MicroSeconds(4000), - max: TraceEngine.Types.Timing.MicroSeconds(6000), - range: TraceEngine.Types.Timing.MicroSeconds(2000), + min: Trace.Types.Timing.MicroSeconds(4000), + max: Trace.Types.Timing.MicroSeconds(6000), + range: Trace.Types.Timing.MicroSeconds(2000), }; const breadcrumb2 = { window: traceWindow2, @@ -92,9 +92,9 @@ describe('Timeline breadcrumbs', () => { assert.deepEqual(crumbs.activeBreadcrumb, initialBreadcrumb); // Add a new breadcrumb const traceWindow4 = { - min: TraceEngine.Types.Timing.MicroSeconds(2000), - max: TraceEngine.Types.Timing.MicroSeconds(5000), - range: TraceEngine.Types.Timing.MicroSeconds(3000), + min: Trace.Types.Timing.MicroSeconds(2000), + max: Trace.Types.Timing.MicroSeconds(5000), + range: Trace.Types.Timing.MicroSeconds(3000), }; const breadcrumb4 = { window: traceWindow4, @@ -136,21 +136,21 @@ describe('Timeline breadcrumbs', () => { }); it('can create breadcrumbs with equal start or end as the parent breadcrumb', () => { const initialTraceWindow = { - min: TraceEngine.Types.Timing.MicroSeconds(1000), - max: TraceEngine.Types.Timing.MicroSeconds(10000), - range: TraceEngine.Types.Timing.MicroSeconds(9000), + min: Trace.Types.Timing.MicroSeconds(1000), + max: Trace.Types.Timing.MicroSeconds(10000), + range: Trace.Types.Timing.MicroSeconds(9000), }; TraceBounds.TraceBounds.BoundsManager.instance({ forceNew: true }).resetWithNewBounds(initialTraceWindow); const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialTraceWindow); const traceWindow1 = { - min: TraceEngine.Types.Timing.MicroSeconds(1000), - max: TraceEngine.Types.Timing.MicroSeconds(9000), - range: TraceEngine.Types.Timing.MicroSeconds(8000), + min: Trace.Types.Timing.MicroSeconds(1000), + max: Trace.Types.Timing.MicroSeconds(9000), + range: Trace.Types.Timing.MicroSeconds(8000), }; const traceWindow2 = { - min: TraceEngine.Types.Timing.MicroSeconds(3000), - max: TraceEngine.Types.Timing.MicroSeconds(9000), - range: TraceEngine.Types.Timing.MicroSeconds(6000), + min: Trace.Types.Timing.MicroSeconds(3000), + max: Trace.Types.Timing.MicroSeconds(9000), + range: Trace.Types.Timing.MicroSeconds(6000), }; crumbs.add(traceWindow1); crumbs.add(traceWindow2); diff --git a/public/panels/timeline/Breadcrumbs.test.js.map b/public/panels/timeline/Breadcrumbs.test.js.map index 3ff74ab11..099d45c5a 100644 --- a/public/panels/timeline/Breadcrumbs.test.js.map +++ b/public/panels/timeline/Breadcrumbs.test.js.map @@ -1 +1 @@ -{"version":3,"file":"Breadcrumbs.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/Breadcrumbs.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as TraceBounds from '../../services/trace_bounds/trace_bounds.js';\n\nimport * as TimelineComponents from './components/components.js';\n\nfunction nestedBreadcrumbs(): {\n initialBreadcrumb: TraceEngine.Types.File.Breadcrumb,\n breadcrumb1: TraceEngine.Types.File.Breadcrumb,\n breadcrumb2: TraceEngine.Types.File.Breadcrumb,\n} {\n const initialTraceWindow: TraceEngine.Types.Timing.TraceWindowMicroSeconds = {\n min: TraceEngine.Types.Timing.MicroSeconds(1000),\n max: TraceEngine.Types.Timing.MicroSeconds(10000),\n range: TraceEngine.Types.Timing.MicroSeconds(9000),\n };\n\n const traceWindow1: TraceEngine.Types.Timing.TraceWindowMicroSeconds = {\n min: TraceEngine.Types.Timing.MicroSeconds(3000),\n max: TraceEngine.Types.Timing.MicroSeconds(9000),\n range: TraceEngine.Types.Timing.MicroSeconds(6000),\n };\n\n const traceWindow2: TraceEngine.Types.Timing.TraceWindowMicroSeconds = {\n min: TraceEngine.Types.Timing.MicroSeconds(4000),\n max: TraceEngine.Types.Timing.MicroSeconds(6000),\n range: TraceEngine.Types.Timing.MicroSeconds(2000),\n };\n\n const breadcrumb2: TraceEngine.Types.File.Breadcrumb = {\n window: traceWindow2,\n child: null,\n };\n\n const breadcrumb1: TraceEngine.Types.File.Breadcrumb = {\n window: traceWindow1,\n child: breadcrumb2,\n };\n\n const initialBreadcrumb: TraceEngine.Types.File.Breadcrumb = {\n window: initialTraceWindow,\n child: breadcrumb1,\n };\n\n return {\n initialBreadcrumb,\n breadcrumb1,\n breadcrumb2,\n };\n}\n\ndescribe('Timeline breadcrumbs', () => {\n it('can create breadcrumbs', () => {\n const {initialBreadcrumb, breadcrumb1, breadcrumb2} = nestedBreadcrumbs();\n\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(initialBreadcrumb.window);\n const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialBreadcrumb.window);\n\n crumbs.add(breadcrumb1.window);\n crumbs.add(breadcrumb2.window);\n\n assert.deepEqual(\n TimelineComponents.Breadcrumbs.flattenBreadcrumbs(initialBreadcrumb),\n [initialBreadcrumb, breadcrumb1, breadcrumb2]);\n\n assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb2);\n });\n\n it('can activate breadcrumbs', () => {\n const {initialBreadcrumb, breadcrumb1, breadcrumb2} = nestedBreadcrumbs();\n\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(initialBreadcrumb.window);\n const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialBreadcrumb.window);\n crumbs.add(breadcrumb1.window);\n crumbs.add(breadcrumb2.window);\n\n // Last added breadcrumb should be active\n assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb2);\n\n // Make sure breadcrumb 1 can be actived\n crumbs.setActiveBreadcrumb(breadcrumb1, {\n removeChildBreadcrumbs: false,\n updateVisibleWindow: true,\n });\n assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb1);\n\n // Make sure initial breadcrumb can be actived\n crumbs.setActiveBreadcrumb(initialBreadcrumb, {\n removeChildBreadcrumbs: false,\n updateVisibleWindow: true,\n });\n assert.deepEqual(crumbs.activeBreadcrumb, initialBreadcrumb);\n\n // No breadcrumb were removed\n assert.deepEqual(\n TimelineComponents.Breadcrumbs.flattenBreadcrumbs(initialBreadcrumb),\n [initialBreadcrumb, breadcrumb1, breadcrumb2]);\n });\n\n it('can overwrite child breadcrumbs when a new one is added', () => {\n const {initialBreadcrumb, breadcrumb1, breadcrumb2} = nestedBreadcrumbs();\n\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(initialBreadcrumb.window);\n\n const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialBreadcrumb.window);\n crumbs.add(breadcrumb1.window);\n crumbs.add(breadcrumb2.window);\n\n // Last added breadcrumb should be active\n assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb2);\n\n // Currently, breadcrumbs structure is:\n // initialBreadcrumb -> breadcrumb1 -> breadcrumb2(activated)\n assert.deepEqual(\n TimelineComponents.Breadcrumbs.flattenBreadcrumbs(initialBreadcrumb),\n [initialBreadcrumb, breadcrumb1, breadcrumb2]);\n\n // In this test we want to check if the children of the activated breadcrumb will be overwrritten if a new one is added\n // Make the initial breadcrumb active:\n // initialBreadcrumb(activated) -> breadcrumb1 -> breadcrumb2\n crumbs.setActiveBreadcrumb(initialBreadcrumb, {\n removeChildBreadcrumbs: false,\n updateVisibleWindow: true,\n });\n assert.deepEqual(crumbs.activeBreadcrumb, initialBreadcrumb);\n\n // Add a new breadcrumb\n const traceWindow4: TraceEngine.Types.Timing.TraceWindowMicroSeconds = {\n min: TraceEngine.Types.Timing.MicroSeconds(2000),\n max: TraceEngine.Types.Timing.MicroSeconds(5000),\n range: TraceEngine.Types.Timing.MicroSeconds(3000),\n };\n\n const breadcrumb4: TraceEngine.Types.File.Breadcrumb = {\n window: traceWindow4,\n child: null,\n };\n\n crumbs.add(traceWindow4);\n\n // Breadcrumbs should look like this:\n // initialBreadcrumb -> breadcrumb4\n assert.deepEqual(\n TimelineComponents.Breadcrumbs.flattenBreadcrumbs(initialBreadcrumb), [initialBreadcrumb, breadcrumb4]);\n assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb4);\n });\n\n it('can remove breadcrumbs', () => {\n const {initialBreadcrumb, breadcrumb1, breadcrumb2} = nestedBreadcrumbs();\n\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(initialBreadcrumb.window);\n\n const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialBreadcrumb.window);\n crumbs.add(breadcrumb1.window);\n crumbs.add(breadcrumb2.window);\n\n assert.deepEqual(\n TimelineComponents.Breadcrumbs.flattenBreadcrumbs(initialBreadcrumb),\n [initialBreadcrumb, breadcrumb1, breadcrumb2]);\n assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb2);\n crumbs.setActiveBreadcrumb(breadcrumb1, {\n removeChildBreadcrumbs: true,\n updateVisibleWindow: true,\n });\n\n assert.deepEqual(\n TimelineComponents.Breadcrumbs.flattenBreadcrumbs(initialBreadcrumb), [initialBreadcrumb, breadcrumb1]);\n assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb1);\n });\n\n it('can not create a breadcrumb equal to the parent breadcrumb', () => {\n const {initialBreadcrumb} = nestedBreadcrumbs();\n\n assert.throws(() => {\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(initialBreadcrumb.window);\n\n const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialBreadcrumb.window);\n\n const equalTraceWindow: TraceEngine.Types.Timing.TraceWindowMicroSeconds = {\n min: initialBreadcrumb.window.min,\n max: initialBreadcrumb.window.max,\n range: initialBreadcrumb.window.range,\n };\n\n crumbs.add(equalTraceWindow);\n }, 'Can not add a breadcrumb that is equal to or is outside of the parent breadcrumb TimeWindow');\n });\n\n it('can create breadcrumbs with equal start or end as the parent breadcrumb', () => {\n const initialTraceWindow: TraceEngine.Types.Timing.TraceWindowMicroSeconds = {\n min: TraceEngine.Types.Timing.MicroSeconds(1000),\n max: TraceEngine.Types.Timing.MicroSeconds(10000),\n range: TraceEngine.Types.Timing.MicroSeconds(9000),\n };\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(initialTraceWindow);\n\n const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialTraceWindow);\n\n const traceWindow1: TraceEngine.Types.Timing.TraceWindowMicroSeconds = {\n min: TraceEngine.Types.Timing.MicroSeconds(1000),\n max: TraceEngine.Types.Timing.MicroSeconds(9000),\n range: TraceEngine.Types.Timing.MicroSeconds(8000),\n };\n\n const traceWindow2: TraceEngine.Types.Timing.TraceWindowMicroSeconds = {\n min: TraceEngine.Types.Timing.MicroSeconds(3000),\n max: TraceEngine.Types.Timing.MicroSeconds(9000),\n range: TraceEngine.Types.Timing.MicroSeconds(6000),\n };\n\n crumbs.add(traceWindow1);\n crumbs.add(traceWindow2);\n\n const breadcrumb2: TraceEngine.Types.File.Breadcrumb = {\n window: traceWindow2,\n child: null,\n };\n\n const breadcrumb1: TraceEngine.Types.File.Breadcrumb = {\n window: traceWindow1,\n child: breadcrumb2,\n };\n\n const initialBreadcrumb: TraceEngine.Types.File.Breadcrumb = {\n window: initialTraceWindow,\n child: breadcrumb1,\n };\n\n assert.deepEqual(\n TimelineComponents.Breadcrumbs.flattenBreadcrumbs(initialBreadcrumb),\n [initialBreadcrumb, breadcrumb1, breadcrumb2]);\n assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb2);\n });\n\n it('correctly sets the last breadrumb and trace bound window when a new initial breadcrumb is provided', () => {\n const {initialBreadcrumb, breadcrumb1, breadcrumb2} = nestedBreadcrumbs();\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(initialBreadcrumb.window);\n\n const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialBreadcrumb.window);\n crumbs.setInitialBreadcrumbFromLoadedModifications(initialBreadcrumb);\n\n assert.deepEqual(\n TimelineComponents.Breadcrumbs.flattenBreadcrumbs(initialBreadcrumb),\n [initialBreadcrumb, breadcrumb1, breadcrumb2]);\n assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb2);\n\n // Make sure the trace bounds were correctly set to the last breadcrumb bounds\n assert.deepEqual(\n TraceBounds.TraceBounds.BoundsManager.instance().state()?.micro.minimapTraceBounds, breadcrumb2.window);\n\n // Make sure the TimelineVisibleWindow was correctly set to the last breadcrumb bounds\n assert.deepEqual(\n TraceBounds.TraceBounds.BoundsManager.instance().state()?.micro.minimapTraceBounds, breadcrumb2.window);\n });\n\n it('it will not update the trace window when activating a breadcrumb if the option is set to false', () => {\n const {initialBreadcrumb, breadcrumb1, breadcrumb2} = nestedBreadcrumbs();\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(initialBreadcrumb.window);\n const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialBreadcrumb.window);\n crumbs.setInitialBreadcrumbFromLoadedModifications(initialBreadcrumb);\n // Make sure the trace bounds were correctly set to the last breadcrumb bounds\n assert.deepEqual(\n TraceBounds.TraceBounds.BoundsManager.instance().state()?.micro.minimapTraceBounds, breadcrumb2.window);\n\n // Now activate breadcrumb1, but tell it not to update the bounds\n crumbs.setActiveBreadcrumb(breadcrumb1, {removeChildBreadcrumbs: false, updateVisibleWindow: false});\n\n // The visible window is still breadcrumb2.\n assert.deepEqual(\n TraceBounds.TraceBounds.BoundsManager.instance().state()?.micro.timelineTraceWindow, breadcrumb2.window);\n\n // Now activate breadcrumb1, but ask it to update the bounds this time\n crumbs.setActiveBreadcrumb(breadcrumb1, {removeChildBreadcrumbs: false, updateVisibleWindow: true});\n // Now the window has changed.\n assert.deepEqual(\n TraceBounds.TraceBounds.BoundsManager.instance().state()?.micro.timelineTraceWindow, breadcrumb1.window);\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"Breadcrumbs.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/Breadcrumbs.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../models/trace/trace.js';\nimport * as TraceBounds from '../../services/trace_bounds/trace_bounds.js';\n\nimport * as TimelineComponents from './components/components.js';\n\nfunction nestedBreadcrumbs(): {\n initialBreadcrumb: Trace.Types.File.Breadcrumb,\n breadcrumb1: Trace.Types.File.Breadcrumb,\n breadcrumb2: Trace.Types.File.Breadcrumb,\n} {\n const initialTraceWindow: Trace.Types.Timing.TraceWindowMicroSeconds = {\n min: Trace.Types.Timing.MicroSeconds(1000),\n max: Trace.Types.Timing.MicroSeconds(10000),\n range: Trace.Types.Timing.MicroSeconds(9000),\n };\n\n const traceWindow1: Trace.Types.Timing.TraceWindowMicroSeconds = {\n min: Trace.Types.Timing.MicroSeconds(3000),\n max: Trace.Types.Timing.MicroSeconds(9000),\n range: Trace.Types.Timing.MicroSeconds(6000),\n };\n\n const traceWindow2: Trace.Types.Timing.TraceWindowMicroSeconds = {\n min: Trace.Types.Timing.MicroSeconds(4000),\n max: Trace.Types.Timing.MicroSeconds(6000),\n range: Trace.Types.Timing.MicroSeconds(2000),\n };\n\n const breadcrumb2: Trace.Types.File.Breadcrumb = {\n window: traceWindow2,\n child: null,\n };\n\n const breadcrumb1: Trace.Types.File.Breadcrumb = {\n window: traceWindow1,\n child: breadcrumb2,\n };\n\n const initialBreadcrumb: Trace.Types.File.Breadcrumb = {\n window: initialTraceWindow,\n child: breadcrumb1,\n };\n\n return {\n initialBreadcrumb,\n breadcrumb1,\n breadcrumb2,\n };\n}\n\ndescribe('Timeline breadcrumbs', () => {\n it('can create breadcrumbs', () => {\n const {initialBreadcrumb, breadcrumb1, breadcrumb2} = nestedBreadcrumbs();\n\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(initialBreadcrumb.window);\n const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialBreadcrumb.window);\n\n crumbs.add(breadcrumb1.window);\n crumbs.add(breadcrumb2.window);\n\n assert.deepEqual(\n TimelineComponents.Breadcrumbs.flattenBreadcrumbs(initialBreadcrumb),\n [initialBreadcrumb, breadcrumb1, breadcrumb2]);\n\n assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb2);\n });\n\n it('can activate breadcrumbs', () => {\n const {initialBreadcrumb, breadcrumb1, breadcrumb2} = nestedBreadcrumbs();\n\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(initialBreadcrumb.window);\n const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialBreadcrumb.window);\n crumbs.add(breadcrumb1.window);\n crumbs.add(breadcrumb2.window);\n\n // Last added breadcrumb should be active\n assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb2);\n\n // Make sure breadcrumb 1 can be actived\n crumbs.setActiveBreadcrumb(breadcrumb1, {\n removeChildBreadcrumbs: false,\n updateVisibleWindow: true,\n });\n assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb1);\n\n // Make sure initial breadcrumb can be actived\n crumbs.setActiveBreadcrumb(initialBreadcrumb, {\n removeChildBreadcrumbs: false,\n updateVisibleWindow: true,\n });\n assert.deepEqual(crumbs.activeBreadcrumb, initialBreadcrumb);\n\n // No breadcrumb were removed\n assert.deepEqual(\n TimelineComponents.Breadcrumbs.flattenBreadcrumbs(initialBreadcrumb),\n [initialBreadcrumb, breadcrumb1, breadcrumb2]);\n });\n\n it('can overwrite child breadcrumbs when a new one is added', () => {\n const {initialBreadcrumb, breadcrumb1, breadcrumb2} = nestedBreadcrumbs();\n\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(initialBreadcrumb.window);\n\n const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialBreadcrumb.window);\n crumbs.add(breadcrumb1.window);\n crumbs.add(breadcrumb2.window);\n\n // Last added breadcrumb should be active\n assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb2);\n\n // Currently, breadcrumbs structure is:\n // initialBreadcrumb -> breadcrumb1 -> breadcrumb2(activated)\n assert.deepEqual(\n TimelineComponents.Breadcrumbs.flattenBreadcrumbs(initialBreadcrumb),\n [initialBreadcrumb, breadcrumb1, breadcrumb2]);\n\n // In this test we want to check if the children of the activated breadcrumb will be overwrritten if a new one is added\n // Make the initial breadcrumb active:\n // initialBreadcrumb(activated) -> breadcrumb1 -> breadcrumb2\n crumbs.setActiveBreadcrumb(initialBreadcrumb, {\n removeChildBreadcrumbs: false,\n updateVisibleWindow: true,\n });\n assert.deepEqual(crumbs.activeBreadcrumb, initialBreadcrumb);\n\n // Add a new breadcrumb\n const traceWindow4: Trace.Types.Timing.TraceWindowMicroSeconds = {\n min: Trace.Types.Timing.MicroSeconds(2000),\n max: Trace.Types.Timing.MicroSeconds(5000),\n range: Trace.Types.Timing.MicroSeconds(3000),\n };\n\n const breadcrumb4: Trace.Types.File.Breadcrumb = {\n window: traceWindow4,\n child: null,\n };\n\n crumbs.add(traceWindow4);\n\n // Breadcrumbs should look like this:\n // initialBreadcrumb -> breadcrumb4\n assert.deepEqual(\n TimelineComponents.Breadcrumbs.flattenBreadcrumbs(initialBreadcrumb), [initialBreadcrumb, breadcrumb4]);\n assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb4);\n });\n\n it('can remove breadcrumbs', () => {\n const {initialBreadcrumb, breadcrumb1, breadcrumb2} = nestedBreadcrumbs();\n\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(initialBreadcrumb.window);\n\n const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialBreadcrumb.window);\n crumbs.add(breadcrumb1.window);\n crumbs.add(breadcrumb2.window);\n\n assert.deepEqual(\n TimelineComponents.Breadcrumbs.flattenBreadcrumbs(initialBreadcrumb),\n [initialBreadcrumb, breadcrumb1, breadcrumb2]);\n assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb2);\n crumbs.setActiveBreadcrumb(breadcrumb1, {\n removeChildBreadcrumbs: true,\n updateVisibleWindow: true,\n });\n\n assert.deepEqual(\n TimelineComponents.Breadcrumbs.flattenBreadcrumbs(initialBreadcrumb), [initialBreadcrumb, breadcrumb1]);\n assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb1);\n });\n\n it('can not create a breadcrumb equal to the parent breadcrumb', () => {\n const {initialBreadcrumb} = nestedBreadcrumbs();\n\n assert.throws(() => {\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(initialBreadcrumb.window);\n\n const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialBreadcrumb.window);\n\n const equalTraceWindow: Trace.Types.Timing.TraceWindowMicroSeconds = {\n min: initialBreadcrumb.window.min,\n max: initialBreadcrumb.window.max,\n range: initialBreadcrumb.window.range,\n };\n\n crumbs.add(equalTraceWindow);\n }, 'Can not add a breadcrumb that is equal to or is outside of the parent breadcrumb TimeWindow');\n });\n\n it('can create breadcrumbs with equal start or end as the parent breadcrumb', () => {\n const initialTraceWindow: Trace.Types.Timing.TraceWindowMicroSeconds = {\n min: Trace.Types.Timing.MicroSeconds(1000),\n max: Trace.Types.Timing.MicroSeconds(10000),\n range: Trace.Types.Timing.MicroSeconds(9000),\n };\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(initialTraceWindow);\n\n const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialTraceWindow);\n\n const traceWindow1: Trace.Types.Timing.TraceWindowMicroSeconds = {\n min: Trace.Types.Timing.MicroSeconds(1000),\n max: Trace.Types.Timing.MicroSeconds(9000),\n range: Trace.Types.Timing.MicroSeconds(8000),\n };\n\n const traceWindow2: Trace.Types.Timing.TraceWindowMicroSeconds = {\n min: Trace.Types.Timing.MicroSeconds(3000),\n max: Trace.Types.Timing.MicroSeconds(9000),\n range: Trace.Types.Timing.MicroSeconds(6000),\n };\n\n crumbs.add(traceWindow1);\n crumbs.add(traceWindow2);\n\n const breadcrumb2: Trace.Types.File.Breadcrumb = {\n window: traceWindow2,\n child: null,\n };\n\n const breadcrumb1: Trace.Types.File.Breadcrumb = {\n window: traceWindow1,\n child: breadcrumb2,\n };\n\n const initialBreadcrumb: Trace.Types.File.Breadcrumb = {\n window: initialTraceWindow,\n child: breadcrumb1,\n };\n\n assert.deepEqual(\n TimelineComponents.Breadcrumbs.flattenBreadcrumbs(initialBreadcrumb),\n [initialBreadcrumb, breadcrumb1, breadcrumb2]);\n assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb2);\n });\n\n it('correctly sets the last breadrumb and trace bound window when a new initial breadcrumb is provided', () => {\n const {initialBreadcrumb, breadcrumb1, breadcrumb2} = nestedBreadcrumbs();\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(initialBreadcrumb.window);\n\n const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialBreadcrumb.window);\n crumbs.setInitialBreadcrumbFromLoadedModifications(initialBreadcrumb);\n\n assert.deepEqual(\n TimelineComponents.Breadcrumbs.flattenBreadcrumbs(initialBreadcrumb),\n [initialBreadcrumb, breadcrumb1, breadcrumb2]);\n assert.deepEqual(crumbs.activeBreadcrumb, breadcrumb2);\n\n // Make sure the trace bounds were correctly set to the last breadcrumb bounds\n assert.deepEqual(\n TraceBounds.TraceBounds.BoundsManager.instance().state()?.micro.minimapTraceBounds, breadcrumb2.window);\n\n // Make sure the TimelineVisibleWindow was correctly set to the last breadcrumb bounds\n assert.deepEqual(\n TraceBounds.TraceBounds.BoundsManager.instance().state()?.micro.minimapTraceBounds, breadcrumb2.window);\n });\n\n it('it will not update the trace window when activating a breadcrumb if the option is set to false', () => {\n const {initialBreadcrumb, breadcrumb1, breadcrumb2} = nestedBreadcrumbs();\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(initialBreadcrumb.window);\n const crumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(initialBreadcrumb.window);\n crumbs.setInitialBreadcrumbFromLoadedModifications(initialBreadcrumb);\n // Make sure the trace bounds were correctly set to the last breadcrumb bounds\n assert.deepEqual(\n TraceBounds.TraceBounds.BoundsManager.instance().state()?.micro.minimapTraceBounds, breadcrumb2.window);\n\n // Now activate breadcrumb1, but tell it not to update the bounds\n crumbs.setActiveBreadcrumb(breadcrumb1, {removeChildBreadcrumbs: false, updateVisibleWindow: false});\n\n // The visible window is still breadcrumb2.\n assert.deepEqual(\n TraceBounds.TraceBounds.BoundsManager.instance().state()?.micro.timelineTraceWindow, breadcrumb2.window);\n\n // Now activate breadcrumb1, but ask it to update the bounds this time\n crumbs.setActiveBreadcrumb(breadcrumb1, {removeChildBreadcrumbs: false, updateVisibleWindow: true});\n // Now the window has changed.\n assert.deepEqual(\n TraceBounds.TraceBounds.BoundsManager.instance().state()?.micro.timelineTraceWindow, breadcrumb1.window);\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/CompatibilityTracksAppender.d.ts b/public/panels/timeline/CompatibilityTracksAppender.d.ts index be301c7f7..b850616c9 100644 --- a/public/panels/timeline/CompatibilityTracksAppender.d.ts +++ b/public/panels/timeline/CompatibilityTracksAppender.d.ts @@ -1,4 +1,4 @@ -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import type * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; import { AnimationsTrackAppender } from './AnimationsTrackAppender.js'; import { GPUTrackAppender } from './GPUTrackAppender.js'; @@ -13,7 +13,7 @@ export type HighlightedEntryInfo = { formattedTime: string; warningElements?: HTMLSpanElement[]; }; -export declare function entryIsVisibleInTimeline(entry: TraceEngine.Types.TraceEvents.TraceEventData, traceParsedData?: TraceEngine.Handlers.Types.TraceParseData): boolean; +export declare function entryIsVisibleInTimeline(entry: Trace.Types.Events.Event, parsedTrace?: Trace.Handlers.Types.ParsedTrace): boolean; /** * Track appenders add the data of each track into the timeline flame * chart. Each track appender also implements functions tha allow the @@ -51,18 +51,23 @@ export interface TrackAppender { /** * Returns the color an event is shown with in the timeline. */ - colorForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): string; + colorForEvent(event: Trace.Types.Events.Event): string; /** * Returns the title an event is shown with in the timeline. */ - titleForEvent?(event: TraceEngine.Types.TraceEvents.TraceEventData): string; + titleForEvent?(event: Trace.Types.Events.Event): string; /** * Returns the info shown when an event in the timeline is hovered. */ - highlightedEntryInfo?(event: TraceEngine.Types.TraceEvents.TraceEventData): Partial; + highlightedEntryInfo?(event: Trace.Types.Events.Event): Partial; + /** + * Returns the a callback function to draw an event to overrides the normal rectangle draw operation. + */ + getDrawOverride?(event: Trace.Types.Events.Event): DrawOverride | undefined; } export declare const TrackNames: readonly ["Animations", "Timings", "Interactions", "GPU", "LayoutShifts", "Thread", "Thread_AuctionWorklet", "Extension", "ServerTimings"]; export type TrackAppenderName = typeof TrackNames[number] | 'Network'; +export type DrawOverride = PerfUI.FlameChart.DrawOverride; /** * Used as the context when a track (aka group) is selected and we log * something to the VE Logging framework. @@ -97,7 +102,7 @@ export declare class CompatibilityTracksAppender { /** * @param flameChartData the data used by the flame chart renderer on * which the track data will be appended. - * @param traceParsedData the trace parsing engines output. + * @param parsedTrace the trace parsing engines output. * @param entryData the array containing all event to be rendered in * the flamechart. * @param legacyEntryTypeByLevel an array containing the type of @@ -107,7 +112,7 @@ export declare class CompatibilityTracksAppender { * architecture and should be removed once all tracks use the new * system. */ - constructor(flameChartData: PerfUI.FlameChart.FlameChartTimelineData, traceParsedData: TraceEngine.Handlers.Types.TraceParseData, entryData: TimelineFlameChartEntry[], legacyEntryTypeByLevel: EntryType[]); + constructor(flameChartData: PerfUI.FlameChart.FlameChartTimelineData, parsedTrace: Trace.Handlers.Types.ParsedTrace, entryData: TimelineFlameChartEntry[], legacyEntryTypeByLevel: EntryType[]); setFlameChartDataAndEntryData(flameChartData: PerfUI.FlameChart.FlameChartTimelineData, entryData: TimelineFlameChartEntry[], legacyEntryTypeByLevel: EntryType[]): void; getFlameChartTimelineData(): PerfUI.FlameChart.FlameChartTimelineData; timingsTrackAppender(): TimingsTrackAppender; @@ -117,13 +122,13 @@ export declare class CompatibilityTracksAppender { layoutShiftsTrackAppender(): LayoutShiftsTrackAppender; threadAppenders(): ThreadAppender[]; serverTimingsTrackAppender(): ServerTimingsTrackAppender; - eventsInTrack(trackAppender: TrackAppender): TraceEngine.Types.TraceEvents.TraceEventData[]; + eventsInTrack(trackAppender: TrackAppender): Trace.Types.Events.Event[]; /** * Gets the events to be shown in the tree views of the details pane * (Bottom-up, Call tree, etc.). These are the events from the track * that can be arranged in a tree shape. */ - eventsForTreeView(trackAppender: TrackAppender): TraceEngine.Types.TraceEvents.TraceEventData[]; + eventsForTreeView(trackAppender: TrackAppender): Trace.Types.Events.Event[]; /** * Caches the track appender that owns a flame chart group. FlameChart * groups are created for each track in the timeline. When an user @@ -135,7 +140,7 @@ export declare class CompatibilityTracksAppender { * Returns number of tracks of given type already appended. * Used to name the "Raster Thread 6" tracks, etc */ - getCurrentTrackCountForThreadType(threadType: TraceEngine.Handlers.Threads.ThreadType.RASTERIZER | TraceEngine.Handlers.Threads.ThreadType.THREAD_POOL): number; + getCurrentTrackCountForThreadType(threadType: Trace.Handlers.Threads.ThreadType.RASTERIZER | Trace.Handlers.Threads.ThreadType.THREAD_POOL): number; /** * Looks up a FlameChart group for a given appender. */ @@ -144,7 +149,7 @@ export declare class CompatibilityTracksAppender { * Given a FlameChart group, gets the events to be shown in the tree * views if that group was registered by the appender system. */ - groupEventsForTreeView(group: PerfUI.FlameChart.Group): TraceEngine.Types.TraceEvents.TraceEventData[] | null; + groupEventsForTreeView(group: PerfUI.FlameChart.Group): Trace.Types.Events.Event[] | null; /** * Caches the track appender that owns a level. An appender takes * ownership of a level when it appends data to it. @@ -161,7 +166,7 @@ export declare class CompatibilityTracksAppender { * @param appender the track which the event belongs to. * @returns the index of the event in all events to be rendered in the flamechart. */ - appendEventAtLevel(event: TraceEngine.Types.TraceEvents.TraceEventData, level: number, appender: TrackAppender): number; + appendEventAtLevel(event: Trace.Types.Events.Event, level: number, appender: TrackAppender): number; /** * Adds into the flame chart data a list of trace events. * @param events the trace events that will be appended to the flame chart. @@ -179,28 +184,29 @@ export declare class CompatibilityTracksAppender { * @returns the next level after the last occupied by the appended these * trace events (the first available level to append next track). */ - appendEventsAtLevel(events: readonly T[], trackStartLevel: number, appender: TrackAppender, eventAppendedCallback?: (event: T, index: number) => void): number; + appendEventsAtLevel(events: readonly T[], trackStartLevel: number, appender: TrackAppender, eventAppendedCallback?: (event: T, index: number) => void): number; /** * Gets the all track appenders that have been set to be visible. */ allVisibleTrackAppenders(): TrackAppender[]; - allThreadAppendersByProcess(): Map; + allThreadAppendersByProcess(): Map; /** * Sets the visible tracks internally * @param visibleTracks set with the names of the visible track * appenders. If undefined, all tracks are set to be visible. */ setVisibleTracks(visibleTracks?: Set): void; + getDrawOverride(event: Trace.Types.Events.Event, level: number): DrawOverride | undefined; /** * Returns the color an event is shown with in the timeline. */ - colorForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData, level: number): string; + colorForEvent(event: Trace.Types.Events.Event, level: number): string; /** * Returns the title an event is shown with in the timeline. */ - titleForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData, level: number): string; + titleForEvent(event: Trace.Types.Events.Event, level: number): string; /** * Returns the info shown when an event in the timeline is hovered. */ - highlightedEntryInfo(event: TraceEngine.Types.TraceEvents.TraceEventData, level: number): HighlightedEntryInfo; + highlightedEntryInfo(event: Trace.Types.Events.Event, level: number): HighlightedEntryInfo; } diff --git a/public/panels/timeline/CompatibilityTracksAppender.js b/public/panels/timeline/CompatibilityTracksAppender.js index ca3efe844..8630bafca 100644 --- a/public/panels/timeline/CompatibilityTracksAppender.js +++ b/public/panels/timeline/CompatibilityTracksAppender.js @@ -3,7 +3,7 @@ // found in the LICENSE file. import * as Common from '../../core/common/common.js'; import * as Root from '../../core/root/root.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js'; import { AnimationsTrackAppender } from './AnimationsTrackAppender.js'; import { getEventLevel, getFormattedTime } from './AppenderUtils.js'; @@ -17,11 +17,11 @@ import { ServerTimingsTrackAppender } from './ServerTimingsTrackAppender.js'; import { ThreadAppender } from './ThreadAppender.js'; import { InstantEventVisibleDurationMs, } from './TimelineFlameChartDataProvider.js'; import { TimingsTrackAppender } from './TimingsTrackAppender.js'; -export function entryIsVisibleInTimeline(entry, traceParsedData) { - if (traceParsedData && traceParsedData.Meta.traceIsGeneric) { +export function entryIsVisibleInTimeline(entry, parsedTrace) { + if (parsedTrace && parsedTrace.Meta.traceIsGeneric) { return true; } - if (TraceEngine.Types.TraceEvents.isTraceEventUpdateCounters(entry)) { + if (Trace.Types.Events.isUpdateCounters(entry)) { // These events are not "visible" on the timeline because they are instant events with 0 duration. // However, the Memory view (CountersGraph in the codebase) relies on // finding the UpdateCounters events within the user's active trace @@ -32,20 +32,17 @@ export function entryIsVisibleInTimeline(entry, traceParsedData) { return true; } // Gate the visibility of post message events behind the experiement flag - if (TraceEngine.Types.TraceEvents.isTraceEventSchedulePostMessage(entry) || - TraceEngine.Types.TraceEvents.isTraceEventHandlePostMessage(entry)) { + if (Trace.Types.Events.isSchedulePostMessage(entry) || Trace.Types.Events.isHandlePostMessage(entry)) { return Root.Runtime.experiments.isEnabled("timeline-show-postmessage-events" /* Root.Runtime.ExperimentName.TIMELINE_SHOW_POST_MESSAGE_EVENTS */); } - if (TraceEngine.Types.Extensions.isSyntheticExtensionEntry(entry) || - TraceEngine.Types.TraceEvents.isSyntheticServerTiming(entry)) { + if (Trace.Types.Extensions.isSyntheticExtensionEntry(entry) || Trace.Types.Events.isSyntheticServerTiming(entry)) { return true; } // Default styles are globally defined for each event name. Some // events are hidden by default. const eventStyle = TimelineComponents.EntryStyles.getEventStyle(entry.name); - const eventIsTiming = TraceEngine.Types.TraceEvents.isTraceEventConsoleTime(entry) || - TraceEngine.Types.TraceEvents.isTraceEventPerformanceMeasure(entry) || - TraceEngine.Types.TraceEvents.isTraceEventPerformanceMark(entry); + const eventIsTiming = Trace.Types.Events.isConsoleTime(entry) || Trace.Types.Events.isPerformanceMeasure(entry) || + Trace.Types.Events.isPerformanceMark(entry); return (eventStyle && !eventStyle.hidden) || eventIsTiming; } export const TrackNames = [ @@ -65,7 +62,7 @@ export class CompatibilityTracksAppender { #eventsForTrack = new Map(); #trackEventsForTreeview = new Map(); #flameChartData; - #traceParsedData; + #parsedTrace; #entryData; #colorGenerator; #allTrackAppenders = []; @@ -81,7 +78,7 @@ export class CompatibilityTracksAppender { /** * @param flameChartData the data used by the flame chart renderer on * which the track data will be appended. - * @param traceParsedData the trace parsing engines output. + * @param parsedTrace the trace parsing engines output. * @param entryData the array containing all event to be rendered in * the flamechart. * @param legacyEntryTypeByLevel an array containing the type of @@ -91,9 +88,9 @@ export class CompatibilityTracksAppender { * architecture and should be removed once all tracks use the new * system. */ - constructor(flameChartData, traceParsedData, entryData, legacyEntryTypeByLevel) { + constructor(flameChartData, parsedTrace, entryData, legacyEntryTypeByLevel) { this.#flameChartData = flameChartData; - this.#traceParsedData = traceParsedData; + this.#parsedTrace = parsedTrace; this.#entryData = entryData; this.#colorGenerator = new Common.Color.Generator( /* hueSpace= */ { min: 30, max: 55, count: undefined }, @@ -101,17 +98,17 @@ export class CompatibilityTracksAppender { /* lightnessSpace= */ 50, /* alphaSpace= */ 0.7); this.#legacyEntryTypeByLevel = legacyEntryTypeByLevel; - this.#timingsTrackAppender = new TimingsTrackAppender(this, this.#traceParsedData, this.#colorGenerator); + this.#timingsTrackAppender = new TimingsTrackAppender(this, this.#parsedTrace, this.#colorGenerator); this.#allTrackAppenders.push(this.#timingsTrackAppender); - this.#interactionsTrackAppender = new InteractionsTrackAppender(this, this.#traceParsedData, this.#colorGenerator); + this.#interactionsTrackAppender = new InteractionsTrackAppender(this, this.#parsedTrace, this.#colorGenerator); this.#allTrackAppenders.push(this.#interactionsTrackAppender); - this.#animationsTrackAppender = new AnimationsTrackAppender(this, this.#traceParsedData); + this.#animationsTrackAppender = new AnimationsTrackAppender(this, this.#parsedTrace); this.#allTrackAppenders.push(this.#animationsTrackAppender); - this.#gpuTrackAppender = new GPUTrackAppender(this, this.#traceParsedData); + this.#gpuTrackAppender = new GPUTrackAppender(this, this.#parsedTrace); this.#allTrackAppenders.push(this.#gpuTrackAppender); - this.#layoutShiftsTrackAppender = new LayoutShiftsTrackAppender(this, this.#traceParsedData); + this.#layoutShiftsTrackAppender = new LayoutShiftsTrackAppender(this, this.#parsedTrace); this.#allTrackAppenders.push(this.#layoutShiftsTrackAppender); - this.#serverTimingsTrackAppender = new ServerTimingsTrackAppender(this, this.#traceParsedData); + this.#serverTimingsTrackAppender = new ServerTimingsTrackAppender(this, this.#parsedTrace); this.#allTrackAppenders.push(this.#serverTimingsTrackAppender); this.#addThreadAppenders(); this.#addExtensionAppenders(); @@ -142,7 +139,7 @@ export class CompatibilityTracksAppender { #addThreadAppenders() { const threadTrackOrder = (appender) => { switch (appender.threadType) { - case "MAIN_THREAD" /* TraceEngine.Handlers.Threads.ThreadType.MAIN_THREAD */: { + case "MAIN_THREAD" /* Trace.Handlers.Threads.ThreadType.MAIN_THREAD */: { if (appender.isOnMainFrame) { // Ensure `about:blank` or `chrome://new-tab-page` are deprioritized, as they're likely not the profiling targets const url = appender.getUrl(); @@ -153,36 +150,36 @@ export class CompatibilityTracksAppender { } return 1; } - case "WORKER" /* TraceEngine.Handlers.Threads.ThreadType.WORKER */: + case "WORKER" /* Trace.Handlers.Threads.ThreadType.WORKER */: return 3; - case "RASTERIZER" /* TraceEngine.Handlers.Threads.ThreadType.RASTERIZER */: + case "RASTERIZER" /* Trace.Handlers.Threads.ThreadType.RASTERIZER */: return 4; - case "THREAD_POOL" /* TraceEngine.Handlers.Threads.ThreadType.THREAD_POOL */: + case "THREAD_POOL" /* Trace.Handlers.Threads.ThreadType.THREAD_POOL */: return 5; - case "AUCTION_WORKLET" /* TraceEngine.Handlers.Threads.ThreadType.AUCTION_WORKLET */: + case "AUCTION_WORKLET" /* Trace.Handlers.Threads.ThreadType.AUCTION_WORKLET */: return 6; - case "OTHER" /* TraceEngine.Handlers.Threads.ThreadType.OTHER */: + case "OTHER" /* Trace.Handlers.Threads.ThreadType.OTHER */: return 7; default: return 8; } }; - const threads = TraceEngine.Handlers.Threads.threadsInTrace(this.#traceParsedData); + const threads = Trace.Handlers.Threads.threadsInTrace(this.#parsedTrace); const processedAuctionWorkletsIds = new Set(); const showAllEvents = Root.Runtime.experiments.isEnabled('timeline-show-all-events'); for (const { pid, tid, name, type } of threads) { - if (this.#traceParsedData.Meta.traceIsGeneric) { + if (this.#parsedTrace.Meta.traceIsGeneric) { // If the trace is generic, we just push all of the threads with no // effort to differentiate them, hence overriding the thread type to be // OTHER for all threads. - this.#threadAppenders.push(new ThreadAppender(this, this.#traceParsedData, pid, tid, name, "OTHER" /* TraceEngine.Handlers.Threads.ThreadType.OTHER */)); + this.#threadAppenders.push(new ThreadAppender(this, this.#parsedTrace, pid, tid, name, "OTHER" /* Trace.Handlers.Threads.ThreadType.OTHER */)); continue; } // These threads have no useful information. Omit them if ((name === 'Chrome_ChildIOThread' || name === 'Compositor' || name === 'GpuMemoryThread') && !showAllEvents) { continue; } - const maybeWorklet = this.#traceParsedData.AuctionWorklets.worklets.get(pid); + const maybeWorklet = this.#parsedTrace.AuctionWorklets.worklets.get(pid); if (processedAuctionWorkletsIds.has(pid)) { // Keep track of this process to ensure we only add the following // tracks once per process and not once per thread. @@ -194,11 +191,11 @@ export class CompatibilityTracksAppender { // 1. the Utility Thread // 2. the V8 Helper Thread // Note that the names passed here are not used visually. TODO: remove this name? - this.#threadAppenders.push(new ThreadAppender(this, this.#traceParsedData, pid, maybeWorklet.args.data.utilityThread.tid, 'auction-worket-utility', "AUCTION_WORKLET" /* TraceEngine.Handlers.Threads.ThreadType.AUCTION_WORKLET */)); - this.#threadAppenders.push(new ThreadAppender(this, this.#traceParsedData, pid, maybeWorklet.args.data.v8HelperThread.tid, 'auction-worklet-v8helper', "AUCTION_WORKLET" /* TraceEngine.Handlers.Threads.ThreadType.AUCTION_WORKLET */)); + this.#threadAppenders.push(new ThreadAppender(this, this.#parsedTrace, pid, maybeWorklet.args.data.utilityThread.tid, 'auction-worket-utility', "AUCTION_WORKLET" /* Trace.Handlers.Threads.ThreadType.AUCTION_WORKLET */)); + this.#threadAppenders.push(new ThreadAppender(this, this.#parsedTrace, pid, maybeWorklet.args.data.v8HelperThread.tid, 'auction-worklet-v8helper', "AUCTION_WORKLET" /* Trace.Handlers.Threads.ThreadType.AUCTION_WORKLET */)); continue; } - this.#threadAppenders.push(new ThreadAppender(this, this.#traceParsedData, pid, tid, name, type)); + this.#threadAppenders.push(new ThreadAppender(this, this.#parsedTrace, pid, tid, name, type)); } // Sort first by track order, then break ties by placing busier tracks first. this.#threadAppenders.sort((a, b) => (threadTrackOrder(a) - threadTrackOrder(b)) || (b.getEntries().length - a.getEntries().length)); @@ -267,14 +264,14 @@ export class CompatibilityTracksAppender { return cachedData; } let trackEvents = this.eventsInTrack(trackAppender); - if (!TraceEngine.Helpers.TreeHelpers.canBuildTreesFromEvents(trackEvents)) { + if (!Trace.Helpers.TreeHelpers.canBuildTreesFromEvents(trackEvents)) { // Some tracks can include both async and sync events. When this // happens, we use all events for the tree views if a trees can be // built from both sync and async events. If this is not possible, // async events are filtered out and only sync events are used // (it's assumed a tree can always be built using a tracks sync // events). - trackEvents = trackEvents.filter(e => !TraceEngine.Types.TraceEvents.isAsyncPhase(e.ph)); + trackEvents = trackEvents.filter(e => !Trace.Types.Events.isPhaseAsync(e.ph)); } this.#trackEventsForTreeview.set(trackAppender, trackEvents); return trackEvents; @@ -353,9 +350,9 @@ export class CompatibilityTracksAppender { this.#entryData.push(event); this.#legacyEntryTypeByLevel[level] = "TrackAppender" /* EntryType.TRACK_APPENDER */; this.#flameChartData.entryLevels[index] = level; - this.#flameChartData.entryStartTimes[index] = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.ts); - const dur = event.dur || TraceEngine.Helpers.Timing.millisecondsToMicroseconds(InstantEventVisibleDurationMs); - this.#flameChartData.entryTotalTimes[index] = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(dur); + this.#flameChartData.entryStartTimes[index] = Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts); + const dur = event.dur || Trace.Helpers.Timing.millisecondsToMicroseconds(InstantEventVisibleDurationMs); + this.#flameChartData.entryTotalTimes[index] = Trace.Helpers.Timing.microSecondsToMilliseconds(dur); return index; } /** @@ -379,7 +376,7 @@ export class CompatibilityTracksAppender { const lastTimestampByLevel = []; for (let i = 0; i < events.length; ++i) { const event = events[i]; - if (!entryIsVisibleInTimeline(event, this.#traceParsedData)) { + if (!entryIsVisibleInTimeline(event, this.#parsedTrace)) { continue; } const level = getEventLevel(event, lastTimestampByLevel); @@ -421,6 +418,13 @@ export class CompatibilityTracksAppender { } this.#visibleTrackNames = visibleTracks; } + getDrawOverride(event, level) { + const track = this.#trackForLevel.get(level); + if (!track) { + throw new Error('Track not found for level'); + } + return track.getDrawOverride?.(event); + } /** * Returns the color an event is shown with in the timeline. */ @@ -447,7 +451,7 @@ export class CompatibilityTracksAppender { if (track.titleForEvent) { return track.titleForEvent(event); } - return TimelineComponents.EntryName.nameForEntry(event, this.#traceParsedData); + return TimelineComponents.EntryName.nameForEntry(event, this.#parsedTrace); } /** * Returns the info shown when an event in the timeline is hovered. @@ -461,7 +465,7 @@ export class CompatibilityTracksAppender { // By doing this here, we ensure that any warnings that are // added to the WarningsHandler are automatically used and added // to the tooltip. - const warningElements = TimelineComponents.DetailsView.buildWarningElementsForEvent(event, this.#traceParsedData); + const warningElements = TimelineComponents.DetailsView.buildWarningElementsForEvent(event, this.#parsedTrace); let title = this.titleForEvent(event, level); let formattedTime = getFormattedTime(event.dur); // If the track defines a custom highlight, call it and use its values. diff --git a/public/panels/timeline/CompatibilityTracksAppender.js.map b/public/panels/timeline/CompatibilityTracksAppender.js.map index 4eb94ab3f..bc1463d28 100644 --- a/public/panels/timeline/CompatibilityTracksAppender.js.map +++ b/public/panels/timeline/CompatibilityTracksAppender.js.map @@ -1 +1 @@ -{"version":3,"file":"CompatibilityTracksAppender.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/CompatibilityTracksAppender.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as Root from '../../core/root/root.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport type * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\n\nimport {AnimationsTrackAppender} from './AnimationsTrackAppender.js';\nimport {getEventLevel, getFormattedTime, type LastTimestampByLevel} from './AppenderUtils.js';\nimport * as TimelineComponents from './components/components.js';\nimport {ExtensionDataGatherer} from './ExtensionDataGatherer.js';\nimport {ExtensionTrackAppender} from './ExtensionTrackAppender.js';\nimport {GPUTrackAppender} from './GPUTrackAppender.js';\nimport {InteractionsTrackAppender} from './InteractionsTrackAppender.js';\nimport {LayoutShiftsTrackAppender} from './LayoutShiftsTrackAppender.js';\nimport {ServerTimingsTrackAppender} from './ServerTimingsTrackAppender.js';\nimport {ThreadAppender} from './ThreadAppender.js';\nimport {\n EntryType,\n InstantEventVisibleDurationMs,\n type TimelineFlameChartEntry,\n} from './TimelineFlameChartDataProvider.js';\nimport {TimingsTrackAppender} from './TimingsTrackAppender.js';\n\nexport type HighlightedEntryInfo = {\n title: string,\n formattedTime: string,\n warningElements?: HTMLSpanElement[],\n};\n\nexport function entryIsVisibleInTimeline(\n entry: TraceEngine.Types.TraceEvents.TraceEventData,\n traceParsedData?: TraceEngine.Handlers.Types.TraceParseData): boolean {\n if (traceParsedData && traceParsedData.Meta.traceIsGeneric) {\n return true;\n }\n\n if (TraceEngine.Types.TraceEvents.isTraceEventUpdateCounters(entry)) {\n // These events are not \"visible\" on the timeline because they are instant events with 0 duration.\n // However, the Memory view (CountersGraph in the codebase) relies on\n // finding the UpdateCounters events within the user's active trace\n // selection in order to show the memory usage for the selected time\n // period.\n // Therefore we mark them as visible so they are appended onto the Thread\n // track, and hence accessible by the CountersGraph view.\n return true;\n }\n\n // Gate the visibility of post message events behind the experiement flag\n if (TraceEngine.Types.TraceEvents.isTraceEventSchedulePostMessage(entry) ||\n TraceEngine.Types.TraceEvents.isTraceEventHandlePostMessage(entry)) {\n return Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_SHOW_POST_MESSAGE_EVENTS);\n }\n\n if (TraceEngine.Types.Extensions.isSyntheticExtensionEntry(entry) ||\n TraceEngine.Types.TraceEvents.isSyntheticServerTiming(entry)) {\n return true;\n }\n\n // Default styles are globally defined for each event name. Some\n // events are hidden by default.\n const eventStyle =\n TimelineComponents.EntryStyles.getEventStyle(entry.name as TraceEngine.Types.TraceEvents.KnownEventName);\n const eventIsTiming = TraceEngine.Types.TraceEvents.isTraceEventConsoleTime(entry) ||\n TraceEngine.Types.TraceEvents.isTraceEventPerformanceMeasure(entry) ||\n TraceEngine.Types.TraceEvents.isTraceEventPerformanceMark(entry);\n\n return (eventStyle && !eventStyle.hidden) || eventIsTiming;\n}\n\n/**\n * Track appenders add the data of each track into the timeline flame\n * chart. Each track appender also implements functions tha allow the\n * canvas renderer to gather more information about an event in a track,\n * like its display name or color.\n *\n * At the moment, tracks in the timeline flame chart are appended in\n * two locations: in the TimelineFlameChartDataProvider and in the track\n * appenders exported by this module. As part of the work to use a new\n * trace parsing engine, a track appender will be defined with this API\n * for each of the tracks in the timeline. With this implementation in\n * place its counterpart in the TimelineFlameChartDataProvider can be\n * removed. This processes of doing this for a track is referred to as\n * \"migrating the track\" to the new system.\n *\n * The migration implementation will result beneficial among other\n * things because the complexity of rendering the details of each track\n * is distributed among multiple standalone modules.\n * Read more at go/rpp-flamechart-arch\n */\n\nexport interface TrackAppender {\n /**\n * The unique name given to the track appender.\n */\n appenderName: TrackAppenderName;\n\n /**\n * Appends into the flame chart data the data corresponding to a track.\n * @param level the horizontal level of the flame chart events where the\n * track's events will start being appended.\n * @param expanded wether the track should be rendered expanded.\n * @returns the first available level to append more data after having\n * appended the track's events.\n */\n appendTrackAtLevel(level: number, expanded?: boolean): number;\n /**\n * Returns the color an event is shown with in the timeline.\n */\n colorForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): string;\n /**\n * Returns the title an event is shown with in the timeline.\n */\n titleForEvent?(event: TraceEngine.Types.TraceEvents.TraceEventData): string;\n /**\n * Returns the info shown when an event in the timeline is hovered.\n */\n highlightedEntryInfo?(event: TraceEngine.Types.TraceEvents.TraceEventData): Partial;\n}\n\nexport const TrackNames = [\n 'Animations',\n 'Timings',\n 'Interactions',\n 'GPU',\n 'LayoutShifts',\n 'Thread',\n 'Thread_AuctionWorklet',\n 'Extension',\n 'ServerTimings',\n] as const;\n// Network track will use TrackAppender interface, but it won't be shown in Main flamechart.\n// So manually add it to TrackAppenderName.\nexport type TrackAppenderName = typeof TrackNames[number]|'Network';\n\n/**\n * Used as the context when a track (aka group) is selected and we log\n * something to the VE Logging framework.\n * This enum broadly corresponds with the list of TrackNames, but can be more\n * specific in some situations such as when we want to identify the thread type\n * rather than log \"thread\" - it is useful to know if the thread is the main\n * thread or not.\n * VE context needs to be kebab-case, and not contain any PII, which is why we\n * log this set list rather than full track names, which in the case of threads\n * can contain URLswhich we do not want to log.\n */\nexport const enum VisualLoggingTrackName {\n ANIMATIONS = 'animations',\n TIMINGS = 'timings',\n INTERACTIONS = 'interactions',\n GPU = 'gpu',\n LAYOUT_SHIFTS = 'layout-shifts',\n SERVER_TIMINGS = 'server.timings',\n THREAD_CPU_PROFILE = 'thread.cpu-profile',\n THREAD_MAIN = 'thread.main',\n THREAD_FRAME = 'thread.frame',\n THREAD_WORKER = 'thread.worker',\n THREAD_AUCTION_WORKLET = 'thread.auction-worklet',\n THREAD_RASTERIZER = 'thread.rasterizer',\n THREAD_POOL = 'thread.pool',\n THREAD_OTHER = 'thread.other',\n EXTENSION = 'extension',\n NETWORK = 'network',\n}\n\nexport class CompatibilityTracksAppender {\n #trackForLevel = new Map();\n #trackForGroup = new Map();\n #eventsForTrack = new Map();\n #trackEventsForTreeview = new Map();\n #flameChartData: PerfUI.FlameChart.FlameChartTimelineData;\n #traceParsedData: TraceEngine.Handlers.Types.TraceParseData;\n #entryData: TimelineFlameChartEntry[];\n #colorGenerator: Common.Color.Generator;\n #allTrackAppenders: TrackAppender[] = [];\n #visibleTrackNames: Set = new Set([...TrackNames]);\n\n #legacyEntryTypeByLevel: EntryType[];\n #timingsTrackAppender: TimingsTrackAppender;\n #animationsTrackAppender: AnimationsTrackAppender;\n #interactionsTrackAppender: InteractionsTrackAppender;\n #gpuTrackAppender: GPUTrackAppender;\n #layoutShiftsTrackAppender: LayoutShiftsTrackAppender;\n #threadAppenders: ThreadAppender[] = [];\n #serverTimingsTrackAppender: ServerTimingsTrackAppender;\n\n /**\n * @param flameChartData the data used by the flame chart renderer on\n * which the track data will be appended.\n * @param traceParsedData the trace parsing engines output.\n * @param entryData the array containing all event to be rendered in\n * the flamechart.\n * @param legacyEntryTypeByLevel an array containing the type of\n * each entry in the entryData array. Indexed by the position the\n * corresponding entry occupies in the entryData array. This reference\n * is needed only for compatibility with the legacy flamechart\n * architecture and should be removed once all tracks use the new\n * system.\n */\n constructor(\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData,\n traceParsedData: TraceEngine.Handlers.Types.TraceParseData, entryData: TimelineFlameChartEntry[],\n legacyEntryTypeByLevel: EntryType[]) {\n this.#flameChartData = flameChartData;\n this.#traceParsedData = traceParsedData;\n this.#entryData = entryData;\n this.#colorGenerator = new Common.Color.Generator(\n /* hueSpace= */ {min: 30, max: 55, count: undefined},\n /* satSpace= */ {min: 70, max: 100, count: 6},\n /* lightnessSpace= */ 50,\n /* alphaSpace= */ 0.7);\n this.#legacyEntryTypeByLevel = legacyEntryTypeByLevel;\n this.#timingsTrackAppender = new TimingsTrackAppender(this, this.#traceParsedData, this.#colorGenerator);\n this.#allTrackAppenders.push(this.#timingsTrackAppender);\n\n this.#interactionsTrackAppender = new InteractionsTrackAppender(this, this.#traceParsedData, this.#colorGenerator);\n this.#allTrackAppenders.push(this.#interactionsTrackAppender);\n\n this.#animationsTrackAppender = new AnimationsTrackAppender(this, this.#traceParsedData);\n this.#allTrackAppenders.push(this.#animationsTrackAppender);\n\n this.#gpuTrackAppender = new GPUTrackAppender(this, this.#traceParsedData);\n this.#allTrackAppenders.push(this.#gpuTrackAppender);\n\n this.#layoutShiftsTrackAppender = new LayoutShiftsTrackAppender(this, this.#traceParsedData);\n this.#allTrackAppenders.push(this.#layoutShiftsTrackAppender);\n\n this.#serverTimingsTrackAppender = new ServerTimingsTrackAppender(this, this.#traceParsedData);\n this.#allTrackAppenders.push(this.#serverTimingsTrackAppender);\n this.#addThreadAppenders();\n this.#addExtensionAppenders();\n ThemeSupport.ThemeSupport.instance().addEventListener(ThemeSupport.ThemeChangeEvent.eventName, () => {\n for (const group of this.#flameChartData.groups) {\n // We only need to update the color here, because FlameChart will call `scheduleUpdate()` when theme is changed.\n group.style.color = ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-on-surface');\n group.style.backgroundColor =\n ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-cdt-base-container');\n }\n });\n }\n\n setFlameChartDataAndEntryData(\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData, entryData: TimelineFlameChartEntry[],\n legacyEntryTypeByLevel: EntryType[]): void {\n this.#trackForGroup.clear();\n this.#flameChartData = flameChartData;\n this.#entryData = entryData;\n this.#legacyEntryTypeByLevel = legacyEntryTypeByLevel;\n }\n\n getFlameChartTimelineData(): PerfUI.FlameChart.FlameChartTimelineData {\n return this.#flameChartData;\n }\n\n #addExtensionAppenders(): void {\n const tracks = ExtensionDataGatherer.instance().getExtensionData().extensionTrackData;\n for (const trackData of tracks) {\n this.#allTrackAppenders.push(new ExtensionTrackAppender(this, trackData));\n }\n }\n\n #addThreadAppenders(): void {\n const threadTrackOrder = (appender: ThreadAppender): number => {\n switch (appender.threadType) {\n case TraceEngine.Handlers.Threads.ThreadType.MAIN_THREAD: {\n if (appender.isOnMainFrame) {\n // Ensure `about:blank` or `chrome://new-tab-page` are deprioritized, as they're likely not the profiling targets\n const url = appender.getUrl();\n if (url.startsWith('about:') || url.startsWith('chrome:')) {\n return 2;\n }\n return 0;\n }\n return 1;\n }\n case TraceEngine.Handlers.Threads.ThreadType.WORKER:\n return 3;\n case TraceEngine.Handlers.Threads.ThreadType.RASTERIZER:\n return 4;\n case TraceEngine.Handlers.Threads.ThreadType.THREAD_POOL:\n return 5;\n case TraceEngine.Handlers.Threads.ThreadType.AUCTION_WORKLET:\n return 6;\n case TraceEngine.Handlers.Threads.ThreadType.OTHER:\n return 7;\n default:\n return 8;\n }\n };\n const threads = TraceEngine.Handlers.Threads.threadsInTrace(this.#traceParsedData);\n const processedAuctionWorkletsIds = new Set();\n const showAllEvents = Root.Runtime.experiments.isEnabled('timeline-show-all-events');\n\n for (const {pid, tid, name, type} of threads) {\n if (this.#traceParsedData.Meta.traceIsGeneric) {\n // If the trace is generic, we just push all of the threads with no\n // effort to differentiate them, hence overriding the thread type to be\n // OTHER for all threads.\n this.#threadAppenders.push(new ThreadAppender(\n this, this.#traceParsedData, pid, tid, name, TraceEngine.Handlers.Threads.ThreadType.OTHER));\n continue;\n }\n // These threads have no useful information. Omit them\n if ((name === 'Chrome_ChildIOThread' || name === 'Compositor' || name === 'GpuMemoryThread') && !showAllEvents) {\n continue;\n }\n\n const maybeWorklet = this.#traceParsedData.AuctionWorklets.worklets.get(pid);\n if (processedAuctionWorkletsIds.has(pid)) {\n // Keep track of this process to ensure we only add the following\n // tracks once per process and not once per thread.\n continue;\n }\n if (maybeWorklet) {\n processedAuctionWorkletsIds.add(pid);\n // Each AuctionWorklet event represents two threads:\n // 1. the Utility Thread\n // 2. the V8 Helper Thread\n // Note that the names passed here are not used visually. TODO: remove this name?\n this.#threadAppenders.push(new ThreadAppender(\n this, this.#traceParsedData, pid, maybeWorklet.args.data.utilityThread.tid, 'auction-worket-utility',\n TraceEngine.Handlers.Threads.ThreadType.AUCTION_WORKLET));\n this.#threadAppenders.push(new ThreadAppender(\n this, this.#traceParsedData, pid, maybeWorklet.args.data.v8HelperThread.tid, 'auction-worklet-v8helper',\n TraceEngine.Handlers.Threads.ThreadType.AUCTION_WORKLET));\n continue;\n }\n\n this.#threadAppenders.push(new ThreadAppender(this, this.#traceParsedData, pid, tid, name, type));\n }\n // Sort first by track order, then break ties by placing busier tracks first.\n this.#threadAppenders.sort(\n (a, b) => (threadTrackOrder(a) - threadTrackOrder(b)) || (b.getEntries().length - a.getEntries().length));\n this.#allTrackAppenders.push(...this.#threadAppenders);\n }\n\n timingsTrackAppender(): TimingsTrackAppender {\n return this.#timingsTrackAppender;\n }\n\n animationsTrackAppender(): AnimationsTrackAppender {\n return this.#animationsTrackAppender;\n }\n\n interactionsTrackAppender(): InteractionsTrackAppender {\n return this.#interactionsTrackAppender;\n }\n\n gpuTrackAppender(): GPUTrackAppender {\n return this.#gpuTrackAppender;\n }\n\n layoutShiftsTrackAppender(): LayoutShiftsTrackAppender {\n return this.#layoutShiftsTrackAppender;\n }\n\n threadAppenders(): ThreadAppender[] {\n return this.#threadAppenders;\n }\n\n serverTimingsTrackAppender(): ServerTimingsTrackAppender {\n return this.#serverTimingsTrackAppender;\n }\n\n eventsInTrack(trackAppender: TrackAppender): TraceEngine.Types.TraceEvents.TraceEventData[] {\n const cachedData = this.#eventsForTrack.get(trackAppender);\n if (cachedData) {\n return cachedData;\n }\n\n // Calculate the levels occupied by a track.\n let trackStartLevel = null;\n let trackEndLevel = null;\n for (const [level, track] of this.#trackForLevel) {\n if (track !== trackAppender) {\n continue;\n }\n if (trackStartLevel === null) {\n trackStartLevel = level;\n }\n trackEndLevel = level;\n }\n\n if (trackStartLevel === null || trackEndLevel === null) {\n throw new Error(`Could not find events for track: ${trackAppender}`);\n }\n const entryLevels = this.#flameChartData.entryLevels;\n const events = [];\n for (let i = 0; i < entryLevels.length; i++) {\n if (trackStartLevel <= entryLevels[i] && entryLevels[i] <= trackEndLevel) {\n events.push(this.#entryData[i] as TraceEngine.Types.TraceEvents.TraceEventData);\n }\n }\n events.sort((a, b) => a.ts - b.ts); // TODO(paulirish): Remove as I'm 90% it's already sorted.\n\n this.#eventsForTrack.set(trackAppender, events);\n return events;\n }\n\n /**\n * Gets the events to be shown in the tree views of the details pane\n * (Bottom-up, Call tree, etc.). These are the events from the track\n * that can be arranged in a tree shape.\n */\n eventsForTreeView(trackAppender: TrackAppender): TraceEngine.Types.TraceEvents.TraceEventData[] {\n const cachedData = this.#trackEventsForTreeview.get(trackAppender);\n if (cachedData) {\n return cachedData;\n }\n\n let trackEvents = this.eventsInTrack(trackAppender);\n if (!TraceEngine.Helpers.TreeHelpers.canBuildTreesFromEvents(trackEvents)) {\n // Some tracks can include both async and sync events. When this\n // happens, we use all events for the tree views if a trees can be\n // built from both sync and async events. If this is not possible,\n // async events are filtered out and only sync events are used\n // (it's assumed a tree can always be built using a tracks sync\n // events).\n trackEvents = trackEvents.filter(e => !TraceEngine.Types.TraceEvents.isAsyncPhase(e.ph));\n }\n this.#trackEventsForTreeview.set(trackAppender, trackEvents);\n return trackEvents;\n }\n\n /**\n * Caches the track appender that owns a flame chart group. FlameChart\n * groups are created for each track in the timeline. When an user\n * selects a track in the UI, the track's group is passed to the model\n * layer to inform about the selection.\n */\n registerTrackForGroup(group: PerfUI.FlameChart.Group, appender: TrackAppender): void {\n this.#flameChartData.groups.push(group);\n this.#trackForGroup.set(group, appender);\n }\n\n /**\n * Returns number of tracks of given type already appended.\n * Used to name the \"Raster Thread 6\" tracks, etc\n */\n getCurrentTrackCountForThreadType(threadType: TraceEngine.Handlers.Threads.ThreadType.RASTERIZER|\n TraceEngine.Handlers.Threads.ThreadType.THREAD_POOL): number {\n return this.#threadAppenders.filter(appender => appender.threadType === threadType && appender.headerAppended())\n .length;\n }\n\n /**\n * Looks up a FlameChart group for a given appender.\n */\n groupForAppender(targetAppender: TrackAppender): PerfUI.FlameChart.Group|null {\n let foundGroup: PerfUI.FlameChart.Group|null = null;\n for (const [group, appender] of this.#trackForGroup) {\n if (appender === targetAppender) {\n foundGroup = group;\n break;\n }\n }\n return foundGroup;\n }\n\n /**\n * Given a FlameChart group, gets the events to be shown in the tree\n * views if that group was registered by the appender system.\n */\n groupEventsForTreeView(group: PerfUI.FlameChart.Group): TraceEngine.Types.TraceEvents.TraceEventData[]|null {\n const track = this.#trackForGroup.get(group);\n if (!track) {\n return null;\n }\n return this.eventsForTreeView(track);\n }\n\n /**\n * Caches the track appender that owns a level. An appender takes\n * ownership of a level when it appends data to it.\n * The cache is useful to determine what appender should handle a\n * query from the flame chart renderer when an event's feature (like\n * style, title, etc.) is needed.\n */\n registerTrackForLevel(level: number, appender: TrackAppender): void {\n // TODO(crbug.com/1442454) Figure out how to avoid the circular calls.\n this.#trackForLevel.set(level, appender);\n }\n\n groupForLevel(level: number): PerfUI.FlameChart.Group|null {\n const appenderForLevel = this.#trackForLevel.get(level);\n if (!appenderForLevel) {\n return null;\n }\n return this.groupForAppender(appenderForLevel);\n }\n\n /**\n * Adds an event to the flame chart data at a defined level.\n * @param event the event to be appended,\n * @param level the level to append the event,\n * @param appender the track which the event belongs to.\n * @returns the index of the event in all events to be rendered in the flamechart.\n */\n appendEventAtLevel(event: TraceEngine.Types.TraceEvents.TraceEventData, level: number, appender: TrackAppender):\n number {\n // TODO(crbug.com/1442454) Figure out how to avoid the circular calls.\n this.#trackForLevel.set(level, appender);\n const index = this.#entryData.length;\n this.#entryData.push(event);\n this.#legacyEntryTypeByLevel[level] = EntryType.TRACK_APPENDER;\n this.#flameChartData.entryLevels[index] = level;\n this.#flameChartData.entryStartTimes[index] = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.ts);\n const dur = event.dur || TraceEngine.Helpers.Timing.millisecondsToMicroseconds(InstantEventVisibleDurationMs);\n this.#flameChartData.entryTotalTimes[index] = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(dur);\n return index;\n }\n\n /**\n * Adds into the flame chart data a list of trace events.\n * @param events the trace events that will be appended to the flame chart.\n * The events should be taken straight from the trace handlers. The handlers\n * should sort the events by start time, and the parent event is before the\n * child.\n * @param trackStartLevel the flame chart level from which the events will\n * be appended.\n * @param appender the track that the trace events belong to.\n * @param eventAppendedCallback an optional function called after the\n * event has been added to the timeline data. This allows the caller\n * to know f.e. the position of the event in the entry data. Use this\n * hook to customize the data after it has been appended, f.e. to add\n * decorations to a set of the entries.\n * @returns the next level after the last occupied by the appended these\n * trace events (the first available level to append next track).\n */\n appendEventsAtLevel(\n events: readonly T[], trackStartLevel: number, appender: TrackAppender,\n eventAppendedCallback?: (event: T, index: number) => void): number {\n const lastTimestampByLevel: LastTimestampByLevel = [];\n for (let i = 0; i < events.length; ++i) {\n const event = events[i];\n if (!entryIsVisibleInTimeline(event, this.#traceParsedData)) {\n continue;\n }\n\n const level = getEventLevel(event, lastTimestampByLevel);\n const index = this.appendEventAtLevel(event, trackStartLevel + level, appender);\n eventAppendedCallback?.(event, index);\n }\n\n this.#legacyEntryTypeByLevel.length = trackStartLevel + lastTimestampByLevel.length;\n this.#legacyEntryTypeByLevel.fill(EntryType.TRACK_APPENDER, trackStartLevel);\n return trackStartLevel + lastTimestampByLevel.length;\n }\n\n /**\n * Gets the all track appenders that have been set to be visible.\n */\n allVisibleTrackAppenders(): TrackAppender[] {\n return this.#allTrackAppenders.filter(track => this.#visibleTrackNames.has(track.appenderName));\n }\n\n allThreadAppendersByProcess(): Map {\n const appenders = this.allVisibleTrackAppenders();\n const result = new Map();\n for (const appender of appenders) {\n if (!(appender instanceof ThreadAppender)) {\n continue;\n }\n const existing = result.get(appender.processId()) ?? [];\n existing.push(appender);\n result.set(appender.processId(), existing);\n }\n return result;\n }\n\n /**\n * Sets the visible tracks internally\n * @param visibleTracks set with the names of the visible track\n * appenders. If undefined, all tracks are set to be visible.\n */\n setVisibleTracks(visibleTracks?: Set): void {\n if (!visibleTracks) {\n this.#visibleTrackNames = new Set([...TrackNames]);\n return;\n }\n this.#visibleTrackNames = visibleTracks;\n }\n\n /**\n * Returns the color an event is shown with in the timeline.\n */\n colorForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData, level: number): string {\n const track = this.#trackForLevel.get(level);\n if (!track) {\n throw new Error('Track not found for level');\n }\n return track.colorForEvent(event);\n }\n /**\n * Returns the title an event is shown with in the timeline.\n */\n titleForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData, level: number): string {\n const track = this.#trackForLevel.get(level);\n if (!track) {\n throw new Error('Track not found for level');\n }\n\n // Historically all tracks would have a titleForEvent() method.\n // However, we are working on migrating all event title logic into one place (components/EntryName)\n // TODO(crbug.com/365047728):\n // Once this migration is complete, no tracks will have a custom\n // titleForEvent method and we can remove titleForEvent entirely.\n if (track.titleForEvent) {\n return track.titleForEvent(event);\n }\n return TimelineComponents.EntryName.nameForEntry(event, this.#traceParsedData);\n }\n /**\n * Returns the info shown when an event in the timeline is hovered.\n */\n highlightedEntryInfo(event: TraceEngine.Types.TraceEvents.TraceEventData, level: number): HighlightedEntryInfo {\n const track = this.#trackForLevel.get(level);\n if (!track) {\n throw new Error('Track not found for level');\n }\n\n // Add any warnings information to the tooltip. Done here to avoid duplicating this call in every appender.\n // By doing this here, we ensure that any warnings that are\n // added to the WarningsHandler are automatically used and added\n // to the tooltip.\n const warningElements: HTMLSpanElement[] =\n TimelineComponents.DetailsView.buildWarningElementsForEvent(event, this.#traceParsedData);\n\n let title = this.titleForEvent(event, level);\n let formattedTime = getFormattedTime(event.dur);\n\n // If the track defines a custom highlight, call it and use its values.\n if (track.highlightedEntryInfo) {\n const {title: customTitle, formattedTime: customFormattedTime, warningElements: extraWarningElements} =\n track.highlightedEntryInfo(event);\n if (customTitle) {\n title = customTitle;\n }\n if (customFormattedTime) {\n formattedTime = customFormattedTime;\n }\n if (extraWarningElements) {\n warningElements.push(...extraWarningElements);\n }\n }\n return {\n title,\n formattedTime,\n warningElements,\n };\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"CompatibilityTracksAppender.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/CompatibilityTracksAppender.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as Root from '../../core/root/root.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport type * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\n\nimport {AnimationsTrackAppender} from './AnimationsTrackAppender.js';\nimport {getEventLevel, getFormattedTime, type LastTimestampByLevel} from './AppenderUtils.js';\nimport * as TimelineComponents from './components/components.js';\nimport {ExtensionDataGatherer} from './ExtensionDataGatherer.js';\nimport {ExtensionTrackAppender} from './ExtensionTrackAppender.js';\nimport {GPUTrackAppender} from './GPUTrackAppender.js';\nimport {InteractionsTrackAppender} from './InteractionsTrackAppender.js';\nimport {LayoutShiftsTrackAppender} from './LayoutShiftsTrackAppender.js';\nimport {ServerTimingsTrackAppender} from './ServerTimingsTrackAppender.js';\nimport {ThreadAppender} from './ThreadAppender.js';\nimport {\n EntryType,\n InstantEventVisibleDurationMs,\n type TimelineFlameChartEntry,\n} from './TimelineFlameChartDataProvider.js';\nimport {TimingsTrackAppender} from './TimingsTrackAppender.js';\n\nexport type HighlightedEntryInfo = {\n title: string,\n formattedTime: string,\n warningElements?: HTMLSpanElement[],\n};\n\nexport function entryIsVisibleInTimeline(\n entry: Trace.Types.Events.Event, parsedTrace?: Trace.Handlers.Types.ParsedTrace): boolean {\n if (parsedTrace && parsedTrace.Meta.traceIsGeneric) {\n return true;\n }\n\n if (Trace.Types.Events.isUpdateCounters(entry)) {\n // These events are not \"visible\" on the timeline because they are instant events with 0 duration.\n // However, the Memory view (CountersGraph in the codebase) relies on\n // finding the UpdateCounters events within the user's active trace\n // selection in order to show the memory usage for the selected time\n // period.\n // Therefore we mark them as visible so they are appended onto the Thread\n // track, and hence accessible by the CountersGraph view.\n return true;\n }\n\n // Gate the visibility of post message events behind the experiement flag\n if (Trace.Types.Events.isSchedulePostMessage(entry) || Trace.Types.Events.isHandlePostMessage(entry)) {\n return Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_SHOW_POST_MESSAGE_EVENTS);\n }\n\n if (Trace.Types.Extensions.isSyntheticExtensionEntry(entry) || Trace.Types.Events.isSyntheticServerTiming(entry)) {\n return true;\n }\n\n // Default styles are globally defined for each event name. Some\n // events are hidden by default.\n const eventStyle = TimelineComponents.EntryStyles.getEventStyle(entry.name as Trace.Types.Events.Name);\n const eventIsTiming = Trace.Types.Events.isConsoleTime(entry) || Trace.Types.Events.isPerformanceMeasure(entry) ||\n Trace.Types.Events.isPerformanceMark(entry);\n\n return (eventStyle && !eventStyle.hidden) || eventIsTiming;\n}\n\n/**\n * Track appenders add the data of each track into the timeline flame\n * chart. Each track appender also implements functions tha allow the\n * canvas renderer to gather more information about an event in a track,\n * like its display name or color.\n *\n * At the moment, tracks in the timeline flame chart are appended in\n * two locations: in the TimelineFlameChartDataProvider and in the track\n * appenders exported by this module. As part of the work to use a new\n * trace parsing engine, a track appender will be defined with this API\n * for each of the tracks in the timeline. With this implementation in\n * place its counterpart in the TimelineFlameChartDataProvider can be\n * removed. This processes of doing this for a track is referred to as\n * \"migrating the track\" to the new system.\n *\n * The migration implementation will result beneficial among other\n * things because the complexity of rendering the details of each track\n * is distributed among multiple standalone modules.\n * Read more at go/rpp-flamechart-arch\n */\n\nexport interface TrackAppender {\n /**\n * The unique name given to the track appender.\n */\n appenderName: TrackAppenderName;\n\n /**\n * Appends into the flame chart data the data corresponding to a track.\n * @param level the horizontal level of the flame chart events where the\n * track's events will start being appended.\n * @param expanded wether the track should be rendered expanded.\n * @returns the first available level to append more data after having\n * appended the track's events.\n */\n appendTrackAtLevel(level: number, expanded?: boolean): number;\n /**\n * Returns the color an event is shown with in the timeline.\n */\n colorForEvent(event: Trace.Types.Events.Event): string;\n /**\n * Returns the title an event is shown with in the timeline.\n */\n titleForEvent?(event: Trace.Types.Events.Event): string;\n /**\n * Returns the info shown when an event in the timeline is hovered.\n */\n highlightedEntryInfo?(event: Trace.Types.Events.Event): Partial;\n /**\n * Returns the a callback function to draw an event to overrides the normal rectangle draw operation.\n */\n getDrawOverride?(event: Trace.Types.Events.Event): DrawOverride|undefined;\n}\n\nexport const TrackNames = [\n 'Animations',\n 'Timings',\n 'Interactions',\n 'GPU',\n 'LayoutShifts',\n 'Thread',\n 'Thread_AuctionWorklet',\n 'Extension',\n 'ServerTimings',\n] as const;\n// Network track will use TrackAppender interface, but it won't be shown in Main flamechart.\n// So manually add it to TrackAppenderName.\nexport type TrackAppenderName = typeof TrackNames[number]|'Network';\n\nexport type DrawOverride = PerfUI.FlameChart.DrawOverride;\n\n/**\n * Used as the context when a track (aka group) is selected and we log\n * something to the VE Logging framework.\n * This enum broadly corresponds with the list of TrackNames, but can be more\n * specific in some situations such as when we want to identify the thread type\n * rather than log \"thread\" - it is useful to know if the thread is the main\n * thread or not.\n * VE context needs to be kebab-case, and not contain any PII, which is why we\n * log this set list rather than full track names, which in the case of threads\n * can contain URLswhich we do not want to log.\n */\nexport const enum VisualLoggingTrackName {\n ANIMATIONS = 'animations',\n TIMINGS = 'timings',\n INTERACTIONS = 'interactions',\n GPU = 'gpu',\n LAYOUT_SHIFTS = 'layout-shifts',\n SERVER_TIMINGS = 'server.timings',\n THREAD_CPU_PROFILE = 'thread.cpu-profile',\n THREAD_MAIN = 'thread.main',\n THREAD_FRAME = 'thread.frame',\n THREAD_WORKER = 'thread.worker',\n THREAD_AUCTION_WORKLET = 'thread.auction-worklet',\n THREAD_RASTERIZER = 'thread.rasterizer',\n THREAD_POOL = 'thread.pool',\n THREAD_OTHER = 'thread.other',\n EXTENSION = 'extension',\n NETWORK = 'network',\n}\n\nexport class CompatibilityTracksAppender {\n #trackForLevel = new Map();\n #trackForGroup = new Map();\n #eventsForTrack = new Map();\n #trackEventsForTreeview = new Map();\n #flameChartData: PerfUI.FlameChart.FlameChartTimelineData;\n #parsedTrace: Trace.Handlers.Types.ParsedTrace;\n #entryData: TimelineFlameChartEntry[];\n #colorGenerator: Common.Color.Generator;\n #allTrackAppenders: TrackAppender[] = [];\n #visibleTrackNames: Set = new Set([...TrackNames]);\n\n #legacyEntryTypeByLevel: EntryType[];\n #timingsTrackAppender: TimingsTrackAppender;\n #animationsTrackAppender: AnimationsTrackAppender;\n #interactionsTrackAppender: InteractionsTrackAppender;\n #gpuTrackAppender: GPUTrackAppender;\n #layoutShiftsTrackAppender: LayoutShiftsTrackAppender;\n #threadAppenders: ThreadAppender[] = [];\n #serverTimingsTrackAppender: ServerTimingsTrackAppender;\n\n /**\n * @param flameChartData the data used by the flame chart renderer on\n * which the track data will be appended.\n * @param parsedTrace the trace parsing engines output.\n * @param entryData the array containing all event to be rendered in\n * the flamechart.\n * @param legacyEntryTypeByLevel an array containing the type of\n * each entry in the entryData array. Indexed by the position the\n * corresponding entry occupies in the entryData array. This reference\n * is needed only for compatibility with the legacy flamechart\n * architecture and should be removed once all tracks use the new\n * system.\n */\n constructor(\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData, parsedTrace: Trace.Handlers.Types.ParsedTrace,\n entryData: TimelineFlameChartEntry[], legacyEntryTypeByLevel: EntryType[]) {\n this.#flameChartData = flameChartData;\n this.#parsedTrace = parsedTrace;\n this.#entryData = entryData;\n this.#colorGenerator = new Common.Color.Generator(\n /* hueSpace= */ {min: 30, max: 55, count: undefined},\n /* satSpace= */ {min: 70, max: 100, count: 6},\n /* lightnessSpace= */ 50,\n /* alphaSpace= */ 0.7);\n this.#legacyEntryTypeByLevel = legacyEntryTypeByLevel;\n this.#timingsTrackAppender = new TimingsTrackAppender(this, this.#parsedTrace, this.#colorGenerator);\n this.#allTrackAppenders.push(this.#timingsTrackAppender);\n\n this.#interactionsTrackAppender = new InteractionsTrackAppender(this, this.#parsedTrace, this.#colorGenerator);\n this.#allTrackAppenders.push(this.#interactionsTrackAppender);\n\n this.#animationsTrackAppender = new AnimationsTrackAppender(this, this.#parsedTrace);\n this.#allTrackAppenders.push(this.#animationsTrackAppender);\n\n this.#gpuTrackAppender = new GPUTrackAppender(this, this.#parsedTrace);\n this.#allTrackAppenders.push(this.#gpuTrackAppender);\n\n this.#layoutShiftsTrackAppender = new LayoutShiftsTrackAppender(this, this.#parsedTrace);\n this.#allTrackAppenders.push(this.#layoutShiftsTrackAppender);\n\n this.#serverTimingsTrackAppender = new ServerTimingsTrackAppender(this, this.#parsedTrace);\n this.#allTrackAppenders.push(this.#serverTimingsTrackAppender);\n this.#addThreadAppenders();\n this.#addExtensionAppenders();\n ThemeSupport.ThemeSupport.instance().addEventListener(ThemeSupport.ThemeChangeEvent.eventName, () => {\n for (const group of this.#flameChartData.groups) {\n // We only need to update the color here, because FlameChart will call `scheduleUpdate()` when theme is changed.\n group.style.color = ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-on-surface');\n group.style.backgroundColor =\n ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-cdt-base-container');\n }\n });\n }\n\n setFlameChartDataAndEntryData(\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData, entryData: TimelineFlameChartEntry[],\n legacyEntryTypeByLevel: EntryType[]): void {\n this.#trackForGroup.clear();\n this.#flameChartData = flameChartData;\n this.#entryData = entryData;\n this.#legacyEntryTypeByLevel = legacyEntryTypeByLevel;\n }\n\n getFlameChartTimelineData(): PerfUI.FlameChart.FlameChartTimelineData {\n return this.#flameChartData;\n }\n\n #addExtensionAppenders(): void {\n const tracks = ExtensionDataGatherer.instance().getExtensionData().extensionTrackData;\n for (const trackData of tracks) {\n this.#allTrackAppenders.push(new ExtensionTrackAppender(this, trackData));\n }\n }\n\n #addThreadAppenders(): void {\n const threadTrackOrder = (appender: ThreadAppender): number => {\n switch (appender.threadType) {\n case Trace.Handlers.Threads.ThreadType.MAIN_THREAD: {\n if (appender.isOnMainFrame) {\n // Ensure `about:blank` or `chrome://new-tab-page` are deprioritized, as they're likely not the profiling targets\n const url = appender.getUrl();\n if (url.startsWith('about:') || url.startsWith('chrome:')) {\n return 2;\n }\n return 0;\n }\n return 1;\n }\n case Trace.Handlers.Threads.ThreadType.WORKER:\n return 3;\n case Trace.Handlers.Threads.ThreadType.RASTERIZER:\n return 4;\n case Trace.Handlers.Threads.ThreadType.THREAD_POOL:\n return 5;\n case Trace.Handlers.Threads.ThreadType.AUCTION_WORKLET:\n return 6;\n case Trace.Handlers.Threads.ThreadType.OTHER:\n return 7;\n default:\n return 8;\n }\n };\n const threads = Trace.Handlers.Threads.threadsInTrace(this.#parsedTrace);\n const processedAuctionWorkletsIds = new Set();\n const showAllEvents = Root.Runtime.experiments.isEnabled('timeline-show-all-events');\n\n for (const {pid, tid, name, type} of threads) {\n if (this.#parsedTrace.Meta.traceIsGeneric) {\n // If the trace is generic, we just push all of the threads with no\n // effort to differentiate them, hence overriding the thread type to be\n // OTHER for all threads.\n this.#threadAppenders.push(\n new ThreadAppender(this, this.#parsedTrace, pid, tid, name, Trace.Handlers.Threads.ThreadType.OTHER));\n continue;\n }\n // These threads have no useful information. Omit them\n if ((name === 'Chrome_ChildIOThread' || name === 'Compositor' || name === 'GpuMemoryThread') && !showAllEvents) {\n continue;\n }\n\n const maybeWorklet = this.#parsedTrace.AuctionWorklets.worklets.get(pid);\n if (processedAuctionWorkletsIds.has(pid)) {\n // Keep track of this process to ensure we only add the following\n // tracks once per process and not once per thread.\n continue;\n }\n if (maybeWorklet) {\n processedAuctionWorkletsIds.add(pid);\n // Each AuctionWorklet event represents two threads:\n // 1. the Utility Thread\n // 2. the V8 Helper Thread\n // Note that the names passed here are not used visually. TODO: remove this name?\n this.#threadAppenders.push(new ThreadAppender(\n this, this.#parsedTrace, pid, maybeWorklet.args.data.utilityThread.tid, 'auction-worket-utility',\n Trace.Handlers.Threads.ThreadType.AUCTION_WORKLET));\n this.#threadAppenders.push(new ThreadAppender(\n this, this.#parsedTrace, pid, maybeWorklet.args.data.v8HelperThread.tid, 'auction-worklet-v8helper',\n Trace.Handlers.Threads.ThreadType.AUCTION_WORKLET));\n continue;\n }\n\n this.#threadAppenders.push(new ThreadAppender(this, this.#parsedTrace, pid, tid, name, type));\n }\n // Sort first by track order, then break ties by placing busier tracks first.\n this.#threadAppenders.sort(\n (a, b) => (threadTrackOrder(a) - threadTrackOrder(b)) || (b.getEntries().length - a.getEntries().length));\n this.#allTrackAppenders.push(...this.#threadAppenders);\n }\n\n timingsTrackAppender(): TimingsTrackAppender {\n return this.#timingsTrackAppender;\n }\n\n animationsTrackAppender(): AnimationsTrackAppender {\n return this.#animationsTrackAppender;\n }\n\n interactionsTrackAppender(): InteractionsTrackAppender {\n return this.#interactionsTrackAppender;\n }\n\n gpuTrackAppender(): GPUTrackAppender {\n return this.#gpuTrackAppender;\n }\n\n layoutShiftsTrackAppender(): LayoutShiftsTrackAppender {\n return this.#layoutShiftsTrackAppender;\n }\n\n threadAppenders(): ThreadAppender[] {\n return this.#threadAppenders;\n }\n\n serverTimingsTrackAppender(): ServerTimingsTrackAppender {\n return this.#serverTimingsTrackAppender;\n }\n\n eventsInTrack(trackAppender: TrackAppender): Trace.Types.Events.Event[] {\n const cachedData = this.#eventsForTrack.get(trackAppender);\n if (cachedData) {\n return cachedData;\n }\n\n // Calculate the levels occupied by a track.\n let trackStartLevel = null;\n let trackEndLevel = null;\n for (const [level, track] of this.#trackForLevel) {\n if (track !== trackAppender) {\n continue;\n }\n if (trackStartLevel === null) {\n trackStartLevel = level;\n }\n trackEndLevel = level;\n }\n\n if (trackStartLevel === null || trackEndLevel === null) {\n throw new Error(`Could not find events for track: ${trackAppender}`);\n }\n const entryLevels = this.#flameChartData.entryLevels;\n const events = [];\n for (let i = 0; i < entryLevels.length; i++) {\n if (trackStartLevel <= entryLevels[i] && entryLevels[i] <= trackEndLevel) {\n events.push(this.#entryData[i] as Trace.Types.Events.Event);\n }\n }\n events.sort((a, b) => a.ts - b.ts); // TODO(paulirish): Remove as I'm 90% it's already sorted.\n\n this.#eventsForTrack.set(trackAppender, events);\n return events;\n }\n\n /**\n * Gets the events to be shown in the tree views of the details pane\n * (Bottom-up, Call tree, etc.). These are the events from the track\n * that can be arranged in a tree shape.\n */\n eventsForTreeView(trackAppender: TrackAppender): Trace.Types.Events.Event[] {\n const cachedData = this.#trackEventsForTreeview.get(trackAppender);\n if (cachedData) {\n return cachedData;\n }\n\n let trackEvents = this.eventsInTrack(trackAppender);\n if (!Trace.Helpers.TreeHelpers.canBuildTreesFromEvents(trackEvents)) {\n // Some tracks can include both async and sync events. When this\n // happens, we use all events for the tree views if a trees can be\n // built from both sync and async events. If this is not possible,\n // async events are filtered out and only sync events are used\n // (it's assumed a tree can always be built using a tracks sync\n // events).\n trackEvents = trackEvents.filter(e => !Trace.Types.Events.isPhaseAsync(e.ph));\n }\n this.#trackEventsForTreeview.set(trackAppender, trackEvents);\n return trackEvents;\n }\n\n /**\n * Caches the track appender that owns a flame chart group. FlameChart\n * groups are created for each track in the timeline. When an user\n * selects a track in the UI, the track's group is passed to the model\n * layer to inform about the selection.\n */\n registerTrackForGroup(group: PerfUI.FlameChart.Group, appender: TrackAppender): void {\n this.#flameChartData.groups.push(group);\n this.#trackForGroup.set(group, appender);\n }\n\n /**\n * Returns number of tracks of given type already appended.\n * Used to name the \"Raster Thread 6\" tracks, etc\n */\n getCurrentTrackCountForThreadType(threadType: Trace.Handlers.Threads.ThreadType.RASTERIZER|\n Trace.Handlers.Threads.ThreadType.THREAD_POOL): number {\n return this.#threadAppenders.filter(appender => appender.threadType === threadType && appender.headerAppended())\n .length;\n }\n\n /**\n * Looks up a FlameChart group for a given appender.\n */\n groupForAppender(targetAppender: TrackAppender): PerfUI.FlameChart.Group|null {\n let foundGroup: PerfUI.FlameChart.Group|null = null;\n for (const [group, appender] of this.#trackForGroup) {\n if (appender === targetAppender) {\n foundGroup = group;\n break;\n }\n }\n return foundGroup;\n }\n\n /**\n * Given a FlameChart group, gets the events to be shown in the tree\n * views if that group was registered by the appender system.\n */\n groupEventsForTreeView(group: PerfUI.FlameChart.Group): Trace.Types.Events.Event[]|null {\n const track = this.#trackForGroup.get(group);\n if (!track) {\n return null;\n }\n return this.eventsForTreeView(track);\n }\n\n /**\n * Caches the track appender that owns a level. An appender takes\n * ownership of a level when it appends data to it.\n * The cache is useful to determine what appender should handle a\n * query from the flame chart renderer when an event's feature (like\n * style, title, etc.) is needed.\n */\n registerTrackForLevel(level: number, appender: TrackAppender): void {\n // TODO(crbug.com/1442454) Figure out how to avoid the circular calls.\n this.#trackForLevel.set(level, appender);\n }\n\n groupForLevel(level: number): PerfUI.FlameChart.Group|null {\n const appenderForLevel = this.#trackForLevel.get(level);\n if (!appenderForLevel) {\n return null;\n }\n return this.groupForAppender(appenderForLevel);\n }\n\n /**\n * Adds an event to the flame chart data at a defined level.\n * @param event the event to be appended,\n * @param level the level to append the event,\n * @param appender the track which the event belongs to.\n * @returns the index of the event in all events to be rendered in the flamechart.\n */\n appendEventAtLevel(event: Trace.Types.Events.Event, level: number, appender: TrackAppender): number {\n // TODO(crbug.com/1442454) Figure out how to avoid the circular calls.\n this.#trackForLevel.set(level, appender);\n const index = this.#entryData.length;\n this.#entryData.push(event);\n this.#legacyEntryTypeByLevel[level] = EntryType.TRACK_APPENDER;\n this.#flameChartData.entryLevels[index] = level;\n this.#flameChartData.entryStartTimes[index] = Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts);\n const dur = event.dur || Trace.Helpers.Timing.millisecondsToMicroseconds(InstantEventVisibleDurationMs);\n this.#flameChartData.entryTotalTimes[index] = Trace.Helpers.Timing.microSecondsToMilliseconds(dur);\n return index;\n }\n\n /**\n * Adds into the flame chart data a list of trace events.\n * @param events the trace events that will be appended to the flame chart.\n * The events should be taken straight from the trace handlers. The handlers\n * should sort the events by start time, and the parent event is before the\n * child.\n * @param trackStartLevel the flame chart level from which the events will\n * be appended.\n * @param appender the track that the trace events belong to.\n * @param eventAppendedCallback an optional function called after the\n * event has been added to the timeline data. This allows the caller\n * to know f.e. the position of the event in the entry data. Use this\n * hook to customize the data after it has been appended, f.e. to add\n * decorations to a set of the entries.\n * @returns the next level after the last occupied by the appended these\n * trace events (the first available level to append next track).\n */\n appendEventsAtLevel(\n events: readonly T[], trackStartLevel: number, appender: TrackAppender,\n eventAppendedCallback?: (event: T, index: number) => void): number {\n const lastTimestampByLevel: LastTimestampByLevel = [];\n for (let i = 0; i < events.length; ++i) {\n const event = events[i];\n if (!entryIsVisibleInTimeline(event, this.#parsedTrace)) {\n continue;\n }\n\n const level = getEventLevel(event, lastTimestampByLevel);\n const index = this.appendEventAtLevel(event, trackStartLevel + level, appender);\n eventAppendedCallback?.(event, index);\n }\n\n this.#legacyEntryTypeByLevel.length = trackStartLevel + lastTimestampByLevel.length;\n this.#legacyEntryTypeByLevel.fill(EntryType.TRACK_APPENDER, trackStartLevel);\n return trackStartLevel + lastTimestampByLevel.length;\n }\n\n /**\n * Gets the all track appenders that have been set to be visible.\n */\n allVisibleTrackAppenders(): TrackAppender[] {\n return this.#allTrackAppenders.filter(track => this.#visibleTrackNames.has(track.appenderName));\n }\n\n allThreadAppendersByProcess(): Map {\n const appenders = this.allVisibleTrackAppenders();\n const result = new Map();\n for (const appender of appenders) {\n if (!(appender instanceof ThreadAppender)) {\n continue;\n }\n const existing = result.get(appender.processId()) ?? [];\n existing.push(appender);\n result.set(appender.processId(), existing);\n }\n return result;\n }\n\n /**\n * Sets the visible tracks internally\n * @param visibleTracks set with the names of the visible track\n * appenders. If undefined, all tracks are set to be visible.\n */\n setVisibleTracks(visibleTracks?: Set): void {\n if (!visibleTracks) {\n this.#visibleTrackNames = new Set([...TrackNames]);\n return;\n }\n this.#visibleTrackNames = visibleTracks;\n }\n\n getDrawOverride(event: Trace.Types.Events.Event, level: number): DrawOverride|undefined {\n const track = this.#trackForLevel.get(level);\n if (!track) {\n throw new Error('Track not found for level');\n }\n return track.getDrawOverride?.(event);\n }\n\n /**\n * Returns the color an event is shown with in the timeline.\n */\n colorForEvent(event: Trace.Types.Events.Event, level: number): string {\n const track = this.#trackForLevel.get(level);\n if (!track) {\n throw new Error('Track not found for level');\n }\n return track.colorForEvent(event);\n }\n /**\n * Returns the title an event is shown with in the timeline.\n */\n titleForEvent(event: Trace.Types.Events.Event, level: number): string {\n const track = this.#trackForLevel.get(level);\n if (!track) {\n throw new Error('Track not found for level');\n }\n\n // Historically all tracks would have a titleForEvent() method.\n // However, we are working on migrating all event title logic into one place (components/EntryName)\n // TODO(crbug.com/365047728):\n // Once this migration is complete, no tracks will have a custom\n // titleForEvent method and we can remove titleForEvent entirely.\n if (track.titleForEvent) {\n return track.titleForEvent(event);\n }\n return TimelineComponents.EntryName.nameForEntry(event, this.#parsedTrace);\n }\n /**\n * Returns the info shown when an event in the timeline is hovered.\n */\n highlightedEntryInfo(event: Trace.Types.Events.Event, level: number): HighlightedEntryInfo {\n const track = this.#trackForLevel.get(level);\n if (!track) {\n throw new Error('Track not found for level');\n }\n\n // Add any warnings information to the tooltip. Done here to avoid duplicating this call in every appender.\n // By doing this here, we ensure that any warnings that are\n // added to the WarningsHandler are automatically used and added\n // to the tooltip.\n const warningElements: HTMLSpanElement[] =\n TimelineComponents.DetailsView.buildWarningElementsForEvent(event, this.#parsedTrace);\n\n let title = this.titleForEvent(event, level);\n let formattedTime = getFormattedTime(event.dur);\n\n // If the track defines a custom highlight, call it and use its values.\n if (track.highlightedEntryInfo) {\n const {title: customTitle, formattedTime: customFormattedTime, warningElements: extraWarningElements} =\n track.highlightedEntryInfo(event);\n if (customTitle) {\n title = customTitle;\n }\n if (customFormattedTime) {\n formattedTime = customFormattedTime;\n }\n if (extraWarningElements) {\n warningElements.push(...extraWarningElements);\n }\n }\n return {\n title,\n formattedTime,\n warningElements,\n };\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/CountersGraph.d.ts b/public/panels/timeline/CountersGraph.d.ts index b55ecb598..626976a63 100644 --- a/public/panels/timeline/CountersGraph.d.ts +++ b/public/panels/timeline/CountersGraph.d.ts @@ -1,4 +1,4 @@ -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; import * as UI from '../../ui/legacy/legacy.js'; import { type TimelineModeViewDelegate } from './TimelinePanel.js'; @@ -19,7 +19,7 @@ export declare class CountersGraph extends UI.Widget.VBox { currentValuesBar?: HTMLElement; private markerXPosition?; constructor(delegate: TimelineModeViewDelegate); - setModel(traceEngineData: TraceEngine.Handlers.Types.TraceParseData | null, events: TraceEngine.Types.TraceEvents.TraceEventData[] | null): void; + setModel(parsedTrace: Trace.Handlers.Types.ParsedTrace | null, events: Trace.Types.Events.Event[] | null): void; private createCurrentValuesBar; private createCounter; resizerElement(): Element | null; diff --git a/public/panels/timeline/CountersGraph.js b/public/panels/timeline/CountersGraph.js index d02a19c24..f1dad80e8 100644 --- a/public/panels/timeline/CountersGraph.js +++ b/public/panels/timeline/CountersGraph.js @@ -30,7 +30,7 @@ import * as Common from '../../core/common/common.js'; import * as i18n from '../../core/i18n/i18n.js'; import * as Platform from '../../core/platform/platform.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as TraceBounds from '../../services/trace_bounds/trace_bounds.js'; import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; import * as UI from '../../ui/legacy/legacy.js'; @@ -139,12 +139,12 @@ export class CountersGraph extends UI.Widget.VBox { this.#scheduleRefresh(); } } - setModel(traceEngineData, events) { + setModel(parsedTrace, events) { this.#events = events; - if (!events || !traceEngineData) { + if (!events || !parsedTrace) { return; } - const minTime = TraceEngine.Helpers.Timing.traceWindowMilliSeconds(traceEngineData.Meta.traceBounds).min; + const minTime = Trace.Helpers.Timing.traceWindowMilliSeconds(parsedTrace.Meta.traceBounds).min; this.calculator.setZeroTime(minTime); for (let i = 0; i < this.counters.length; ++i) { this.counters[i].reset(); @@ -154,7 +154,7 @@ export class CountersGraph extends UI.Widget.VBox { let counterEventsFound = 0; for (let i = 0; i < events.length; ++i) { const event = events[i]; - if (!TraceEngine.Types.TraceEvents.isTraceEventUpdateCounters(event)) { + if (!Trace.Types.Events.isUpdateCounters(event)) { continue; } counterEventsFound++; @@ -165,7 +165,7 @@ export class CountersGraph extends UI.Widget.VBox { for (const name in counters) { const counter = this.countersByName.get(name); if (counter) { - const { startTime } = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event); + const { startTime } = Trace.Helpers.Timing.eventTimingsMilliSeconds(event); counter.appendSample(startTime, counters[name]); } } diff --git a/public/panels/timeline/CountersGraph.js.map b/public/panels/timeline/CountersGraph.js.map index 70eca677f..8408b826c 100644 --- a/public/panels/timeline/CountersGraph.js.map +++ b/public/panels/timeline/CountersGraph.js.map @@ -1 +1 @@ -{"version":3,"file":"CountersGraph.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/CountersGraph.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (C) 2012 Google Inc. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * * Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above\n * copyright notice, this list of conditions and the following disclaimer\n * in the documentation and/or other materials provided with the\n * distribution.\n * * Neither the name of Google Inc. nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as TraceBounds from '../../services/trace_bounds/trace_bounds.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport {type TimelineModeViewDelegate} from './TimelinePanel.js';\n\nconst UIStrings = {\n /**\n *@description Text for a heap profile type\n */\n jsHeap: 'JS heap',\n /**\n *@description Text for documents, a type of resources\n */\n documents: 'Documents',\n /**\n *@description Text in Counters Graph of the Performance panel\n */\n nodes: 'Nodes',\n /**\n *@description Text in Counters Graph of the Performance panel\n */\n listeners: 'Listeners',\n /**\n *@description Text in Counters Graph of the Performance panel\n */\n gpuMemory: 'GPU memory',\n /**\n *@description Range text content in Counters Graph of the Performance panel\n *@example {2} PH1\n *@example {10} PH2\n */\n ss: '[{PH1} – {PH2}]',\n /**\n * @description text shown when no counter events are found and the graph is empty\n */\n noEventsFound: 'No memory usage data found within selected events.',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/CountersGraph.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport class CountersGraph extends UI.Widget.VBox {\n private readonly delegate: TimelineModeViewDelegate;\n private readonly calculator: Calculator;\n private readonly header: UI.Widget.HBox;\n readonly toolbar: UI.Toolbar.Toolbar;\n private graphsContainer: UI.Widget.VBox;\n canvasContainer: typeof UI.Widget.Widget.prototype.element;\n private canvas: HTMLCanvasElement;\n private readonly timelineGrid: PerfUI.TimelineGrid.TimelineGrid;\n private readonly counters: Counter[];\n private readonly counterUI: CounterUI[];\n private readonly countersByName: Map;\n private readonly gpuMemoryCounter: Counter;\n #events: TraceEngine.Types.TraceEvents.TraceEventData[]|null = null;\n currentValuesBar?: HTMLElement;\n private markerXPosition?: number;\n #onTraceBoundsChangeBound = this.#onTraceBoundsChange.bind(this);\n\n #noEventsFoundMessage = document.createElement('div');\n #showNoEventsMessage: boolean = false;\n\n constructor(delegate: TimelineModeViewDelegate) {\n super();\n this.element.id = 'memory-graphs-container';\n\n this.delegate = delegate;\n this.calculator = new Calculator();\n\n // Create selectors\n this.header = new UI.Widget.HBox();\n this.header.element.classList.add('timeline-memory-header');\n this.header.show(this.element);\n this.toolbar = new UI.Toolbar.Toolbar('timeline-memory-toolbar');\n this.header.element.appendChild(this.toolbar.element);\n\n this.graphsContainer = new UI.Widget.VBox();\n this.graphsContainer.show(this.element);\n const canvasWidget = new UI.Widget.VBoxWithResizeCallback(this.resize.bind(this));\n canvasWidget.show(this.graphsContainer.element);\n this.createCurrentValuesBar();\n this.canvasContainer = canvasWidget.element;\n this.canvasContainer.id = 'memory-graphs-canvas-container';\n this.canvas = document.createElement('canvas');\n this.canvasContainer.appendChild(this.canvas);\n this.canvas.id = 'memory-counters-graph';\n\n const noEventsFound = document.createElement('p');\n noEventsFound.innerText = i18nString(UIStrings.noEventsFound);\n this.#noEventsFoundMessage.classList.add('no-events-found');\n this.#noEventsFoundMessage.setAttribute('hidden', 'hidden');\n this.#noEventsFoundMessage.appendChild(noEventsFound);\n this.canvasContainer.appendChild(this.#noEventsFoundMessage);\n\n this.canvasContainer.addEventListener('mouseover', this.onMouseMove.bind(this), true);\n this.canvasContainer.addEventListener('mousemove', this.onMouseMove.bind(this), true);\n this.canvasContainer.addEventListener('mouseleave', this.onMouseLeave.bind(this), true);\n this.canvasContainer.addEventListener('click', this.onClick.bind(this), true);\n // We create extra timeline grid here to reuse its event dividers.\n this.timelineGrid = new PerfUI.TimelineGrid.TimelineGrid();\n this.canvasContainer.appendChild(this.timelineGrid.dividersElement);\n\n this.counters = [];\n this.counterUI = [];\n\n this.countersByName = new Map();\n this.countersByName.set(\n 'jsHeapSizeUsed',\n this.createCounter(\n i18nString(UIStrings.jsHeap), 'js-heap-size-used', 'hsl(220, 90%, 43%)',\n Platform.NumberUtilities.bytesToString));\n this.countersByName.set(\n 'documents', this.createCounter(i18nString(UIStrings.documents), 'documents', 'hsl(0, 90%, 43%)'));\n this.countersByName.set('nodes', this.createCounter(i18nString(UIStrings.nodes), 'nodes', 'hsl(120, 90%, 43%)'));\n this.countersByName.set(\n 'jsEventListeners',\n this.createCounter(i18nString(UIStrings.listeners), 'js-event-listeners', 'hsl(38, 90%, 43%)'));\n\n this.gpuMemoryCounter = this.createCounter(\n i18nString(UIStrings.gpuMemory), 'gpu-memory-used-kb', 'hsl(300, 90%, 43%)',\n Platform.NumberUtilities.bytesToString);\n this.countersByName.set('gpuMemoryUsedKB', this.gpuMemoryCounter);\n\n TraceBounds.TraceBounds.onChange(this.#onTraceBoundsChangeBound);\n }\n\n #onTraceBoundsChange(event: TraceBounds.TraceBounds.StateChangedEvent): void {\n if (event.updateType === 'RESET' || event.updateType === 'VISIBLE_WINDOW') {\n const newWindow = event.state.milli.timelineTraceWindow;\n this.calculator.setWindow(newWindow.min, newWindow.max);\n this.#scheduleRefresh();\n }\n }\n\n setModel(\n traceEngineData: TraceEngine.Handlers.Types.TraceParseData|null,\n events: TraceEngine.Types.TraceEvents.TraceEventData[]|null): void {\n this.#events = events;\n if (!events || !traceEngineData) {\n return;\n }\n const minTime = TraceEngine.Helpers.Timing.traceWindowMilliSeconds(traceEngineData.Meta.traceBounds).min;\n this.calculator.setZeroTime(minTime);\n\n for (let i = 0; i < this.counters.length; ++i) {\n this.counters[i].reset();\n this.counterUI[i].reset();\n }\n this.#scheduleRefresh();\n let counterEventsFound = 0;\n for (let i = 0; i < events.length; ++i) {\n const event = events[i];\n if (!TraceEngine.Types.TraceEvents.isTraceEventUpdateCounters(event)) {\n continue;\n }\n counterEventsFound++;\n\n const counters = event.args.data;\n if (!counters) {\n return;\n }\n for (const name in counters) {\n const counter = this.countersByName.get(name);\n if (counter) {\n const {startTime} = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event);\n counter.appendSample(\n startTime, counters[name as 'documents' | 'jsEventListeners' | 'jsHeapSizeUsed' | 'nodes']);\n }\n }\n\n if (typeof counters.gpuMemoryLimitKB !== 'undefined') {\n this.gpuMemoryCounter.setLimit(counters.gpuMemoryLimitKB);\n }\n }\n this.#showNoEventsMessage = counterEventsFound === 0;\n }\n\n private createCurrentValuesBar(): void {\n this.currentValuesBar = this.graphsContainer.element.createChild('div');\n this.currentValuesBar.id = 'counter-values-bar';\n }\n\n private createCounter(uiName: string, settingsKey: string, color: string, formatter?: ((arg0: number) => string)):\n Counter {\n const counter = new Counter();\n this.counters.push(counter);\n this.counterUI.push(new CounterUI(this, uiName, settingsKey, color, counter, formatter));\n return counter;\n }\n\n resizerElement(): Element|null {\n return this.header.element;\n }\n\n private resize(): void {\n const parentElement = (this.canvas.parentElement as HTMLElement);\n this.canvas.width = parentElement.clientWidth * window.devicePixelRatio;\n this.canvas.height = parentElement.clientHeight * window.devicePixelRatio;\n this.calculator.setDisplayWidth(this.canvas.width);\n this.refresh();\n }\n\n #scheduleRefresh(): void {\n UI.UIUtils.invokeOnceAfterBatchUpdate(this, this.refresh);\n }\n\n draw(): void {\n this.clear();\n if (this.#showNoEventsMessage) {\n this.#noEventsFoundMessage.removeAttribute('hidden');\n } else {\n this.#noEventsFoundMessage.setAttribute('hidden', 'hidden');\n }\n for (const counter of this.counters) {\n counter.calculateVisibleIndexes(this.calculator);\n counter.calculateXValues(this.canvas.width);\n }\n for (const counterUI of this.counterUI) {\n counterUI.drawGraph(this.canvas);\n }\n }\n\n private onClick(event: Event): void {\n const x = (event as MouseEvent).x - this.canvasContainer.getBoundingClientRect().left;\n let minDistance: number = Infinity;\n let bestTime;\n for (const counterUI of this.counterUI) {\n if (!counterUI.counter.times.length) {\n continue;\n }\n const index = counterUI.recordIndexAt(x);\n const distance = Math.abs(x * window.devicePixelRatio - counterUI.counter.x[index]);\n if (distance < minDistance) {\n minDistance = distance;\n bestTime = counterUI.counter.times[index];\n }\n }\n if (bestTime !== undefined && this.#events) {\n this.delegate.selectEntryAtTime(this.#events, bestTime);\n }\n }\n\n private onMouseLeave(_event: Event): void {\n delete this.markerXPosition;\n this.clearCurrentValueAndMarker();\n }\n\n private clearCurrentValueAndMarker(): void {\n for (let i = 0; i < this.counterUI.length; i++) {\n this.counterUI[i].clearCurrentValueAndMarker();\n }\n }\n\n private onMouseMove(event: Event): void {\n const x = (event as MouseEvent).x - this.canvasContainer.getBoundingClientRect().left;\n this.markerXPosition = x;\n this.refreshCurrentValues();\n }\n\n private refreshCurrentValues(): void {\n if (this.markerXPosition === undefined) {\n return;\n }\n for (let i = 0; i < this.counterUI.length; ++i) {\n this.counterUI[i].updateCurrentValue(this.markerXPosition);\n }\n }\n\n refresh(): void {\n this.timelineGrid.updateDividers(this.calculator);\n this.draw();\n this.refreshCurrentValues();\n }\n\n private clear(): void {\n const ctx = this.canvas.getContext('2d');\n if (!ctx) {\n throw new Error('Unable to get canvas context');\n }\n ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);\n }\n}\n\nexport class Counter {\n times: number[];\n values: number[];\n x: number[];\n minimumIndex: number;\n maximumIndex: number;\n private maxTime: number;\n private minTime: number;\n limitValue?: number;\n\n constructor() {\n this.times = [];\n this.values = [];\n this.x = [];\n this.minimumIndex = 0;\n this.maximumIndex = 0;\n this.maxTime = 0;\n this.minTime = 0;\n }\n\n appendSample(time: number, value: number): void {\n if (this.values.length && this.values[this.values.length - 1] === value) {\n return;\n }\n this.times.push(time);\n this.values.push(value);\n }\n\n reset(): void {\n this.times = [];\n this.values = [];\n }\n\n setLimit(value: number): void {\n this.limitValue = value;\n }\n\n calculateBounds(): {\n min: number,\n max: number,\n } {\n let maxValue;\n let minValue;\n for (let i = this.minimumIndex; i <= this.maximumIndex; i++) {\n const value = this.values[i];\n if (minValue === undefined || value < minValue) {\n minValue = value;\n }\n if (maxValue === undefined || value > maxValue) {\n maxValue = value;\n }\n }\n minValue = minValue || 0;\n maxValue = maxValue || 1;\n if (this.limitValue) {\n if (maxValue > this.limitValue * 0.5) {\n maxValue = Math.max(maxValue, this.limitValue);\n }\n minValue = Math.min(minValue, this.limitValue);\n }\n return {min: minValue, max: maxValue};\n }\n\n calculateVisibleIndexes(calculator: Calculator): void {\n const start = calculator.minimumBoundary();\n const end = calculator.maximumBoundary();\n\n // Maximum index of element whose time <= start.\n this.minimumIndex = Platform.NumberUtilities.clamp(\n Platform.ArrayUtilities.upperBound(this.times, start, Platform.ArrayUtilities.DEFAULT_COMPARATOR) - 1, 0,\n this.times.length - 1);\n\n // Minimum index of element whose time >= end.\n this.maximumIndex = Platform.NumberUtilities.clamp(\n Platform.ArrayUtilities.lowerBound(this.times, end, Platform.ArrayUtilities.DEFAULT_COMPARATOR), 0,\n this.times.length - 1);\n\n // Current window bounds.\n this.minTime = start;\n this.maxTime = end;\n }\n\n calculateXValues(width: number): void {\n if (!this.values.length) {\n return;\n }\n\n const xFactor = width / (this.maxTime - this.minTime);\n\n this.x = new Array(this.values.length);\n for (let i = this.minimumIndex + 1; i <= this.maximumIndex; i++) {\n this.x[i] = xFactor * (this.times[i] - this.minTime);\n }\n }\n}\n\nexport class CounterUI {\n private readonly countersPane: CountersGraph;\n counter: Counter;\n private readonly formatter: (arg0: number) => string;\n private readonly setting: Common.Settings.Setting;\n private filter: UI.Toolbar.ToolbarSettingCheckbox;\n private range: HTMLElement;\n private value: HTMLElement;\n graphColor: string;\n limitColor: string|null|undefined;\n graphYValues: number[];\n private readonly verticalPadding: number;\n private currentValueLabel: string;\n private marker: HTMLElement;\n\n constructor(\n countersPane: CountersGraph, title: string, settingsKey: string, graphColor: string, counter: Counter,\n formatter?: (arg0: number) => string) {\n this.countersPane = countersPane;\n this.counter = counter;\n this.formatter = formatter || Platform.NumberUtilities.withThousandsSeparator;\n\n this.setting = Common.Settings.Settings.instance().createSetting('timeline-counters-graph-' + settingsKey, true);\n this.setting.setTitle(title);\n this.filter = new UI.Toolbar.ToolbarSettingCheckbox(this.setting, title);\n this.filter.inputElement.classList.add('-theme-preserve-input');\n const parsedColor = Common.Color.parse(graphColor);\n if (parsedColor) {\n const colorWithAlpha = parsedColor.setAlpha(0.5).asString(Common.Color.Format.RGBA);\n const htmlElement = (this.filter.element as HTMLElement);\n if (colorWithAlpha) {\n htmlElement.style.backgroundColor = colorWithAlpha;\n }\n htmlElement.style.borderColor = 'transparent';\n }\n this.filter.inputElement.addEventListener('click', this.toggleCounterGraph.bind(this));\n countersPane.toolbar.appendToolbarItem(this.filter);\n this.range = this.filter.element.createChild('span', 'range');\n\n this.value = (countersPane.currentValuesBar as HTMLElement).createChild('span', 'memory-counter-value');\n this.value.style.color = graphColor;\n this.graphColor = graphColor;\n if (parsedColor) {\n this.limitColor = parsedColor.setAlpha(0.3).asString(Common.Color.Format.RGBA);\n }\n this.graphYValues = [];\n this.verticalPadding = 10;\n\n this.currentValueLabel = title;\n this.marker = countersPane.canvasContainer.createChild('div', 'memory-counter-marker');\n this.marker.style.backgroundColor = graphColor;\n this.clearCurrentValueAndMarker();\n }\n\n reset(): void {\n this.range.textContent = '';\n }\n\n setRange(minValue: number, maxValue: number): void {\n const min = this.formatter(minValue);\n const max = this.formatter(maxValue);\n this.range.textContent = i18nString(UIStrings.ss, {PH1: min, PH2: max});\n }\n\n private toggleCounterGraph(): void {\n this.value.classList.toggle('hidden', !this.filter.checked());\n this.countersPane.refresh();\n }\n\n recordIndexAt(x: number): number {\n return Platform.ArrayUtilities.upperBound(\n this.counter.x, x * window.devicePixelRatio, Platform.ArrayUtilities.DEFAULT_COMPARATOR,\n this.counter.minimumIndex + 1, this.counter.maximumIndex + 1) -\n 1;\n }\n\n updateCurrentValue(x: number): void {\n if (!this.visible() || !this.counter.values.length || !this.counter.x) {\n return;\n }\n const index = this.recordIndexAt(x);\n const value = Platform.NumberUtilities.withThousandsSeparator(this.counter.values[index]);\n this.value.textContent = `${this.currentValueLabel}: ${value}`;\n const y = this.graphYValues[index] / window.devicePixelRatio;\n this.marker.style.left = x + 'px';\n this.marker.style.top = y + 'px';\n this.marker.classList.remove('hidden');\n }\n\n clearCurrentValueAndMarker(): void {\n this.value.textContent = '';\n this.marker.classList.add('hidden');\n }\n\n drawGraph(canvas: HTMLCanvasElement): void {\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n throw new Error('Unable to get canvas context');\n }\n const width = canvas.width;\n const height = canvas.height - 2 * this.verticalPadding;\n if (height <= 0) {\n this.graphYValues = [];\n return;\n }\n const originY = this.verticalPadding;\n const counter = this.counter;\n const values = counter.values;\n\n if (!values.length) {\n return;\n }\n\n const bounds = counter.calculateBounds();\n const minValue = bounds.min;\n const maxValue = bounds.max;\n this.setRange(minValue, maxValue);\n\n if (!this.visible()) {\n return;\n }\n\n const yValues = this.graphYValues;\n const maxYRange = maxValue - minValue;\n const yFactor = maxYRange ? height / (maxYRange) : 1;\n\n ctx.save();\n ctx.lineWidth = window.devicePixelRatio;\n if (ctx.lineWidth % 2) {\n ctx.translate(0.5, 0.5);\n }\n ctx.beginPath();\n let value: number = values[counter.minimumIndex];\n let currentY = Math.round(originY + height - (value - minValue) * yFactor);\n ctx.moveTo(0, currentY);\n let i = counter.minimumIndex;\n for (; i <= counter.maximumIndex; i++) {\n const x = Math.round(counter.x[i]);\n ctx.lineTo(x, currentY);\n const currentValue = values[i];\n if (typeof currentValue !== 'undefined') {\n value = currentValue;\n }\n currentY = Math.round(originY + height - (value - minValue) * yFactor);\n ctx.lineTo(x, currentY);\n yValues[i] = currentY;\n }\n yValues.length = i;\n ctx.lineTo(width, currentY);\n ctx.strokeStyle = this.graphColor;\n ctx.stroke();\n if (counter.limitValue) {\n const limitLineY = Math.round(originY + height - (counter.limitValue - minValue) * yFactor);\n ctx.moveTo(0, limitLineY);\n ctx.lineTo(width, limitLineY);\n if (this.limitColor) {\n ctx.strokeStyle = this.limitColor;\n }\n ctx.stroke();\n }\n ctx.closePath();\n ctx.restore();\n }\n\n visible(): boolean {\n return this.filter.checked();\n }\n}\n\nexport class Calculator implements PerfUI.TimelineGrid.Calculator {\n private minimumBoundaryInternal: number;\n private maximumBoundaryInternal: number;\n private workingArea: number;\n private zeroTimeInternal: number;\n\n constructor() {\n this.minimumBoundaryInternal = 0;\n this.maximumBoundaryInternal = 0;\n this.workingArea = 0;\n this.zeroTimeInternal = 0;\n }\n setZeroTime(time: number): void {\n this.zeroTimeInternal = time;\n }\n\n computePosition(time: number): number {\n return (time - this.minimumBoundaryInternal) / this.boundarySpan() * this.workingArea;\n }\n\n setWindow(minimumBoundary: number, maximumBoundary: number): void {\n this.minimumBoundaryInternal = minimumBoundary;\n this.maximumBoundaryInternal = maximumBoundary;\n }\n\n setDisplayWidth(clientWidth: number): void {\n this.workingArea = clientWidth;\n }\n\n formatValue(value: number, precision?: number): string {\n return i18n.TimeUtilities.preciseMillisToString(value - this.zeroTime(), precision);\n }\n\n maximumBoundary(): number {\n return this.maximumBoundaryInternal;\n }\n\n minimumBoundary(): number {\n return this.minimumBoundaryInternal;\n }\n\n zeroTime(): number {\n return this.zeroTimeInternal;\n }\n\n boundarySpan(): number {\n return this.maximumBoundaryInternal - this.minimumBoundaryInternal;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"CountersGraph.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/CountersGraph.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (C) 2012 Google Inc. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * * Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above\n * copyright notice, this list of conditions and the following disclaimer\n * in the documentation and/or other materials provided with the\n * distribution.\n * * Neither the name of Google Inc. nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as TraceBounds from '../../services/trace_bounds/trace_bounds.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport {type TimelineModeViewDelegate} from './TimelinePanel.js';\n\nconst UIStrings = {\n /**\n *@description Text for a heap profile type\n */\n jsHeap: 'JS heap',\n /**\n *@description Text for documents, a type of resources\n */\n documents: 'Documents',\n /**\n *@description Text in Counters Graph of the Performance panel\n */\n nodes: 'Nodes',\n /**\n *@description Text in Counters Graph of the Performance panel\n */\n listeners: 'Listeners',\n /**\n *@description Text in Counters Graph of the Performance panel\n */\n gpuMemory: 'GPU memory',\n /**\n *@description Range text content in Counters Graph of the Performance panel\n *@example {2} PH1\n *@example {10} PH2\n */\n ss: '[{PH1} – {PH2}]',\n /**\n * @description text shown when no counter events are found and the graph is empty\n */\n noEventsFound: 'No memory usage data found within selected events.',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/CountersGraph.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport class CountersGraph extends UI.Widget.VBox {\n private readonly delegate: TimelineModeViewDelegate;\n private readonly calculator: Calculator;\n private readonly header: UI.Widget.HBox;\n readonly toolbar: UI.Toolbar.Toolbar;\n private graphsContainer: UI.Widget.VBox;\n canvasContainer: typeof UI.Widget.Widget.prototype.element;\n private canvas: HTMLCanvasElement;\n private readonly timelineGrid: PerfUI.TimelineGrid.TimelineGrid;\n private readonly counters: Counter[];\n private readonly counterUI: CounterUI[];\n private readonly countersByName: Map;\n private readonly gpuMemoryCounter: Counter;\n #events: Trace.Types.Events.Event[]|null = null;\n currentValuesBar?: HTMLElement;\n private markerXPosition?: number;\n #onTraceBoundsChangeBound = this.#onTraceBoundsChange.bind(this);\n\n #noEventsFoundMessage = document.createElement('div');\n #showNoEventsMessage: boolean = false;\n\n constructor(delegate: TimelineModeViewDelegate) {\n super();\n this.element.id = 'memory-graphs-container';\n\n this.delegate = delegate;\n this.calculator = new Calculator();\n\n // Create selectors\n this.header = new UI.Widget.HBox();\n this.header.element.classList.add('timeline-memory-header');\n this.header.show(this.element);\n this.toolbar = new UI.Toolbar.Toolbar('timeline-memory-toolbar');\n this.header.element.appendChild(this.toolbar.element);\n\n this.graphsContainer = new UI.Widget.VBox();\n this.graphsContainer.show(this.element);\n const canvasWidget = new UI.Widget.VBoxWithResizeCallback(this.resize.bind(this));\n canvasWidget.show(this.graphsContainer.element);\n this.createCurrentValuesBar();\n this.canvasContainer = canvasWidget.element;\n this.canvasContainer.id = 'memory-graphs-canvas-container';\n this.canvas = document.createElement('canvas');\n this.canvasContainer.appendChild(this.canvas);\n this.canvas.id = 'memory-counters-graph';\n\n const noEventsFound = document.createElement('p');\n noEventsFound.innerText = i18nString(UIStrings.noEventsFound);\n this.#noEventsFoundMessage.classList.add('no-events-found');\n this.#noEventsFoundMessage.setAttribute('hidden', 'hidden');\n this.#noEventsFoundMessage.appendChild(noEventsFound);\n this.canvasContainer.appendChild(this.#noEventsFoundMessage);\n\n this.canvasContainer.addEventListener('mouseover', this.onMouseMove.bind(this), true);\n this.canvasContainer.addEventListener('mousemove', this.onMouseMove.bind(this), true);\n this.canvasContainer.addEventListener('mouseleave', this.onMouseLeave.bind(this), true);\n this.canvasContainer.addEventListener('click', this.onClick.bind(this), true);\n // We create extra timeline grid here to reuse its event dividers.\n this.timelineGrid = new PerfUI.TimelineGrid.TimelineGrid();\n this.canvasContainer.appendChild(this.timelineGrid.dividersElement);\n\n this.counters = [];\n this.counterUI = [];\n\n this.countersByName = new Map();\n this.countersByName.set(\n 'jsHeapSizeUsed',\n this.createCounter(\n i18nString(UIStrings.jsHeap), 'js-heap-size-used', 'hsl(220, 90%, 43%)',\n Platform.NumberUtilities.bytesToString));\n this.countersByName.set(\n 'documents', this.createCounter(i18nString(UIStrings.documents), 'documents', 'hsl(0, 90%, 43%)'));\n this.countersByName.set('nodes', this.createCounter(i18nString(UIStrings.nodes), 'nodes', 'hsl(120, 90%, 43%)'));\n this.countersByName.set(\n 'jsEventListeners',\n this.createCounter(i18nString(UIStrings.listeners), 'js-event-listeners', 'hsl(38, 90%, 43%)'));\n\n this.gpuMemoryCounter = this.createCounter(\n i18nString(UIStrings.gpuMemory), 'gpu-memory-used-kb', 'hsl(300, 90%, 43%)',\n Platform.NumberUtilities.bytesToString);\n this.countersByName.set('gpuMemoryUsedKB', this.gpuMemoryCounter);\n\n TraceBounds.TraceBounds.onChange(this.#onTraceBoundsChangeBound);\n }\n\n #onTraceBoundsChange(event: TraceBounds.TraceBounds.StateChangedEvent): void {\n if (event.updateType === 'RESET' || event.updateType === 'VISIBLE_WINDOW') {\n const newWindow = event.state.milli.timelineTraceWindow;\n this.calculator.setWindow(newWindow.min, newWindow.max);\n this.#scheduleRefresh();\n }\n }\n\n setModel(parsedTrace: Trace.Handlers.Types.ParsedTrace|null, events: Trace.Types.Events.Event[]|null): void {\n this.#events = events;\n if (!events || !parsedTrace) {\n return;\n }\n const minTime = Trace.Helpers.Timing.traceWindowMilliSeconds(parsedTrace.Meta.traceBounds).min;\n this.calculator.setZeroTime(minTime);\n\n for (let i = 0; i < this.counters.length; ++i) {\n this.counters[i].reset();\n this.counterUI[i].reset();\n }\n this.#scheduleRefresh();\n let counterEventsFound = 0;\n for (let i = 0; i < events.length; ++i) {\n const event = events[i];\n if (!Trace.Types.Events.isUpdateCounters(event)) {\n continue;\n }\n counterEventsFound++;\n\n const counters = event.args.data;\n if (!counters) {\n return;\n }\n for (const name in counters) {\n const counter = this.countersByName.get(name);\n if (counter) {\n const {startTime} = Trace.Helpers.Timing.eventTimingsMilliSeconds(event);\n counter.appendSample(\n startTime, counters[name as 'documents' | 'jsEventListeners' | 'jsHeapSizeUsed' | 'nodes']);\n }\n }\n\n if (typeof counters.gpuMemoryLimitKB !== 'undefined') {\n this.gpuMemoryCounter.setLimit(counters.gpuMemoryLimitKB);\n }\n }\n this.#showNoEventsMessage = counterEventsFound === 0;\n }\n\n private createCurrentValuesBar(): void {\n this.currentValuesBar = this.graphsContainer.element.createChild('div');\n this.currentValuesBar.id = 'counter-values-bar';\n }\n\n private createCounter(uiName: string, settingsKey: string, color: string, formatter?: ((arg0: number) => string)):\n Counter {\n const counter = new Counter();\n this.counters.push(counter);\n this.counterUI.push(new CounterUI(this, uiName, settingsKey, color, counter, formatter));\n return counter;\n }\n\n resizerElement(): Element|null {\n return this.header.element;\n }\n\n private resize(): void {\n const parentElement = (this.canvas.parentElement as HTMLElement);\n this.canvas.width = parentElement.clientWidth * window.devicePixelRatio;\n this.canvas.height = parentElement.clientHeight * window.devicePixelRatio;\n this.calculator.setDisplayWidth(this.canvas.width);\n this.refresh();\n }\n\n #scheduleRefresh(): void {\n UI.UIUtils.invokeOnceAfterBatchUpdate(this, this.refresh);\n }\n\n draw(): void {\n this.clear();\n if (this.#showNoEventsMessage) {\n this.#noEventsFoundMessage.removeAttribute('hidden');\n } else {\n this.#noEventsFoundMessage.setAttribute('hidden', 'hidden');\n }\n for (const counter of this.counters) {\n counter.calculateVisibleIndexes(this.calculator);\n counter.calculateXValues(this.canvas.width);\n }\n for (const counterUI of this.counterUI) {\n counterUI.drawGraph(this.canvas);\n }\n }\n\n private onClick(event: Event): void {\n const x = (event as MouseEvent).x - this.canvasContainer.getBoundingClientRect().left;\n let minDistance: number = Infinity;\n let bestTime;\n for (const counterUI of this.counterUI) {\n if (!counterUI.counter.times.length) {\n continue;\n }\n const index = counterUI.recordIndexAt(x);\n const distance = Math.abs(x * window.devicePixelRatio - counterUI.counter.x[index]);\n if (distance < minDistance) {\n minDistance = distance;\n bestTime = counterUI.counter.times[index];\n }\n }\n if (bestTime !== undefined && this.#events) {\n this.delegate.selectEntryAtTime(this.#events, bestTime);\n }\n }\n\n private onMouseLeave(_event: Event): void {\n delete this.markerXPosition;\n this.clearCurrentValueAndMarker();\n }\n\n private clearCurrentValueAndMarker(): void {\n for (let i = 0; i < this.counterUI.length; i++) {\n this.counterUI[i].clearCurrentValueAndMarker();\n }\n }\n\n private onMouseMove(event: Event): void {\n const x = (event as MouseEvent).x - this.canvasContainer.getBoundingClientRect().left;\n this.markerXPosition = x;\n this.refreshCurrentValues();\n }\n\n private refreshCurrentValues(): void {\n if (this.markerXPosition === undefined) {\n return;\n }\n for (let i = 0; i < this.counterUI.length; ++i) {\n this.counterUI[i].updateCurrentValue(this.markerXPosition);\n }\n }\n\n refresh(): void {\n this.timelineGrid.updateDividers(this.calculator);\n this.draw();\n this.refreshCurrentValues();\n }\n\n private clear(): void {\n const ctx = this.canvas.getContext('2d');\n if (!ctx) {\n throw new Error('Unable to get canvas context');\n }\n ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);\n }\n}\n\nexport class Counter {\n times: number[];\n values: number[];\n x: number[];\n minimumIndex: number;\n maximumIndex: number;\n private maxTime: number;\n private minTime: number;\n limitValue?: number;\n\n constructor() {\n this.times = [];\n this.values = [];\n this.x = [];\n this.minimumIndex = 0;\n this.maximumIndex = 0;\n this.maxTime = 0;\n this.minTime = 0;\n }\n\n appendSample(time: number, value: number): void {\n if (this.values.length && this.values[this.values.length - 1] === value) {\n return;\n }\n this.times.push(time);\n this.values.push(value);\n }\n\n reset(): void {\n this.times = [];\n this.values = [];\n }\n\n setLimit(value: number): void {\n this.limitValue = value;\n }\n\n calculateBounds(): {\n min: number,\n max: number,\n } {\n let maxValue;\n let minValue;\n for (let i = this.minimumIndex; i <= this.maximumIndex; i++) {\n const value = this.values[i];\n if (minValue === undefined || value < minValue) {\n minValue = value;\n }\n if (maxValue === undefined || value > maxValue) {\n maxValue = value;\n }\n }\n minValue = minValue || 0;\n maxValue = maxValue || 1;\n if (this.limitValue) {\n if (maxValue > this.limitValue * 0.5) {\n maxValue = Math.max(maxValue, this.limitValue);\n }\n minValue = Math.min(minValue, this.limitValue);\n }\n return {min: minValue, max: maxValue};\n }\n\n calculateVisibleIndexes(calculator: Calculator): void {\n const start = calculator.minimumBoundary();\n const end = calculator.maximumBoundary();\n\n // Maximum index of element whose time <= start.\n this.minimumIndex = Platform.NumberUtilities.clamp(\n Platform.ArrayUtilities.upperBound(this.times, start, Platform.ArrayUtilities.DEFAULT_COMPARATOR) - 1, 0,\n this.times.length - 1);\n\n // Minimum index of element whose time >= end.\n this.maximumIndex = Platform.NumberUtilities.clamp(\n Platform.ArrayUtilities.lowerBound(this.times, end, Platform.ArrayUtilities.DEFAULT_COMPARATOR), 0,\n this.times.length - 1);\n\n // Current window bounds.\n this.minTime = start;\n this.maxTime = end;\n }\n\n calculateXValues(width: number): void {\n if (!this.values.length) {\n return;\n }\n\n const xFactor = width / (this.maxTime - this.minTime);\n\n this.x = new Array(this.values.length);\n for (let i = this.minimumIndex + 1; i <= this.maximumIndex; i++) {\n this.x[i] = xFactor * (this.times[i] - this.minTime);\n }\n }\n}\n\nexport class CounterUI {\n private readonly countersPane: CountersGraph;\n counter: Counter;\n private readonly formatter: (arg0: number) => string;\n private readonly setting: Common.Settings.Setting;\n private filter: UI.Toolbar.ToolbarSettingCheckbox;\n private range: HTMLElement;\n private value: HTMLElement;\n graphColor: string;\n limitColor: string|null|undefined;\n graphYValues: number[];\n private readonly verticalPadding: number;\n private currentValueLabel: string;\n private marker: HTMLElement;\n\n constructor(\n countersPane: CountersGraph, title: string, settingsKey: string, graphColor: string, counter: Counter,\n formatter?: (arg0: number) => string) {\n this.countersPane = countersPane;\n this.counter = counter;\n this.formatter = formatter || Platform.NumberUtilities.withThousandsSeparator;\n\n this.setting = Common.Settings.Settings.instance().createSetting('timeline-counters-graph-' + settingsKey, true);\n this.setting.setTitle(title);\n this.filter = new UI.Toolbar.ToolbarSettingCheckbox(this.setting, title);\n this.filter.inputElement.classList.add('-theme-preserve-input');\n const parsedColor = Common.Color.parse(graphColor);\n if (parsedColor) {\n const colorWithAlpha = parsedColor.setAlpha(0.5).asString(Common.Color.Format.RGBA);\n const htmlElement = (this.filter.element as HTMLElement);\n if (colorWithAlpha) {\n htmlElement.style.backgroundColor = colorWithAlpha;\n }\n htmlElement.style.borderColor = 'transparent';\n }\n this.filter.inputElement.addEventListener('click', this.toggleCounterGraph.bind(this));\n countersPane.toolbar.appendToolbarItem(this.filter);\n this.range = this.filter.element.createChild('span', 'range');\n\n this.value = (countersPane.currentValuesBar as HTMLElement).createChild('span', 'memory-counter-value');\n this.value.style.color = graphColor;\n this.graphColor = graphColor;\n if (parsedColor) {\n this.limitColor = parsedColor.setAlpha(0.3).asString(Common.Color.Format.RGBA);\n }\n this.graphYValues = [];\n this.verticalPadding = 10;\n\n this.currentValueLabel = title;\n this.marker = countersPane.canvasContainer.createChild('div', 'memory-counter-marker');\n this.marker.style.backgroundColor = graphColor;\n this.clearCurrentValueAndMarker();\n }\n\n reset(): void {\n this.range.textContent = '';\n }\n\n setRange(minValue: number, maxValue: number): void {\n const min = this.formatter(minValue);\n const max = this.formatter(maxValue);\n this.range.textContent = i18nString(UIStrings.ss, {PH1: min, PH2: max});\n }\n\n private toggleCounterGraph(): void {\n this.value.classList.toggle('hidden', !this.filter.checked());\n this.countersPane.refresh();\n }\n\n recordIndexAt(x: number): number {\n return Platform.ArrayUtilities.upperBound(\n this.counter.x, x * window.devicePixelRatio, Platform.ArrayUtilities.DEFAULT_COMPARATOR,\n this.counter.minimumIndex + 1, this.counter.maximumIndex + 1) -\n 1;\n }\n\n updateCurrentValue(x: number): void {\n if (!this.visible() || !this.counter.values.length || !this.counter.x) {\n return;\n }\n const index = this.recordIndexAt(x);\n const value = Platform.NumberUtilities.withThousandsSeparator(this.counter.values[index]);\n this.value.textContent = `${this.currentValueLabel}: ${value}`;\n const y = this.graphYValues[index] / window.devicePixelRatio;\n this.marker.style.left = x + 'px';\n this.marker.style.top = y + 'px';\n this.marker.classList.remove('hidden');\n }\n\n clearCurrentValueAndMarker(): void {\n this.value.textContent = '';\n this.marker.classList.add('hidden');\n }\n\n drawGraph(canvas: HTMLCanvasElement): void {\n const ctx = canvas.getContext('2d');\n if (!ctx) {\n throw new Error('Unable to get canvas context');\n }\n const width = canvas.width;\n const height = canvas.height - 2 * this.verticalPadding;\n if (height <= 0) {\n this.graphYValues = [];\n return;\n }\n const originY = this.verticalPadding;\n const counter = this.counter;\n const values = counter.values;\n\n if (!values.length) {\n return;\n }\n\n const bounds = counter.calculateBounds();\n const minValue = bounds.min;\n const maxValue = bounds.max;\n this.setRange(minValue, maxValue);\n\n if (!this.visible()) {\n return;\n }\n\n const yValues = this.graphYValues;\n const maxYRange = maxValue - minValue;\n const yFactor = maxYRange ? height / (maxYRange) : 1;\n\n ctx.save();\n ctx.lineWidth = window.devicePixelRatio;\n if (ctx.lineWidth % 2) {\n ctx.translate(0.5, 0.5);\n }\n ctx.beginPath();\n let value: number = values[counter.minimumIndex];\n let currentY = Math.round(originY + height - (value - minValue) * yFactor);\n ctx.moveTo(0, currentY);\n let i = counter.minimumIndex;\n for (; i <= counter.maximumIndex; i++) {\n const x = Math.round(counter.x[i]);\n ctx.lineTo(x, currentY);\n const currentValue = values[i];\n if (typeof currentValue !== 'undefined') {\n value = currentValue;\n }\n currentY = Math.round(originY + height - (value - minValue) * yFactor);\n ctx.lineTo(x, currentY);\n yValues[i] = currentY;\n }\n yValues.length = i;\n ctx.lineTo(width, currentY);\n ctx.strokeStyle = this.graphColor;\n ctx.stroke();\n if (counter.limitValue) {\n const limitLineY = Math.round(originY + height - (counter.limitValue - minValue) * yFactor);\n ctx.moveTo(0, limitLineY);\n ctx.lineTo(width, limitLineY);\n if (this.limitColor) {\n ctx.strokeStyle = this.limitColor;\n }\n ctx.stroke();\n }\n ctx.closePath();\n ctx.restore();\n }\n\n visible(): boolean {\n return this.filter.checked();\n }\n}\n\nexport class Calculator implements PerfUI.TimelineGrid.Calculator {\n private minimumBoundaryInternal: number;\n private maximumBoundaryInternal: number;\n private workingArea: number;\n private zeroTimeInternal: number;\n\n constructor() {\n this.minimumBoundaryInternal = 0;\n this.maximumBoundaryInternal = 0;\n this.workingArea = 0;\n this.zeroTimeInternal = 0;\n }\n setZeroTime(time: number): void {\n this.zeroTimeInternal = time;\n }\n\n computePosition(time: number): number {\n return (time - this.minimumBoundaryInternal) / this.boundarySpan() * this.workingArea;\n }\n\n setWindow(minimumBoundary: number, maximumBoundary: number): void {\n this.minimumBoundaryInternal = minimumBoundary;\n this.maximumBoundaryInternal = maximumBoundary;\n }\n\n setDisplayWidth(clientWidth: number): void {\n this.workingArea = clientWidth;\n }\n\n formatValue(value: number, precision?: number): string {\n return i18n.TimeUtilities.preciseMillisToString(value - this.zeroTime(), precision);\n }\n\n maximumBoundary(): number {\n return this.maximumBoundaryInternal;\n }\n\n minimumBoundary(): number {\n return this.minimumBoundaryInternal;\n }\n\n zeroTime(): number {\n return this.zeroTimeInternal;\n }\n\n boundarySpan(): number {\n return this.maximumBoundaryInternal - this.minimumBoundaryInternal;\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/EntriesFilter.d.ts b/public/panels/timeline/EntriesFilter.d.ts index 5bed83a39..0824e1f17 100644 --- a/public/panels/timeline/EntriesFilter.d.ts +++ b/public/panels/timeline/EntriesFilter.d.ts @@ -1,6 +1,6 @@ -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; -type EntryToNodeMap = Map; +type EntryToNodeMap = Map; /** * This class can take in a thread that has been generated by the * RendererHandler and apply certain actions to it in order to modify what is @@ -18,38 +18,38 @@ export declare class EntriesFilter { * Checks which actions can be applied on an entry. This allows us to only show possible actions in the Context Menu. * For example, if an entry has no children, COLLAPSE_FUNCTION will not change the FlameChart, therefore there is no need to show this action as an option. */ - findPossibleActions(entry: TraceEngine.Types.TraceEvents.TraceEventData): PerfUI.FlameChart.PossibleFilterActions; + findPossibleActions(entry: Trace.Types.Events.Event): PerfUI.FlameChart.PossibleFilterActions; /** * Returns the amount of entry descendants that belong to the hidden entries array. * */ - findHiddenDescendantsAmount(entry: TraceEngine.Types.TraceEvents.TraceEventData): number; + findHiddenDescendantsAmount(entry: Trace.Types.Events.Event): number; /** * Returns the set of entries that are invisible given the set of applied actions. */ - invisibleEntries(): TraceEngine.Types.TraceEvents.TraceEventData[]; + invisibleEntries(): Trace.Types.Events.Event[]; /** * Sets hidden and expandable. Called when a trace with modifications is loaded and some entries are set as hidden and expandable. * Both arrays are set together because if there is one, the other must be present too. */ - setHiddenAndExpandableEntries(invisibleEntries: TraceEngine.Types.TraceEvents.TraceEventData[], expandableEntries: TraceEngine.Types.TraceEvents.TraceEventData[]): void; - entryIsInvisible(entry: TraceEngine.Types.TraceEvents.TraceEventData): boolean; + setHiddenAndExpandableEntries(invisibleEntries: Trace.Types.Events.Event[], expandableEntries: Trace.Types.Events.Event[]): void; + entryIsInvisible(entry: Trace.Types.Events.Event): boolean; /** * Returns the array of entries that have a sign indicating that entries below are hidden, * and so that they can be "expanded" to reveal their hidden children. */ - expandableEntries(): TraceEngine.Types.TraceEvents.TraceEventData[]; + expandableEntries(): Trace.Types.Events.Event[]; /** * Applies an action to hide entries or removes entries * from hidden entries array depending on the action. */ - applyFilterAction(action: PerfUI.FlameChart.UserFilterAction): TraceEngine.Types.TraceEvents.TraceEventData[]; - firstVisibleParentEntryForEntry(entry: TraceEngine.Types.TraceEvents.TraceEventData): TraceEngine.Types.TraceEvents.TraceEventData | null; + applyFilterAction(action: PerfUI.FlameChart.UserFilterAction): Trace.Types.Events.Event[]; + firstVisibleParentEntryForEntry(entry: Trace.Types.Events.Event): Trace.Types.Events.Event | null; /** * If an entry was selected from a link instead of clicking on it, * it might be in the invisible entries array. * If it is, reveal it by resetting clidren the closest expandable entry, */ - revealEntry(entry: TraceEngine.Types.TraceEvents.TraceEventData): void; - isEntryExpandable(event: TraceEngine.Types.TraceEvents.TraceEventData): boolean; + revealEntry(entry: Trace.Types.Events.Event): void; + isEntryExpandable(event: Trace.Types.Events.Event): boolean; } export {}; diff --git a/public/panels/timeline/EntriesFilter.js b/public/panels/timeline/EntriesFilter.js index 831050597..d099a2ed5 100644 --- a/public/panels/timeline/EntriesFilter.js +++ b/public/panels/timeline/EntriesFilter.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as Platform from '../../core/platform/platform.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; import { entryIsVisibleInTimeline, } from './CompatibilityTracksAppender.js'; /** @@ -228,15 +228,15 @@ export class EntriesFilter { // Walk through all the ancestors, starting at the root node. const children = [...root.children]; const repeatingNodes = []; - const rootIsProfileCall = TraceEngine.Types.TraceEvents.isProfileCall(root.entry); + const rootIsProfileCall = Trace.Types.Events.isProfileCall(root.entry); while (children.length > 0) { const childNode = children.shift(); if (childNode) { - const childIsProfileCall = TraceEngine.Types.TraceEvents.isProfileCall(childNode.entry); + const childIsProfileCall = Trace.Types.Events.isProfileCall(childNode.entry); if ( /* Handle SyntheticProfileCalls */rootIsProfileCall && childIsProfileCall) { const rootNodeEntry = root.entry; const childNodeEntry = childNode.entry; - if (TraceEngine.Helpers.SamplesIntegrator.SamplesIntegrator.framesAreEqual(rootNodeEntry.callFrame, childNodeEntry.callFrame)) { + if (Trace.Helpers.SamplesIntegrator.SamplesIntegrator.framesAreEqual(rootNodeEntry.callFrame, childNodeEntry.callFrame)) { repeatingNodes.push(childNode.entry); } } /* Handle Renderer events */ diff --git a/public/panels/timeline/EntriesFilter.js.map b/public/panels/timeline/EntriesFilter.js.map index f12b61395..ec85f87c1 100644 --- a/public/panels/timeline/EntriesFilter.js.map +++ b/public/panels/timeline/EntriesFilter.js.map @@ -1 +1 @@ -{"version":3,"file":"EntriesFilter.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/EntriesFilter.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as Platform from '../../core/platform/platform.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\n\nimport {\n entryIsVisibleInTimeline,\n} from './CompatibilityTracksAppender.js';\n\ntype EntryToNodeMap = Map;\n\n/**\n * This class can take in a thread that has been generated by the\n * RendererHandler and apply certain actions to it in order to modify what is\n * shown to the user. These actions can be automatically applied by DevTools or\n * applied by the user.\n *\n * Once actions are applied, the invisibleEntries() method will return the\n * entries that are invisible, and this is the list of entries that should be\n * removed before rendering the resulting thread on the timeline.\n */\nexport class EntriesFilter {\n // Maps from an individual TraceEvent entry to its representation as a\n // RendererEntryNode. We need this so we can then parse the tree structure\n // generated by the RendererHandler.\n #entryToNode: EntryToNodeMap;\n\n // Track the set of invisible entries.\n #invisibleEntries: TraceEngine.Types.TraceEvents.TraceEventData[] = [];\n // List of entries whose children are hidden. This list is used to\n // keep track of entries that should be identified in the UI as \"expandable\",\n // since they can be clicked to reveal their hidden children.\n #expandableEntries: TraceEngine.Types.TraceEvents.TraceEventData[] = [];\n // Cache for descendants of entry that have already been gathered. The descendants\n // will never change so we can avoid running the potentially expensive search again.\n #entryToDescendantsMap:\n Map = new Map();\n\n constructor(entryToNodeMap: EntryToNodeMap) {\n this.#entryToNode = entryToNodeMap;\n }\n\n /**\n * Checks which actions can be applied on an entry. This allows us to only show possible actions in the Context Menu.\n * For example, if an entry has no children, COLLAPSE_FUNCTION will not change the FlameChart, therefore there is no need to show this action as an option.\n */\n findPossibleActions(entry: TraceEngine.Types.TraceEvents.TraceEventData): PerfUI.FlameChart.PossibleFilterActions {\n const entryNode = this.#entryToNode.get(entry);\n if (!entryNode) {\n // Invalid node was given, return no possible actions.\n return {\n [PerfUI.FlameChart.FilterAction.MERGE_FUNCTION]: false,\n [PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION]: false,\n [PerfUI.FlameChart.FilterAction.COLLAPSE_REPEATING_DESCENDANTS]: false,\n [PerfUI.FlameChart.FilterAction.RESET_CHILDREN]: false,\n [PerfUI.FlameChart.FilterAction.UNDO_ALL_ACTIONS]: false,\n };\n }\n const entryParent = entryNode.parent;\n const allVisibleDescendants =\n this.#findAllDescendantsOfNode(entryNode).filter(descendant => !this.#invisibleEntries.includes(descendant));\n const allVisibleRepeatingDescendants = this.#findAllRepeatingDescendantsOfNext(entryNode).filter(\n descendant => !this.#invisibleEntries.includes(descendant));\n const allInVisibleDescendants =\n this.#findAllDescendantsOfNode(entryNode).filter(descendant => this.#invisibleEntries.includes(descendant));\n\n // If there are children to hide, indicate action as possible\n const possibleActions: PerfUI.FlameChart.PossibleFilterActions = {\n [PerfUI.FlameChart.FilterAction.MERGE_FUNCTION]: entryParent !== null,\n [PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION]: allVisibleDescendants.length > 0,\n [PerfUI.FlameChart.FilterAction.COLLAPSE_REPEATING_DESCENDANTS]: allVisibleRepeatingDescendants.length > 0,\n [PerfUI.FlameChart.FilterAction.RESET_CHILDREN]: allInVisibleDescendants.length > 0,\n [PerfUI.FlameChart.FilterAction.UNDO_ALL_ACTIONS]: this.#invisibleEntries.length > 0,\n };\n return possibleActions;\n }\n\n /**\n * Returns the amount of entry descendants that belong to the hidden entries array.\n * */\n findHiddenDescendantsAmount(entry: TraceEngine.Types.TraceEvents.TraceEventData): number {\n const entryNode = this.#entryToNode.get(entry);\n if (!entryNode) {\n return 0;\n }\n const allDescendants = this.#findAllDescendantsOfNode(entryNode);\n return allDescendants.filter(descendant => this.invisibleEntries().includes(descendant)).length;\n }\n\n /**\n * Returns the set of entries that are invisible given the set of applied actions.\n */\n invisibleEntries(): TraceEngine.Types.TraceEvents.TraceEventData[] {\n return this.#invisibleEntries;\n }\n\n /**\n * Sets hidden and expandable. Called when a trace with modifications is loaded and some entries are set as hidden and expandable.\n * Both arrays are set together because if there is one, the other must be present too.\n */\n setHiddenAndExpandableEntries(\n invisibleEntries: TraceEngine.Types.TraceEvents.TraceEventData[],\n expandableEntries: TraceEngine.Types.TraceEvents.TraceEventData[]): void {\n this.#invisibleEntries.push(...invisibleEntries);\n this.#expandableEntries.push(...expandableEntries);\n }\n\n entryIsInvisible(entry: TraceEngine.Types.TraceEvents.TraceEventData): boolean {\n return this.#invisibleEntries.includes(entry);\n }\n\n /**\n * Returns the array of entries that have a sign indicating that entries below are hidden,\n * and so that they can be \"expanded\" to reveal their hidden children.\n */\n expandableEntries(): TraceEngine.Types.TraceEvents.TraceEventData[] {\n return this.#expandableEntries;\n }\n\n /**\n * Applies an action to hide entries or removes entries\n * from hidden entries array depending on the action.\n */\n applyFilterAction(action: PerfUI.FlameChart.UserFilterAction): TraceEngine.Types.TraceEvents.TraceEventData[] {\n // We apply new user action to the set of all entries, and mark\n // any that should be hidden by adding them to this set.\n // Another approach would be to use splice() to remove items from the\n // array, but doing this would be a mutation of the arry for every hidden\n // event. Instead, we add entries to this set and return it as an array at the end.\n const entriesToHide = new Set();\n\n switch (action.type) {\n case PerfUI.FlameChart.FilterAction.MERGE_FUNCTION: {\n // The entry that was clicked on is merged into its parent. All its\n // children remain visible, so we just have to hide the entry that was\n // selected.\n entriesToHide.add(action.entry);\n // If parent node exists, add it to expandableEntries, so it would be possible to uncollapse its children.\n const actionNode = this.#entryToNode.get(action.entry) || null;\n const parentNode = actionNode && this.#firstVisibleParentNodeForEntryNode(actionNode);\n if (parentNode) {\n this.#addExpandableEntry(parentNode.entry);\n }\n break;\n }\n case PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION: {\n // The entry itself remains visible, but all of its descendants are hidden.\n const entryNode = this.#entryToNode.get(action.entry);\n if (!entryNode) {\n // Invalid node was given, just ignore and move on.\n break;\n }\n const allDescendants = this.#findAllDescendantsOfNode(entryNode);\n allDescendants.forEach(descendant => entriesToHide.add(descendant));\n this.#addExpandableEntry(action.entry);\n break;\n }\n case PerfUI.FlameChart.FilterAction.COLLAPSE_REPEATING_DESCENDANTS: {\n const entryNode = this.#entryToNode.get(action.entry);\n if (!entryNode) {\n // Invalid node was given, just ignore and move on.\n break;\n }\n const allRepeatingDescendants = this.#findAllRepeatingDescendantsOfNext(entryNode);\n allRepeatingDescendants.forEach(descendant => entriesToHide.add(descendant));\n if (entriesToHide.size > 0) {\n this.#addExpandableEntry(action.entry);\n }\n break;\n }\n case PerfUI.FlameChart.FilterAction.UNDO_ALL_ACTIONS: {\n this.#invisibleEntries = [];\n this.#expandableEntries = [];\n break;\n }\n case PerfUI.FlameChart.FilterAction.RESET_CHILDREN: {\n this.#makeEntryChildrenVisible(action.entry);\n break;\n }\n default:\n Platform.assertNever(action.type, `Unknown EntriesFilter action: ${action.type}`);\n }\n\n this.#invisibleEntries.push(...entriesToHide);\n\n return this.#invisibleEntries;\n }\n\n /**\n * Add an entry to the array of entries that have a sign indicating that entries below are hidden.\n * Also, remove all of the child entries of the new expandable entry from the expandable array. Do that because\n * to draw the initiator from the closest visible entry, we need to get the closest entry that is\n * marked as expandable and we do not want to get some that are hidden.\n */\n #addExpandableEntry(entry: TraceEngine.Types.TraceEvents.TraceEventData): void {\n this.#expandableEntries.push(entry);\n const entryNode = this.#entryToNode.get(entry);\n if (!entryNode) {\n // Invalid node was given, just ignore and move on.\n return;\n }\n const allDescendants = this.#findAllDescendantsOfNode(entryNode);\n if (allDescendants.length > 0) {\n this.#expandableEntries = this.#expandableEntries.filter(entry => {\n return !allDescendants.includes(entry);\n });\n }\n }\n\n firstVisibleParentEntryForEntry(entry: TraceEngine.Types.TraceEvents.TraceEventData):\n TraceEngine.Types.TraceEvents.TraceEventData|null {\n const node = this.#entryToNode.get(entry);\n if (!node) {\n return null;\n }\n const parent = this.#firstVisibleParentNodeForEntryNode(node);\n return parent ? parent.entry : null;\n }\n\n // The direct parent might be hidden by other actions, therefore we look for the next visible parent.\n #firstVisibleParentNodeForEntryNode(node: TraceEngine.Helpers.TreeHelpers.TraceEntryNode):\n TraceEngine.Helpers.TreeHelpers.TraceEntryNode|null {\n let parent = node.parent;\n while ((parent && this.#invisibleEntries.includes(parent.entry)) ||\n (parent && !entryIsVisibleInTimeline(parent.entry))) {\n parent = parent.parent;\n }\n return parent;\n }\n\n #findAllDescendantsOfNode(root: TraceEngine.Helpers.TreeHelpers.TraceEntryNode):\n TraceEngine.Types.TraceEvents.TraceEventData[] {\n const cachedDescendants = this.#entryToDescendantsMap.get(root);\n if (cachedDescendants) {\n return cachedDescendants;\n }\n\n const descendants: TraceEngine.Types.TraceEvents.TraceEventData[] = [];\n\n // Walk through all the descendants, starting at the root node.\n const children: TraceEngine.Helpers.TreeHelpers.TraceEntryNode[] = [...root.children];\n while (children.length > 0) {\n const childNode = children.shift();\n if (childNode) {\n descendants.push(childNode.entry);\n const childNodeCachedDescendants = this.#entryToDescendantsMap.get(childNode);\n // If the descendants of a child are cached, get them from the cache instead of iterating through them again\n if (childNodeCachedDescendants) {\n descendants.push(...childNodeCachedDescendants);\n } else {\n children.push(...childNode.children);\n }\n }\n }\n\n this.#entryToDescendantsMap.set(root, descendants);\n return descendants;\n }\n\n #findAllRepeatingDescendantsOfNext(root: TraceEngine.Helpers.TreeHelpers.TraceEntryNode):\n TraceEngine.Types.TraceEvents.TraceEventData[] {\n // Walk through all the ancestors, starting at the root node.\n const children: TraceEngine.Helpers.TreeHelpers.TraceEntryNode[] = [...root.children];\n const repeatingNodes: TraceEngine.Types.TraceEvents.TraceEventData[] = [];\n const rootIsProfileCall = TraceEngine.Types.TraceEvents.isProfileCall(root.entry);\n\n while (children.length > 0) {\n const childNode = children.shift();\n if (childNode) {\n const childIsProfileCall = TraceEngine.Types.TraceEvents.isProfileCall(childNode.entry);\n if (/* Handle SyntheticProfileCalls */ rootIsProfileCall && childIsProfileCall) {\n const rootNodeEntry = root.entry as TraceEngine.Types.TraceEvents.SyntheticProfileCall;\n const childNodeEntry = childNode.entry as TraceEngine.Types.TraceEvents.SyntheticProfileCall;\n\n if (TraceEngine.Helpers.SamplesIntegrator.SamplesIntegrator.framesAreEqual(\n rootNodeEntry.callFrame, childNodeEntry.callFrame)) {\n repeatingNodes.push(childNode.entry);\n }\n } /* Handle Renderer events */ else if (!rootIsProfileCall && !childIsProfileCall) {\n if (root.entry.name === childNode.entry.name) {\n repeatingNodes.push(childNode.entry);\n }\n }\n children.push(...childNode.children);\n }\n }\n\n return repeatingNodes;\n }\n\n /**\n * If an entry was selected from a link instead of clicking on it,\n * it might be in the invisible entries array.\n * If it is, reveal it by resetting clidren the closest expandable entry,\n */\n revealEntry(entry: TraceEngine.Types.TraceEvents.TraceEventData): void {\n const entryNode = this.#entryToNode.get(entry);\n if (!entryNode) {\n // Invalid node was given, just ignore and move on.\n return;\n }\n let closestExpandableParent = entryNode;\n while (closestExpandableParent.parent && !this.#expandableEntries.includes(closestExpandableParent.entry)) {\n closestExpandableParent = closestExpandableParent.parent;\n }\n this.#makeEntryChildrenVisible(closestExpandableParent.entry);\n }\n\n /**\n * Removes all of the entry children from the\n * invisible entries array to make them visible.\n */\n #makeEntryChildrenVisible(entry: TraceEngine.Types.TraceEvents.TraceEventData): void {\n const entryNode = this.#entryToNode.get(entry);\n if (!entryNode) {\n // Invalid node was given, just ignore and move on.\n return;\n }\n const descendants = this.#findAllDescendantsOfNode(entryNode);\n\n /**\n * Filter out all descendant of the node\n * from the invisible entries list.\n */\n this.#invisibleEntries = this.#invisibleEntries.filter(entry => {\n if (descendants.includes(entry)) {\n return false;\n }\n return true;\n });\n\n /**\n * Filter out all descentants and entry from expandable entries\n * list to not show that some entries below those are hidden.\n */\n this.#expandableEntries = this.#expandableEntries.filter(iterEntry => {\n if (descendants.includes(iterEntry) || iterEntry === entry) {\n return false;\n }\n return true;\n });\n }\n\n isEntryExpandable(event: TraceEngine.Types.TraceEvents.TraceEventData): boolean {\n return this.#expandableEntries.includes(event);\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"EntriesFilter.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/EntriesFilter.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as Platform from '../../core/platform/platform.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\n\nimport {\n entryIsVisibleInTimeline,\n} from './CompatibilityTracksAppender.js';\n\ntype EntryToNodeMap = Map;\n\n/**\n * This class can take in a thread that has been generated by the\n * RendererHandler and apply certain actions to it in order to modify what is\n * shown to the user. These actions can be automatically applied by DevTools or\n * applied by the user.\n *\n * Once actions are applied, the invisibleEntries() method will return the\n * entries that are invisible, and this is the list of entries that should be\n * removed before rendering the resulting thread on the timeline.\n */\nexport class EntriesFilter {\n // Maps from an individual TraceEvent entry to its representation as a\n // RendererEntryNode. We need this so we can then parse the tree structure\n // generated by the RendererHandler.\n #entryToNode: EntryToNodeMap;\n\n // Track the set of invisible entries.\n #invisibleEntries: Trace.Types.Events.Event[] = [];\n // List of entries whose children are hidden. This list is used to\n // keep track of entries that should be identified in the UI as \"expandable\",\n // since they can be clicked to reveal their hidden children.\n #expandableEntries: Trace.Types.Events.Event[] = [];\n // Cache for descendants of entry that have already been gathered. The descendants\n // will never change so we can avoid running the potentially expensive search again.\n #entryToDescendantsMap: Map = new Map();\n\n constructor(entryToNodeMap: EntryToNodeMap) {\n this.#entryToNode = entryToNodeMap;\n }\n\n /**\n * Checks which actions can be applied on an entry. This allows us to only show possible actions in the Context Menu.\n * For example, if an entry has no children, COLLAPSE_FUNCTION will not change the FlameChart, therefore there is no need to show this action as an option.\n */\n findPossibleActions(entry: Trace.Types.Events.Event): PerfUI.FlameChart.PossibleFilterActions {\n const entryNode = this.#entryToNode.get(entry);\n if (!entryNode) {\n // Invalid node was given, return no possible actions.\n return {\n [PerfUI.FlameChart.FilterAction.MERGE_FUNCTION]: false,\n [PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION]: false,\n [PerfUI.FlameChart.FilterAction.COLLAPSE_REPEATING_DESCENDANTS]: false,\n [PerfUI.FlameChart.FilterAction.RESET_CHILDREN]: false,\n [PerfUI.FlameChart.FilterAction.UNDO_ALL_ACTIONS]: false,\n };\n }\n const entryParent = entryNode.parent;\n const allVisibleDescendants =\n this.#findAllDescendantsOfNode(entryNode).filter(descendant => !this.#invisibleEntries.includes(descendant));\n const allVisibleRepeatingDescendants = this.#findAllRepeatingDescendantsOfNext(entryNode).filter(\n descendant => !this.#invisibleEntries.includes(descendant));\n const allInVisibleDescendants =\n this.#findAllDescendantsOfNode(entryNode).filter(descendant => this.#invisibleEntries.includes(descendant));\n\n // If there are children to hide, indicate action as possible\n const possibleActions: PerfUI.FlameChart.PossibleFilterActions = {\n [PerfUI.FlameChart.FilterAction.MERGE_FUNCTION]: entryParent !== null,\n [PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION]: allVisibleDescendants.length > 0,\n [PerfUI.FlameChart.FilterAction.COLLAPSE_REPEATING_DESCENDANTS]: allVisibleRepeatingDescendants.length > 0,\n [PerfUI.FlameChart.FilterAction.RESET_CHILDREN]: allInVisibleDescendants.length > 0,\n [PerfUI.FlameChart.FilterAction.UNDO_ALL_ACTIONS]: this.#invisibleEntries.length > 0,\n };\n return possibleActions;\n }\n\n /**\n * Returns the amount of entry descendants that belong to the hidden entries array.\n * */\n findHiddenDescendantsAmount(entry: Trace.Types.Events.Event): number {\n const entryNode = this.#entryToNode.get(entry);\n if (!entryNode) {\n return 0;\n }\n const allDescendants = this.#findAllDescendantsOfNode(entryNode);\n return allDescendants.filter(descendant => this.invisibleEntries().includes(descendant)).length;\n }\n\n /**\n * Returns the set of entries that are invisible given the set of applied actions.\n */\n invisibleEntries(): Trace.Types.Events.Event[] {\n return this.#invisibleEntries;\n }\n\n /**\n * Sets hidden and expandable. Called when a trace with modifications is loaded and some entries are set as hidden and expandable.\n * Both arrays are set together because if there is one, the other must be present too.\n */\n setHiddenAndExpandableEntries(\n invisibleEntries: Trace.Types.Events.Event[], expandableEntries: Trace.Types.Events.Event[]): void {\n this.#invisibleEntries.push(...invisibleEntries);\n this.#expandableEntries.push(...expandableEntries);\n }\n\n entryIsInvisible(entry: Trace.Types.Events.Event): boolean {\n return this.#invisibleEntries.includes(entry);\n }\n\n /**\n * Returns the array of entries that have a sign indicating that entries below are hidden,\n * and so that they can be \"expanded\" to reveal their hidden children.\n */\n expandableEntries(): Trace.Types.Events.Event[] {\n return this.#expandableEntries;\n }\n\n /**\n * Applies an action to hide entries or removes entries\n * from hidden entries array depending on the action.\n */\n applyFilterAction(action: PerfUI.FlameChart.UserFilterAction): Trace.Types.Events.Event[] {\n // We apply new user action to the set of all entries, and mark\n // any that should be hidden by adding them to this set.\n // Another approach would be to use splice() to remove items from the\n // array, but doing this would be a mutation of the arry for every hidden\n // event. Instead, we add entries to this set and return it as an array at the end.\n const entriesToHide = new Set();\n\n switch (action.type) {\n case PerfUI.FlameChart.FilterAction.MERGE_FUNCTION: {\n // The entry that was clicked on is merged into its parent. All its\n // children remain visible, so we just have to hide the entry that was\n // selected.\n entriesToHide.add(action.entry);\n // If parent node exists, add it to expandableEntries, so it would be possible to uncollapse its children.\n const actionNode = this.#entryToNode.get(action.entry) || null;\n const parentNode = actionNode && this.#firstVisibleParentNodeForEntryNode(actionNode);\n if (parentNode) {\n this.#addExpandableEntry(parentNode.entry);\n }\n break;\n }\n case PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION: {\n // The entry itself remains visible, but all of its descendants are hidden.\n const entryNode = this.#entryToNode.get(action.entry);\n if (!entryNode) {\n // Invalid node was given, just ignore and move on.\n break;\n }\n const allDescendants = this.#findAllDescendantsOfNode(entryNode);\n allDescendants.forEach(descendant => entriesToHide.add(descendant));\n this.#addExpandableEntry(action.entry);\n break;\n }\n case PerfUI.FlameChart.FilterAction.COLLAPSE_REPEATING_DESCENDANTS: {\n const entryNode = this.#entryToNode.get(action.entry);\n if (!entryNode) {\n // Invalid node was given, just ignore and move on.\n break;\n }\n const allRepeatingDescendants = this.#findAllRepeatingDescendantsOfNext(entryNode);\n allRepeatingDescendants.forEach(descendant => entriesToHide.add(descendant));\n if (entriesToHide.size > 0) {\n this.#addExpandableEntry(action.entry);\n }\n break;\n }\n case PerfUI.FlameChart.FilterAction.UNDO_ALL_ACTIONS: {\n this.#invisibleEntries = [];\n this.#expandableEntries = [];\n break;\n }\n case PerfUI.FlameChart.FilterAction.RESET_CHILDREN: {\n this.#makeEntryChildrenVisible(action.entry);\n break;\n }\n default:\n Platform.assertNever(action.type, `Unknown EntriesFilter action: ${action.type}`);\n }\n\n this.#invisibleEntries.push(...entriesToHide);\n\n return this.#invisibleEntries;\n }\n\n /**\n * Add an entry to the array of entries that have a sign indicating that entries below are hidden.\n * Also, remove all of the child entries of the new expandable entry from the expandable array. Do that because\n * to draw the initiator from the closest visible entry, we need to get the closest entry that is\n * marked as expandable and we do not want to get some that are hidden.\n */\n #addExpandableEntry(entry: Trace.Types.Events.Event): void {\n this.#expandableEntries.push(entry);\n const entryNode = this.#entryToNode.get(entry);\n if (!entryNode) {\n // Invalid node was given, just ignore and move on.\n return;\n }\n const allDescendants = this.#findAllDescendantsOfNode(entryNode);\n if (allDescendants.length > 0) {\n this.#expandableEntries = this.#expandableEntries.filter(entry => {\n return !allDescendants.includes(entry);\n });\n }\n }\n\n firstVisibleParentEntryForEntry(entry: Trace.Types.Events.Event): Trace.Types.Events.Event|null {\n const node = this.#entryToNode.get(entry);\n if (!node) {\n return null;\n }\n const parent = this.#firstVisibleParentNodeForEntryNode(node);\n return parent ? parent.entry : null;\n }\n\n // The direct parent might be hidden by other actions, therefore we look for the next visible parent.\n #firstVisibleParentNodeForEntryNode(node: Trace.Helpers.TreeHelpers.TraceEntryNode):\n Trace.Helpers.TreeHelpers.TraceEntryNode|null {\n let parent = node.parent;\n while ((parent && this.#invisibleEntries.includes(parent.entry)) ||\n (parent && !entryIsVisibleInTimeline(parent.entry))) {\n parent = parent.parent;\n }\n return parent;\n }\n\n #findAllDescendantsOfNode(root: Trace.Helpers.TreeHelpers.TraceEntryNode): Trace.Types.Events.Event[] {\n const cachedDescendants = this.#entryToDescendantsMap.get(root);\n if (cachedDescendants) {\n return cachedDescendants;\n }\n\n const descendants: Trace.Types.Events.Event[] = [];\n\n // Walk through all the descendants, starting at the root node.\n const children: Trace.Helpers.TreeHelpers.TraceEntryNode[] = [...root.children];\n while (children.length > 0) {\n const childNode = children.shift();\n if (childNode) {\n descendants.push(childNode.entry);\n const childNodeCachedDescendants = this.#entryToDescendantsMap.get(childNode);\n // If the descendants of a child are cached, get them from the cache instead of iterating through them again\n if (childNodeCachedDescendants) {\n descendants.push(...childNodeCachedDescendants);\n } else {\n children.push(...childNode.children);\n }\n }\n }\n\n this.#entryToDescendantsMap.set(root, descendants);\n return descendants;\n }\n\n #findAllRepeatingDescendantsOfNext(root: Trace.Helpers.TreeHelpers.TraceEntryNode): Trace.Types.Events.Event[] {\n // Walk through all the ancestors, starting at the root node.\n const children: Trace.Helpers.TreeHelpers.TraceEntryNode[] = [...root.children];\n const repeatingNodes: Trace.Types.Events.Event[] = [];\n const rootIsProfileCall = Trace.Types.Events.isProfileCall(root.entry);\n\n while (children.length > 0) {\n const childNode = children.shift();\n if (childNode) {\n const childIsProfileCall = Trace.Types.Events.isProfileCall(childNode.entry);\n if (/* Handle SyntheticProfileCalls */ rootIsProfileCall && childIsProfileCall) {\n const rootNodeEntry = root.entry as Trace.Types.Events.SyntheticProfileCall;\n const childNodeEntry = childNode.entry as Trace.Types.Events.SyntheticProfileCall;\n\n if (Trace.Helpers.SamplesIntegrator.SamplesIntegrator.framesAreEqual(\n rootNodeEntry.callFrame, childNodeEntry.callFrame)) {\n repeatingNodes.push(childNode.entry);\n }\n } /* Handle Renderer events */ else if (!rootIsProfileCall && !childIsProfileCall) {\n if (root.entry.name === childNode.entry.name) {\n repeatingNodes.push(childNode.entry);\n }\n }\n children.push(...childNode.children);\n }\n }\n\n return repeatingNodes;\n }\n\n /**\n * If an entry was selected from a link instead of clicking on it,\n * it might be in the invisible entries array.\n * If it is, reveal it by resetting clidren the closest expandable entry,\n */\n revealEntry(entry: Trace.Types.Events.Event): void {\n const entryNode = this.#entryToNode.get(entry);\n if (!entryNode) {\n // Invalid node was given, just ignore and move on.\n return;\n }\n let closestExpandableParent = entryNode;\n while (closestExpandableParent.parent && !this.#expandableEntries.includes(closestExpandableParent.entry)) {\n closestExpandableParent = closestExpandableParent.parent;\n }\n this.#makeEntryChildrenVisible(closestExpandableParent.entry);\n }\n\n /**\n * Removes all of the entry children from the\n * invisible entries array to make them visible.\n */\n #makeEntryChildrenVisible(entry: Trace.Types.Events.Event): void {\n const entryNode = this.#entryToNode.get(entry);\n if (!entryNode) {\n // Invalid node was given, just ignore and move on.\n return;\n }\n const descendants = this.#findAllDescendantsOfNode(entryNode);\n\n /**\n * Filter out all descendant of the node\n * from the invisible entries list.\n */\n this.#invisibleEntries = this.#invisibleEntries.filter(entry => {\n if (descendants.includes(entry)) {\n return false;\n }\n return true;\n });\n\n /**\n * Filter out all descentants and entry from expandable entries\n * list to not show that some entries below those are hidden.\n */\n this.#expandableEntries = this.#expandableEntries.filter(iterEntry => {\n if (descendants.includes(iterEntry) || iterEntry === entry) {\n return false;\n }\n return true;\n });\n }\n\n isEntryExpandable(event: Trace.Types.Events.Event): boolean {\n return this.#expandableEntries.includes(event);\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/EntriesFilter.test.js b/public/panels/timeline/EntriesFilter.test.js index 0ac11fbe7..d36478050 100644 --- a/public/panels/timeline/EntriesFilter.test.js +++ b/public/panels/timeline/EntriesFilter.test.js @@ -4,12 +4,12 @@ // Copyright 2023222 The Chromium Author2s. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import * as TraceEngine from '../../models/trace/trace.js'; -import * as Timeline from './timeline.js'; -import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; -import { TraceLoader } from '../../testing/TraceLoader.js'; -import { getMainThread } from '../../testing/TraceHelpers.js'; +import * as Trace from '../../models/trace/trace.js'; import { describeWithEnvironment } from '../../testing/EnvironmentHelpers.js'; +import { getMainThread } from '../../testing/TraceHelpers.js'; +import { TraceLoader } from '../../testing/TraceLoader.js'; +import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; +import * as Timeline from './timeline.js'; function findFirstEntry(allEntries, predicate) { const entry = allEntries.find(entry => predicate(entry)); if (!entry) { @@ -19,13 +19,13 @@ function findFirstEntry(allEntries, predicate) { } describeWithEnvironment('EntriesFilter', function () { 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 Timeline.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'basic-stack.json.gz'); + const stack = new Timeline.EntriesFilter.EntriesFilter(parsedTrace.Renderer.entryToNode); assert.deepEqual([], stack?.invisibleEntries()); }); it('supports the user merging an entry into its parent', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'basic-stack.json.gz'); - const mainThread = getMainThread(traceData.Renderer); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'basic-stack.json.gz'); + const mainThread = getMainThread(parsedTrace.Renderer); /** This stack looks roughly like so (with some events omitted): * ======== basicStackOne ============ * =========== basicTwo ============== @@ -51,10 +51,10 @@ describeWithEnvironment('EntriesFilter', function () { const entryTwo = findFirstEntry(mainThread.entries, entry => { // Processing this trace ends up with two distinct stacks for basicTwo() // So we find the first one so we can focus this test on just one stack. - return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'basicTwo' && + return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'basicTwo' && entry.dur === 827; }); - const stack = new Timeline.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode); + const stack = new Timeline.EntriesFilter.EntriesFilter(parsedTrace.Renderer.entryToNode); if (!stack) { throw new Error('EntriesFilter does not exist'); } @@ -64,8 +64,8 @@ describeWithEnvironment('EntriesFilter', function () { assert.strictEqual(stack.invisibleEntries().length, 1); }); it('adds the parent of the merged entry into the expandableEntries array', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'basic-stack.json.gz'); - const mainThread = getMainThread(traceData.Renderer); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'basic-stack.json.gz'); + const mainThread = getMainThread(parsedTrace.Renderer); /** This stack looks roughly like so (with some events omitted): * ======== basicStackOne ============ * =========== basicTwo ============== @@ -89,10 +89,10 @@ describeWithEnvironment('EntriesFilter', function () { const entryTwo = findFirstEntry(mainThread.entries, entry => { // Processing this trace ends up with two distinct stacks for basicTwo() // So we find the first one so we can focus this test on just one stack. - return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'basicTwo' && + return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'basicTwo' && entry.dur === 827; }); - const stack = new Timeline.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode); + const stack = new Timeline.EntriesFilter.EntriesFilter(parsedTrace.Renderer.entryToNode); if (!stack) { throw new Error('EntriesFilter does not exist'); } @@ -100,15 +100,15 @@ describeWithEnvironment('EntriesFilter', function () { assert.isTrue(stack.invisibleEntries().includes(entryTwo), 'entryTwo is invisble'); // Get the parent of basicTwo, which is basicStackOne. const basicStackOne = findFirstEntry(mainThread.entries, entry => { - return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'basicStackOne' && + return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'basicStackOne' && entry.dur === 827; }); // Get the parent of basicTwo marked as expandable. assert.isTrue(stack.isEntryExpandable(basicStackOne)); }); it('adds the collapsed entry into the expandableEntries array', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'basic-stack.json.gz'); - const mainThread = getMainThread(traceData.Renderer); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'basic-stack.json.gz'); + const mainThread = getMainThread(parsedTrace.Renderer); /** This stack looks roughly like so (with some events omitted): * ======== basicStackOne ============ * =========== basicTwo ============== @@ -129,10 +129,10 @@ describeWithEnvironment('EntriesFilter', function () { const entryTwo = findFirstEntry(mainThread.entries, entry => { // Processing this trace ends up with two distinct stacks for basicTwo() // So we find the first one so we can focus this test on just one stack. - return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'basicTwo' && + return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'basicTwo' && entry.dur === 827; }); - const stack = new Timeline.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode); + const stack = new Timeline.EntriesFilter.EntriesFilter(parsedTrace.Renderer.entryToNode); if (!stack) { throw new Error('EntriesFilter does not exist'); } @@ -141,8 +141,8 @@ describeWithEnvironment('EntriesFilter', function () { assert.isTrue(stack.isEntryExpandable(entryTwo)); }); it('adds the next visible parent of the merged entry into the expandableEntries array if the direct parent is hidden', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'two-functions-recursion.json.gz'); - const mainThread = getMainThread(traceData.Renderer); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'two-functions-recursion.json.gz'); + const mainThread = getMainThread(parsedTrace.Renderer); /** This stack looks roughly like so (with some events omitted): * ======== onclick ============ * =========== foo ============= @@ -172,19 +172,18 @@ describeWithEnvironment('EntriesFilter', function () { * **/ const firstFooCallEntry = findFirstEntry(mainThread.entries, entry => { - return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'foo' && - entry.dur === 233; + return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'foo' && entry.dur === 233; }); - const firstFooCallEndTime = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(firstFooCallEntry).endTime; + const firstFooCallEndTime = Trace.Helpers.Timing.eventTimingsMicroSeconds(firstFooCallEntry).endTime; const fooCalls = mainThread.entries.filter(entry => { - const isFooCall = TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'foo'; + const isFooCall = Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'foo'; if (!isFooCall) { return false; } - const { endTime } = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(entry); + const { endTime } = Trace.Helpers.Timing.eventTimingsMicroSeconds(entry); return endTime <= firstFooCallEndTime; }); - const stack = new Timeline.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode); + const stack = new Timeline.EntriesFilter.EntriesFilter(parsedTrace.Renderer.entryToNode); if (!stack) { throw new Error('EntriesFilter does not exist'); } @@ -205,11 +204,11 @@ describeWithEnvironment('EntriesFilter', function () { }); assert.isTrue(allFooExceptFirstInStackAreHidden, 'First foo is invisible or some following foo calls are still visible'); const foo2Calls = mainThread.entries.filter(entry => { - const isFoo2Call = TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'foo2'; + const isFoo2Call = Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'foo2'; if (!isFoo2Call) { return false; } - const { endTime } = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(entry); + const { endTime } = Trace.Helpers.Timing.eventTimingsMicroSeconds(entry); return endTime <= firstFooCallEndTime; }); // Merge second foo2 entry. @@ -218,8 +217,8 @@ describeWithEnvironment('EntriesFilter', function () { assert.isTrue(stack.isEntryExpandable(foo2Calls[0])); }); it('supports collapsing an entry', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'basic-stack.json.gz'); - const mainThread = getMainThread(traceData.Renderer); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'basic-stack.json.gz'); + const mainThread = getMainThread(parsedTrace.Renderer); /** This stack looks roughly like so (with some events omitted): * ======== basicStackOne ============ * =========== basicTwo ============== @@ -239,22 +238,22 @@ describeWithEnvironment('EntriesFilter', function () { const basicTwoCallEntry = findFirstEntry(mainThread.entries, entry => { // Processing this trace ends up with two distinct stacks for basicTwo() // So we find the first one so we can focus this test on just one stack. - return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'basicTwo' && + return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'basicTwo' && entry.dur === 827; }); // Gather the fib() calls under the first basicTwo stack, by finding all // the calls whose end time is less than or equal to the end time of the // `basicTwo` function. const fibonacciCalls = mainThread.entries.filter(entry => { - const isFibCall = TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'fibonacci'; + const isFibCall = Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'fibonacci'; if (!isFibCall) { return false; } - const { endTime } = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(entry); - const basicTwoCallEndTime = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(basicTwoCallEntry).endTime; + const { endTime } = Trace.Helpers.Timing.eventTimingsMicroSeconds(entry); + const basicTwoCallEndTime = Trace.Helpers.Timing.eventTimingsMicroSeconds(basicTwoCallEntry).endTime; return endTime <= basicTwoCallEndTime; }); - const stack = new Timeline.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode); + const stack = new Timeline.EntriesFilter.EntriesFilter(parsedTrace.Renderer.entryToNode); if (!stack) { throw new Error('EntriesFilter does not exist'); } @@ -268,8 +267,8 @@ describeWithEnvironment('EntriesFilter', function () { assert.isTrue(allFibonacciInStackAreHidden, 'Some fibonacci calls are still visible'); }); it('supports collapsing all repeating entries among descendants', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'two-functions-recursion.json.gz'); - const mainThread = getMainThread(traceData.Renderer); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'two-functions-recursion.json.gz'); + const mainThread = getMainThread(parsedTrace.Renderer); /** This stack looks roughly like so (with some events omitted): * ======== onclick ============ * =========== foo ============= @@ -289,29 +288,28 @@ describeWithEnvironment('EntriesFilter', function () { * ==== foo2 ===== **/ const firstFooCallEntry = findFirstEntry(mainThread.entries, entry => { - return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'foo' && - entry.dur === 233; + return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'foo' && entry.dur === 233; }); // Gather the foo() and foo2() calls under and including the first foo entry, by finding all // the calls whose end time is less than or equal to the end time of the first `foo` function. - const firstFooCallEndTime = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(firstFooCallEntry).endTime; + const firstFooCallEndTime = Trace.Helpers.Timing.eventTimingsMicroSeconds(firstFooCallEntry).endTime; const fooCalls = mainThread.entries.filter(entry => { - const isFooCall = TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'foo'; + const isFooCall = Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'foo'; if (!isFooCall) { return false; } - const { endTime } = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(entry); + const { endTime } = Trace.Helpers.Timing.eventTimingsMicroSeconds(entry); return endTime <= firstFooCallEndTime; }); const foo2Calls = mainThread.entries.filter(entry => { - const isFoo2Call = TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'foo2'; + const isFoo2Call = Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'foo2'; if (!isFoo2Call) { return false; } - const { endTime } = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(entry); + const { endTime } = Trace.Helpers.Timing.eventTimingsMicroSeconds(entry); return endTime <= firstFooCallEndTime; }); - const stack = new Timeline.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode); + const stack = new Timeline.EntriesFilter.EntriesFilter(parsedTrace.Renderer.entryToNode); if (!stack) { throw new Error('EntriesFilter does not exist'); } @@ -333,8 +331,8 @@ describeWithEnvironment('EntriesFilter', function () { assert.isTrue(allFoo2InStackAreVisible, 'Some foo2 calls are invisible'); }); it('supports undo all filter actions by applying context menu undo action', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'basic-stack.json.gz'); - const mainThread = getMainThread(traceData.Renderer); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'basic-stack.json.gz'); + const mainThread = getMainThread(parsedTrace.Renderer); /** This stack looks roughly like so (with some events omitted): * ======== basicStackOne ============ * =========== basicTwo ============== @@ -364,23 +362,23 @@ describeWithEnvironment('EntriesFilter', function () { * * Applying 'undo all actions' should bring the stack to the original state. **/ - const stack = new Timeline.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode); + const stack = new Timeline.EntriesFilter.EntriesFilter(parsedTrace.Renderer.entryToNode); if (!stack) { throw new Error('EntriesFilter does not exist'); } const basicTwoCallEntry = findFirstEntry(mainThread.entries, entry => { // Processing this trace ends up with two distinct stacks for basicTwo() // So we find the first one so we can focus this test on just one stack. - return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'basicTwo' && + return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'basicTwo' && entry.dur === 827; }); const fibonacciCalls = mainThread.entries.filter(entry => { - const isFibCall = TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'fibonacci'; + const isFibCall = Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'fibonacci'; if (!isFibCall) { return false; } - const { endTime } = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(entry); - const basicTwoCallEndTime = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(basicTwoCallEntry).endTime; + const { endTime } = Trace.Helpers.Timing.eventTimingsMicroSeconds(entry); + const basicTwoCallEndTime = Trace.Helpers.Timing.eventTimingsMicroSeconds(basicTwoCallEntry).endTime; return endTime <= basicTwoCallEndTime; }); // Collapse all repeating descendants of the first fibonacci call: @@ -397,7 +395,7 @@ describeWithEnvironment('EntriesFilter', function () { assert.isTrue(allFibExceptFirstInStackAreHidden, 'First fib is invisible or some following fib calls are still visible'); // Merge basicStackOne: const basicStackOne = findFirstEntry(mainThread.entries, entry => { - return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'basicStackOne' && + return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'basicStackOne' && entry.dur === 827; }); stack.applyFilterAction({ type: "MERGE_FUNCTION" /* PerfUI.FlameChart.FilterAction.MERGE_FUNCTION */, entry: basicStackOne }); @@ -406,7 +404,7 @@ describeWithEnvironment('EntriesFilter', function () { stack.applyFilterAction({ type: "COLLAPSE_FUNCTION" /* PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION */, entry: basicTwoCallEntry }); // basicThree and first fibnacci should now be hidden: const basicThree = findFirstEntry(mainThread.entries, entry => { - return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'basicThree' && + return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'basicThree' && entry.dur === 827; }); assert.isTrue(stack.invisibleEntries().includes(basicThree), 'basicThree is visble'); @@ -418,8 +416,8 @@ describeWithEnvironment('EntriesFilter', function () { assert.strictEqual(stack.invisibleEntries().length, 0); }); it('supports resetting children of the closest expandable parent when a hidden entry is provided', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'basic-stack.json.gz'); - const mainThread = getMainThread(traceData.Renderer); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'basic-stack.json.gz'); + const mainThread = getMainThread(parsedTrace.Renderer); /** This stack looks roughly like so (with some events omitted): * ======== basicStackOne ============ * =========== basicTwo ============== @@ -449,14 +447,14 @@ describeWithEnvironment('EntriesFilter', function () { * * This should result in all basicTwo children being removed from the invisible array and stack being in the initial state. **/ - const stack = new Timeline.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode); + const stack = new Timeline.EntriesFilter.EntriesFilter(parsedTrace.Renderer.entryToNode); if (!stack) { throw new Error('EntriesFilter does not exist'); } const basicTwoCallEntry = findFirstEntry(mainThread.entries, entry => { // Processing this trace ends up with two distinct stacks for basicTwo() // So we find the first one so we can focus this test on just one stack. - return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'basicTwo' && + return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'basicTwo' && entry.dur === 827; }); // Make sure no entries are hidden @@ -467,7 +465,7 @@ describeWithEnvironment('EntriesFilter', function () { assert.strictEqual(stack.invisibleEntries().length, 37); // Get the first fibonacci call that is one of the hidden children and make sure it is hidden const firstFibCallEntry = findFirstEntry(mainThread.entries, entry => { - return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'fibonacci'; + return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'fibonacci'; }); assert.isTrue(stack.invisibleEntries().includes(firstFibCallEntry)); // Reveal the first fibonacci call and make sure that the all of the entries are now visible because the closest @@ -476,8 +474,8 @@ describeWithEnvironment('EntriesFilter', function () { assert.strictEqual(stack.invisibleEntries().length, 0); }); it('supports resetting all hidden children of a selected entry', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'two-functions-recursion.json.gz'); - const mainThread = getMainThread(traceData.Renderer); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'two-functions-recursion.json.gz'); + const mainThread = getMainThread(parsedTrace.Renderer); /** This stack looks roughly like so (with some events omitted): * ======== onclick ============ * =========== foo ============= @@ -509,29 +507,28 @@ describeWithEnvironment('EntriesFilter', function () { * are visible, but the entries hidden above the entry children were reset on stay hidden. **/ const firstFooCallEntry = findFirstEntry(mainThread.entries, entry => { - return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'foo' && - entry.dur === 233; + return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'foo' && entry.dur === 233; }); // Gather the foo() and foo2() calls under and including the first foo entry, by finding all // the calls whose end time is less than or equal to the end time of the first `foo` function. - const firstFooCallEndTime = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(firstFooCallEntry).endTime; + const firstFooCallEndTime = Trace.Helpers.Timing.eventTimingsMicroSeconds(firstFooCallEntry).endTime; const fooCalls = mainThread.entries.filter(entry => { - const isFooCall = TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'foo'; + const isFooCall = Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'foo'; if (!isFooCall) { return false; } - const { endTime } = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(entry); + const { endTime } = Trace.Helpers.Timing.eventTimingsMicroSeconds(entry); return endTime <= firstFooCallEndTime; }); const foo2Calls = mainThread.entries.filter(entry => { - const isFoo2Call = TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'foo2'; + const isFoo2Call = Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'foo2'; if (!isFoo2Call) { return false; } - const { endTime } = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(entry); + const { endTime } = Trace.Helpers.Timing.eventTimingsMicroSeconds(entry); return endTime <= firstFooCallEndTime; }); - const stack = new Timeline.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode); + const stack = new Timeline.EntriesFilter.EntriesFilter(parsedTrace.Renderer.entryToNode); if (!stack) { throw new Error('EntriesFilter does not exist'); } @@ -569,8 +566,8 @@ describeWithEnvironment('EntriesFilter', function () { assert.isTrue(allFooExceptSecondInStackAreVisible, 'Some foo calls except the second one are invisible or the second one is visible'); }); it('correctly returns the amount of hidden children of a node', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'two-functions-recursion.json.gz'); - const mainThread = getMainThread(traceData.Renderer); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'two-functions-recursion.json.gz'); + const mainThread = getMainThread(parsedTrace.Renderer); /** This stack looks roughly like so (with some erlier events omitted): * ======== onclick ============ * =========== foo ============= @@ -591,10 +588,9 @@ describeWithEnvironment('EntriesFilter', function () { * ==== foo2 ===== **/ const firstFooCallEntry = findFirstEntry(mainThread.entries, entry => { - return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'foo' && - entry.dur === 233; + return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'foo' && entry.dur === 233; }); - const stack = new Timeline.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode); + const stack = new Timeline.EntriesFilter.EntriesFilter(parsedTrace.Renderer.entryToNode); if (!stack) { throw new Error('EntriesFilter does not exist'); } @@ -605,8 +601,8 @@ describeWithEnvironment('EntriesFilter', function () { assert.strictEqual(stack.findHiddenDescendantsAmount(firstFooCallEntry), 3); }); it('correctly assigns a visible parent to expandable entries if the direct parent is not visible', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'basic-stack.json.gz'); - const mainThread = getMainThread(traceData.Renderer); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'basic-stack.json.gz'); + const mainThread = getMainThread(parsedTrace.Renderer); /** This stack looks roughly like so (with some events omitted): * ======== Task =============== * ======== (anonymous) ======== << entry with an invisible in the timeline direct parent. We need to make sure that we correctly add Task to the expandable entries @@ -614,9 +610,9 @@ describeWithEnvironment('EntriesFilter', function () { * ======== postMessage ======== **/ const anonymousEntryWithInvisibleParent = findFirstEntry(mainThread.entries, entry => { - return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.nodeId === 42; + return Trace.Types.Events.isProfileCall(entry) && entry.nodeId === 42; }); - const stack = new Timeline.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode); + const stack = new Timeline.EntriesFilter.EntriesFilter(parsedTrace.Renderer.entryToNode); if (!stack) { throw new Error('EntriesFilter does not exist'); } diff --git a/public/panels/timeline/EntriesFilter.test.js.map b/public/panels/timeline/EntriesFilter.test.js.map index 39110b659..d2b30c4b7 100644 --- a/public/panels/timeline/EntriesFilter.test.js.map +++ b/public/panels/timeline/EntriesFilter.test.js.map @@ -1 +1 @@ -{"version":3,"file":"EntriesFilter.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/EntriesFilter.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// Copyright 2023222 The Chromium Author2s. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as Timeline from './timeline.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\n\nimport {TraceLoader} from '../../testing/TraceLoader.js';\nimport {getMainThread} from '../../testing/TraceHelpers.js';\nimport { describeWithEnvironment } from '../../testing/EnvironmentHelpers.js';\n\nfunction findFirstEntry(\n allEntries: readonly TraceEngine.Types.TraceEvents.TraceEventData[],\n predicate: (entry: TraceEngine.Types.TraceEvents.TraceEventData) =>\n boolean): TraceEngine.Types.TraceEvents.TraceEventData {\n const entry = allEntries.find(entry => predicate(entry));\n if (!entry) {\n throw new Error('Could not find expected entry.');\n }\n return entry;\n}\n\ndescribeWithEnvironment('EntriesFilter', function() {\n it('parses a stack and returns an empty list of invisible entries', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'basic-stack.json.gz');\n const stack = new Timeline.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode);\n assert.deepEqual([], stack?.invisibleEntries());\n });\n\n it('supports the user merging an entry into its parent', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'basic-stack.json.gz');\n const mainThread = getMainThread(traceData.Renderer);\n /** This stack looks roughly like so (with some events omitted):\n * ======== basicStackOne ============\n * =========== basicTwo ==============\n * =========== basicThree ============\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ==== fibonacci ===\n *\n * In this test we want to test the user merging basicTwo into its parent, so the resulting trace should look like so:\n * ======== basicStackOne ============\n * =========== basicThree ============ << No more basicTwo, it has been merged.\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ==== fibonacci ===\n *\n **/\n const entryTwo = findFirstEntry(mainThread.entries, entry => {\n // Processing this trace ends up with two distinct stacks for basicTwo()\n // So we find the first one so we can focus this test on just one stack.\n return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'basicTwo' &&\n entry.dur === 827;\n });\n const stack = new Timeline.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode);\n if (!stack) {\n throw new Error('EntriesFilter does not exist');\n }\n stack.applyFilterAction({type: PerfUI.FlameChart.FilterAction.MERGE_FUNCTION, entry: entryTwo});\n assert.isTrue(stack.invisibleEntries().includes(entryTwo), 'entryTwo is invisble');\n // Only one entry - the one for the `basicTwo` function - should have been hidden.\n assert.strictEqual(stack.invisibleEntries().length, 1);\n });\n\n it('adds the parent of the merged entry into the expandableEntries array', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'basic-stack.json.gz');\n const mainThread = getMainThread(traceData.Renderer);\n /** This stack looks roughly like so (with some events omitted):\n * ======== basicStackOne ============\n * =========== basicTwo ==============\n * =========== basicThree ============\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n *\n * In this test we want to test that the parent of the merged entry is added to the expandableEntries array,\n * so that later an array decoration is added to it and the merged entry could be shown again if the array is clicked.\n * the user merging basicTwo into its parent, so the resulting trace should look like so:\n * ======== basicStackOne ============ << As parent of basicTwo, it belongs to the expandableEntries array\n * =========== basicThree ============ << No more basicTwo, it has been merged.\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n *\n **/\n const entryTwo = findFirstEntry(mainThread.entries, entry => {\n // Processing this trace ends up with two distinct stacks for basicTwo()\n // So we find the first one so we can focus this test on just one stack.\n return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'basicTwo' &&\n entry.dur === 827;\n });\n const stack = new Timeline.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode);\n if (!stack) {\n throw new Error('EntriesFilter does not exist');\n }\n stack.applyFilterAction({type: PerfUI.FlameChart.FilterAction.MERGE_FUNCTION, entry: entryTwo});\n assert.isTrue(stack.invisibleEntries().includes(entryTwo), 'entryTwo is invisble');\n\n // Get the parent of basicTwo, which is basicStackOne.\n const basicStackOne = findFirstEntry(mainThread.entries, entry => {\n return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'basicStackOne' &&\n entry.dur === 827;\n });\n // Get the parent of basicTwo marked as expandable.\n assert.isTrue(stack.isEntryExpandable(basicStackOne));\n });\n\n it('adds the collapsed entry into the expandableEntries array', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'basic-stack.json.gz');\n const mainThread = getMainThread(traceData.Renderer);\n /** This stack looks roughly like so (with some events omitted):\n * ======== basicStackOne ============\n * =========== basicTwo ==============\n * =========== basicThree ============\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n *\n * In this test we want to test that the collapsed entry is added to the expandableEntries array,\n * so that later an arrow decoration is added to it and the collapsed entries could be shown again if the arraw is clicked.\n *\n * The user collapses basicTwo, so the resulting trace should look like so:\n * ======== basicStackOne ============\n * =========== basicTwo ============ << All entries under basicTwo merged collapsed and it belongs to the expandableEntries array\n *\n **/\n const entryTwo = findFirstEntry(mainThread.entries, entry => {\n // Processing this trace ends up with two distinct stacks for basicTwo()\n // So we find the first one so we can focus this test on just one stack.\n return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'basicTwo' &&\n entry.dur === 827;\n });\n const stack = new Timeline.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode);\n if (!stack) {\n throw new Error('EntriesFilter does not exist');\n }\n stack.applyFilterAction({type: PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION, entry: entryTwo});\n // basicTwo is marked as expandable.\n assert.isTrue(stack.isEntryExpandable(entryTwo));\n });\n\n it('adds the next visible parent of the merged entry into the expandableEntries array if the direct parent is hidden',\n async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'two-functions-recursion.json.gz');\n const mainThread = getMainThread(traceData.Renderer);\n /** This stack looks roughly like so (with some events omitted):\n * ======== onclick ============\n * =========== foo =============\n * ==== foo2 =====\n * ===== foo =====\n * ==== foo2 =====\n * ===== foo =====\n * ==== foo2 =====\n * ===== foo =====\n *\n * In this test we want to test that the next visible parent of the merged entry is added to the\n * expandableEntries array even if the direct one is hidden by some other action,\n * so that later an array decoration is added to it and the merged entry could be shown again if the array is clicked.\n *\n * collapse all repeating calls of foo after the first one:\n * ======== onclick ============\n * =========== foo ============= << all foo except first removed\n * ===== foo2 ====\n * ==== foo2 ===== << direct parent is not visible anymore\n * ==== foo2 =====\n *\n * merge second foo2 and add the next visible parent to the expandableEntries array:\n * ======== onclick ============\n * =========== foo =============\n * ===== foo2 ==== << added to expandableEntries as the next visible parent of the merged entry\n * ==== foo2 =====\n *\n **/\n const firstFooCallEntry = findFirstEntry(mainThread.entries, entry => {\n return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'foo' &&\n entry.dur === 233;\n });\n const firstFooCallEndTime = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(firstFooCallEntry).endTime;\n const fooCalls = mainThread.entries.filter(entry => {\n const isFooCall = TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'foo';\n if (!isFooCall) {\n return false;\n }\n const {endTime} = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(entry);\n return endTime <= firstFooCallEndTime;\n });\n const stack = new Timeline.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode);\n if (!stack) {\n throw new Error('EntriesFilter does not exist');\n }\n // Collapse all foo calls after the first one.\n stack.applyFilterAction({\n type: PerfUI.FlameChart.FilterAction.COLLAPSE_REPEATING_DESCENDANTS,\n entry: firstFooCallEntry,\n });\n\n // First foo call is marked as expandable since its' children are hidden.\n assert.isTrue(stack.isEntryExpandable(firstFooCallEntry));\n\n // Make sure all foo calls after first are hidden.\n const allFooExceptFirstInStackAreHidden = fooCalls.every((fooCall, i) => {\n if (i === 0) {\n // First foo should not be invisible.\n return !stack.invisibleEntries().includes(fooCall);\n }\n return stack.invisibleEntries().includes(fooCall);\n });\n assert.isTrue(\n allFooExceptFirstInStackAreHidden, 'First foo is invisible or some following foo calls are still visible');\n\n const foo2Calls = mainThread.entries.filter(entry => {\n const isFoo2Call =\n TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'foo2';\n if (!isFoo2Call) {\n return false;\n }\n const {endTime} = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(entry);\n return endTime <= firstFooCallEndTime;\n });\n\n // Merge second foo2 entry.\n stack.applyFilterAction({type: PerfUI.FlameChart.FilterAction.MERGE_FUNCTION, entry: foo2Calls[1]});\n // First foo2 entry should be in the expandableEntries array.\n assert.isTrue(stack.isEntryExpandable(foo2Calls[0]));\n });\n\n it('supports collapsing an entry', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'basic-stack.json.gz');\n const mainThread = getMainThread(traceData.Renderer);\n /** This stack looks roughly like so (with some events omitted):\n * ======== basicStackOne ============\n * =========== basicTwo ==============\n * =========== basicThree ============\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ==== fibonacci ===\n *\n * In this test we want to test the user collapsing basicTwo, which should have the effect of keeping basicTwo visible, but removing all of its children:\n * ======== basicStackOne ============\n * =========== basicTwo ==============\n * << all children removed\n **/\n const basicTwoCallEntry = findFirstEntry(mainThread.entries, entry => {\n // Processing this trace ends up with two distinct stacks for basicTwo()\n // So we find the first one so we can focus this test on just one stack.\n return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'basicTwo' &&\n entry.dur === 827;\n });\n\n // Gather the fib() calls under the first basicTwo stack, by finding all\n // the calls whose end time is less than or equal to the end time of the\n // `basicTwo` function.\n const fibonacciCalls = mainThread.entries.filter(entry => {\n const isFibCall =\n TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'fibonacci';\n if (!isFibCall) {\n return false;\n }\n const {endTime} = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(entry);\n const basicTwoCallEndTime = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(basicTwoCallEntry).endTime;\n return endTime <= basicTwoCallEndTime;\n });\n const stack = new Timeline.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode);\n if (!stack) {\n throw new Error('EntriesFilter does not exist');\n }\n stack.applyFilterAction({type: PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION, entry: basicTwoCallEntry});\n\n // We collapsed at the `basicTwo` entry - so it should not be included in the invisible list itself.\n assert.isFalse(stack.invisibleEntries().includes(basicTwoCallEntry), 'entryTwo is not visible');\n // But all fib() calls below it in the stack should now be invisible.\n const allFibonacciInStackAreHidden = fibonacciCalls.every(fibCall => {\n return stack.invisibleEntries().includes(fibCall);\n });\n assert.isTrue(allFibonacciInStackAreHidden, 'Some fibonacci calls are still visible');\n });\n\n it('supports collapsing all repeating entries among descendants', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'two-functions-recursion.json.gz');\n const mainThread = getMainThread(traceData.Renderer);\n /** This stack looks roughly like so (with some events omitted):\n * ======== onclick ============\n * =========== foo =============\n * ==== foo2 =====\n * ===== foo =====\n * ==== foo2 =====\n * ===== foo =====\n * ==== foo2 =====\n * ===== foo =====\n *\n * In this test we want to test the user collapsing all descendant foo calls of the first first one,\n * which should have the effect of keeping the first foo visible, but removing all of its other calls:\n * ======== onclick ============\n * =========== foo =============\n * ===== foo2 ==== << all foo except first removed\n * ==== foo2 =====\n * ==== foo2 =====\n **/\n\n const firstFooCallEntry = findFirstEntry(mainThread.entries, entry => {\n return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'foo' &&\n entry.dur === 233;\n });\n\n // Gather the foo() and foo2() calls under and including the first foo entry, by finding all\n // the calls whose end time is less than or equal to the end time of the first `foo` function.\n const firstFooCallEndTime = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(firstFooCallEntry).endTime;\n const fooCalls = mainThread.entries.filter(entry => {\n const isFooCall = TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'foo';\n if (!isFooCall) {\n return false;\n }\n const {endTime} = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(entry);\n return endTime <= firstFooCallEndTime;\n });\n\n const foo2Calls = mainThread.entries.filter(entry => {\n const isFoo2Call = TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'foo2';\n if (!isFoo2Call) {\n return false;\n }\n const {endTime} = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(entry);\n return endTime <= firstFooCallEndTime;\n });\n\n const stack = new Timeline.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode);\n if (!stack) {\n throw new Error('EntriesFilter does not exist');\n }\n stack.applyFilterAction(\n {type: PerfUI.FlameChart.FilterAction.COLLAPSE_REPEATING_DESCENDANTS, entry: firstFooCallEntry});\n\n // We collapsed identical descendants after the first `foo` entry - so it should not be included in the invisible list itself,\n // but all foo() calls below it in the stack should now be invisible.\n const allFooExceptFirstInStackAreHidden = fooCalls.every((fooCall, i) => {\n if (i === 0) {\n // First foo should not be invisible.\n return !stack.invisibleEntries().includes(fooCall);\n }\n return stack.invisibleEntries().includes(fooCall);\n });\n assert.isTrue(\n allFooExceptFirstInStackAreHidden, 'First foo is invisible or some following foo calls are still visible');\n\n // All of the foo2 calls that were inbetween foo calls should still be visible.\n const allFoo2InStackAreVisible = foo2Calls.every(fooCall => {\n return !stack.invisibleEntries().includes(fooCall);\n });\n assert.isTrue(allFoo2InStackAreVisible, 'Some foo2 calls are invisible');\n });\n\n it('supports undo all filter actions by applying context menu undo action', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'basic-stack.json.gz');\n const mainThread = getMainThread(traceData.Renderer);\n /** This stack looks roughly like so (with some events omitted):\n * ======== basicStackOne ============\n * =========== basicTwo ==============\n * =========== basicThree ============\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ==== fibonacci ===\n *\n * In this test we want to test the user undoing all actions with 'undo all actions' after applying merge, collapse repeating descendants and collapse function.\n *\n * First, collapse all repeating descendants of the first fibonacci call:\n * ======== basicStackOne ============\n * =========== basicTwo ==============\n * =========== basicThree ============\n * ======== fibonacci === << repeating children removed\n *\n * Then, merge basicStackOne:\n * =========== basicTwo ==============\n * =========== basicThree ============\n * ======== fibonacci ===\n *\n * Finally, collapse basicTwo():\n * =========== basicTwo ==============\n *\n * Applying 'undo all actions' should bring the stack to the original state.\n **/\n\n const stack = new Timeline.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode);\n if (!stack) {\n throw new Error('EntriesFilter does not exist');\n }\n const basicTwoCallEntry = findFirstEntry(mainThread.entries, entry => {\n // Processing this trace ends up with two distinct stacks for basicTwo()\n // So we find the first one so we can focus this test on just one stack.\n return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'basicTwo' &&\n entry.dur === 827;\n });\n const fibonacciCalls = mainThread.entries.filter(entry => {\n const isFibCall =\n TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'fibonacci';\n if (!isFibCall) {\n return false;\n }\n const {endTime} = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(entry);\n const basicTwoCallEndTime = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(basicTwoCallEntry).endTime;\n return endTime <= basicTwoCallEndTime;\n });\n\n // Collapse all repeating descendants of the first fibonacci call:\n stack.applyFilterAction(\n {type: PerfUI.FlameChart.FilterAction.COLLAPSE_REPEATING_DESCENDANTS, entry: fibonacciCalls[0]});\n // We collapsed identical descendants after the first `foo` entry - so it should not be included in the invisible list itself,\n // but all foo() calls below it in the stack should now be invisible.\n const allFibExceptFirstInStackAreHidden = fibonacciCalls.every((fibCall, i) => {\n if (i === 0) {\n // First foo should not be invisible.\n return !stack.invisibleEntries().includes(fibCall);\n }\n return stack.invisibleEntries().includes(fibCall);\n });\n assert.isTrue(\n allFibExceptFirstInStackAreHidden, 'First fib is invisible or some following fib calls are still visible');\n\n // Merge basicStackOne:\n const basicStackOne = findFirstEntry(mainThread.entries, entry => {\n return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'basicStackOne' &&\n entry.dur === 827;\n });\n stack.applyFilterAction({type: PerfUI.FlameChart.FilterAction.MERGE_FUNCTION, entry: basicStackOne});\n assert.isTrue(stack.invisibleEntries().includes(basicStackOne), 'entrybasicStackOneTwo is visble');\n\n // Collapse basicTwo():\n stack.applyFilterAction({type: PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION, entry: basicTwoCallEntry});\n // basicThree and first fibnacci should now be hidden:\n const basicThree = findFirstEntry(mainThread.entries, entry => {\n return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'basicThree' &&\n entry.dur === 827;\n });\n assert.isTrue(stack.invisibleEntries().includes(basicThree), 'basicThree is visble');\n assert.isTrue(stack.invisibleEntries().includes(fibonacciCalls[0]), 'first fibonacci is visble');\n\n // Apply UNDO_ALL_ACTIONS to bring back all of the hidden entries:\n // UNDO_ALL_ACTIONS can be called on any visible entry\n stack.applyFilterAction({type: PerfUI.FlameChart.FilterAction.UNDO_ALL_ACTIONS, entry: basicTwoCallEntry});\n // If the length of invisibleEntries list is 0, all of the entries added earlier were removed and are now visible.\n assert.strictEqual(stack.invisibleEntries().length, 0);\n });\n\n it('supports resetting children of the closest expandable parent when a hidden entry is provided', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'basic-stack.json.gz');\n const mainThread = getMainThread(traceData.Renderer);\n /** This stack looks roughly like so (with some events omitted):\n * ======== basicStackOne ============\n * =========== basicTwo ==============\n * =========== basicThree ============\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ==== fibonacci ===\n *\n * In this test we want to test the user selecting an entry that is hidden via a link.\n * If this happens, we should reveal this entry to resetting children of the closest expandable parent.\n *\n * First, collapse all children of the basicTwo:\n * ======== basicStackOne ============\n * =========== basicTwo ============== << children collapsed\n * =========== basicThree ============\n * ======== fibonacci === << repeating children removed\n *\n * Then, reveal the first fibonacci entry that is hidden:\n * ======== basicStackOne ============\n * =========== basicTwo ==============\n * =========== basicThree ============\n * ======== fibonacci === << reveal this hidden entry\n * ======== fibonacci ===\n *\n * This should result in all basicTwo children being removed from the invisible array and stack being in the initial state.\n **/\n\n const stack = new Timeline.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode);\n if (!stack) {\n throw new Error('EntriesFilter does not exist');\n }\n const basicTwoCallEntry = findFirstEntry(mainThread.entries, entry => {\n // Processing this trace ends up with two distinct stacks for basicTwo()\n // So we find the first one so we can focus this test on just one stack.\n return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'basicTwo' &&\n entry.dur === 827;\n });\n\n // Make sure no entries are hidden\n assert.strictEqual(stack.invisibleEntries().length, 0);\n\n // Collapse all children of basicTwo call:\n stack.applyFilterAction({type: PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION, entry: basicTwoCallEntry});\n\n // Make sure all 37 of basicTwo descdendants are hidden\n assert.strictEqual(stack.invisibleEntries().length, 37);\n\n // Get the first fibonacci call that is one of the hidden children and make sure it is hidden\n const firstFibCallEntry = findFirstEntry(mainThread.entries, entry => {\n return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'fibonacci';\n });\n\n assert.isTrue(stack.invisibleEntries().includes(firstFibCallEntry));\n\n // Reveal the first fibonacci call and make sure that the all of the entries are now visible because the closest\n // expandable parent to the fib call is basicTwo and, therefore, we need to reset its children.\n stack.revealEntry(firstFibCallEntry);\n assert.strictEqual(stack.invisibleEntries().length, 0);\n });\n\n it('supports resetting all hidden children of a selected entry', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'two-functions-recursion.json.gz');\n const mainThread = getMainThread(traceData.Renderer);\n /** This stack looks roughly like so (with some events omitted):\n * ======== onclick ============\n * =========== foo =============\n * ==== foo2 =====\n * ===== foo =====\n * ==== foo2 =====\n * ===== foo =====\n * ==== foo2 =====\n * ===== foo =====\n *\n * In this test we want to test the user collapsing all descendant foo calls of the first first one,\n * which should have the effect of keeping the first foo visible, but removing all of its other calls:\n * ======== onclick ============\n * =========== foo =============\n * ===== foo2 ==== << all foo except first removed\n * ==== foo2 =====\n * ==== foo2 =====\n *\n * Then, reset children on the second visible foo2.\n * ======== onclick ============\n * =========== foo =============\n * ===== foo2 ==== << foo() after this entry still hidden\n * ==== foo2 ===== << all children from this node are visible\n * ===== foo =====\n * ==== foo2 =====\n * ===== foo =====\n *\n * This results in a stack where all children of an entry children were reset on (second foo2)\n * are visible, but the entries hidden above the entry children were reset on stay hidden.\n **/\n\n const firstFooCallEntry = findFirstEntry(mainThread.entries, entry => {\n return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'foo' &&\n entry.dur === 233;\n });\n\n // Gather the foo() and foo2() calls under and including the first foo entry, by finding all\n // the calls whose end time is less than or equal to the end time of the first `foo` function.\n const firstFooCallEndTime = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(firstFooCallEntry).endTime;\n const fooCalls = mainThread.entries.filter(entry => {\n const isFooCall = TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'foo';\n if (!isFooCall) {\n return false;\n }\n const {endTime} = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(entry);\n return endTime <= firstFooCallEndTime;\n });\n\n const foo2Calls = mainThread.entries.filter(entry => {\n const isFoo2Call = TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'foo2';\n if (!isFoo2Call) {\n return false;\n }\n const {endTime} = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(entry);\n return endTime <= firstFooCallEndTime;\n });\n\n const stack = new Timeline.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode);\n if (!stack) {\n throw new Error('EntriesFilter does not exist');\n }\n stack.applyFilterAction(\n {type: PerfUI.FlameChart.FilterAction.COLLAPSE_REPEATING_DESCENDANTS, entry: firstFooCallEntry});\n\n // We collapsed identical descendants after the first `foo` entry - so it should not be included in the invisible list itself,\n // but all foo() calls below it in the stack should now be invisible.\n const allFooExceptFirstInStackAreHidden = fooCalls.every((fooCall, i) => {\n if (i === 0) {\n // First foo should not be invisible.\n return !stack.invisibleEntries().includes(fooCall);\n }\n return stack.invisibleEntries().includes(fooCall);\n });\n assert.isTrue(\n allFooExceptFirstInStackAreHidden, 'First foo is invisible or some following foo calls are still visible');\n\n // All of the foo2 calls that were inbetween foo calls should still be visible.\n let allFoo2InStackAreVisible = foo2Calls.every(fooCall => {\n return !stack.invisibleEntries().includes(fooCall);\n });\n assert.isTrue(allFoo2InStackAreVisible, 'Some foo2 calls are invisible');\n\n // Reset all children after second foo2 call\n assert.strictEqual(foo2Calls.length, 3);\n stack.applyFilterAction({type: PerfUI.FlameChart.FilterAction.RESET_CHILDREN, entry: foo2Calls[1]});\n\n // All foo and foo2 calls except the second foo cll should now be visible\n allFoo2InStackAreVisible = foo2Calls.every(fooCall => {\n return !stack.invisibleEntries().includes(fooCall);\n });\n assert.isTrue(allFoo2InStackAreVisible, 'Some foo2 calls are invisible');\n\n const allFooExceptSecondInStackAreVisible = fooCalls.every((fooCall, i) => {\n if (i === 1) {\n // Second foo should be invisible.\n return stack.invisibleEntries().includes(fooCall);\n }\n return !stack.invisibleEntries().includes(fooCall);\n });\n assert.isTrue(\n allFooExceptSecondInStackAreVisible,\n 'Some foo calls except the second one are invisible or the second one is visible');\n });\n\n it('correctly returns the amount of hidden children of a node', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'two-functions-recursion.json.gz');\n const mainThread = getMainThread(traceData.Renderer);\n /** This stack looks roughly like so (with some erlier events omitted):\n * ======== onclick ============\n * =========== foo =============\n * ==== foo2 =====\n * ===== foo =====\n * ==== foo2 =====\n * ===== foo =====\n * ==== foo2 =====\n * ===== foo =====\n *\n * In this test we want to test if the amount of hidden children returned is correct:\n * If we collapse repeating children on the first foo call, the 3 child foo calls should be removed.\n * Therefore, the amount of hidden children should be equal to 3.\n * ======== onclick ============\n * =========== foo ============= << all foo except first hidden\n * ===== foo2 ====\n * ==== foo2 =====\n * ==== foo2 =====\n **/\n\n const firstFooCallEntry = findFirstEntry(mainThread.entries, entry => {\n return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'foo' &&\n entry.dur === 233;\n });\n\n const stack = new Timeline.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode);\n if (!stack) {\n throw new Error('EntriesFilter does not exist');\n }\n // Before applying any action on a node, there should be no entries hidden under it\n assert.strictEqual(stack.findHiddenDescendantsAmount(firstFooCallEntry), 0);\n\n stack.applyFilterAction(\n {type: PerfUI.FlameChart.FilterAction.COLLAPSE_REPEATING_DESCENDANTS, entry: firstFooCallEntry});\n\n // There should be 3 foo() entries hidden under the first foo call entry\n assert.strictEqual(stack.findHiddenDescendantsAmount(firstFooCallEntry), 3);\n });\n\n it('correctly assigns a visible parent to expandable entries if the direct parent is not visible', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'basic-stack.json.gz');\n const mainThread = getMainThread(traceData.Renderer);\n /** This stack looks roughly like so (with some events omitted):\n * ======== Task ===============\n * ======== (anonymous) ======== << entry with an invisible in the timeline direct parent. We need to make sure that we correctly add Task to the expandable entries\n * ======== RegisterFrameID ====\n * ======== postMessage ========\n **/\n const anonymousEntryWithInvisibleParent = findFirstEntry(mainThread.entries, entry => {\n return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.nodeId === 42;\n });\n\n const stack = new Timeline.EntriesFilter.EntriesFilter(traceData.Renderer.entryToNode);\n if (!stack) {\n throw new Error('EntriesFilter does not exist');\n }\n\n const taskEntry = findFirstEntry(mainThread.entries, entry => {\n return entry.name === 'RunTask' && entry.dur === 978 && entry.ts === 164397762991;\n });\n\n // Make sure the expandable entries are empty at first\n assert.strictEqual(stack.expandableEntries().length, 0);\n\n // Hide the anonymous function\n stack.applyFilterAction(\n {type: PerfUI.FlameChart.FilterAction.MERGE_FUNCTION, entry: anonymousEntryWithInvisibleParent});\n\n // Make sure Task entry is added to expandable entries\n assert.strictEqual(stack.expandableEntries().length, 1);\n assert.isTrue(stack.expandableEntries().includes(taskEntry));\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"EntriesFilter.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/EntriesFilter.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// Copyright 2023222 The Chromium Author2s. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {getMainThread} from '../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\n\nimport * as Timeline from './timeline.js';\n\nfunction findFirstEntry(\n allEntries: readonly Trace.Types.Events.Event[],\n predicate: (entry: Trace.Types.Events.Event) => boolean): Trace.Types.Events.Event {\n const entry = allEntries.find(entry => predicate(entry));\n if (!entry) {\n throw new Error('Could not find expected entry.');\n }\n return entry;\n}\n\ndescribeWithEnvironment('EntriesFilter', function() {\n it('parses a stack and returns an empty list of invisible entries', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'basic-stack.json.gz');\n const stack = new Timeline.EntriesFilter.EntriesFilter(parsedTrace.Renderer.entryToNode);\n assert.deepEqual([], stack?.invisibleEntries());\n });\n\n it('supports the user merging an entry into its parent', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'basic-stack.json.gz');\n const mainThread = getMainThread(parsedTrace.Renderer);\n /** This stack looks roughly like so (with some events omitted):\n * ======== basicStackOne ============\n * =========== basicTwo ==============\n * =========== basicThree ============\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ==== fibonacci ===\n *\n * In this test we want to test the user merging basicTwo into its parent, so the resulting trace should look like so:\n * ======== basicStackOne ============\n * =========== basicThree ============ << No more basicTwo, it has been merged.\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ==== fibonacci ===\n *\n **/\n const entryTwo = findFirstEntry(mainThread.entries, entry => {\n // Processing this trace ends up with two distinct stacks for basicTwo()\n // So we find the first one so we can focus this test on just one stack.\n return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'basicTwo' &&\n entry.dur === 827;\n });\n const stack = new Timeline.EntriesFilter.EntriesFilter(parsedTrace.Renderer.entryToNode);\n if (!stack) {\n throw new Error('EntriesFilter does not exist');\n }\n stack.applyFilterAction({type: PerfUI.FlameChart.FilterAction.MERGE_FUNCTION, entry: entryTwo});\n assert.isTrue(stack.invisibleEntries().includes(entryTwo), 'entryTwo is invisble');\n // Only one entry - the one for the `basicTwo` function - should have been hidden.\n assert.strictEqual(stack.invisibleEntries().length, 1);\n });\n\n it('adds the parent of the merged entry into the expandableEntries array', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'basic-stack.json.gz');\n const mainThread = getMainThread(parsedTrace.Renderer);\n /** This stack looks roughly like so (with some events omitted):\n * ======== basicStackOne ============\n * =========== basicTwo ==============\n * =========== basicThree ============\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n *\n * In this test we want to test that the parent of the merged entry is added to the expandableEntries array,\n * so that later an array decoration is added to it and the merged entry could be shown again if the array is clicked.\n * the user merging basicTwo into its parent, so the resulting trace should look like so:\n * ======== basicStackOne ============ << As parent of basicTwo, it belongs to the expandableEntries array\n * =========== basicThree ============ << No more basicTwo, it has been merged.\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n *\n **/\n const entryTwo = findFirstEntry(mainThread.entries, entry => {\n // Processing this trace ends up with two distinct stacks for basicTwo()\n // So we find the first one so we can focus this test on just one stack.\n return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'basicTwo' &&\n entry.dur === 827;\n });\n const stack = new Timeline.EntriesFilter.EntriesFilter(parsedTrace.Renderer.entryToNode);\n if (!stack) {\n throw new Error('EntriesFilter does not exist');\n }\n stack.applyFilterAction({type: PerfUI.FlameChart.FilterAction.MERGE_FUNCTION, entry: entryTwo});\n assert.isTrue(stack.invisibleEntries().includes(entryTwo), 'entryTwo is invisble');\n\n // Get the parent of basicTwo, which is basicStackOne.\n const basicStackOne = findFirstEntry(mainThread.entries, entry => {\n return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'basicStackOne' &&\n entry.dur === 827;\n });\n // Get the parent of basicTwo marked as expandable.\n assert.isTrue(stack.isEntryExpandable(basicStackOne));\n });\n\n it('adds the collapsed entry into the expandableEntries array', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'basic-stack.json.gz');\n const mainThread = getMainThread(parsedTrace.Renderer);\n /** This stack looks roughly like so (with some events omitted):\n * ======== basicStackOne ============\n * =========== basicTwo ==============\n * =========== basicThree ============\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n *\n * In this test we want to test that the collapsed entry is added to the expandableEntries array,\n * so that later an arrow decoration is added to it and the collapsed entries could be shown again if the arraw is clicked.\n *\n * The user collapses basicTwo, so the resulting trace should look like so:\n * ======== basicStackOne ============\n * =========== basicTwo ============ << All entries under basicTwo merged collapsed and it belongs to the expandableEntries array\n *\n **/\n const entryTwo = findFirstEntry(mainThread.entries, entry => {\n // Processing this trace ends up with two distinct stacks for basicTwo()\n // So we find the first one so we can focus this test on just one stack.\n return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'basicTwo' &&\n entry.dur === 827;\n });\n const stack = new Timeline.EntriesFilter.EntriesFilter(parsedTrace.Renderer.entryToNode);\n if (!stack) {\n throw new Error('EntriesFilter does not exist');\n }\n stack.applyFilterAction({type: PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION, entry: entryTwo});\n // basicTwo is marked as expandable.\n assert.isTrue(stack.isEntryExpandable(entryTwo));\n });\n\n it('adds the next visible parent of the merged entry into the expandableEntries array if the direct parent is hidden',\n async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'two-functions-recursion.json.gz');\n const mainThread = getMainThread(parsedTrace.Renderer);\n /** This stack looks roughly like so (with some events omitted):\n * ======== onclick ============\n * =========== foo =============\n * ==== foo2 =====\n * ===== foo =====\n * ==== foo2 =====\n * ===== foo =====\n * ==== foo2 =====\n * ===== foo =====\n *\n * In this test we want to test that the next visible parent of the merged entry is added to the\n * expandableEntries array even if the direct one is hidden by some other action,\n * so that later an array decoration is added to it and the merged entry could be shown again if the array is clicked.\n *\n * collapse all repeating calls of foo after the first one:\n * ======== onclick ============\n * =========== foo ============= << all foo except first removed\n * ===== foo2 ====\n * ==== foo2 ===== << direct parent is not visible anymore\n * ==== foo2 =====\n *\n * merge second foo2 and add the next visible parent to the expandableEntries array:\n * ======== onclick ============\n * =========== foo =============\n * ===== foo2 ==== << added to expandableEntries as the next visible parent of the merged entry\n * ==== foo2 =====\n *\n **/\n const firstFooCallEntry = findFirstEntry(mainThread.entries, entry => {\n return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'foo' && entry.dur === 233;\n });\n const firstFooCallEndTime = Trace.Helpers.Timing.eventTimingsMicroSeconds(firstFooCallEntry).endTime;\n const fooCalls = mainThread.entries.filter(entry => {\n const isFooCall = Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'foo';\n if (!isFooCall) {\n return false;\n }\n const {endTime} = Trace.Helpers.Timing.eventTimingsMicroSeconds(entry);\n return endTime <= firstFooCallEndTime;\n });\n const stack = new Timeline.EntriesFilter.EntriesFilter(parsedTrace.Renderer.entryToNode);\n if (!stack) {\n throw new Error('EntriesFilter does not exist');\n }\n // Collapse all foo calls after the first one.\n stack.applyFilterAction({\n type: PerfUI.FlameChart.FilterAction.COLLAPSE_REPEATING_DESCENDANTS,\n entry: firstFooCallEntry,\n });\n\n // First foo call is marked as expandable since its' children are hidden.\n assert.isTrue(stack.isEntryExpandable(firstFooCallEntry));\n\n // Make sure all foo calls after first are hidden.\n const allFooExceptFirstInStackAreHidden = fooCalls.every((fooCall, i) => {\n if (i === 0) {\n // First foo should not be invisible.\n return !stack.invisibleEntries().includes(fooCall);\n }\n return stack.invisibleEntries().includes(fooCall);\n });\n assert.isTrue(\n allFooExceptFirstInStackAreHidden, 'First foo is invisible or some following foo calls are still visible');\n\n const foo2Calls = mainThread.entries.filter(entry => {\n const isFoo2Call = Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'foo2';\n if (!isFoo2Call) {\n return false;\n }\n const {endTime} = Trace.Helpers.Timing.eventTimingsMicroSeconds(entry);\n return endTime <= firstFooCallEndTime;\n });\n\n // Merge second foo2 entry.\n stack.applyFilterAction({type: PerfUI.FlameChart.FilterAction.MERGE_FUNCTION, entry: foo2Calls[1]});\n // First foo2 entry should be in the expandableEntries array.\n assert.isTrue(stack.isEntryExpandable(foo2Calls[0]));\n });\n\n it('supports collapsing an entry', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'basic-stack.json.gz');\n const mainThread = getMainThread(parsedTrace.Renderer);\n /** This stack looks roughly like so (with some events omitted):\n * ======== basicStackOne ============\n * =========== basicTwo ==============\n * =========== basicThree ============\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ==== fibonacci ===\n *\n * In this test we want to test the user collapsing basicTwo, which should have the effect of keeping basicTwo visible, but removing all of its children:\n * ======== basicStackOne ============\n * =========== basicTwo ==============\n * << all children removed\n **/\n const basicTwoCallEntry = findFirstEntry(mainThread.entries, entry => {\n // Processing this trace ends up with two distinct stacks for basicTwo()\n // So we find the first one so we can focus this test on just one stack.\n return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'basicTwo' &&\n entry.dur === 827;\n });\n\n // Gather the fib() calls under the first basicTwo stack, by finding all\n // the calls whose end time is less than or equal to the end time of the\n // `basicTwo` function.\n const fibonacciCalls = mainThread.entries.filter(entry => {\n const isFibCall = Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'fibonacci';\n if (!isFibCall) {\n return false;\n }\n const {endTime} = Trace.Helpers.Timing.eventTimingsMicroSeconds(entry);\n const basicTwoCallEndTime = Trace.Helpers.Timing.eventTimingsMicroSeconds(basicTwoCallEntry).endTime;\n return endTime <= basicTwoCallEndTime;\n });\n const stack = new Timeline.EntriesFilter.EntriesFilter(parsedTrace.Renderer.entryToNode);\n if (!stack) {\n throw new Error('EntriesFilter does not exist');\n }\n stack.applyFilterAction({type: PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION, entry: basicTwoCallEntry});\n\n // We collapsed at the `basicTwo` entry - so it should not be included in the invisible list itself.\n assert.isFalse(stack.invisibleEntries().includes(basicTwoCallEntry), 'entryTwo is not visible');\n // But all fib() calls below it in the stack should now be invisible.\n const allFibonacciInStackAreHidden = fibonacciCalls.every(fibCall => {\n return stack.invisibleEntries().includes(fibCall);\n });\n assert.isTrue(allFibonacciInStackAreHidden, 'Some fibonacci calls are still visible');\n });\n\n it('supports collapsing all repeating entries among descendants', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'two-functions-recursion.json.gz');\n const mainThread = getMainThread(parsedTrace.Renderer);\n /** This stack looks roughly like so (with some events omitted):\n * ======== onclick ============\n * =========== foo =============\n * ==== foo2 =====\n * ===== foo =====\n * ==== foo2 =====\n * ===== foo =====\n * ==== foo2 =====\n * ===== foo =====\n *\n * In this test we want to test the user collapsing all descendant foo calls of the first first one,\n * which should have the effect of keeping the first foo visible, but removing all of its other calls:\n * ======== onclick ============\n * =========== foo =============\n * ===== foo2 ==== << all foo except first removed\n * ==== foo2 =====\n * ==== foo2 =====\n **/\n\n const firstFooCallEntry = findFirstEntry(mainThread.entries, entry => {\n return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'foo' && entry.dur === 233;\n });\n\n // Gather the foo() and foo2() calls under and including the first foo entry, by finding all\n // the calls whose end time is less than or equal to the end time of the first `foo` function.\n const firstFooCallEndTime = Trace.Helpers.Timing.eventTimingsMicroSeconds(firstFooCallEntry).endTime;\n const fooCalls = mainThread.entries.filter(entry => {\n const isFooCall = Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'foo';\n if (!isFooCall) {\n return false;\n }\n const {endTime} = Trace.Helpers.Timing.eventTimingsMicroSeconds(entry);\n return endTime <= firstFooCallEndTime;\n });\n\n const foo2Calls = mainThread.entries.filter(entry => {\n const isFoo2Call = Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'foo2';\n if (!isFoo2Call) {\n return false;\n }\n const {endTime} = Trace.Helpers.Timing.eventTimingsMicroSeconds(entry);\n return endTime <= firstFooCallEndTime;\n });\n\n const stack = new Timeline.EntriesFilter.EntriesFilter(parsedTrace.Renderer.entryToNode);\n if (!stack) {\n throw new Error('EntriesFilter does not exist');\n }\n stack.applyFilterAction(\n {type: PerfUI.FlameChart.FilterAction.COLLAPSE_REPEATING_DESCENDANTS, entry: firstFooCallEntry});\n\n // We collapsed identical descendants after the first `foo` entry - so it should not be included in the invisible list itself,\n // but all foo() calls below it in the stack should now be invisible.\n const allFooExceptFirstInStackAreHidden = fooCalls.every((fooCall, i) => {\n if (i === 0) {\n // First foo should not be invisible.\n return !stack.invisibleEntries().includes(fooCall);\n }\n return stack.invisibleEntries().includes(fooCall);\n });\n assert.isTrue(\n allFooExceptFirstInStackAreHidden, 'First foo is invisible or some following foo calls are still visible');\n\n // All of the foo2 calls that were inbetween foo calls should still be visible.\n const allFoo2InStackAreVisible = foo2Calls.every(fooCall => {\n return !stack.invisibleEntries().includes(fooCall);\n });\n assert.isTrue(allFoo2InStackAreVisible, 'Some foo2 calls are invisible');\n });\n\n it('supports undo all filter actions by applying context menu undo action', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'basic-stack.json.gz');\n const mainThread = getMainThread(parsedTrace.Renderer);\n /** This stack looks roughly like so (with some events omitted):\n * ======== basicStackOne ============\n * =========== basicTwo ==============\n * =========== basicThree ============\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ==== fibonacci ===\n *\n * In this test we want to test the user undoing all actions with 'undo all actions' after applying merge, collapse repeating descendants and collapse function.\n *\n * First, collapse all repeating descendants of the first fibonacci call:\n * ======== basicStackOne ============\n * =========== basicTwo ==============\n * =========== basicThree ============\n * ======== fibonacci === << repeating children removed\n *\n * Then, merge basicStackOne:\n * =========== basicTwo ==============\n * =========== basicThree ============\n * ======== fibonacci ===\n *\n * Finally, collapse basicTwo():\n * =========== basicTwo ==============\n *\n * Applying 'undo all actions' should bring the stack to the original state.\n **/\n\n const stack = new Timeline.EntriesFilter.EntriesFilter(parsedTrace.Renderer.entryToNode);\n if (!stack) {\n throw new Error('EntriesFilter does not exist');\n }\n const basicTwoCallEntry = findFirstEntry(mainThread.entries, entry => {\n // Processing this trace ends up with two distinct stacks for basicTwo()\n // So we find the first one so we can focus this test on just one stack.\n return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'basicTwo' &&\n entry.dur === 827;\n });\n const fibonacciCalls = mainThread.entries.filter(entry => {\n const isFibCall = Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'fibonacci';\n if (!isFibCall) {\n return false;\n }\n const {endTime} = Trace.Helpers.Timing.eventTimingsMicroSeconds(entry);\n const basicTwoCallEndTime = Trace.Helpers.Timing.eventTimingsMicroSeconds(basicTwoCallEntry).endTime;\n return endTime <= basicTwoCallEndTime;\n });\n\n // Collapse all repeating descendants of the first fibonacci call:\n stack.applyFilterAction(\n {type: PerfUI.FlameChart.FilterAction.COLLAPSE_REPEATING_DESCENDANTS, entry: fibonacciCalls[0]});\n // We collapsed identical descendants after the first `foo` entry - so it should not be included in the invisible list itself,\n // but all foo() calls below it in the stack should now be invisible.\n const allFibExceptFirstInStackAreHidden = fibonacciCalls.every((fibCall, i) => {\n if (i === 0) {\n // First foo should not be invisible.\n return !stack.invisibleEntries().includes(fibCall);\n }\n return stack.invisibleEntries().includes(fibCall);\n });\n assert.isTrue(\n allFibExceptFirstInStackAreHidden, 'First fib is invisible or some following fib calls are still visible');\n\n // Merge basicStackOne:\n const basicStackOne = findFirstEntry(mainThread.entries, entry => {\n return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'basicStackOne' &&\n entry.dur === 827;\n });\n stack.applyFilterAction({type: PerfUI.FlameChart.FilterAction.MERGE_FUNCTION, entry: basicStackOne});\n assert.isTrue(stack.invisibleEntries().includes(basicStackOne), 'entrybasicStackOneTwo is visble');\n\n // Collapse basicTwo():\n stack.applyFilterAction({type: PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION, entry: basicTwoCallEntry});\n // basicThree and first fibnacci should now be hidden:\n const basicThree = findFirstEntry(mainThread.entries, entry => {\n return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'basicThree' &&\n entry.dur === 827;\n });\n assert.isTrue(stack.invisibleEntries().includes(basicThree), 'basicThree is visble');\n assert.isTrue(stack.invisibleEntries().includes(fibonacciCalls[0]), 'first fibonacci is visble');\n\n // Apply UNDO_ALL_ACTIONS to bring back all of the hidden entries:\n // UNDO_ALL_ACTIONS can be called on any visible entry\n stack.applyFilterAction({type: PerfUI.FlameChart.FilterAction.UNDO_ALL_ACTIONS, entry: basicTwoCallEntry});\n // If the length of invisibleEntries list is 0, all of the entries added earlier were removed and are now visible.\n assert.strictEqual(stack.invisibleEntries().length, 0);\n });\n\n it('supports resetting children of the closest expandable parent when a hidden entry is provided', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'basic-stack.json.gz');\n const mainThread = getMainThread(parsedTrace.Renderer);\n /** This stack looks roughly like so (with some events omitted):\n * ======== basicStackOne ============\n * =========== basicTwo ==============\n * =========== basicThree ============\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ======== fibonacci ===\n * ==== fibonacci ===\n *\n * In this test we want to test the user selecting an entry that is hidden via a link.\n * If this happens, we should reveal this entry to resetting children of the closest expandable parent.\n *\n * First, collapse all children of the basicTwo:\n * ======== basicStackOne ============\n * =========== basicTwo ============== << children collapsed\n * =========== basicThree ============\n * ======== fibonacci === << repeating children removed\n *\n * Then, reveal the first fibonacci entry that is hidden:\n * ======== basicStackOne ============\n * =========== basicTwo ==============\n * =========== basicThree ============\n * ======== fibonacci === << reveal this hidden entry\n * ======== fibonacci ===\n *\n * This should result in all basicTwo children being removed from the invisible array and stack being in the initial state.\n **/\n\n const stack = new Timeline.EntriesFilter.EntriesFilter(parsedTrace.Renderer.entryToNode);\n if (!stack) {\n throw new Error('EntriesFilter does not exist');\n }\n const basicTwoCallEntry = findFirstEntry(mainThread.entries, entry => {\n // Processing this trace ends up with two distinct stacks for basicTwo()\n // So we find the first one so we can focus this test on just one stack.\n return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'basicTwo' &&\n entry.dur === 827;\n });\n\n // Make sure no entries are hidden\n assert.strictEqual(stack.invisibleEntries().length, 0);\n\n // Collapse all children of basicTwo call:\n stack.applyFilterAction({type: PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION, entry: basicTwoCallEntry});\n\n // Make sure all 37 of basicTwo descdendants are hidden\n assert.strictEqual(stack.invisibleEntries().length, 37);\n\n // Get the first fibonacci call that is one of the hidden children and make sure it is hidden\n const firstFibCallEntry = findFirstEntry(mainThread.entries, entry => {\n return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'fibonacci';\n });\n\n assert.isTrue(stack.invisibleEntries().includes(firstFibCallEntry));\n\n // Reveal the first fibonacci call and make sure that the all of the entries are now visible because the closest\n // expandable parent to the fib call is basicTwo and, therefore, we need to reset its children.\n stack.revealEntry(firstFibCallEntry);\n assert.strictEqual(stack.invisibleEntries().length, 0);\n });\n\n it('supports resetting all hidden children of a selected entry', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'two-functions-recursion.json.gz');\n const mainThread = getMainThread(parsedTrace.Renderer);\n /** This stack looks roughly like so (with some events omitted):\n * ======== onclick ============\n * =========== foo =============\n * ==== foo2 =====\n * ===== foo =====\n * ==== foo2 =====\n * ===== foo =====\n * ==== foo2 =====\n * ===== foo =====\n *\n * In this test we want to test the user collapsing all descendant foo calls of the first first one,\n * which should have the effect of keeping the first foo visible, but removing all of its other calls:\n * ======== onclick ============\n * =========== foo =============\n * ===== foo2 ==== << all foo except first removed\n * ==== foo2 =====\n * ==== foo2 =====\n *\n * Then, reset children on the second visible foo2.\n * ======== onclick ============\n * =========== foo =============\n * ===== foo2 ==== << foo() after this entry still hidden\n * ==== foo2 ===== << all children from this node are visible\n * ===== foo =====\n * ==== foo2 =====\n * ===== foo =====\n *\n * This results in a stack where all children of an entry children were reset on (second foo2)\n * are visible, but the entries hidden above the entry children were reset on stay hidden.\n **/\n\n const firstFooCallEntry = findFirstEntry(mainThread.entries, entry => {\n return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'foo' && entry.dur === 233;\n });\n\n // Gather the foo() and foo2() calls under and including the first foo entry, by finding all\n // the calls whose end time is less than or equal to the end time of the first `foo` function.\n const firstFooCallEndTime = Trace.Helpers.Timing.eventTimingsMicroSeconds(firstFooCallEntry).endTime;\n const fooCalls = mainThread.entries.filter(entry => {\n const isFooCall = Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'foo';\n if (!isFooCall) {\n return false;\n }\n const {endTime} = Trace.Helpers.Timing.eventTimingsMicroSeconds(entry);\n return endTime <= firstFooCallEndTime;\n });\n\n const foo2Calls = mainThread.entries.filter(entry => {\n const isFoo2Call = Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'foo2';\n if (!isFoo2Call) {\n return false;\n }\n const {endTime} = Trace.Helpers.Timing.eventTimingsMicroSeconds(entry);\n return endTime <= firstFooCallEndTime;\n });\n\n const stack = new Timeline.EntriesFilter.EntriesFilter(parsedTrace.Renderer.entryToNode);\n if (!stack) {\n throw new Error('EntriesFilter does not exist');\n }\n stack.applyFilterAction(\n {type: PerfUI.FlameChart.FilterAction.COLLAPSE_REPEATING_DESCENDANTS, entry: firstFooCallEntry});\n\n // We collapsed identical descendants after the first `foo` entry - so it should not be included in the invisible list itself,\n // but all foo() calls below it in the stack should now be invisible.\n const allFooExceptFirstInStackAreHidden = fooCalls.every((fooCall, i) => {\n if (i === 0) {\n // First foo should not be invisible.\n return !stack.invisibleEntries().includes(fooCall);\n }\n return stack.invisibleEntries().includes(fooCall);\n });\n assert.isTrue(\n allFooExceptFirstInStackAreHidden, 'First foo is invisible or some following foo calls are still visible');\n\n // All of the foo2 calls that were inbetween foo calls should still be visible.\n let allFoo2InStackAreVisible = foo2Calls.every(fooCall => {\n return !stack.invisibleEntries().includes(fooCall);\n });\n assert.isTrue(allFoo2InStackAreVisible, 'Some foo2 calls are invisible');\n\n // Reset all children after second foo2 call\n assert.strictEqual(foo2Calls.length, 3);\n stack.applyFilterAction({type: PerfUI.FlameChart.FilterAction.RESET_CHILDREN, entry: foo2Calls[1]});\n\n // All foo and foo2 calls except the second foo cll should now be visible\n allFoo2InStackAreVisible = foo2Calls.every(fooCall => {\n return !stack.invisibleEntries().includes(fooCall);\n });\n assert.isTrue(allFoo2InStackAreVisible, 'Some foo2 calls are invisible');\n\n const allFooExceptSecondInStackAreVisible = fooCalls.every((fooCall, i) => {\n if (i === 1) {\n // Second foo should be invisible.\n return stack.invisibleEntries().includes(fooCall);\n }\n return !stack.invisibleEntries().includes(fooCall);\n });\n assert.isTrue(\n allFooExceptSecondInStackAreVisible,\n 'Some foo calls except the second one are invisible or the second one is visible');\n });\n\n it('correctly returns the amount of hidden children of a node', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'two-functions-recursion.json.gz');\n const mainThread = getMainThread(parsedTrace.Renderer);\n /** This stack looks roughly like so (with some erlier events omitted):\n * ======== onclick ============\n * =========== foo =============\n * ==== foo2 =====\n * ===== foo =====\n * ==== foo2 =====\n * ===== foo =====\n * ==== foo2 =====\n * ===== foo =====\n *\n * In this test we want to test if the amount of hidden children returned is correct:\n * If we collapse repeating children on the first foo call, the 3 child foo calls should be removed.\n * Therefore, the amount of hidden children should be equal to 3.\n * ======== onclick ============\n * =========== foo ============= << all foo except first hidden\n * ===== foo2 ====\n * ==== foo2 =====\n * ==== foo2 =====\n **/\n\n const firstFooCallEntry = findFirstEntry(mainThread.entries, entry => {\n return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'foo' && entry.dur === 233;\n });\n\n const stack = new Timeline.EntriesFilter.EntriesFilter(parsedTrace.Renderer.entryToNode);\n if (!stack) {\n throw new Error('EntriesFilter does not exist');\n }\n // Before applying any action on a node, there should be no entries hidden under it\n assert.strictEqual(stack.findHiddenDescendantsAmount(firstFooCallEntry), 0);\n\n stack.applyFilterAction(\n {type: PerfUI.FlameChart.FilterAction.COLLAPSE_REPEATING_DESCENDANTS, entry: firstFooCallEntry});\n\n // There should be 3 foo() entries hidden under the first foo call entry\n assert.strictEqual(stack.findHiddenDescendantsAmount(firstFooCallEntry), 3);\n });\n\n it('correctly assigns a visible parent to expandable entries if the direct parent is not visible', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'basic-stack.json.gz');\n const mainThread = getMainThread(parsedTrace.Renderer);\n /** This stack looks roughly like so (with some events omitted):\n * ======== Task ===============\n * ======== (anonymous) ======== << entry with an invisible in the timeline direct parent. We need to make sure that we correctly add Task to the expandable entries\n * ======== RegisterFrameID ====\n * ======== postMessage ========\n **/\n const anonymousEntryWithInvisibleParent = findFirstEntry(mainThread.entries, entry => {\n return Trace.Types.Events.isProfileCall(entry) && entry.nodeId === 42;\n });\n\n const stack = new Timeline.EntriesFilter.EntriesFilter(parsedTrace.Renderer.entryToNode);\n if (!stack) {\n throw new Error('EntriesFilter does not exist');\n }\n\n const taskEntry = findFirstEntry(mainThread.entries, entry => {\n return entry.name === 'RunTask' && entry.dur === 978 && entry.ts === 164397762991;\n });\n\n // Make sure the expandable entries are empty at first\n assert.strictEqual(stack.expandableEntries().length, 0);\n\n // Hide the anonymous function\n stack.applyFilterAction(\n {type: PerfUI.FlameChart.FilterAction.MERGE_FUNCTION, entry: anonymousEntryWithInvisibleParent});\n\n // Make sure Task entry is added to expandable entries\n assert.strictEqual(stack.expandableEntries().length, 1);\n assert.isTrue(stack.expandableEntries().includes(taskEntry));\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/EventsSerializer.d.ts b/public/panels/timeline/EventsSerializer.d.ts index 0bca48f55..100bb32ef 100644 --- a/public/panels/timeline/EventsSerializer.d.ts +++ b/public/panels/timeline/EventsSerializer.d.ts @@ -1,10 +1,10 @@ -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; export declare class EventsSerializer { #private; - keyForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): TraceEngine.Types.File.TraceEventSerializableKey | null; - eventForKey(key: TraceEngine.Types.File.TraceEventSerializableKey, traceParsedData: TraceEngine.Handlers.Types.TraceParseData): TraceEngine.Types.TraceEvents.TraceEventData; - static isProfileCallKey(key: TraceEngine.Types.File.TraceEventSerializableKeyValues): key is TraceEngine.Types.File.ProfileCallKeyValues; - static isLegacyTimelineFrameKey(key: TraceEngine.Types.File.TraceEventSerializableKeyValues): key is TraceEngine.Types.File.LegacyTimelineFrameKeyValues; - static isRawEventKey(key: TraceEngine.Types.File.TraceEventSerializableKeyValues): key is TraceEngine.Types.File.RawEventKeyValues; - static isSyntheticEventKey(key: TraceEngine.Types.File.TraceEventSerializableKeyValues): key is TraceEngine.Types.File.SyntheticEventKeyValues; + keyForEvent(event: Trace.Types.Events.Event): Trace.Types.File.SerializableKey | null; + eventForKey(key: Trace.Types.File.SerializableKey, parsedTrace: Trace.Handlers.Types.ParsedTrace): Trace.Types.Events.Event; + static isProfileCallKey(key: Trace.Types.File.SerializableKeyValues): key is Trace.Types.File.ProfileCallKeyValues; + static isLegacyTimelineFrameKey(key: Trace.Types.File.SerializableKeyValues): key is Trace.Types.File.LegacyTimelineFrameKeyValues; + static isRawEventKey(key: Trace.Types.File.SerializableKeyValues): key is Trace.Types.File.RawEventKeyValues; + static isSyntheticEventKey(key: Trace.Types.File.SerializableKeyValues): key is Trace.Types.File.SyntheticEventKeyValues; } diff --git a/public/panels/timeline/EventsSerializer.js b/public/panels/timeline/EventsSerializer.js index 9b66a7a69..4d8fb5509 100644 --- a/public/panels/timeline/EventsSerializer.js +++ b/public/panels/timeline/EventsSerializer.js @@ -1,39 +1,39 @@ // Copyright 2024 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 * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; export class EventsSerializer { #modifiedProfileCallByKey = new Map(); keyForEvent(event) { - if (TraceEngine.Types.TraceEvents.isProfileCall(event)) { - return `${"p" /* TraceEngine.Types.File.EventKeyType.PROFILE_CALL */}-${event.pid}-${event.tid}-${TraceEngine.Types.TraceEvents.SampleIndex(event.sampleIndex)}-${event.nodeId}`; + if (Trace.Types.Events.isProfileCall(event)) { + return `${"p" /* Trace.Types.File.EventKeyType.PROFILE_CALL */}-${event.pid}-${event.tid}-${Trace.Types.Events.SampleIndex(event.sampleIndex)}-${event.nodeId}`; } - if (TraceEngine.Types.TraceEvents.isLegacyTimelineFrame(event)) { - return `${"l" /* TraceEngine.Types.File.EventKeyType.LEGACY_TIMELINE_FRAME */}-${event.index}`; + if (Trace.Types.Events.isLegacyTimelineFrame(event)) { + return `${"l" /* Trace.Types.File.EventKeyType.LEGACY_TIMELINE_FRAME */}-${event.index}`; } - const rawEvents = TraceEngine.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager().getRawTraceEvents(); - const key = TraceEngine.Types.TraceEvents.isSyntheticBasedEvent(event) ? - `${"s" /* TraceEngine.Types.File.EventKeyType.SYNTHETIC_EVENT */}-${rawEvents.indexOf(event.rawSourceEvent)}` : - `${"r" /* TraceEngine.Types.File.EventKeyType.RAW_EVENT */}-${rawEvents.indexOf(event)}`; + const rawEvents = Trace.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager().getRawTraceEvents(); + const key = Trace.Types.Events.isSyntheticBased(event) ? + `${"s" /* Trace.Types.File.EventKeyType.SYNTHETIC_EVENT */}-${rawEvents.indexOf(event.rawSourceEvent)}` : + `${"r" /* Trace.Types.File.EventKeyType.RAW_EVENT */}-${rawEvents.indexOf(event)}`; if (key.length < 3) { return null; } return key; } - eventForKey(key, traceParsedData) { - const eventValues = TraceEngine.Types.File.traceEventKeyToValues(key); + eventForKey(key, parsedTrace) { + const eventValues = Trace.Types.File.traceEventKeyToValues(key); if (EventsSerializer.isProfileCallKey(eventValues)) { - return this.#getModifiedProfileCallByKeyValues(eventValues, traceParsedData); + return this.#getModifiedProfileCallByKeyValues(eventValues, parsedTrace); } if (EventsSerializer.isLegacyTimelineFrameKey(eventValues)) { - const event = traceParsedData.Frames.frames.at(eventValues.rawIndex); + const event = parsedTrace.Frames.frames.at(eventValues.rawIndex); if (!event) { throw new Error(`Could not find frame with index ${eventValues.rawIndex}`); } return event; } if (EventsSerializer.isSyntheticEventKey(eventValues)) { - const syntheticEvents = TraceEngine.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager().getSyntheticTraceEvents(); + const syntheticEvents = Trace.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager().getSyntheticTraces(); const syntheticEvent = syntheticEvents.at(eventValues.rawIndex); if (!syntheticEvent) { throw new Error(`Attempted to get a synthetic event from an unknown raw event index: ${eventValues.rawIndex}`); @@ -41,29 +41,29 @@ export class EventsSerializer { return syntheticEvent; } if (EventsSerializer.isRawEventKey(eventValues)) { - const rawEvents = TraceEngine.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager().getRawTraceEvents(); + const rawEvents = Trace.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager().getRawTraceEvents(); return rawEvents[eventValues.rawIndex]; } throw new Error(`Unknown trace event serializable key values: ${eventValues.join('-')}`); } static isProfileCallKey(key) { - return key.type === "p" /* TraceEngine.Types.File.EventKeyType.PROFILE_CALL */; + return key.type === "p" /* Trace.Types.File.EventKeyType.PROFILE_CALL */; } static isLegacyTimelineFrameKey(key) { - return key.type === "l" /* TraceEngine.Types.File.EventKeyType.LEGACY_TIMELINE_FRAME */; + return key.type === "l" /* Trace.Types.File.EventKeyType.LEGACY_TIMELINE_FRAME */; } static isRawEventKey(key) { - return key.type === "r" /* TraceEngine.Types.File.EventKeyType.RAW_EVENT */; + return key.type === "r" /* Trace.Types.File.EventKeyType.RAW_EVENT */; } static isSyntheticEventKey(key) { - return key.type === "s" /* TraceEngine.Types.File.EventKeyType.SYNTHETIC_EVENT */; + return key.type === "s" /* Trace.Types.File.EventKeyType.SYNTHETIC_EVENT */; } - #getModifiedProfileCallByKeyValues(key, traceParsedData) { + #getModifiedProfileCallByKeyValues(key, parsedTrace) { const cacheResult = this.#modifiedProfileCallByKey.get(key); if (cacheResult) { return cacheResult; } - const profileCallsInThread = traceParsedData.Renderer.processes.get(key.processID)?.threads.get(key.threadID)?.profileCalls; + const profileCallsInThread = parsedTrace.Renderer.processes.get(key.processID)?.threads.get(key.threadID)?.profileCalls; if (!profileCallsInThread) { throw new Error(`Unknown profile call serializable key: ${(key)}`); } diff --git a/public/panels/timeline/EventsSerializer.js.map b/public/panels/timeline/EventsSerializer.js.map index 66ffe6528..b517408c5 100644 --- a/public/panels/timeline/EventsSerializer.js.map +++ b/public/panels/timeline/EventsSerializer.js.map @@ -1 +1 @@ -{"version":3,"file":"EventsSerializer.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/EventsSerializer.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceEngine from '../../models/trace/trace.js';\n\nexport class EventsSerializer {\n #modifiedProfileCallByKey:\n Map = new Map();\n\n keyForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): TraceEngine.Types.File.TraceEventSerializableKey\n |null {\n if (TraceEngine.Types.TraceEvents.isProfileCall(event)) {\n return `${TraceEngine.Types.File.EventKeyType.PROFILE_CALL}-${event.pid}-${event.tid}-${\n TraceEngine.Types.TraceEvents.SampleIndex(event.sampleIndex)}-${event.nodeId}`;\n }\n\n if (TraceEngine.Types.TraceEvents.isLegacyTimelineFrame(event)) {\n return `${TraceEngine.Types.File.EventKeyType.LEGACY_TIMELINE_FRAME}-${event.index}`;\n }\n\n const rawEvents = TraceEngine.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager().getRawTraceEvents();\n const key: TraceEngine.Types.File.SyntheticEventKey|TraceEngine.Types.File.RawEventKey =\n TraceEngine.Types.TraceEvents.isSyntheticBasedEvent(event) ?\n `${TraceEngine.Types.File.EventKeyType.SYNTHETIC_EVENT}-${rawEvents.indexOf(event.rawSourceEvent)}` :\n `${TraceEngine.Types.File.EventKeyType.RAW_EVENT}-${rawEvents.indexOf(event)}`;\n if (key.length < 3) {\n return null;\n }\n return key;\n }\n\n eventForKey(\n key: TraceEngine.Types.File.TraceEventSerializableKey,\n traceParsedData: TraceEngine.Handlers.Types.TraceParseData): TraceEngine.Types.TraceEvents.TraceEventData {\n const eventValues = TraceEngine.Types.File.traceEventKeyToValues(key);\n\n if (EventsSerializer.isProfileCallKey(eventValues)) {\n return this.#getModifiedProfileCallByKeyValues(eventValues, traceParsedData);\n }\n\n if (EventsSerializer.isLegacyTimelineFrameKey(eventValues)) {\n const event = traceParsedData.Frames.frames.at(eventValues.rawIndex);\n if (!event) {\n throw new Error(`Could not find frame with index ${eventValues.rawIndex}`);\n }\n return event;\n }\n\n if (EventsSerializer.isSyntheticEventKey(eventValues)) {\n const syntheticEvents =\n TraceEngine.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager().getSyntheticTraceEvents();\n const syntheticEvent = syntheticEvents.at(eventValues.rawIndex);\n if (!syntheticEvent) {\n throw new Error(`Attempted to get a synthetic event from an unknown raw event index: ${eventValues.rawIndex}`);\n }\n return syntheticEvent;\n }\n\n if (EventsSerializer.isRawEventKey(eventValues)) {\n const rawEvents =\n TraceEngine.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager().getRawTraceEvents();\n return rawEvents[eventValues.rawIndex];\n }\n throw new Error(`Unknown trace event serializable key values: ${(eventValues as Array).join('-')}`);\n }\n\n static isProfileCallKey(key: TraceEngine.Types.File.TraceEventSerializableKeyValues):\n key is TraceEngine.Types.File.ProfileCallKeyValues {\n return key.type === TraceEngine.Types.File.EventKeyType.PROFILE_CALL;\n }\n static isLegacyTimelineFrameKey(key: TraceEngine.Types.File.TraceEventSerializableKeyValues):\n key is TraceEngine.Types.File.LegacyTimelineFrameKeyValues {\n return key.type === TraceEngine.Types.File.EventKeyType.LEGACY_TIMELINE_FRAME;\n }\n\n static isRawEventKey(key: TraceEngine.Types.File.TraceEventSerializableKeyValues):\n key is TraceEngine.Types.File.RawEventKeyValues {\n return key.type === TraceEngine.Types.File.EventKeyType.RAW_EVENT;\n }\n static isSyntheticEventKey(key: TraceEngine.Types.File.TraceEventSerializableKeyValues):\n key is TraceEngine.Types.File.SyntheticEventKeyValues {\n return key.type === TraceEngine.Types.File.EventKeyType.SYNTHETIC_EVENT;\n }\n\n #getModifiedProfileCallByKeyValues(\n key: TraceEngine.Types.File.ProfileCallKeyValues,\n traceParsedData: TraceEngine.Handlers.Types.TraceParseData): TraceEngine.Types.TraceEvents.SyntheticProfileCall {\n const cacheResult = this.#modifiedProfileCallByKey.get(key);\n if (cacheResult) {\n return cacheResult;\n }\n const profileCallsInThread =\n traceParsedData.Renderer.processes.get(key.processID)?.threads.get(key.threadID)?.profileCalls;\n if (!profileCallsInThread) {\n throw new Error(`Unknown profile call serializable key: ${(key)}`);\n }\n\n const match = profileCallsInThread?.find(e => {\n return e.sampleIndex === key.sampleIndex && e.nodeId === key.protocol;\n });\n if (!match) {\n throw new Error(`Unknown profile call serializable key: ${(JSON.stringify(key))}`);\n }\n // Cache to avoid looking up in subsequent calls.\n this.#modifiedProfileCallByKey.set(key, match);\n return match;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"EventsSerializer.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/EventsSerializer.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../models/trace/trace.js';\n\nexport class EventsSerializer {\n #modifiedProfileCallByKey: Map =\n new Map();\n\n keyForEvent(event: Trace.Types.Events.Event): Trace.Types.File.SerializableKey|null {\n if (Trace.Types.Events.isProfileCall(event)) {\n return `${Trace.Types.File.EventKeyType.PROFILE_CALL}-${event.pid}-${event.tid}-${\n Trace.Types.Events.SampleIndex(event.sampleIndex)}-${event.nodeId}`;\n }\n\n if (Trace.Types.Events.isLegacyTimelineFrame(event)) {\n return `${Trace.Types.File.EventKeyType.LEGACY_TIMELINE_FRAME}-${event.index}`;\n }\n\n const rawEvents = Trace.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager().getRawTraceEvents();\n const key: Trace.Types.File.SyntheticEventKey|Trace.Types.File.RawEventKey =\n Trace.Types.Events.isSyntheticBased(event) ?\n `${Trace.Types.File.EventKeyType.SYNTHETIC_EVENT}-${rawEvents.indexOf(event.rawSourceEvent)}` :\n `${Trace.Types.File.EventKeyType.RAW_EVENT}-${rawEvents.indexOf(event)}`;\n if (key.length < 3) {\n return null;\n }\n return key;\n }\n\n eventForKey(key: Trace.Types.File.SerializableKey, parsedTrace: Trace.Handlers.Types.ParsedTrace):\n Trace.Types.Events.Event {\n const eventValues = Trace.Types.File.traceEventKeyToValues(key);\n\n if (EventsSerializer.isProfileCallKey(eventValues)) {\n return this.#getModifiedProfileCallByKeyValues(eventValues, parsedTrace);\n }\n\n if (EventsSerializer.isLegacyTimelineFrameKey(eventValues)) {\n const event = parsedTrace.Frames.frames.at(eventValues.rawIndex);\n if (!event) {\n throw new Error(`Could not find frame with index ${eventValues.rawIndex}`);\n }\n return event;\n }\n\n if (EventsSerializer.isSyntheticEventKey(eventValues)) {\n const syntheticEvents =\n Trace.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager().getSyntheticTraces();\n const syntheticEvent = syntheticEvents.at(eventValues.rawIndex);\n if (!syntheticEvent) {\n throw new Error(`Attempted to get a synthetic event from an unknown raw event index: ${eventValues.rawIndex}`);\n }\n return syntheticEvent;\n }\n\n if (EventsSerializer.isRawEventKey(eventValues)) {\n const rawEvents = Trace.Helpers.SyntheticEvents.SyntheticEventsManager.getActiveManager().getRawTraceEvents();\n return rawEvents[eventValues.rawIndex];\n }\n throw new Error(`Unknown trace event serializable key values: ${(eventValues as Array).join('-')}`);\n }\n\n static isProfileCallKey(key: Trace.Types.File.SerializableKeyValues): key is Trace.Types.File.ProfileCallKeyValues {\n return key.type === Trace.Types.File.EventKeyType.PROFILE_CALL;\n }\n static isLegacyTimelineFrameKey(key: Trace.Types.File.SerializableKeyValues):\n key is Trace.Types.File.LegacyTimelineFrameKeyValues {\n return key.type === Trace.Types.File.EventKeyType.LEGACY_TIMELINE_FRAME;\n }\n\n static isRawEventKey(key: Trace.Types.File.SerializableKeyValues): key is Trace.Types.File.RawEventKeyValues {\n return key.type === Trace.Types.File.EventKeyType.RAW_EVENT;\n }\n static isSyntheticEventKey(key: Trace.Types.File.SerializableKeyValues):\n key is Trace.Types.File.SyntheticEventKeyValues {\n return key.type === Trace.Types.File.EventKeyType.SYNTHETIC_EVENT;\n }\n\n #getModifiedProfileCallByKeyValues(\n key: Trace.Types.File.ProfileCallKeyValues,\n parsedTrace: Trace.Handlers.Types.ParsedTrace): Trace.Types.Events.SyntheticProfileCall {\n const cacheResult = this.#modifiedProfileCallByKey.get(key);\n if (cacheResult) {\n return cacheResult;\n }\n const profileCallsInThread =\n parsedTrace.Renderer.processes.get(key.processID)?.threads.get(key.threadID)?.profileCalls;\n if (!profileCallsInThread) {\n throw new Error(`Unknown profile call serializable key: ${(key)}`);\n }\n\n const match = profileCallsInThread?.find(e => {\n return e.sampleIndex === key.sampleIndex && e.nodeId === key.protocol;\n });\n if (!match) {\n throw new Error(`Unknown profile call serializable key: ${(JSON.stringify(key))}`);\n }\n // Cache to avoid looking up in subsequent calls.\n this.#modifiedProfileCallByKey.set(key, match);\n return match;\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/EventsSerializer.test.js b/public/panels/timeline/EventsSerializer.test.js index a2a20a895..aef201e1e 100644 --- a/public/panels/timeline/EventsSerializer.test.js +++ b/public/panels/timeline/EventsSerializer.test.js @@ -1,7 +1,7 @@ // Copyright 2024 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 * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import { describeWithEnvironment } from '../../testing/EnvironmentHelpers.js'; import { getMainThread } from '../../testing/TraceHelpers.js'; import { TraceLoader } from '../../testing/TraceLoader.js'; @@ -15,15 +15,15 @@ function findFirstEntry(allEntries, predicate) { } describeWithEnvironment('EventsSerializer', () => { it('correctly implements a bidirectional key <-> event mapping', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'basic-stack.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'basic-stack.json.gz'); const eventsSerializer = new Timeline.EventsSerializer.EventsSerializer(); - const mainThread = getMainThread(traceData.Renderer); + const mainThread = getMainThread(parsedTrace.Renderer); // Find first 'Timer Fired' entry in the trace const rawEntry = findFirstEntry(mainThread.entries, entry => { return entry.name === 'TimerFire'; }); - const syntheticEvent = traceData.NetworkRequests.byTime[0]; - const profileCall = findFirstEntry(mainThread.entries, entry => TraceEngine.Types.TraceEvents.isProfileCall(entry)); + const syntheticEvent = parsedTrace.NetworkRequests.byTime[0]; + const profileCall = findFirstEntry(mainThread.entries, entry => Trace.Types.Events.isProfileCall(entry)); const rawEntryKey = eventsSerializer.keyForEvent(rawEntry); const syntheticEventKey = eventsSerializer.keyForEvent(syntheticEvent); const profileCallKey = eventsSerializer.keyForEvent(profileCall); @@ -34,23 +34,23 @@ describeWithEnvironment('EventsSerializer', () => { assert.isOk(rawEntryKey); assert.isOk(syntheticEventKey); assert.isOk(profileCallKey); - const resolvedRawEntry = eventsSerializer.eventForKey(rawEntryKey, traceData); - const resolvedSyntheticEntry = eventsSerializer.eventForKey(syntheticEventKey, traceData); - const resolvedProfileCall = eventsSerializer.eventForKey(profileCallKey, traceData); + const resolvedRawEntry = eventsSerializer.eventForKey(rawEntryKey, parsedTrace); + const resolvedSyntheticEntry = eventsSerializer.eventForKey(syntheticEventKey, parsedTrace); + const resolvedProfileCall = eventsSerializer.eventForKey(profileCallKey, parsedTrace); // Test key -> event mappings assert.strictEqual(resolvedRawEntry, rawEntry); assert.strictEqual(resolvedSyntheticEntry, syntheticEvent); assert.strictEqual(resolvedProfileCall, profileCall); }); it('correctly maps to and from legacy timeline frames', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); const eventsSerializer = new Timeline.EventsSerializer.EventsSerializer(); - const frame = traceData.Frames.frames.at(0); + const frame = parsedTrace.Frames.frames.at(0); assert.isOk(frame); const frameKey = eventsSerializer.keyForEvent(frame); assert.isOk(frameKey); assert.strictEqual(frameKey, 'l-0'); - const resolvedFrame = eventsSerializer.eventForKey(frameKey, traceData); + const resolvedFrame = eventsSerializer.eventForKey(frameKey, parsedTrace); assert.strictEqual(resolvedFrame, frame); }); }); diff --git a/public/panels/timeline/EventsSerializer.test.js.map b/public/panels/timeline/EventsSerializer.test.js.map index abc3e99d4..55620257f 100644 --- a/public/panels/timeline/EventsSerializer.test.js.map +++ b/public/panels/timeline/EventsSerializer.test.js.map @@ -1 +1 @@ -{"version":3,"file":"EventsSerializer.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/EventsSerializer.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {getMainThread} from '../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\n\nimport * as Timeline from './timeline.js';\n\nfunction findFirstEntry(\n allEntries: readonly TraceEngine.Types.TraceEvents.TraceEventData[],\n predicate: (entry: TraceEngine.Types.TraceEvents.TraceEventData) =>\n boolean): TraceEngine.Types.TraceEvents.TraceEventData {\n const entry = allEntries.find(entry => predicate(entry));\n if (!entry) {\n throw new Error('Could not find expected entry.');\n }\n return entry;\n}\n\ndescribeWithEnvironment('EventsSerializer', () => {\n it('correctly implements a bidirectional key <-> event mapping', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'basic-stack.json.gz');\n const eventsSerializer = new Timeline.EventsSerializer.EventsSerializer();\n const mainThread = getMainThread(traceData.Renderer);\n // Find first 'Timer Fired' entry in the trace\n const rawEntry = findFirstEntry(mainThread.entries, entry => {\n return entry.name === 'TimerFire';\n });\n\n const syntheticEvent = traceData.NetworkRequests.byTime[0];\n const profileCall = findFirstEntry(mainThread.entries, entry => TraceEngine.Types.TraceEvents.isProfileCall(entry));\n const rawEntryKey = eventsSerializer.keyForEvent(rawEntry);\n const syntheticEventKey = eventsSerializer.keyForEvent(syntheticEvent);\n const profileCallKey = eventsSerializer.keyForEvent(profileCall);\n\n // Test event -> key mappings\n assert.deepEqual(rawEntryKey, 'r-8036');\n assert.deepEqual(syntheticEventKey, 's-2078');\n assert.deepEqual(profileCallKey, 'p-55385-259-38-4');\n\n assert.isOk(rawEntryKey);\n assert.isOk(syntheticEventKey);\n assert.isOk(profileCallKey);\n\n const resolvedRawEntry = eventsSerializer.eventForKey(rawEntryKey, traceData);\n const resolvedSyntheticEntry = eventsSerializer.eventForKey(syntheticEventKey, traceData);\n const resolvedProfileCall = eventsSerializer.eventForKey(profileCallKey, traceData);\n\n // Test key -> event mappings\n assert.strictEqual(resolvedRawEntry, rawEntry);\n assert.strictEqual(resolvedSyntheticEntry, syntheticEvent);\n assert.strictEqual(resolvedProfileCall, profileCall);\n });\n\n it('correctly maps to and from legacy timeline frames', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n const eventsSerializer = new Timeline.EventsSerializer.EventsSerializer();\n\n const frame = traceData.Frames.frames.at(0);\n assert.isOk(frame);\n\n const frameKey = eventsSerializer.keyForEvent(frame);\n assert.isOk(frameKey);\n assert.strictEqual(frameKey, 'l-0');\n\n const resolvedFrame = eventsSerializer.eventForKey(frameKey, traceData);\n assert.strictEqual(resolvedFrame, frame);\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"EventsSerializer.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/EventsSerializer.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {getMainThread} from '../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\n\nimport * as Timeline from './timeline.js';\n\nfunction findFirstEntry(\n allEntries: readonly Trace.Types.Events.Event[],\n predicate: (entry: Trace.Types.Events.Event) => boolean): Trace.Types.Events.Event {\n const entry = allEntries.find(entry => predicate(entry));\n if (!entry) {\n throw new Error('Could not find expected entry.');\n }\n return entry;\n}\n\ndescribeWithEnvironment('EventsSerializer', () => {\n it('correctly implements a bidirectional key <-> event mapping', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'basic-stack.json.gz');\n const eventsSerializer = new Timeline.EventsSerializer.EventsSerializer();\n const mainThread = getMainThread(parsedTrace.Renderer);\n // Find first 'Timer Fired' entry in the trace\n const rawEntry = findFirstEntry(mainThread.entries, entry => {\n return entry.name === 'TimerFire';\n });\n\n const syntheticEvent = parsedTrace.NetworkRequests.byTime[0];\n const profileCall = findFirstEntry(mainThread.entries, entry => Trace.Types.Events.isProfileCall(entry));\n const rawEntryKey = eventsSerializer.keyForEvent(rawEntry);\n const syntheticEventKey = eventsSerializer.keyForEvent(syntheticEvent);\n const profileCallKey = eventsSerializer.keyForEvent(profileCall);\n\n // Test event -> key mappings\n assert.deepEqual(rawEntryKey, 'r-8036');\n assert.deepEqual(syntheticEventKey, 's-2078');\n assert.deepEqual(profileCallKey, 'p-55385-259-38-4');\n\n assert.isOk(rawEntryKey);\n assert.isOk(syntheticEventKey);\n assert.isOk(profileCallKey);\n\n const resolvedRawEntry = eventsSerializer.eventForKey(rawEntryKey, parsedTrace);\n const resolvedSyntheticEntry = eventsSerializer.eventForKey(syntheticEventKey, parsedTrace);\n const resolvedProfileCall = eventsSerializer.eventForKey(profileCallKey, parsedTrace);\n\n // Test key -> event mappings\n assert.strictEqual(resolvedRawEntry, rawEntry);\n assert.strictEqual(resolvedSyntheticEntry, syntheticEvent);\n assert.strictEqual(resolvedProfileCall, profileCall);\n });\n\n it('correctly maps to and from legacy timeline frames', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n const eventsSerializer = new Timeline.EventsSerializer.EventsSerializer();\n\n const frame = parsedTrace.Frames.frames.at(0);\n assert.isOk(frame);\n\n const frameKey = eventsSerializer.keyForEvent(frame);\n assert.isOk(frameKey);\n assert.strictEqual(frameKey, 'l-0');\n\n const resolvedFrame = eventsSerializer.eventForKey(frameKey, parsedTrace);\n assert.strictEqual(resolvedFrame, frame);\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/EventsTimelineTreeView.js b/public/panels/timeline/EventsTimelineTreeView.js index 03e07bcf1..55e57e65e 100644 --- a/public/panels/timeline/EventsTimelineTreeView.js +++ b/public/panels/timeline/EventsTimelineTreeView.js @@ -3,7 +3,7 @@ // found in the LICENSE file. import * as Common from '../../core/common/common.js'; import * as i18n from '../../core/i18n/i18n.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as DataGrid from '../../ui/legacy/components/data_grid/data_grid.js'; import * as UI from '../../ui/legacy/legacy.js'; import * as VisualLogging from '../../ui/visual_logging/visual_logging.js'; @@ -52,7 +52,7 @@ export class EventsTimelineTreeView extends TimelineTreeView { } updateContents(selection) { super.updateContents(selection); - if (TimelineSelection.isTraceEventSelection(selection.object)) { + if (TimelineSelection.isSelection(selection.object)) { this.selectEvent(selection.object, true); } } @@ -69,7 +69,7 @@ export class EventsTimelineTreeView extends TimelineTreeView { } } findNodeWithEvent(event) { - if (event.name === "RunTask" /* TraceEngine.Types.TraceEvents.KnownEventName.RUN_TASK */) { + if (event.name === "RunTask" /* Trace.Types.Events.Name.RUN_TASK */) { // No node is ever created for the top level RunTask event, so // bail out preemptively return null; @@ -119,15 +119,15 @@ export class EventsTimelineTreeView extends TimelineTreeView { this.filtersControl.populateToolbar(toolbar); } showDetailsForNode(node) { - const traceParseData = this.traceParseData(); - if (!traceParseData) { + const parsedTrace = this.parsedTrace(); + if (!parsedTrace) { return false; } const traceEvent = node.event; if (!traceEvent) { return false; } - void TimelineUIUtils.buildTraceEventDetails(traceParseData, traceEvent, this.linkifier, false) + void TimelineUIUtils.buildTraceEventDetails(parsedTrace, traceEvent, this.linkifier, false) .then(fragment => this.detailsView.element.appendChild(fragment)); return true; } @@ -170,7 +170,7 @@ export class Filters extends Common.ObjectWrapper.ObjectWrapper { function durationFilterChanged() { const duration = durationFilterUI.selectedOption().value; const minimumRecordDuration = parseInt(duration, 10); - this.durationFilter.setMinimumRecordDuration(TraceEngine.Types.Timing.MilliSeconds(minimumRecordDuration)); + this.durationFilter.setMinimumRecordDuration(Trace.Types.Timing.MilliSeconds(minimumRecordDuration)); this.notifyFiltersChanged(); } function categoriesFilterChanged(name) { diff --git a/public/panels/timeline/EventsTimelineTreeView.js.map b/public/panels/timeline/EventsTimelineTreeView.js.map index 928e080c0..f36dae3e8 100644 --- a/public/panels/timeline/EventsTimelineTreeView.js.map +++ b/public/panels/timeline/EventsTimelineTreeView.js.map @@ -1 +1 @@ -{"version":3,"file":"EventsTimelineTreeView.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/EventsTimelineTreeView.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport type * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as DataGrid from '../../ui/legacy/components/data_grid/data_grid.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport * as Components from './components/components.js';\nimport {Category, IsLong} from './TimelineFilters.js';\nimport {type TimelineModeViewDelegate} from './TimelinePanel.js';\nimport {TimelineSelection} from './TimelineSelection.js';\nimport {TimelineTreeView} from './TimelineTreeView.js';\nimport {TimelineUIUtils} from './TimelineUIUtils.js';\n\nconst UIStrings = {\n /**\n *@description Text for the start time of an activity\n */\n startTime: 'Start time',\n /**\n *@description Screen reader label for a select box that filters the Performance panel Event Log by duration.\n */\n durationFilter: 'Duration filter',\n /**\n *@description Text in Events Timeline Tree View of the Performance panel\n *@example {2} PH1\n */\n Dms: '{PH1} ms',\n /**\n *@description Text for everything\n */\n all: 'All',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/EventsTimelineTreeView.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nexport class EventsTimelineTreeView extends TimelineTreeView {\n private readonly filtersControl: Filters;\n private readonly delegate: TimelineModeViewDelegate;\n private currentTree!: TimelineModel.TimelineProfileTree.Node;\n constructor(delegate: TimelineModeViewDelegate) {\n super();\n this.element.setAttribute('jslog', `${VisualLogging.pane('event-log').track({resize: true})}`);\n this.filtersControl = new Filters();\n this.filtersControl.addEventListener(Events.FILTER_CHANGED, this.onFilterChanged, this);\n this.init();\n this.delegate = delegate;\n this.dataGrid.markColumnAsSortedBy('start-time', DataGrid.DataGrid.Order.Ascending);\n this.splitWidget.showBoth();\n }\n\n override filters(): TimelineModel.TimelineModelFilter.TimelineModelFilter[] {\n return [...super.filters(), ...this.filtersControl.filters()];\n }\n\n override updateContents(selection: TimelineSelection): void {\n super.updateContents(selection);\n if (TimelineSelection.isTraceEventSelection(selection.object)) {\n this.selectEvent(selection.object, true);\n }\n }\n\n override buildTree(): TimelineModel.TimelineProfileTree.Node {\n this.currentTree = this.buildTopDownTree(true, null);\n return this.currentTree;\n }\n\n private onFilterChanged(): void {\n const lastSelectedNode = this.lastSelectedNode();\n const selectedEvent = lastSelectedNode && lastSelectedNode.event;\n this.refreshTree();\n if (selectedEvent) {\n this.selectEvent(selectedEvent, false);\n }\n }\n\n private findNodeWithEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): TimelineModel.TimelineProfileTree.Node\n |null {\n if (event.name === TraceEngine.Types.TraceEvents.KnownEventName.RUN_TASK) {\n // No node is ever created for the top level RunTask event, so\n // bail out preemptively\n return null;\n }\n const iterators = [this.currentTree.children().values()];\n while (iterators.length) {\n const {done, value: child} = iterators[iterators.length - 1].next();\n if (done) {\n iterators.pop();\n continue;\n }\n if (child.event === event) {\n return child;\n }\n iterators.push(child.children().values());\n }\n return null;\n }\n\n private selectEvent(event: TraceEngine.Types.TraceEvents.TraceEventData, expand?: boolean): void {\n const node = this.findNodeWithEvent(event);\n if (!node) {\n return;\n }\n this.selectProfileNode(node, false);\n if (expand) {\n const dataGridNode = this.dataGridNodeForTreeNode(node);\n if (dataGridNode) {\n dataGridNode.expand();\n }\n }\n }\n\n override populateColumns(columns: DataGrid.DataGrid.ColumnDescriptor[]): void {\n columns.push(({\n id: 'start-time',\n title: i18nString(UIStrings.startTime),\n width: '80px',\n fixedWidth: true,\n sortable: true,\n } as DataGrid.DataGrid.ColumnDescriptor));\n super.populateColumns(columns);\n columns.filter(c => c.fixedWidth).forEach(c => {\n c.width = '80px';\n });\n }\n\n override populateToolbar(toolbar: UI.Toolbar.Toolbar): void {\n super.populateToolbar(toolbar);\n this.filtersControl.populateToolbar(toolbar);\n }\n\n override showDetailsForNode(node: TimelineModel.TimelineProfileTree.Node): boolean {\n const traceParseData = this.traceParseData();\n if (!traceParseData) {\n return false;\n }\n const traceEvent = node.event;\n if (!traceEvent) {\n return false;\n }\n void TimelineUIUtils.buildTraceEventDetails(traceParseData, traceEvent, this.linkifier, false)\n .then(fragment => this.detailsView.element.appendChild(fragment));\n return true;\n }\n\n override onHover(node: TimelineModel.TimelineProfileTree.Node|null): void {\n this.delegate.highlightEvent(node && node.event);\n }\n}\n\nexport class Filters extends Common.ObjectWrapper.ObjectWrapper {\n private readonly categoryFilter: Category;\n private readonly durationFilter: IsLong;\n private readonly filtersInternal: (IsLong|Category)[];\n constructor() {\n super();\n this.categoryFilter = new Category();\n this.durationFilter = new IsLong();\n this.filtersInternal = [this.categoryFilter, this.durationFilter];\n }\n\n filters(): TimelineModel.TimelineModelFilter.TimelineModelFilter[] {\n return this.filtersInternal;\n }\n\n populateToolbar(toolbar: UI.Toolbar.Toolbar): void {\n const durationFilterUI = new UI.Toolbar.ToolbarComboBox(\n durationFilterChanged.bind(this), i18nString(UIStrings.durationFilter), undefined, 'duration');\n for (const durationMs of Filters.durationFilterPresetsMs) {\n durationFilterUI.addOption(durationFilterUI.createOption(\n durationMs ? `≥ ${i18nString(UIStrings.Dms, {PH1: durationMs})}` : i18nString(UIStrings.all),\n String(durationMs)));\n }\n toolbar.appendToolbarItem(durationFilterUI);\n\n const categoryFiltersUI = new Map();\n const categories = Components.EntryStyles.getCategoryStyles();\n for (const categoryName in categories) {\n const category = categories[categoryName as Components.EntryStyles.EventCategory];\n if (!category.visible) {\n continue;\n }\n const checkbox = new UI.Toolbar.ToolbarCheckbox(\n category.title, undefined,\n categoriesFilterChanged.bind(this, categoryName as Components.EntryStyles.EventCategory), categoryName);\n checkbox.setChecked(true);\n checkbox.inputElement.style.backgroundColor = category.color;\n categoryFiltersUI.set(category.name, checkbox);\n toolbar.appendToolbarItem(checkbox);\n }\n\n function durationFilterChanged(this: Filters): void {\n const duration = (durationFilterUI.selectedOption() as HTMLOptionElement).value;\n const minimumRecordDuration = parseInt(duration, 10);\n this.durationFilter.setMinimumRecordDuration(TraceEngine.Types.Timing.MilliSeconds(minimumRecordDuration));\n this.notifyFiltersChanged();\n }\n\n function categoriesFilterChanged(this: Filters, name: Components.EntryStyles.EventCategory): void {\n const categories = Components.EntryStyles.getCategoryStyles();\n const checkBox = categoryFiltersUI.get(name);\n categories[name].hidden = !checkBox || !checkBox.checked();\n this.notifyFiltersChanged();\n }\n }\n\n private notifyFiltersChanged(): void {\n this.dispatchEventToListeners(Events.FILTER_CHANGED);\n }\n\n private static readonly durationFilterPresetsMs = [0, 1, 15];\n}\n\nconst enum Events {\n FILTER_CHANGED = 'FilterChanged',\n}\n\ntype EventTypes = {\n [Events.FILTER_CHANGED]: void,\n};\n"]} \ No newline at end of file +{"version":3,"file":"EventsTimelineTreeView.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/EventsTimelineTreeView.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport type * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as DataGrid from '../../ui/legacy/components/data_grid/data_grid.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport * as Components from './components/components.js';\nimport {Category, IsLong} from './TimelineFilters.js';\nimport {type TimelineModeViewDelegate} from './TimelinePanel.js';\nimport {TimelineSelection} from './TimelineSelection.js';\nimport {TimelineTreeView} from './TimelineTreeView.js';\nimport {TimelineUIUtils} from './TimelineUIUtils.js';\n\nconst UIStrings = {\n /**\n *@description Text for the start time of an activity\n */\n startTime: 'Start time',\n /**\n *@description Screen reader label for a select box that filters the Performance panel Event Log by duration.\n */\n durationFilter: 'Duration filter',\n /**\n *@description Text in Events Timeline Tree View of the Performance panel\n *@example {2} PH1\n */\n Dms: '{PH1} ms',\n /**\n *@description Text for everything\n */\n all: 'All',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/EventsTimelineTreeView.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nexport class EventsTimelineTreeView extends TimelineTreeView {\n private readonly filtersControl: Filters;\n private readonly delegate: TimelineModeViewDelegate;\n private currentTree!: TimelineModel.TimelineProfileTree.Node;\n constructor(delegate: TimelineModeViewDelegate) {\n super();\n this.element.setAttribute('jslog', `${VisualLogging.pane('event-log').track({resize: true})}`);\n this.filtersControl = new Filters();\n this.filtersControl.addEventListener(Events.FILTER_CHANGED, this.onFilterChanged, this);\n this.init();\n this.delegate = delegate;\n this.dataGrid.markColumnAsSortedBy('start-time', DataGrid.DataGrid.Order.Ascending);\n this.splitWidget.showBoth();\n }\n\n override filters(): TimelineModel.TimelineModelFilter.TimelineModelFilter[] {\n return [...super.filters(), ...this.filtersControl.filters()];\n }\n\n override updateContents(selection: TimelineSelection): void {\n super.updateContents(selection);\n if (TimelineSelection.isSelection(selection.object)) {\n this.selectEvent(selection.object, true);\n }\n }\n\n override buildTree(): TimelineModel.TimelineProfileTree.Node {\n this.currentTree = this.buildTopDownTree(true, null);\n return this.currentTree;\n }\n\n private onFilterChanged(): void {\n const lastSelectedNode = this.lastSelectedNode();\n const selectedEvent = lastSelectedNode && lastSelectedNode.event;\n this.refreshTree();\n if (selectedEvent) {\n this.selectEvent(selectedEvent, false);\n }\n }\n\n private findNodeWithEvent(event: Trace.Types.Events.Event): TimelineModel.TimelineProfileTree.Node|null {\n if (event.name === Trace.Types.Events.Name.RUN_TASK) {\n // No node is ever created for the top level RunTask event, so\n // bail out preemptively\n return null;\n }\n const iterators = [this.currentTree.children().values()];\n while (iterators.length) {\n const {done, value: child} = iterators[iterators.length - 1].next();\n if (done) {\n iterators.pop();\n continue;\n }\n if (child.event === event) {\n return child;\n }\n iterators.push(child.children().values());\n }\n return null;\n }\n\n private selectEvent(event: Trace.Types.Events.Event, expand?: boolean): void {\n const node = this.findNodeWithEvent(event);\n if (!node) {\n return;\n }\n this.selectProfileNode(node, false);\n if (expand) {\n const dataGridNode = this.dataGridNodeForTreeNode(node);\n if (dataGridNode) {\n dataGridNode.expand();\n }\n }\n }\n\n override populateColumns(columns: DataGrid.DataGrid.ColumnDescriptor[]): void {\n columns.push(({\n id: 'start-time',\n title: i18nString(UIStrings.startTime),\n width: '80px',\n fixedWidth: true,\n sortable: true,\n } as DataGrid.DataGrid.ColumnDescriptor));\n super.populateColumns(columns);\n columns.filter(c => c.fixedWidth).forEach(c => {\n c.width = '80px';\n });\n }\n\n override populateToolbar(toolbar: UI.Toolbar.Toolbar): void {\n super.populateToolbar(toolbar);\n this.filtersControl.populateToolbar(toolbar);\n }\n\n override showDetailsForNode(node: TimelineModel.TimelineProfileTree.Node): boolean {\n const parsedTrace = this.parsedTrace();\n if (!parsedTrace) {\n return false;\n }\n const traceEvent = node.event;\n if (!traceEvent) {\n return false;\n }\n void TimelineUIUtils.buildTraceEventDetails(parsedTrace, traceEvent, this.linkifier, false)\n .then(fragment => this.detailsView.element.appendChild(fragment));\n return true;\n }\n\n override onHover(node: TimelineModel.TimelineProfileTree.Node|null): void {\n this.delegate.highlightEvent(node && node.event);\n }\n}\n\nexport class Filters extends Common.ObjectWrapper.ObjectWrapper {\n private readonly categoryFilter: Category;\n private readonly durationFilter: IsLong;\n private readonly filtersInternal: (IsLong|Category)[];\n constructor() {\n super();\n this.categoryFilter = new Category();\n this.durationFilter = new IsLong();\n this.filtersInternal = [this.categoryFilter, this.durationFilter];\n }\n\n filters(): TimelineModel.TimelineModelFilter.TimelineModelFilter[] {\n return this.filtersInternal;\n }\n\n populateToolbar(toolbar: UI.Toolbar.Toolbar): void {\n const durationFilterUI = new UI.Toolbar.ToolbarComboBox(\n durationFilterChanged.bind(this), i18nString(UIStrings.durationFilter), undefined, 'duration');\n for (const durationMs of Filters.durationFilterPresetsMs) {\n durationFilterUI.addOption(durationFilterUI.createOption(\n durationMs ? `≥ ${i18nString(UIStrings.Dms, {PH1: durationMs})}` : i18nString(UIStrings.all),\n String(durationMs)));\n }\n toolbar.appendToolbarItem(durationFilterUI);\n\n const categoryFiltersUI = new Map();\n const categories = Components.EntryStyles.getCategoryStyles();\n for (const categoryName in categories) {\n const category = categories[categoryName as Components.EntryStyles.EventCategory];\n if (!category.visible) {\n continue;\n }\n const checkbox = new UI.Toolbar.ToolbarCheckbox(\n category.title, undefined,\n categoriesFilterChanged.bind(this, categoryName as Components.EntryStyles.EventCategory), categoryName);\n checkbox.setChecked(true);\n checkbox.inputElement.style.backgroundColor = category.color;\n categoryFiltersUI.set(category.name, checkbox);\n toolbar.appendToolbarItem(checkbox);\n }\n\n function durationFilterChanged(this: Filters): void {\n const duration = (durationFilterUI.selectedOption() as HTMLOptionElement).value;\n const minimumRecordDuration = parseInt(duration, 10);\n this.durationFilter.setMinimumRecordDuration(Trace.Types.Timing.MilliSeconds(minimumRecordDuration));\n this.notifyFiltersChanged();\n }\n\n function categoriesFilterChanged(this: Filters, name: Components.EntryStyles.EventCategory): void {\n const categories = Components.EntryStyles.getCategoryStyles();\n const checkBox = categoryFiltersUI.get(name);\n categories[name].hidden = !checkBox || !checkBox.checked();\n this.notifyFiltersChanged();\n }\n }\n\n private notifyFiltersChanged(): void {\n this.dispatchEventToListeners(Events.FILTER_CHANGED);\n }\n\n private static readonly durationFilterPresetsMs = [0, 1, 15];\n}\n\nconst enum Events {\n FILTER_CHANGED = 'FilterChanged',\n}\n\ntype EventTypes = {\n [Events.FILTER_CHANGED]: void,\n};\n"]} \ No newline at end of file diff --git a/public/panels/timeline/ExtensionDataGatherer.d.ts b/public/panels/timeline/ExtensionDataGatherer.d.ts index fdbcd8a85..e2683edf9 100644 --- a/public/panels/timeline/ExtensionDataGatherer.d.ts +++ b/public/panels/timeline/ExtensionDataGatherer.d.ts @@ -1,5 +1,5 @@ -import type * as TraceEngine from '../../models/trace/trace.js'; -type ExtensionData = TraceEngine.Handlers.ModelHandlers.ExtensionTraceData.ExtensionTraceData; +import type * as Trace from '../../models/trace/trace.js'; +type ExtensionData = Trace.Handlers.ModelHandlers.ExtensionTraceData.ExtensionTraceData; /** * This class abstracts the source of extension data out by providing a * single access point to the performance panel for extension data. @@ -13,6 +13,6 @@ export declare class ExtensionDataGatherer { */ getExtensionData(): ExtensionData; saveCurrentModelData(): void; - modelChanged(traceParsedData: TraceEngine.Handlers.Types.TraceParseData | null): void; + modelChanged(parsedTrace: Trace.Handlers.Types.ParsedTrace | null): void; } export {}; diff --git a/public/panels/timeline/ExtensionDataGatherer.js b/public/panels/timeline/ExtensionDataGatherer.js index f05958579..5f3f63fcf 100644 --- a/public/panels/timeline/ExtensionDataGatherer.js +++ b/public/panels/timeline/ExtensionDataGatherer.js @@ -5,7 +5,7 @@ let extensionDataGathererInstance; * single access point to the performance panel for extension data. */ export class ExtensionDataGatherer { - #traceParsedData = null; + #parsedTrace = null; #extensionDataByModel = new Map(); static instance() { if (extensionDataGathererInstance) { @@ -22,32 +22,32 @@ export class ExtensionDataGatherer { */ getExtensionData() { const extensionDataEnabled = TimelinePanel.extensionDataVisibilitySetting().get(); - if (!extensionDataEnabled || !this.#traceParsedData || !this.#traceParsedData.ExtensionTraceData) { + if (!extensionDataEnabled || !this.#parsedTrace || !this.#parsedTrace.ExtensionTraceData) { return { extensionMarkers: [], extensionTrackData: [], entryToNode: new Map() }; } - const maybeCachedData = this.#extensionDataByModel.get(this.#traceParsedData); + const maybeCachedData = this.#extensionDataByModel.get(this.#parsedTrace); if (maybeCachedData) { return maybeCachedData; } - return this.#traceParsedData.ExtensionTraceData; + return this.#parsedTrace.ExtensionTraceData; } saveCurrentModelData() { - if (this.#traceParsedData && !this.#extensionDataByModel.has(this.#traceParsedData)) { - this.#extensionDataByModel.set(this.#traceParsedData, this.getExtensionData()); + if (this.#parsedTrace && !this.#extensionDataByModel.has(this.#parsedTrace)) { + this.#extensionDataByModel.set(this.#parsedTrace, this.getExtensionData()); } } - modelChanged(traceParsedData) { - if (traceParsedData === this.#traceParsedData) { + modelChanged(parsedTrace) { + if (parsedTrace === this.#parsedTrace) { return; } - if (this.#traceParsedData !== null) { + if (this.#parsedTrace !== null) { // DevTools extension data is assumed to be useful only for the current // trace data (model). As such, if the model changes, we cache the devtools // extension data we have collected for the previous model and listen // for new data that applies to the new model. this.saveCurrentModelData(); } - this.#traceParsedData = traceParsedData; + this.#parsedTrace = parsedTrace; } } //# sourceMappingURL=ExtensionDataGatherer.js.map \ No newline at end of file diff --git a/public/panels/timeline/ExtensionDataGatherer.js.map b/public/panels/timeline/ExtensionDataGatherer.js.map index 1ec950e85..104d76c3d 100644 --- a/public/panels/timeline/ExtensionDataGatherer.js.map +++ b/public/panels/timeline/ExtensionDataGatherer.js.map @@ -1 +1 @@ -{"version":3,"file":"ExtensionDataGatherer.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/ExtensionDataGatherer.ts"],"names":[],"mappings":"AAKA,OAAO,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAC;AAIjD,IAAI,6BAA8D,CAAC;AAEnE;;;GAGG;AACH,MAAM,OAAO,qBAAqB;IAChC,gBAAgB,GAAmD,IAAI,CAAC;IACxE,qBAAqB,GAAkE,IAAI,GAAG,EAAE,CAAC;IACjG,MAAM,CAAC,QAAQ;QACb,IAAI,6BAA6B,EAAE,CAAC;YAClC,OAAO,6BAA6B,CAAC;QACvC,CAAC;QACD,6BAA6B,GAAG,IAAI,qBAAqB,EAAE,CAAC;QAC5D,OAAO,6BAA6B,CAAC;IACvC,CAAC;IAED,MAAM,CAAC,cAAc;QACnB,6BAA6B,GAAG,SAAS,CAAC;IAC5C,CAAC;IAED;;OAEG;IACH,gBAAgB;QACd,MAAM,oBAAoB,GAAG,aAAa,CAAC,8BAA8B,EAAE,CAAC,GAAG,EAAE,CAAC;QAClF,IAAI,CAAC,oBAAoB,IAAI,CAAC,IAAI,CAAC,gBAAgB,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,CAAC;YACjG,OAAO,EAAC,gBAAgB,EAAE,EAAE,EAAE,kBAAkB,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,GAAG,EAAE,EAAC,CAAC;QAChF,CAAC;QACD,MAAM,eAAe,GAAG,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC9E,IAAI,eAAe,EAAE,CAAC;YACpB,OAAO,eAAe,CAAC;QACzB,CAAC;QACD,OAAO,IAAI,CAAC,gBAAgB,CAAC,kBAAkB,CAAC;IAClD,CAAC;IAED,oBAAoB;QAClB,IAAI,IAAI,CAAC,gBAAgB,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACpF,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;QACjF,CAAC;IACH,CAAC;IAED,YAAY,CAAC,eAA+D;QAC1E,IAAI,eAAe,KAAK,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC9C,OAAO;QACT,CAAC;QACD,IAAI,IAAI,CAAC,gBAAgB,KAAK,IAAI,EAAE,CAAC;YACnC,uEAAuE;YACvE,2EAA2E;YAC3E,qEAAqE;YACrE,8CAA8C;YAC9C,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC9B,CAAC;QACD,IAAI,CAAC,gBAAgB,GAAG,eAAe,CAAC;IAC1C,CAAC;CACF","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport type * as TraceEngine from '../../models/trace/trace.js';\n\nimport {TimelinePanel} from './TimelinePanel.js';\n\ntype ExtensionData = TraceEngine.Handlers.ModelHandlers.ExtensionTraceData.ExtensionTraceData;\n\nlet extensionDataGathererInstance: ExtensionDataGatherer|undefined;\n\n/**\n * This class abstracts the source of extension data out by providing a\n * single access point to the performance panel for extension data.\n */\nexport class ExtensionDataGatherer {\n #traceParsedData: TraceEngine.Handlers.Types.TraceParseData|null = null;\n #extensionDataByModel: Map = new Map();\n static instance(): ExtensionDataGatherer {\n if (extensionDataGathererInstance) {\n return extensionDataGathererInstance;\n }\n extensionDataGathererInstance = new ExtensionDataGatherer();\n return extensionDataGathererInstance;\n }\n\n static removeInstance(): void {\n extensionDataGathererInstance = undefined;\n }\n\n /**\n * Gets the data provided by extensions.\n */\n getExtensionData(): ExtensionData {\n const extensionDataEnabled = TimelinePanel.extensionDataVisibilitySetting().get();\n if (!extensionDataEnabled || !this.#traceParsedData || !this.#traceParsedData.ExtensionTraceData) {\n return {extensionMarkers: [], extensionTrackData: [], entryToNode: new Map()};\n }\n const maybeCachedData = this.#extensionDataByModel.get(this.#traceParsedData);\n if (maybeCachedData) {\n return maybeCachedData;\n }\n return this.#traceParsedData.ExtensionTraceData;\n }\n\n saveCurrentModelData(): void {\n if (this.#traceParsedData && !this.#extensionDataByModel.has(this.#traceParsedData)) {\n this.#extensionDataByModel.set(this.#traceParsedData, this.getExtensionData());\n }\n }\n\n modelChanged(traceParsedData: TraceEngine.Handlers.Types.TraceParseData|null): void {\n if (traceParsedData === this.#traceParsedData) {\n return;\n }\n if (this.#traceParsedData !== null) {\n // DevTools extension data is assumed to be useful only for the current\n // trace data (model). As such, if the model changes, we cache the devtools\n // extension data we have collected for the previous model and listen\n // for new data that applies to the new model.\n this.saveCurrentModelData();\n }\n this.#traceParsedData = traceParsedData;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"ExtensionDataGatherer.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/ExtensionDataGatherer.ts"],"names":[],"mappings":"AAKA,OAAO,EAAC,aAAa,EAAC,MAAM,oBAAoB,CAAC;AAIjD,IAAI,6BAA8D,CAAC;AAEnE;;;GAGG;AACH,MAAM,OAAO,qBAAqB;IAChC,YAAY,GAA0C,IAAI,CAAC;IAC3D,qBAAqB,GAAyD,IAAI,GAAG,EAAE,CAAC;IACxF,MAAM,CAAC,QAAQ;QACb,IAAI,6BAA6B,EAAE,CAAC;YAClC,OAAO,6BAA6B,CAAC;QACvC,CAAC;QACD,6BAA6B,GAAG,IAAI,qBAAqB,EAAE,CAAC;QAC5D,OAAO,6BAA6B,CAAC;IACvC,CAAC;IAED,MAAM,CAAC,cAAc;QACnB,6BAA6B,GAAG,SAAS,CAAC;IAC5C,CAAC;IAED;;OAEG;IACH,gBAAgB;QACd,MAAM,oBAAoB,GAAG,aAAa,CAAC,8BAA8B,EAAE,CAAC,GAAG,EAAE,CAAC;QAClF,IAAI,CAAC,oBAAoB,IAAI,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,kBAAkB,EAAE,CAAC;YACzF,OAAO,EAAC,gBAAgB,EAAE,EAAE,EAAE,kBAAkB,EAAE,EAAE,EAAE,WAAW,EAAE,IAAI,GAAG,EAAE,EAAC,CAAC;QAChF,CAAC;QACD,MAAM,eAAe,GAAG,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC1E,IAAI,eAAe,EAAE,CAAC;YACpB,OAAO,eAAe,CAAC;QACzB,CAAC;QACD,OAAO,IAAI,CAAC,YAAY,CAAC,kBAAkB,CAAC;IAC9C,CAAC;IAED,oBAAoB;QAClB,IAAI,IAAI,CAAC,YAAY,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC;YAC5E,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC;IAED,YAAY,CAAC,WAAkD;QAC7D,IAAI,WAAW,KAAK,IAAI,CAAC,YAAY,EAAE,CAAC;YACtC,OAAO;QACT,CAAC;QACD,IAAI,IAAI,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;YAC/B,uEAAuE;YACvE,2EAA2E;YAC3E,qEAAqE;YACrE,8CAA8C;YAC9C,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC9B,CAAC;QACD,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC;IAClC,CAAC;CACF","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport type * as Trace from '../../models/trace/trace.js';\n\nimport {TimelinePanel} from './TimelinePanel.js';\n\ntype ExtensionData = Trace.Handlers.ModelHandlers.ExtensionTraceData.ExtensionTraceData;\n\nlet extensionDataGathererInstance: ExtensionDataGatherer|undefined;\n\n/**\n * This class abstracts the source of extension data out by providing a\n * single access point to the performance panel for extension data.\n */\nexport class ExtensionDataGatherer {\n #parsedTrace: Trace.Handlers.Types.ParsedTrace|null = null;\n #extensionDataByModel: Map = new Map();\n static instance(): ExtensionDataGatherer {\n if (extensionDataGathererInstance) {\n return extensionDataGathererInstance;\n }\n extensionDataGathererInstance = new ExtensionDataGatherer();\n return extensionDataGathererInstance;\n }\n\n static removeInstance(): void {\n extensionDataGathererInstance = undefined;\n }\n\n /**\n * Gets the data provided by extensions.\n */\n getExtensionData(): ExtensionData {\n const extensionDataEnabled = TimelinePanel.extensionDataVisibilitySetting().get();\n if (!extensionDataEnabled || !this.#parsedTrace || !this.#parsedTrace.ExtensionTraceData) {\n return {extensionMarkers: [], extensionTrackData: [], entryToNode: new Map()};\n }\n const maybeCachedData = this.#extensionDataByModel.get(this.#parsedTrace);\n if (maybeCachedData) {\n return maybeCachedData;\n }\n return this.#parsedTrace.ExtensionTraceData;\n }\n\n saveCurrentModelData(): void {\n if (this.#parsedTrace && !this.#extensionDataByModel.has(this.#parsedTrace)) {\n this.#extensionDataByModel.set(this.#parsedTrace, this.getExtensionData());\n }\n }\n\n modelChanged(parsedTrace: Trace.Handlers.Types.ParsedTrace|null): void {\n if (parsedTrace === this.#parsedTrace) {\n return;\n }\n if (this.#parsedTrace !== null) {\n // DevTools extension data is assumed to be useful only for the current\n // trace data (model). As such, if the model changes, we cache the devtools\n // extension data we have collected for the previous model and listen\n // for new data that applies to the new model.\n this.saveCurrentModelData();\n }\n this.#parsedTrace = parsedTrace;\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/ExtensionTrackAppender.d.ts b/public/panels/timeline/ExtensionTrackAppender.d.ts index b1da368cd..1901b8a99 100644 --- a/public/panels/timeline/ExtensionTrackAppender.d.ts +++ b/public/panels/timeline/ExtensionTrackAppender.d.ts @@ -1,15 +1,15 @@ -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import { type CompatibilityTracksAppender, type HighlightedEntryInfo, type TrackAppender, type TrackAppenderName } from './CompatibilityTracksAppender.js'; export declare class ExtensionTrackAppender implements TrackAppender { #private; readonly appenderName: TrackAppenderName; - constructor(compatibilityBuilder: CompatibilityTracksAppender, extensionTracks: TraceEngine.Types.Extensions.ExtensionTrackData); + constructor(compatibilityBuilder: CompatibilityTracksAppender, extensionTracks: Trace.Types.Extensions.ExtensionTrackData); appendTrackAtLevel(trackStartLevel: number, expanded?: boolean): number; - colorForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): string; - titleForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): string; + colorForEvent(event: Trace.Types.Events.Event): string; + titleForEvent(event: Trace.Types.Events.Event): string; /** * Returns the info shown when an event added by this appender * is hovered in the timeline. */ - highlightedEntryInfo(event: TraceEngine.Types.TraceEvents.TraceEventData): HighlightedEntryInfo; + highlightedEntryInfo(event: Trace.Types.Events.Event): HighlightedEntryInfo; } diff --git a/public/panels/timeline/ExtensionTrackAppender.js b/public/panels/timeline/ExtensionTrackAppender.js index ecd20eab9..bc9f2858d 100644 --- a/public/panels/timeline/ExtensionTrackAppender.js +++ b/public/panels/timeline/ExtensionTrackAppender.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as i18n from '../../core/i18n/i18n.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js'; import { buildGroupStyle, buildTrackHeader, getFormattedTime } from './AppenderUtils.js'; import * as Extensions from './extensions/extensions.js'; @@ -72,7 +72,7 @@ export class ExtensionTrackAppender { } colorForEvent(event) { const defaultColor = ThemeSupport.ThemeSupport.instance().getComputedValue('--app-color-rendering'); - if (!TraceEngine.Types.Extensions.isSyntheticExtensionEntry(event)) { + if (!Trace.Types.Extensions.isSyntheticExtensionEntry(event)) { return defaultColor; } return Extensions.ExtensionUI.extensionEntryColor(event); @@ -85,7 +85,7 @@ export class ExtensionTrackAppender { * is hovered in the timeline. */ highlightedEntryInfo(event) { - const title = TraceEngine.Types.Extensions.isSyntheticExtensionEntry(event) && event.args.tooltipText ? + const title = Trace.Types.Extensions.isSyntheticExtensionEntry(event) && event.args.tooltipText ? event.args.tooltipText : this.titleForEvent(event); return { title, formattedTime: getFormattedTime(event.dur) }; diff --git a/public/panels/timeline/ExtensionTrackAppender.js.map b/public/panels/timeline/ExtensionTrackAppender.js.map index 454142dcf..c014ad13d 100644 --- a/public/panels/timeline/ExtensionTrackAppender.js.map +++ b/public/panels/timeline/ExtensionTrackAppender.js.map @@ -1 +1 @@ -{"version":3,"file":"ExtensionTrackAppender.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/ExtensionTrackAppender.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAC7B,OAAO,KAAK,IAAI,MAAM,yBAAyB,CAAC;AAChD,OAAO,KAAK,WAAW,MAAM,6BAA6B,CAAC;AAC3D,OAAO,KAAK,YAAY,MAAM,gDAAgD,CAAC;AAE/E,OAAO,EAAC,eAAe,EAAE,gBAAgB,EAAE,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AAQvF,OAAO,KAAK,UAAU,MAAM,4BAA4B,CAAC;AAEzD,MAAM,SAAS,GAAG;IAChB;;OAEG;IACH,sBAAsB,EAAE,gDAAgD;IACxE;;;OAGG;IACH,eAAe,EAAE,sBAAsB;CACxC,CAAC;AAEF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,2CAA2C,EAAE,SAAS,CAAC,CAAC;AACjG,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAEtE,MAAM,OAAO,sBAAsB;IACxB,YAAY,GAAsB,WAAW,CAAC;IAEvD,uBAAuB,CAAkD;IACzE,qBAAqB,CAA8B;IACnD,YACI,oBAAiD,EACjD,eAAgE;QAClE,IAAI,CAAC,uBAAuB,GAAG,eAAe,CAAC;QAC/C,IAAI,CAAC,qBAAqB,GAAG,oBAAoB,CAAC;IACpD,CAAC;IAED,kBAAkB,CAAC,eAAuB,EAAE,QAAkB;QAC5D,MAAM,eAAe,GACjB,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,uBAAuB,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;QACnH,IAAI,eAAe,KAAK,CAAC,EAAE,CAAC;YAC1B,OAAO,eAAe,CAAC;QACzB,CAAC;QACD,IAAI,CAAC,4BAA4B,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;QAC7D,OAAO,IAAI,CAAC,yBAAyB,CAAC,eAAe,CAAC,CAAC;IACzD,CAAC;IAED;;;;;OAKG;IACH,4BAA4B,CAAC,YAAoB,EAAE,QAAkB;QACnE,MAAM,KAAK,GAAG,eAAe,CAAC,EAAC,eAAe,EAAE,KAAK,EAAE,WAAW,EAAE,IAAI,EAAC,CAAC,CAAC;QAC3E,MAAM,WAAW,GAAG,UAAU,CAAC,SAAS,CAAC,eAAe,EAAE,EAAC,GAAG,EAAE,IAAI,CAAC,uBAAuB,CAAC,IAAI,EAAC,CAAC,CAAC;QACpG,MAAM,KAAK,GAAG,gBAAgB,qDACQ,YAAY,EAAE,WAAW,EAAE,KAAK;QAClE,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACtC,KAAK,CAAC,WAAW,GAAG,UAAU,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC;QACjE,IAAI,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAChE,CAAC;IAED;;;OAGG;IACH,wBAAwB,CAAC,eAAuB,EAAE,WAAmB;QACnE,MAAM,KAAK,GAAG,eAAe,CAAC,EAAC,eAAe,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,WAAW,EAAE,IAAI,EAAC,CAAC,CAAC;QACxG,MAAM,KAAK,GAAG,gBAAgB,qDACQ,eAAe,EAAE,WAAW,EAAE,KAAK;QACrE,iBAAiB,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAChE,CAAC;IAED,yBAAyB,CAAC,eAAuB;QAC/C,IAAI,iBAAiB,GAAG,eAAe,CAAC;QACxC,KAAK,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,uBAAuB,CAAC,cAAc,CAAC,EAAE,CAAC;YAC/F,IAAI,IAAI,CAAC,uBAAuB,CAAC,YAAY,EAAE,CAAC;gBAC9C,mDAAmD;gBACnD,IAAI,CAAC,wBAAwB,CAAC,iBAAiB,EAAE,SAAmB,CAAC,CAAC;YACxE,CAAC;YACD,iBAAiB,GAAG,IAAI,CAAC,qBAAqB,CAAC,mBAAmB,CAAC,OAAO,EAAE,iBAAiB,EAAE,IAAI,CAAC,CAAC;QACvG,CAAC;QACD,OAAO,iBAAiB,CAAC;IAC3B,CAAC;IAED,aAAa,CAAC,KAAmD;QAC/D,MAAM,YAAY,GAAG,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,CAAC;QACpG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,UAAU,CAAC,yBAAyB,CAAC,KAAK,CAAC,EAAE,CAAC;YACnE,OAAO,YAAY,CAAC;QACtB,CAAC;QACD,OAAO,UAAU,CAAC,WAAW,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;IAC3D,CAAC;IAED,aAAa,CAAC,KAAmD;QAC/D,OAAO,KAAK,CAAC,IAAI,CAAC;IACpB,CAAC;IAED;;;OAGG;IACH,oBAAoB,CAAC,KAAmD;QACtE,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,UAAU,CAAC,yBAAyB,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACnG,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACxB,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC9B,OAAO,EAAC,KAAK,EAAE,aAAa,EAAE,gBAAgB,CAAC,KAAK,CAAC,GAAG,CAAC,EAAC,CAAC;IAC7D,CAAC;CACF","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\n\nimport {buildGroupStyle, buildTrackHeader, getFormattedTime} from './AppenderUtils.js';\nimport {\n type CompatibilityTracksAppender,\n type HighlightedEntryInfo,\n type TrackAppender,\n type TrackAppenderName,\n VisualLoggingTrackName,\n} from './CompatibilityTracksAppender.js';\nimport * as Extensions from './extensions/extensions.js';\n\nconst UIStrings = {\n /**\n *@description Text in Timeline Flame Chart Data Provider of the Performance panel\n */\n customTrackDescription: 'This is a custom track added by a third party.',\n /**\n * @description The name of a track, which is a horizontal division of the timeline, synonym with \"swimlane\".\n * @example {A track name} PH1\n */\n customTrackName: '{PH1} — Custom track',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/ExtensionTrackAppender.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport class ExtensionTrackAppender implements TrackAppender {\n readonly appenderName: TrackAppenderName = 'Extension';\n\n #extensionTopLevelTrack: TraceEngine.Types.Extensions.ExtensionTrackData;\n #compatibilityBuilder: CompatibilityTracksAppender;\n constructor(\n compatibilityBuilder: CompatibilityTracksAppender,\n extensionTracks: TraceEngine.Types.Extensions.ExtensionTrackData) {\n this.#extensionTopLevelTrack = extensionTracks;\n this.#compatibilityBuilder = compatibilityBuilder;\n }\n\n appendTrackAtLevel(trackStartLevel: number, expanded?: boolean): number {\n const totalEntryCount =\n Object.values(this.#extensionTopLevelTrack.entriesByTrack).reduce((prev, current) => current.length + prev, 0);\n if (totalEntryCount === 0) {\n return trackStartLevel;\n }\n this.#appendTopLevelHeaderAtLevel(trackStartLevel, expanded);\n return this.#appendExtensionTrackData(trackStartLevel);\n }\n\n /**\n * Appends the top level header for a track. Extension entries can be\n * added to tracks or sub-tracks. In the former case, the top level\n * header corresponds to the track name, in the latter it corresponds\n * to the track group name.\n */\n #appendTopLevelHeaderAtLevel(currentLevel: number, expanded?: boolean): void {\n const style = buildGroupStyle({shareHeaderLine: false, collapsible: true});\n const headerTitle = i18nString(UIStrings.customTrackName, {PH1: this.#extensionTopLevelTrack.name});\n const group = buildTrackHeader(\n VisualLoggingTrackName.EXTENSION, currentLevel, headerTitle, style,\n /* selectable= */ true, expanded);\n group.description = i18nString(UIStrings.customTrackDescription);\n this.#compatibilityBuilder.registerTrackForGroup(group, this);\n }\n\n /**\n * Appends the second level header for a grouped track, which\n * corresponds to the track name itself, instead of the track name.\n */\n #appendSecondLevelHeader(trackStartLevel: number, headerTitle: string): void {\n const style = buildGroupStyle({shareHeaderLine: false, padding: 2, nestingLevel: 1, collapsible: true});\n const group = buildTrackHeader(\n VisualLoggingTrackName.EXTENSION, trackStartLevel, headerTitle, style,\n /* selectable= */ true);\n this.#compatibilityBuilder.registerTrackForGroup(group, this);\n }\n\n #appendExtensionTrackData(trackStartLevel: number): number {\n let currentStartLevel = trackStartLevel;\n for (const [trackName, entries] of Object.entries(this.#extensionTopLevelTrack.entriesByTrack)) {\n if (this.#extensionTopLevelTrack.isTrackGroup) {\n // Second level header is used for only sub-tracks.\n this.#appendSecondLevelHeader(currentStartLevel, trackName as string);\n }\n currentStartLevel = this.#compatibilityBuilder.appendEventsAtLevel(entries, currentStartLevel, this);\n }\n return currentStartLevel;\n }\n\n colorForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): string {\n const defaultColor = ThemeSupport.ThemeSupport.instance().getComputedValue('--app-color-rendering');\n if (!TraceEngine.Types.Extensions.isSyntheticExtensionEntry(event)) {\n return defaultColor;\n }\n return Extensions.ExtensionUI.extensionEntryColor(event);\n }\n\n titleForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): string {\n return event.name;\n }\n\n /**\n * Returns the info shown when an event added by this appender\n * is hovered in the timeline.\n */\n highlightedEntryInfo(event: TraceEngine.Types.TraceEvents.TraceEventData): HighlightedEntryInfo {\n const title = TraceEngine.Types.Extensions.isSyntheticExtensionEntry(event) && event.args.tooltipText ?\n event.args.tooltipText :\n this.titleForEvent(event);\n return {title, formattedTime: getFormattedTime(event.dur)};\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"ExtensionTrackAppender.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/ExtensionTrackAppender.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\n\nimport {buildGroupStyle, buildTrackHeader, getFormattedTime} from './AppenderUtils.js';\nimport {\n type CompatibilityTracksAppender,\n type HighlightedEntryInfo,\n type TrackAppender,\n type TrackAppenderName,\n VisualLoggingTrackName,\n} from './CompatibilityTracksAppender.js';\nimport * as Extensions from './extensions/extensions.js';\n\nconst UIStrings = {\n /**\n *@description Text in Timeline Flame Chart Data Provider of the Performance panel\n */\n customTrackDescription: 'This is a custom track added by a third party.',\n /**\n * @description The name of a track, which is a horizontal division of the timeline, synonym with \"swimlane\".\n * @example {A track name} PH1\n */\n customTrackName: '{PH1} — Custom track',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/ExtensionTrackAppender.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport class ExtensionTrackAppender implements TrackAppender {\n readonly appenderName: TrackAppenderName = 'Extension';\n\n #extensionTopLevelTrack: Trace.Types.Extensions.ExtensionTrackData;\n #compatibilityBuilder: CompatibilityTracksAppender;\n constructor(\n compatibilityBuilder: CompatibilityTracksAppender, extensionTracks: Trace.Types.Extensions.ExtensionTrackData) {\n this.#extensionTopLevelTrack = extensionTracks;\n this.#compatibilityBuilder = compatibilityBuilder;\n }\n\n appendTrackAtLevel(trackStartLevel: number, expanded?: boolean): number {\n const totalEntryCount =\n Object.values(this.#extensionTopLevelTrack.entriesByTrack).reduce((prev, current) => current.length + prev, 0);\n if (totalEntryCount === 0) {\n return trackStartLevel;\n }\n this.#appendTopLevelHeaderAtLevel(trackStartLevel, expanded);\n return this.#appendExtensionTrackData(trackStartLevel);\n }\n\n /**\n * Appends the top level header for a track. Extension entries can be\n * added to tracks or sub-tracks. In the former case, the top level\n * header corresponds to the track name, in the latter it corresponds\n * to the track group name.\n */\n #appendTopLevelHeaderAtLevel(currentLevel: number, expanded?: boolean): void {\n const style = buildGroupStyle({shareHeaderLine: false, collapsible: true});\n const headerTitle = i18nString(UIStrings.customTrackName, {PH1: this.#extensionTopLevelTrack.name});\n const group = buildTrackHeader(\n VisualLoggingTrackName.EXTENSION, currentLevel, headerTitle, style,\n /* selectable= */ true, expanded);\n group.description = i18nString(UIStrings.customTrackDescription);\n this.#compatibilityBuilder.registerTrackForGroup(group, this);\n }\n\n /**\n * Appends the second level header for a grouped track, which\n * corresponds to the track name itself, instead of the track name.\n */\n #appendSecondLevelHeader(trackStartLevel: number, headerTitle: string): void {\n const style = buildGroupStyle({shareHeaderLine: false, padding: 2, nestingLevel: 1, collapsible: true});\n const group = buildTrackHeader(\n VisualLoggingTrackName.EXTENSION, trackStartLevel, headerTitle, style,\n /* selectable= */ true);\n this.#compatibilityBuilder.registerTrackForGroup(group, this);\n }\n\n #appendExtensionTrackData(trackStartLevel: number): number {\n let currentStartLevel = trackStartLevel;\n for (const [trackName, entries] of Object.entries(this.#extensionTopLevelTrack.entriesByTrack)) {\n if (this.#extensionTopLevelTrack.isTrackGroup) {\n // Second level header is used for only sub-tracks.\n this.#appendSecondLevelHeader(currentStartLevel, trackName as string);\n }\n currentStartLevel = this.#compatibilityBuilder.appendEventsAtLevel(entries, currentStartLevel, this);\n }\n return currentStartLevel;\n }\n\n colorForEvent(event: Trace.Types.Events.Event): string {\n const defaultColor = ThemeSupport.ThemeSupport.instance().getComputedValue('--app-color-rendering');\n if (!Trace.Types.Extensions.isSyntheticExtensionEntry(event)) {\n return defaultColor;\n }\n return Extensions.ExtensionUI.extensionEntryColor(event);\n }\n\n titleForEvent(event: Trace.Types.Events.Event): string {\n return event.name;\n }\n\n /**\n * Returns the info shown when an event added by this appender\n * is hovered in the timeline.\n */\n highlightedEntryInfo(event: Trace.Types.Events.Event): HighlightedEntryInfo {\n const title = Trace.Types.Extensions.isSyntheticExtensionEntry(event) && event.args.tooltipText ?\n event.args.tooltipText :\n this.titleForEvent(event);\n return {title, formattedTime: getFormattedTime(event.dur)};\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/FreshRecording.d.ts b/public/panels/timeline/FreshRecording.d.ts index dc67e068d..7140cea77 100644 --- a/public/panels/timeline/FreshRecording.d.ts +++ b/public/panels/timeline/FreshRecording.d.ts @@ -1,4 +1,4 @@ -import type * as TraceEngine from '../../models/trace/trace.js'; +import type * as Trace from '../../models/trace/trace.js'; /** * In multiple places we need to know if the trace we are working on is fresh * or not. We cannot store that data in the trace file's metadata (otherwise a @@ -10,6 +10,6 @@ export declare class Tracker { static instance(opts?: { forceNew: boolean; }): Tracker; - registerFreshRecording(data: TraceEngine.Handlers.Types.TraceParseData): void; - recordingIsFresh(data: TraceEngine.Handlers.Types.TraceParseData): boolean; + registerFreshRecording(data: Trace.Handlers.Types.ParsedTrace): void; + recordingIsFresh(data: Trace.Handlers.Types.ParsedTrace): boolean; } diff --git a/public/panels/timeline/FreshRecording.js.map b/public/panels/timeline/FreshRecording.js.map index 3732ee886..c0866c076 100644 --- a/public/panels/timeline/FreshRecording.js.map +++ b/public/panels/timeline/FreshRecording.js.map @@ -1 +1 @@ -{"version":3,"file":"FreshRecording.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/FreshRecording.ts"],"names":[],"mappings":"AAKA,IAAI,QAAQ,GAAiB,IAAI,CAAC;AAElC;;;;;IAKI;AACJ,MAAM,OAAO,OAAO;IAClB,gBAAgB,GAAuD,IAAI,OAAO,EAAE,CAAC;IAErF,MAAM,CAAC,QAAQ,CAAC,OAA4B,EAAC,QAAQ,EAAE,KAAK,EAAC;QAC3D,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC/B,QAAQ,GAAG,IAAI,OAAO,EAAE,CAAC;QAC3B,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,sBAAsB,CAAC,IAA+C;QACpE,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,gBAAgB,CAAC,IAA+C;QAC9D,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC;CACF","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport type * as TraceEngine from '../../models/trace/trace.js';\n\nlet instance: Tracker|null = null;\n\n/**\n * In multiple places we need to know if the trace we are working on is fresh\n * or not. We cannot store that data in the trace file's metadata (otherwise a\n * loaded trace file could claim to be fresh), so we store it here. When a new trace\n * is loaded, we set this flag accordingly.\n **/\nexport class Tracker {\n #freshRecordings: WeakSet = new WeakSet();\n\n static instance(opts: {forceNew: boolean} = {forceNew: false}): Tracker {\n if (!instance || opts.forceNew) {\n instance = new Tracker();\n }\n return instance;\n }\n\n registerFreshRecording(data: TraceEngine.Handlers.Types.TraceParseData): void {\n this.#freshRecordings.add(data);\n }\n\n recordingIsFresh(data: TraceEngine.Handlers.Types.TraceParseData): boolean {\n return this.#freshRecordings.has(data);\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"FreshRecording.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/FreshRecording.ts"],"names":[],"mappings":"AAKA,IAAI,QAAQ,GAAiB,IAAI,CAAC;AAElC;;;;;IAKI;AACJ,MAAM,OAAO,OAAO;IAClB,gBAAgB,GAA8C,IAAI,OAAO,EAAE,CAAC;IAE5E,MAAM,CAAC,QAAQ,CAAC,OAA4B,EAAC,QAAQ,EAAE,KAAK,EAAC;QAC3D,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC/B,QAAQ,GAAG,IAAI,OAAO,EAAE,CAAC;QAC3B,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,sBAAsB,CAAC,IAAsC;QAC3D,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,gBAAgB,CAAC,IAAsC;QACrD,OAAO,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC;CACF","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport type * as Trace from '../../models/trace/trace.js';\n\nlet instance: Tracker|null = null;\n\n/**\n * In multiple places we need to know if the trace we are working on is fresh\n * or not. We cannot store that data in the trace file's metadata (otherwise a\n * loaded trace file could claim to be fresh), so we store it here. When a new trace\n * is loaded, we set this flag accordingly.\n **/\nexport class Tracker {\n #freshRecordings: WeakSet = new WeakSet();\n\n static instance(opts: {forceNew: boolean} = {forceNew: false}): Tracker {\n if (!instance || opts.forceNew) {\n instance = new Tracker();\n }\n return instance;\n }\n\n registerFreshRecording(data: Trace.Handlers.Types.ParsedTrace): void {\n this.#freshRecordings.add(data);\n }\n\n recordingIsFresh(data: Trace.Handlers.Types.ParsedTrace): boolean {\n return this.#freshRecordings.has(data);\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/FreshRecording.test.js b/public/panels/timeline/FreshRecording.test.js index 216e64f0e..bfa5dc872 100644 --- a/public/panels/timeline/FreshRecording.test.js +++ b/public/panels/timeline/FreshRecording.test.js @@ -7,14 +7,14 @@ import * as Timeline from './timeline.js'; describeWithEnvironment('FreshRecordingTracker', () => { it('knows that a recording has been registered as fresh', async function () { const instance = Timeline.FreshRecording.Tracker.instance({ forceNew: true }); - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - instance.registerFreshRecording(traceData); - assert.isTrue(instance.recordingIsFresh(traceData)); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + instance.registerFreshRecording(parsedTrace); + assert.isTrue(instance.recordingIsFresh(parsedTrace)); }); it('knows that un-registered recordings are not fresh', async function () { const instance = Timeline.FreshRecording.Tracker.instance({ forceNew: true }); - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - assert.isFalse(instance.recordingIsFresh(traceData)); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + assert.isFalse(instance.recordingIsFresh(parsedTrace)); }); }); //# sourceMappingURL=FreshRecording.test.js.map \ No newline at end of file diff --git a/public/panels/timeline/FreshRecording.test.js.map b/public/panels/timeline/FreshRecording.test.js.map index 2700072e6..83396036d 100644 --- a/public/panels/timeline/FreshRecording.test.js.map +++ b/public/panels/timeline/FreshRecording.test.js.map @@ -1 +1 @@ -{"version":3,"file":"FreshRecording.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/FreshRecording.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,EAAC,uBAAuB,EAAC,MAAM,qCAAqC,CAAC;AAC5E,OAAO,EAAC,WAAW,EAAC,MAAM,8BAA8B,CAAC;AAEzD,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAE1C,uBAAuB,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACpD,EAAE,CAAC,qDAAqD,EAAE,KAAK;QAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAC,QAAQ,EAAE,IAAI,EAAC,CAAC,CAAC;QAC5E,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;QAC3E,QAAQ,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC;QAC3C,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK;QAC3D,MAAM,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAC,QAAQ,EAAE,IAAI,EAAC,CAAC,CAAC;QAC5E,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;QAC3E,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\n\nimport * as Timeline from './timeline.js';\n\ndescribeWithEnvironment('FreshRecordingTracker', () => {\n it('knows that a recording has been registered as fresh', async function() {\n const instance = Timeline.FreshRecording.Tracker.instance({forceNew: true});\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n instance.registerFreshRecording(traceData);\n assert.isTrue(instance.recordingIsFresh(traceData));\n });\n\n it('knows that un-registered recordings are not fresh', async function() {\n const instance = Timeline.FreshRecording.Tracker.instance({forceNew: true});\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n assert.isFalse(instance.recordingIsFresh(traceData));\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"FreshRecording.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/FreshRecording.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,EAAC,uBAAuB,EAAC,MAAM,qCAAqC,CAAC;AAC5E,OAAO,EAAC,WAAW,EAAC,MAAM,8BAA8B,CAAC;AAEzD,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAE1C,uBAAuB,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACpD,EAAE,CAAC,qDAAqD,EAAE,KAAK;QAC7D,MAAM,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAC,QAAQ,EAAE,IAAI,EAAC,CAAC,CAAC;QAC5E,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;QAC7E,QAAQ,CAAC,sBAAsB,CAAC,WAAW,CAAC,CAAC;QAC7C,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK;QAC3D,MAAM,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAC,QAAQ,EAAE,IAAI,EAAC,CAAC,CAAC;QAC5E,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;QAC7E,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\n\nimport * as Timeline from './timeline.js';\n\ndescribeWithEnvironment('FreshRecordingTracker', () => {\n it('knows that a recording has been registered as fresh', async function() {\n const instance = Timeline.FreshRecording.Tracker.instance({forceNew: true});\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n instance.registerFreshRecording(parsedTrace);\n assert.isTrue(instance.recordingIsFresh(parsedTrace));\n });\n\n it('knows that un-registered recordings are not fresh', async function() {\n const instance = Timeline.FreshRecording.Tracker.instance({forceNew: true});\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n assert.isFalse(instance.recordingIsFresh(parsedTrace));\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/GPUTrackAppender.d.ts b/public/panels/timeline/GPUTrackAppender.d.ts index d4235030c..619cf3312 100644 --- a/public/panels/timeline/GPUTrackAppender.d.ts +++ b/public/panels/timeline/GPUTrackAppender.d.ts @@ -1,9 +1,9 @@ -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import { type CompatibilityTracksAppender, type TrackAppender, type TrackAppenderName } from './CompatibilityTracksAppender.js'; export declare class GPUTrackAppender implements TrackAppender { #private; readonly appenderName: TrackAppenderName; - constructor(compatibilityBuilder: CompatibilityTracksAppender, traceParsedData: TraceEngine.Handlers.Types.TraceParseData); + constructor(compatibilityBuilder: CompatibilityTracksAppender, parsedTrace: Trace.Handlers.Types.ParsedTrace); /** * Appends into the flame chart data the data corresponding to the * GPU track. @@ -17,5 +17,5 @@ export declare class GPUTrackAppender implements TrackAppender { /** * Gets the color an event added by this appender should be rendered with. */ - colorForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): string; + colorForEvent(event: Trace.Types.Events.Event): string; } diff --git a/public/panels/timeline/GPUTrackAppender.js b/public/panels/timeline/GPUTrackAppender.js index 627e3f50f..d86972c4a 100644 --- a/public/panels/timeline/GPUTrackAppender.js +++ b/public/panels/timeline/GPUTrackAppender.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as i18n from '../../core/i18n/i18n.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js'; import { buildGroupStyle, buildTrackHeader } from './AppenderUtils.js'; const UIStrings = { @@ -16,10 +16,10 @@ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); export class GPUTrackAppender { appenderName = 'GPU'; #compatibilityBuilder; - #traceParsedData; - constructor(compatibilityBuilder, traceParsedData) { + #parsedTrace; + constructor(compatibilityBuilder, parsedTrace) { this.#compatibilityBuilder = compatibilityBuilder; - this.#traceParsedData = traceParsedData; + this.#parsedTrace = parsedTrace; } /** * Appends into the flame chart data the data corresponding to the @@ -31,7 +31,7 @@ export class GPUTrackAppender { * appended the track's events. */ appendTrackAtLevel(trackStartLevel, expanded) { - const gpuEvents = this.#traceParsedData.GPU.mainGPUThreadTasks; + const gpuEvents = this.#parsedTrace.GPU.mainGPUThreadTasks; if (gpuEvents.length === 0) { return trackStartLevel; } @@ -63,7 +63,7 @@ export class GPUTrackAppender { * Gets the color an event added by this appender should be rendered with. */ colorForEvent(event) { - if (!TraceEngine.Types.TraceEvents.isTraceEventGPUTask(event)) { + if (!Trace.Types.Events.isGPUTask(event)) { throw new Error(`Unexpected GPU Task: The event's type is '${event.name}'`); } return ThemeSupport.ThemeSupport.instance().getComputedValue('--app-color-painting'); diff --git a/public/panels/timeline/GPUTrackAppender.js.map b/public/panels/timeline/GPUTrackAppender.js.map index b9ef952d3..2ee626b1b 100644 --- a/public/panels/timeline/GPUTrackAppender.js.map +++ b/public/panels/timeline/GPUTrackAppender.js.map @@ -1 +1 @@ -{"version":3,"file":"GPUTrackAppender.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/GPUTrackAppender.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAC7B,OAAO,KAAK,IAAI,MAAM,yBAAyB,CAAC;AAChD,OAAO,KAAK,WAAW,MAAM,6BAA6B,CAAC;AAC3D,OAAO,KAAK,YAAY,MAAM,gDAAgD,CAAC;AAE/E,OAAO,EAAC,eAAe,EAAE,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AAQrE,MAAM,SAAS,GAAG;IAChB;;OAEG;IACH,GAAG,EAAE,KAAK;CACX,CAAC;AAEF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,qCAAqC,EAAE,SAAS,CAAC,CAAC;AAC3F,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAEtE,MAAM,OAAO,gBAAgB;IAClB,YAAY,GAAsB,KAAK,CAAC;IAEjD,qBAAqB,CAA8B;IACnD,gBAAgB,CAAsD;IAEtE,YACI,oBAAiD,EAAE,eAA0D;QAC/G,IAAI,CAAC,qBAAqB,GAAG,oBAAoB,CAAC;QAClD,IAAI,CAAC,gBAAgB,GAAG,eAAe,CAAC;IAC1C,CAAC;IAED;;;;;;;;OAQG;IACH,kBAAkB,CAAC,eAAuB,EAAE,QAA4B;QACtE,MAAM,SAAS,GAAG,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,kBAAkB,CAAC;QAC/D,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO,eAAe,CAAC;QACzB,CAAC;QACD,IAAI,CAAC,yBAAyB,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC,qBAAqB,CAAC,mBAAmB,CAAC,SAAS,EAAE,eAAe,EAAE,IAAI,CAAC,CAAC;IAC1F,CAAC;IAED;;;;;;;;;OASG;IACH,yBAAyB,CAAC,YAAoB,EAAE,QAAkB;QAChE,MAAM,KAAK,GAAG,eAAe,CAAC,EAAC,WAAW,EAAE,KAAK,EAAC,CAAC,CAAC;QACpD,MAAM,KAAK,GAAG,gBAAgB,yCACE,YAAY,EAAE,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAClH,IAAI,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAChE,CAAC;IAED;;;;;MAKE;IAEF;;OAEG;IACH,aAAa,CAAC,KAAmD;QAC/D,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9D,MAAM,IAAI,KAAK,CAAC,6CAA6C,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC;QAC9E,CAAC;QACD,OAAO,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,gBAAgB,CAAC,sBAAsB,CAAC,CAAC;IACvF,CAAC;CACF","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\n\nimport {buildGroupStyle, buildTrackHeader} from './AppenderUtils.js';\nimport {\n type CompatibilityTracksAppender,\n type TrackAppender,\n type TrackAppenderName,\n VisualLoggingTrackName,\n} from './CompatibilityTracksAppender.js';\n\nconst UIStrings = {\n /**\n *@description Text in Timeline Flame Chart Data Provider of the Performance panel\n */\n gpu: 'GPU',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/GPUTrackAppender.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport class GPUTrackAppender implements TrackAppender {\n readonly appenderName: TrackAppenderName = 'GPU';\n\n #compatibilityBuilder: CompatibilityTracksAppender;\n #traceParsedData: Readonly;\n\n constructor(\n compatibilityBuilder: CompatibilityTracksAppender, traceParsedData: TraceEngine.Handlers.Types.TraceParseData) {\n this.#compatibilityBuilder = compatibilityBuilder;\n this.#traceParsedData = traceParsedData;\n }\n\n /**\n * Appends into the flame chart data the data corresponding to the\n * GPU track.\n * @param trackStartLevel the horizontal level of the flame chart events where\n * the track's events will start being appended.\n * @param expanded wether the track should be rendered expanded.\n * @returns the first available level to append more data after having\n * appended the track's events.\n */\n appendTrackAtLevel(trackStartLevel: number, expanded?: boolean|undefined): number {\n const gpuEvents = this.#traceParsedData.GPU.mainGPUThreadTasks;\n if (gpuEvents.length === 0) {\n return trackStartLevel;\n }\n this.#appendTrackHeaderAtLevel(trackStartLevel, expanded);\n return this.#compatibilityBuilder.appendEventsAtLevel(gpuEvents, trackStartLevel, this);\n }\n\n /**\n * Adds into the flame chart data the header corresponding to the\n * GPU track. A header is added in the shape of a group in the\n * flame chart data. A group has a predefined style and a reference\n * to the definition of the legacy track (which should be removed\n * in the future).\n * @param currentLevel the flame chart level at which the header is\n * appended.\n * @param expanded wether the track should be rendered expanded.\n */\n #appendTrackHeaderAtLevel(currentLevel: number, expanded?: boolean): void {\n const style = buildGroupStyle({collapsible: false});\n const group = buildTrackHeader(\n VisualLoggingTrackName.GPU, currentLevel, i18nString(UIStrings.gpu), style, /* selectable= */ true, expanded);\n this.#compatibilityBuilder.registerTrackForGroup(group, this);\n }\n\n /*\n ------------------------------------------------------------------------------------\n The following methods are invoked by the flame chart renderer to query features about\n events on rendering.\n ------------------------------------------------------------------------------------\n */\n\n /**\n * Gets the color an event added by this appender should be rendered with.\n */\n colorForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): string {\n if (!TraceEngine.Types.TraceEvents.isTraceEventGPUTask(event)) {\n throw new Error(`Unexpected GPU Task: The event's type is '${event.name}'`);\n }\n return ThemeSupport.ThemeSupport.instance().getComputedValue('--app-color-painting');\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"GPUTrackAppender.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/GPUTrackAppender.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAC7B,OAAO,KAAK,IAAI,MAAM,yBAAyB,CAAC;AAChD,OAAO,KAAK,KAAK,MAAM,6BAA6B,CAAC;AACrD,OAAO,KAAK,YAAY,MAAM,gDAAgD,CAAC;AAE/E,OAAO,EAAC,eAAe,EAAE,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AAQrE,MAAM,SAAS,GAAG;IAChB;;OAEG;IACH,GAAG,EAAE,KAAK;CACX,CAAC;AAEF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,qCAAqC,EAAE,SAAS,CAAC,CAAC;AAC3F,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAEtE,MAAM,OAAO,gBAAgB;IAClB,YAAY,GAAsB,KAAK,CAAC;IAEjD,qBAAqB,CAA8B;IACnD,YAAY,CAA6C;IAEzD,YAAY,oBAAiD,EAAE,WAA6C;QAC1G,IAAI,CAAC,qBAAqB,GAAG,oBAAoB,CAAC;QAClD,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC;IAClC,CAAC;IAED;;;;;;;;OAQG;IACH,kBAAkB,CAAC,eAAuB,EAAE,QAA4B;QACtE,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,kBAAkB,CAAC;QAC3D,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3B,OAAO,eAAe,CAAC;QACzB,CAAC;QACD,IAAI,CAAC,yBAAyB,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC,qBAAqB,CAAC,mBAAmB,CAAC,SAAS,EAAE,eAAe,EAAE,IAAI,CAAC,CAAC;IAC1F,CAAC;IAED;;;;;;;;;OASG;IACH,yBAAyB,CAAC,YAAoB,EAAE,QAAkB;QAChE,MAAM,KAAK,GAAG,eAAe,CAAC,EAAC,WAAW,EAAE,KAAK,EAAC,CAAC,CAAC;QACpD,MAAM,KAAK,GAAG,gBAAgB,yCACE,YAAY,EAAE,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAClH,IAAI,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAChE,CAAC;IAED;;;;;MAKE;IAEF;;OAEG;IACH,aAAa,CAAC,KAA+B;QAC3C,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC;YACzC,MAAM,IAAI,KAAK,CAAC,6CAA6C,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC;QAC9E,CAAC;QACD,OAAO,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,gBAAgB,CAAC,sBAAsB,CAAC,CAAC;IACvF,CAAC;CACF","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\n\nimport {buildGroupStyle, buildTrackHeader} from './AppenderUtils.js';\nimport {\n type CompatibilityTracksAppender,\n type TrackAppender,\n type TrackAppenderName,\n VisualLoggingTrackName,\n} from './CompatibilityTracksAppender.js';\n\nconst UIStrings = {\n /**\n *@description Text in Timeline Flame Chart Data Provider of the Performance panel\n */\n gpu: 'GPU',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/GPUTrackAppender.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport class GPUTrackAppender implements TrackAppender {\n readonly appenderName: TrackAppenderName = 'GPU';\n\n #compatibilityBuilder: CompatibilityTracksAppender;\n #parsedTrace: Readonly;\n\n constructor(compatibilityBuilder: CompatibilityTracksAppender, parsedTrace: Trace.Handlers.Types.ParsedTrace) {\n this.#compatibilityBuilder = compatibilityBuilder;\n this.#parsedTrace = parsedTrace;\n }\n\n /**\n * Appends into the flame chart data the data corresponding to the\n * GPU track.\n * @param trackStartLevel the horizontal level of the flame chart events where\n * the track's events will start being appended.\n * @param expanded wether the track should be rendered expanded.\n * @returns the first available level to append more data after having\n * appended the track's events.\n */\n appendTrackAtLevel(trackStartLevel: number, expanded?: boolean|undefined): number {\n const gpuEvents = this.#parsedTrace.GPU.mainGPUThreadTasks;\n if (gpuEvents.length === 0) {\n return trackStartLevel;\n }\n this.#appendTrackHeaderAtLevel(trackStartLevel, expanded);\n return this.#compatibilityBuilder.appendEventsAtLevel(gpuEvents, trackStartLevel, this);\n }\n\n /**\n * Adds into the flame chart data the header corresponding to the\n * GPU track. A header is added in the shape of a group in the\n * flame chart data. A group has a predefined style and a reference\n * to the definition of the legacy track (which should be removed\n * in the future).\n * @param currentLevel the flame chart level at which the header is\n * appended.\n * @param expanded wether the track should be rendered expanded.\n */\n #appendTrackHeaderAtLevel(currentLevel: number, expanded?: boolean): void {\n const style = buildGroupStyle({collapsible: false});\n const group = buildTrackHeader(\n VisualLoggingTrackName.GPU, currentLevel, i18nString(UIStrings.gpu), style, /* selectable= */ true, expanded);\n this.#compatibilityBuilder.registerTrackForGroup(group, this);\n }\n\n /*\n ------------------------------------------------------------------------------------\n The following methods are invoked by the flame chart renderer to query features about\n events on rendering.\n ------------------------------------------------------------------------------------\n */\n\n /**\n * Gets the color an event added by this appender should be rendered with.\n */\n colorForEvent(event: Trace.Types.Events.Event): string {\n if (!Trace.Types.Events.isGPUTask(event)) {\n throw new Error(`Unexpected GPU Task: The event's type is '${event.name}'`);\n }\n return ThemeSupport.ThemeSupport.instance().getComputedValue('--app-color-painting');\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/Initiators.d.ts b/public/panels/timeline/Initiators.d.ts index 4a82452a2..ea424adb5 100644 --- a/public/panels/timeline/Initiators.d.ts +++ b/public/panels/timeline/Initiators.d.ts @@ -1,7 +1,7 @@ -import type * as TraceEngine from '../../models/trace/trace.js'; +import type * as Trace from '../../models/trace/trace.js'; export interface InitiatorData { - event: TraceEngine.Types.TraceEvents.TraceEventData; - initiator: TraceEngine.Types.TraceEvents.TraceEventData; + event: Trace.Types.Events.Event; + initiator: Trace.Types.Events.Event; isEntryHidden?: boolean; isInitiatorHidden?: boolean; } @@ -12,5 +12,5 @@ export interface InitiatorData { * entire chain: for each, we see if it had an initiator, and * work backwards to draw each one, as well as the events initiated directly by the entry. */ -export declare function initiatorsDataToDraw(traceParsedData: TraceEngine.Handlers.Types.TraceParseData, selectedEvent: TraceEngine.Types.TraceEvents.TraceEventData, hiddenEntries: TraceEngine.Types.TraceEvents.TraceEventData[], expandableEntries: TraceEngine.Types.TraceEvents.TraceEventData[]): readonly InitiatorData[]; -export declare function initiatorsDataToDrawForNetwork(traceParsedData: TraceEngine.Handlers.Types.TraceParseData, selectedEvent: TraceEngine.Types.TraceEvents.TraceEventData): readonly InitiatorData[]; +export declare function initiatorsDataToDraw(parsedTrace: Trace.Handlers.Types.ParsedTrace, selectedEvent: Trace.Types.Events.Event, hiddenEntries: Trace.Types.Events.Event[], expandableEntries: Trace.Types.Events.Event[]): readonly InitiatorData[]; +export declare function initiatorsDataToDrawForNetwork(parsedTrace: Trace.Handlers.Types.ParsedTrace, selectedEvent: Trace.Types.Events.Event): readonly InitiatorData[]; diff --git a/public/panels/timeline/Initiators.js b/public/panels/timeline/Initiators.js index 87d1d83d1..8c483af06 100644 --- a/public/panels/timeline/Initiators.js +++ b/public/panels/timeline/Initiators.js @@ -8,20 +8,20 @@ * entire chain: for each, we see if it had an initiator, and * work backwards to draw each one, as well as the events initiated directly by the entry. */ -export function initiatorsDataToDraw(traceParsedData, selectedEvent, hiddenEntries, expandableEntries) { +export function initiatorsDataToDraw(parsedTrace, selectedEvent, hiddenEntries, expandableEntries) { const initiatorsData = [ - ...findInitiatorDataPredecessors(traceParsedData, selectedEvent, traceParsedData.Initiators.eventToInitiator), - ...findInitiatorDataDirectSuccessors(selectedEvent, traceParsedData.Initiators.initiatorToEvents), + ...findInitiatorDataPredecessors(parsedTrace, selectedEvent, parsedTrace.Initiators.eventToInitiator), + ...findInitiatorDataDirectSuccessors(selectedEvent, parsedTrace.Initiators.initiatorToEvents), ]; // For each InitiatorData, call a function that makes sure that neither the initiator or initiated entry is hidden. // If they are, it will reassign the event or initiator to the closest ancestor. - initiatorsData.forEach(initiatorData => getClosestVisibleInitiatorEntriesAncestors(initiatorData, expandableEntries, hiddenEntries, traceParsedData)); + initiatorsData.forEach(initiatorData => getClosestVisibleInitiatorEntriesAncestors(initiatorData, expandableEntries, hiddenEntries, parsedTrace)); return initiatorsData; } -export function initiatorsDataToDrawForNetwork(traceParsedData, selectedEvent) { - return findInitiatorDataPredecessors(traceParsedData, selectedEvent, traceParsedData.NetworkRequests.eventToInitiator); +export function initiatorsDataToDrawForNetwork(parsedTrace, selectedEvent) { + return findInitiatorDataPredecessors(parsedTrace, selectedEvent, parsedTrace.NetworkRequests.eventToInitiator); } -function findInitiatorDataPredecessors(traceParsedData, selectedEvent, eventToInitiator) { +function findInitiatorDataPredecessors(parsedTrace, selectedEvent, eventToInitiator) { const initiatorsData = []; let currentEvent = selectedEvent; const visited = new Set(); @@ -42,7 +42,7 @@ function findInitiatorDataPredecessors(traceParsedData, selectedEvent, eventToIn visited.add(currentEvent); continue; } - const nodeForCurrentEvent = traceParsedData.Renderer.entryToNode.get(currentEvent); + const nodeForCurrentEvent = parsedTrace.Renderer.entryToNode.get(currentEvent); if (!nodeForCurrentEvent) { // Should not happen - if it does something odd is going // on so let's give up. @@ -71,9 +71,9 @@ function findInitiatorDataDirectSuccessors(selectedEvent, initiatorToEvents) { * the actual initiator or initiated event might be hidden form the flame chart. * If neither entry is hidden, this function returns the initial initiatorData object. */ -function getClosestVisibleInitiatorEntriesAncestors(initiatorData, expandableEntries, hiddenEntries, traceParsedData) { +function getClosestVisibleInitiatorEntriesAncestors(initiatorData, expandableEntries, hiddenEntries, parsedTrace) { if (hiddenEntries.includes(initiatorData.event)) { - let nextParent = traceParsedData.Renderer.entryToNode.get(initiatorData.event)?.parent; + let nextParent = parsedTrace.Renderer.entryToNode.get(initiatorData.event)?.parent; while (nextParent?.entry && !expandableEntries.includes(nextParent?.entry)) { nextParent = nextParent.parent ?? undefined; } @@ -81,7 +81,7 @@ function getClosestVisibleInitiatorEntriesAncestors(initiatorData, expandableEnt initiatorData.isEntryHidden = true; } if (hiddenEntries.includes(initiatorData.initiator)) { - let nextParent = traceParsedData.Renderer.entryToNode.get(initiatorData.initiator)?.parent; + let nextParent = parsedTrace.Renderer.entryToNode.get(initiatorData.initiator)?.parent; while (nextParent?.entry && !expandableEntries.includes(nextParent?.entry)) { nextParent = nextParent.parent ?? undefined; } diff --git a/public/panels/timeline/Initiators.js.map b/public/panels/timeline/Initiators.js.map index 4b49eb211..ad947cfae 100644 --- a/public/panels/timeline/Initiators.js.map +++ b/public/panels/timeline/Initiators.js.map @@ -1 +1 @@ -{"version":3,"file":"Initiators.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/Initiators.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as TraceEngine from '../../models/trace/trace.js';\n\nexport interface InitiatorData {\n event: TraceEngine.Types.TraceEvents.TraceEventData;\n initiator: TraceEngine.Types.TraceEvents.TraceEventData;\n isEntryHidden?: boolean;\n isInitiatorHidden?: boolean;\n}\n/**\n * Given an event that the user has selected, this function returns all the\n * data of events and their initiators that need to be drawn on the flamechart.\n * The reason that this can return multiple InitiatorEntry objects is because we draw the\n * entire chain: for each, we see if it had an initiator, and\n * work backwards to draw each one, as well as the events initiated directly by the entry.\n */\nexport function initiatorsDataToDraw(\n traceParsedData: TraceEngine.Handlers.Types.TraceParseData,\n selectedEvent: TraceEngine.Types.TraceEvents.TraceEventData,\n hiddenEntries: TraceEngine.Types.TraceEvents.TraceEventData[],\n expandableEntries: TraceEngine.Types.TraceEvents.TraceEventData[],\n ): readonly InitiatorData[] {\n const initiatorsData = [\n ...findInitiatorDataPredecessors(traceParsedData, selectedEvent, traceParsedData.Initiators.eventToInitiator),\n ...findInitiatorDataDirectSuccessors(selectedEvent, traceParsedData.Initiators.initiatorToEvents),\n ];\n\n // For each InitiatorData, call a function that makes sure that neither the initiator or initiated entry is hidden.\n // If they are, it will reassign the event or initiator to the closest ancestor.\n initiatorsData.forEach(\n initiatorData =>\n getClosestVisibleInitiatorEntriesAncestors(initiatorData, expandableEntries, hiddenEntries, traceParsedData));\n return initiatorsData;\n}\n\nexport function initiatorsDataToDrawForNetwork(\n traceParsedData: TraceEngine.Handlers.Types.TraceParseData,\n selectedEvent: TraceEngine.Types.TraceEvents.TraceEventData,\n ): readonly InitiatorData[] {\n return findInitiatorDataPredecessors(\n traceParsedData, selectedEvent, traceParsedData.NetworkRequests.eventToInitiator);\n}\n\nfunction findInitiatorDataPredecessors(\n traceParsedData: TraceEngine.Handlers.Types.TraceParseData,\n selectedEvent: TraceEngine.Types.TraceEvents.TraceEventData,\n eventToInitiator: Map,\n ): readonly InitiatorData[] {\n const initiatorsData: InitiatorData[] = [];\n\n let currentEvent: TraceEngine.Types.TraceEvents.TraceEventData|null = selectedEvent;\n const visited = new Set();\n visited.add(currentEvent);\n\n // Build event initiator data up to the selected one\n while (currentEvent) {\n const currentInitiator = eventToInitiator.get(currentEvent);\n\n if (currentInitiator) {\n if (visited.has(currentInitiator)) {\n break;\n }\n // Store the current initiator data, and then set the initiator to\n // be the current event, so we work back through the\n // trace and find the initiator of the initiator, and so\n // on...\n initiatorsData.push({event: currentEvent, initiator: currentInitiator});\n currentEvent = currentInitiator;\n visited.add(currentEvent);\n continue;\n }\n\n const nodeForCurrentEvent = traceParsedData.Renderer.entryToNode.get(currentEvent);\n if (!nodeForCurrentEvent) {\n // Should not happen - if it does something odd is going\n // on so let's give up.\n currentEvent = null;\n break;\n }\n\n // Go up to the parent, and loop again.\n currentEvent = nodeForCurrentEvent.parent?.entry || null;\n }\n\n return initiatorsData;\n}\n\nfunction findInitiatorDataDirectSuccessors(\n selectedEvent: TraceEngine.Types.TraceEvents.TraceEventData,\n initiatorToEvents:\n Map,\n ): readonly InitiatorData[] {\n const initiatorsData: InitiatorData[] = [];\n\n // Add all of the initiated events to the initiatorsData array.\n const eventsInitiatedByCurrent = initiatorToEvents.get(selectedEvent);\n if (eventsInitiatedByCurrent) {\n eventsInitiatedByCurrent.forEach(event => {\n initiatorsData.push({event, initiator: selectedEvent});\n });\n }\n\n return initiatorsData;\n}\n\n/**\n * Given an InitiatorData object that contains an initiator and event, this function returns\n * the closest visible ancestors. We need to apply this to each initiatorData because\n * the actual initiator or initiated event might be hidden form the flame chart.\n * If neither entry is hidden, this function returns the initial initiatorData object.\n */\nfunction getClosestVisibleInitiatorEntriesAncestors(\n initiatorData: InitiatorData, expandableEntries: TraceEngine.Types.TraceEvents.TraceEventData[],\n hiddenEntries: TraceEngine.Types.TraceEvents.TraceEventData[],\n traceParsedData: TraceEngine.Handlers.Types.TraceParseData): InitiatorData {\n if (hiddenEntries.includes(initiatorData.event)) {\n let nextParent = traceParsedData.Renderer.entryToNode.get(initiatorData.event)?.parent;\n while (nextParent?.entry && !expandableEntries.includes(nextParent?.entry)) {\n nextParent = nextParent.parent ?? undefined;\n }\n initiatorData.event = nextParent?.entry ?? initiatorData.event;\n initiatorData.isEntryHidden = true;\n }\n\n if (hiddenEntries.includes(initiatorData.initiator)) {\n let nextParent = traceParsedData.Renderer.entryToNode.get(initiatorData.initiator)?.parent;\n while (nextParent?.entry && !expandableEntries.includes(nextParent?.entry)) {\n nextParent = nextParent.parent ?? undefined;\n }\n initiatorData.initiator = nextParent?.entry ?? initiatorData.initiator;\n initiatorData.isInitiatorHidden = true;\n }\n\n return initiatorData;\n}\n"]} \ No newline at end of file +{"version":3,"file":"Initiators.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/Initiators.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Trace from '../../models/trace/trace.js';\n\nexport interface InitiatorData {\n event: Trace.Types.Events.Event;\n initiator: Trace.Types.Events.Event;\n isEntryHidden?: boolean;\n isInitiatorHidden?: boolean;\n}\n/**\n * Given an event that the user has selected, this function returns all the\n * data of events and their initiators that need to be drawn on the flamechart.\n * The reason that this can return multiple InitiatorEntry objects is because we draw the\n * entire chain: for each, we see if it had an initiator, and\n * work backwards to draw each one, as well as the events initiated directly by the entry.\n */\nexport function initiatorsDataToDraw(\n parsedTrace: Trace.Handlers.Types.ParsedTrace,\n selectedEvent: Trace.Types.Events.Event,\n hiddenEntries: Trace.Types.Events.Event[],\n expandableEntries: Trace.Types.Events.Event[],\n ): readonly InitiatorData[] {\n const initiatorsData = [\n ...findInitiatorDataPredecessors(parsedTrace, selectedEvent, parsedTrace.Initiators.eventToInitiator),\n ...findInitiatorDataDirectSuccessors(selectedEvent, parsedTrace.Initiators.initiatorToEvents),\n ];\n\n // For each InitiatorData, call a function that makes sure that neither the initiator or initiated entry is hidden.\n // If they are, it will reassign the event or initiator to the closest ancestor.\n initiatorsData.forEach(\n initiatorData =>\n getClosestVisibleInitiatorEntriesAncestors(initiatorData, expandableEntries, hiddenEntries, parsedTrace));\n return initiatorsData;\n}\n\nexport function initiatorsDataToDrawForNetwork(\n parsedTrace: Trace.Handlers.Types.ParsedTrace,\n selectedEvent: Trace.Types.Events.Event,\n ): readonly InitiatorData[] {\n return findInitiatorDataPredecessors(parsedTrace, selectedEvent, parsedTrace.NetworkRequests.eventToInitiator);\n}\n\nfunction findInitiatorDataPredecessors(\n parsedTrace: Trace.Handlers.Types.ParsedTrace,\n selectedEvent: Trace.Types.Events.Event,\n eventToInitiator: Map,\n ): readonly InitiatorData[] {\n const initiatorsData: InitiatorData[] = [];\n\n let currentEvent: Trace.Types.Events.Event|null = selectedEvent;\n const visited = new Set();\n visited.add(currentEvent);\n\n // Build event initiator data up to the selected one\n while (currentEvent) {\n const currentInitiator = eventToInitiator.get(currentEvent);\n\n if (currentInitiator) {\n if (visited.has(currentInitiator)) {\n break;\n }\n // Store the current initiator data, and then set the initiator to\n // be the current event, so we work back through the\n // trace and find the initiator of the initiator, and so\n // on...\n initiatorsData.push({event: currentEvent, initiator: currentInitiator});\n currentEvent = currentInitiator;\n visited.add(currentEvent);\n continue;\n }\n\n const nodeForCurrentEvent = parsedTrace.Renderer.entryToNode.get(currentEvent);\n if (!nodeForCurrentEvent) {\n // Should not happen - if it does something odd is going\n // on so let's give up.\n currentEvent = null;\n break;\n }\n\n // Go up to the parent, and loop again.\n currentEvent = nodeForCurrentEvent.parent?.entry || null;\n }\n\n return initiatorsData;\n}\n\nfunction findInitiatorDataDirectSuccessors(\n selectedEvent: Trace.Types.Events.Event,\n initiatorToEvents: Map,\n ): readonly InitiatorData[] {\n const initiatorsData: InitiatorData[] = [];\n\n // Add all of the initiated events to the initiatorsData array.\n const eventsInitiatedByCurrent = initiatorToEvents.get(selectedEvent);\n if (eventsInitiatedByCurrent) {\n eventsInitiatedByCurrent.forEach(event => {\n initiatorsData.push({event, initiator: selectedEvent});\n });\n }\n\n return initiatorsData;\n}\n\n/**\n * Given an InitiatorData object that contains an initiator and event, this function returns\n * the closest visible ancestors. We need to apply this to each initiatorData because\n * the actual initiator or initiated event might be hidden form the flame chart.\n * If neither entry is hidden, this function returns the initial initiatorData object.\n */\nfunction getClosestVisibleInitiatorEntriesAncestors(\n initiatorData: InitiatorData, expandableEntries: Trace.Types.Events.Event[],\n hiddenEntries: Trace.Types.Events.Event[], parsedTrace: Trace.Handlers.Types.ParsedTrace): InitiatorData {\n if (hiddenEntries.includes(initiatorData.event)) {\n let nextParent = parsedTrace.Renderer.entryToNode.get(initiatorData.event)?.parent;\n while (nextParent?.entry && !expandableEntries.includes(nextParent?.entry)) {\n nextParent = nextParent.parent ?? undefined;\n }\n initiatorData.event = nextParent?.entry ?? initiatorData.event;\n initiatorData.isEntryHidden = true;\n }\n\n if (hiddenEntries.includes(initiatorData.initiator)) {\n let nextParent = parsedTrace.Renderer.entryToNode.get(initiatorData.initiator)?.parent;\n while (nextParent?.entry && !expandableEntries.includes(nextParent?.entry)) {\n nextParent = nextParent.parent ?? undefined;\n }\n initiatorData.initiator = nextParent?.entry ?? initiatorData.initiator;\n initiatorData.isInitiatorHidden = true;\n }\n\n return initiatorData;\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/Initiators.test.js b/public/panels/timeline/Initiators.test.js index 6c4201766..728a2ea45 100644 --- a/public/panels/timeline/Initiators.test.js +++ b/public/panels/timeline/Initiators.test.js @@ -1,140 +1,138 @@ // 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 * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import { describeWithEnvironment } from '../../testing/EnvironmentHelpers.js'; import { TraceLoader } from '../../testing/TraceLoader.js'; import * as Timeline from './timeline.js'; describeWithEnvironment('Initiators', () => { it('returns the initiator data', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'set-timeout-long-task.json.gz'); - const timerFireEvent = Array.from(traceData.Initiators.eventToInitiator.keys()) - .find(TraceEngine.Types.TraceEvents.isTraceEventTimerFire); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'set-timeout-long-task.json.gz'); + const timerFireEvent = Array.from(parsedTrace.Initiators.eventToInitiator.keys()).find(Trace.Types.Events.isTimerFire); assert.exists(timerFireEvent); - const timerInstallEvent = traceData.Initiators.eventToInitiator.get(timerFireEvent); + const timerInstallEvent = parsedTrace.Initiators.eventToInitiator.get(timerFireEvent); assert.exists(timerInstallEvent); - const initiatorData = Timeline.Initiators.initiatorsDataToDraw(traceData, timerFireEvent, [], []); + const initiatorData = Timeline.Initiators.initiatorsDataToDraw(parsedTrace, timerFireEvent, [], []); assert.deepEqual(initiatorData, [{ event: timerFireEvent, initiator: timerInstallEvent, }]); }); it('returns the initiator data for network requests', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'network-requests-initiators.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'network-requests-initiators.json.gz'); // Find the network request to test, it is initiated by `youtube.com`. - const event = traceData.NetworkRequests.byTime.find(event => event.ts === 1491680762420); + const event = parsedTrace.NetworkRequests.byTime.find(event => event.ts === 1491680762420); assert.exists(event); // Find the `youtube.com` network request. - const initiator = traceData.NetworkRequests.byTime.find(event => event.ts === 1491680629144); + const initiator = parsedTrace.NetworkRequests.byTime.find(event => event.ts === 1491680629144); assert.exists(initiator); - const initiatorData = Timeline.Initiators.initiatorsDataToDrawForNetwork(traceData, event); + const initiatorData = Timeline.Initiators.initiatorsDataToDrawForNetwork(parsedTrace, event); assert.deepEqual(initiatorData, [{ event, initiator }]); }); it('can walk up the tree to find the first parent with an initiator', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'set-timeout-long-task.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'set-timeout-long-task.json.gz'); // Find any of the fibonnaci() calls; they have a parent // event (TimerFire) that has an initiator. - const fibonacciCall = traceData.Renderer.allTraceEntries.find(entry => { - return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'fibonacci'; + const fibonacciCall = parsedTrace.Renderer.allTraceEntries.find(entry => { + return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'fibonacci'; }); assert.exists(fibonacciCall); - const timerFireEvent = Array.from(traceData.Initiators.eventToInitiator.keys()) - .find(TraceEngine.Types.TraceEvents.isTraceEventTimerFire); + const timerFireEvent = Array.from(parsedTrace.Initiators.eventToInitiator.keys()).find(Trace.Types.Events.isTimerFire); assert.exists(timerFireEvent); - const timerInstallEvent = traceData.Initiators.eventToInitiator.get(timerFireEvent); + const timerInstallEvent = parsedTrace.Initiators.eventToInitiator.get(timerFireEvent); assert.exists(timerInstallEvent); // Find the initator data but starting at the fibonacci() // call. - const initiatorsData = Timeline.Initiators.initiatorsDataToDraw(traceData, fibonacciCall, [], []); + const initiatorsData = Timeline.Initiators.initiatorsDataToDraw(parsedTrace, fibonacciCall, [], []); assert.deepEqual(initiatorsData, [{ event: timerFireEvent, initiator: timerInstallEvent, }]); }); it('will walk back through the initiators to find the entire chain', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'nested-initiators.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'nested-initiators.json.gz'); // Find any of the fibonnaci() calls; they have a parent // event (TimerFire) that has an initiator. - const fibonacciCall = traceData.Renderer.allTraceEntries.find(entry => { - return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'fibonacci'; + const fibonacciCall = parsedTrace.Renderer.allTraceEntries.find(entry => { + return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'fibonacci'; }); assert.exists(fibonacciCall); // Find the initators data but starting at the fibonacci() // call. We expect to find two initiatorData objects here: // 1. fibonacci() ===> TimerFire caused by TimerInstall // 2. The TimerInstall from (1), caused by a prior TimerInstall. - const initiatorsData = Timeline.Initiators.initiatorsDataToDraw(traceData, fibonacciCall, [], []); + const initiatorsData = Timeline.Initiators.initiatorsDataToDraw(parsedTrace, fibonacciCall, [], []); assert.lengthOf(initiatorsData, 2); for (const initiatorData of initiatorsData) { // Ensure each initiatorData object has TimerInstall>TimerFire event to initiator. - assert.strictEqual(initiatorData.event.name, "TimerFire" /* TraceEngine.Types.TraceEvents.KnownEventName.TIMER_FIRE */); - assert.strictEqual(initiatorData.initiator.name, "TimerInstall" /* TraceEngine.Types.TraceEvents.KnownEventName.TIMER_INSTALL */); + assert.strictEqual(initiatorData.event.name, "TimerFire" /* Trace.Types.Events.Name.TIMER_FIRE */); + assert.strictEqual(initiatorData.initiator.name, "TimerInstall" /* Trace.Types.Events.Name.TIMER_INSTALL */); } }); it('will walk forward to find the events initiated by the selected entry', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'nested-initiators.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'nested-initiators.json.gz'); // Find any of the InstallTimer calls; they initiate other events. - const timerInstall = traceData.Renderer.allTraceEntries.find(entry => { - return entry.name === "TimerInstall" /* TraceEngine.Types.TraceEvents.KnownEventName.TIMER_INSTALL */; + const timerInstall = parsedTrace.Renderer.allTraceEntries.find(entry => { + return entry.name === "TimerInstall" /* Trace.Types.Events.Name.TIMER_INSTALL */; }); assert.exists(timerInstall); // Find the initatorData objects starting at the TimerInstall // call. We expect to find one initatorData here: // TimerFire that was initiated by the entry we found - TimerInstall - const initatorsData = Timeline.Initiators.initiatorsDataToDraw(traceData, timerInstall, [], []); + const initatorsData = Timeline.Initiators.initiatorsDataToDraw(parsedTrace, timerInstall, [], []); assert.lengthOf(initatorsData, 1); for (const initatorData of initatorsData) { // Ensure each initiatorData object has TimerInstall>TimerFire event to initiator. - assert.strictEqual(initatorData.event.name, "TimerFire" /* TraceEngine.Types.TraceEvents.KnownEventName.TIMER_FIRE */); - assert.strictEqual(initatorData.initiator.name, "TimerInstall" /* TraceEngine.Types.TraceEvents.KnownEventName.TIMER_INSTALL */); + assert.strictEqual(initatorData.event.name, "TimerFire" /* Trace.Types.Events.Name.TIMER_FIRE */); + assert.strictEqual(initatorData.initiator.name, "TimerInstall" /* Trace.Types.Events.Name.TIMER_INSTALL */); } }); it('will return the closest expandable ancestor as an initiator in a pair if the initiator itself is hidden', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'nested-initiators.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'nested-initiators.json.gz'); // Find any of the InstallTimer calls; they initiate other events. - const timerInstall = traceData.Renderer.allTraceEntries.find(entry => { - return entry.name === "TimerInstall" /* TraceEngine.Types.TraceEvents.KnownEventName.TIMER_INSTALL */; + const timerInstall = parsedTrace.Renderer.allTraceEntries.find(entry => { + return entry.name === "TimerInstall" /* Trace.Types.Events.Name.TIMER_INSTALL */; }); assert.exists(timerInstall); // Get the parent of InstallTimer to add to the expandable events array. // When we add TimerInstall to hidden entries list, it will be the closest expandable parent and the initiator should point to it. - const timerInstallParent = traceData.Renderer.entryToNode.get(timerInstall)?.parent; + const timerInstallParent = parsedTrace.Renderer.entryToNode.get(timerInstall)?.parent; assert.exists(timerInstallParent); // Find the initatorData objects starting at the TimerInstall // call. We expect to find one initatorData here: // TimerFire that was initiated by the entry we found - Parent of TimerInstall because TimerInstall is hidden - const initiatorsData = Timeline.Initiators.initiatorsDataToDraw(traceData, timerInstall, [timerInstall], [timerInstallParent?.entry]); + const initiatorsData = Timeline.Initiators.initiatorsDataToDraw(parsedTrace, timerInstall, [timerInstall], [timerInstallParent?.entry]); assert.lengthOf(initiatorsData, 1); // Ensure each initiatorData object has TimerInstall>TimerFire event to initiator. for (const initiatorData of initiatorsData) { - assert.strictEqual(initiatorData.event.name, "TimerFire" /* TraceEngine.Types.TraceEvents.KnownEventName.TIMER_FIRE */); + assert.strictEqual(initiatorData.event.name, "TimerFire" /* Trace.Types.Events.Name.TIMER_FIRE */); assert.strictEqual(initiatorData.initiator, timerInstallParent.entry); // Ensure the expandable entry is marked as hidden assert.strictEqual(initiatorData.isInitiatorHidden, true); } }); it('will return the closest expandable ancestor as an initiated event in a pair if the event itself is hidden', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'nested-initiators.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'nested-initiators.json.gz'); // Find any of the fibonnaci() calls; they have a parent // event (TimerFire) that has an initiator. - const fibonacciCall = traceData.Renderer.allTraceEntries.find(entry => { - return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'fibonacci'; + const fibonacciCall = parsedTrace.Renderer.allTraceEntries.find(entry => { + return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'fibonacci'; }); assert.exists(fibonacciCall); // Find the initatorData objects but starting at the fibonacci() // call. We expect to find two initiatorData objects here: // 1. fibonacci() ===> TimerFire caused by TimerInstall // 2. The TimerInstall from (1), caused by a prior TimerInstall. - let initiatorsData = Timeline.Initiators.initiatorsDataToDraw(traceData, fibonacciCall, [], []); + let initiatorsData = Timeline.Initiators.initiatorsDataToDraw(parsedTrace, fibonacciCall, [], []); assert.lengthOf(initiatorsData, 2); // Save the parents of initiated events and the events themselves to get initiators again with those as expandable and hidden const timerFireParents = []; const initiatedEvents = []; for (const initiatorData of initiatorsData) { // Ensure each initiatorData object has TimerInstall>TimerFire event to initiator. - assert.strictEqual(initiatorData.event.name, "TimerFire" /* TraceEngine.Types.TraceEvents.KnownEventName.TIMER_FIRE */); - assert.strictEqual(initiatorData.initiator.name, "TimerInstall" /* TraceEngine.Types.TraceEvents.KnownEventName.TIMER_INSTALL */); - const parentEvent = traceData.Renderer.entryToNode.get(initiatorData.event)?.parent?.entry; + assert.strictEqual(initiatorData.event.name, "TimerFire" /* Trace.Types.Events.Name.TIMER_FIRE */); + assert.strictEqual(initiatorData.initiator.name, "TimerInstall" /* Trace.Types.Events.Name.TIMER_INSTALL */); + const parentEvent = parsedTrace.Renderer.entryToNode.get(initiatorData.event)?.parent?.entry; if (parentEvent) { timerFireParents.push(parentEvent); initiatedEvents.push(initiatorData.event); @@ -142,14 +140,14 @@ describeWithEnvironment('Initiators', () => { } // Get initiatorData object again, now with the previously initiated events hidden and parents marked as expandable initiatorsData = - Timeline.Initiators.initiatorsDataToDraw(traceData, fibonacciCall, initiatedEvents, timerFireParents); + Timeline.Initiators.initiatorsDataToDraw(parsedTrace, fibonacciCall, initiatedEvents, timerFireParents); // The length should not change, just the inititated events. assert.lengthOf(initiatorsData, 2); for (let i = 0; i < initiatorsData.length; i++) { const initiatorData = initiatorsData[i]; // Ensure each initiatorData object has TimerInstall>TimerFire event to initiator. assert.strictEqual(initiatorData.event, timerFireParents[i]); - assert.strictEqual(initiatorData.initiator.name, "TimerInstall" /* TraceEngine.Types.TraceEvents.KnownEventName.TIMER_INSTALL */); + assert.strictEqual(initiatorData.initiator.name, "TimerInstall" /* Trace.Types.Events.Name.TIMER_INSTALL */); // Ensure the expandable entry is marked as hidden assert.strictEqual(initiatorData.isEntryHidden, true); } diff --git a/public/panels/timeline/Initiators.test.js.map b/public/panels/timeline/Initiators.test.js.map index b934594bd..e11bffbd1 100644 --- a/public/panels/timeline/Initiators.test.js.map +++ b/public/panels/timeline/Initiators.test.js.map @@ -1 +1 @@ -{"version":3,"file":"Initiators.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/Initiators.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\n\nimport * as Timeline from './timeline.js';\n\ndescribeWithEnvironment('Initiators', () => {\n it('returns the initiator data', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'set-timeout-long-task.json.gz');\n\n const timerFireEvent = Array.from(traceData.Initiators.eventToInitiator.keys())\n .find(TraceEngine.Types.TraceEvents.isTraceEventTimerFire);\n assert.exists(timerFireEvent);\n const timerInstallEvent = traceData.Initiators.eventToInitiator.get(timerFireEvent);\n assert.exists(timerInstallEvent);\n const initiatorData = Timeline.Initiators.initiatorsDataToDraw(traceData, timerFireEvent, [], []);\n\n assert.deepEqual(initiatorData, [{\n event: timerFireEvent,\n initiator: timerInstallEvent,\n }]);\n });\n\n it('returns the initiator data for network requests', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'network-requests-initiators.json.gz');\n\n // Find the network request to test, it is initiated by `youtube.com`.\n const event = traceData.NetworkRequests.byTime.find(event => event.ts === 1491680762420);\n assert.exists(event);\n // Find the `youtube.com` network request.\n const initiator = traceData.NetworkRequests.byTime.find(event => event.ts === 1491680629144);\n assert.exists(initiator);\n const initiatorData = Timeline.Initiators.initiatorsDataToDrawForNetwork(traceData, event);\n\n assert.deepEqual(initiatorData, [{event, initiator}]);\n });\n\n it('can walk up the tree to find the first parent with an initiator', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'set-timeout-long-task.json.gz');\n\n // Find any of the fibonnaci() calls; they have a parent\n // event (TimerFire) that has an initiator.\n const fibonacciCall = traceData.Renderer.allTraceEntries.find(entry => {\n return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'fibonacci';\n });\n assert.exists(fibonacciCall);\n\n const timerFireEvent = Array.from(traceData.Initiators.eventToInitiator.keys())\n .find(TraceEngine.Types.TraceEvents.isTraceEventTimerFire);\n assert.exists(timerFireEvent);\n const timerInstallEvent = traceData.Initiators.eventToInitiator.get(timerFireEvent);\n assert.exists(timerInstallEvent);\n\n // Find the initator data but starting at the fibonacci()\n // call.\n const initiatorsData = Timeline.Initiators.initiatorsDataToDraw(traceData, fibonacciCall, [], []);\n\n assert.deepEqual(initiatorsData, [{\n event: timerFireEvent,\n initiator: timerInstallEvent,\n }]);\n });\n\n it('will walk back through the initiators to find the entire chain', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'nested-initiators.json.gz');\n\n // Find any of the fibonnaci() calls; they have a parent\n // event (TimerFire) that has an initiator.\n const fibonacciCall = traceData.Renderer.allTraceEntries.find(entry => {\n return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'fibonacci';\n });\n assert.exists(fibonacciCall);\n\n // Find the initators data but starting at the fibonacci()\n // call. We expect to find two initiatorData objects here:\n // 1. fibonacci() ===> TimerFire caused by TimerInstall\n // 2. The TimerInstall from (1), caused by a prior TimerInstall.\n const initiatorsData = Timeline.Initiators.initiatorsDataToDraw(traceData, fibonacciCall, [], []);\n\n assert.lengthOf(initiatorsData, 2);\n for (const initiatorData of initiatorsData) {\n // Ensure each initiatorData object has TimerInstall>TimerFire event to initiator.\n assert.strictEqual(initiatorData.event.name, TraceEngine.Types.TraceEvents.KnownEventName.TIMER_FIRE);\n assert.strictEqual(initiatorData.initiator.name, TraceEngine.Types.TraceEvents.KnownEventName.TIMER_INSTALL);\n }\n });\n\n it('will walk forward to find the events initiated by the selected entry', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'nested-initiators.json.gz');\n\n // Find any of the InstallTimer calls; they initiate other events.\n const timerInstall = traceData.Renderer.allTraceEntries.find(entry => {\n return entry.name === TraceEngine.Types.TraceEvents.KnownEventName.TIMER_INSTALL;\n });\n assert.exists(timerInstall);\n\n // Find the initatorData objects starting at the TimerInstall\n // call. We expect to find one initatorData here:\n // TimerFire that was initiated by the entry we found - TimerInstall\n\n const initatorsData = Timeline.Initiators.initiatorsDataToDraw(traceData, timerInstall, [], []);\n\n assert.lengthOf(initatorsData, 1);\n for (const initatorData of initatorsData) {\n // Ensure each initiatorData object has TimerInstall>TimerFire event to initiator.\n assert.strictEqual(initatorData.event.name, TraceEngine.Types.TraceEvents.KnownEventName.TIMER_FIRE);\n assert.strictEqual(initatorData.initiator.name, TraceEngine.Types.TraceEvents.KnownEventName.TIMER_INSTALL);\n }\n });\n\n it('will return the closest expandable ancestor as an initiator in a pair if the initiator itself is hidden',\n async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'nested-initiators.json.gz');\n\n // Find any of the InstallTimer calls; they initiate other events.\n const timerInstall = traceData.Renderer.allTraceEntries.find(entry => {\n return entry.name === TraceEngine.Types.TraceEvents.KnownEventName.TIMER_INSTALL;\n });\n assert.exists(timerInstall);\n // Get the parent of InstallTimer to add to the expandable events array.\n // When we add TimerInstall to hidden entries list, it will be the closest expandable parent and the initiator should point to it.\n const timerInstallParent = traceData.Renderer.entryToNode.get(timerInstall)?.parent;\n assert.exists(timerInstallParent);\n\n // Find the initatorData objects starting at the TimerInstall\n // call. We expect to find one initatorData here:\n // TimerFire that was initiated by the entry we found - Parent of TimerInstall because TimerInstall is hidden\n const initiatorsData = Timeline.Initiators.initiatorsDataToDraw(\n traceData, timerInstall, [timerInstall], [timerInstallParent?.entry]);\n\n assert.lengthOf(initiatorsData, 1);\n // Ensure each initiatorData object has TimerInstall>TimerFire event to initiator.\n for (const initiatorData of initiatorsData) {\n assert.strictEqual(initiatorData.event.name, TraceEngine.Types.TraceEvents.KnownEventName.TIMER_FIRE);\n assert.strictEqual(initiatorData.initiator, timerInstallParent.entry);\n // Ensure the expandable entry is marked as hidden\n assert.strictEqual(initiatorData.isInitiatorHidden, true);\n }\n });\n\n it('will return the closest expandable ancestor as an initiated event in a pair if the event itself is hidden',\n async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'nested-initiators.json.gz');\n\n // Find any of the fibonnaci() calls; they have a parent\n // event (TimerFire) that has an initiator.\n const fibonacciCall = traceData.Renderer.allTraceEntries.find(entry => {\n return TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === 'fibonacci';\n });\n assert.exists(fibonacciCall);\n\n // Find the initatorData objects but starting at the fibonacci()\n // call. We expect to find two initiatorData objects here:\n // 1. fibonacci() ===> TimerFire caused by TimerInstall\n // 2. The TimerInstall from (1), caused by a prior TimerInstall.\n let initiatorsData = Timeline.Initiators.initiatorsDataToDraw(traceData, fibonacciCall, [], []);\n\n assert.lengthOf(initiatorsData, 2);\n // Save the parents of initiated events and the events themselves to get initiators again with those as expandable and hidden\n const timerFireParents: TraceEngine.Types.TraceEvents.TraceEventData[] = [];\n const initiatedEvents: TraceEngine.Types.TraceEvents.TraceEventData[] = [];\n\n for (const initiatorData of initiatorsData) {\n // Ensure each initiatorData object has TimerInstall>TimerFire event to initiator.\n assert.strictEqual(initiatorData.event.name, TraceEngine.Types.TraceEvents.KnownEventName.TIMER_FIRE);\n assert.strictEqual(initiatorData.initiator.name, TraceEngine.Types.TraceEvents.KnownEventName.TIMER_INSTALL);\n const parentEvent = traceData.Renderer.entryToNode.get(initiatorData.event)?.parent?.entry;\n if (parentEvent) {\n timerFireParents.push(parentEvent);\n initiatedEvents.push(initiatorData.event);\n }\n }\n\n // Get initiatorData object again, now with the previously initiated events hidden and parents marked as expandable\n initiatorsData =\n Timeline.Initiators.initiatorsDataToDraw(traceData, fibonacciCall, initiatedEvents, timerFireParents);\n // The length should not change, just the inititated events.\n assert.lengthOf(initiatorsData, 2);\n for (let i = 0; i < initiatorsData.length; i++) {\n const initiatorData = initiatorsData[i];\n // Ensure each initiatorData object has TimerInstall>TimerFire event to initiator.\n assert.strictEqual(initiatorData.event, timerFireParents[i]);\n assert.strictEqual(initiatorData.initiator.name, TraceEngine.Types.TraceEvents.KnownEventName.TIMER_INSTALL);\n // Ensure the expandable entry is marked as hidden\n assert.strictEqual(initiatorData.isEntryHidden, true);\n }\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"Initiators.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/Initiators.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\n\nimport * as Timeline from './timeline.js';\n\ndescribeWithEnvironment('Initiators', () => {\n it('returns the initiator data', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'set-timeout-long-task.json.gz');\n\n const timerFireEvent =\n Array.from(parsedTrace.Initiators.eventToInitiator.keys()).find(Trace.Types.Events.isTimerFire);\n assert.exists(timerFireEvent);\n const timerInstallEvent = parsedTrace.Initiators.eventToInitiator.get(timerFireEvent);\n assert.exists(timerInstallEvent);\n const initiatorData = Timeline.Initiators.initiatorsDataToDraw(parsedTrace, timerFireEvent, [], []);\n\n assert.deepEqual(initiatorData, [{\n event: timerFireEvent,\n initiator: timerInstallEvent,\n }]);\n });\n\n it('returns the initiator data for network requests', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'network-requests-initiators.json.gz');\n\n // Find the network request to test, it is initiated by `youtube.com`.\n const event = parsedTrace.NetworkRequests.byTime.find(event => event.ts === 1491680762420);\n assert.exists(event);\n // Find the `youtube.com` network request.\n const initiator = parsedTrace.NetworkRequests.byTime.find(event => event.ts === 1491680629144);\n assert.exists(initiator);\n const initiatorData = Timeline.Initiators.initiatorsDataToDrawForNetwork(parsedTrace, event);\n\n assert.deepEqual(initiatorData, [{event, initiator}]);\n });\n\n it('can walk up the tree to find the first parent with an initiator', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'set-timeout-long-task.json.gz');\n\n // Find any of the fibonnaci() calls; they have a parent\n // event (TimerFire) that has an initiator.\n const fibonacciCall = parsedTrace.Renderer.allTraceEntries.find(entry => {\n return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'fibonacci';\n });\n assert.exists(fibonacciCall);\n\n const timerFireEvent =\n Array.from(parsedTrace.Initiators.eventToInitiator.keys()).find(Trace.Types.Events.isTimerFire);\n assert.exists(timerFireEvent);\n const timerInstallEvent = parsedTrace.Initiators.eventToInitiator.get(timerFireEvent);\n assert.exists(timerInstallEvent);\n\n // Find the initator data but starting at the fibonacci()\n // call.\n const initiatorsData = Timeline.Initiators.initiatorsDataToDraw(parsedTrace, fibonacciCall, [], []);\n\n assert.deepEqual(initiatorsData, [{\n event: timerFireEvent,\n initiator: timerInstallEvent,\n }]);\n });\n\n it('will walk back through the initiators to find the entire chain', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'nested-initiators.json.gz');\n\n // Find any of the fibonnaci() calls; they have a parent\n // event (TimerFire) that has an initiator.\n const fibonacciCall = parsedTrace.Renderer.allTraceEntries.find(entry => {\n return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'fibonacci';\n });\n assert.exists(fibonacciCall);\n\n // Find the initators data but starting at the fibonacci()\n // call. We expect to find two initiatorData objects here:\n // 1. fibonacci() ===> TimerFire caused by TimerInstall\n // 2. The TimerInstall from (1), caused by a prior TimerInstall.\n const initiatorsData = Timeline.Initiators.initiatorsDataToDraw(parsedTrace, fibonacciCall, [], []);\n\n assert.lengthOf(initiatorsData, 2);\n for (const initiatorData of initiatorsData) {\n // Ensure each initiatorData object has TimerInstall>TimerFire event to initiator.\n assert.strictEqual(initiatorData.event.name, Trace.Types.Events.Name.TIMER_FIRE);\n assert.strictEqual(initiatorData.initiator.name, Trace.Types.Events.Name.TIMER_INSTALL);\n }\n });\n\n it('will walk forward to find the events initiated by the selected entry', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'nested-initiators.json.gz');\n\n // Find any of the InstallTimer calls; they initiate other events.\n const timerInstall = parsedTrace.Renderer.allTraceEntries.find(entry => {\n return entry.name === Trace.Types.Events.Name.TIMER_INSTALL;\n });\n assert.exists(timerInstall);\n\n // Find the initatorData objects starting at the TimerInstall\n // call. We expect to find one initatorData here:\n // TimerFire that was initiated by the entry we found - TimerInstall\n\n const initatorsData = Timeline.Initiators.initiatorsDataToDraw(parsedTrace, timerInstall, [], []);\n\n assert.lengthOf(initatorsData, 1);\n for (const initatorData of initatorsData) {\n // Ensure each initiatorData object has TimerInstall>TimerFire event to initiator.\n assert.strictEqual(initatorData.event.name, Trace.Types.Events.Name.TIMER_FIRE);\n assert.strictEqual(initatorData.initiator.name, Trace.Types.Events.Name.TIMER_INSTALL);\n }\n });\n\n it('will return the closest expandable ancestor as an initiator in a pair if the initiator itself is hidden',\n async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'nested-initiators.json.gz');\n\n // Find any of the InstallTimer calls; they initiate other events.\n const timerInstall = parsedTrace.Renderer.allTraceEntries.find(entry => {\n return entry.name === Trace.Types.Events.Name.TIMER_INSTALL;\n });\n assert.exists(timerInstall);\n // Get the parent of InstallTimer to add to the expandable events array.\n // When we add TimerInstall to hidden entries list, it will be the closest expandable parent and the initiator should point to it.\n const timerInstallParent = parsedTrace.Renderer.entryToNode.get(timerInstall)?.parent;\n assert.exists(timerInstallParent);\n\n // Find the initatorData objects starting at the TimerInstall\n // call. We expect to find one initatorData here:\n // TimerFire that was initiated by the entry we found - Parent of TimerInstall because TimerInstall is hidden\n const initiatorsData = Timeline.Initiators.initiatorsDataToDraw(\n parsedTrace, timerInstall, [timerInstall], [timerInstallParent?.entry]);\n\n assert.lengthOf(initiatorsData, 1);\n // Ensure each initiatorData object has TimerInstall>TimerFire event to initiator.\n for (const initiatorData of initiatorsData) {\n assert.strictEqual(initiatorData.event.name, Trace.Types.Events.Name.TIMER_FIRE);\n assert.strictEqual(initiatorData.initiator, timerInstallParent.entry);\n // Ensure the expandable entry is marked as hidden\n assert.strictEqual(initiatorData.isInitiatorHidden, true);\n }\n });\n\n it('will return the closest expandable ancestor as an initiated event in a pair if the event itself is hidden',\n async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'nested-initiators.json.gz');\n\n // Find any of the fibonnaci() calls; they have a parent\n // event (TimerFire) that has an initiator.\n const fibonacciCall = parsedTrace.Renderer.allTraceEntries.find(entry => {\n return Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === 'fibonacci';\n });\n assert.exists(fibonacciCall);\n\n // Find the initatorData objects but starting at the fibonacci()\n // call. We expect to find two initiatorData objects here:\n // 1. fibonacci() ===> TimerFire caused by TimerInstall\n // 2. The TimerInstall from (1), caused by a prior TimerInstall.\n let initiatorsData = Timeline.Initiators.initiatorsDataToDraw(parsedTrace, fibonacciCall, [], []);\n\n assert.lengthOf(initiatorsData, 2);\n // Save the parents of initiated events and the events themselves to get initiators again with those as expandable and hidden\n const timerFireParents: Trace.Types.Events.Event[] = [];\n const initiatedEvents: Trace.Types.Events.Event[] = [];\n\n for (const initiatorData of initiatorsData) {\n // Ensure each initiatorData object has TimerInstall>TimerFire event to initiator.\n assert.strictEqual(initiatorData.event.name, Trace.Types.Events.Name.TIMER_FIRE);\n assert.strictEqual(initiatorData.initiator.name, Trace.Types.Events.Name.TIMER_INSTALL);\n const parentEvent = parsedTrace.Renderer.entryToNode.get(initiatorData.event)?.parent?.entry;\n if (parentEvent) {\n timerFireParents.push(parentEvent);\n initiatedEvents.push(initiatorData.event);\n }\n }\n\n // Get initiatorData object again, now with the previously initiated events hidden and parents marked as expandable\n initiatorsData =\n Timeline.Initiators.initiatorsDataToDraw(parsedTrace, fibonacciCall, initiatedEvents, timerFireParents);\n // The length should not change, just the inititated events.\n assert.lengthOf(initiatorsData, 2);\n for (let i = 0; i < initiatorsData.length; i++) {\n const initiatorData = initiatorsData[i];\n // Ensure each initiatorData object has TimerInstall>TimerFire event to initiator.\n assert.strictEqual(initiatorData.event, timerFireParents[i]);\n assert.strictEqual(initiatorData.initiator.name, Trace.Types.Events.Name.TIMER_INSTALL);\n // Ensure the expandable entry is marked as hidden\n assert.strictEqual(initiatorData.isEntryHidden, true);\n }\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/InteractionsTrackAppender.d.ts b/public/panels/timeline/InteractionsTrackAppender.d.ts index 06d2625cc..4518fa165 100644 --- a/public/panels/timeline/InteractionsTrackAppender.d.ts +++ b/public/panels/timeline/InteractionsTrackAppender.d.ts @@ -1,10 +1,10 @@ import type * as Common from '../../core/common/common.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import { type CompatibilityTracksAppender, type TrackAppender, type TrackAppenderName } from './CompatibilityTracksAppender.js'; export declare class InteractionsTrackAppender implements TrackAppender { #private; readonly appenderName: TrackAppenderName; - constructor(compatibilityBuilder: CompatibilityTracksAppender, traceParsedData: TraceEngine.Handlers.Types.TraceParseData, colorGenerator: Common.Color.Generator); + constructor(compatibilityBuilder: CompatibilityTracksAppender, parsedTrace: Trace.Handlers.Types.ParsedTrace, colorGenerator: Common.Color.Generator); /** * Appends into the flame chart data the data corresponding to the * interactions track. @@ -18,5 +18,5 @@ export declare class InteractionsTrackAppender implements TrackAppender { /** * Gets the color an event added by this appender should be rendered with. */ - colorForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): string; + colorForEvent(event: Trace.Types.Events.Event): string; } diff --git a/public/panels/timeline/InteractionsTrackAppender.js b/public/panels/timeline/InteractionsTrackAppender.js index 582c3884c..8ac95e81e 100644 --- a/public/panels/timeline/InteractionsTrackAppender.js +++ b/public/panels/timeline/InteractionsTrackAppender.js @@ -1,5 +1,5 @@ import * as i18n from '../../core/i18n/i18n.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; import { buildGroupStyle, buildTrackHeader } from './AppenderUtils.js'; import * as Components from './components/components.js'; @@ -15,11 +15,11 @@ export class InteractionsTrackAppender { appenderName = 'Interactions'; #colorGenerator; #compatibilityBuilder; - #traceParsedData; - constructor(compatibilityBuilder, traceParsedData, colorGenerator) { + #parsedTrace; + constructor(compatibilityBuilder, parsedTrace, colorGenerator) { this.#compatibilityBuilder = compatibilityBuilder; this.#colorGenerator = colorGenerator; - this.#traceParsedData = traceParsedData; + this.#parsedTrace = parsedTrace; } /** * Appends into the flame chart data the data corresponding to the @@ -31,7 +31,7 @@ export class InteractionsTrackAppender { * appended the track's events. */ appendTrackAtLevel(trackStartLevel, expanded) { - if (this.#traceParsedData.UserInteractions.interactionEvents.length === 0) { + if (this.#parsedTrace.UserInteractions.interactionEvents.length === 0) { return trackStartLevel; } this.#appendTrackHeaderAtLevel(trackStartLevel, expanded); @@ -47,7 +47,7 @@ export class InteractionsTrackAppender { * appended. */ #appendTrackHeaderAtLevel(currentLevel, expanded) { - const trackIsCollapsible = this.#traceParsedData.UserInteractions.interactionEvents.length > 0; + const trackIsCollapsible = this.#parsedTrace.UserInteractions.interactionEvents.length > 0; const style = buildGroupStyle({ collapsible: trackIsCollapsible, useDecoratorsForOverview: true }); const group = buildTrackHeader("interactions" /* VisualLoggingTrackName.INTERACTIONS */, currentLevel, i18nString(UIStrings.interactions), style, /* selectable= */ true, expanded); @@ -63,7 +63,7 @@ export class InteractionsTrackAppender { * interactions (the first available level to append more data). */ #appendInteractionsAtLevel(trackStartLevel) { - const { interactionEventsWithNoNesting, interactionsOverThreshold } = this.#traceParsedData.UserInteractions; + const { interactionEventsWithNoNesting, interactionsOverThreshold } = this.#parsedTrace.UserInteractions; const addCandyStripeToLongInteraction = (event, index) => { // Each interaction that we drew that is over the INP threshold needs to be // candy-striped. @@ -83,7 +83,7 @@ export class InteractionsTrackAppender { const decorationsForEvent = this.#compatibilityBuilder.getFlameChartTimelineData().entryDecorations[eventIndex] || []; decorationsForEvent.push({ type: "CANDY" /* PerfUI.FlameChart.FlameChartDecorationType.CANDY */, - startAtTime: TraceEngine.Handlers.ModelHandlers.UserInteractions.LONG_INTERACTION_THRESHOLD, + startAtTime: Trace.Handlers.ModelHandlers.UserInteractions.LONG_INTERACTION_THRESHOLD, // Interaction events have whiskers, so we do not want to candy stripe // the entire duration. The box represents processing duration, so we only // candystripe up to the end of processing. @@ -104,8 +104,8 @@ export class InteractionsTrackAppender { * Gets the color an event added by this appender should be rendered with. */ colorForEvent(event) { - let idForColorGeneration = Components.EntryName.nameForEntry(event, this.#traceParsedData); - if (TraceEngine.Types.TraceEvents.isSyntheticInteractionEvent(event)) { + let idForColorGeneration = Components.EntryName.nameForEntry(event, this.#parsedTrace); + if (Trace.Types.Events.isSyntheticInteraction(event)) { // Append the ID so that we vary the colours, ensuring that two events of // the same type are coloured differently. idForColorGeneration += event.interactionId; diff --git a/public/panels/timeline/InteractionsTrackAppender.js.map b/public/panels/timeline/InteractionsTrackAppender.js.map index 2f77bceaf..af9abce3f 100644 --- a/public/panels/timeline/InteractionsTrackAppender.js.map +++ b/public/panels/timeline/InteractionsTrackAppender.js.map @@ -1 +1 @@ -{"version":3,"file":"InteractionsTrackAppender.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/InteractionsTrackAppender.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,IAAI,MAAM,yBAAyB,CAAC;AAChD,OAAO,KAAK,WAAW,MAAM,6BAA6B,CAAC;AAC3D,OAAO,KAAK,MAAM,MAAM,+CAA+C,CAAC;AAExE,OAAO,EAAC,eAAe,EAAE,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AAOrE,OAAO,KAAK,UAAU,MAAM,4BAA4B,CAAC;AAEzD,MAAM,SAAS,GAAG;IAChB;;OAEG;IACH,YAAY,EAAE,cAAc;CAC7B,CAAC;AAEF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,8CAA8C,EAAE,SAAS,CAAC,CAAC;AACpG,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAEtE,MAAM,OAAO,yBAAyB;IAC3B,YAAY,GAAsB,cAAc,CAAC;IAE1D,eAAe,CAAyB;IACxC,qBAAqB,CAA8B;IACnD,gBAAgB,CAAsD;IAEtE,YACI,oBAAiD,EAAE,eAA0D,EAC7G,cAAsC;QACxC,IAAI,CAAC,qBAAqB,GAAG,oBAAoB,CAAC;QAClD,IAAI,CAAC,eAAe,GAAG,cAAc,CAAC;QACtC,IAAI,CAAC,gBAAgB,GAAG,eAAe,CAAC;IAC1C,CAAC;IAED;;;;;;;;OAQG;IACH,kBAAkB,CAAC,eAAuB,EAAE,QAAkB;QAC5D,IAAI,IAAI,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1E,OAAO,eAAe,CAAC;QACzB,CAAC;QACD,IAAI,CAAC,yBAAyB,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC,0BAA0B,CAAC,eAAe,CAAC,CAAC;IAC1D,CAAC;IAED;;;;;;;;OAQG;IACH,yBAAyB,CAAC,YAAoB,EAAE,QAAkB;QAChE,MAAM,kBAAkB,GAAG,IAAI,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC;QAC/F,MAAM,KAAK,GAAG,eAAe,CAAC,EAAC,WAAW,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,IAAI,EAAC,CAAC,CAAC;QACjG,MAAM,KAAK,GAAG,gBAAgB,2DACW,YAAY,EAAE,UAAU,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,KAAK;QAC5F,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACtC,IAAI,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAChE,CAAC;IAED;;;;;;;;OAQG;IACH,0BAA0B,CAAC,eAAuB;QAChD,MAAM,EAAC,8BAA8B,EAAE,yBAAyB,EAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,gBAAgB,CAAC;QAE3G,MAAM,+BAA+B,GACjC,CAAC,KAA6D,EAAE,KAAa,EAAQ,EAAE;YACrF,2EAA2E;YAC3E,iBAAiB;YACjB,MAAM,aAAa,GAAG,yBAAyB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;YAC3D,IAAI,CAAC,aAAa,EAAE,CAAC;gBACnB,OAAO;YACT,CAAC;YACD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,IAAI,CAAC,2CAA2C,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YACjE,CAAC;QACH,CAAC,CAAC;QACN,oHAAoH;QACpH,MAAM,QAAQ,GAAG,IAAI,CAAC,qBAAqB,CAAC,mBAAmB,CAC3D,8BAA8B,EAAE,eAAe,EAAE,IAAI,EAAE,+BAA+B,CAAC,CAAC;QAE5F,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,2CAA2C,CACvC,KAA6D,EAAE,UAAkB;QACnF,MAAM,mBAAmB,GACrB,IAAI,CAAC,qBAAqB,CAAC,yBAAyB,EAAE,CAAC,gBAAgB,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QAC9F,mBAAmB,CAAC,IAAI,CACpB;YACE,IAAI,gEAAkD;YACtD,WAAW,EAAE,WAAW,CAAC,QAAQ,CAAC,aAAa,CAAC,gBAAgB,CAAC,0BAA0B;YAC3F,sEAAsE;YACtE,0EAA0E;YAC1E,2CAA2C;YAC3C,SAAS,EAAE,KAAK,CAAC,aAAa;SAC/B,EACD;YACE,IAAI,sFAA6D;YACjE,aAAa,EAAE,KAAK,CAAC,aAAa;SACnC,CAAC,CAAC;QACP,IAAI,CAAC,qBAAqB,CAAC,yBAAyB,EAAE,CAAC,gBAAgB,CAAC,UAAU,CAAC,GAAG,mBAAmB,CAAC;IAC5G,CAAC;IAED;;;;;MAKE;IAEF;;OAEG;IACH,aAAa,CAAC,KAAmD;QAC/D,IAAI,oBAAoB,GAAG,UAAU,CAAC,SAAS,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC3F,IAAI,WAAW,CAAC,KAAK,CAAC,WAAW,CAAC,2BAA2B,CAAC,KAAK,CAAC,EAAE,CAAC;YACrE,yEAAyE;YACzE,0CAA0C;YAC1C,oBAAoB,IAAI,KAAK,CAAC,aAAa,CAAC;QAC9C,CAAC;QACD,OAAO,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAC;IAC/D,CAAC;CACF","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport type * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\n\nimport {buildGroupStyle, buildTrackHeader} from './AppenderUtils.js';\nimport {\n type CompatibilityTracksAppender,\n type TrackAppender,\n type TrackAppenderName,\n VisualLoggingTrackName,\n} from './CompatibilityTracksAppender.js';\nimport * as Components from './components/components.js';\n\nconst UIStrings = {\n /**\n *@description Text in Timeline Flame Chart Data Provider of the Performance panel\n */\n interactions: 'Interactions',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/InteractionsTrackAppender.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport class InteractionsTrackAppender implements TrackAppender {\n readonly appenderName: TrackAppenderName = 'Interactions';\n\n #colorGenerator: Common.Color.Generator;\n #compatibilityBuilder: CompatibilityTracksAppender;\n #traceParsedData: Readonly;\n\n constructor(\n compatibilityBuilder: CompatibilityTracksAppender, traceParsedData: TraceEngine.Handlers.Types.TraceParseData,\n colorGenerator: Common.Color.Generator) {\n this.#compatibilityBuilder = compatibilityBuilder;\n this.#colorGenerator = colorGenerator;\n this.#traceParsedData = traceParsedData;\n }\n\n /**\n * Appends into the flame chart data the data corresponding to the\n * interactions track.\n * @param trackStartLevel the horizontal level of the flame chart events where\n * the track's events will start being appended.\n * @param expanded wether the track should be rendered expanded.\n * @returns the first available level to append more data after having\n * appended the track's events.\n */\n appendTrackAtLevel(trackStartLevel: number, expanded?: boolean): number {\n if (this.#traceParsedData.UserInteractions.interactionEvents.length === 0) {\n return trackStartLevel;\n }\n this.#appendTrackHeaderAtLevel(trackStartLevel, expanded);\n return this.#appendInteractionsAtLevel(trackStartLevel);\n }\n\n /**\n * Adds into the flame chart data the header corresponding to the\n * interactions track. A header is added in the shape of a group in the\n * flame chart data. A group has a predefined style and a reference\n * to the definition of the legacy track (which should be removed\n * in the future).\n * @param currentLevel the flame chart level at which the header is\n * appended.\n */\n #appendTrackHeaderAtLevel(currentLevel: number, expanded?: boolean): void {\n const trackIsCollapsible = this.#traceParsedData.UserInteractions.interactionEvents.length > 0;\n const style = buildGroupStyle({collapsible: trackIsCollapsible, useDecoratorsForOverview: true});\n const group = buildTrackHeader(\n VisualLoggingTrackName.INTERACTIONS, currentLevel, i18nString(UIStrings.interactions), style,\n /* selectable= */ true, expanded);\n this.#compatibilityBuilder.registerTrackForGroup(group, this);\n }\n\n /**\n * Adds into the flame chart data the trace events dispatched by the\n * performance.measure API. These events are taken from the UserInteractions\n * handler.\n * @param currentLevel the flame chart level from which interactions will\n * be appended.\n * @returns the next level after the last occupied by the appended\n * interactions (the first available level to append more data).\n */\n #appendInteractionsAtLevel(trackStartLevel: number): number {\n const {interactionEventsWithNoNesting, interactionsOverThreshold} = this.#traceParsedData.UserInteractions;\n\n const addCandyStripeToLongInteraction =\n (event: TraceEngine.Types.TraceEvents.SyntheticInteractionPair, index: number): void => {\n // Each interaction that we drew that is over the INP threshold needs to be\n // candy-striped.\n const overThreshold = interactionsOverThreshold.has(event);\n if (!overThreshold) {\n return;\n }\n if (index !== undefined) {\n this.#addCandyStripeAndWarningForLongInteraction(event, index);\n }\n };\n // Render all top level interactions (see UserInteractionsHandler for an explanation on the nesting) onto the track.\n const newLevel = this.#compatibilityBuilder.appendEventsAtLevel(\n interactionEventsWithNoNesting, trackStartLevel, this, addCandyStripeToLongInteraction);\n\n return newLevel;\n }\n\n #addCandyStripeAndWarningForLongInteraction(\n entry: TraceEngine.Types.TraceEvents.SyntheticInteractionPair, eventIndex: number): void {\n const decorationsForEvent =\n this.#compatibilityBuilder.getFlameChartTimelineData().entryDecorations[eventIndex] || [];\n decorationsForEvent.push(\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,\n startAtTime: TraceEngine.Handlers.ModelHandlers.UserInteractions.LONG_INTERACTION_THRESHOLD,\n // Interaction events have whiskers, so we do not want to candy stripe\n // the entire duration. The box represents processing duration, so we only\n // candystripe up to the end of processing.\n endAtTime: entry.processingEnd,\n },\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE,\n customEndTime: entry.processingEnd,\n });\n this.#compatibilityBuilder.getFlameChartTimelineData().entryDecorations[eventIndex] = decorationsForEvent;\n }\n\n /*\n ------------------------------------------------------------------------------------\n The following methods are invoked by the flame chart renderer to query features about\n events on rendering.\n ------------------------------------------------------------------------------------\n */\n\n /**\n * Gets the color an event added by this appender should be rendered with.\n */\n colorForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): string {\n let idForColorGeneration = Components.EntryName.nameForEntry(event, this.#traceParsedData);\n if (TraceEngine.Types.TraceEvents.isSyntheticInteractionEvent(event)) {\n // Append the ID so that we vary the colours, ensuring that two events of\n // the same type are coloured differently.\n idForColorGeneration += event.interactionId;\n }\n return this.#colorGenerator.colorForID(idForColorGeneration);\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"InteractionsTrackAppender.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/InteractionsTrackAppender.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport type * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\n\nimport {buildGroupStyle, buildTrackHeader} from './AppenderUtils.js';\nimport {\n type CompatibilityTracksAppender,\n type TrackAppender,\n type TrackAppenderName,\n VisualLoggingTrackName,\n} from './CompatibilityTracksAppender.js';\nimport * as Components from './components/components.js';\n\nconst UIStrings = {\n /**\n *@description Text in Timeline Flame Chart Data Provider of the Performance panel\n */\n interactions: 'Interactions',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/InteractionsTrackAppender.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport class InteractionsTrackAppender implements TrackAppender {\n readonly appenderName: TrackAppenderName = 'Interactions';\n\n #colorGenerator: Common.Color.Generator;\n #compatibilityBuilder: CompatibilityTracksAppender;\n #parsedTrace: Readonly;\n\n constructor(\n compatibilityBuilder: CompatibilityTracksAppender, parsedTrace: Trace.Handlers.Types.ParsedTrace,\n colorGenerator: Common.Color.Generator) {\n this.#compatibilityBuilder = compatibilityBuilder;\n this.#colorGenerator = colorGenerator;\n this.#parsedTrace = parsedTrace;\n }\n\n /**\n * Appends into the flame chart data the data corresponding to the\n * interactions track.\n * @param trackStartLevel the horizontal level of the flame chart events where\n * the track's events will start being appended.\n * @param expanded wether the track should be rendered expanded.\n * @returns the first available level to append more data after having\n * appended the track's events.\n */\n appendTrackAtLevel(trackStartLevel: number, expanded?: boolean): number {\n if (this.#parsedTrace.UserInteractions.interactionEvents.length === 0) {\n return trackStartLevel;\n }\n this.#appendTrackHeaderAtLevel(trackStartLevel, expanded);\n return this.#appendInteractionsAtLevel(trackStartLevel);\n }\n\n /**\n * Adds into the flame chart data the header corresponding to the\n * interactions track. A header is added in the shape of a group in the\n * flame chart data. A group has a predefined style and a reference\n * to the definition of the legacy track (which should be removed\n * in the future).\n * @param currentLevel the flame chart level at which the header is\n * appended.\n */\n #appendTrackHeaderAtLevel(currentLevel: number, expanded?: boolean): void {\n const trackIsCollapsible = this.#parsedTrace.UserInteractions.interactionEvents.length > 0;\n const style = buildGroupStyle({collapsible: trackIsCollapsible, useDecoratorsForOverview: true});\n const group = buildTrackHeader(\n VisualLoggingTrackName.INTERACTIONS, currentLevel, i18nString(UIStrings.interactions), style,\n /* selectable= */ true, expanded);\n this.#compatibilityBuilder.registerTrackForGroup(group, this);\n }\n\n /**\n * Adds into the flame chart data the trace events dispatched by the\n * performance.measure API. These events are taken from the UserInteractions\n * handler.\n * @param currentLevel the flame chart level from which interactions will\n * be appended.\n * @returns the next level after the last occupied by the appended\n * interactions (the first available level to append more data).\n */\n #appendInteractionsAtLevel(trackStartLevel: number): number {\n const {interactionEventsWithNoNesting, interactionsOverThreshold} = this.#parsedTrace.UserInteractions;\n\n const addCandyStripeToLongInteraction =\n (event: Trace.Types.Events.SyntheticInteractionPair, index: number): void => {\n // Each interaction that we drew that is over the INP threshold needs to be\n // candy-striped.\n const overThreshold = interactionsOverThreshold.has(event);\n if (!overThreshold) {\n return;\n }\n if (index !== undefined) {\n this.#addCandyStripeAndWarningForLongInteraction(event, index);\n }\n };\n // Render all top level interactions (see UserInteractionsHandler for an explanation on the nesting) onto the track.\n const newLevel = this.#compatibilityBuilder.appendEventsAtLevel(\n interactionEventsWithNoNesting, trackStartLevel, this, addCandyStripeToLongInteraction);\n\n return newLevel;\n }\n\n #addCandyStripeAndWarningForLongInteraction(entry: Trace.Types.Events.SyntheticInteractionPair, eventIndex: number):\n void {\n const decorationsForEvent =\n this.#compatibilityBuilder.getFlameChartTimelineData().entryDecorations[eventIndex] || [];\n decorationsForEvent.push(\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,\n startAtTime: Trace.Handlers.ModelHandlers.UserInteractions.LONG_INTERACTION_THRESHOLD,\n // Interaction events have whiskers, so we do not want to candy stripe\n // the entire duration. The box represents processing duration, so we only\n // candystripe up to the end of processing.\n endAtTime: entry.processingEnd,\n },\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE,\n customEndTime: entry.processingEnd,\n });\n this.#compatibilityBuilder.getFlameChartTimelineData().entryDecorations[eventIndex] = decorationsForEvent;\n }\n\n /*\n ------------------------------------------------------------------------------------\n The following methods are invoked by the flame chart renderer to query features about\n events on rendering.\n ------------------------------------------------------------------------------------\n */\n\n /**\n * Gets the color an event added by this appender should be rendered with.\n */\n colorForEvent(event: Trace.Types.Events.Event): string {\n let idForColorGeneration = Components.EntryName.nameForEntry(event, this.#parsedTrace);\n if (Trace.Types.Events.isSyntheticInteraction(event)) {\n // Append the ID so that we vary the colours, ensuring that two events of\n // the same type are coloured differently.\n idForColorGeneration += event.interactionId;\n }\n return this.#colorGenerator.colorForID(idForColorGeneration);\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/LayoutShiftsTrackAppender.d.ts b/public/panels/timeline/LayoutShiftsTrackAppender.d.ts index 1f7367f17..74d80eb5c 100644 --- a/public/panels/timeline/LayoutShiftsTrackAppender.d.ts +++ b/public/panels/timeline/LayoutShiftsTrackAppender.d.ts @@ -1,10 +1,10 @@ -import * as TraceEngine from '../../models/trace/trace.js'; -import { type CompatibilityTracksAppender, type HighlightedEntryInfo, type TrackAppender, type TrackAppenderName } from './CompatibilityTracksAppender.js'; -export declare const LAYOUT_SHIFT_SYNTHETIC_DURATION: TraceEngine.Types.Timing.MicroSeconds; +import * as Trace from '../../models/trace/trace.js'; +import { type CompatibilityTracksAppender, type DrawOverride, type HighlightedEntryInfo, type TrackAppender, type TrackAppenderName } from './CompatibilityTracksAppender.js'; +export declare const LAYOUT_SHIFT_SYNTHETIC_DURATION: Trace.Types.Timing.MicroSeconds; export declare class LayoutShiftsTrackAppender implements TrackAppender { #private; readonly appenderName: TrackAppenderName; - constructor(compatibilityBuilder: CompatibilityTracksAppender, traceParsedData: TraceEngine.Handlers.Types.TraceParseData); + constructor(compatibilityBuilder: CompatibilityTracksAppender, parsedTrace: Trace.Handlers.Types.ParsedTrace); /** * Appends into the flame chart data the data corresponding to the * layout shifts track. @@ -18,14 +18,15 @@ export declare class LayoutShiftsTrackAppender implements TrackAppender { /** * Gets the color an event added by this appender should be rendered with. */ - colorForEvent(_event: TraceEngine.Types.TraceEvents.TraceEventData): string; + colorForEvent(_event: Trace.Types.Events.Event): string; /** * Gets the title an event added by this appender should be rendered with. */ - titleForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): string; + titleForEvent(event: Trace.Types.Events.Event): string; /** * Returns the info shown when an event added by this appender * is hovered in the timeline. */ - highlightedEntryInfo(event: TraceEngine.Types.TraceEvents.TraceEventLayoutShift): HighlightedEntryInfo; + highlightedEntryInfo(event: Trace.Types.Events.LayoutShift): HighlightedEntryInfo; + getDrawOverride(event: Trace.Types.Events.Event): DrawOverride | undefined; } diff --git a/public/panels/timeline/LayoutShiftsTrackAppender.js b/public/panels/timeline/LayoutShiftsTrackAppender.js index c06f848e9..ecf43684c 100644 --- a/public/panels/timeline/LayoutShiftsTrackAppender.js +++ b/public/panels/timeline/LayoutShiftsTrackAppender.js @@ -3,7 +3,7 @@ // found in the LICENSE file. import * as i18n from '../../core/i18n/i18n.js'; import * as Root from '../../core/root/root.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js'; import { buildGroupStyle, buildTrackHeader, getFormattedTime } from './AppenderUtils.js'; const UIStrings = { @@ -19,14 +19,14 @@ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); // set it to a small duration so that the user is able to see and click // them more easily. Long term we will explore a better UI solution to // allow us to do this properly and not hack around it. -export const LAYOUT_SHIFT_SYNTHETIC_DURATION = TraceEngine.Types.Timing.MicroSeconds(5_000); +export const LAYOUT_SHIFT_SYNTHETIC_DURATION = Trace.Types.Timing.MicroSeconds(5_000); export class LayoutShiftsTrackAppender { appenderName = 'LayoutShifts'; #compatibilityBuilder; - #traceParsedData; - constructor(compatibilityBuilder, traceParsedData) { + #parsedTrace; + constructor(compatibilityBuilder, parsedTrace) { this.#compatibilityBuilder = compatibilityBuilder; - this.#traceParsedData = traceParsedData; + this.#parsedTrace = parsedTrace; } /** * Appends into the flame chart data the data corresponding to the @@ -38,7 +38,7 @@ export class LayoutShiftsTrackAppender { * appended the track's events. */ appendTrackAtLevel(trackStartLevel, expanded) { - if (this.#traceParsedData.LayoutShifts.clusters.length === 0) { + if (this.#parsedTrace.LayoutShifts.clusters.length === 0) { return trackStartLevel; } this.#appendTrackHeaderAtLevel(trackStartLevel, expanded); @@ -68,24 +68,25 @@ export class LayoutShiftsTrackAppender { * layout shifts (the first available level to append more data). */ #appendLayoutShiftsAtLevel(currentLevel) { - const allLayoutShifts = this.#traceParsedData.LayoutShifts.clusters.flatMap(cluster => cluster.events); + const allLayoutShifts = this.#parsedTrace.LayoutShifts.clusters.flatMap(cluster => cluster.events); const setFlameChartEntryTotalTime = (_event, index) => { let totalTime = LAYOUT_SHIFT_SYNTHETIC_DURATION; - if (TraceEngine.Types.TraceEvents.isSyntheticLayoutShiftCluster(_event)) { + if (Trace.Types.Events.isSyntheticLayoutShiftCluster(_event)) { // This is to handle the cases where there is a singular shift for a cluster. // A single shift would make the cluster duration 0 and hard to read. // So in this case, give it the LAYOUT_SHIFT_SYNTHETIC_DURATION duration. totalTime = _event.dur || LAYOUT_SHIFT_SYNTHETIC_DURATION; } this.#compatibilityBuilder.getFlameChartTimelineData().entryTotalTimes[index] = - TraceEngine.Helpers.Timing.microSecondsToMilliseconds(totalTime); + Trace.Helpers.Timing.microSecondsToMilliseconds(totalTime); }; let shiftLevel = currentLevel; if (Root.Runtime.experiments.isEnabled("timeline-layout-shift-details" /* Root.Runtime.ExperimentName.TIMELINE_LAYOUT_SHIFT_DETAILS */)) { - const allClusters = this.#traceParsedData.LayoutShifts.clusters; - this.#compatibilityBuilder.appendEventsAtLevel(allClusters, currentLevel, this, setFlameChartEntryTotalTime); + const allClusters = this.#parsedTrace.LayoutShifts.clusters; + this.#compatibilityBuilder.appendEventsAtLevel(allClusters, currentLevel + 1, this, setFlameChartEntryTotalTime); // layout shifts should be below clusters. - shiftLevel = currentLevel + 1; + shiftLevel = currentLevel + 2; + return this.#compatibilityBuilder.appendEventsAtLevel(allLayoutShifts, shiftLevel, this); } return this.#compatibilityBuilder.appendEventsAtLevel(allLayoutShifts, shiftLevel, this, setFlameChartEntryTotalTime); } @@ -105,10 +106,10 @@ export class LayoutShiftsTrackAppender { * Gets the title an event added by this appender should be rendered with. */ titleForEvent(event) { - if (TraceEngine.Types.TraceEvents.isTraceEventLayoutShift(event)) { + if (Trace.Types.Events.isLayoutShift(event)) { return 'Layout shift'; } - if (TraceEngine.Types.TraceEvents.isSyntheticLayoutShiftCluster(event)) { + if (Trace.Types.Events.isSyntheticLayoutShiftCluster(event)) { return 'Layout shift cluster'; } return event.name; @@ -121,5 +122,39 @@ export class LayoutShiftsTrackAppender { const title = this.titleForEvent(event); return { title, formattedTime: getFormattedTime(event.dur) }; } + getDrawOverride(event) { + if (!Root.Runtime.experiments.isEnabled("timeline-layout-shift-details" /* Root.Runtime.ExperimentName.TIMELINE_LAYOUT_SHIFT_DETAILS */)) { + return; + } + if (!Trace.Types.Events.isLayoutShift(event)) { + return; + } + const score = event.args.data?.weighted_score_delta || 0; + // `buffer` is how much space is between the actual diamond shape and the + // edge of its select box. The select box will have a constant size + // so a larger `buffer` will create a smaller diamond. + // + // This logic will scale the size of the diamond based on the layout shift score. + // A LS score of >=0.1 will create a diamond of maximum size + // A LS score of ~0 will create a diamond of minimum size (exactly 0 should not happen in practice) + const bufferScale = 1 - Math.min(score / 0.1, 1); + const buffer = Math.round(bufferScale * 3); + return (context, x, y, _width, height) => { + const boxSize = height; + const halfSize = boxSize / 2; + context.beginPath(); + context.moveTo(x, y + buffer); + context.lineTo(x + halfSize - buffer, y + halfSize); + context.lineTo(x, y + height - buffer); + context.lineTo(x - halfSize + buffer, y + halfSize); + context.closePath(); + context.fillStyle = this.colorForEvent(event); + context.fill(); + return { + x: x - halfSize, + width: boxSize, + }; + }; + } } //# sourceMappingURL=LayoutShiftsTrackAppender.js.map \ No newline at end of file diff --git a/public/panels/timeline/LayoutShiftsTrackAppender.js.map b/public/panels/timeline/LayoutShiftsTrackAppender.js.map index 12b8f170e..2ab3e414e 100644 --- a/public/panels/timeline/LayoutShiftsTrackAppender.js.map +++ b/public/panels/timeline/LayoutShiftsTrackAppender.js.map @@ -1 +1 @@ -{"version":3,"file":"LayoutShiftsTrackAppender.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/LayoutShiftsTrackAppender.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Root from '../../core/root/root.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\n\nimport {buildGroupStyle, buildTrackHeader, getFormattedTime} from './AppenderUtils.js';\nimport {\n type CompatibilityTracksAppender,\n type HighlightedEntryInfo,\n type TrackAppender,\n type TrackAppenderName,\n VisualLoggingTrackName,\n} from './CompatibilityTracksAppender.js';\n\nconst UIStrings = {\n /**\n *@description Text in Timeline Flame Chart Data Provider of the Performance panel\n */\n layoutShifts: 'Layout shifts',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/LayoutShiftsTrackAppender.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\n// Bit of a hack: LayoutShifts are instant events, so have no duration. But\n// OPP doesn't do well at making tiny events easy to spot and click. So we\n// set it to a small duration so that the user is able to see and click\n// them more easily. Long term we will explore a better UI solution to\n// allow us to do this properly and not hack around it.\nexport const LAYOUT_SHIFT_SYNTHETIC_DURATION = TraceEngine.Types.Timing.MicroSeconds(5_000);\n\nexport class LayoutShiftsTrackAppender implements TrackAppender {\n readonly appenderName: TrackAppenderName = 'LayoutShifts';\n\n #compatibilityBuilder: CompatibilityTracksAppender;\n #traceParsedData: Readonly;\n\n constructor(\n compatibilityBuilder: CompatibilityTracksAppender, traceParsedData: TraceEngine.Handlers.Types.TraceParseData) {\n this.#compatibilityBuilder = compatibilityBuilder;\n this.#traceParsedData = traceParsedData;\n }\n\n /**\n * Appends into the flame chart data the data corresponding to the\n * layout shifts track.\n * @param trackStartLevel the horizontal level of the flame chart events where\n * the track's events will start being appended.\n * @param expanded wether the track should be rendered expanded.\n * @returns the first available level to append more data after having\n * appended the track's events.\n */\n appendTrackAtLevel(trackStartLevel: number, expanded?: boolean): number {\n if (this.#traceParsedData.LayoutShifts.clusters.length === 0) {\n return trackStartLevel;\n }\n this.#appendTrackHeaderAtLevel(trackStartLevel, expanded);\n return this.#appendLayoutShiftsAtLevel(trackStartLevel);\n }\n\n /**\n * Adds into the flame chart data the header corresponding to the\n * layout shifts track. A header is added in the shape of a group in the\n * flame chart data. A group has a predefined style and a reference\n * to the definition of the legacy track (which should be removed\n * in the future).\n * @param currentLevel the flame chart level at which the header is\n * appended.\n */\n #appendTrackHeaderAtLevel(currentLevel: number, expanded?: boolean): void {\n const style = buildGroupStyle({collapsible: false});\n const group = buildTrackHeader(\n VisualLoggingTrackName.LAYOUT_SHIFTS, currentLevel, i18nString(UIStrings.layoutShifts), style,\n /* selectable= */ true, expanded);\n this.#compatibilityBuilder.registerTrackForGroup(group, this);\n }\n\n /**\n * Adds into the flame chart data all the layout shifts. These are taken from\n * the clusters that are collected in the LayoutShiftsHandler.\n * @param currentLevel the flame chart level from which layout shifts will\n * be appended.\n * @returns the next level after the last occupied by the appended\n * layout shifts (the first available level to append more data).\n */\n #appendLayoutShiftsAtLevel(currentLevel: number): number {\n const allLayoutShifts = this.#traceParsedData.LayoutShifts.clusters.flatMap(cluster => cluster.events);\n const setFlameChartEntryTotalTime =\n (_event: TraceEngine.Types.TraceEvents.SyntheticLayoutShift|\n TraceEngine.Types.TraceEvents.SyntheticLayoutShiftCluster,\n index: number): void => {\n let totalTime = LAYOUT_SHIFT_SYNTHETIC_DURATION;\n if (TraceEngine.Types.TraceEvents.isSyntheticLayoutShiftCluster(_event)) {\n // This is to handle the cases where there is a singular shift for a cluster.\n // A single shift would make the cluster duration 0 and hard to read.\n // So in this case, give it the LAYOUT_SHIFT_SYNTHETIC_DURATION duration.\n totalTime = _event.dur || LAYOUT_SHIFT_SYNTHETIC_DURATION;\n }\n this.#compatibilityBuilder.getFlameChartTimelineData().entryTotalTimes[index] =\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds(totalTime);\n };\n let shiftLevel = currentLevel;\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_LAYOUT_SHIFT_DETAILS)) {\n const allClusters = this.#traceParsedData.LayoutShifts.clusters;\n this.#compatibilityBuilder.appendEventsAtLevel(allClusters, currentLevel, this, setFlameChartEntryTotalTime);\n\n // layout shifts should be below clusters.\n shiftLevel = currentLevel + 1;\n }\n\n return this.#compatibilityBuilder.appendEventsAtLevel(\n allLayoutShifts, shiftLevel, this, setFlameChartEntryTotalTime);\n }\n\n /*\n ------------------------------------------------------------------------------------\n The following methods are invoked by the flame chart renderer to query features about\n events on rendering.\n ------------------------------------------------------------------------------------\n */\n\n /**\n * Gets the color an event added by this appender should be rendered with.\n */\n colorForEvent(_event: TraceEngine.Types.TraceEvents.TraceEventData): string {\n return ThemeSupport.ThemeSupport.instance().getComputedValue('--app-color-rendering');\n }\n\n /**\n * Gets the title an event added by this appender should be rendered with.\n */\n titleForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): string {\n if (TraceEngine.Types.TraceEvents.isTraceEventLayoutShift(event)) {\n return 'Layout shift';\n }\n if (TraceEngine.Types.TraceEvents.isSyntheticLayoutShiftCluster(event)) {\n return 'Layout shift cluster';\n }\n return event.name;\n }\n\n /**\n * Returns the info shown when an event added by this appender\n * is hovered in the timeline.\n */\n highlightedEntryInfo(event: TraceEngine.Types.TraceEvents.TraceEventLayoutShift): HighlightedEntryInfo {\n const title = this.titleForEvent(event);\n return {title, formattedTime: getFormattedTime(event.dur)};\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"LayoutShiftsTrackAppender.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/LayoutShiftsTrackAppender.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAC7B,OAAO,KAAK,IAAI,MAAM,yBAAyB,CAAC;AAChD,OAAO,KAAK,IAAI,MAAM,yBAAyB,CAAC;AAChD,OAAO,KAAK,KAAK,MAAM,6BAA6B,CAAC;AACrD,OAAO,KAAK,YAAY,MAAM,gDAAgD,CAAC;AAE/E,OAAO,EAAC,eAAe,EAAE,gBAAgB,EAAE,gBAAgB,EAAC,MAAM,oBAAoB,CAAC;AAUvF,MAAM,SAAS,GAAG;IAChB;;OAEG;IACH,YAAY,EAAE,eAAe;CAC9B,CAAC;AAEF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,8CAA8C,EAAE,SAAS,CAAC,CAAC;AACpG,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAEtE,2EAA2E;AAC3E,0EAA0E;AAC1E,uEAAuE;AACvE,sEAAsE;AACtE,uDAAuD;AACvD,MAAM,CAAC,MAAM,+BAA+B,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;AAEtF,MAAM,OAAO,yBAAyB;IAC3B,YAAY,GAAsB,cAAc,CAAC;IAE1D,qBAAqB,CAA8B;IACnD,YAAY,CAA6C;IAEzD,YAAY,oBAAiD,EAAE,WAA6C;QAC1G,IAAI,CAAC,qBAAqB,GAAG,oBAAoB,CAAC;QAClD,IAAI,CAAC,YAAY,GAAG,WAAW,CAAC;IAClC,CAAC;IAED;;;;;;;;OAQG;IACH,kBAAkB,CAAC,eAAuB,EAAE,QAAkB;QAC5D,IAAI,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzD,OAAO,eAAe,CAAC;QACzB,CAAC;QACD,IAAI,CAAC,yBAAyB,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC,0BAA0B,CAAC,eAAe,CAAC,CAAC;IAC1D,CAAC;IAED;;;;;;;;OAQG;IACH,yBAAyB,CAAC,YAAoB,EAAE,QAAkB;QAChE,MAAM,KAAK,GAAG,eAAe,CAAC,EAAC,WAAW,EAAE,KAAK,EAAC,CAAC,CAAC;QACpD,MAAM,KAAK,GAAG,gBAAgB,6DACY,YAAY,EAAE,UAAU,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,KAAK;QAC7F,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACtC,IAAI,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAChE,CAAC;IAED;;;;;;;OAOG;IACH,0BAA0B,CAAC,YAAoB;QAC7C,MAAM,eAAe,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACnG,MAAM,2BAA2B,GAC7B,CAAC,MAA8F,EAC9F,KAAa,EAAQ,EAAE;YACtB,IAAI,SAAS,GAAG,+BAA+B,CAAC;YAChD,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,6BAA6B,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC7D,6EAA6E;gBAC7E,qEAAqE;gBACrE,yEAAyE;gBACzE,SAAS,GAAG,MAAM,CAAC,GAAG,IAAI,+BAA+B,CAAC;YAC5D,CAAC;YACD,IAAI,CAAC,qBAAqB,CAAC,yBAAyB,EAAE,CAAC,eAAe,CAAC,KAAK,CAAC;gBACzE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,SAAS,CAAC,CAAC;QACjE,CAAC,CAAC;QACN,IAAI,UAAU,GAAG,YAAY,CAAC;QAC9B,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,SAAS,iGAA2D,EAAE,CAAC;YAClG,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,QAAQ,CAAC;YAC5D,IAAI,CAAC,qBAAqB,CAAC,mBAAmB,CAAC,WAAW,EAAE,YAAY,GAAG,CAAC,EAAE,IAAI,EAAE,2BAA2B,CAAC,CAAC;YAEjH,0CAA0C;YAC1C,UAAU,GAAG,YAAY,GAAG,CAAC,CAAC;YAE9B,OAAO,IAAI,CAAC,qBAAqB,CAAC,mBAAmB,CAAC,eAAe,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;QAC3F,CAAC;QAED,OAAO,IAAI,CAAC,qBAAqB,CAAC,mBAAmB,CACjD,eAAe,EAAE,UAAU,EAAE,IAAI,EAAE,2BAA2B,CAAC,CAAC;IACtE,CAAC;IAED;;;;;MAKE;IAEF;;OAEG;IACH,aAAa,CAAC,MAAgC;QAC5C,OAAO,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,gBAAgB,CAAC,uBAAuB,CAAC,CAAC;IACxF,CAAC;IAED;;OAEG;IACH,aAAa,CAAC,KAA+B;QAC3C,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5C,OAAO,cAAc,CAAC;QACxB,CAAC;QACD,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,6BAA6B,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5D,OAAO,sBAAsB,CAAC;QAChC,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC;IACpB,CAAC;IAED;;;OAGG;IACH,oBAAoB,CAAC,KAAqC;QACxD,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACxC,OAAO,EAAC,KAAK,EAAE,aAAa,EAAE,gBAAgB,CAAC,KAAK,CAAC,GAAG,CAAC,EAAC,CAAC;IAC7D,CAAC;IAED,eAAe,CAAC,KAA+B;QAC7C,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,SAAS,iGAA2D,EAAE,CAAC;YACnG,OAAO;QACT,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;YAC7C,OAAO;QACT,CAAC;QAED,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,oBAAoB,IAAI,CAAC,CAAC;QAEzD,yEAAyE;QACzE,mEAAmE;QACnE,sDAAsD;QACtD,EAAE;QACF,iFAAiF;QACjF,4DAA4D;QAC5D,mGAAmG;QACnG,MAAM,WAAW,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,GAAG,CAAC,CAAC,CAAC;QAE3C,OAAO,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;YACvC,MAAM,OAAO,GAAG,MAAM,CAAC;YACvB,MAAM,QAAQ,GAAG,OAAO,GAAG,CAAC,CAAC;YAC7B,OAAO,CAAC,SAAS,EAAE,CAAC;YACpB,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC;YAC9B,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,QAAQ,GAAG,MAAM,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC;YACpD,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,GAAG,MAAM,CAAC,CAAC;YACvC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,QAAQ,GAAG,MAAM,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC;YACpD,OAAO,CAAC,SAAS,EAAE,CAAC;YACpB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YAC9C,OAAO,CAAC,IAAI,EAAE,CAAC;YACf,OAAO;gBACL,CAAC,EAAE,CAAC,GAAG,QAAQ;gBACf,KAAK,EAAE,OAAO;aACf,CAAC;QACJ,CAAC,CAAC;IACJ,CAAC;CACF","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Root from '../../core/root/root.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\n\nimport {buildGroupStyle, buildTrackHeader, getFormattedTime} from './AppenderUtils.js';\nimport {\n type CompatibilityTracksAppender,\n type DrawOverride,\n type HighlightedEntryInfo,\n type TrackAppender,\n type TrackAppenderName,\n VisualLoggingTrackName,\n} from './CompatibilityTracksAppender.js';\n\nconst UIStrings = {\n /**\n *@description Text in Timeline Flame Chart Data Provider of the Performance panel\n */\n layoutShifts: 'Layout shifts',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/LayoutShiftsTrackAppender.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\n// Bit of a hack: LayoutShifts are instant events, so have no duration. But\n// OPP doesn't do well at making tiny events easy to spot and click. So we\n// set it to a small duration so that the user is able to see and click\n// them more easily. Long term we will explore a better UI solution to\n// allow us to do this properly and not hack around it.\nexport const LAYOUT_SHIFT_SYNTHETIC_DURATION = Trace.Types.Timing.MicroSeconds(5_000);\n\nexport class LayoutShiftsTrackAppender implements TrackAppender {\n readonly appenderName: TrackAppenderName = 'LayoutShifts';\n\n #compatibilityBuilder: CompatibilityTracksAppender;\n #parsedTrace: Readonly;\n\n constructor(compatibilityBuilder: CompatibilityTracksAppender, parsedTrace: Trace.Handlers.Types.ParsedTrace) {\n this.#compatibilityBuilder = compatibilityBuilder;\n this.#parsedTrace = parsedTrace;\n }\n\n /**\n * Appends into the flame chart data the data corresponding to the\n * layout shifts track.\n * @param trackStartLevel the horizontal level of the flame chart events where\n * the track's events will start being appended.\n * @param expanded wether the track should be rendered expanded.\n * @returns the first available level to append more data after having\n * appended the track's events.\n */\n appendTrackAtLevel(trackStartLevel: number, expanded?: boolean): number {\n if (this.#parsedTrace.LayoutShifts.clusters.length === 0) {\n return trackStartLevel;\n }\n this.#appendTrackHeaderAtLevel(trackStartLevel, expanded);\n return this.#appendLayoutShiftsAtLevel(trackStartLevel);\n }\n\n /**\n * Adds into the flame chart data the header corresponding to the\n * layout shifts track. A header is added in the shape of a group in the\n * flame chart data. A group has a predefined style and a reference\n * to the definition of the legacy track (which should be removed\n * in the future).\n * @param currentLevel the flame chart level at which the header is\n * appended.\n */\n #appendTrackHeaderAtLevel(currentLevel: number, expanded?: boolean): void {\n const style = buildGroupStyle({collapsible: false});\n const group = buildTrackHeader(\n VisualLoggingTrackName.LAYOUT_SHIFTS, currentLevel, i18nString(UIStrings.layoutShifts), style,\n /* selectable= */ true, expanded);\n this.#compatibilityBuilder.registerTrackForGroup(group, this);\n }\n\n /**\n * Adds into the flame chart data all the layout shifts. These are taken from\n * the clusters that are collected in the LayoutShiftsHandler.\n * @param currentLevel the flame chart level from which layout shifts will\n * be appended.\n * @returns the next level after the last occupied by the appended\n * layout shifts (the first available level to append more data).\n */\n #appendLayoutShiftsAtLevel(currentLevel: number): number {\n const allLayoutShifts = this.#parsedTrace.LayoutShifts.clusters.flatMap(cluster => cluster.events);\n const setFlameChartEntryTotalTime =\n (_event: Trace.Types.Events.SyntheticLayoutShift|Trace.Types.Events.SyntheticLayoutShiftCluster,\n index: number): void => {\n let totalTime = LAYOUT_SHIFT_SYNTHETIC_DURATION;\n if (Trace.Types.Events.isSyntheticLayoutShiftCluster(_event)) {\n // This is to handle the cases where there is a singular shift for a cluster.\n // A single shift would make the cluster duration 0 and hard to read.\n // So in this case, give it the LAYOUT_SHIFT_SYNTHETIC_DURATION duration.\n totalTime = _event.dur || LAYOUT_SHIFT_SYNTHETIC_DURATION;\n }\n this.#compatibilityBuilder.getFlameChartTimelineData().entryTotalTimes[index] =\n Trace.Helpers.Timing.microSecondsToMilliseconds(totalTime);\n };\n let shiftLevel = currentLevel;\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_LAYOUT_SHIFT_DETAILS)) {\n const allClusters = this.#parsedTrace.LayoutShifts.clusters;\n this.#compatibilityBuilder.appendEventsAtLevel(allClusters, currentLevel + 1, this, setFlameChartEntryTotalTime);\n\n // layout shifts should be below clusters.\n shiftLevel = currentLevel + 2;\n\n return this.#compatibilityBuilder.appendEventsAtLevel(allLayoutShifts, shiftLevel, this);\n }\n\n return this.#compatibilityBuilder.appendEventsAtLevel(\n allLayoutShifts, shiftLevel, this, setFlameChartEntryTotalTime);\n }\n\n /*\n ------------------------------------------------------------------------------------\n The following methods are invoked by the flame chart renderer to query features about\n events on rendering.\n ------------------------------------------------------------------------------------\n */\n\n /**\n * Gets the color an event added by this appender should be rendered with.\n */\n colorForEvent(_event: Trace.Types.Events.Event): string {\n return ThemeSupport.ThemeSupport.instance().getComputedValue('--app-color-rendering');\n }\n\n /**\n * Gets the title an event added by this appender should be rendered with.\n */\n titleForEvent(event: Trace.Types.Events.Event): string {\n if (Trace.Types.Events.isLayoutShift(event)) {\n return 'Layout shift';\n }\n if (Trace.Types.Events.isSyntheticLayoutShiftCluster(event)) {\n return 'Layout shift cluster';\n }\n return event.name;\n }\n\n /**\n * Returns the info shown when an event added by this appender\n * is hovered in the timeline.\n */\n highlightedEntryInfo(event: Trace.Types.Events.LayoutShift): HighlightedEntryInfo {\n const title = this.titleForEvent(event);\n return {title, formattedTime: getFormattedTime(event.dur)};\n }\n\n getDrawOverride(event: Trace.Types.Events.Event): DrawOverride|undefined {\n if (!Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_LAYOUT_SHIFT_DETAILS)) {\n return;\n }\n\n if (!Trace.Types.Events.isLayoutShift(event)) {\n return;\n }\n\n const score = event.args.data?.weighted_score_delta || 0;\n\n // `buffer` is how much space is between the actual diamond shape and the\n // edge of its select box. The select box will have a constant size\n // so a larger `buffer` will create a smaller diamond.\n //\n // This logic will scale the size of the diamond based on the layout shift score.\n // A LS score of >=0.1 will create a diamond of maximum size\n // A LS score of ~0 will create a diamond of minimum size (exactly 0 should not happen in practice)\n const bufferScale = 1 - Math.min(score / 0.1, 1);\n const buffer = Math.round(bufferScale * 3);\n\n return (context, x, y, _width, height) => {\n const boxSize = height;\n const halfSize = boxSize / 2;\n context.beginPath();\n context.moveTo(x, y + buffer);\n context.lineTo(x + halfSize - buffer, y + halfSize);\n context.lineTo(x, y + height - buffer);\n context.lineTo(x - halfSize + buffer, y + halfSize);\n context.closePath();\n context.fillStyle = this.colorForEvent(event);\n context.fill();\n return {\n x: x - halfSize,\n width: boxSize,\n };\n };\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/ModificationsManager.d.ts b/public/panels/timeline/ModificationsManager.d.ts index 974ac8df2..d8d1538c0 100644 --- a/public/panels/timeline/ModificationsManager.d.ts +++ b/public/panels/timeline/ModificationsManager.d.ts @@ -1,8 +1,8 @@ -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as TimelineComponents from '../../panels/timeline/components/components.js'; import { EntriesFilter } from './EntriesFilter.js'; import * as Overlays from './overlays/overlays.js'; -export type UpdateAction = 'Remove' | 'Add' | 'UpdateLabel' | 'UpdateTimeRange' | 'UpdateLinkToEntry'; +export type UpdateAction = 'Remove' | 'Add' | 'UpdateLabel' | 'UpdateTimeRange' | 'UpdateLinkToEntry' | 'EnterLabelEditState'; export declare class AnnotationModifiedEvent extends Event { overlay: Overlays.Overlays.TimelineOverlay; action: UpdateAction; @@ -23,22 +23,22 @@ export declare class ModificationsManager extends EventTarget { * Initializes a ModificationsManager instance for a parsed trace or changes the active manager for an existing one. * This needs to be called if and a trace has been parsed or switched to. */ - static initAndActivateModificationsManager(traceModel: TraceEngine.TraceModel.Model, traceIndex: number): ModificationsManager | null; + static initAndActivateModificationsManager(traceModel: Trace.TraceModel.Model, traceIndex: number): ModificationsManager | null; private constructor(); getEntriesFilter(): EntriesFilter; getTimelineBreadcrumbs(): TimelineComponents.Breadcrumbs.Breadcrumbs; - createAnnotation(newAnnotation: TraceEngine.Types.File.Annotation, loadedFromFile?: boolean): void; - removeAnnotation(removedAnnotation: TraceEngine.Types.File.Annotation): void; + createAnnotation(newAnnotation: Trace.Types.File.Annotation, loadedFromFile?: boolean): void; + removeAnnotation(removedAnnotation: Trace.Types.File.Annotation): void; removeAnnotationOverlay(removedOverlay: Overlays.Overlays.TimelineOverlay): void; - updateAnnotation(updatedAnnotation: TraceEngine.Types.File.Annotation): void; + updateAnnotation(updatedAnnotation: Trace.Types.File.Annotation): void; updateAnnotationOverlay(updatedOverlay: Overlays.Overlays.TimelineOverlay): void; - getAnnotationByOverlay(overlay: Overlays.Overlays.TimelineOverlay): TraceEngine.Types.File.Annotation | null; - getAnnotations(): TraceEngine.Types.File.Annotation[]; + getAnnotationByOverlay(overlay: Overlays.Overlays.TimelineOverlay): Trace.Types.File.Annotation | null; + getAnnotations(): Trace.Types.File.Annotation[]; getOverlays(): Overlays.Overlays.TimelineOverlay[]; /** * Builds all modifications into a serializable object written into * the 'modifications' trace file metadata field. */ - toJSON(): TraceEngine.Types.File.Modifications; + toJSON(): Trace.Types.File.Modifications; applyModificationsIfPresent(): void; } diff --git a/public/panels/timeline/ModificationsManager.js b/public/panels/timeline/ModificationsManager.js index f3a747ee6..9d4bb4078 100644 --- a/public/panels/timeline/ModificationsManager.js +++ b/public/panels/timeline/ModificationsManager.js @@ -3,7 +3,7 @@ // found in the LICENSE file. import * as Common from '../../core/common/common.js'; import * as Platform from '../../core/platform/platform.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as TimelineComponents from '../../panels/timeline/components/components.js'; import { EntriesFilter } from './EntriesFilter.js'; import { EventsSerializer } from './EventsSerializer.js'; @@ -27,7 +27,7 @@ export class ModificationsManager extends EventTarget { #entriesFilter; #timelineBreadcrumbs; #modifications = null; - #traceParsedData; + #parsedTrace; #eventsSerializer; #overlayForAnnotation; #annotationsHiddenSetting; @@ -57,11 +57,11 @@ export class ModificationsManager extends EventTarget { activeManager = modificationsManagerByTraceIndex[traceIndex]; ModificationsManager.activeManager()?.applyModificationsIfPresent(); } - const traceParsedData = traceModel.traceParsedData(traceIndex); - if (!traceParsedData) { + const parsedTrace = traceModel.parsedTrace(traceIndex); + if (!parsedTrace) { throw new Error('ModificationsManager was initialized without a corresponding trace data'); } - const traceBounds = traceParsedData.Meta.traceBounds; + const traceBounds = parsedTrace.Meta.traceBounds; const traceEvents = traceModel.rawTraceEvents(traceIndex); if (!traceEvents) { throw new Error('ModificationsManager was initialized without a corresponding raw trace events array'); @@ -72,25 +72,25 @@ export class ModificationsManager extends EventTarget { } const metadata = traceModel.metadata(traceIndex); const newModificationsManager = new ModificationsManager({ - traceParsedData, + parsedTrace, traceBounds, rawTraceEvents: traceEvents, modifications: metadata?.modifications, - syntheticEvents: syntheticEventsManager.getSyntheticTraceEvents(), + syntheticEvents: syntheticEventsManager.getSyntheticTraces(), }); modificationsManagerByTraceIndex[traceIndex] = newModificationsManager; activeManager = newModificationsManager; ModificationsManager.activeManager()?.applyModificationsIfPresent(); return this.activeManager(); } - constructor({ traceParsedData, traceBounds, modifications }) { + constructor({ parsedTrace, traceBounds, modifications }) { super(); - const entryToNodeMap = new Map([...traceParsedData.Samples.entryToNode, ...traceParsedData.Renderer.entryToNode]); + const entryToNodeMap = new Map([...parsedTrace.Samples.entryToNode, ...parsedTrace.Renderer.entryToNode]); this.#entriesFilter = new EntriesFilter(entryToNodeMap); // Create first breadcrumb from the initial full window this.#timelineBreadcrumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(traceBounds); this.#modifications = modifications || null; - this.#traceParsedData = traceParsedData; + this.#parsedTrace = parsedTrace; this.#eventsSerializer = new EventsSerializer(); // This method is also called in SidebarAnnotationsTab, but calling this multiple times doesn't recreate the setting. // Instead, after the second call, the cached setting is returned. @@ -105,6 +105,14 @@ export class ModificationsManager extends EventTarget { return this.#timelineBreadcrumbs; } createAnnotation(newAnnotation, loadedFromFile = false) { + // If a label already exists on an entry and a user is trying to create a new one, start editing an existing label instead. + if (newAnnotation.type === 'ENTRY_LABEL') { + const overlay = this.#findLabelOverlayForEntry(newAnnotation.entry); + if (overlay) { + this.dispatchEvent(new AnnotationModifiedEvent(overlay, 'EnterLabelEditState')); + return; + } + } // If the new annotation created was not loaded from the file, set the annotations visibility setting to true. That way we make sure // the annotations are on when a new one is created. if (!loadedFromFile) { @@ -118,6 +126,14 @@ export class ModificationsManager extends EventTarget { this.#overlayForAnnotation.set(newAnnotation, newOverlay); this.dispatchEvent(new AnnotationModifiedEvent(newOverlay, 'Add')); } + #findLabelOverlayForEntry(entry) { + for (const [annotation, overlay] of this.#overlayForAnnotation.entries()) { + if (annotation.type === 'ENTRY_LABEL' && annotation.entry === entry) { + return overlay; + } + } + return null; + } #createOverlayFromAnnotation(annotation) { switch (annotation.type) { case 'ENTRY_LABEL': @@ -164,13 +180,13 @@ export class ModificationsManager extends EventTarget { updateAnnotation(updatedAnnotation) { const overlay = this.#overlayForAnnotation.get(updatedAnnotation); if (overlay && Overlays.Overlays.isTimeRangeLabel(overlay) && - TraceEngine.Types.File.isTimeRangeAnnotation(updatedAnnotation)) { + Trace.Types.File.isTimeRangeAnnotation(updatedAnnotation)) { overlay.label = updatedAnnotation.label; overlay.bounds = updatedAnnotation.bounds; this.dispatchEvent(new AnnotationModifiedEvent(overlay, 'UpdateTimeRange')); } else if (overlay && Overlays.Overlays.isEntriesLink(overlay) && - TraceEngine.Types.File.isEntriesLinkAnnotation(updatedAnnotation)) { + Trace.Types.File.isEntriesLinkAnnotation(updatedAnnotation)) { overlay.entryFrom = updatedAnnotation.entryFrom; overlay.entryTo = updatedAnnotation.entryTo; this.dispatchEvent(new AnnotationModifiedEvent(overlay, 'UpdateLinkToEntry')); @@ -234,7 +250,7 @@ export class ModificationsManager extends EventTarget { const linksBetweenEntriesSerialized = []; for (let i = 0; i < annotations.length; i++) { const currAnnotation = annotations[i]; - if (TraceEngine.Types.File.isEntryLabelAnnotation(currAnnotation)) { + if (Trace.Types.File.isEntryLabelAnnotation(currAnnotation)) { const serializedEvent = this.#eventsSerializer.keyForEvent(currAnnotation.entry); if (serializedEvent) { entryLabelsSerialized.push({ @@ -243,13 +259,13 @@ export class ModificationsManager extends EventTarget { }); } } - else if (TraceEngine.Types.File.isTimeRangeAnnotation(currAnnotation)) { + else if (Trace.Types.File.isTimeRangeAnnotation(currAnnotation)) { labelledTimeRangesSerialized.push({ bounds: currAnnotation.bounds, label: currAnnotation.label, }); } - else if (TraceEngine.Types.File.isEntriesLinkAnnotation(currAnnotation)) { + else if (Trace.Types.File.isEntriesLinkAnnotation(currAnnotation)) { // Only save the links between entries that are fully created and have the entry that it is pointing to set if (currAnnotation.entryTo) { const serializedFromEvent = this.#eventsSerializer.keyForEvent(currAnnotation.entryFrom); @@ -287,7 +303,7 @@ export class ModificationsManager extends EventTarget { entryLabels.forEach(entryLabel => { this.createAnnotation({ type: 'ENTRY_LABEL', - entry: this.#eventsSerializer.eventForKey(entryLabel.entry, this.#traceParsedData), + entry: this.#eventsSerializer.eventForKey(entryLabel.entry, this.#parsedTrace), label: entryLabel.label, }, true); }); @@ -303,8 +319,8 @@ export class ModificationsManager extends EventTarget { linksBetweenEntries.forEach(linkBetweenEntries => { this.createAnnotation({ type: 'ENTRIES_LINK', - entryFrom: this.#eventsSerializer.eventForKey(linkBetweenEntries.entryFrom, this.#traceParsedData), - entryTo: this.#eventsSerializer.eventForKey(linkBetweenEntries.entryTo, this.#traceParsedData), + entryFrom: this.#eventsSerializer.eventForKey(linkBetweenEntries.entryFrom, this.#parsedTrace), + entryTo: this.#eventsSerializer.eventForKey(linkBetweenEntries.entryTo, this.#parsedTrace), }, true); }); } @@ -321,8 +337,8 @@ export class ModificationsManager extends EventTarget { } #applyEntriesFilterModifications(hiddenEntriesKeys, expandableEntriesKeys) { try { - const hiddenEntries = hiddenEntriesKeys.map(key => this.#eventsSerializer.eventForKey(key, this.#traceParsedData)); - const expandableEntries = expandableEntriesKeys.map(key => this.#eventsSerializer.eventForKey(key, this.#traceParsedData)); + const hiddenEntries = hiddenEntriesKeys.map(key => this.#eventsSerializer.eventForKey(key, this.#parsedTrace)); + const expandableEntries = expandableEntriesKeys.map(key => this.#eventsSerializer.eventForKey(key, this.#parsedTrace)); this.#entriesFilter.setHiddenAndExpandableEntries(hiddenEntries, expandableEntries); } catch (err) { diff --git a/public/panels/timeline/ModificationsManager.js.map b/public/panels/timeline/ModificationsManager.js.map index d02462f52..4bc3d2155 100644 --- a/public/panels/timeline/ModificationsManager.js.map +++ b/public/panels/timeline/ModificationsManager.js.map @@ -1 +1 @@ -{"version":3,"file":"ModificationsManager.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/ModificationsManager.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as TimelineComponents from '../../panels/timeline/components/components.js';\n\nimport {EntriesFilter} from './EntriesFilter.js';\nimport {EventsSerializer} from './EventsSerializer.js';\nimport * as Overlays from './overlays/overlays.js';\n\nconst modificationsManagerByTraceIndex: ModificationsManager[] = [];\nlet activeManager: ModificationsManager|null;\n\nexport type UpdateAction = 'Remove'|'Add'|'UpdateLabel'|'UpdateTimeRange'|'UpdateLinkToEntry';\n\n// Event dispatched after an annotation was added, removed or updated.\n// The event argument is the Overlay that needs to be created,removed\n// or updated by `Overlays.ts` and the action that needs to be applied to it.\nexport class AnnotationModifiedEvent extends Event {\n static readonly eventName = 'annotationmodifiedevent';\n\n constructor(public overlay: Overlays.Overlays.TimelineOverlay, public action: UpdateAction) {\n super(AnnotationModifiedEvent.eventName);\n }\n}\n\ntype ModificationsManagerData = {\n traceParsedData: TraceEngine.Handlers.Types.TraceParseData,\n traceBounds: TraceEngine.Types.Timing.TraceWindowMicroSeconds,\n rawTraceEvents: readonly TraceEngine.Types.TraceEvents.TraceEventData[],\n syntheticEvents: TraceEngine.Types.TraceEvents.SyntheticBasedEvent[],\n modifications?: TraceEngine.Types.File.Modifications,\n};\n\nexport class ModificationsManager extends EventTarget {\n #entriesFilter: EntriesFilter;\n #timelineBreadcrumbs: TimelineComponents.Breadcrumbs.Breadcrumbs;\n #modifications: TraceEngine.Types.File.Modifications|null = null;\n #traceParsedData: TraceEngine.Handlers.Types.TraceParseData;\n #eventsSerializer: EventsSerializer;\n #overlayForAnnotation: Map;\n readonly #annotationsHiddenSetting: Common.Settings.Setting;\n\n /**\n * Gets the ModificationsManager instance corresponding to a trace\n * given its index used in Model#traces. If no index is passed gets\n * the manager instance for the last trace. If no instance is found,\n * throws.\n */\n static activeManager(): ModificationsManager|null {\n return activeManager;\n }\n\n static reset(): void {\n modificationsManagerByTraceIndex.length = 0;\n activeManager = null;\n }\n\n /**\n * Initializes a ModificationsManager instance for a parsed trace or changes the active manager for an existing one.\n * This needs to be called if and a trace has been parsed or switched to.\n */\n static initAndActivateModificationsManager(traceModel: TraceEngine.TraceModel.Model, traceIndex: number):\n ModificationsManager|null {\n // If a manager for a given index has already been created, active it.\n if (modificationsManagerByTraceIndex[traceIndex]) {\n if (activeManager === modificationsManagerByTraceIndex[traceIndex]) {\n return activeManager;\n }\n\n activeManager = modificationsManagerByTraceIndex[traceIndex];\n ModificationsManager.activeManager()?.applyModificationsIfPresent();\n }\n const traceParsedData = traceModel.traceParsedData(traceIndex);\n if (!traceParsedData) {\n throw new Error('ModificationsManager was initialized without a corresponding trace data');\n }\n const traceBounds = traceParsedData.Meta.traceBounds;\n const traceEvents = traceModel.rawTraceEvents(traceIndex);\n if (!traceEvents) {\n throw new Error('ModificationsManager was initialized without a corresponding raw trace events array');\n }\n const syntheticEventsManager = traceModel.syntheticTraceEventsManager(traceIndex);\n if (!syntheticEventsManager) {\n throw new Error('ModificationsManager was initialized without a corresponding SyntheticEventsManager');\n }\n const metadata = traceModel.metadata(traceIndex);\n const newModificationsManager = new ModificationsManager({\n traceParsedData,\n traceBounds,\n rawTraceEvents: traceEvents,\n modifications: metadata?.modifications,\n syntheticEvents: syntheticEventsManager.getSyntheticTraceEvents(),\n });\n modificationsManagerByTraceIndex[traceIndex] = newModificationsManager;\n activeManager = newModificationsManager;\n ModificationsManager.activeManager()?.applyModificationsIfPresent();\n return this.activeManager();\n }\n\n private constructor({traceParsedData, traceBounds, modifications}: ModificationsManagerData) {\n super();\n const entryToNodeMap = new Map([...traceParsedData.Samples.entryToNode, ...traceParsedData.Renderer.entryToNode]);\n this.#entriesFilter = new EntriesFilter(entryToNodeMap);\n // Create first breadcrumb from the initial full window\n this.#timelineBreadcrumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(traceBounds);\n this.#modifications = modifications || null;\n this.#traceParsedData = traceParsedData;\n this.#eventsSerializer = new EventsSerializer();\n // This method is also called in SidebarAnnotationsTab, but calling this multiple times doesn't recreate the setting.\n // Instead, after the second call, the cached setting is returned.\n this.#annotationsHiddenSetting = Common.Settings.Settings.instance().moduleSetting('annotations-hidden');\n // TODO: Assign annotations loaded from the trace file\n this.#overlayForAnnotation = new Map();\n }\n\n getEntriesFilter(): EntriesFilter {\n return this.#entriesFilter;\n }\n\n getTimelineBreadcrumbs(): TimelineComponents.Breadcrumbs.Breadcrumbs {\n return this.#timelineBreadcrumbs;\n }\n\n createAnnotation(newAnnotation: TraceEngine.Types.File.Annotation, loadedFromFile: boolean = false): void {\n // If the new annotation created was not loaded from the file, set the annotations visibility setting to true. That way we make sure\n // the annotations are on when a new one is created.\n if (!loadedFromFile) {\n // Time range annotation could also be used to check the length of a selection in the timeline. Therefore, only set the annotations\n // hidden to true if annotations label is added. This is done in OverlaysImpl.\n if (newAnnotation.type !== 'TIME_RANGE') {\n this.#annotationsHiddenSetting.set(false);\n }\n }\n const newOverlay = this.#createOverlayFromAnnotation(newAnnotation);\n this.#overlayForAnnotation.set(newAnnotation, newOverlay);\n this.dispatchEvent(new AnnotationModifiedEvent(newOverlay, 'Add'));\n }\n\n #createOverlayFromAnnotation(annotation: TraceEngine.Types.File.Annotation): Overlays.Overlays.EntryLabel\n |Overlays.Overlays.TimeRangeLabel|Overlays.Overlays.EntriesLink {\n switch (annotation.type) {\n case 'ENTRY_LABEL':\n return {\n type: 'ENTRY_LABEL',\n entry: annotation.entry,\n label: annotation.label,\n };\n case 'TIME_RANGE':\n return {\n type: 'TIME_RANGE',\n label: annotation.label,\n showDuration: true,\n bounds: annotation.bounds,\n };\n case 'ENTRIES_LINK':\n return {\n type: 'ENTRIES_LINK',\n entryFrom: annotation.entryFrom,\n entryTo: annotation.entryTo,\n };\n default:\n Platform.assertNever(annotation, 'Overlay for provided annotation cannot be created');\n }\n }\n\n removeAnnotation(removedAnnotation: TraceEngine.Types.File.Annotation): void {\n const overlayToRemove = this.#overlayForAnnotation.get(removedAnnotation);\n if (!overlayToRemove) {\n console.warn('Overlay for deleted Annotation does not exist');\n return;\n }\n this.#overlayForAnnotation.delete(removedAnnotation);\n this.dispatchEvent(new AnnotationModifiedEvent(overlayToRemove, 'Remove'));\n }\n\n removeAnnotationOverlay(removedOverlay: Overlays.Overlays.TimelineOverlay): void {\n const annotationForRemovedOverlay = this.getAnnotationByOverlay(removedOverlay);\n if (!annotationForRemovedOverlay) {\n console.warn('Annotation for deleted Overlay does not exist');\n return;\n }\n this.#overlayForAnnotation.delete(annotationForRemovedOverlay);\n this.dispatchEvent(new AnnotationModifiedEvent(removedOverlay, 'Remove'));\n }\n\n updateAnnotation(updatedAnnotation: TraceEngine.Types.File.Annotation): void {\n const overlay = this.#overlayForAnnotation.get(updatedAnnotation);\n\n if (overlay && Overlays.Overlays.isTimeRangeLabel(overlay) &&\n TraceEngine.Types.File.isTimeRangeAnnotation(updatedAnnotation)) {\n overlay.label = updatedAnnotation.label;\n overlay.bounds = updatedAnnotation.bounds;\n this.dispatchEvent(new AnnotationModifiedEvent(overlay, 'UpdateTimeRange'));\n\n } else if (\n overlay && Overlays.Overlays.isEntriesLink(overlay) &&\n TraceEngine.Types.File.isEntriesLinkAnnotation(updatedAnnotation)) {\n overlay.entryFrom = updatedAnnotation.entryFrom;\n overlay.entryTo = updatedAnnotation.entryTo;\n this.dispatchEvent(new AnnotationModifiedEvent(overlay, 'UpdateLinkToEntry'));\n\n } else {\n console.error('Annotation could not be updated');\n }\n }\n\n updateAnnotationOverlay(updatedOverlay: Overlays.Overlays.TimelineOverlay): void {\n const annotationForUpdatedOverlay = this.getAnnotationByOverlay(updatedOverlay);\n if (!annotationForUpdatedOverlay) {\n console.warn('Annotation for updated Overlay does not exist');\n return;\n }\n\n if ((updatedOverlay.type === 'ENTRY_LABEL' && annotationForUpdatedOverlay.type === 'ENTRY_LABEL') ||\n (updatedOverlay.type === 'TIME_RANGE' && annotationForUpdatedOverlay.type === 'TIME_RANGE')) {\n this.#annotationsHiddenSetting.set(false);\n annotationForUpdatedOverlay.label = updatedOverlay.label;\n }\n this.dispatchEvent(new AnnotationModifiedEvent(updatedOverlay, 'UpdateLabel'));\n }\n\n getAnnotationByOverlay(overlay: Overlays.Overlays.TimelineOverlay): TraceEngine.Types.File.Annotation|null {\n for (const [annotation, currOverlay] of this.#overlayForAnnotation.entries()) {\n if (currOverlay === overlay) {\n return annotation;\n }\n }\n return null;\n }\n\n getAnnotations(): TraceEngine.Types.File.Annotation[] {\n return [...this.#overlayForAnnotation.keys()];\n }\n\n getOverlays(): Overlays.Overlays.TimelineOverlay[] {\n return [...this.#overlayForAnnotation.values()];\n }\n\n /**\n * Builds all modifications into a serializable object written into\n * the 'modifications' trace file metadata field.\n */\n toJSON(): TraceEngine.Types.File.Modifications {\n const hiddenEntries = this.#entriesFilter.invisibleEntries()\n .map(entry => this.#eventsSerializer.keyForEvent(entry))\n .filter(entry => entry !== null) as TraceEngine.Types.File.TraceEventSerializableKey[];\n const expandableEntries =\n this.#entriesFilter.expandableEntries()\n .map(entry => this.#eventsSerializer.keyForEvent(entry))\n .filter(entry => entry !== null) as TraceEngine.Types.File.TraceEventSerializableKey[];\n this.#modifications = {\n entriesModifications: {\n hiddenEntries,\n expandableEntries,\n },\n initialBreadcrumb: this.#timelineBreadcrumbs.initialBreadcrumb,\n annotations: this.#annotationsJSON(),\n };\n return this.#modifications;\n }\n\n #annotationsJSON(): TraceEngine.Types.File.SerializedAnnotations {\n const annotations = this.getAnnotations();\n const entryLabelsSerialized: TraceEngine.Types.File.EntryLabelAnnotationSerialized[] = [];\n const labelledTimeRangesSerialized: TraceEngine.Types.File.TimeRangeAnnotationSerialized[] = [];\n const linksBetweenEntriesSerialized: TraceEngine.Types.File.EntriesLinkAnnotationSerialized[] = [];\n\n for (let i = 0; i < annotations.length; i++) {\n const currAnnotation = annotations[i];\n if (TraceEngine.Types.File.isEntryLabelAnnotation(currAnnotation)) {\n const serializedEvent = this.#eventsSerializer.keyForEvent(currAnnotation.entry);\n if (serializedEvent) {\n entryLabelsSerialized.push({\n entry: serializedEvent,\n label: currAnnotation.label,\n });\n }\n } else if (TraceEngine.Types.File.isTimeRangeAnnotation(currAnnotation)) {\n labelledTimeRangesSerialized.push({\n bounds: currAnnotation.bounds,\n label: currAnnotation.label,\n });\n } else if (TraceEngine.Types.File.isEntriesLinkAnnotation(currAnnotation)) {\n // Only save the links between entries that are fully created and have the entry that it is pointing to set\n if (currAnnotation.entryTo) {\n const serializedFromEvent = this.#eventsSerializer.keyForEvent(currAnnotation.entryFrom);\n const serializedToEvent = this.#eventsSerializer.keyForEvent(currAnnotation.entryTo);\n if (serializedFromEvent && serializedToEvent) {\n linksBetweenEntriesSerialized.push({\n entryFrom: serializedFromEvent,\n entryTo: serializedToEvent,\n });\n }\n }\n }\n }\n\n return {\n entryLabels: entryLabelsSerialized,\n labelledTimeRanges: labelledTimeRangesSerialized,\n linksBetweenEntries: linksBetweenEntriesSerialized,\n };\n }\n\n applyModificationsIfPresent(): void {\n if (!this.#modifications || !this.#modifications.annotations) {\n return;\n }\n\n const hiddenEntries = this.#modifications.entriesModifications.hiddenEntries;\n const expandableEntries = this.#modifications.entriesModifications.expandableEntries;\n\n this.#timelineBreadcrumbs.setInitialBreadcrumbFromLoadedModifications(this.#modifications.initialBreadcrumb);\n this.#applyEntriesFilterModifications(hiddenEntries, expandableEntries);\n this.#applyStoredAnnotations(this.#modifications.annotations);\n }\n\n #applyStoredAnnotations(annotations: TraceEngine.Types.File.SerializedAnnotations): void {\n try {\n // Assign annotations to an empty array if they don't exist to not\n // break the traces that were saved before those annotations were implemented\n const entryLabels = annotations.entryLabels ?? [];\n entryLabels.forEach(entryLabel => {\n this.createAnnotation(\n {\n type: 'ENTRY_LABEL',\n entry: this.#eventsSerializer.eventForKey(entryLabel.entry, this.#traceParsedData),\n label: entryLabel.label,\n },\n true);\n });\n\n const timeRanges = annotations.labelledTimeRanges ?? [];\n timeRanges.forEach(timeRange => {\n this.createAnnotation(\n {\n type: 'TIME_RANGE',\n bounds: timeRange.bounds,\n label: timeRange.label,\n },\n true);\n });\n\n const linksBetweenEntries = annotations.linksBetweenEntries ?? [];\n linksBetweenEntries.forEach(linkBetweenEntries => {\n this.createAnnotation(\n {\n type: 'ENTRIES_LINK',\n entryFrom: this.#eventsSerializer.eventForKey(linkBetweenEntries.entryFrom, this.#traceParsedData),\n entryTo: this.#eventsSerializer.eventForKey(linkBetweenEntries.entryTo, this.#traceParsedData),\n },\n true);\n });\n } catch (err) {\n // This function is wrapped in a try/catch just in case we get any incoming\n // trace files with broken event keys. Shouldn't happen of course, but if\n // it does, we can discard all the data and then continue loading the\n // trace, rather than have the panel entirely break. This also prevents any\n // issue where we accidentally break the event serializer and break people\n // loading traces; let's at least make sure they can load the panel, even\n // if their annotations are gone.\n console.warn('Failed to apply stored annotations', err);\n }\n }\n\n #applyEntriesFilterModifications(\n hiddenEntriesKeys: TraceEngine.Types.File.TraceEventSerializableKey[],\n expandableEntriesKeys: TraceEngine.Types.File.TraceEventSerializableKey[]): void {\n try {\n const hiddenEntries =\n hiddenEntriesKeys.map(key => this.#eventsSerializer.eventForKey(key, this.#traceParsedData));\n const expandableEntries =\n expandableEntriesKeys.map(key => this.#eventsSerializer.eventForKey(key, this.#traceParsedData));\n this.#entriesFilter.setHiddenAndExpandableEntries(hiddenEntries, expandableEntries);\n } catch (err) {\n console.warn('Failed to apply entriesFilter modifications', err);\n // If there was some invalid data, let's just back out and clear it\n // entirely. This is better than applying a subset of all the hidden\n // entries, which could cause an odd state in the flamechart.\n this.#entriesFilter.setHiddenAndExpandableEntries([], []);\n }\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"ModificationsManager.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/ModificationsManager.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as TimelineComponents from '../../panels/timeline/components/components.js';\n\nimport {EntriesFilter} from './EntriesFilter.js';\nimport {EventsSerializer} from './EventsSerializer.js';\nimport * as Overlays from './overlays/overlays.js';\n\nconst modificationsManagerByTraceIndex: ModificationsManager[] = [];\nlet activeManager: ModificationsManager|null;\n\nexport type UpdateAction = 'Remove'|'Add'|'UpdateLabel'|'UpdateTimeRange'|'UpdateLinkToEntry'|'EnterLabelEditState';\n\n// Event dispatched after an annotation was added, removed or updated.\n// The event argument is the Overlay that needs to be created,removed\n// or updated by `Overlays.ts` and the action that needs to be applied to it.\nexport class AnnotationModifiedEvent extends Event {\n static readonly eventName = 'annotationmodifiedevent';\n\n constructor(public overlay: Overlays.Overlays.TimelineOverlay, public action: UpdateAction) {\n super(AnnotationModifiedEvent.eventName);\n }\n}\n\ntype ModificationsManagerData = {\n parsedTrace: Trace.Handlers.Types.ParsedTrace,\n traceBounds: Trace.Types.Timing.TraceWindowMicroSeconds,\n rawTraceEvents: readonly Trace.Types.Events.Event[],\n syntheticEvents: Trace.Types.Events.SyntheticBased[],\n modifications?: Trace.Types.File.Modifications,\n};\n\nexport class ModificationsManager extends EventTarget {\n #entriesFilter: EntriesFilter;\n #timelineBreadcrumbs: TimelineComponents.Breadcrumbs.Breadcrumbs;\n #modifications: Trace.Types.File.Modifications|null = null;\n #parsedTrace: Trace.Handlers.Types.ParsedTrace;\n #eventsSerializer: EventsSerializer;\n #overlayForAnnotation: Map;\n readonly #annotationsHiddenSetting: Common.Settings.Setting;\n\n /**\n * Gets the ModificationsManager instance corresponding to a trace\n * given its index used in Model#traces. If no index is passed gets\n * the manager instance for the last trace. If no instance is found,\n * throws.\n */\n static activeManager(): ModificationsManager|null {\n return activeManager;\n }\n\n static reset(): void {\n modificationsManagerByTraceIndex.length = 0;\n activeManager = null;\n }\n\n /**\n * Initializes a ModificationsManager instance for a parsed trace or changes the active manager for an existing one.\n * This needs to be called if and a trace has been parsed or switched to.\n */\n static initAndActivateModificationsManager(traceModel: Trace.TraceModel.Model, traceIndex: number):\n ModificationsManager|null {\n // If a manager for a given index has already been created, active it.\n if (modificationsManagerByTraceIndex[traceIndex]) {\n if (activeManager === modificationsManagerByTraceIndex[traceIndex]) {\n return activeManager;\n }\n\n activeManager = modificationsManagerByTraceIndex[traceIndex];\n ModificationsManager.activeManager()?.applyModificationsIfPresent();\n }\n const parsedTrace = traceModel.parsedTrace(traceIndex);\n if (!parsedTrace) {\n throw new Error('ModificationsManager was initialized without a corresponding trace data');\n }\n const traceBounds = parsedTrace.Meta.traceBounds;\n const traceEvents = traceModel.rawTraceEvents(traceIndex);\n if (!traceEvents) {\n throw new Error('ModificationsManager was initialized without a corresponding raw trace events array');\n }\n const syntheticEventsManager = traceModel.syntheticTraceEventsManager(traceIndex);\n if (!syntheticEventsManager) {\n throw new Error('ModificationsManager was initialized without a corresponding SyntheticEventsManager');\n }\n const metadata = traceModel.metadata(traceIndex);\n const newModificationsManager = new ModificationsManager({\n parsedTrace,\n traceBounds,\n rawTraceEvents: traceEvents,\n modifications: metadata?.modifications,\n syntheticEvents: syntheticEventsManager.getSyntheticTraces(),\n });\n modificationsManagerByTraceIndex[traceIndex] = newModificationsManager;\n activeManager = newModificationsManager;\n ModificationsManager.activeManager()?.applyModificationsIfPresent();\n return this.activeManager();\n }\n\n private constructor({parsedTrace, traceBounds, modifications}: ModificationsManagerData) {\n super();\n const entryToNodeMap = new Map([...parsedTrace.Samples.entryToNode, ...parsedTrace.Renderer.entryToNode]);\n this.#entriesFilter = new EntriesFilter(entryToNodeMap);\n // Create first breadcrumb from the initial full window\n this.#timelineBreadcrumbs = new TimelineComponents.Breadcrumbs.Breadcrumbs(traceBounds);\n this.#modifications = modifications || null;\n this.#parsedTrace = parsedTrace;\n this.#eventsSerializer = new EventsSerializer();\n // This method is also called in SidebarAnnotationsTab, but calling this multiple times doesn't recreate the setting.\n // Instead, after the second call, the cached setting is returned.\n this.#annotationsHiddenSetting = Common.Settings.Settings.instance().moduleSetting('annotations-hidden');\n // TODO: Assign annotations loaded from the trace file\n this.#overlayForAnnotation = new Map();\n }\n\n getEntriesFilter(): EntriesFilter {\n return this.#entriesFilter;\n }\n\n getTimelineBreadcrumbs(): TimelineComponents.Breadcrumbs.Breadcrumbs {\n return this.#timelineBreadcrumbs;\n }\n\n createAnnotation(newAnnotation: Trace.Types.File.Annotation, loadedFromFile: boolean = false): void {\n // If a label already exists on an entry and a user is trying to create a new one, start editing an existing label instead.\n if (newAnnotation.type === 'ENTRY_LABEL') {\n const overlay = this.#findLabelOverlayForEntry(newAnnotation.entry);\n if (overlay) {\n this.dispatchEvent(new AnnotationModifiedEvent(overlay, 'EnterLabelEditState'));\n return;\n }\n }\n\n // If the new annotation created was not loaded from the file, set the annotations visibility setting to true. That way we make sure\n // the annotations are on when a new one is created.\n if (!loadedFromFile) {\n // Time range annotation could also be used to check the length of a selection in the timeline. Therefore, only set the annotations\n // hidden to true if annotations label is added. This is done in OverlaysImpl.\n if (newAnnotation.type !== 'TIME_RANGE') {\n this.#annotationsHiddenSetting.set(false);\n }\n }\n const newOverlay = this.#createOverlayFromAnnotation(newAnnotation);\n this.#overlayForAnnotation.set(newAnnotation, newOverlay);\n this.dispatchEvent(new AnnotationModifiedEvent(newOverlay, 'Add'));\n }\n\n #findLabelOverlayForEntry(entry: Trace.Types.Events.Event): Overlays.Overlays.TimelineOverlay|null {\n for (const [annotation, overlay] of this.#overlayForAnnotation.entries()) {\n if (annotation.type === 'ENTRY_LABEL' && annotation.entry === entry) {\n return overlay;\n }\n }\n\n return null;\n }\n\n #createOverlayFromAnnotation(annotation: Trace.Types.File.Annotation): Overlays.Overlays.EntryLabel\n |Overlays.Overlays.TimeRangeLabel|Overlays.Overlays.EntriesLink {\n switch (annotation.type) {\n case 'ENTRY_LABEL':\n return {\n type: 'ENTRY_LABEL',\n entry: annotation.entry,\n label: annotation.label,\n };\n case 'TIME_RANGE':\n return {\n type: 'TIME_RANGE',\n label: annotation.label,\n showDuration: true,\n bounds: annotation.bounds,\n };\n case 'ENTRIES_LINK':\n return {\n type: 'ENTRIES_LINK',\n entryFrom: annotation.entryFrom,\n entryTo: annotation.entryTo,\n };\n default:\n Platform.assertNever(annotation, 'Overlay for provided annotation cannot be created');\n }\n }\n\n removeAnnotation(removedAnnotation: Trace.Types.File.Annotation): void {\n const overlayToRemove = this.#overlayForAnnotation.get(removedAnnotation);\n if (!overlayToRemove) {\n console.warn('Overlay for deleted Annotation does not exist');\n return;\n }\n this.#overlayForAnnotation.delete(removedAnnotation);\n this.dispatchEvent(new AnnotationModifiedEvent(overlayToRemove, 'Remove'));\n }\n\n removeAnnotationOverlay(removedOverlay: Overlays.Overlays.TimelineOverlay): void {\n const annotationForRemovedOverlay = this.getAnnotationByOverlay(removedOverlay);\n if (!annotationForRemovedOverlay) {\n console.warn('Annotation for deleted Overlay does not exist');\n return;\n }\n this.#overlayForAnnotation.delete(annotationForRemovedOverlay);\n this.dispatchEvent(new AnnotationModifiedEvent(removedOverlay, 'Remove'));\n }\n\n updateAnnotation(updatedAnnotation: Trace.Types.File.Annotation): void {\n const overlay = this.#overlayForAnnotation.get(updatedAnnotation);\n\n if (overlay && Overlays.Overlays.isTimeRangeLabel(overlay) &&\n Trace.Types.File.isTimeRangeAnnotation(updatedAnnotation)) {\n overlay.label = updatedAnnotation.label;\n overlay.bounds = updatedAnnotation.bounds;\n this.dispatchEvent(new AnnotationModifiedEvent(overlay, 'UpdateTimeRange'));\n\n } else if (\n overlay && Overlays.Overlays.isEntriesLink(overlay) &&\n Trace.Types.File.isEntriesLinkAnnotation(updatedAnnotation)) {\n overlay.entryFrom = updatedAnnotation.entryFrom;\n overlay.entryTo = updatedAnnotation.entryTo;\n this.dispatchEvent(new AnnotationModifiedEvent(overlay, 'UpdateLinkToEntry'));\n\n } else {\n console.error('Annotation could not be updated');\n }\n }\n\n updateAnnotationOverlay(updatedOverlay: Overlays.Overlays.TimelineOverlay): void {\n const annotationForUpdatedOverlay = this.getAnnotationByOverlay(updatedOverlay);\n if (!annotationForUpdatedOverlay) {\n console.warn('Annotation for updated Overlay does not exist');\n return;\n }\n\n if ((updatedOverlay.type === 'ENTRY_LABEL' && annotationForUpdatedOverlay.type === 'ENTRY_LABEL') ||\n (updatedOverlay.type === 'TIME_RANGE' && annotationForUpdatedOverlay.type === 'TIME_RANGE')) {\n this.#annotationsHiddenSetting.set(false);\n annotationForUpdatedOverlay.label = updatedOverlay.label;\n }\n this.dispatchEvent(new AnnotationModifiedEvent(updatedOverlay, 'UpdateLabel'));\n }\n\n getAnnotationByOverlay(overlay: Overlays.Overlays.TimelineOverlay): Trace.Types.File.Annotation|null {\n for (const [annotation, currOverlay] of this.#overlayForAnnotation.entries()) {\n if (currOverlay === overlay) {\n return annotation;\n }\n }\n return null;\n }\n\n getAnnotations(): Trace.Types.File.Annotation[] {\n return [...this.#overlayForAnnotation.keys()];\n }\n\n getOverlays(): Overlays.Overlays.TimelineOverlay[] {\n return [...this.#overlayForAnnotation.values()];\n }\n\n /**\n * Builds all modifications into a serializable object written into\n * the 'modifications' trace file metadata field.\n */\n toJSON(): Trace.Types.File.Modifications {\n const hiddenEntries = this.#entriesFilter.invisibleEntries()\n .map(entry => this.#eventsSerializer.keyForEvent(entry))\n .filter(entry => entry !== null) as Trace.Types.File.SerializableKey[];\n const expandableEntries = this.#entriesFilter.expandableEntries()\n .map(entry => this.#eventsSerializer.keyForEvent(entry))\n .filter(entry => entry !== null) as Trace.Types.File.SerializableKey[];\n this.#modifications = {\n entriesModifications: {\n hiddenEntries,\n expandableEntries,\n },\n initialBreadcrumb: this.#timelineBreadcrumbs.initialBreadcrumb,\n annotations: this.#annotationsJSON(),\n };\n return this.#modifications;\n }\n\n #annotationsJSON(): Trace.Types.File.SerializedAnnotations {\n const annotations = this.getAnnotations();\n const entryLabelsSerialized: Trace.Types.File.EntryLabelAnnotationSerialized[] = [];\n const labelledTimeRangesSerialized: Trace.Types.File.TimeRangeAnnotationSerialized[] = [];\n const linksBetweenEntriesSerialized: Trace.Types.File.EntriesLinkAnnotationSerialized[] = [];\n\n for (let i = 0; i < annotations.length; i++) {\n const currAnnotation = annotations[i];\n if (Trace.Types.File.isEntryLabelAnnotation(currAnnotation)) {\n const serializedEvent = this.#eventsSerializer.keyForEvent(currAnnotation.entry);\n if (serializedEvent) {\n entryLabelsSerialized.push({\n entry: serializedEvent,\n label: currAnnotation.label,\n });\n }\n } else if (Trace.Types.File.isTimeRangeAnnotation(currAnnotation)) {\n labelledTimeRangesSerialized.push({\n bounds: currAnnotation.bounds,\n label: currAnnotation.label,\n });\n } else if (Trace.Types.File.isEntriesLinkAnnotation(currAnnotation)) {\n // Only save the links between entries that are fully created and have the entry that it is pointing to set\n if (currAnnotation.entryTo) {\n const serializedFromEvent = this.#eventsSerializer.keyForEvent(currAnnotation.entryFrom);\n const serializedToEvent = this.#eventsSerializer.keyForEvent(currAnnotation.entryTo);\n if (serializedFromEvent && serializedToEvent) {\n linksBetweenEntriesSerialized.push({\n entryFrom: serializedFromEvent,\n entryTo: serializedToEvent,\n });\n }\n }\n }\n }\n\n return {\n entryLabels: entryLabelsSerialized,\n labelledTimeRanges: labelledTimeRangesSerialized,\n linksBetweenEntries: linksBetweenEntriesSerialized,\n };\n }\n\n applyModificationsIfPresent(): void {\n if (!this.#modifications || !this.#modifications.annotations) {\n return;\n }\n\n const hiddenEntries = this.#modifications.entriesModifications.hiddenEntries;\n const expandableEntries = this.#modifications.entriesModifications.expandableEntries;\n\n this.#timelineBreadcrumbs.setInitialBreadcrumbFromLoadedModifications(this.#modifications.initialBreadcrumb);\n this.#applyEntriesFilterModifications(hiddenEntries, expandableEntries);\n this.#applyStoredAnnotations(this.#modifications.annotations);\n }\n\n #applyStoredAnnotations(annotations: Trace.Types.File.SerializedAnnotations): void {\n try {\n // Assign annotations to an empty array if they don't exist to not\n // break the traces that were saved before those annotations were implemented\n const entryLabels = annotations.entryLabels ?? [];\n entryLabels.forEach(entryLabel => {\n this.createAnnotation(\n {\n type: 'ENTRY_LABEL',\n entry: this.#eventsSerializer.eventForKey(entryLabel.entry, this.#parsedTrace),\n label: entryLabel.label,\n },\n true);\n });\n\n const timeRanges = annotations.labelledTimeRanges ?? [];\n timeRanges.forEach(timeRange => {\n this.createAnnotation(\n {\n type: 'TIME_RANGE',\n bounds: timeRange.bounds,\n label: timeRange.label,\n },\n true);\n });\n\n const linksBetweenEntries = annotations.linksBetweenEntries ?? [];\n linksBetweenEntries.forEach(linkBetweenEntries => {\n this.createAnnotation(\n {\n type: 'ENTRIES_LINK',\n entryFrom: this.#eventsSerializer.eventForKey(linkBetweenEntries.entryFrom, this.#parsedTrace),\n entryTo: this.#eventsSerializer.eventForKey(linkBetweenEntries.entryTo, this.#parsedTrace),\n },\n true);\n });\n } catch (err) {\n // This function is wrapped in a try/catch just in case we get any incoming\n // trace files with broken event keys. Shouldn't happen of course, but if\n // it does, we can discard all the data and then continue loading the\n // trace, rather than have the panel entirely break. This also prevents any\n // issue where we accidentally break the event serializer and break people\n // loading traces; let's at least make sure they can load the panel, even\n // if their annotations are gone.\n console.warn('Failed to apply stored annotations', err);\n }\n }\n\n #applyEntriesFilterModifications(\n hiddenEntriesKeys: Trace.Types.File.SerializableKey[],\n expandableEntriesKeys: Trace.Types.File.SerializableKey[]): void {\n try {\n const hiddenEntries = hiddenEntriesKeys.map(key => this.#eventsSerializer.eventForKey(key, this.#parsedTrace));\n const expandableEntries =\n expandableEntriesKeys.map(key => this.#eventsSerializer.eventForKey(key, this.#parsedTrace));\n this.#entriesFilter.setHiddenAndExpandableEntries(hiddenEntries, expandableEntries);\n } catch (err) {\n console.warn('Failed to apply entriesFilter modifications', err);\n // If there was some invalid data, let's just back out and clear it\n // entirely. This is better than applying a subset of all the hidden\n // entries, which could cause an odd state in the flamechart.\n this.#entriesFilter.setHiddenAndExpandableEntries([], []);\n }\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/ModificationsManager.test.js b/public/panels/timeline/ModificationsManager.test.js index ff753928a..e8855327c 100644 --- a/public/panels/timeline/ModificationsManager.test.js +++ b/public/panels/timeline/ModificationsManager.test.js @@ -1,7 +1,7 @@ // Copyright 2024 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 * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import { describeWithEnvironment } from '../../testing/EnvironmentHelpers.js'; import { TraceLoader } from '../../testing/TraceLoader.js'; import * as Timeline from './timeline.js'; @@ -56,10 +56,10 @@ describeWithEnvironment('ModificationsManager', () => { ]); }); it('creates annotations and generates correct json for annotations', async function () { - const traceParsedData = (await TraceLoader.traceEngine(null, 'web-dev-with-commit.json.gz')).traceData; + const parsedTrace = (await TraceLoader.traceEngine(null, 'web-dev-with-commit.json.gz')).parsedTrace; // Get any entres to create a label and a link with. - const entry = traceParsedData.Renderer.allTraceEntries[0]; - const entry2 = traceParsedData.Renderer.allTraceEntries[1]; + const entry = parsedTrace.Renderer.allTraceEntries[0]; + const entry2 = parsedTrace.Renderer.allTraceEntries[1]; const modificationsManager = Timeline.ModificationsManager.ModificationsManager.activeManager(); assert.isOk(modificationsManager); modificationsManager.createAnnotation({ @@ -75,9 +75,9 @@ describeWithEnvironment('ModificationsManager', () => { modificationsManager.createAnnotation({ type: 'TIME_RANGE', bounds: { - min: TraceEngine.Types.Timing.MicroSeconds(0), - max: TraceEngine.Types.Timing.MicroSeconds(10), - range: TraceEngine.Types.Timing.MicroSeconds(10), + min: Trace.Types.Timing.MicroSeconds(0), + max: Trace.Types.Timing.MicroSeconds(10), + range: Trace.Types.Timing.MicroSeconds(10), }, label: 'range label', }); @@ -89,9 +89,9 @@ describeWithEnvironment('ModificationsManager', () => { }], labelledTimeRanges: [{ bounds: { - min: TraceEngine.Types.Timing.MicroSeconds(0), - max: TraceEngine.Types.Timing.MicroSeconds(10), - range: TraceEngine.Types.Timing.MicroSeconds(10), + min: Trace.Types.Timing.MicroSeconds(0), + max: Trace.Types.Timing.MicroSeconds(10), + range: Trace.Types.Timing.MicroSeconds(10), }, label: 'range label', }], @@ -102,10 +102,10 @@ describeWithEnvironment('ModificationsManager', () => { }); }); it('does not add the annotation link between entries into the json saved into metadata if `entryTo` does not exist', async function () { - const traceParsedData = (await TraceLoader.traceEngine(null, 'web-dev-with-commit.json.gz')).traceData; + const parsedTrace = (await TraceLoader.traceEngine(null, 'web-dev-with-commit.json.gz')).parsedTrace; // Get any entry to create links with. - const entry = traceParsedData.Renderer.allTraceEntries[0]; - const entry2 = traceParsedData.Renderer.allTraceEntries[1]; + const entry = parsedTrace.Renderer.allTraceEntries[0]; + const entry2 = parsedTrace.Renderer.allTraceEntries[1]; const modificationsManager = Timeline.ModificationsManager.ModificationsManager.activeManager(); assert.isOk(modificationsManager); modificationsManager.createAnnotation({ diff --git a/public/panels/timeline/ModificationsManager.test.js.map b/public/panels/timeline/ModificationsManager.test.js.map index ce226de96..d595e33f4 100644 --- a/public/panels/timeline/ModificationsManager.test.js.map +++ b/public/panels/timeline/ModificationsManager.test.js.map @@ -1 +1 @@ -{"version":3,"file":"ModificationsManager.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/ModificationsManager.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\n\nimport * as Timeline from './timeline.js';\n\ndescribeWithEnvironment('ModificationsManager', () => {\n it('applies modifications when present in a trace file', async function() {\n await TraceLoader.traceEngine(null, 'web-dev-modifications.json.gz');\n const modificationsManager = Timeline.ModificationsManager.ModificationsManager.activeManager();\n if (!modificationsManager) {\n throw new Error('Modifications manager does not exist.');\n }\n const entriesFilter = modificationsManager.getEntriesFilter();\n assert.strictEqual(entriesFilter.expandableEntries().length, 1);\n assert.strictEqual(entriesFilter.invisibleEntries().length, 108);\n assert.deepEqual(modificationsManager.getTimelineBreadcrumbs().initialBreadcrumb, {\n window: {min: 1020034823047, max: 1020036087961, range: 1264914},\n child: {window: {min: 1020034823047, max: 1020035228006.5569, range: 404959.5568847656}, child: null},\n } as TraceEngine.Types.File.Breadcrumb);\n // Make sure the saved Label Annotation is applied\n const labelAnnotation = modificationsManager.getAnnotations()[0];\n const label = (labelAnnotation.type === 'ENTRY_LABEL') ? labelAnnotation.label : '';\n assert.deepEqual(labelAnnotation.type, 'ENTRY_LABEL');\n assert.deepEqual(label, 'Initialize App');\n // Make sure the saved Range Annotation is applied\n const timeRangeAnnotation = modificationsManager.getAnnotations()[1];\n const rangeLabel = (timeRangeAnnotation.type === 'TIME_RANGE') ? timeRangeAnnotation.label : '';\n assert.deepEqual(modificationsManager.getAnnotations()[1].type, 'TIME_RANGE');\n assert.deepEqual(rangeLabel, 'Visibility change 1');\n });\n\n it('generates a serializable modifications json ', async function() {\n await TraceLoader.traceEngine(null, 'web-dev-modifications.json.gz');\n const modificationsManager = Timeline.ModificationsManager.ModificationsManager.activeManager();\n if (!modificationsManager) {\n throw new Error('Modifications manager does not exist.');\n }\n const entriesFilter = modificationsManager.getEntriesFilter();\n const modifications = modificationsManager.toJSON();\n assert.strictEqual(entriesFilter.expandableEntries().length, 1);\n assert.strictEqual(modifications.entriesModifications.expandableEntries.length, 1);\n assert.strictEqual(modifications.entriesModifications.hiddenEntries.length, 108);\n assert.deepEqual(modifications.initialBreadcrumb, {\n window: {min: 1020034823047, max: 1020036087961, range: 1264914},\n child: {window: {min: 1020034823047, max: 1020035228006.5569, range: 404959.5568847656}, child: null},\n } as TraceEngine.Types.File.Breadcrumb);\n assert.deepEqual(modifications.annotations.entryLabels, [\n {entry: 'p-73704-775-2151-457', label: 'Initialize App'},\n ]);\n assert.deepEqual(modifications.annotations.labelledTimeRanges, [\n {\n bounds: {min: 1020034870460.4769, max: 1020034880507.9258, range: 10047.448852539062},\n label: 'Visibility change 1',\n },\n ]);\n });\n\n it('creates annotations and generates correct json for annotations', async function() {\n const traceParsedData = (await TraceLoader.traceEngine(null, 'web-dev-with-commit.json.gz')).traceData;\n // Get any entres to create a label and a link with.\n const entry = traceParsedData.Renderer.allTraceEntries[0];\n const entry2 = traceParsedData.Renderer.allTraceEntries[1];\n\n const modificationsManager = Timeline.ModificationsManager.ModificationsManager.activeManager();\n assert.isOk(modificationsManager);\n\n modificationsManager.createAnnotation({\n type: 'ENTRY_LABEL',\n entry,\n label: 'entry label',\n });\n\n modificationsManager.createAnnotation({\n type: 'ENTRIES_LINK',\n entryFrom: entry,\n entryTo: entry2,\n });\n\n modificationsManager.createAnnotation({\n type: 'TIME_RANGE',\n bounds: {\n min: TraceEngine.Types.Timing.MicroSeconds(0),\n max: TraceEngine.Types.Timing.MicroSeconds(10),\n range: TraceEngine.Types.Timing.MicroSeconds(10),\n },\n label: 'range label',\n });\n\n const modifications = modificationsManager.toJSON().annotations;\n assert.deepEqual(modifications, {\n entryLabels: [{\n entry: 'r-38',\n label: 'entry label',\n }],\n labelledTimeRanges: [{\n bounds: {\n min: TraceEngine.Types.Timing.MicroSeconds(0),\n max: TraceEngine.Types.Timing.MicroSeconds(10),\n range: TraceEngine.Types.Timing.MicroSeconds(10),\n },\n label: 'range label',\n }],\n linksBetweenEntries: [{\n entryFrom: 'r-38',\n entryTo: 'r-39',\n }],\n });\n });\n\n it('does not add the annotation link between entries into the json saved into metadata if `entryTo` does not exist',\n async function() {\n const traceParsedData = (await TraceLoader.traceEngine(null, 'web-dev-with-commit.json.gz')).traceData;\n // Get any entry to create links with.\n const entry = traceParsedData.Renderer.allTraceEntries[0];\n const entry2 = traceParsedData.Renderer.allTraceEntries[1];\n\n const modificationsManager = Timeline.ModificationsManager.ModificationsManager.activeManager();\n assert.isOk(modificationsManager);\n\n modificationsManager.createAnnotation({\n type: 'ENTRIES_LINK',\n entryFrom: entry,\n entryTo: entry2,\n });\n\n modificationsManager.createAnnotation({\n type: 'ENTRIES_LINK',\n entryFrom: entry2,\n });\n\n // Make sure only the link with both 'to' and 'from' entries in in the generated JSON\n const modifications = modificationsManager.toJSON().annotations;\n assert.deepEqual(modifications, {\n entryLabels: [],\n labelledTimeRanges: [],\n linksBetweenEntries: [{\n entryFrom: 'r-38',\n entryTo: 'r-39',\n }],\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"ModificationsManager.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/ModificationsManager.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\n\nimport * as Timeline from './timeline.js';\n\ndescribeWithEnvironment('ModificationsManager', () => {\n it('applies modifications when present in a trace file', async function() {\n await TraceLoader.traceEngine(null, 'web-dev-modifications.json.gz');\n const modificationsManager = Timeline.ModificationsManager.ModificationsManager.activeManager();\n if (!modificationsManager) {\n throw new Error('Modifications manager does not exist.');\n }\n const entriesFilter = modificationsManager.getEntriesFilter();\n assert.strictEqual(entriesFilter.expandableEntries().length, 1);\n assert.strictEqual(entriesFilter.invisibleEntries().length, 108);\n assert.deepEqual(modificationsManager.getTimelineBreadcrumbs().initialBreadcrumb, {\n window: {min: 1020034823047, max: 1020036087961, range: 1264914},\n child: {window: {min: 1020034823047, max: 1020035228006.5569, range: 404959.5568847656}, child: null},\n } as Trace.Types.File.Breadcrumb);\n // Make sure the saved Label Annotation is applied\n const labelAnnotation = modificationsManager.getAnnotations()[0];\n const label = (labelAnnotation.type === 'ENTRY_LABEL') ? labelAnnotation.label : '';\n assert.deepEqual(labelAnnotation.type, 'ENTRY_LABEL');\n assert.deepEqual(label, 'Initialize App');\n // Make sure the saved Range Annotation is applied\n const timeRangeAnnotation = modificationsManager.getAnnotations()[1];\n const rangeLabel = (timeRangeAnnotation.type === 'TIME_RANGE') ? timeRangeAnnotation.label : '';\n assert.deepEqual(modificationsManager.getAnnotations()[1].type, 'TIME_RANGE');\n assert.deepEqual(rangeLabel, 'Visibility change 1');\n });\n\n it('generates a serializable modifications json ', async function() {\n await TraceLoader.traceEngine(null, 'web-dev-modifications.json.gz');\n const modificationsManager = Timeline.ModificationsManager.ModificationsManager.activeManager();\n if (!modificationsManager) {\n throw new Error('Modifications manager does not exist.');\n }\n const entriesFilter = modificationsManager.getEntriesFilter();\n const modifications = modificationsManager.toJSON();\n assert.strictEqual(entriesFilter.expandableEntries().length, 1);\n assert.strictEqual(modifications.entriesModifications.expandableEntries.length, 1);\n assert.strictEqual(modifications.entriesModifications.hiddenEntries.length, 108);\n assert.deepEqual(modifications.initialBreadcrumb, {\n window: {min: 1020034823047, max: 1020036087961, range: 1264914},\n child: {window: {min: 1020034823047, max: 1020035228006.5569, range: 404959.5568847656}, child: null},\n } as Trace.Types.File.Breadcrumb);\n assert.deepEqual(modifications.annotations.entryLabels, [\n {entry: 'p-73704-775-2151-457', label: 'Initialize App'},\n ]);\n assert.deepEqual(modifications.annotations.labelledTimeRanges, [\n {\n bounds: {min: 1020034870460.4769, max: 1020034880507.9258, range: 10047.448852539062},\n label: 'Visibility change 1',\n },\n ]);\n });\n\n it('creates annotations and generates correct json for annotations', async function() {\n const parsedTrace = (await TraceLoader.traceEngine(null, 'web-dev-with-commit.json.gz')).parsedTrace;\n // Get any entres to create a label and a link with.\n const entry = parsedTrace.Renderer.allTraceEntries[0];\n const entry2 = parsedTrace.Renderer.allTraceEntries[1];\n\n const modificationsManager = Timeline.ModificationsManager.ModificationsManager.activeManager();\n assert.isOk(modificationsManager);\n\n modificationsManager.createAnnotation({\n type: 'ENTRY_LABEL',\n entry,\n label: 'entry label',\n });\n\n modificationsManager.createAnnotation({\n type: 'ENTRIES_LINK',\n entryFrom: entry,\n entryTo: entry2,\n });\n\n modificationsManager.createAnnotation({\n type: 'TIME_RANGE',\n bounds: {\n min: Trace.Types.Timing.MicroSeconds(0),\n max: Trace.Types.Timing.MicroSeconds(10),\n range: Trace.Types.Timing.MicroSeconds(10),\n },\n label: 'range label',\n });\n\n const modifications = modificationsManager.toJSON().annotations;\n assert.deepEqual(modifications, {\n entryLabels: [{\n entry: 'r-38',\n label: 'entry label',\n }],\n labelledTimeRanges: [{\n bounds: {\n min: Trace.Types.Timing.MicroSeconds(0),\n max: Trace.Types.Timing.MicroSeconds(10),\n range: Trace.Types.Timing.MicroSeconds(10),\n },\n label: 'range label',\n }],\n linksBetweenEntries: [{\n entryFrom: 'r-38',\n entryTo: 'r-39',\n }],\n });\n });\n\n it('does not add the annotation link between entries into the json saved into metadata if `entryTo` does not exist',\n async function() {\n const parsedTrace = (await TraceLoader.traceEngine(null, 'web-dev-with-commit.json.gz')).parsedTrace;\n // Get any entry to create links with.\n const entry = parsedTrace.Renderer.allTraceEntries[0];\n const entry2 = parsedTrace.Renderer.allTraceEntries[1];\n\n const modificationsManager = Timeline.ModificationsManager.ModificationsManager.activeManager();\n assert.isOk(modificationsManager);\n\n modificationsManager.createAnnotation({\n type: 'ENTRIES_LINK',\n entryFrom: entry,\n entryTo: entry2,\n });\n\n modificationsManager.createAnnotation({\n type: 'ENTRIES_LINK',\n entryFrom: entry2,\n });\n\n // Make sure only the link with both 'to' and 'from' entries in in the generated JSON\n const modifications = modificationsManager.toJSON().annotations;\n assert.deepEqual(modifications, {\n entryLabels: [],\n labelledTimeRanges: [],\n linksBetweenEntries: [{\n entryFrom: 'r-38',\n entryTo: 'r-39',\n }],\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/NetworkTrackAppender.d.ts b/public/panels/timeline/NetworkTrackAppender.d.ts index 3c0f94afd..0446f063b 100644 --- a/public/panels/timeline/NetworkTrackAppender.d.ts +++ b/public/panels/timeline/NetworkTrackAppender.d.ts @@ -1,8 +1,8 @@ -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; import { type LastTimestampByLevel } from './AppenderUtils.js'; import { type TrackAppender, type TrackAppenderName } from './CompatibilityTracksAppender.js'; -export type NetworkTrackEvent = TraceEngine.Types.TraceEvents.SyntheticNetworkRequest | TraceEngine.Types.TraceEvents.WebSocketEvent; +export type NetworkTrackEvent = Trace.Types.Events.SyntheticNetworkRequest | Trace.Types.Events.WebSocketEvent; export declare class NetworkTrackAppender implements TrackAppender { #private; readonly appenderName: TrackAppenderName; @@ -27,10 +27,10 @@ export declare class NetworkTrackAppender implements TrackAppender { * invisible events to the last level, and hide them. * @returns the number of levels used by this track */ - relayoutEntriesWithinBounds(events: NetworkTrackEvent[], minTime: TraceEngine.Types.Timing.MilliSeconds, maxTime: TraceEngine.Types.Timing.MilliSeconds): number; - getWebSocketLevel(event: TraceEngine.Types.TraceEvents.WebSocketEvent, lastTimestampByLevel: LastTimestampByLevel): number; + relayoutEntriesWithinBounds(events: NetworkTrackEvent[], minTime: Trace.Types.Timing.MilliSeconds, maxTime: Trace.Types.Timing.MilliSeconds): number; + getWebSocketLevel(event: Trace.Types.Events.WebSocketEvent, lastTimestampByLevel: LastTimestampByLevel): number; /** * Gets the color an event added by this appender should be rendered with. */ - colorForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): string; + colorForEvent(event: Trace.Types.Events.Event): string; } diff --git a/public/panels/timeline/NetworkTrackAppender.js b/public/panels/timeline/NetworkTrackAppender.js index 39f33689e..cd0f8bd4b 100644 --- a/public/panels/timeline/NetworkTrackAppender.js +++ b/public/panels/timeline/NetworkTrackAppender.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as i18n from '../../core/i18n/i18n.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; import * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js'; import { addDecorationToEvent, buildGroupStyle, buildTrackHeader, getEventLevel, } from './AppenderUtils.js'; @@ -103,8 +103,8 @@ export class NetworkTrackAppender { const event = events[i]; this.#appendEventAtLevel(event, trackStartLevel); // Decorate render blocking - if (TraceEngine.Types.TraceEvents.isSyntheticNetworkRequestEvent(event) && - TraceEngine.Helpers.Network.isSyntheticNetworkRequestEventRenderBlocking(event)) { + if (Trace.Types.Events.isSyntheticNetworkRequest(event) && + Trace.Helpers.Network.isSyntheticNetworkRequestEventRenderBlocking(event)) { addDecorationToEvent(this.#flameChartData, i, { type: "WARNING_TRIANGLE" /* PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE */, customStartTime: event.args.data.syntheticData.sendStartTime, @@ -112,7 +112,7 @@ export class NetworkTrackAppender { }); } } - return this.relayoutEntriesWithinBounds(events, TraceEngine.Types.Timing.MilliSeconds(-Infinity), TraceEngine.Types.Timing.MilliSeconds(Infinity)); + return this.relayoutEntriesWithinBounds(events, Trace.Types.Timing.MilliSeconds(-Infinity), Trace.Types.Timing.MilliSeconds(Infinity)); } /** * Adds an event to the flame chart data at a defined level. @@ -123,9 +123,9 @@ export class NetworkTrackAppender { #appendEventAtLevel(event, level) { const index = this.#flameChartData.entryLevels.length; this.#flameChartData.entryLevels[index] = level; - this.#flameChartData.entryStartTimes[index] = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.ts); - const dur = event.dur || TraceEngine.Helpers.Timing.millisecondsToMicroseconds(InstantEventVisibleDurationMs); - this.#flameChartData.entryTotalTimes[index] = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(dur); + this.#flameChartData.entryStartTimes[index] = Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts); + const dur = event.dur || Trace.Helpers.Timing.millisecondsToMicroseconds(InstantEventVisibleDurationMs); + this.#flameChartData.entryTotalTimes[index] = Trace.Helpers.Timing.microSecondsToMilliseconds(dur); return level; } /** @@ -144,8 +144,8 @@ export class NetworkTrackAppender { let maxLevel = 0; for (let i = 0; i < events.length; ++i) { const event = events[i]; - const beginTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.ts); - const dur = event.dur ? TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.dur) : InstantEventVisibleDurationMs; + const beginTime = Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts); + const dur = event.dur ? Trace.Helpers.Timing.microSecondsToMilliseconds(event.dur) : InstantEventVisibleDurationMs; const endTime = beginTime + dur; const isBetweenTimes = beginTime < maxTime && endTime > minTime; // Exclude events outside the the specified timebounds @@ -155,7 +155,7 @@ export class NetworkTrackAppender { } // Layout the entries by assigning levels. let level; - if ('identifier' in event.args.data && TraceEngine.Types.TraceEvents.isWebSocketEvent(event)) { + if ('identifier' in event.args.data && Trace.Types.Events.isWebSocketEvent(event)) { level = this.getWebSocketLevel(event, lastTimestampByLevel); } else { @@ -197,14 +197,14 @@ export class NetworkTrackAppender { * Gets the color an event added by this appender should be rendered with. */ colorForEvent(event) { - if (TraceEngine.Types.TraceEvents.isSyntheticWebSocketConnectionEvent(event)) { + if (Trace.Types.Events.isSyntheticWebSocketConnection(event)) { // the synthetic WebSocket events are not selectable, so we don't need to set the color. return ''; } - if (TraceEngine.Types.TraceEvents.isWebSocketTraceEvent(event)) { + if (Trace.Types.Events.isWebSocketTraceEvent(event)) { return Components.Utils.colorForNetworkCategory(Components.Utils.NetworkCategory.JS); } - if (!TraceEngine.Types.TraceEvents.isSyntheticNetworkRequestEvent(event)) { + if (!Trace.Types.Events.isSyntheticNetworkRequest(event)) { throw new Error(`Unexpected Network Request: The event's type is '${event.name}'`); } return Components.Utils.colorForNetworkRequest(event); diff --git a/public/panels/timeline/NetworkTrackAppender.js.map b/public/panels/timeline/NetworkTrackAppender.js.map index 6f9ef96f2..a51cdad3e 100644 --- a/public/panels/timeline/NetworkTrackAppender.js.map +++ b/public/panels/timeline/NetworkTrackAppender.js.map @@ -1 +1 @@ -{"version":3,"file":"NetworkTrackAppender.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/NetworkTrackAppender.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\n\nimport {\n addDecorationToEvent,\n buildGroupStyle,\n buildTrackHeader,\n getEventLevel,\n type LastTimestampByLevel,\n} from './AppenderUtils.js';\nimport {\n type TrackAppender,\n type TrackAppenderName,\n VisualLoggingTrackName,\n} from './CompatibilityTracksAppender.js';\nimport * as Components from './components/components.js';\nimport {InstantEventVisibleDurationMs} from './TimelineFlameChartDataProvider.js';\n\nconst UIStrings = {\n /**\n *@description Text in Timeline Flame Chart Data Provider of the Performance panel\n */\n network: 'Network',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/NetworkTrackAppender.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport type NetworkTrackEvent =\n TraceEngine.Types.TraceEvents.SyntheticNetworkRequest|TraceEngine.Types.TraceEvents.WebSocketEvent;\n\nexport class NetworkTrackAppender implements TrackAppender {\n readonly appenderName: TrackAppenderName = 'Network';\n\n #flameChartData: PerfUI.FlameChart.FlameChartTimelineData;\n webSocketIdToLevel = new Map();\n #events: NetworkTrackEvent[] = [];\n\n #font: string;\n #group?: PerfUI.FlameChart.Group;\n\n constructor(flameChartData: PerfUI.FlameChart.FlameChartTimelineData, events: NetworkTrackEvent[]) {\n this.#flameChartData = flameChartData;\n this.#events = events;\n this.#font = `${PerfUI.Font.DEFAULT_FONT_SIZE} ${PerfUI.Font.getFontFamilyForCanvas()}`;\n\n ThemeSupport.ThemeSupport.instance().addEventListener(ThemeSupport.ThemeChangeEvent.eventName, () => {\n if (this.#group) {\n // We only need to update the color here, because FlameChart will call `scheduleUpdate()` when theme is changed.\n this.#group.style.color = ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-on-surface');\n this.#group.style.backgroundColor =\n ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-cdt-base-container');\n }\n });\n }\n\n group(): PerfUI.FlameChart.Group|undefined {\n return this.#group;\n }\n\n font(): string {\n return this.#font;\n }\n\n /**\n * Appends into the flame chart data the data corresponding to the\n * Network track.\n * @param trackStartLevel the horizontal level of the flame chart events where\n * the track's events will start being appended.\n * @param expanded wether the track should be rendered expanded.\n * @returns the first available level to append more data after having\n * appended the track's events.\n */\n appendTrackAtLevel(trackStartLevel: number, expanded?: boolean|undefined): number {\n if (this.#events.length === 0) {\n return trackStartLevel;\n }\n this.#appendTrackHeaderAtLevel(trackStartLevel, expanded);\n return this.#appendEventsAtLevel(this.#events, trackStartLevel);\n }\n\n /**\n * Adds into the flame chart data the header corresponding to the\n * Network track. A header is added in the shape of a group in the\n * flame chart data. A group has a predefined style and a reference\n * to the definition of the legacy track (which should be removed\n * in the future).\n * @param currentLevel the flame chart level at which the header is\n * appended.\n * @param expanded wether the track should be rendered expanded.\n */\n #appendTrackHeaderAtLevel(_currentLevel: number, expanded?: boolean): void {\n const style = buildGroupStyle({\n shareHeaderLine: false,\n useFirstLineForOverview: false,\n useDecoratorsForOverview: true,\n });\n const legends: PerfUI.FlameChart.Legend[] = [];\n for (const category of Object.values(Components.Utils.NetworkCategory)) {\n legends.push({\n color: Components.Utils.colorForNetworkCategory(category),\n category,\n });\n }\n this.#group = buildTrackHeader(\n VisualLoggingTrackName.NETWORK, 0, i18nString(UIStrings.network), style, /* selectable= */ true, expanded,\n /* showStackContextMenu= */ false, legends);\n this.#flameChartData.groups.push(this.#group);\n }\n\n /**\n * Adds into the flame chart data a list of trace events.\n * @param events the trace events that will be appended to the flame chart.\n * The events should be taken straight from the trace handlers. The handlers\n * should sort the events by start time, and the parent event is before the\n * child.\n * @param trackStartLevel the flame chart level from which the events will\n * be appended.\n * @returns the next level after the last occupied by the appended these\n * trace events (the first available level to append next track).\n */\n #appendEventsAtLevel(events: NetworkTrackEvent[], trackStartLevel: number): number {\n // Appending everything to the same level isn't \"correct\", but filterTimelineDataBetweenTimes() will handle that\n // before anything is rendered.\n for (let i = 0; i < events.length; ++i) {\n const event = events[i];\n this.#appendEventAtLevel(event, trackStartLevel);\n // Decorate render blocking\n if (TraceEngine.Types.TraceEvents.isSyntheticNetworkRequestEvent(event) &&\n TraceEngine.Helpers.Network.isSyntheticNetworkRequestEventRenderBlocking(event)) {\n addDecorationToEvent(this.#flameChartData, i, {\n type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE,\n customStartTime: event.args.data.syntheticData.sendStartTime,\n customEndTime: event.args.data.syntheticData.finishTime,\n });\n }\n }\n return this.relayoutEntriesWithinBounds(\n events, TraceEngine.Types.Timing.MilliSeconds(-Infinity), TraceEngine.Types.Timing.MilliSeconds(Infinity));\n }\n\n /**\n * Adds an event to the flame chart data at a defined level.\n * @param event the event to be appended,\n * @param level the level to append the event,\n * @returns the index of the event in all events to be rendered in the flamechart.\n */\n #appendEventAtLevel(event: TraceEngine.Types.TraceEvents.TraceEventData, level: number): number {\n const index = this.#flameChartData.entryLevels.length;\n this.#flameChartData.entryLevels[index] = level;\n this.#flameChartData.entryStartTimes[index] = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.ts);\n const dur = event.dur || TraceEngine.Helpers.Timing.millisecondsToMicroseconds(InstantEventVisibleDurationMs);\n this.#flameChartData.entryTotalTimes[index] = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(dur);\n return level;\n }\n\n /**\n * Update the flame chart data.\n * When users zoom in the flamechart, we only want to show them the network\n * requests between minTime and maxTime. This function will append those\n * invisible events to the last level, and hide them.\n * @returns the number of levels used by this track\n */\n relayoutEntriesWithinBounds(\n events: NetworkTrackEvent[], minTime: TraceEngine.Types.Timing.MilliSeconds,\n maxTime: TraceEngine.Types.Timing.MilliSeconds): number {\n if (!this.#flameChartData || events.length === 0) {\n return 0;\n }\n const lastTimestampByLevel: LastTimestampByLevel = [];\n this.webSocketIdToLevel = new Map();\n let maxLevel = 0;\n for (let i = 0; i < events.length; ++i) {\n const event = events[i];\n const beginTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.ts);\n const dur =\n event.dur ? TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.dur) : InstantEventVisibleDurationMs;\n const endTime = beginTime + dur;\n const isBetweenTimes = beginTime < maxTime && endTime > minTime;\n // Exclude events outside the the specified timebounds\n if (!isBetweenTimes) {\n this.#flameChartData.entryLevels[i] = -1;\n continue;\n }\n // Layout the entries by assigning levels.\n let level: number;\n if ('identifier' in event.args.data && TraceEngine.Types.TraceEvents.isWebSocketEvent(event)) {\n level = this.getWebSocketLevel(event, lastTimestampByLevel);\n } else {\n level = getEventLevel(event, lastTimestampByLevel);\n }\n this.#flameChartData.entryLevels[i] = level;\n maxLevel = Math.max(maxLevel, lastTimestampByLevel.length, level);\n }\n for (let i = 0; i < events.length; ++i) {\n // -1 means this event is invisible.\n if (this.#flameChartData.entryLevels[i] === -1) {\n // The maxLevel is an invisible level.\n this.#flameChartData.entryLevels[i] = maxLevel;\n }\n }\n return maxLevel;\n }\n\n getWebSocketLevel(event: TraceEngine.Types.TraceEvents.WebSocketEvent, lastTimestampByLevel: LastTimestampByLevel):\n number {\n const webSocketIdentifier = event.args.data.identifier;\n let level: number;\n if (this.webSocketIdToLevel.has(webSocketIdentifier)) {\n // We're placing an instant event on top of its parent websocket\n level = this.webSocketIdToLevel.get(webSocketIdentifier) || 0;\n } else {\n // We're placing the parent websocket\n level = getEventLevel(event, lastTimestampByLevel);\n this.webSocketIdToLevel.set(webSocketIdentifier, level);\n }\n return level;\n }\n\n /*\n ------------------------------------------------------------------------------------\n The following methods are invoked by the flame chart renderer to query features about\n events on rendering.\n ------------------------------------------------------------------------------------\n */\n\n /**\n * Gets the color an event added by this appender should be rendered with.\n */\n colorForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): string {\n if (TraceEngine.Types.TraceEvents.isSyntheticWebSocketConnectionEvent(event)) {\n // the synthetic WebSocket events are not selectable, so we don't need to set the color.\n return '';\n }\n if (TraceEngine.Types.TraceEvents.isWebSocketTraceEvent(event)) {\n return Components.Utils.colorForNetworkCategory(Components.Utils.NetworkCategory.JS);\n }\n if (!TraceEngine.Types.TraceEvents.isSyntheticNetworkRequestEvent(event)) {\n throw new Error(`Unexpected Network Request: The event's type is '${event.name}'`);\n }\n return Components.Utils.colorForNetworkRequest(event);\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"NetworkTrackAppender.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/NetworkTrackAppender.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\n\nimport {\n addDecorationToEvent,\n buildGroupStyle,\n buildTrackHeader,\n getEventLevel,\n type LastTimestampByLevel,\n} from './AppenderUtils.js';\nimport {\n type TrackAppender,\n type TrackAppenderName,\n VisualLoggingTrackName,\n} from './CompatibilityTracksAppender.js';\nimport * as Components from './components/components.js';\nimport {InstantEventVisibleDurationMs} from './TimelineFlameChartDataProvider.js';\n\nconst UIStrings = {\n /**\n *@description Text in Timeline Flame Chart Data Provider of the Performance panel\n */\n network: 'Network',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/NetworkTrackAppender.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport type NetworkTrackEvent = Trace.Types.Events.SyntheticNetworkRequest|Trace.Types.Events.WebSocketEvent;\n\nexport class NetworkTrackAppender implements TrackAppender {\n readonly appenderName: TrackAppenderName = 'Network';\n\n #flameChartData: PerfUI.FlameChart.FlameChartTimelineData;\n webSocketIdToLevel = new Map();\n #events: NetworkTrackEvent[] = [];\n\n #font: string;\n #group?: PerfUI.FlameChart.Group;\n\n constructor(flameChartData: PerfUI.FlameChart.FlameChartTimelineData, events: NetworkTrackEvent[]) {\n this.#flameChartData = flameChartData;\n this.#events = events;\n this.#font = `${PerfUI.Font.DEFAULT_FONT_SIZE} ${PerfUI.Font.getFontFamilyForCanvas()}`;\n\n ThemeSupport.ThemeSupport.instance().addEventListener(ThemeSupport.ThemeChangeEvent.eventName, () => {\n if (this.#group) {\n // We only need to update the color here, because FlameChart will call `scheduleUpdate()` when theme is changed.\n this.#group.style.color = ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-on-surface');\n this.#group.style.backgroundColor =\n ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-cdt-base-container');\n }\n });\n }\n\n group(): PerfUI.FlameChart.Group|undefined {\n return this.#group;\n }\n\n font(): string {\n return this.#font;\n }\n\n /**\n * Appends into the flame chart data the data corresponding to the\n * Network track.\n * @param trackStartLevel the horizontal level of the flame chart events where\n * the track's events will start being appended.\n * @param expanded wether the track should be rendered expanded.\n * @returns the first available level to append more data after having\n * appended the track's events.\n */\n appendTrackAtLevel(trackStartLevel: number, expanded?: boolean|undefined): number {\n if (this.#events.length === 0) {\n return trackStartLevel;\n }\n this.#appendTrackHeaderAtLevel(trackStartLevel, expanded);\n return this.#appendEventsAtLevel(this.#events, trackStartLevel);\n }\n\n /**\n * Adds into the flame chart data the header corresponding to the\n * Network track. A header is added in the shape of a group in the\n * flame chart data. A group has a predefined style and a reference\n * to the definition of the legacy track (which should be removed\n * in the future).\n * @param currentLevel the flame chart level at which the header is\n * appended.\n * @param expanded wether the track should be rendered expanded.\n */\n #appendTrackHeaderAtLevel(_currentLevel: number, expanded?: boolean): void {\n const style = buildGroupStyle({\n shareHeaderLine: false,\n useFirstLineForOverview: false,\n useDecoratorsForOverview: true,\n });\n const legends: PerfUI.FlameChart.Legend[] = [];\n for (const category of Object.values(Components.Utils.NetworkCategory)) {\n legends.push({\n color: Components.Utils.colorForNetworkCategory(category),\n category,\n });\n }\n this.#group = buildTrackHeader(\n VisualLoggingTrackName.NETWORK, 0, i18nString(UIStrings.network), style, /* selectable= */ true, expanded,\n /* showStackContextMenu= */ false, legends);\n this.#flameChartData.groups.push(this.#group);\n }\n\n /**\n * Adds into the flame chart data a list of trace events.\n * @param events the trace events that will be appended to the flame chart.\n * The events should be taken straight from the trace handlers. The handlers\n * should sort the events by start time, and the parent event is before the\n * child.\n * @param trackStartLevel the flame chart level from which the events will\n * be appended.\n * @returns the next level after the last occupied by the appended these\n * trace events (the first available level to append next track).\n */\n #appendEventsAtLevel(events: NetworkTrackEvent[], trackStartLevel: number): number {\n // Appending everything to the same level isn't \"correct\", but filterTimelineDataBetweenTimes() will handle that\n // before anything is rendered.\n for (let i = 0; i < events.length; ++i) {\n const event = events[i];\n this.#appendEventAtLevel(event, trackStartLevel);\n // Decorate render blocking\n if (Trace.Types.Events.isSyntheticNetworkRequest(event) &&\n Trace.Helpers.Network.isSyntheticNetworkRequestEventRenderBlocking(event)) {\n addDecorationToEvent(this.#flameChartData, i, {\n type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE,\n customStartTime: event.args.data.syntheticData.sendStartTime,\n customEndTime: event.args.data.syntheticData.finishTime,\n });\n }\n }\n return this.relayoutEntriesWithinBounds(\n events, Trace.Types.Timing.MilliSeconds(-Infinity), Trace.Types.Timing.MilliSeconds(Infinity));\n }\n\n /**\n * Adds an event to the flame chart data at a defined level.\n * @param event the event to be appended,\n * @param level the level to append the event,\n * @returns the index of the event in all events to be rendered in the flamechart.\n */\n #appendEventAtLevel(event: Trace.Types.Events.Event, level: number): number {\n const index = this.#flameChartData.entryLevels.length;\n this.#flameChartData.entryLevels[index] = level;\n this.#flameChartData.entryStartTimes[index] = Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts);\n const dur = event.dur || Trace.Helpers.Timing.millisecondsToMicroseconds(InstantEventVisibleDurationMs);\n this.#flameChartData.entryTotalTimes[index] = Trace.Helpers.Timing.microSecondsToMilliseconds(dur);\n return level;\n }\n\n /**\n * Update the flame chart data.\n * When users zoom in the flamechart, we only want to show them the network\n * requests between minTime and maxTime. This function will append those\n * invisible events to the last level, and hide them.\n * @returns the number of levels used by this track\n */\n relayoutEntriesWithinBounds(\n events: NetworkTrackEvent[], minTime: Trace.Types.Timing.MilliSeconds,\n maxTime: Trace.Types.Timing.MilliSeconds): number {\n if (!this.#flameChartData || events.length === 0) {\n return 0;\n }\n const lastTimestampByLevel: LastTimestampByLevel = [];\n this.webSocketIdToLevel = new Map();\n let maxLevel = 0;\n for (let i = 0; i < events.length; ++i) {\n const event = events[i];\n const beginTime = Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts);\n const dur =\n event.dur ? Trace.Helpers.Timing.microSecondsToMilliseconds(event.dur) : InstantEventVisibleDurationMs;\n const endTime = beginTime + dur;\n const isBetweenTimes = beginTime < maxTime && endTime > minTime;\n // Exclude events outside the the specified timebounds\n if (!isBetweenTimes) {\n this.#flameChartData.entryLevels[i] = -1;\n continue;\n }\n // Layout the entries by assigning levels.\n let level: number;\n if ('identifier' in event.args.data && Trace.Types.Events.isWebSocketEvent(event)) {\n level = this.getWebSocketLevel(event, lastTimestampByLevel);\n } else {\n level = getEventLevel(event, lastTimestampByLevel);\n }\n this.#flameChartData.entryLevels[i] = level;\n maxLevel = Math.max(maxLevel, lastTimestampByLevel.length, level);\n }\n for (let i = 0; i < events.length; ++i) {\n // -1 means this event is invisible.\n if (this.#flameChartData.entryLevels[i] === -1) {\n // The maxLevel is an invisible level.\n this.#flameChartData.entryLevels[i] = maxLevel;\n }\n }\n return maxLevel;\n }\n\n getWebSocketLevel(event: Trace.Types.Events.WebSocketEvent, lastTimestampByLevel: LastTimestampByLevel): number {\n const webSocketIdentifier = event.args.data.identifier;\n let level: number;\n if (this.webSocketIdToLevel.has(webSocketIdentifier)) {\n // We're placing an instant event on top of its parent websocket\n level = this.webSocketIdToLevel.get(webSocketIdentifier) || 0;\n } else {\n // We're placing the parent websocket\n level = getEventLevel(event, lastTimestampByLevel);\n this.webSocketIdToLevel.set(webSocketIdentifier, level);\n }\n return level;\n }\n\n /*\n ------------------------------------------------------------------------------------\n The following methods are invoked by the flame chart renderer to query features about\n events on rendering.\n ------------------------------------------------------------------------------------\n */\n\n /**\n * Gets the color an event added by this appender should be rendered with.\n */\n colorForEvent(event: Trace.Types.Events.Event): string {\n if (Trace.Types.Events.isSyntheticWebSocketConnection(event)) {\n // the synthetic WebSocket events are not selectable, so we don't need to set the color.\n return '';\n }\n if (Trace.Types.Events.isWebSocketTraceEvent(event)) {\n return Components.Utils.colorForNetworkCategory(Components.Utils.NetworkCategory.JS);\n }\n if (!Trace.Types.Events.isSyntheticNetworkRequest(event)) {\n throw new Error(`Unexpected Network Request: The event's type is '${event.name}'`);\n }\n return Components.Utils.colorForNetworkRequest(event);\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/SaveFileFormatter.d.ts b/public/panels/timeline/SaveFileFormatter.d.ts index 5fe4ca06f..8ad8cc15c 100644 --- a/public/panels/timeline/SaveFileFormatter.d.ts +++ b/public/panels/timeline/SaveFileFormatter.d.ts @@ -1,15 +1,15 @@ import type * as Protocol from '../../generated/protocol.js'; -import type * as TraceEngine from '../../models/trace/trace.js'; +import type * as Trace from '../../models/trace/trace.js'; /** * Generates a JSON representation of an array of objects with the objects * printed one per line for improved readability (but not *too* verbose). */ -export declare function arrayOfObjectsJsonGenerator(arrayOfObjects: readonly TraceEngine.Types.TraceEvents.TraceEventData[]): IterableIterator; +export declare function arrayOfObjectsJsonGenerator(arrayOfObjects: readonly Trace.Types.Events.Event[]): IterableIterator; /** - * Generates a JSON representation of traceData line-by-line for a nicer printed + * Generates a JSON representation of the TraceObject file line-by-line for a nicer printed * version with one trace event per line. */ -export declare function traceJsonGenerator(traceEvents: readonly TraceEngine.Types.TraceEvents.TraceEventData[], metadata: Readonly | null): IterableIterator; +export declare function traceJsonGenerator(traceEvents: readonly Trace.Types.Events.Event[], metadata: Readonly | null): IterableIterator; /** * Generates a JSON representation of CPU profile. */ diff --git a/public/panels/timeline/SaveFileFormatter.js b/public/panels/timeline/SaveFileFormatter.js index 254f86191..6266ebdfc 100644 --- a/public/panels/timeline/SaveFileFormatter.js +++ b/public/panels/timeline/SaveFileFormatter.js @@ -30,7 +30,7 @@ export function* arrayOfObjectsJsonGenerator(arrayOfObjects) { yield '\n]'; } /** - * Generates a JSON representation of traceData line-by-line for a nicer printed + * Generates a JSON representation of the TraceObject file line-by-line for a nicer printed * version with one trace event per line. */ export function* traceJsonGenerator(traceEvents, metadata) { diff --git a/public/panels/timeline/SaveFileFormatter.js.map b/public/panels/timeline/SaveFileFormatter.js.map index 546a95c9f..5d4df00f8 100644 --- a/public/panels/timeline/SaveFileFormatter.js.map +++ b/public/panels/timeline/SaveFileFormatter.js.map @@ -1 +1 @@ -{"version":3,"file":"SaveFileFormatter.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/SaveFileFormatter.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAI7B;;;GAGG;AACH,MAAM,SAAS,CAAC,CACZ,2BAA2B,CAAC,cAAuE;IAErG,MAAM,mBAAmB,GAAG,MAAM,CAAC;IAEnC,yEAAyE;IACzE,MAAM,KAAK,CAAC;IACZ,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,MAAM,aAAa,GAAG,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxD,sDAAsD;QACtD,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;QAC7C,MAAM,KAAK,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;QAEvC,IAAI,cAAc,GAAG,mBAAmB,CAAC;QACzC,IAAI,SAAS,GAAG,EAAE,CAAC;QACnB,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;YACjC,SAAS,IAAI,QAAQ,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5C,cAAc,EAAE,CAAC;YACjB,IAAI,cAAc,KAAK,CAAC,EAAE,CAAC;gBACzB,MAAM,SAAS,CAAC;gBAChB,cAAc,GAAG,mBAAmB,CAAC;gBACrC,SAAS,GAAG,EAAE,CAAC;YACjB,CAAC;QACH,CAAC;QACD,MAAM,SAAS,CAAC;IAClB,CAAC;IACD,MAAM,KAAK,CAAC;AACd,CAAC;AACD;;;GAGG;AACH,MAAM,SAAS,CAAC,CACZ,kBAAkB,CACd,WAAoE,EACpE,QAAwD;IAE9D,MAAM,gBAAgB,IAAI,CAAC,SAAS,CAAC,QAAQ,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;IAChE,MAAM,oBAAoB,CAAC;IAC3B,KAAK,CAAC,CAAC,2BAA2B,CAAC,WAAW,CAAC,CAAC;IAChD,MAAM,KAAK,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,UAAqC;IAC3E,OAAO,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;AACpC,CAAC","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Protocol from '../../generated/protocol.js';\nimport type * as TraceEngine from '../../models/trace/trace.js';\n/**\n * Generates a JSON representation of an array of objects with the objects\n * printed one per line for improved readability (but not *too* verbose).\n */\nexport function*\n arrayOfObjectsJsonGenerator(arrayOfObjects: readonly TraceEngine.Types.TraceEvents.TraceEventData[]):\n IterableIterator {\n const ITEMS_PER_ITERATION = 10_000;\n\n // Stringify and emit items separately to avoid a giant string in memory.\n yield '[\\n';\n if (arrayOfObjects.length > 0) {\n const itemsIterator = arrayOfObjects[Symbol.iterator]();\n // Emit first item manually to avoid a trailing comma.\n const firstItem = itemsIterator.next().value;\n yield ` ${JSON.stringify(firstItem)}`;\n\n let itemsRemaining = ITEMS_PER_ITERATION;\n let itemsJSON = '';\n for (const item of itemsIterator) {\n itemsJSON += `,\\n ${JSON.stringify(item)}`;\n itemsRemaining--;\n if (itemsRemaining === 0) {\n yield itemsJSON;\n itemsRemaining = ITEMS_PER_ITERATION;\n itemsJSON = '';\n }\n }\n yield itemsJSON;\n }\n yield '\\n]';\n}\n/**\n * Generates a JSON representation of traceData line-by-line for a nicer printed\n * version with one trace event per line.\n */\nexport function*\n traceJsonGenerator(\n traceEvents: readonly TraceEngine.Types.TraceEvents.TraceEventData[],\n metadata: Readonly|null,\n ): IterableIterator {\n yield `{\"metadata\": ${JSON.stringify(metadata || {}, null, 2)}`;\n yield ',\\n\"traceEvents\": ';\n yield* arrayOfObjectsJsonGenerator(traceEvents);\n yield '}\\n';\n}\n\n/**\n * Generates a JSON representation of CPU profile.\n */\nexport function cpuprofileJsonGenerator(cpuprofile: Protocol.Profiler.Profile): string {\n return JSON.stringify(cpuprofile);\n}\n"]} \ No newline at end of file +{"version":3,"file":"SaveFileFormatter.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/SaveFileFormatter.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAI7B;;;GAGG;AACH,MAAM,SAAS,CAAC,CACZ,2BAA2B,CAAC,cAAmD;IACjF,MAAM,mBAAmB,GAAG,MAAM,CAAC;IAEnC,yEAAyE;IACzE,MAAM,KAAK,CAAC;IACZ,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,MAAM,aAAa,GAAG,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxD,sDAAsD;QACtD,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;QAC7C,MAAM,KAAK,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC;QAEvC,IAAI,cAAc,GAAG,mBAAmB,CAAC;QACzC,IAAI,SAAS,GAAG,EAAE,CAAC;QACnB,KAAK,MAAM,IAAI,IAAI,aAAa,EAAE,CAAC;YACjC,SAAS,IAAI,QAAQ,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5C,cAAc,EAAE,CAAC;YACjB,IAAI,cAAc,KAAK,CAAC,EAAE,CAAC;gBACzB,MAAM,SAAS,CAAC;gBAChB,cAAc,GAAG,mBAAmB,CAAC;gBACrC,SAAS,GAAG,EAAE,CAAC;YACjB,CAAC;QACH,CAAC;QACD,MAAM,SAAS,CAAC;IAClB,CAAC;IACD,MAAM,KAAK,CAAC;AACd,CAAC;AACD;;;GAGG;AACH,MAAM,SAAS,CAAC,CACZ,kBAAkB,CACd,WAAgD,EAChD,QAAkD;IAExD,MAAM,gBAAgB,IAAI,CAAC,SAAS,CAAC,QAAQ,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;IAChE,MAAM,oBAAoB,CAAC;IAC3B,KAAK,CAAC,CAAC,2BAA2B,CAAC,WAAW,CAAC,CAAC;IAChD,MAAM,KAAK,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,UAAqC;IAC3E,OAAO,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;AACpC,CAAC","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Protocol from '../../generated/protocol.js';\nimport type * as Trace from '../../models/trace/trace.js';\n/**\n * Generates a JSON representation of an array of objects with the objects\n * printed one per line for improved readability (but not *too* verbose).\n */\nexport function*\n arrayOfObjectsJsonGenerator(arrayOfObjects: readonly Trace.Types.Events.Event[]): IterableIterator {\n const ITEMS_PER_ITERATION = 10_000;\n\n // Stringify and emit items separately to avoid a giant string in memory.\n yield '[\\n';\n if (arrayOfObjects.length > 0) {\n const itemsIterator = arrayOfObjects[Symbol.iterator]();\n // Emit first item manually to avoid a trailing comma.\n const firstItem = itemsIterator.next().value;\n yield ` ${JSON.stringify(firstItem)}`;\n\n let itemsRemaining = ITEMS_PER_ITERATION;\n let itemsJSON = '';\n for (const item of itemsIterator) {\n itemsJSON += `,\\n ${JSON.stringify(item)}`;\n itemsRemaining--;\n if (itemsRemaining === 0) {\n yield itemsJSON;\n itemsRemaining = ITEMS_PER_ITERATION;\n itemsJSON = '';\n }\n }\n yield itemsJSON;\n }\n yield '\\n]';\n}\n/**\n * Generates a JSON representation of the TraceObject file line-by-line for a nicer printed\n * version with one trace event per line.\n */\nexport function*\n traceJsonGenerator(\n traceEvents: readonly Trace.Types.Events.Event[],\n metadata: Readonly|null,\n ): IterableIterator {\n yield `{\"metadata\": ${JSON.stringify(metadata || {}, null, 2)}`;\n yield ',\\n\"traceEvents\": ';\n yield* arrayOfObjectsJsonGenerator(traceEvents);\n yield '}\\n';\n}\n\n/**\n * Generates a JSON representation of CPU profile.\n */\nexport function cpuprofileJsonGenerator(cpuprofile: Protocol.Profiler.Profile): string {\n return JSON.stringify(cpuprofile);\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/SaveFileFormatter.test.js.map b/public/panels/timeline/SaveFileFormatter.test.js.map index 68c2b1102..a1710e109 100644 --- a/public/panels/timeline/SaveFileFormatter.test.js.map +++ b/public/panels/timeline/SaveFileFormatter.test.js.map @@ -1 +1 @@ -{"version":3,"file":"SaveFileFormatter.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/SaveFileFormatter.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAG7B,OAAO,EAAC,iBAAiB,EAAC,MAAM,+BAA+B,CAAC;AAEhE,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAE1C,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,SAAS,eAAe,CAAC,KAAa;QACpC,IAAI,CAAC;YACH,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IACD,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;QAC3C,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;YAClE,MAAM,QAAQ,GAAG,EAAC,GAAG,iBAAiB,EAAE,IAAI,EAAE,WAAW,EAAC,CAAC;YAC3D,MAAM,QAAQ,GAAG,EAAC,GAAG,iBAAiB,EAAE,IAAI,EAAE,WAAW,EAAC,CAAC;YAE3D,MAAM,SAAS,GACX,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,2BAA2B,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACtG,eAAe,CAAC,SAAS,CAAC,CAAC;YAC3B,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE;;;EAGlC,CAAC,CAAC;QACA,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAClC,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;YAC3E,MAAM,QAAQ,GAAG,EAAC,GAAG,iBAAiB,EAAE,IAAI,EAAE,WAAW,EAAC,CAAC;YAC3D,MAAM,QAAQ,GAAG,EAAC,GAAG,iBAAiB,EAAE,IAAI,EAAE,WAAW,EAAC,CAAC;YAC3D,MAAM,MAAM,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YACpC,MAAM,QAAQ,GAAoC;gBAChD,MAAM,EAAE,UAAU;gBAClB,SAAS,EAAE,MAAM;gBACjB,iBAAiB,EAAE,GAAG;gBACtB,aAAa,EAAE,CAAC;gBAChB,mBAAmB,EAAE,CAAC;gBACtB,oBAAoB,EAAE,CAAC;aACxB,CAAC;YACF,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACvG,eAAe,CAAC,SAAS,CAAC,CAAC;YAC3B,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE;;;;;;;;;;;KAW/B,CAAC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;YACjE,MAAM,QAAQ,GAAG,EAAC,GAAG,iBAAiB,EAAE,IAAI,EAAE,WAAW,EAAC,CAAC;YAC3D,MAAM,QAAQ,GAAG,EAAC,GAAG,iBAAiB,EAAE,IAAI,EAAE,WAAW,EAAC,CAAC;YAC3D,MAAM,MAAM,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YACpC,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACnG,eAAe,CAAC,SAAS,CAAC,CAAC;YAC3B,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE;;;;KAI/B,CAAC,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as TraceEngine from '../../models/trace/trace.js';\nimport {defaultTraceEvent} from '../../testing/TraceHelpers.js';\n\nimport * as Timeline from './timeline.js';\n\ndescribe('SaveFileFormatter', () => {\n function assertValidJSON(input: string) {\n try {\n JSON.parse(input);\n } catch {\n assert.fail('Parsing input as JSON failed');\n }\n }\n describe('arrayOfObjectsJsonGenerator', () => {\n it('generates JSON where each event is on its own line', async () => {\n const eventOne = {...defaultTraceEvent, name: 'event_one'};\n const eventTwo = {...defaultTraceEvent, name: 'event_two'};\n\n const formatted =\n Array.from(Timeline.SaveFileFormatter.arrayOfObjectsJsonGenerator([eventOne, eventTwo])).join('');\n assertValidJSON(formatted);\n assert.strictEqual(formatted, `[\n {\"name\":\"event_one\",\"tid\":0,\"pid\":0,\"ts\":0,\"cat\":\"test\",\"ph\":\"M\"},\n {\"name\":\"event_two\",\"tid\":0,\"pid\":0,\"ts\":0,\"cat\":\"test\",\"ph\":\"M\"}\n]`);\n });\n });\n\n describe('traceJsonGenerator', () => {\n it('contains top level keys for the events and for the metadata', async () => {\n const eventOne = {...defaultTraceEvent, name: 'event_one'};\n const eventTwo = {...defaultTraceEvent, name: 'event_two'};\n const events = [eventOne, eventTwo];\n const metadata: TraceEngine.Types.File.MetaData = {\n source: 'DevTools',\n startTime: '1234',\n networkThrottling: '4',\n cpuThrottling: 1,\n hardwareConcurrency: 1,\n enhancedTraceVersion: 1,\n };\n const formatted = Array.from(Timeline.SaveFileFormatter.traceJsonGenerator(events, metadata)).join('');\n assertValidJSON(formatted);\n assert.strictEqual(formatted, `{\"metadata\": {\n \"source\": \"DevTools\",\n \"startTime\": \"1234\",\n \"networkThrottling\": \"4\",\n \"cpuThrottling\": 1,\n \"hardwareConcurrency\": 1,\n \"enhancedTraceVersion\": 1\n},\n\"traceEvents\": [\n {\"name\":\"event_one\",\"tid\":0,\"pid\":0,\"ts\":0,\"cat\":\"test\",\"ph\":\"M\"},\n {\"name\":\"event_two\",\"tid\":0,\"pid\":0,\"ts\":0,\"cat\":\"test\",\"ph\":\"M\"}\n]}\\n`);\n });\n\n it('will emit {} for the metadata if none is provided', async () => {\n const eventOne = {...defaultTraceEvent, name: 'event_one'};\n const eventTwo = {...defaultTraceEvent, name: 'event_two'};\n const events = [eventOne, eventTwo];\n const formatted = Array.from(Timeline.SaveFileFormatter.traceJsonGenerator(events, null)).join('');\n assertValidJSON(formatted);\n assert.strictEqual(formatted, `{\"metadata\": {},\n\"traceEvents\": [\n {\"name\":\"event_one\",\"tid\":0,\"pid\":0,\"ts\":0,\"cat\":\"test\",\"ph\":\"M\"},\n {\"name\":\"event_two\",\"tid\":0,\"pid\":0,\"ts\":0,\"cat\":\"test\",\"ph\":\"M\"}\n]}\\n`);\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"SaveFileFormatter.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/SaveFileFormatter.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAG7B,OAAO,EAAC,iBAAiB,EAAC,MAAM,+BAA+B,CAAC;AAEhE,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAE1C,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,SAAS,eAAe,CAAC,KAAa;QACpC,IAAI,CAAC;YACH,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IACD,QAAQ,CAAC,6BAA6B,EAAE,GAAG,EAAE;QAC3C,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;YAClE,MAAM,QAAQ,GAAG,EAAC,GAAG,iBAAiB,EAAE,IAAI,EAAE,WAAW,EAAC,CAAC;YAC3D,MAAM,QAAQ,GAAG,EAAC,GAAG,iBAAiB,EAAE,IAAI,EAAE,WAAW,EAAC,CAAC;YAE3D,MAAM,SAAS,GACX,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,2BAA2B,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACtG,eAAe,CAAC,SAAS,CAAC,CAAC;YAC3B,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE;;;EAGlC,CAAC,CAAC;QACA,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAClC,EAAE,CAAC,6DAA6D,EAAE,KAAK,IAAI,EAAE;YAC3E,MAAM,QAAQ,GAAG,EAAC,GAAG,iBAAiB,EAAE,IAAI,EAAE,WAAW,EAAC,CAAC;YAC3D,MAAM,QAAQ,GAAG,EAAC,GAAG,iBAAiB,EAAE,IAAI,EAAE,WAAW,EAAC,CAAC;YAC3D,MAAM,MAAM,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YACpC,MAAM,QAAQ,GAA8B;gBAC1C,MAAM,EAAE,UAAU;gBAClB,SAAS,EAAE,MAAM;gBACjB,iBAAiB,EAAE,GAAG;gBACtB,aAAa,EAAE,CAAC;gBAChB,mBAAmB,EAAE,CAAC;gBACtB,oBAAoB,EAAE,CAAC;aACxB,CAAC;YACF,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACvG,eAAe,CAAC,SAAS,CAAC,CAAC;YAC3B,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE;;;;;;;;;;;KAW/B,CAAC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;YACjE,MAAM,QAAQ,GAAG,EAAC,GAAG,iBAAiB,EAAE,IAAI,EAAE,WAAW,EAAC,CAAC;YAC3D,MAAM,QAAQ,GAAG,EAAC,GAAG,iBAAiB,EAAE,IAAI,EAAE,WAAW,EAAC,CAAC;YAC3D,MAAM,MAAM,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YACpC,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACnG,eAAe,CAAC,SAAS,CAAC,CAAC;YAC3B,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE;;;;KAI/B,CAAC,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Trace from '../../models/trace/trace.js';\nimport {defaultTraceEvent} from '../../testing/TraceHelpers.js';\n\nimport * as Timeline from './timeline.js';\n\ndescribe('SaveFileFormatter', () => {\n function assertValidJSON(input: string) {\n try {\n JSON.parse(input);\n } catch {\n assert.fail('Parsing input as JSON failed');\n }\n }\n describe('arrayOfObjectsJsonGenerator', () => {\n it('generates JSON where each event is on its own line', async () => {\n const eventOne = {...defaultTraceEvent, name: 'event_one'};\n const eventTwo = {...defaultTraceEvent, name: 'event_two'};\n\n const formatted =\n Array.from(Timeline.SaveFileFormatter.arrayOfObjectsJsonGenerator([eventOne, eventTwo])).join('');\n assertValidJSON(formatted);\n assert.strictEqual(formatted, `[\n {\"name\":\"event_one\",\"tid\":0,\"pid\":0,\"ts\":0,\"cat\":\"test\",\"ph\":\"M\"},\n {\"name\":\"event_two\",\"tid\":0,\"pid\":0,\"ts\":0,\"cat\":\"test\",\"ph\":\"M\"}\n]`);\n });\n });\n\n describe('traceJsonGenerator', () => {\n it('contains top level keys for the events and for the metadata', async () => {\n const eventOne = {...defaultTraceEvent, name: 'event_one'};\n const eventTwo = {...defaultTraceEvent, name: 'event_two'};\n const events = [eventOne, eventTwo];\n const metadata: Trace.Types.File.MetaData = {\n source: 'DevTools',\n startTime: '1234',\n networkThrottling: '4',\n cpuThrottling: 1,\n hardwareConcurrency: 1,\n enhancedTraceVersion: 1,\n };\n const formatted = Array.from(Timeline.SaveFileFormatter.traceJsonGenerator(events, metadata)).join('');\n assertValidJSON(formatted);\n assert.strictEqual(formatted, `{\"metadata\": {\n \"source\": \"DevTools\",\n \"startTime\": \"1234\",\n \"networkThrottling\": \"4\",\n \"cpuThrottling\": 1,\n \"hardwareConcurrency\": 1,\n \"enhancedTraceVersion\": 1\n},\n\"traceEvents\": [\n {\"name\":\"event_one\",\"tid\":0,\"pid\":0,\"ts\":0,\"cat\":\"test\",\"ph\":\"M\"},\n {\"name\":\"event_two\",\"tid\":0,\"pid\":0,\"ts\":0,\"cat\":\"test\",\"ph\":\"M\"}\n]}\\n`);\n });\n\n it('will emit {} for the metadata if none is provided', async () => {\n const eventOne = {...defaultTraceEvent, name: 'event_one'};\n const eventTwo = {...defaultTraceEvent, name: 'event_two'};\n const events = [eventOne, eventTwo];\n const formatted = Array.from(Timeline.SaveFileFormatter.traceJsonGenerator(events, null)).join('');\n assertValidJSON(formatted);\n assert.strictEqual(formatted, `{\"metadata\": {},\n\"traceEvents\": [\n {\"name\":\"event_one\",\"tid\":0,\"pid\":0,\"ts\":0,\"cat\":\"test\",\"ph\":\"M\"},\n {\"name\":\"event_two\",\"tid\":0,\"pid\":0,\"ts\":0,\"cat\":\"test\",\"ph\":\"M\"}\n]}\\n`);\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/ServerTimingsTrackAppender.d.ts b/public/panels/timeline/ServerTimingsTrackAppender.d.ts index c78b3c67b..bbdd1df64 100644 --- a/public/panels/timeline/ServerTimingsTrackAppender.d.ts +++ b/public/panels/timeline/ServerTimingsTrackAppender.d.ts @@ -1,15 +1,15 @@ -import type * as TraceEngine from '../../models/trace/trace.js'; +import type * as Trace from '../../models/trace/trace.js'; import { type CompatibilityTracksAppender, type HighlightedEntryInfo, type TrackAppender, type TrackAppenderName } from './CompatibilityTracksAppender.js'; export declare class ServerTimingsTrackAppender implements TrackAppender { #private; readonly appenderName: TrackAppenderName; - constructor(compatibilityBuilder: CompatibilityTracksAppender, traceParsedData: TraceEngine.Handlers.Types.TraceParseData); + constructor(compatibilityBuilder: CompatibilityTracksAppender, parsedTrace: Trace.Handlers.Types.ParsedTrace); appendTrackAtLevel(trackStartLevel: number, expanded?: boolean): number; colorForEvent(): string; - titleForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): string; + titleForEvent(event: Trace.Types.Events.Event): string; /** * Returns the info shown when an event added by this appender * is hovered in the timeline. */ - highlightedEntryInfo(event: TraceEngine.Types.TraceEvents.TraceEventData): HighlightedEntryInfo; + highlightedEntryInfo(event: Trace.Types.Events.Event): HighlightedEntryInfo; } diff --git a/public/panels/timeline/ServerTimingsTrackAppender.js b/public/panels/timeline/ServerTimingsTrackAppender.js index 7a2483e3b..e99430360 100644 --- a/public/panels/timeline/ServerTimingsTrackAppender.js +++ b/public/panels/timeline/ServerTimingsTrackAppender.js @@ -20,21 +20,21 @@ const str_ = i18n.i18n.registerUIStrings('panels/timeline/ServerTimingsTrackAppe const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); export class ServerTimingsTrackAppender { appenderName = 'ServerTimings'; - #traceParsedData; + #parsedTrace; #compatibilityBuilder; - constructor(compatibilityBuilder, traceParsedData) { - this.#traceParsedData = traceParsedData; + constructor(compatibilityBuilder, parsedTrace) { + this.#parsedTrace = parsedTrace; this.#compatibilityBuilder = compatibilityBuilder; } appendTrackAtLevel(trackStartLevel, expanded) { if (!Root.Runtime.experiments.isEnabled("timeline-server-timings" /* Root.Runtime.ExperimentName.TIMELINE_SERVER_TIMINGS */)) { return trackStartLevel; } - if (this.#traceParsedData.ServerTimings.serverTimings.length === 0) { + if (this.#parsedTrace.ServerTimings.serverTimings.length === 0) { return trackStartLevel; } let lastLevel = trackStartLevel; - const serverTimingsByOrigin = Object.groupBy(this.#traceParsedData.ServerTimings.serverTimings, serverTiming => serverTiming.args.data.origin); + const serverTimingsByOrigin = Object.groupBy(this.#parsedTrace.ServerTimings.serverTimings, serverTiming => serverTiming.args.data.origin); for (const [origin, serverTimings] of Object.entries(serverTimingsByOrigin)) { if (!serverTimings || serverTimings.length === 0) { continue; diff --git a/public/panels/timeline/ServerTimingsTrackAppender.js.map b/public/panels/timeline/ServerTimingsTrackAppender.js.map index cf5f19569..4f090edfc 100644 --- a/public/panels/timeline/ServerTimingsTrackAppender.js.map +++ b/public/panels/timeline/ServerTimingsTrackAppender.js.map @@ -1 +1 @@ -{"version":3,"file":"ServerTimingsTrackAppender.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/ServerTimingsTrackAppender.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Root from '../../core/root/root.js';\nimport type * as TraceEngine from '../../models/trace/trace.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\n\nimport {buildGroupStyle, buildTrackHeader, getFormattedTime} from './AppenderUtils.js';\nimport {\n type CompatibilityTracksAppender,\n type HighlightedEntryInfo,\n type TrackAppender,\n type TrackAppenderName,\n VisualLoggingTrackName,\n} from './CompatibilityTracksAppender.js';\n\nconst UIStrings = {\n /**\n *@description Text in Timeline Flame Chart Data Provider of the Performance panel\n */\n serverTimingTrack:\n 'This track contains timings taken from Server-Timing network response headers. Their respective start times are only estimated and may not be accurate.',\n /**\n * @description Server Side refers to activity happening in the server in the context of an HTTP request.\n * @example {origin} PH1\n */\n serverSideTrack: 'Server Timings — {PH1}',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/ServerTimingsTrackAppender.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport class ServerTimingsTrackAppender implements TrackAppender {\n readonly appenderName: TrackAppenderName = 'ServerTimings';\n\n #traceParsedData: Readonly;\n #compatibilityBuilder: CompatibilityTracksAppender;\n constructor(\n compatibilityBuilder: CompatibilityTracksAppender, traceParsedData: TraceEngine.Handlers.Types.TraceParseData) {\n this.#traceParsedData = traceParsedData;\n this.#compatibilityBuilder = compatibilityBuilder;\n }\n\n appendTrackAtLevel(trackStartLevel: number, expanded?: boolean): number {\n if (!Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_SERVER_TIMINGS)) {\n return trackStartLevel;\n }\n if (this.#traceParsedData.ServerTimings.serverTimings.length === 0) {\n return trackStartLevel;\n }\n let lastLevel = trackStartLevel;\n const serverTimingsByOrigin = Object.groupBy(\n this.#traceParsedData.ServerTimings.serverTimings, serverTiming => serverTiming.args.data.origin);\n for (const [origin, serverTimings] of Object.entries(serverTimingsByOrigin)) {\n if (!serverTimings || serverTimings.length === 0) {\n continue;\n }\n this.#appendTopLevelHeaderAtLevel(lastLevel, origin, expanded);\n lastLevel = this.#appendServerTimings(lastLevel, serverTimings);\n }\n return lastLevel;\n }\n\n /**\n * Appends the top level header for a track. Extension entries can be\n * added to tracks or sub-tracks. In the former case, the top level\n * header corresponds to the track name, in the latter it corresponds\n * to the track group name.\n */\n #appendTopLevelHeaderAtLevel(currentLevel: number, origin: string, expanded?: boolean): void {\n const style = buildGroupStyle({shareHeaderLine: false, collapsible: true});\n const headerTitle = i18nString(UIStrings.serverSideTrack, {PH1: origin});\n const group = buildTrackHeader(\n VisualLoggingTrackName.SERVER_TIMINGS, currentLevel, headerTitle, style,\n /* selectable= */ true, expanded);\n group.description = i18nString(UIStrings.serverTimingTrack);\n this.#compatibilityBuilder.registerTrackForGroup(group, this);\n }\n\n #appendServerTimings(trackStartLevel: number, serverTimings: TraceEngine.Types.TraceEvents.SyntheticServerTiming[]):\n number {\n let currentStartLevel = trackStartLevel;\n currentStartLevel = this.#compatibilityBuilder.appendEventsAtLevel(serverTimings, currentStartLevel, this);\n return currentStartLevel;\n }\n\n colorForEvent(): string {\n return ThemeSupport.ThemeSupport.instance().getComputedValue('--ref-palette-primary70');\n }\n\n titleForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): string {\n return event.name;\n }\n\n /**\n * Returns the info shown when an event added by this appender\n * is hovered in the timeline.\n */\n highlightedEntryInfo(event: TraceEngine.Types.TraceEvents.TraceEventData): HighlightedEntryInfo {\n return {title: event.name, formattedTime: getFormattedTime(event.dur)};\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"ServerTimingsTrackAppender.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/ServerTimingsTrackAppender.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Root from '../../core/root/root.js';\nimport type * as Trace from '../../models/trace/trace.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\n\nimport {buildGroupStyle, buildTrackHeader, getFormattedTime} from './AppenderUtils.js';\nimport {\n type CompatibilityTracksAppender,\n type HighlightedEntryInfo,\n type TrackAppender,\n type TrackAppenderName,\n VisualLoggingTrackName,\n} from './CompatibilityTracksAppender.js';\n\nconst UIStrings = {\n /**\n *@description Text in Timeline Flame Chart Data Provider of the Performance panel\n */\n serverTimingTrack:\n 'This track contains timings taken from Server-Timing network response headers. Their respective start times are only estimated and may not be accurate.',\n /**\n * @description Server Side refers to activity happening in the server in the context of an HTTP request.\n * @example {origin} PH1\n */\n serverSideTrack: 'Server Timings — {PH1}',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/ServerTimingsTrackAppender.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport class ServerTimingsTrackAppender implements TrackAppender {\n readonly appenderName: TrackAppenderName = 'ServerTimings';\n\n #parsedTrace: Readonly;\n #compatibilityBuilder: CompatibilityTracksAppender;\n constructor(compatibilityBuilder: CompatibilityTracksAppender, parsedTrace: Trace.Handlers.Types.ParsedTrace) {\n this.#parsedTrace = parsedTrace;\n this.#compatibilityBuilder = compatibilityBuilder;\n }\n\n appendTrackAtLevel(trackStartLevel: number, expanded?: boolean): number {\n if (!Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_SERVER_TIMINGS)) {\n return trackStartLevel;\n }\n if (this.#parsedTrace.ServerTimings.serverTimings.length === 0) {\n return trackStartLevel;\n }\n let lastLevel = trackStartLevel;\n const serverTimingsByOrigin =\n Object.groupBy(this.#parsedTrace.ServerTimings.serverTimings, serverTiming => serverTiming.args.data.origin);\n for (const [origin, serverTimings] of Object.entries(serverTimingsByOrigin)) {\n if (!serverTimings || serverTimings.length === 0) {\n continue;\n }\n this.#appendTopLevelHeaderAtLevel(lastLevel, origin, expanded);\n lastLevel = this.#appendServerTimings(lastLevel, serverTimings);\n }\n return lastLevel;\n }\n\n /**\n * Appends the top level header for a track. Extension entries can be\n * added to tracks or sub-tracks. In the former case, the top level\n * header corresponds to the track name, in the latter it corresponds\n * to the track group name.\n */\n #appendTopLevelHeaderAtLevel(currentLevel: number, origin: string, expanded?: boolean): void {\n const style = buildGroupStyle({shareHeaderLine: false, collapsible: true});\n const headerTitle = i18nString(UIStrings.serverSideTrack, {PH1: origin});\n const group = buildTrackHeader(\n VisualLoggingTrackName.SERVER_TIMINGS, currentLevel, headerTitle, style,\n /* selectable= */ true, expanded);\n group.description = i18nString(UIStrings.serverTimingTrack);\n this.#compatibilityBuilder.registerTrackForGroup(group, this);\n }\n\n #appendServerTimings(trackStartLevel: number, serverTimings: Trace.Types.Events.SyntheticServerTiming[]): number {\n let currentStartLevel = trackStartLevel;\n currentStartLevel = this.#compatibilityBuilder.appendEventsAtLevel(serverTimings, currentStartLevel, this);\n return currentStartLevel;\n }\n\n colorForEvent(): string {\n return ThemeSupport.ThemeSupport.instance().getComputedValue('--ref-palette-primary70');\n }\n\n titleForEvent(event: Trace.Types.Events.Event): string {\n return event.name;\n }\n\n /**\n * Returns the info shown when an event added by this appender\n * is hovered in the timeline.\n */\n highlightedEntryInfo(event: Trace.Types.Events.Event): HighlightedEntryInfo {\n return {title: event.name, formattedTime: getFormattedTime(event.dur)};\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/SourceMapsResolver.d.ts b/public/panels/timeline/SourceMapsResolver.d.ts index 0d8981237..ea987bdba 100644 --- a/public/panels/timeline/SourceMapsResolver.d.ts +++ b/public/panels/timeline/SourceMapsResolver.d.ts @@ -1,14 +1,14 @@ -import type * as TraceEngine from '../../models/trace/trace.js'; +import type * as Trace from '../../models/trace/trace.js'; export declare class NodeNamesUpdated extends Event { static readonly eventName = "nodenamesupdated"; constructor(); } export declare class SourceMapsResolver extends EventTarget { #private; - constructor(traceData: TraceEngine.Handlers.Types.TraceParseData); + constructor(parsedTrace: Trace.Handlers.Types.ParsedTrace); static clearResolvedNodeNames(): void; - static resolvedNodeNameForEntry(entry: TraceEngine.Types.TraceEvents.SyntheticProfileCall): string | null; - static storeResolvedNodeNameForEntry(pid: TraceEngine.Types.TraceEvents.ProcessID, tid: TraceEngine.Types.TraceEvents.ThreadID, nodeId: number, resolvedFunctionName: string | null): void; + static resolvedNodeNameForEntry(entry: Trace.Types.Events.SyntheticProfileCall): string | null; + static storeResolvedNodeNameForEntry(pid: Trace.Types.Events.ProcessID, tid: Trace.Types.Events.ThreadID, nodeId: number, resolvedFunctionName: string | null): void; install(): Promise; /** * Removes the event listeners and stops tracking newly added sourcemaps. diff --git a/public/panels/timeline/SourceMapsResolver.js b/public/panels/timeline/SourceMapsResolver.js index 2b7a0288c..31a598c26 100644 --- a/public/panels/timeline/SourceMapsResolver.js +++ b/public/panels/timeline/SourceMapsResolver.js @@ -18,7 +18,7 @@ export class NodeNamesUpdated extends Event { // Keying it by the IDs rather than the Node itself means we can avoid passing around trace data in order to get or set values in this map. const resolvedNodeNames = new Map(); export class SourceMapsResolver extends EventTarget { - #traceData; + #parsedTrace; #isResolvingNames = false; // We need to gather up a list of all the DebuggerModels that we should // listen to for source map attached events. For most pages this will be @@ -26,9 +26,9 @@ export class SourceMapsResolver extends EventTarget { // workers, we would also need to gather up the DebuggerModel instances for // those workers too. #debuggerModelsToListen = new Set(); - constructor(traceData) { + constructor(parsedTrace) { super(); - this.#traceData = traceData; + this.#parsedTrace = parsedTrace; } static clearResolvedNodeNames() { resolvedNodeNames.clear(); @@ -47,10 +47,10 @@ export class SourceMapsResolver extends EventTarget { // Required as during the migration we might not always run the Renderer/Samples // handlers. Once we are fully migrated, this check can go as that data will // always be present. - if (!this.#traceData.Samples) { + if (!this.#parsedTrace.Samples) { return; } - for (const threadToProfileMap of this.#traceData.Samples.profilesInProcess.values()) { + for (const threadToProfileMap of this.#parsedTrace.Samples.profilesInProcess.values()) { for (const [tid, profile] of threadToProfileMap) { const nodes = profile.parsedProfile.nodes(); if (!nodes || nodes.length === 0) { @@ -91,10 +91,10 @@ export class SourceMapsResolver extends EventTarget { this.#debuggerModelsToListen.clear(); } async #resolveNamesForNodes() { - if (!this.#traceData.Samples) { + if (!this.#parsedTrace.Samples) { return; } - for (const [pid, threadsInProcess] of this.#traceData.Samples.profilesInProcess) { + for (const [pid, threadsInProcess] of this.#parsedTrace.Samples.profilesInProcess) { for (const [tid, threadProfile] of threadsInProcess) { const nodes = threadProfile.parsedProfile.nodes() ?? []; const target = this.#targetForThread(tid); @@ -130,7 +130,7 @@ export class SourceMapsResolver extends EventTarget { // Figure out the target for the node. If it is in a worker thread, // that is the target, otherwise we use the primary page target. #targetForThread(tid) { - const maybeWorkerId = this.#traceData.Workers.workerIdByThread.get(tid); + const maybeWorkerId = this.#parsedTrace.Workers.workerIdByThread.get(tid); if (maybeWorkerId) { return SDK.TargetManager.TargetManager.instance().targetById(maybeWorkerId); } diff --git a/public/panels/timeline/SourceMapsResolver.js.map b/public/panels/timeline/SourceMapsResolver.js.map index f3771167a..f64881a2f 100644 --- a/public/panels/timeline/SourceMapsResolver.js.map +++ b/public/panels/timeline/SourceMapsResolver.js.map @@ -1 +1 @@ -{"version":3,"file":"SourceMapsResolver.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/SourceMapsResolver.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as SourceMapScopes from '../../models/source_map_scopes/source_map_scopes.js';\nimport type * as TraceEngine from '../../models/trace/trace.js';\n\nexport class NodeNamesUpdated extends Event {\n static readonly eventName = 'nodenamesupdated';\n\n constructor() {\n super(NodeNamesUpdated.eventName, {\n composed: true,\n bubbles: true,\n });\n }\n}\n\n// Track node function names resolved by sourcemaps.\n// Because NodeIDs could conflict, we key these based on:\n// ProcessID=>ThreadID=>NodeId=>resolved function name.\n// Keying it by the IDs rather than the Node itself means we can avoid passing around trace data in order to get or set values in this map.\nconst resolvedNodeNames:\n Map>> = new Map();\n\nexport class SourceMapsResolver extends EventTarget {\n #traceData: TraceEngine.Handlers.Types.TraceParseData;\n\n #isResolvingNames = false;\n\n // We need to gather up a list of all the DebuggerModels that we should\n // listen to for source map attached events. For most pages this will be\n // the debugger model for the primary page target, but if a trace has\n // workers, we would also need to gather up the DebuggerModel instances for\n // those workers too.\n #debuggerModelsToListen = new Set();\n\n constructor(traceData: TraceEngine.Handlers.Types.TraceParseData) {\n super();\n this.#traceData = traceData;\n }\n\n static clearResolvedNodeNames(): void {\n resolvedNodeNames.clear();\n }\n\n static resolvedNodeNameForEntry(entry: TraceEngine.Types.TraceEvents.SyntheticProfileCall): string|null {\n return resolvedNodeNames.get(entry.pid)?.get(entry.tid)?.get(entry.nodeId) ?? null;\n }\n\n static storeResolvedNodeNameForEntry(\n pid: TraceEngine.Types.TraceEvents.ProcessID, tid: TraceEngine.Types.TraceEvents.ThreadID, nodeId: number,\n resolvedFunctionName: string|null): void {\n const resolvedForPid =\n resolvedNodeNames.get(pid) || new Map>();\n const resolvedForTid = resolvedForPid.get(tid) || new Map();\n resolvedForTid.set(nodeId, resolvedFunctionName);\n resolvedForPid.set(tid, resolvedForTid);\n resolvedNodeNames.set(pid, resolvedForPid);\n }\n\n async install(): Promise {\n // Required as during the migration we might not always run the Renderer/Samples\n // handlers. Once we are fully migrated, this check can go as that data will\n // always be present.\n if (!this.#traceData.Samples) {\n return;\n }\n\n for (const threadToProfileMap of this.#traceData.Samples.profilesInProcess.values()) {\n for (const [tid, profile] of threadToProfileMap) {\n const nodes = profile.parsedProfile.nodes();\n if (!nodes || nodes.length === 0) {\n continue;\n }\n\n const target = this.#targetForThread(tid);\n const debuggerModel = target?.model(SDK.DebuggerModel.DebuggerModel);\n if (!debuggerModel) {\n continue;\n }\n for (const node of nodes) {\n const script = debuggerModel.scriptForId(String(node.callFrame.scriptId));\n const shouldListenToSourceMap = !script || script.sourceMapURL;\n if (!shouldListenToSourceMap) {\n continue;\n }\n this.#debuggerModelsToListen.add(debuggerModel);\n }\n }\n }\n\n for (const debuggerModel of this.#debuggerModelsToListen) {\n debuggerModel.sourceMapManager().addEventListener(\n SDK.SourceMapManager.Events.SourceMapAttached, this.#onAttachedSourceMap, this);\n }\n\n // Although we have added listeners for SourceMapAttached events, we also\n // immediately try to resolve function names. This ensures we use any\n // sourcemaps that were attached before we bound our event listener.\n await this.#resolveNamesForNodes();\n }\n\n /**\n * Removes the event listeners and stops tracking newly added sourcemaps.\n * Should be called before destroying an instance of this class to avoid leaks\n * with listeners.\n */\n uninstall(): void {\n for (const debuggerModel of this.#debuggerModelsToListen) {\n debuggerModel.sourceMapManager().removeEventListener(\n SDK.SourceMapManager.Events.SourceMapAttached, this.#onAttachedSourceMap, this);\n }\n this.#debuggerModelsToListen.clear();\n }\n\n async #resolveNamesForNodes(): Promise {\n if (!this.#traceData.Samples) {\n return;\n }\n\n for (const [pid, threadsInProcess] of this.#traceData.Samples.profilesInProcess) {\n for (const [tid, threadProfile] of threadsInProcess) {\n const nodes = threadProfile.parsedProfile.nodes() ?? [];\n const target = this.#targetForThread(tid);\n if (!target) {\n continue;\n }\n for (const node of nodes) {\n const resolvedFunctionName =\n await SourceMapScopes.NamesResolver.resolveProfileFrameFunctionName(node.callFrame, target);\n node.setFunctionName(resolvedFunctionName);\n\n SourceMapsResolver.storeResolvedNodeNameForEntry(pid, tid, node.id, resolvedFunctionName);\n }\n }\n }\n this.dispatchEvent(new NodeNamesUpdated());\n }\n\n #onAttachedSourceMap(): void {\n // Exit if we are already resolving so that we batch requests; if pages\n // have a lot of sourcemaps we can get a lot of events at once.\n if (this.#isResolvingNames) {\n return;\n }\n\n this.#isResolvingNames = true;\n // Resolving names triggers a repaint of the flame chart. Instead of attempting to resolve\n // names every time a source map is attached, wait for some time once the first source map is\n // attached. This way we allow for other source maps to be parsed before attempting a name\n // resolving using the available source maps. Otherwise the UI is blocked when the number\n // of source maps is particularly large.\n setTimeout(async () => {\n this.#isResolvingNames = false;\n await this.#resolveNamesForNodes();\n }, 500);\n }\n\n // Figure out the target for the node. If it is in a worker thread,\n // that is the target, otherwise we use the primary page target.\n #targetForThread(tid: TraceEngine.Types.TraceEvents.ThreadID): SDK.Target.Target|null {\n const maybeWorkerId = this.#traceData.Workers.workerIdByThread.get(tid);\n if (maybeWorkerId) {\n return SDK.TargetManager.TargetManager.instance().targetById(maybeWorkerId);\n }\n return SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"SourceMapsResolver.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/SourceMapsResolver.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as SourceMapScopes from '../../models/source_map_scopes/source_map_scopes.js';\nimport type * as Trace from '../../models/trace/trace.js';\n\nexport class NodeNamesUpdated extends Event {\n static readonly eventName = 'nodenamesupdated';\n\n constructor() {\n super(NodeNamesUpdated.eventName, {\n composed: true,\n bubbles: true,\n });\n }\n}\n\n// Track node function names resolved by sourcemaps.\n// Because NodeIDs could conflict, we key these based on:\n// ProcessID=>ThreadID=>NodeId=>resolved function name.\n// Keying it by the IDs rather than the Node itself means we can avoid passing around trace data in order to get or set values in this map.\nconst resolvedNodeNames: Map>> =\n new Map();\n\nexport class SourceMapsResolver extends EventTarget {\n #parsedTrace: Trace.Handlers.Types.ParsedTrace;\n\n #isResolvingNames = false;\n\n // We need to gather up a list of all the DebuggerModels that we should\n // listen to for source map attached events. For most pages this will be\n // the debugger model for the primary page target, but if a trace has\n // workers, we would also need to gather up the DebuggerModel instances for\n // those workers too.\n #debuggerModelsToListen = new Set();\n\n constructor(parsedTrace: Trace.Handlers.Types.ParsedTrace) {\n super();\n this.#parsedTrace = parsedTrace;\n }\n\n static clearResolvedNodeNames(): void {\n resolvedNodeNames.clear();\n }\n\n static resolvedNodeNameForEntry(entry: Trace.Types.Events.SyntheticProfileCall): string|null {\n return resolvedNodeNames.get(entry.pid)?.get(entry.tid)?.get(entry.nodeId) ?? null;\n }\n\n static storeResolvedNodeNameForEntry(\n pid: Trace.Types.Events.ProcessID, tid: Trace.Types.Events.ThreadID, nodeId: number,\n resolvedFunctionName: string|null): void {\n const resolvedForPid =\n resolvedNodeNames.get(pid) || new Map>();\n const resolvedForTid = resolvedForPid.get(tid) || new Map();\n resolvedForTid.set(nodeId, resolvedFunctionName);\n resolvedForPid.set(tid, resolvedForTid);\n resolvedNodeNames.set(pid, resolvedForPid);\n }\n\n async install(): Promise {\n // Required as during the migration we might not always run the Renderer/Samples\n // handlers. Once we are fully migrated, this check can go as that data will\n // always be present.\n if (!this.#parsedTrace.Samples) {\n return;\n }\n\n for (const threadToProfileMap of this.#parsedTrace.Samples.profilesInProcess.values()) {\n for (const [tid, profile] of threadToProfileMap) {\n const nodes = profile.parsedProfile.nodes();\n if (!nodes || nodes.length === 0) {\n continue;\n }\n\n const target = this.#targetForThread(tid);\n const debuggerModel = target?.model(SDK.DebuggerModel.DebuggerModel);\n if (!debuggerModel) {\n continue;\n }\n for (const node of nodes) {\n const script = debuggerModel.scriptForId(String(node.callFrame.scriptId));\n const shouldListenToSourceMap = !script || script.sourceMapURL;\n if (!shouldListenToSourceMap) {\n continue;\n }\n this.#debuggerModelsToListen.add(debuggerModel);\n }\n }\n }\n\n for (const debuggerModel of this.#debuggerModelsToListen) {\n debuggerModel.sourceMapManager().addEventListener(\n SDK.SourceMapManager.Events.SourceMapAttached, this.#onAttachedSourceMap, this);\n }\n\n // Although we have added listeners for SourceMapAttached events, we also\n // immediately try to resolve function names. This ensures we use any\n // sourcemaps that were attached before we bound our event listener.\n await this.#resolveNamesForNodes();\n }\n\n /**\n * Removes the event listeners and stops tracking newly added sourcemaps.\n * Should be called before destroying an instance of this class to avoid leaks\n * with listeners.\n */\n uninstall(): void {\n for (const debuggerModel of this.#debuggerModelsToListen) {\n debuggerModel.sourceMapManager().removeEventListener(\n SDK.SourceMapManager.Events.SourceMapAttached, this.#onAttachedSourceMap, this);\n }\n this.#debuggerModelsToListen.clear();\n }\n\n async #resolveNamesForNodes(): Promise {\n if (!this.#parsedTrace.Samples) {\n return;\n }\n\n for (const [pid, threadsInProcess] of this.#parsedTrace.Samples.profilesInProcess) {\n for (const [tid, threadProfile] of threadsInProcess) {\n const nodes = threadProfile.parsedProfile.nodes() ?? [];\n const target = this.#targetForThread(tid);\n if (!target) {\n continue;\n }\n for (const node of nodes) {\n const resolvedFunctionName =\n await SourceMapScopes.NamesResolver.resolveProfileFrameFunctionName(node.callFrame, target);\n node.setFunctionName(resolvedFunctionName);\n\n SourceMapsResolver.storeResolvedNodeNameForEntry(pid, tid, node.id, resolvedFunctionName);\n }\n }\n }\n this.dispatchEvent(new NodeNamesUpdated());\n }\n\n #onAttachedSourceMap(): void {\n // Exit if we are already resolving so that we batch requests; if pages\n // have a lot of sourcemaps we can get a lot of events at once.\n if (this.#isResolvingNames) {\n return;\n }\n\n this.#isResolvingNames = true;\n // Resolving names triggers a repaint of the flame chart. Instead of attempting to resolve\n // names every time a source map is attached, wait for some time once the first source map is\n // attached. This way we allow for other source maps to be parsed before attempting a name\n // resolving using the available source maps. Otherwise the UI is blocked when the number\n // of source maps is particularly large.\n setTimeout(async () => {\n this.#isResolvingNames = false;\n await this.#resolveNamesForNodes();\n }, 500);\n }\n\n // Figure out the target for the node. If it is in a worker thread,\n // that is the target, otherwise we use the primary page target.\n #targetForThread(tid: Trace.Types.Events.ThreadID): SDK.Target.Target|null {\n const maybeWorkerId = this.#parsedTrace.Workers.workerIdByThread.get(tid);\n if (maybeWorkerId) {\n return SDK.TargetManager.TargetManager.instance().targetById(maybeWorkerId);\n }\n return SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/SourceMapsResolver.test.js b/public/panels/timeline/SourceMapsResolver.test.js index 571655a67..686a90dde 100644 --- a/public/panels/timeline/SourceMapsResolver.test.js +++ b/public/panels/timeline/SourceMapsResolver.test.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as Bindings from '../../models/bindings/bindings.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import { createTarget } from '../../testing/EnvironmentHelpers.js'; import { TestPlugin } from '../../testing/LanguagePluginHelpers.js'; import { describeWithMockConnection, } from '../../testing/MockConnection.js'; @@ -14,7 +14,7 @@ const AUTHORED_FUNCTION_NAME = 'someFunction'; describeWithMockConnection('SourceMapsResolver', () => { let target; let script; - let traceParsedData; + let parsedTrace; let profileCall; beforeEach(async function () { target = createTarget(); @@ -23,7 +23,7 @@ describeWithMockConnection('SourceMapsResolver', () => { // map however the current status of the source map helpers makes // it difficult to do so. const columnNumber = 51; - profileCall = makeProfileCall('function', 10, 100, TraceEngine.Types.TraceEvents.ProcessID(1), TraceEngine.Types.TraceEvents.ThreadID(1)); + profileCall = makeProfileCall('function', 10, 100, Trace.Types.Events.ProcessID(1), Trace.Types.Events.ThreadID(1)); profileCall.callFrame = { columnNumber, functionName: 'minified', @@ -37,19 +37,19 @@ describeWithMockConnection('SourceMapsResolver', () => { workerURLById: new Map(), }; // This only includes data used in the SourceMapsResolver - traceParsedData = { + parsedTrace = { Samples: makeMockSamplesHandlerData([profileCall]), Workers: workersData, }; }); it('renames nodes from the profile models when the corresponding scripts and source maps have loaded', async function () { - const resolver = new Timeline.SourceMapsResolver.SourceMapsResolver(traceParsedData); + const resolver = new Timeline.SourceMapsResolver.SourceMapsResolver(parsedTrace); // Test the node's name is minified before the script and source maps load. - assert.strictEqual(TraceEngine.Handlers.ModelHandlers.Samples.getProfileCallFunctionName(traceParsedData.Samples, profileCall), MINIFIED_FUNCTION_NAME); + assert.strictEqual(Trace.Handlers.ModelHandlers.Samples.getProfileCallFunctionName(parsedTrace.Samples, profileCall), MINIFIED_FUNCTION_NAME); await resolver.install(); // Now that the script and source map have loaded, test that the model has been automatically // reparsed to resolve function names. - assert.strictEqual(TraceEngine.Handlers.ModelHandlers.Samples.getProfileCallFunctionName(traceParsedData.Samples, profileCall), AUTHORED_FUNCTION_NAME); + assert.strictEqual(Trace.Handlers.ModelHandlers.Samples.getProfileCallFunctionName(parsedTrace.Samples, profileCall), AUTHORED_FUNCTION_NAME); // Ensure we populate the cache assert.strictEqual(Timeline.SourceMapsResolver.SourceMapsResolver.resolvedNodeNameForEntry(profileCall), AUTHORED_FUNCTION_NAME); }); @@ -68,9 +68,9 @@ describeWithMockConnection('SourceMapsResolver', () => { } const { pluginManager } = Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance(); pluginManager.addPlugin(new Plugin()); - const resolver = new Timeline.SourceMapsResolver.SourceMapsResolver(traceParsedData); + const resolver = new Timeline.SourceMapsResolver.SourceMapsResolver(parsedTrace); await resolver.install(); - assert.strictEqual(TraceEngine.Handlers.ModelHandlers.Samples.getProfileCallFunctionName(traceParsedData.Samples, profileCall), PLUGIN_FUNCTION_NAME); + assert.strictEqual(Trace.Handlers.ModelHandlers.Samples.getProfileCallFunctionName(parsedTrace.Samples, profileCall), PLUGIN_FUNCTION_NAME); }); }); //# sourceMappingURL=SourceMapsResolver.test.js.map \ No newline at end of file diff --git a/public/panels/timeline/SourceMapsResolver.test.js.map b/public/panels/timeline/SourceMapsResolver.test.js.map index 3a2a5e74c..b8c84ad3c 100644 --- a/public/panels/timeline/SourceMapsResolver.test.js.map +++ b/public/panels/timeline/SourceMapsResolver.test.js.map @@ -1 +1 @@ -{"version":3,"file":"SourceMapsResolver.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/SourceMapsResolver.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {type Chrome} from '../../../extension-api/ExtensionAPI.js';\nimport type * as SDK from '../../core/sdk/sdk.js';\nimport * as Bindings from '../../models/bindings/bindings.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport {createTarget} from '../../testing/EnvironmentHelpers.js';\nimport {TestPlugin} from '../../testing/LanguagePluginHelpers.js';\nimport {\n describeWithMockConnection,\n} from '../../testing/MockConnection.js';\nimport {loadBasicSourceMapExample} from '../../testing/SourceMapHelpers.js';\nimport {\n makeMockSamplesHandlerData,\n makeProfileCall,\n} from '../../testing/TraceHelpers.js';\n\nimport * as Timeline from './timeline.js';\n\nconst MINIFIED_FUNCTION_NAME = 'minified';\nconst AUTHORED_FUNCTION_NAME = 'someFunction';\n\ndescribeWithMockConnection('SourceMapsResolver', () => {\n let target: SDK.Target.Target;\n let script: SDK.Script.Script;\n let traceParsedData: TraceEngine.Handlers.Types.TraceParseData;\n let profileCall: TraceEngine.Types.TraceEvents.SyntheticProfileCall;\n beforeEach(async function() {\n target = createTarget();\n script = (await loadBasicSourceMapExample(target)).script;\n // Ideally we would get a column number we can use from the source\n // map however the current status of the source map helpers makes\n // it difficult to do so.\n const columnNumber = 51;\n profileCall = makeProfileCall(\n 'function', 10, 100, TraceEngine.Types.TraceEvents.ProcessID(1), TraceEngine.Types.TraceEvents.ThreadID(1));\n\n profileCall.callFrame = {\n columnNumber,\n functionName: 'minified',\n lineNumber: 0,\n scriptId: script.scriptId,\n url: 'file://gen.js',\n };\n\n const workersData: TraceEngine.Handlers.ModelHandlers.Workers.WorkersData = {\n workerSessionIdEvents: [],\n workerIdByThread: new Map(),\n workerURLById: new Map(),\n };\n // This only includes data used in the SourceMapsResolver\n traceParsedData = {\n Samples: makeMockSamplesHandlerData([profileCall]),\n Workers: workersData,\n } as TraceEngine.Handlers.Types.TraceParseData;\n });\n\n it('renames nodes from the profile models when the corresponding scripts and source maps have loaded',\n async function() {\n const resolver = new Timeline.SourceMapsResolver.SourceMapsResolver(traceParsedData);\n\n // Test the node's name is minified before the script and source maps load.\n assert.strictEqual(\n TraceEngine.Handlers.ModelHandlers.Samples.getProfileCallFunctionName(traceParsedData.Samples, profileCall),\n MINIFIED_FUNCTION_NAME);\n\n await resolver.install();\n\n // Now that the script and source map have loaded, test that the model has been automatically\n // reparsed to resolve function names.\n assert.strictEqual(\n TraceEngine.Handlers.ModelHandlers.Samples.getProfileCallFunctionName(traceParsedData.Samples, profileCall),\n AUTHORED_FUNCTION_NAME);\n\n // Ensure we populate the cache\n assert.strictEqual(\n Timeline.SourceMapsResolver.SourceMapsResolver.resolvedNodeNameForEntry(profileCall),\n AUTHORED_FUNCTION_NAME);\n });\n\n it('resolves function names using a plugin when available', async () => {\n const PLUGIN_FUNCTION_NAME = 'PLUGIN_FUNCTION_NAME';\n class Plugin extends TestPlugin {\n constructor() {\n super('InstrumentationBreakpoints');\n }\n\n override getFunctionInfo(_rawLocation: Chrome.DevTools.RawLocation):\n Promise<{frames: Chrome.DevTools.FunctionInfo[], missingSymbolFiles?: string[]|undefined}> {\n return Promise.resolve({frames: [{name: PLUGIN_FUNCTION_NAME}]});\n }\n override handleScript(_: SDK.Script.Script) {\n return true;\n }\n }\n\n const {pluginManager} = Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance();\n pluginManager.addPlugin(new Plugin());\n const resolver = new Timeline.SourceMapsResolver.SourceMapsResolver(traceParsedData);\n await resolver.install();\n assert.strictEqual(\n TraceEngine.Handlers.ModelHandlers.Samples.getProfileCallFunctionName(traceParsedData.Samples, profileCall),\n PLUGIN_FUNCTION_NAME);\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"SourceMapsResolver.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/SourceMapsResolver.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport {type Chrome} from '../../../extension-api/ExtensionAPI.js';\nimport type * as SDK from '../../core/sdk/sdk.js';\nimport * as Bindings from '../../models/bindings/bindings.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport {createTarget} from '../../testing/EnvironmentHelpers.js';\nimport {TestPlugin} from '../../testing/LanguagePluginHelpers.js';\nimport {\n describeWithMockConnection,\n} from '../../testing/MockConnection.js';\nimport {loadBasicSourceMapExample} from '../../testing/SourceMapHelpers.js';\nimport {\n makeMockSamplesHandlerData,\n makeProfileCall,\n} from '../../testing/TraceHelpers.js';\n\nimport * as Timeline from './timeline.js';\n\nconst MINIFIED_FUNCTION_NAME = 'minified';\nconst AUTHORED_FUNCTION_NAME = 'someFunction';\n\ndescribeWithMockConnection('SourceMapsResolver', () => {\n let target: SDK.Target.Target;\n let script: SDK.Script.Script;\n let parsedTrace: Trace.Handlers.Types.ParsedTrace;\n let profileCall: Trace.Types.Events.SyntheticProfileCall;\n beforeEach(async function() {\n target = createTarget();\n script = (await loadBasicSourceMapExample(target)).script;\n // Ideally we would get a column number we can use from the source\n // map however the current status of the source map helpers makes\n // it difficult to do so.\n const columnNumber = 51;\n profileCall = makeProfileCall('function', 10, 100, Trace.Types.Events.ProcessID(1), Trace.Types.Events.ThreadID(1));\n\n profileCall.callFrame = {\n columnNumber,\n functionName: 'minified',\n lineNumber: 0,\n scriptId: script.scriptId,\n url: 'file://gen.js',\n };\n\n const workersData: Trace.Handlers.ModelHandlers.Workers.WorkersData = {\n workerSessionIdEvents: [],\n workerIdByThread: new Map(),\n workerURLById: new Map(),\n };\n // This only includes data used in the SourceMapsResolver\n parsedTrace = {\n Samples: makeMockSamplesHandlerData([profileCall]),\n Workers: workersData,\n } as Trace.Handlers.Types.ParsedTrace;\n });\n\n it('renames nodes from the profile models when the corresponding scripts and source maps have loaded',\n async function() {\n const resolver = new Timeline.SourceMapsResolver.SourceMapsResolver(parsedTrace);\n\n // Test the node's name is minified before the script and source maps load.\n assert.strictEqual(\n Trace.Handlers.ModelHandlers.Samples.getProfileCallFunctionName(parsedTrace.Samples, profileCall),\n MINIFIED_FUNCTION_NAME);\n\n await resolver.install();\n\n // Now that the script and source map have loaded, test that the model has been automatically\n // reparsed to resolve function names.\n assert.strictEqual(\n Trace.Handlers.ModelHandlers.Samples.getProfileCallFunctionName(parsedTrace.Samples, profileCall),\n AUTHORED_FUNCTION_NAME);\n\n // Ensure we populate the cache\n assert.strictEqual(\n Timeline.SourceMapsResolver.SourceMapsResolver.resolvedNodeNameForEntry(profileCall),\n AUTHORED_FUNCTION_NAME);\n });\n\n it('resolves function names using a plugin when available', async () => {\n const PLUGIN_FUNCTION_NAME = 'PLUGIN_FUNCTION_NAME';\n class Plugin extends TestPlugin {\n constructor() {\n super('InstrumentationBreakpoints');\n }\n\n override getFunctionInfo(_rawLocation: Chrome.DevTools.RawLocation):\n Promise<{frames: Chrome.DevTools.FunctionInfo[], missingSymbolFiles?: string[]|undefined}> {\n return Promise.resolve({frames: [{name: PLUGIN_FUNCTION_NAME}]});\n }\n override handleScript(_: SDK.Script.Script) {\n return true;\n }\n }\n\n const {pluginManager} = Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance();\n pluginManager.addPlugin(new Plugin());\n const resolver = new Timeline.SourceMapsResolver.SourceMapsResolver(parsedTrace);\n await resolver.install();\n assert.strictEqual(\n Trace.Handlers.ModelHandlers.Samples.getProfileCallFunctionName(parsedTrace.Samples, profileCall),\n PLUGIN_FUNCTION_NAME);\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TargetForEvent.d.ts b/public/panels/timeline/TargetForEvent.d.ts index 0ffc96ca2..45d3f5e9f 100644 --- a/public/panels/timeline/TargetForEvent.d.ts +++ b/public/panels/timeline/TargetForEvent.d.ts @@ -1,8 +1,8 @@ import * as SDK from '../../core/sdk/sdk.js'; -import type * as TraceEngine from '../../models/trace/trace.js'; +import type * as Trace from '../../models/trace/trace.js'; /** * If the event's thread was identified as belonging to a worker, this will * return the target representing that worker. Otherwise, we return the primary * page's target. **/ -export declare function targetForEvent(traceParsedData: TraceEngine.Handlers.Types.TraceParseData, event: TraceEngine.Types.TraceEvents.TraceEventData): SDK.Target.Target | null; +export declare function targetForEvent(parsedTrace: Trace.Handlers.Types.ParsedTrace, event: Trace.Types.Events.Event): SDK.Target.Target | null; diff --git a/public/panels/timeline/TargetForEvent.js b/public/panels/timeline/TargetForEvent.js index a09baff9f..4b55fcd91 100644 --- a/public/panels/timeline/TargetForEvent.js +++ b/public/panels/timeline/TargetForEvent.js @@ -7,9 +7,9 @@ import * as SDK from '../../core/sdk/sdk.js'; * return the target representing that worker. Otherwise, we return the primary * page's target. **/ -export function targetForEvent(traceParsedData, event) { +export function targetForEvent(parsedTrace, event) { const targetManager = SDK.TargetManager.TargetManager.instance(); - const workerId = traceParsedData.Workers.workerIdByThread.get(event.tid); + const workerId = parsedTrace.Workers.workerIdByThread.get(event.tid); if (workerId) { return targetManager.targetById(workerId); } diff --git a/public/panels/timeline/TargetForEvent.js.map b/public/panels/timeline/TargetForEvent.js.map index 78c2a2319..a0525be19 100644 --- a/public/panels/timeline/TargetForEvent.js.map +++ b/public/panels/timeline/TargetForEvent.js.map @@ -1 +1 @@ -{"version":3,"file":"TargetForEvent.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TargetForEvent.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,GAAG,MAAM,uBAAuB,CAAC;AAG7C;;;;IAII;AACJ,MAAM,UAAU,cAAc,CAC1B,eAA0D,EAC1D,KAAmD;IACrD,MAAM,aAAa,GAAG,GAAG,CAAC,aAAa,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC;IACjE,MAAM,QAAQ,GAAG,eAAe,CAAC,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzE,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,aAAa,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC5C,CAAC;IAED,OAAO,aAAa,CAAC,iBAAiB,EAAE,CAAC;AAC3C,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as SDK from '../../core/sdk/sdk.js';\nimport type * as TraceEngine from '../../models/trace/trace.js';\n\n/**\n * If the event's thread was identified as belonging to a worker, this will\n * return the target representing that worker. Otherwise, we return the primary\n * page's target.\n **/\nexport function targetForEvent(\n traceParsedData: TraceEngine.Handlers.Types.TraceParseData,\n event: TraceEngine.Types.TraceEvents.TraceEventData): SDK.Target.Target|null {\n const targetManager = SDK.TargetManager.TargetManager.instance();\n const workerId = traceParsedData.Workers.workerIdByThread.get(event.tid);\n if (workerId) {\n return targetManager.targetById(workerId);\n }\n\n return targetManager.primaryPageTarget();\n}\n"]} \ No newline at end of file +{"version":3,"file":"TargetForEvent.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TargetForEvent.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,GAAG,MAAM,uBAAuB,CAAC;AAG7C;;;;IAII;AACJ,MAAM,UAAU,cAAc,CAC1B,WAA6C,EAAE,KAA+B;IAChF,MAAM,aAAa,GAAG,GAAG,CAAC,aAAa,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC;IACjE,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,gBAAgB,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACrE,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,aAAa,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAC5C,CAAC;IAED,OAAO,aAAa,CAAC,iBAAiB,EAAE,CAAC;AAC3C,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as SDK from '../../core/sdk/sdk.js';\nimport type * as Trace from '../../models/trace/trace.js';\n\n/**\n * If the event's thread was identified as belonging to a worker, this will\n * return the target representing that worker. Otherwise, we return the primary\n * page's target.\n **/\nexport function targetForEvent(\n parsedTrace: Trace.Handlers.Types.ParsedTrace, event: Trace.Types.Events.Event): SDK.Target.Target|null {\n const targetManager = SDK.TargetManager.TargetManager.instance();\n const workerId = parsedTrace.Workers.workerIdByThread.get(event.tid);\n if (workerId) {\n return targetManager.targetById(workerId);\n }\n\n return targetManager.primaryPageTarget();\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/ThreadAppender.d.ts b/public/panels/timeline/ThreadAppender.d.ts index 55b358694..2bc1fb0cc 100644 --- a/public/panels/timeline/ThreadAppender.d.ts +++ b/public/panels/timeline/ThreadAppender.d.ts @@ -1,13 +1,13 @@ -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import { type CompatibilityTracksAppender, type HighlightedEntryInfo, type TrackAppender, type TrackAppenderName } from './CompatibilityTracksAppender.js'; export declare class ThreadAppender implements TrackAppender { #private; readonly appenderName: TrackAppenderName; - readonly threadType: TraceEngine.Handlers.Threads.ThreadType; + readonly threadType: Trace.Handlers.Threads.ThreadType; readonly isOnMainFrame: boolean; - constructor(compatibilityBuilder: CompatibilityTracksAppender, traceParsedData: TraceEngine.Handlers.Types.TraceParseData, processId: TraceEngine.Types.TraceEvents.ProcessID, threadId: TraceEngine.Types.TraceEvents.ThreadID, threadName: string | null, type: TraceEngine.Handlers.Threads.ThreadType); - processId(): TraceEngine.Types.TraceEvents.ProcessID; - threadId(): TraceEngine.Types.TraceEvents.ThreadID; + constructor(compatibilityBuilder: CompatibilityTracksAppender, parsedTrace: Trace.Handlers.Types.ParsedTrace, processId: Trace.Types.Events.ProcessID, threadId: Trace.Types.Events.ThreadID, threadName: string | null, type: Trace.Handlers.Threads.ThreadType); + processId(): Trace.Types.Events.ProcessID; + threadId(): Trace.Types.Events.ThreadID; /** * Appends into the flame chart data the data corresponding to the * this thread. @@ -23,20 +23,20 @@ export declare class ThreadAppender implements TrackAppender { headerAppended(): boolean; trackName(): string; getUrl(): string; - getEntries(): TraceEngine.Types.TraceEvents.TraceEventData[]; - isIgnoreListedEntry(entry: TraceEngine.Types.TraceEvents.TraceEventData): boolean; + getEntries(): Trace.Types.Events.Event[]; + isIgnoreListedEntry(entry: Trace.Types.Events.Event): boolean; private isIgnoreListedURL; /** * Gets the color an event added by this appender should be rendered with. */ - colorForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): string; + colorForEvent(event: Trace.Types.Events.Event): string; /** * Gets the title an event added by this appender should be rendered with. */ - titleForEvent(entry: TraceEngine.Types.TraceEvents.TraceEventData): string; + titleForEvent(entry: Trace.Types.Events.Event): string; /** * Returns the info shown when an event added by this appender * is hovered in the timeline. */ - highlightedEntryInfo(event: TraceEngine.Types.TraceEvents.TraceEventData): HighlightedEntryInfo; + highlightedEntryInfo(event: Trace.Types.Events.Event): HighlightedEntryInfo; } diff --git a/public/panels/timeline/ThreadAppender.js b/public/panels/timeline/ThreadAppender.js index 680ea3150..a2d537d0b 100644 --- a/public/panels/timeline/ThreadAppender.js +++ b/public/panels/timeline/ThreadAppender.js @@ -7,7 +7,7 @@ import * as Platform from '../../core/platform/platform.js'; import * as Root from '../../core/root/root.js'; import * as SDK from '../../core/sdk/sdk.js'; import * as Bindings from '../../models/bindings/bindings.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; import { addDecorationToEvent, buildGroupStyle, buildTrackHeader, getFormattedTime, } from './AppenderUtils.js'; import { entryIsVisibleInTimeline, } from './CompatibilityTracksAppender.js'; @@ -120,7 +120,7 @@ export class ThreadAppender { appenderName = 'Thread'; #colorGenerator; #compatibilityBuilder; - #traceParsedData; + #parsedTrace; #entries = []; #tree; #processId; @@ -128,12 +128,12 @@ export class ThreadAppender { #threadDefaultName; #expanded = false; #headerAppended = false; - threadType = "MAIN_THREAD" /* TraceEngine.Handlers.Threads.ThreadType.MAIN_THREAD */; + threadType = "MAIN_THREAD" /* Trace.Handlers.Threads.ThreadType.MAIN_THREAD */; isOnMainFrame; #showAllEventsEnabled = Root.Runtime.experiments.isEnabled('timeline-show-all-events'); #url = ''; #headerNestingLevel = null; - constructor(compatibilityBuilder, traceParsedData, processId, threadId, threadName, type) { + constructor(compatibilityBuilder, parsedTrace, processId, threadId, threadName, type) { this.#compatibilityBuilder = compatibilityBuilder; // TODO(crbug.com/1456706): // The values for this color generator have been taken from the old @@ -145,32 +145,32 @@ export class ThreadAppender { new Common.Color.Generator({ min: 30, max: 330, count: undefined }, { min: 50, max: 80, count: 3 }, 85); // Add a default color for call frames with no url. this.#colorGenerator.setColorForID('', '#f2ecdc'); - this.#traceParsedData = traceParsedData; + this.#parsedTrace = parsedTrace; this.#processId = processId; this.#threadId = threadId; // When loading a CPU profile, only CPU data will be available, thus // we get the data from the SamplesHandler. - const entries = type === "CPU_PROFILE" /* TraceEngine.Handlers.Threads.ThreadType.CPU_PROFILE */ ? - this.#traceParsedData.Samples?.profilesInProcess.get(processId)?.get(threadId)?.profileCalls : - this.#traceParsedData.Renderer?.processes.get(processId)?.threads?.get(threadId)?.entries; - const tree = type === "CPU_PROFILE" /* TraceEngine.Handlers.Threads.ThreadType.CPU_PROFILE */ ? - this.#traceParsedData.Samples?.profilesInProcess.get(processId)?.get(threadId)?.profileTree : - this.#traceParsedData.Renderer?.processes.get(processId)?.threads?.get(threadId)?.tree; + const entries = type === "CPU_PROFILE" /* Trace.Handlers.Threads.ThreadType.CPU_PROFILE */ ? + this.#parsedTrace.Samples?.profilesInProcess.get(processId)?.get(threadId)?.profileCalls : + this.#parsedTrace.Renderer?.processes.get(processId)?.threads?.get(threadId)?.entries; + const tree = type === "CPU_PROFILE" /* Trace.Handlers.Threads.ThreadType.CPU_PROFILE */ ? + this.#parsedTrace.Samples?.profilesInProcess.get(processId)?.get(threadId)?.profileTree : + this.#parsedTrace.Renderer?.processes.get(processId)?.threads?.get(threadId)?.tree; if (!entries || !tree) { throw new Error(`Could not find data for thread with id ${threadId} in process with id ${processId}`); } this.#entries = entries; this.#tree = tree; this.#threadDefaultName = threadName || i18nString(UIStrings.threadS, { PH1: threadId }); - this.isOnMainFrame = Boolean(this.#traceParsedData.Renderer?.processes.get(processId)?.isOnMainFrame); + this.isOnMainFrame = Boolean(this.#parsedTrace.Renderer?.processes.get(processId)?.isOnMainFrame); this.threadType = type; // AuctionWorklets are threads, so we re-use this appender rather than // duplicate it, but we change the name because we want to render these // lower down than other threads. - if (this.#traceParsedData.AuctionWorklets.worklets.has(processId)) { + if (this.#parsedTrace.AuctionWorklets.worklets.has(processId)) { this.appenderName = 'Thread_AuctionWorklet'; } - this.#url = this.#traceParsedData.Renderer?.processes.get(this.#processId)?.url || ''; + this.#url = this.#parsedTrace.Renderer?.processes.get(this.#processId)?.url || ''; } processId() { return this.#processId; @@ -207,8 +207,8 @@ export class ThreadAppender { if (this.#headerAppended) { return; } - if (this.threadType === "RASTERIZER" /* TraceEngine.Handlers.Threads.ThreadType.RASTERIZER */ || - this.threadType === "THREAD_POOL" /* TraceEngine.Handlers.Threads.ThreadType.THREAD_POOL */) { + if (this.threadType === "RASTERIZER" /* Trace.Handlers.Threads.ThreadType.RASTERIZER */ || + this.threadType === "THREAD_POOL" /* Trace.Handlers.Threads.ThreadType.THREAD_POOL */) { this.#appendGroupedTrackHeaderAndTitle(trackStartLevel, this.threadType); } else { @@ -244,19 +244,19 @@ export class ThreadAppender { } #visualLoggingNameForThread() { switch (this.threadType) { - case "MAIN_THREAD" /* TraceEngine.Handlers.Threads.ThreadType.MAIN_THREAD */: + case "MAIN_THREAD" /* Trace.Handlers.Threads.ThreadType.MAIN_THREAD */: return this.isOnMainFrame ? "thread.main" /* VisualLoggingTrackName.THREAD_MAIN */ : "thread.frame" /* VisualLoggingTrackName.THREAD_FRAME */; - case "WORKER" /* TraceEngine.Handlers.Threads.ThreadType.WORKER */: + case "WORKER" /* Trace.Handlers.Threads.ThreadType.WORKER */: return "thread.worker" /* VisualLoggingTrackName.THREAD_WORKER */; - case "RASTERIZER" /* TraceEngine.Handlers.Threads.ThreadType.RASTERIZER */: + case "RASTERIZER" /* Trace.Handlers.Threads.ThreadType.RASTERIZER */: return "thread.rasterizer" /* VisualLoggingTrackName.THREAD_RASTERIZER */; - case "AUCTION_WORKLET" /* TraceEngine.Handlers.Threads.ThreadType.AUCTION_WORKLET */: + case "AUCTION_WORKLET" /* Trace.Handlers.Threads.ThreadType.AUCTION_WORKLET */: return "thread.auction-worklet" /* VisualLoggingTrackName.THREAD_AUCTION_WORKLET */; - case "OTHER" /* TraceEngine.Handlers.Threads.ThreadType.OTHER */: + case "OTHER" /* Trace.Handlers.Threads.ThreadType.OTHER */: return "thread.other" /* VisualLoggingTrackName.THREAD_OTHER */; - case "CPU_PROFILE" /* TraceEngine.Handlers.Threads.ThreadType.CPU_PROFILE */: + case "CPU_PROFILE" /* Trace.Handlers.Threads.ThreadType.CPU_PROFILE */: return "thread.cpu-profile" /* VisualLoggingTrackName.THREAD_CPU_PROFILE */; - case "THREAD_POOL" /* TraceEngine.Handlers.Threads.ThreadType.THREAD_POOL */: + case "THREAD_POOL" /* Trace.Handlers.Threads.ThreadType.THREAD_POOL */: return "thread.pool" /* VisualLoggingTrackName.THREAD_POOL */; default: return null; @@ -280,7 +280,7 @@ export class ThreadAppender { // Nesting is set to 1 because the track is appended inside the // header for all raster threads. const titleStyle = buildGroupStyle({ padding: 2, nestingLevel: 1, collapsible: false }); - const rasterizerTitle = this.threadType === "RASTERIZER" /* TraceEngine.Handlers.Threads.ThreadType.RASTERIZER */ ? + const rasterizerTitle = this.threadType === "RASTERIZER" /* Trace.Handlers.Threads.ThreadType.RASTERIZER */ ? i18nString(UIStrings.rasterizerThreadS, { PH1: currentTrackCount + 1 }) : i18nString(UIStrings.threadPoolThreadS, { PH1: currentTrackCount + 1 }); const visualLoggingName = this.#visualLoggingNameForThread(); @@ -290,32 +290,32 @@ export class ThreadAppender { trackName() { let threadTypeLabel = null; switch (this.threadType) { - case "MAIN_THREAD" /* TraceEngine.Handlers.Threads.ThreadType.MAIN_THREAD */: + case "MAIN_THREAD" /* Trace.Handlers.Threads.ThreadType.MAIN_THREAD */: threadTypeLabel = this.isOnMainFrame ? i18nString(UIStrings.mainS, { PH1: this.#url }) : i18nString(UIStrings.frameS, { PH1: this.#url }); break; - case "CPU_PROFILE" /* TraceEngine.Handlers.Threads.ThreadType.CPU_PROFILE */: + case "CPU_PROFILE" /* Trace.Handlers.Threads.ThreadType.CPU_PROFILE */: threadTypeLabel = i18nString(UIStrings.main); break; - case "WORKER" /* TraceEngine.Handlers.Threads.ThreadType.WORKER */: + case "WORKER" /* Trace.Handlers.Threads.ThreadType.WORKER */: threadTypeLabel = this.#buildNameForWorker(); break; - case "RASTERIZER" /* TraceEngine.Handlers.Threads.ThreadType.RASTERIZER */: + case "RASTERIZER" /* Trace.Handlers.Threads.ThreadType.RASTERIZER */: threadTypeLabel = i18nString(UIStrings.raster); break; - case "THREAD_POOL" /* TraceEngine.Handlers.Threads.ThreadType.THREAD_POOL */: + case "THREAD_POOL" /* Trace.Handlers.Threads.ThreadType.THREAD_POOL */: threadTypeLabel = i18nString(UIStrings.threadPool); break; - case "OTHER" /* TraceEngine.Handlers.Threads.ThreadType.OTHER */: + case "OTHER" /* Trace.Handlers.Threads.ThreadType.OTHER */: break; - case "AUCTION_WORKLET" /* TraceEngine.Handlers.Threads.ThreadType.AUCTION_WORKLET */: + case "AUCTION_WORKLET" /* Trace.Handlers.Threads.ThreadType.AUCTION_WORKLET */: threadTypeLabel = this.#buildNameForAuctionWorklet(); break; default: return Platform.assertNever(this.threadType, `Unknown thread type: ${this.threadType}`); } let suffix = ''; - if (this.#traceParsedData.Meta.traceIsGeneric) { + if (this.#parsedTrace.Meta.traceIsGeneric) { suffix = suffix + ` (${this.threadId()})`; } return (threadTypeLabel || this.#threadDefaultName) + suffix; @@ -327,7 +327,7 @@ export class ThreadAppender { return this.#entries; } #buildNameForAuctionWorklet() { - const workletMetadataEvent = this.#traceParsedData.AuctionWorklets.worklets.get(this.#processId); + const workletMetadataEvent = this.#parsedTrace.AuctionWorklets.worklets.get(this.#processId); // We should always have this event - if we do not, we were instantiated with invalid data. if (!workletMetadataEvent) { return i18nString(UIStrings.unknownWorklet); @@ -358,13 +358,13 @@ export class ThreadAppender { } if (isBidderOrSeller) { switch (workletMetadataEvent.type) { - case "seller" /* TraceEngine.Types.TraceEvents.AuctionWorkletType.SELLER */: + case "seller" /* Trace.Types.Events.AuctionWorkletType.SELLER */: return shouldAddHost ? i18nString(UIStrings.sellerWorkletS, { PH1: host }) : i18nString(UIStrings.sellerWorklet); - case "bidder" /* TraceEngine.Types.TraceEvents.AuctionWorkletType.BIDDER */: + case "bidder" /* Trace.Types.Events.AuctionWorkletType.BIDDER */: return shouldAddHost ? i18nString(UIStrings.bidderWorkletS, { PH1: host }) : i18nString(UIStrings.bidderWorklet); - case "unknown" /* TraceEngine.Types.TraceEvents.AuctionWorkletType.UNKNOWN */: + case "unknown" /* Trace.Types.Events.AuctionWorkletType.UNKNOWN */: return shouldAddHost ? i18nString(UIStrings.unknownWorkletS, { PH1: host }) : i18nString(UIStrings.unknownWorklet); default: @@ -375,9 +375,9 @@ export class ThreadAppender { return shouldAddHost ? i18nString(UIStrings.unknownWorkletS, { PH1: host }) : i18nString(UIStrings.unknownWorklet); } #buildNameForWorker() { - const url = this.#traceParsedData.Renderer?.processes.get(this.#processId)?.url || ''; - const workerId = this.#traceParsedData.Workers.workerIdByThread.get(this.#threadId); - const workerURL = workerId ? this.#traceParsedData.Workers.workerURLById.get(workerId) : url; + const url = this.#parsedTrace.Renderer?.processes.get(this.#processId)?.url || ''; + const workerId = this.#parsedTrace.Workers.workerIdByThread.get(this.#threadId); + const workerURL = workerId ? this.#parsedTrace.Workers.workerURLById.get(workerId) : url; // Try to create a name using the worker url if present. If not, use a generic label. let workerName = workerURL ? i18nString(UIStrings.workerS, { PH1: workerURL }) : i18nString(UIStrings.dedicatedWorker); const workerTarget = workerId !== undefined && SDK.TargetManager.TargetManager.instance().targetById(workerId); @@ -424,7 +424,7 @@ export class ThreadAppender { // large). To avoid the extra cost we add the check in the // traversal we already need to append events. const entryIsVisible = !invisibleEntries.includes(entry) && - (entryIsVisibleInTimeline(entry, this.#traceParsedData) || this.#showAllEventsEnabled); + (entryIsVisibleInTimeline(entry, this.#parsedTrace) || this.#showAllEventsEnabled); // For ignore listing support, these two conditions need to be met // to not append a profile call to the flame chart: // 1. It is ignore listed @@ -457,7 +457,7 @@ export class ThreadAppender { if (ModificationsManager.ModificationsManager.activeManager()?.getEntriesFilter().isEntryExpandable(entry)) { addDecorationToEvent(flameChartData, index, { type: "HIDDEN_DESCENDANTS_ARROW" /* PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW */ }); } - const warnings = this.#traceParsedData.Warnings.perEvent.get(entry); + const warnings = this.#parsedTrace.Warnings.perEvent.get(entry); if (!warnings) { return; } @@ -467,11 +467,11 @@ export class ThreadAppender { } addDecorationToEvent(flameChartData, index, { type: "CANDY" /* PerfUI.FlameChart.FlameChartDecorationType.CANDY */, - startAtTime: TraceEngine.Handlers.ModelHandlers.Warnings.LONG_MAIN_THREAD_TASK_THRESHOLD, + startAtTime: Trace.Handlers.ModelHandlers.Warnings.LONG_MAIN_THREAD_TASK_THRESHOLD, }); } isIgnoreListedEntry(entry) { - if (!TraceEngine.Types.TraceEvents.isProfileCall(entry)) { + if (!Trace.Types.Events.isProfileCall(entry)) { return false; } const url = entry.callFrame.url; @@ -490,10 +490,10 @@ export class ThreadAppender { * Gets the color an event added by this appender should be rendered with. */ colorForEvent(event) { - if (this.#traceParsedData.Meta.traceIsGeneric) { + if (this.#parsedTrace.Meta.traceIsGeneric) { return event.name ? `hsl(${Platform.StringUtilities.hashCode(event.name) % 300 + 30}, 40%, 70%)` : '#ccc'; } - if (TraceEngine.Types.TraceEvents.isProfileCall(event)) { + if (Trace.Types.Events.isProfileCall(event)) { if (event.callFrame.functionName === '(idle)') { return Components.EntryStyles.getCategoryStyles().idle.getComputedColorValue(); } @@ -505,8 +505,7 @@ export class ThreadAppender { // Otherwise, return a color created based on its URL. return this.#colorGenerator.colorForID(event.callFrame.url); } - const defaultColor = Components.EntryStyles.getEventStyle(event.name) - ?.category.getComputedColorValue(); + const defaultColor = Components.EntryStyles.getEventStyle(event.name)?.category.getComputedColorValue(); return defaultColor || Components.EntryStyles.getCategoryStyles().other.getComputedColorValue(); } /** @@ -516,7 +515,7 @@ export class ThreadAppender { if (this.isIgnoreListedEntry(entry)) { return i18nString(UIStrings.onIgnoreList); } - return Components.EntryName.nameForEntry(entry, this.#traceParsedData); + return Components.EntryName.nameForEntry(entry, this.#parsedTrace); } /** * Returns the info shown when an event added by this appender @@ -524,7 +523,7 @@ export class ThreadAppender { */ highlightedEntryInfo(event) { let title = this.titleForEvent(event); - if (TraceEngine.Types.TraceEvents.isTraceEventParseHTML(event)) { + if (Trace.Types.Events.isParseHTML(event)) { const startLine = event.args['beginData']['startLine']; const endLine = event.args['endData'] && event.args['endData']['endLine']; const eventURL = event.args['beginData']['url']; @@ -532,7 +531,7 @@ export class ThreadAppender { const range = (endLine !== -1 || endLine === startLine) ? `${startLine}...${endLine}` : startLine; title += ` - ${url} [${range}]`; } - const selfTime = this.#traceParsedData.Renderer.entryToNode.get(event)?.selfTime; + const selfTime = this.#parsedTrace.Renderer.entryToNode.get(event)?.selfTime; return { title, formattedTime: getFormattedTime(event.dur, selfTime) }; } } diff --git a/public/panels/timeline/ThreadAppender.js.map b/public/panels/timeline/ThreadAppender.js.map index 1f90ad926..f789f16a1 100644 --- a/public/panels/timeline/ThreadAppender.js.map +++ b/public/panels/timeline/ThreadAppender.js.map @@ -1 +1 @@ -{"version":3,"file":"ThreadAppender.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/ThreadAppender.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as Root from '../../core/root/root.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as Bindings from '../../models/bindings/bindings.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\n\nimport {\n addDecorationToEvent,\n buildGroupStyle,\n buildTrackHeader,\n getFormattedTime,\n} from './AppenderUtils.js';\nimport {\n type CompatibilityTracksAppender,\n entryIsVisibleInTimeline,\n type HighlightedEntryInfo,\n type TrackAppender,\n type TrackAppenderName,\n VisualLoggingTrackName,\n} from './CompatibilityTracksAppender.js';\nimport * as Components from './components/components.js';\nimport * as ModificationsManager from './ModificationsManager.js';\n\nconst UIStrings = {\n /**\n *@description Text shown for an entry in the flame chart that is ignored because it matches\n * a predefined ignore list.\n */\n onIgnoreList: 'On ignore list',\n /**\n * @description Refers to the \"Main frame\", meaning the top level frame. See https://www.w3.org/TR/html401/present/frames.html\n * @example{example.com} PH1\n */\n mainS: 'Main — {PH1}',\n /**\n * @description Refers to the main thread of execution of a program. See https://developer.mozilla.org/en-US/docs/Glossary/Main_thread\n */\n main: 'Main',\n /**\n * @description Refers to any frame in the page. See https://www.w3.org/TR/html401/present/frames.html\n * @example {https://example.com} PH1\n */\n frameS: 'Frame — {PH1}',\n /**\n *@description A web worker in the page. See https://developer.mozilla.org/en-US/docs/Web/API/Worker\n *@example {https://google.com} PH1\n */\n workerS: '`Worker` — {PH1}',\n /**\n *@description A web worker in the page. See https://developer.mozilla.org/en-US/docs/Web/API/Worker\n *@example {FormatterWorker} PH1\n *@example {https://google.com} PH2\n */\n workerSS: '`Worker`: {PH1} — {PH2}',\n /**\n *@description Label for a web worker exclusively allocated for a purpose.\n */\n dedicatedWorker: 'Dedicated `Worker`',\n /**\n *@description A generic name given for a thread running in the browser (sequence of programmed instructions).\n * The placeholder is an enumeration given to the thread.\n *@example {1} PH1\n */\n threadS: 'Thread {PH1}',\n /**\n *@description Rasterization in computer graphics.\n */\n raster: 'Raster',\n /**\n *@description Threads used for background tasks.\n */\n threadPool: 'Thread pool',\n /**\n *@description Name for a thread that rasterizes graphics in a website.\n *@example {2} PH1\n */\n rasterizerThreadS: 'Rasterizer thread {PH1}',\n /**\n *@description Text in Timeline Flame Chart Data Provider of the Performance panel\n *@example {2} PH1\n */\n threadPoolThreadS: 'Thread pool worker {PH1}',\n /**\n *@description Title of a bidder auction worklet with known URL in the timeline flame chart of the Performance panel\n *@example {https://google.com} PH1\n */\n bidderWorkletS: 'Bidder Worklet — {PH1}',\n /**\n *@description Title of a bidder auction worklet in the timeline flame chart of the Performance panel with an unknown URL\n */\n bidderWorklet: 'Bidder Worklet',\n\n /**\n *@description Title of a seller auction worklet in the timeline flame chart of the Performance panel with an unknown URL\n */\n sellerWorklet: 'Seller Worklet',\n\n /**\n *@description Title of an auction worklet in the timeline flame chart of the Performance panel with an unknown URL\n */\n unknownWorklet: 'Auction Worklet',\n\n /**\n *@description Title of control thread of a service process for an auction worklet in the timeline flame chart of the Performance panel with an unknown URL\n */\n workletService: 'Auction Worklet service',\n\n /**\n *@description Title of a seller auction worklet with known URL in the timeline flame chart of the Performance panel\n *@example {https://google.com} PH1\n */\n sellerWorkletS: 'Seller Worklet — {PH1}',\n\n /**\n *@description Title of an auction worklet with known URL in the timeline flame chart of the Performance panel\n *@example {https://google.com} PH1\n */\n unknownWorkletS: 'Auction Worklet — {PH1}',\n\n /**\n *@description Title of control thread of a service process for an auction worklet with known URL in the timeline flame chart of the Performance panel\n * @example {https://google.com} PH1\n */\n workletServiceS: 'Auction Worklet service — {PH1}',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/ThreadAppender.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\n// This appender is only triggered when the Renderer handler is run. At\n// the moment this only happens in the basic component server example.\n// In the future, once this appender fully supports the behaviour of the\n// old engine's thread/sync tracks we can always run it by enabling the\n// Renderer and Samples handler by default.\nexport class ThreadAppender implements TrackAppender {\n readonly appenderName: TrackAppenderName = 'Thread';\n\n #colorGenerator: Common.Color.Generator;\n #compatibilityBuilder: CompatibilityTracksAppender;\n #traceParsedData: TraceEngine.Handlers.Types.TraceParseData;\n\n #entries: TraceEngine.Types.TraceEvents.TraceEventData[] = [];\n #tree: TraceEngine.Helpers.TreeHelpers.TraceEntryTree;\n #processId: TraceEngine.Types.TraceEvents.ProcessID;\n #threadId: TraceEngine.Types.TraceEvents.ThreadID;\n #threadDefaultName: string;\n #expanded = false;\n #headerAppended: boolean = false;\n readonly threadType: TraceEngine.Handlers.Threads.ThreadType = TraceEngine.Handlers.Threads.ThreadType.MAIN_THREAD;\n readonly isOnMainFrame: boolean;\n #showAllEventsEnabled = Root.Runtime.experiments.isEnabled('timeline-show-all-events');\n #url: string = '';\n #headerNestingLevel: number|null = null;\n constructor(\n compatibilityBuilder: CompatibilityTracksAppender, traceParsedData: TraceEngine.Handlers.Types.TraceParseData,\n processId: TraceEngine.Types.TraceEvents.ProcessID, threadId: TraceEngine.Types.TraceEvents.ThreadID,\n threadName: string|null, type: TraceEngine.Handlers.Threads.ThreadType) {\n this.#compatibilityBuilder = compatibilityBuilder;\n // TODO(crbug.com/1456706):\n // The values for this color generator have been taken from the old\n // engine to keep the colors the same after the migration. This\n // generator is used here to create colors for js frames (profile\n // calls) in the flamechart by hashing the script's url. We might\n // need to reconsider this generator when migrating to GM3 colors.\n this.#colorGenerator =\n new Common.Color.Generator({min: 30, max: 330, count: undefined}, {min: 50, max: 80, count: 3}, 85);\n // Add a default color for call frames with no url.\n this.#colorGenerator.setColorForID('', '#f2ecdc');\n this.#traceParsedData = traceParsedData;\n this.#processId = processId;\n this.#threadId = threadId;\n\n // When loading a CPU profile, only CPU data will be available, thus\n // we get the data from the SamplesHandler.\n const entries = type === TraceEngine.Handlers.Threads.ThreadType.CPU_PROFILE ?\n this.#traceParsedData.Samples?.profilesInProcess.get(processId)?.get(threadId)?.profileCalls :\n this.#traceParsedData.Renderer?.processes.get(processId)?.threads?.get(threadId)?.entries;\n const tree = type === TraceEngine.Handlers.Threads.ThreadType.CPU_PROFILE ?\n this.#traceParsedData.Samples?.profilesInProcess.get(processId)?.get(threadId)?.profileTree :\n this.#traceParsedData.Renderer?.processes.get(processId)?.threads?.get(threadId)?.tree;\n if (!entries || !tree) {\n throw new Error(`Could not find data for thread with id ${threadId} in process with id ${processId}`);\n }\n this.#entries = entries;\n this.#tree = tree;\n this.#threadDefaultName = threadName || i18nString(UIStrings.threadS, {PH1: threadId});\n this.isOnMainFrame = Boolean(this.#traceParsedData.Renderer?.processes.get(processId)?.isOnMainFrame);\n this.threadType = type;\n // AuctionWorklets are threads, so we re-use this appender rather than\n // duplicate it, but we change the name because we want to render these\n // lower down than other threads.\n if (this.#traceParsedData.AuctionWorklets.worklets.has(processId)) {\n this.appenderName = 'Thread_AuctionWorklet';\n }\n this.#url = this.#traceParsedData.Renderer?.processes.get(this.#processId)?.url || '';\n }\n\n processId(): TraceEngine.Types.TraceEvents.ProcessID {\n return this.#processId;\n }\n\n threadId(): TraceEngine.Types.TraceEvents.ThreadID {\n return this.#threadId;\n }\n\n /**\n * Appends into the flame chart data the data corresponding to the\n * this thread.\n * @param trackStartLevel the horizontal level of the flame chart events where\n * the track's events will start being appended.\n * @param expanded wether the track should be rendered expanded.\n * @returns the first available level to append more data after having\n * appended the track's events.\n */\n appendTrackAtLevel(trackStartLevel: number, expanded: boolean = false): number {\n if (this.#entries.length === 0) {\n return trackStartLevel;\n }\n this.#expanded = expanded;\n return this.#appendTreeAtLevel(trackStartLevel);\n }\n\n setHeaderNestingLevel(level: number): void {\n this.#headerNestingLevel = level;\n }\n /**\n * Track header is appended only if there are events visible on it.\n * Otherwise we don't append any track. So, instead of preemptively\n * appending a track before appending its events, we only do so once\n * we have detected that the track contains an event that is visible.\n */\n #ensureTrackHeaderAppended(trackStartLevel: number): void {\n if (this.#headerAppended) {\n return;\n }\n if (this.threadType === TraceEngine.Handlers.Threads.ThreadType.RASTERIZER ||\n this.threadType === TraceEngine.Handlers.Threads.ThreadType.THREAD_POOL) {\n this.#appendGroupedTrackHeaderAndTitle(trackStartLevel, this.threadType);\n } else {\n this.#appendTrackHeaderAtLevel(trackStartLevel);\n }\n this.#headerAppended = true;\n }\n\n setHeaderAppended(headerAppended: boolean): void {\n this.#headerAppended = headerAppended;\n }\n\n headerAppended(): boolean {\n return this.#headerAppended;\n }\n\n /**\n * Adds into the flame chart data the header corresponding to this\n * thread. A header is added in the shape of a group in the flame\n * chart data. A group has a predefined style and a reference to the\n * definition of the legacy track (which should be removed in the\n * future).\n * @param currentLevel the flame chart level at which the header is\n * appended.\n */\n #appendTrackHeaderAtLevel(currentLevel: number): void {\n const trackIsCollapsible = this.#entries.length > 0;\n const style = buildGroupStyle({shareHeaderLine: false, collapsible: trackIsCollapsible});\n if (this.#headerNestingLevel !== null) {\n style.nestingLevel = this.#headerNestingLevel;\n }\n const visualLoggingName = this.#visualLoggingNameForThread();\n const group = buildTrackHeader(\n visualLoggingName, currentLevel, this.trackName(), style, /* selectable= */ true, this.#expanded,\n /* showStackContextMenu= */ true);\n this.#compatibilityBuilder.registerTrackForGroup(group, this);\n }\n\n #visualLoggingNameForThread(): VisualLoggingTrackName|null {\n switch (this.threadType) {\n case TraceEngine.Handlers.Threads.ThreadType.MAIN_THREAD:\n return this.isOnMainFrame ? VisualLoggingTrackName.THREAD_MAIN : VisualLoggingTrackName.THREAD_FRAME;\n case TraceEngine.Handlers.Threads.ThreadType.WORKER:\n return VisualLoggingTrackName.THREAD_WORKER;\n case TraceEngine.Handlers.Threads.ThreadType.RASTERIZER:\n return VisualLoggingTrackName.THREAD_RASTERIZER;\n case TraceEngine.Handlers.Threads.ThreadType.AUCTION_WORKLET:\n return VisualLoggingTrackName.THREAD_AUCTION_WORKLET;\n case TraceEngine.Handlers.Threads.ThreadType.OTHER:\n return VisualLoggingTrackName.THREAD_OTHER;\n case TraceEngine.Handlers.Threads.ThreadType.CPU_PROFILE:\n return VisualLoggingTrackName.THREAD_CPU_PROFILE;\n case TraceEngine.Handlers.Threads.ThreadType.THREAD_POOL:\n return VisualLoggingTrackName.THREAD_POOL;\n default:\n return null;\n }\n }\n /**\n * Raster threads are rendered under a single header in the\n * flamechart. However, each thread has a unique title which needs to\n * be added to the flamechart data.\n */\n #appendGroupedTrackHeaderAndTitle(\n trackStartLevel: number,\n threadType: TraceEngine.Handlers.Threads.ThreadType.RASTERIZER|\n TraceEngine.Handlers.Threads.ThreadType.THREAD_POOL): void {\n const currentTrackCount = this.#compatibilityBuilder.getCurrentTrackCountForThreadType(threadType);\n if (currentTrackCount === 0) {\n const trackIsCollapsible = this.#entries.length > 0;\n const headerStyle = buildGroupStyle({shareHeaderLine: false, collapsible: trackIsCollapsible});\n\n // Don't set any jslogcontext (first argument) because this is a shared\n // header group. Each child will have its context set.\n const headerGroup = buildTrackHeader(\n null, trackStartLevel, this.trackName(), headerStyle, /* selectable= */ false, this.#expanded);\n this.#compatibilityBuilder.getFlameChartTimelineData().groups.push(headerGroup);\n }\n\n // Nesting is set to 1 because the track is appended inside the\n // header for all raster threads.\n const titleStyle = buildGroupStyle({padding: 2, nestingLevel: 1, collapsible: false});\n const rasterizerTitle = this.threadType === TraceEngine.Handlers.Threads.ThreadType.RASTERIZER ?\n i18nString(UIStrings.rasterizerThreadS, {PH1: currentTrackCount + 1}) :\n i18nString(UIStrings.threadPoolThreadS, {PH1: currentTrackCount + 1});\n\n const visualLoggingName = this.#visualLoggingNameForThread();\n const titleGroup = buildTrackHeader(\n visualLoggingName, trackStartLevel, rasterizerTitle, titleStyle, /* selectable= */ true, this.#expanded);\n this.#compatibilityBuilder.registerTrackForGroup(titleGroup, this);\n }\n\n trackName(): string {\n let threadTypeLabel: string|null = null;\n switch (this.threadType) {\n case TraceEngine.Handlers.Threads.ThreadType.MAIN_THREAD:\n threadTypeLabel = this.isOnMainFrame ? i18nString(UIStrings.mainS, {PH1: this.#url}) :\n i18nString(UIStrings.frameS, {PH1: this.#url});\n break;\n case TraceEngine.Handlers.Threads.ThreadType.CPU_PROFILE:\n threadTypeLabel = i18nString(UIStrings.main);\n break;\n case TraceEngine.Handlers.Threads.ThreadType.WORKER:\n threadTypeLabel = this.#buildNameForWorker();\n break;\n case TraceEngine.Handlers.Threads.ThreadType.RASTERIZER:\n threadTypeLabel = i18nString(UIStrings.raster);\n break;\n case TraceEngine.Handlers.Threads.ThreadType.THREAD_POOL:\n threadTypeLabel = i18nString(UIStrings.threadPool);\n break;\n case TraceEngine.Handlers.Threads.ThreadType.OTHER:\n break;\n case TraceEngine.Handlers.Threads.ThreadType.AUCTION_WORKLET:\n threadTypeLabel = this.#buildNameForAuctionWorklet();\n break;\n default:\n return Platform.assertNever(this.threadType, `Unknown thread type: ${this.threadType}`);\n }\n let suffix = '';\n if (this.#traceParsedData.Meta.traceIsGeneric) {\n suffix = suffix + ` (${this.threadId()})`;\n }\n return (threadTypeLabel || this.#threadDefaultName) + suffix;\n }\n\n getUrl(): string {\n return this.#url;\n }\n\n getEntries(): TraceEngine.Types.TraceEvents.TraceEventData[] {\n return this.#entries;\n }\n\n #buildNameForAuctionWorklet(): string {\n const workletMetadataEvent = this.#traceParsedData.AuctionWorklets.worklets.get(this.#processId);\n // We should always have this event - if we do not, we were instantiated with invalid data.\n if (!workletMetadataEvent) {\n return i18nString(UIStrings.unknownWorklet);\n }\n\n // Host could be empty - in which case we do not want to add it.\n const host = workletMetadataEvent.host ? `https://${workletMetadataEvent.host}` : '';\n const shouldAddHost = host.length > 0;\n\n // For each Auction Worklet in a page there are two threads we care about on the same process.\n // 1. The \"Worklet Service\" which is a generic helper service. This thread\n // is always named \"auction_worklet.CrUtilityMain\".\n //\n // 2. The \"Seller/Bidder\" service. This thread is always named\n // \"AuctionV8HelperThread\". The AuctionWorkets handler does the job of\n // figuring this out for us - the metadata event it provides for each\n // worklet process will have a `type` already set.\n //\n // Therefore, for this given thread, which we know is part of\n // an AuctionWorklet process, we need to figure out if this thread is the\n // generic service, or a seller/bidder worklet.\n //\n // Note that the worklet could also have the \"unknown\" type - this is not\n // expected but implemented to prevent trace event changes causing DevTools\n // to break with unknown worklet types.\n const isUtilityThread = workletMetadataEvent.args.data.utilityThread.tid === this.#threadId;\n const isBidderOrSeller = workletMetadataEvent.args.data.v8HelperThread.tid === this.#threadId;\n\n if (isUtilityThread) {\n return shouldAddHost ? i18nString(UIStrings.workletServiceS, {PH1: host}) : i18nString(UIStrings.workletService);\n }\n\n if (isBidderOrSeller) {\n switch (workletMetadataEvent.type) {\n case TraceEngine.Types.TraceEvents.AuctionWorkletType.SELLER:\n return shouldAddHost ? i18nString(UIStrings.sellerWorkletS, {PH1: host}) :\n i18nString(UIStrings.sellerWorklet);\n case TraceEngine.Types.TraceEvents.AuctionWorkletType.BIDDER:\n return shouldAddHost ? i18nString(UIStrings.bidderWorkletS, {PH1: host}) :\n i18nString(UIStrings.bidderWorklet);\n case TraceEngine.Types.TraceEvents.AuctionWorkletType.UNKNOWN:\n return shouldAddHost ? i18nString(UIStrings.unknownWorkletS, {PH1: host}) :\n i18nString(UIStrings.unknownWorklet);\n default:\n Platform.assertNever(\n workletMetadataEvent.type, `Unexpected Auction Worklet Type ${workletMetadataEvent.type}`);\n }\n }\n // We should never reach here, but just in case!\n return shouldAddHost ? i18nString(UIStrings.unknownWorkletS, {PH1: host}) : i18nString(UIStrings.unknownWorklet);\n }\n\n #buildNameForWorker(): string {\n const url = this.#traceParsedData.Renderer?.processes.get(this.#processId)?.url || '';\n const workerId = this.#traceParsedData.Workers.workerIdByThread.get(this.#threadId);\n const workerURL = workerId ? this.#traceParsedData.Workers.workerURLById.get(workerId) : url;\n // Try to create a name using the worker url if present. If not, use a generic label.\n let workerName =\n workerURL ? i18nString(UIStrings.workerS, {PH1: workerURL}) : i18nString(UIStrings.dedicatedWorker);\n const workerTarget = workerId !== undefined && SDK.TargetManager.TargetManager.instance().targetById(workerId);\n if (workerTarget) {\n // Get the worker name from the target, which corresponds to the name\n // assigned to the worker when it was constructed.\n workerName = i18nString(UIStrings.workerSS, {PH1: workerTarget.name(), PH2: url});\n }\n return workerName;\n }\n\n /**\n * Adds into the flame chart data the entries of this thread, which\n * includes trace events and JS calls.\n * @param currentLevel the flame chart level from which entries will\n * be appended.\n * @returns the next level after the last occupied by the appended\n * entries (the first available level to append more data).\n */\n #appendTreeAtLevel(trackStartLevel: number): number {\n // We can not used the tree maxDepth in the tree from the\n // RendererHandler because ignore listing and visibility of events\n // alter the final depth of the flame chart.\n return this.#appendNodesAtLevel(this.#tree.roots, trackStartLevel);\n }\n\n /**\n * Traverses the trees formed by the provided nodes in breadth first\n * fashion and appends each node's entry on each iteration. As each\n * entry is handled, a check for the its visibility or if it's ignore\n * listed is done before appending.\n */\n #appendNodesAtLevel(\n nodes: Iterable, startingLevel: number,\n parentIsIgnoredListed: boolean = false): number {\n const invisibleEntries =\n ModificationsManager.ModificationsManager.activeManager()?.getEntriesFilter().invisibleEntries() ?? [];\n let maxDepthInTree = startingLevel;\n for (const node of nodes) {\n let nextLevel = startingLevel;\n const entry = node.entry;\n const entryIsIgnoreListed = this.isIgnoreListedEntry(entry);\n // Events' visibility is determined from their predefined styles,\n // which is something that's not available in the engine data.\n // Thus it needs to be checked in the appenders, but preemptively\n // checking if there are visible events and returning early if not\n // is potentially expensive since, in theory, we would be adding\n // another traversal to the entries array (which could grow\n // large). To avoid the extra cost we add the check in the\n // traversal we already need to append events.\n const entryIsVisible = !invisibleEntries.includes(entry) &&\n (entryIsVisibleInTimeline(entry, this.#traceParsedData) || this.#showAllEventsEnabled);\n // For ignore listing support, these two conditions need to be met\n // to not append a profile call to the flame chart:\n // 1. It is ignore listed\n // 2. It is NOT the bottom-most call in an ignore listed stack (a\n // set of chained profile calls that belong to ignore listed\n // URLs).\n // This means that all of the ignore listed calls are ignored (not\n // appended), except if it is the bottom call of an ignored stack.\n // This is becaue to represent ignore listed stack frames, we add\n // a flame chart entry with the length and position of the bottom\n // frame, which is distictively marked to denote an ignored listed\n // stack.\n const skipEventDueToIgnoreListing = entryIsIgnoreListed && parentIsIgnoredListed;\n if (entryIsVisible && !skipEventDueToIgnoreListing) {\n this.#appendEntryAtLevel(entry, startingLevel);\n nextLevel++;\n }\n\n const depthInChildTree = this.#appendNodesAtLevel(node.children, nextLevel, entryIsIgnoreListed);\n maxDepthInTree = Math.max(depthInChildTree, maxDepthInTree);\n }\n return maxDepthInTree;\n }\n\n #appendEntryAtLevel(entry: TraceEngine.Types.TraceEvents.TraceEventData, level: number): void {\n this.#ensureTrackHeaderAppended(level);\n const index = this.#compatibilityBuilder.appendEventAtLevel(entry, level, this);\n this.#addDecorationsToEntry(entry, index);\n }\n\n #addDecorationsToEntry(entry: TraceEngine.Types.TraceEvents.TraceEventData, index: number): void {\n const flameChartData = this.#compatibilityBuilder.getFlameChartTimelineData();\n if (ModificationsManager.ModificationsManager.activeManager()?.getEntriesFilter().isEntryExpandable(entry)) {\n addDecorationToEvent(\n flameChartData, index, {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW});\n }\n const warnings = this.#traceParsedData.Warnings.perEvent.get(entry);\n if (!warnings) {\n return;\n }\n addDecorationToEvent(flameChartData, index, {type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE});\n if (!warnings.includes('LONG_TASK')) {\n return;\n }\n addDecorationToEvent(flameChartData, index, {\n type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,\n startAtTime: TraceEngine.Handlers.ModelHandlers.Warnings.LONG_MAIN_THREAD_TASK_THRESHOLD,\n });\n }\n\n isIgnoreListedEntry(entry: TraceEngine.Types.TraceEvents.TraceEventData): boolean {\n if (!TraceEngine.Types.TraceEvents.isProfileCall(entry)) {\n return false;\n }\n const url = entry.callFrame.url as Platform.DevToolsPath.UrlString;\n return url && this.isIgnoreListedURL(url);\n }\n\n private isIgnoreListedURL(url: Platform.DevToolsPath.UrlString): boolean {\n return Bindings.IgnoreListManager.IgnoreListManager.instance().isUserIgnoreListedURL(url);\n }\n\n /*\n ------------------------------------------------------------------------------------\n The following methods are invoked by the flame chart renderer to query features about\n events on rendering.\n ------------------------------------------------------------------------------------\n */\n\n /**\n * Gets the color an event added by this appender should be rendered with.\n */\n colorForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): string {\n if (this.#traceParsedData.Meta.traceIsGeneric) {\n return event.name ? `hsl(${Platform.StringUtilities.hashCode(event.name) % 300 + 30}, 40%, 70%)` : '#ccc';\n }\n\n if (TraceEngine.Types.TraceEvents.isProfileCall(event)) {\n if (event.callFrame.functionName === '(idle)') {\n return Components.EntryStyles.getCategoryStyles().idle.getComputedColorValue();\n }\n if (event.callFrame.scriptId === '0') {\n // If we can not match this frame to a script, return the\n // generic \"scripting\" color.\n return Components.EntryStyles.getCategoryStyles().scripting.getComputedColorValue();\n }\n // Otherwise, return a color created based on its URL.\n return this.#colorGenerator.colorForID(event.callFrame.url);\n }\n const defaultColor =\n Components.EntryStyles.getEventStyle(event.name as TraceEngine.Types.TraceEvents.KnownEventName)\n ?.category.getComputedColorValue();\n return defaultColor || Components.EntryStyles.getCategoryStyles().other.getComputedColorValue();\n }\n\n /**\n * Gets the title an event added by this appender should be rendered with.\n */\n titleForEvent(entry: TraceEngine.Types.TraceEvents.TraceEventData): string {\n if (this.isIgnoreListedEntry(entry)) {\n return i18nString(UIStrings.onIgnoreList);\n }\n return Components.EntryName.nameForEntry(entry, this.#traceParsedData);\n }\n\n /**\n * Returns the info shown when an event added by this appender\n * is hovered in the timeline.\n */\n highlightedEntryInfo(event: TraceEngine.Types.TraceEvents.TraceEventData): HighlightedEntryInfo {\n let title = this.titleForEvent(event);\n if (TraceEngine.Types.TraceEvents.isTraceEventParseHTML(event)) {\n const startLine = event.args['beginData']['startLine'];\n const endLine = event.args['endData'] && event.args['endData']['endLine'];\n const eventURL = event.args['beginData']['url'] as Platform.DevToolsPath.UrlString;\n const url = Bindings.ResourceUtils.displayNameForURL(eventURL);\n const range = (endLine !== -1 || endLine === startLine) ? `${startLine}...${endLine}` : startLine;\n title += ` - ${url} [${range}]`;\n }\n const selfTime = this.#traceParsedData.Renderer.entryToNode.get(event)?.selfTime;\n return {title, formattedTime: getFormattedTime(event.dur, selfTime)};\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"ThreadAppender.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/ThreadAppender.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as Root from '../../core/root/root.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as Bindings from '../../models/bindings/bindings.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\n\nimport {\n addDecorationToEvent,\n buildGroupStyle,\n buildTrackHeader,\n getFormattedTime,\n} from './AppenderUtils.js';\nimport {\n type CompatibilityTracksAppender,\n entryIsVisibleInTimeline,\n type HighlightedEntryInfo,\n type TrackAppender,\n type TrackAppenderName,\n VisualLoggingTrackName,\n} from './CompatibilityTracksAppender.js';\nimport * as Components from './components/components.js';\nimport * as ModificationsManager from './ModificationsManager.js';\n\nconst UIStrings = {\n /**\n *@description Text shown for an entry in the flame chart that is ignored because it matches\n * a predefined ignore list.\n */\n onIgnoreList: 'On ignore list',\n /**\n * @description Refers to the \"Main frame\", meaning the top level frame. See https://www.w3.org/TR/html401/present/frames.html\n * @example{example.com} PH1\n */\n mainS: 'Main — {PH1}',\n /**\n * @description Refers to the main thread of execution of a program. See https://developer.mozilla.org/en-US/docs/Glossary/Main_thread\n */\n main: 'Main',\n /**\n * @description Refers to any frame in the page. See https://www.w3.org/TR/html401/present/frames.html\n * @example {https://example.com} PH1\n */\n frameS: 'Frame — {PH1}',\n /**\n *@description A web worker in the page. See https://developer.mozilla.org/en-US/docs/Web/API/Worker\n *@example {https://google.com} PH1\n */\n workerS: '`Worker` — {PH1}',\n /**\n *@description A web worker in the page. See https://developer.mozilla.org/en-US/docs/Web/API/Worker\n *@example {FormatterWorker} PH1\n *@example {https://google.com} PH2\n */\n workerSS: '`Worker`: {PH1} — {PH2}',\n /**\n *@description Label for a web worker exclusively allocated for a purpose.\n */\n dedicatedWorker: 'Dedicated `Worker`',\n /**\n *@description A generic name given for a thread running in the browser (sequence of programmed instructions).\n * The placeholder is an enumeration given to the thread.\n *@example {1} PH1\n */\n threadS: 'Thread {PH1}',\n /**\n *@description Rasterization in computer graphics.\n */\n raster: 'Raster',\n /**\n *@description Threads used for background tasks.\n */\n threadPool: 'Thread pool',\n /**\n *@description Name for a thread that rasterizes graphics in a website.\n *@example {2} PH1\n */\n rasterizerThreadS: 'Rasterizer thread {PH1}',\n /**\n *@description Text in Timeline Flame Chart Data Provider of the Performance panel\n *@example {2} PH1\n */\n threadPoolThreadS: 'Thread pool worker {PH1}',\n /**\n *@description Title of a bidder auction worklet with known URL in the timeline flame chart of the Performance panel\n *@example {https://google.com} PH1\n */\n bidderWorkletS: 'Bidder Worklet — {PH1}',\n /**\n *@description Title of a bidder auction worklet in the timeline flame chart of the Performance panel with an unknown URL\n */\n bidderWorklet: 'Bidder Worklet',\n\n /**\n *@description Title of a seller auction worklet in the timeline flame chart of the Performance panel with an unknown URL\n */\n sellerWorklet: 'Seller Worklet',\n\n /**\n *@description Title of an auction worklet in the timeline flame chart of the Performance panel with an unknown URL\n */\n unknownWorklet: 'Auction Worklet',\n\n /**\n *@description Title of control thread of a service process for an auction worklet in the timeline flame chart of the Performance panel with an unknown URL\n */\n workletService: 'Auction Worklet service',\n\n /**\n *@description Title of a seller auction worklet with known URL in the timeline flame chart of the Performance panel\n *@example {https://google.com} PH1\n */\n sellerWorkletS: 'Seller Worklet — {PH1}',\n\n /**\n *@description Title of an auction worklet with known URL in the timeline flame chart of the Performance panel\n *@example {https://google.com} PH1\n */\n unknownWorkletS: 'Auction Worklet — {PH1}',\n\n /**\n *@description Title of control thread of a service process for an auction worklet with known URL in the timeline flame chart of the Performance panel\n * @example {https://google.com} PH1\n */\n workletServiceS: 'Auction Worklet service — {PH1}',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/ThreadAppender.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\n// This appender is only triggered when the Renderer handler is run. At\n// the moment this only happens in the basic component server example.\n// In the future, once this appender fully supports the behaviour of the\n// old engine's thread/sync tracks we can always run it by enabling the\n// Renderer and Samples handler by default.\nexport class ThreadAppender implements TrackAppender {\n readonly appenderName: TrackAppenderName = 'Thread';\n\n #colorGenerator: Common.Color.Generator;\n #compatibilityBuilder: CompatibilityTracksAppender;\n #parsedTrace: Trace.Handlers.Types.ParsedTrace;\n\n #entries: Trace.Types.Events.Event[] = [];\n #tree: Trace.Helpers.TreeHelpers.TraceEntryTree;\n #processId: Trace.Types.Events.ProcessID;\n #threadId: Trace.Types.Events.ThreadID;\n #threadDefaultName: string;\n #expanded = false;\n #headerAppended: boolean = false;\n readonly threadType: Trace.Handlers.Threads.ThreadType = Trace.Handlers.Threads.ThreadType.MAIN_THREAD;\n readonly isOnMainFrame: boolean;\n #showAllEventsEnabled = Root.Runtime.experiments.isEnabled('timeline-show-all-events');\n #url: string = '';\n #headerNestingLevel: number|null = null;\n constructor(\n compatibilityBuilder: CompatibilityTracksAppender, parsedTrace: Trace.Handlers.Types.ParsedTrace,\n processId: Trace.Types.Events.ProcessID, threadId: Trace.Types.Events.ThreadID, threadName: string|null,\n type: Trace.Handlers.Threads.ThreadType) {\n this.#compatibilityBuilder = compatibilityBuilder;\n // TODO(crbug.com/1456706):\n // The values for this color generator have been taken from the old\n // engine to keep the colors the same after the migration. This\n // generator is used here to create colors for js frames (profile\n // calls) in the flamechart by hashing the script's url. We might\n // need to reconsider this generator when migrating to GM3 colors.\n this.#colorGenerator =\n new Common.Color.Generator({min: 30, max: 330, count: undefined}, {min: 50, max: 80, count: 3}, 85);\n // Add a default color for call frames with no url.\n this.#colorGenerator.setColorForID('', '#f2ecdc');\n this.#parsedTrace = parsedTrace;\n this.#processId = processId;\n this.#threadId = threadId;\n\n // When loading a CPU profile, only CPU data will be available, thus\n // we get the data from the SamplesHandler.\n const entries = type === Trace.Handlers.Threads.ThreadType.CPU_PROFILE ?\n this.#parsedTrace.Samples?.profilesInProcess.get(processId)?.get(threadId)?.profileCalls :\n this.#parsedTrace.Renderer?.processes.get(processId)?.threads?.get(threadId)?.entries;\n const tree = type === Trace.Handlers.Threads.ThreadType.CPU_PROFILE ?\n this.#parsedTrace.Samples?.profilesInProcess.get(processId)?.get(threadId)?.profileTree :\n this.#parsedTrace.Renderer?.processes.get(processId)?.threads?.get(threadId)?.tree;\n if (!entries || !tree) {\n throw new Error(`Could not find data for thread with id ${threadId} in process with id ${processId}`);\n }\n this.#entries = entries;\n this.#tree = tree;\n this.#threadDefaultName = threadName || i18nString(UIStrings.threadS, {PH1: threadId});\n this.isOnMainFrame = Boolean(this.#parsedTrace.Renderer?.processes.get(processId)?.isOnMainFrame);\n this.threadType = type;\n // AuctionWorklets are threads, so we re-use this appender rather than\n // duplicate it, but we change the name because we want to render these\n // lower down than other threads.\n if (this.#parsedTrace.AuctionWorklets.worklets.has(processId)) {\n this.appenderName = 'Thread_AuctionWorklet';\n }\n this.#url = this.#parsedTrace.Renderer?.processes.get(this.#processId)?.url || '';\n }\n\n processId(): Trace.Types.Events.ProcessID {\n return this.#processId;\n }\n\n threadId(): Trace.Types.Events.ThreadID {\n return this.#threadId;\n }\n\n /**\n * Appends into the flame chart data the data corresponding to the\n * this thread.\n * @param trackStartLevel the horizontal level of the flame chart events where\n * the track's events will start being appended.\n * @param expanded wether the track should be rendered expanded.\n * @returns the first available level to append more data after having\n * appended the track's events.\n */\n appendTrackAtLevel(trackStartLevel: number, expanded: boolean = false): number {\n if (this.#entries.length === 0) {\n return trackStartLevel;\n }\n this.#expanded = expanded;\n return this.#appendTreeAtLevel(trackStartLevel);\n }\n\n setHeaderNestingLevel(level: number): void {\n this.#headerNestingLevel = level;\n }\n /**\n * Track header is appended only if there are events visible on it.\n * Otherwise we don't append any track. So, instead of preemptively\n * appending a track before appending its events, we only do so once\n * we have detected that the track contains an event that is visible.\n */\n #ensureTrackHeaderAppended(trackStartLevel: number): void {\n if (this.#headerAppended) {\n return;\n }\n if (this.threadType === Trace.Handlers.Threads.ThreadType.RASTERIZER ||\n this.threadType === Trace.Handlers.Threads.ThreadType.THREAD_POOL) {\n this.#appendGroupedTrackHeaderAndTitle(trackStartLevel, this.threadType);\n } else {\n this.#appendTrackHeaderAtLevel(trackStartLevel);\n }\n this.#headerAppended = true;\n }\n\n setHeaderAppended(headerAppended: boolean): void {\n this.#headerAppended = headerAppended;\n }\n\n headerAppended(): boolean {\n return this.#headerAppended;\n }\n\n /**\n * Adds into the flame chart data the header corresponding to this\n * thread. A header is added in the shape of a group in the flame\n * chart data. A group has a predefined style and a reference to the\n * definition of the legacy track (which should be removed in the\n * future).\n * @param currentLevel the flame chart level at which the header is\n * appended.\n */\n #appendTrackHeaderAtLevel(currentLevel: number): void {\n const trackIsCollapsible = this.#entries.length > 0;\n const style = buildGroupStyle({shareHeaderLine: false, collapsible: trackIsCollapsible});\n if (this.#headerNestingLevel !== null) {\n style.nestingLevel = this.#headerNestingLevel;\n }\n const visualLoggingName = this.#visualLoggingNameForThread();\n const group = buildTrackHeader(\n visualLoggingName, currentLevel, this.trackName(), style, /* selectable= */ true, this.#expanded,\n /* showStackContextMenu= */ true);\n this.#compatibilityBuilder.registerTrackForGroup(group, this);\n }\n\n #visualLoggingNameForThread(): VisualLoggingTrackName|null {\n switch (this.threadType) {\n case Trace.Handlers.Threads.ThreadType.MAIN_THREAD:\n return this.isOnMainFrame ? VisualLoggingTrackName.THREAD_MAIN : VisualLoggingTrackName.THREAD_FRAME;\n case Trace.Handlers.Threads.ThreadType.WORKER:\n return VisualLoggingTrackName.THREAD_WORKER;\n case Trace.Handlers.Threads.ThreadType.RASTERIZER:\n return VisualLoggingTrackName.THREAD_RASTERIZER;\n case Trace.Handlers.Threads.ThreadType.AUCTION_WORKLET:\n return VisualLoggingTrackName.THREAD_AUCTION_WORKLET;\n case Trace.Handlers.Threads.ThreadType.OTHER:\n return VisualLoggingTrackName.THREAD_OTHER;\n case Trace.Handlers.Threads.ThreadType.CPU_PROFILE:\n return VisualLoggingTrackName.THREAD_CPU_PROFILE;\n case Trace.Handlers.Threads.ThreadType.THREAD_POOL:\n return VisualLoggingTrackName.THREAD_POOL;\n default:\n return null;\n }\n }\n /**\n * Raster threads are rendered under a single header in the\n * flamechart. However, each thread has a unique title which needs to\n * be added to the flamechart data.\n */\n #appendGroupedTrackHeaderAndTitle(\n trackStartLevel: number,\n threadType: Trace.Handlers.Threads.ThreadType.RASTERIZER|Trace.Handlers.Threads.ThreadType.THREAD_POOL): void {\n const currentTrackCount = this.#compatibilityBuilder.getCurrentTrackCountForThreadType(threadType);\n if (currentTrackCount === 0) {\n const trackIsCollapsible = this.#entries.length > 0;\n const headerStyle = buildGroupStyle({shareHeaderLine: false, collapsible: trackIsCollapsible});\n\n // Don't set any jslogcontext (first argument) because this is a shared\n // header group. Each child will have its context set.\n const headerGroup = buildTrackHeader(\n null, trackStartLevel, this.trackName(), headerStyle, /* selectable= */ false, this.#expanded);\n this.#compatibilityBuilder.getFlameChartTimelineData().groups.push(headerGroup);\n }\n\n // Nesting is set to 1 because the track is appended inside the\n // header for all raster threads.\n const titleStyle = buildGroupStyle({padding: 2, nestingLevel: 1, collapsible: false});\n const rasterizerTitle = this.threadType === Trace.Handlers.Threads.ThreadType.RASTERIZER ?\n i18nString(UIStrings.rasterizerThreadS, {PH1: currentTrackCount + 1}) :\n i18nString(UIStrings.threadPoolThreadS, {PH1: currentTrackCount + 1});\n\n const visualLoggingName = this.#visualLoggingNameForThread();\n const titleGroup = buildTrackHeader(\n visualLoggingName, trackStartLevel, rasterizerTitle, titleStyle, /* selectable= */ true, this.#expanded);\n this.#compatibilityBuilder.registerTrackForGroup(titleGroup, this);\n }\n\n trackName(): string {\n let threadTypeLabel: string|null = null;\n switch (this.threadType) {\n case Trace.Handlers.Threads.ThreadType.MAIN_THREAD:\n threadTypeLabel = this.isOnMainFrame ? i18nString(UIStrings.mainS, {PH1: this.#url}) :\n i18nString(UIStrings.frameS, {PH1: this.#url});\n break;\n case Trace.Handlers.Threads.ThreadType.CPU_PROFILE:\n threadTypeLabel = i18nString(UIStrings.main);\n break;\n case Trace.Handlers.Threads.ThreadType.WORKER:\n threadTypeLabel = this.#buildNameForWorker();\n break;\n case Trace.Handlers.Threads.ThreadType.RASTERIZER:\n threadTypeLabel = i18nString(UIStrings.raster);\n break;\n case Trace.Handlers.Threads.ThreadType.THREAD_POOL:\n threadTypeLabel = i18nString(UIStrings.threadPool);\n break;\n case Trace.Handlers.Threads.ThreadType.OTHER:\n break;\n case Trace.Handlers.Threads.ThreadType.AUCTION_WORKLET:\n threadTypeLabel = this.#buildNameForAuctionWorklet();\n break;\n default:\n return Platform.assertNever(this.threadType, `Unknown thread type: ${this.threadType}`);\n }\n let suffix = '';\n if (this.#parsedTrace.Meta.traceIsGeneric) {\n suffix = suffix + ` (${this.threadId()})`;\n }\n return (threadTypeLabel || this.#threadDefaultName) + suffix;\n }\n\n getUrl(): string {\n return this.#url;\n }\n\n getEntries(): Trace.Types.Events.Event[] {\n return this.#entries;\n }\n\n #buildNameForAuctionWorklet(): string {\n const workletMetadataEvent = this.#parsedTrace.AuctionWorklets.worklets.get(this.#processId);\n // We should always have this event - if we do not, we were instantiated with invalid data.\n if (!workletMetadataEvent) {\n return i18nString(UIStrings.unknownWorklet);\n }\n\n // Host could be empty - in which case we do not want to add it.\n const host = workletMetadataEvent.host ? `https://${workletMetadataEvent.host}` : '';\n const shouldAddHost = host.length > 0;\n\n // For each Auction Worklet in a page there are two threads we care about on the same process.\n // 1. The \"Worklet Service\" which is a generic helper service. This thread\n // is always named \"auction_worklet.CrUtilityMain\".\n //\n // 2. The \"Seller/Bidder\" service. This thread is always named\n // \"AuctionV8HelperThread\". The AuctionWorkets handler does the job of\n // figuring this out for us - the metadata event it provides for each\n // worklet process will have a `type` already set.\n //\n // Therefore, for this given thread, which we know is part of\n // an AuctionWorklet process, we need to figure out if this thread is the\n // generic service, or a seller/bidder worklet.\n //\n // Note that the worklet could also have the \"unknown\" type - this is not\n // expected but implemented to prevent trace event changes causing DevTools\n // to break with unknown worklet types.\n const isUtilityThread = workletMetadataEvent.args.data.utilityThread.tid === this.#threadId;\n const isBidderOrSeller = workletMetadataEvent.args.data.v8HelperThread.tid === this.#threadId;\n\n if (isUtilityThread) {\n return shouldAddHost ? i18nString(UIStrings.workletServiceS, {PH1: host}) : i18nString(UIStrings.workletService);\n }\n\n if (isBidderOrSeller) {\n switch (workletMetadataEvent.type) {\n case Trace.Types.Events.AuctionWorkletType.SELLER:\n return shouldAddHost ? i18nString(UIStrings.sellerWorkletS, {PH1: host}) :\n i18nString(UIStrings.sellerWorklet);\n case Trace.Types.Events.AuctionWorkletType.BIDDER:\n return shouldAddHost ? i18nString(UIStrings.bidderWorkletS, {PH1: host}) :\n i18nString(UIStrings.bidderWorklet);\n case Trace.Types.Events.AuctionWorkletType.UNKNOWN:\n return shouldAddHost ? i18nString(UIStrings.unknownWorkletS, {PH1: host}) :\n i18nString(UIStrings.unknownWorklet);\n default:\n Platform.assertNever(\n workletMetadataEvent.type, `Unexpected Auction Worklet Type ${workletMetadataEvent.type}`);\n }\n }\n // We should never reach here, but just in case!\n return shouldAddHost ? i18nString(UIStrings.unknownWorkletS, {PH1: host}) : i18nString(UIStrings.unknownWorklet);\n }\n\n #buildNameForWorker(): string {\n const url = this.#parsedTrace.Renderer?.processes.get(this.#processId)?.url || '';\n const workerId = this.#parsedTrace.Workers.workerIdByThread.get(this.#threadId);\n const workerURL = workerId ? this.#parsedTrace.Workers.workerURLById.get(workerId) : url;\n // Try to create a name using the worker url if present. If not, use a generic label.\n let workerName =\n workerURL ? i18nString(UIStrings.workerS, {PH1: workerURL}) : i18nString(UIStrings.dedicatedWorker);\n const workerTarget = workerId !== undefined && SDK.TargetManager.TargetManager.instance().targetById(workerId);\n if (workerTarget) {\n // Get the worker name from the target, which corresponds to the name\n // assigned to the worker when it was constructed.\n workerName = i18nString(UIStrings.workerSS, {PH1: workerTarget.name(), PH2: url});\n }\n return workerName;\n }\n\n /**\n * Adds into the flame chart data the entries of this thread, which\n * includes trace events and JS calls.\n * @param currentLevel the flame chart level from which entries will\n * be appended.\n * @returns the next level after the last occupied by the appended\n * entries (the first available level to append more data).\n */\n #appendTreeAtLevel(trackStartLevel: number): number {\n // We can not used the tree maxDepth in the tree from the\n // RendererHandler because ignore listing and visibility of events\n // alter the final depth of the flame chart.\n return this.#appendNodesAtLevel(this.#tree.roots, trackStartLevel);\n }\n\n /**\n * Traverses the trees formed by the provided nodes in breadth first\n * fashion and appends each node's entry on each iteration. As each\n * entry is handled, a check for the its visibility or if it's ignore\n * listed is done before appending.\n */\n #appendNodesAtLevel(\n nodes: Iterable, startingLevel: number,\n parentIsIgnoredListed: boolean = false): number {\n const invisibleEntries =\n ModificationsManager.ModificationsManager.activeManager()?.getEntriesFilter().invisibleEntries() ?? [];\n let maxDepthInTree = startingLevel;\n for (const node of nodes) {\n let nextLevel = startingLevel;\n const entry = node.entry;\n const entryIsIgnoreListed = this.isIgnoreListedEntry(entry);\n // Events' visibility is determined from their predefined styles,\n // which is something that's not available in the engine data.\n // Thus it needs to be checked in the appenders, but preemptively\n // checking if there are visible events and returning early if not\n // is potentially expensive since, in theory, we would be adding\n // another traversal to the entries array (which could grow\n // large). To avoid the extra cost we add the check in the\n // traversal we already need to append events.\n const entryIsVisible = !invisibleEntries.includes(entry) &&\n (entryIsVisibleInTimeline(entry, this.#parsedTrace) || this.#showAllEventsEnabled);\n // For ignore listing support, these two conditions need to be met\n // to not append a profile call to the flame chart:\n // 1. It is ignore listed\n // 2. It is NOT the bottom-most call in an ignore listed stack (a\n // set of chained profile calls that belong to ignore listed\n // URLs).\n // This means that all of the ignore listed calls are ignored (not\n // appended), except if it is the bottom call of an ignored stack.\n // This is becaue to represent ignore listed stack frames, we add\n // a flame chart entry with the length and position of the bottom\n // frame, which is distictively marked to denote an ignored listed\n // stack.\n const skipEventDueToIgnoreListing = entryIsIgnoreListed && parentIsIgnoredListed;\n if (entryIsVisible && !skipEventDueToIgnoreListing) {\n this.#appendEntryAtLevel(entry, startingLevel);\n nextLevel++;\n }\n\n const depthInChildTree = this.#appendNodesAtLevel(node.children, nextLevel, entryIsIgnoreListed);\n maxDepthInTree = Math.max(depthInChildTree, maxDepthInTree);\n }\n return maxDepthInTree;\n }\n\n #appendEntryAtLevel(entry: Trace.Types.Events.Event, level: number): void {\n this.#ensureTrackHeaderAppended(level);\n const index = this.#compatibilityBuilder.appendEventAtLevel(entry, level, this);\n this.#addDecorationsToEntry(entry, index);\n }\n\n #addDecorationsToEntry(entry: Trace.Types.Events.Event, index: number): void {\n const flameChartData = this.#compatibilityBuilder.getFlameChartTimelineData();\n if (ModificationsManager.ModificationsManager.activeManager()?.getEntriesFilter().isEntryExpandable(entry)) {\n addDecorationToEvent(\n flameChartData, index, {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW});\n }\n const warnings = this.#parsedTrace.Warnings.perEvent.get(entry);\n if (!warnings) {\n return;\n }\n addDecorationToEvent(flameChartData, index, {type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE});\n if (!warnings.includes('LONG_TASK')) {\n return;\n }\n addDecorationToEvent(flameChartData, index, {\n type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,\n startAtTime: Trace.Handlers.ModelHandlers.Warnings.LONG_MAIN_THREAD_TASK_THRESHOLD,\n });\n }\n\n isIgnoreListedEntry(entry: Trace.Types.Events.Event): boolean {\n if (!Trace.Types.Events.isProfileCall(entry)) {\n return false;\n }\n const url = entry.callFrame.url as Platform.DevToolsPath.UrlString;\n return url && this.isIgnoreListedURL(url);\n }\n\n private isIgnoreListedURL(url: Platform.DevToolsPath.UrlString): boolean {\n return Bindings.IgnoreListManager.IgnoreListManager.instance().isUserIgnoreListedURL(url);\n }\n\n /*\n ------------------------------------------------------------------------------------\n The following methods are invoked by the flame chart renderer to query features about\n events on rendering.\n ------------------------------------------------------------------------------------\n */\n\n /**\n * Gets the color an event added by this appender should be rendered with.\n */\n colorForEvent(event: Trace.Types.Events.Event): string {\n if (this.#parsedTrace.Meta.traceIsGeneric) {\n return event.name ? `hsl(${Platform.StringUtilities.hashCode(event.name) % 300 + 30}, 40%, 70%)` : '#ccc';\n }\n\n if (Trace.Types.Events.isProfileCall(event)) {\n if (event.callFrame.functionName === '(idle)') {\n return Components.EntryStyles.getCategoryStyles().idle.getComputedColorValue();\n }\n if (event.callFrame.scriptId === '0') {\n // If we can not match this frame to a script, return the\n // generic \"scripting\" color.\n return Components.EntryStyles.getCategoryStyles().scripting.getComputedColorValue();\n }\n // Otherwise, return a color created based on its URL.\n return this.#colorGenerator.colorForID(event.callFrame.url);\n }\n const defaultColor =\n Components.EntryStyles.getEventStyle(event.name as Trace.Types.Events.Name)?.category.getComputedColorValue();\n return defaultColor || Components.EntryStyles.getCategoryStyles().other.getComputedColorValue();\n }\n\n /**\n * Gets the title an event added by this appender should be rendered with.\n */\n titleForEvent(entry: Trace.Types.Events.Event): string {\n if (this.isIgnoreListedEntry(entry)) {\n return i18nString(UIStrings.onIgnoreList);\n }\n return Components.EntryName.nameForEntry(entry, this.#parsedTrace);\n }\n\n /**\n * Returns the info shown when an event added by this appender\n * is hovered in the timeline.\n */\n highlightedEntryInfo(event: Trace.Types.Events.Event): HighlightedEntryInfo {\n let title = this.titleForEvent(event);\n if (Trace.Types.Events.isParseHTML(event)) {\n const startLine = event.args['beginData']['startLine'];\n const endLine = event.args['endData'] && event.args['endData']['endLine'];\n const eventURL = event.args['beginData']['url'] as Platform.DevToolsPath.UrlString;\n const url = Bindings.ResourceUtils.displayNameForURL(eventURL);\n const range = (endLine !== -1 || endLine === startLine) ? `${startLine}...${endLine}` : startLine;\n title += ` - ${url} [${range}]`;\n }\n const selfTime = this.#parsedTrace.Renderer.entryToNode.get(event)?.selfTime;\n return {title, formattedTime: getFormattedTime(event.dur, selfTime)};\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineController.d.ts b/public/panels/timeline/TimelineController.d.ts index 0e2470a78..5e806d18d 100644 --- a/public/panels/timeline/TimelineController.d.ts +++ b/public/panels/timeline/TimelineController.d.ts @@ -1,8 +1,8 @@ import * as SDK from '../../core/sdk/sdk.js'; import type * as Protocol from '../../generated/protocol.js'; import type * as TimelineModel from '../../models/timeline_model/timeline_model.js'; -import * as TraceEngine from '../../models/trace/trace.js'; -export declare class TimelineController implements TraceEngine.TracingManager.TracingManagerClient { +import * as Trace from '../../models/trace/trace.js'; +export declare class TimelineController implements Trace.TracingManager.TracingManagerClient { #private; readonly primaryPageTarget: SDK.Target.Target; readonly rootTarget: SDK.Target.Target; @@ -42,7 +42,7 @@ export declare class TimelineController implements TraceEngine.TracingManager.Tr private waitForTracingToStop; private startRecordingWithCategories; warmupJsProfiler(): Promise; - traceEventsCollected(events: TraceEngine.Types.TraceEvents.TraceEventData[]): void; + traceEventsCollected(events: Trace.Types.Events.Event[]): void; tracingComplete(): void; private allSourcesFinished; tracingBufferUsage(usage: number): void; @@ -53,7 +53,7 @@ export interface Client { loadingStarted(): void; processingStarted(): void; loadingProgress(progress?: number): void; - loadingComplete(collectedEvents: TraceEngine.Types.TraceEvents.TraceEventData[], exclusiveFilter: TimelineModel.TimelineModelFilter.TimelineModelFilter | null, isCpuProfile: boolean, recordingStartTime: number | null, metadata: TraceEngine.Types.File.MetaData | null): Promise; + loadingComplete(collectedEvents: Trace.Types.Events.Event[], exclusiveFilter: TimelineModel.TimelineModelFilter.TimelineModelFilter | null, isCpuProfile: boolean, recordingStartTime: number | null, metadata: Trace.Types.File.MetaData | null): Promise; loadingCompleteForTest(): void; } export interface RecordingOptions { diff --git a/public/panels/timeline/TimelineController.js b/public/panels/timeline/TimelineController.js index c3cfd2ada..5434c860a 100644 --- a/public/panels/timeline/TimelineController.js +++ b/public/panels/timeline/TimelineController.js @@ -6,7 +6,7 @@ import * as Root from '../../core/root/root.js'; import * as SDK from '../../core/sdk/sdk.js'; import * as Extensions from '../../models/extensions/extensions.js'; import * as LiveMetrics from '../../models/live-metrics/live-metrics.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; const UIStrings = { /** *@description Text in Timeline Controller of the Performance panel indicating that the Performance Panel cannot @@ -56,7 +56,7 @@ export class TimelineController { this.rootTarget = rootTarget; // Ensure the tracing manager is the one for the Root Target, NOT the // primaryPageTarget, as that is the one we have to invoke tracing against. - this.tracingManager = rootTarget.model(TraceEngine.TracingManager.TracingManager); + this.tracingManager = rootTarget.model(Trace.TracingManager.TracingManager); this.client = client; } async dispose() { @@ -78,9 +78,9 @@ export class TimelineController { // └ default: on, option: enableJSSampling const categoriesArray = [ Root.Runtime.experiments.isEnabled('timeline-show-all-events') ? '*' : '-*', - TraceEngine.Types.TraceEvents.Categories.Console, - TraceEngine.Types.TraceEvents.Categories.Loading, - TraceEngine.Types.TraceEvents.Categories.UserTiming, + Trace.Types.Events.Categories.Console, + Trace.Types.Events.Categories.Loading, + Trace.Types.Events.Categories.UserTiming, 'devtools.timeline', disabledByDefault('devtools.timeline'), disabledByDefault('devtools.timeline.frame'), diff --git a/public/panels/timeline/TimelineController.js.map b/public/panels/timeline/TimelineController.js.map index da9ff5be1..bb8966ba2 100644 --- a/public/panels/timeline/TimelineController.js.map +++ b/public/panels/timeline/TimelineController.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineController.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineController.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2016 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Root from '../../core/root/root.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport type * as Protocol from '../../generated/protocol.js';\nimport * as Extensions from '../../models/extensions/extensions.js';\nimport * as LiveMetrics from '../../models/live-metrics/live-metrics.js';\nimport type * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\n\nconst UIStrings = {\n /**\n *@description Text in Timeline Controller of the Performance panel indicating that the Performance Panel cannot\n * record a performance trace because the type of target (where possible types are page, service worker and shared\n * worker) doesn't support it.\n */\n tracingNotSupported: 'Performance trace recording not supported for this type of target',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelineController.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nexport class TimelineController implements TraceEngine.TracingManager.TracingManagerClient {\n readonly primaryPageTarget: SDK.Target.Target;\n readonly rootTarget: SDK.Target.Target;\n private tracingManager: TraceEngine.TracingManager.TracingManager|null;\n #collectedEvents: TraceEngine.Types.TraceEvents.TraceEventData[] = [];\n #recordingStartTime: number|null = null;\n private readonly client: Client;\n private tracingCompletePromise: PromiseWithResolvers|null = null;\n\n /**\n * We always need to profile against the DevTools root target, which is\n * the target that DevTools is attached to.\n *\n * In most cases, this will be the tab that DevTools is inspecting.\n * Now pre-rendering is active, tabs can have multiple pages - only one\n * of which the user is being shown. This is the \"primary page\" and hence\n * why in code we have \"primaryPageTarget\". When there's a prerendered\n * page in a background, tab target would have multiple subtargets, one\n * of them being primaryPageTarget.\n *\n * The problems with using primary page target for tracing are:\n * 1. Performance trace doesn't include information from the other pages on\n * the tab which is probably not what the user wants as it does not\n * reflect reality.\n * 2. Capturing trace never finishes after prerendering activation as\n * we've started on one target and ending on another one, and\n * tracingComplete event never gets processed.\n *\n * However, when we want to look at the URL of the current page, we need\n * to use the primaryPageTarget to ensure we get the URL of the tab and\n * the tab's page that is being shown to the user. This is because the tab\n * target (which is what rootTarget is) only exposes the Target and Tracing\n * domains. We need the Page target to navigate as it implements the Page\n * domain. That is why here we have to store both.\n **/\n constructor(rootTarget: SDK.Target.Target, primaryPageTarget: SDK.Target.Target, client: Client) {\n this.primaryPageTarget = primaryPageTarget;\n this.rootTarget = rootTarget;\n // Ensure the tracing manager is the one for the Root Target, NOT the\n // primaryPageTarget, as that is the one we have to invoke tracing against.\n this.tracingManager = rootTarget.model(TraceEngine.TracingManager.TracingManager);\n this.client = client;\n }\n\n async dispose(): Promise {\n if (this.tracingManager) {\n await this.tracingManager.reset();\n }\n }\n\n async startRecording(options: RecordingOptions): Promise {\n function disabledByDefault(category: string): string {\n return 'disabled-by-default-' + category;\n }\n\n // The following categories are also used in other tools, but this panel\n // offers the possibility of turning them off (see below).\n // 'disabled-by-default-devtools.screenshot'\n // └ default: on, option: captureFilmStrip\n // 'disabled-by-default-devtools.timeline.invalidationTracking'\n // └ default: off, experiment: timelineInvalidationTracking\n // 'disabled-by-default-v8.cpu_profiler'\n // └ default: on, option: enableJSSampling\n const categoriesArray = [\n Root.Runtime.experiments.isEnabled('timeline-show-all-events') ? '*' : '-*',\n TraceEngine.Types.TraceEvents.Categories.Console,\n TraceEngine.Types.TraceEvents.Categories.Loading,\n TraceEngine.Types.TraceEvents.Categories.UserTiming,\n 'devtools.timeline',\n disabledByDefault('devtools.timeline'),\n disabledByDefault('devtools.timeline.frame'),\n disabledByDefault('devtools.timeline.stack'),\n disabledByDefault('v8.compile'),\n disabledByDefault('v8.cpu_profiler.hires'),\n disabledByDefault('lighthouse'),\n 'v8.execute',\n 'v8',\n 'cppgc',\n 'navigation,rail',\n ];\n\n if (Root.Runtime.experiments.isEnabled('timeline-v8-runtime-call-stats') && options.enableJSSampling) {\n categoriesArray.push(disabledByDefault('v8.runtime_stats_sampling'));\n }\n if (options.enableJSSampling) {\n categoriesArray.push(disabledByDefault('v8.cpu_profiler'));\n }\n if (Root.Runtime.experiments.isEnabled('timeline-invalidation-tracking')) {\n categoriesArray.push(disabledByDefault('devtools.timeline.invalidationTracking'));\n }\n if (options.capturePictures) {\n categoriesArray.push(\n disabledByDefault('devtools.timeline.layers'), disabledByDefault('devtools.timeline.picture'),\n disabledByDefault('blink.graphics_context_annotations'));\n }\n if (options.captureFilmStrip) {\n categoriesArray.push(disabledByDefault('devtools.screenshot'));\n }\n if (options.captureSelectorStats) {\n categoriesArray.push(disabledByDefault('blink.debug'));\n }\n if (Root.Runtime.experiments.isEnabled('timeline-enhanced-traces')) {\n categoriesArray.push(disabledByDefault('devtools.target-rundown'));\n categoriesArray.push(disabledByDefault('devtools.v8-source-rundown'));\n }\n if (Root.Runtime.experiments.isEnabled('timeline-compiled-sources')) {\n categoriesArray.push(disabledByDefault('devtools.v8-source-rundown-sources'));\n }\n\n await LiveMetrics.LiveMetrics.instance().disable();\n\n this.#recordingStartTime = Date.now();\n const response = await this.startRecordingWithCategories(categoriesArray.join(','));\n if (response.getError()) {\n await SDK.TargetManager.TargetManager.instance().resumeAllTargets();\n }\n return response;\n }\n\n async stopRecording(): Promise {\n if (this.tracingManager) {\n this.tracingManager.stop();\n }\n\n this.client.loadingStarted();\n await this.waitForTracingToStop();\n await this.allSourcesFinished();\n\n await LiveMetrics.LiveMetrics.instance().enable();\n }\n\n private async waitForTracingToStop(): Promise {\n if (this.tracingManager) {\n await this.tracingCompletePromise?.promise;\n }\n }\n\n private async startRecordingWithCategories(categories: string): Promise {\n if (!this.tracingManager) {\n throw new Error(i18nString(UIStrings.tracingNotSupported));\n }\n // There might be a significant delay in the beginning of timeline recording\n // caused by starting CPU profiler, that needs to traverse JS heap to collect\n // all the functions data.\n await SDK.TargetManager.TargetManager.instance().suspendAllTargets('performance-timeline');\n this.tracingCompletePromise = Promise.withResolvers();\n const response = await this.tracingManager.start(this, categories, '');\n await this.warmupJsProfiler();\n Extensions.ExtensionServer.ExtensionServer.instance().profilingStarted();\n return response;\n }\n\n // CPUProfiler::StartProfiling has a non-trivial cost and we'd prefer it not happen within an\n // interaction as that complicates debugging interaction latency.\n // To trigger the StartProfiling interrupt and get the warmup cost out of the way, we send a\n // very soft invocation to V8.https://crbug.com/1358602\n async warmupJsProfiler(): Promise {\n // primaryPageTarget has RuntimeModel whereas rootTarget (Tab) does not.\n const runtimeModel = this.primaryPageTarget.model(SDK.RuntimeModel.RuntimeModel);\n if (!runtimeModel) {\n return;\n }\n await runtimeModel.agent.invoke_evaluate({\n expression: '(async function(){ await 1; })()',\n throwOnSideEffect: true,\n });\n }\n\n traceEventsCollected(events: TraceEngine.Types.TraceEvents.TraceEventData[]): void {\n this.#collectedEvents.push(...events);\n }\n\n tracingComplete(): void {\n if (!this.tracingCompletePromise) {\n return;\n }\n this.tracingCompletePromise.resolve(undefined);\n this.tracingCompletePromise = null;\n }\n\n private async allSourcesFinished(): Promise {\n // TODO(crbug.com/366072294): Report the progress of this resumption, as it can be lengthy on heavy pages.\n await SDK.TargetManager.TargetManager.instance().resumeAllTargets();\n Extensions.ExtensionServer.ExtensionServer.instance().profilingStopped();\n\n this.client.processingStarted();\n await this.client.loadingComplete(\n this.#collectedEvents, /* exclusiveFilter= */ null, /* isCpuProfile= */ false, this.#recordingStartTime,\n /* metadata= */ null);\n this.client.loadingCompleteForTest();\n }\n\n tracingBufferUsage(usage: number): void {\n this.client.recordingProgress(usage);\n }\n\n eventsRetrievalProgress(progress: number): void {\n this.client.loadingProgress(progress);\n }\n}\n\nexport interface Client {\n recordingProgress(usage: number): void;\n loadingStarted(): void;\n processingStarted(): void;\n loadingProgress(progress?: number): void;\n loadingComplete(\n collectedEvents: TraceEngine.Types.TraceEvents.TraceEventData[],\n exclusiveFilter: TimelineModel.TimelineModelFilter.TimelineModelFilter|null, isCpuProfile: boolean,\n recordingStartTime: number|null, metadata: TraceEngine.Types.File.MetaData|null): Promise;\n loadingCompleteForTest(): void;\n}\nexport interface RecordingOptions {\n enableJSSampling?: boolean;\n capturePictures?: boolean;\n captureFilmStrip?: boolean;\n captureSelectorStats?: boolean;\n}\n"]} \ No newline at end of file +{"version":3,"file":"TimelineController.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineController.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2016 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Root from '../../core/root/root.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport type * as Protocol from '../../generated/protocol.js';\nimport * as Extensions from '../../models/extensions/extensions.js';\nimport * as LiveMetrics from '../../models/live-metrics/live-metrics.js';\nimport type * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport * as Trace from '../../models/trace/trace.js';\n\nconst UIStrings = {\n /**\n *@description Text in Timeline Controller of the Performance panel indicating that the Performance Panel cannot\n * record a performance trace because the type of target (where possible types are page, service worker and shared\n * worker) doesn't support it.\n */\n tracingNotSupported: 'Performance trace recording not supported for this type of target',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelineController.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nexport class TimelineController implements Trace.TracingManager.TracingManagerClient {\n readonly primaryPageTarget: SDK.Target.Target;\n readonly rootTarget: SDK.Target.Target;\n private tracingManager: Trace.TracingManager.TracingManager|null;\n #collectedEvents: Trace.Types.Events.Event[] = [];\n #recordingStartTime: number|null = null;\n private readonly client: Client;\n private tracingCompletePromise: PromiseWithResolvers|null = null;\n\n /**\n * We always need to profile against the DevTools root target, which is\n * the target that DevTools is attached to.\n *\n * In most cases, this will be the tab that DevTools is inspecting.\n * Now pre-rendering is active, tabs can have multiple pages - only one\n * of which the user is being shown. This is the \"primary page\" and hence\n * why in code we have \"primaryPageTarget\". When there's a prerendered\n * page in a background, tab target would have multiple subtargets, one\n * of them being primaryPageTarget.\n *\n * The problems with using primary page target for tracing are:\n * 1. Performance trace doesn't include information from the other pages on\n * the tab which is probably not what the user wants as it does not\n * reflect reality.\n * 2. Capturing trace never finishes after prerendering activation as\n * we've started on one target and ending on another one, and\n * tracingComplete event never gets processed.\n *\n * However, when we want to look at the URL of the current page, we need\n * to use the primaryPageTarget to ensure we get the URL of the tab and\n * the tab's page that is being shown to the user. This is because the tab\n * target (which is what rootTarget is) only exposes the Target and Tracing\n * domains. We need the Page target to navigate as it implements the Page\n * domain. That is why here we have to store both.\n **/\n constructor(rootTarget: SDK.Target.Target, primaryPageTarget: SDK.Target.Target, client: Client) {\n this.primaryPageTarget = primaryPageTarget;\n this.rootTarget = rootTarget;\n // Ensure the tracing manager is the one for the Root Target, NOT the\n // primaryPageTarget, as that is the one we have to invoke tracing against.\n this.tracingManager = rootTarget.model(Trace.TracingManager.TracingManager);\n this.client = client;\n }\n\n async dispose(): Promise {\n if (this.tracingManager) {\n await this.tracingManager.reset();\n }\n }\n\n async startRecording(options: RecordingOptions): Promise {\n function disabledByDefault(category: string): string {\n return 'disabled-by-default-' + category;\n }\n\n // The following categories are also used in other tools, but this panel\n // offers the possibility of turning them off (see below).\n // 'disabled-by-default-devtools.screenshot'\n // └ default: on, option: captureFilmStrip\n // 'disabled-by-default-devtools.timeline.invalidationTracking'\n // └ default: off, experiment: timelineInvalidationTracking\n // 'disabled-by-default-v8.cpu_profiler'\n // └ default: on, option: enableJSSampling\n const categoriesArray = [\n Root.Runtime.experiments.isEnabled('timeline-show-all-events') ? '*' : '-*',\n Trace.Types.Events.Categories.Console,\n Trace.Types.Events.Categories.Loading,\n Trace.Types.Events.Categories.UserTiming,\n 'devtools.timeline',\n disabledByDefault('devtools.timeline'),\n disabledByDefault('devtools.timeline.frame'),\n disabledByDefault('devtools.timeline.stack'),\n disabledByDefault('v8.compile'),\n disabledByDefault('v8.cpu_profiler.hires'),\n disabledByDefault('lighthouse'),\n 'v8.execute',\n 'v8',\n 'cppgc',\n 'navigation,rail',\n ];\n\n if (Root.Runtime.experiments.isEnabled('timeline-v8-runtime-call-stats') && options.enableJSSampling) {\n categoriesArray.push(disabledByDefault('v8.runtime_stats_sampling'));\n }\n if (options.enableJSSampling) {\n categoriesArray.push(disabledByDefault('v8.cpu_profiler'));\n }\n if (Root.Runtime.experiments.isEnabled('timeline-invalidation-tracking')) {\n categoriesArray.push(disabledByDefault('devtools.timeline.invalidationTracking'));\n }\n if (options.capturePictures) {\n categoriesArray.push(\n disabledByDefault('devtools.timeline.layers'), disabledByDefault('devtools.timeline.picture'),\n disabledByDefault('blink.graphics_context_annotations'));\n }\n if (options.captureFilmStrip) {\n categoriesArray.push(disabledByDefault('devtools.screenshot'));\n }\n if (options.captureSelectorStats) {\n categoriesArray.push(disabledByDefault('blink.debug'));\n }\n if (Root.Runtime.experiments.isEnabled('timeline-enhanced-traces')) {\n categoriesArray.push(disabledByDefault('devtools.target-rundown'));\n categoriesArray.push(disabledByDefault('devtools.v8-source-rundown'));\n }\n if (Root.Runtime.experiments.isEnabled('timeline-compiled-sources')) {\n categoriesArray.push(disabledByDefault('devtools.v8-source-rundown-sources'));\n }\n\n await LiveMetrics.LiveMetrics.instance().disable();\n\n this.#recordingStartTime = Date.now();\n const response = await this.startRecordingWithCategories(categoriesArray.join(','));\n if (response.getError()) {\n await SDK.TargetManager.TargetManager.instance().resumeAllTargets();\n }\n return response;\n }\n\n async stopRecording(): Promise {\n if (this.tracingManager) {\n this.tracingManager.stop();\n }\n\n this.client.loadingStarted();\n await this.waitForTracingToStop();\n await this.allSourcesFinished();\n\n await LiveMetrics.LiveMetrics.instance().enable();\n }\n\n private async waitForTracingToStop(): Promise {\n if (this.tracingManager) {\n await this.tracingCompletePromise?.promise;\n }\n }\n\n private async startRecordingWithCategories(categories: string): Promise {\n if (!this.tracingManager) {\n throw new Error(i18nString(UIStrings.tracingNotSupported));\n }\n // There might be a significant delay in the beginning of timeline recording\n // caused by starting CPU profiler, that needs to traverse JS heap to collect\n // all the functions data.\n await SDK.TargetManager.TargetManager.instance().suspendAllTargets('performance-timeline');\n this.tracingCompletePromise = Promise.withResolvers();\n const response = await this.tracingManager.start(this, categories, '');\n await this.warmupJsProfiler();\n Extensions.ExtensionServer.ExtensionServer.instance().profilingStarted();\n return response;\n }\n\n // CPUProfiler::StartProfiling has a non-trivial cost and we'd prefer it not happen within an\n // interaction as that complicates debugging interaction latency.\n // To trigger the StartProfiling interrupt and get the warmup cost out of the way, we send a\n // very soft invocation to V8.https://crbug.com/1358602\n async warmupJsProfiler(): Promise {\n // primaryPageTarget has RuntimeModel whereas rootTarget (Tab) does not.\n const runtimeModel = this.primaryPageTarget.model(SDK.RuntimeModel.RuntimeModel);\n if (!runtimeModel) {\n return;\n }\n await runtimeModel.agent.invoke_evaluate({\n expression: '(async function(){ await 1; })()',\n throwOnSideEffect: true,\n });\n }\n\n traceEventsCollected(events: Trace.Types.Events.Event[]): void {\n this.#collectedEvents.push(...events);\n }\n\n tracingComplete(): void {\n if (!this.tracingCompletePromise) {\n return;\n }\n this.tracingCompletePromise.resolve(undefined);\n this.tracingCompletePromise = null;\n }\n\n private async allSourcesFinished(): Promise {\n // TODO(crbug.com/366072294): Report the progress of this resumption, as it can be lengthy on heavy pages.\n await SDK.TargetManager.TargetManager.instance().resumeAllTargets();\n Extensions.ExtensionServer.ExtensionServer.instance().profilingStopped();\n\n this.client.processingStarted();\n await this.client.loadingComplete(\n this.#collectedEvents, /* exclusiveFilter= */ null, /* isCpuProfile= */ false, this.#recordingStartTime,\n /* metadata= */ null);\n this.client.loadingCompleteForTest();\n }\n\n tracingBufferUsage(usage: number): void {\n this.client.recordingProgress(usage);\n }\n\n eventsRetrievalProgress(progress: number): void {\n this.client.loadingProgress(progress);\n }\n}\n\nexport interface Client {\n recordingProgress(usage: number): void;\n loadingStarted(): void;\n processingStarted(): void;\n loadingProgress(progress?: number): void;\n loadingComplete(\n collectedEvents: Trace.Types.Events.Event[],\n exclusiveFilter: TimelineModel.TimelineModelFilter.TimelineModelFilter|null, isCpuProfile: boolean,\n recordingStartTime: number|null, metadata: Trace.Types.File.MetaData|null): Promise;\n loadingCompleteForTest(): void;\n}\nexport interface RecordingOptions {\n enableJSSampling?: boolean;\n capturePictures?: boolean;\n captureFilmStrip?: boolean;\n captureSelectorStats?: boolean;\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineController.test.js.map b/public/panels/timeline/TimelineController.test.js.map index d56ceb933..341566fc3 100644 --- a/public/panels/timeline/TimelineController.test.js.map +++ b/public/panels/timeline/TimelineController.test.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineController.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineController.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as SDK from '../../core/sdk/sdk.js';\nimport type * as TraceEngine from '../../models/trace/trace.js';\nimport {renderElementIntoDOM} from '../../testing/DOMHelpers.js';\nimport {describeWithRealConnection} from '../../testing/RealConnection.js';\n\nimport * as Timeline from './timeline.js';\n\ndescribeWithRealConnection('TimelineController', () => {\n it('calls the callback methods on the client in the expected order', async function() {\n // The test needs at least 0.5s to have progress events be sent. Set a higher timeout to avoid flakiness.\n if (this.timeout() !== 0) {\n this.timeout(5_000);\n }\n const stubs = {\n recordingProgress: sinon.stub(),\n loadingStarted: sinon.stub(),\n processingStarted: sinon.stub(),\n loadingProgress: sinon.stub(),\n loadingComplete: sinon.stub().callsFake(function(\n _collectedEvents: TraceEngine.Types.TraceEvents.TraceEventData[],\n ) {}),\n };\n const client: Timeline.TimelineController.Client = {\n recordingProgress(usage) {\n stubs.recordingProgress(usage);\n },\n loadingStarted() {\n stubs.loadingStarted();\n },\n processingStarted() {\n stubs.processingStarted();\n },\n loadingProgress() {\n stubs.loadingProgress();\n },\n async loadingComplete(collectedEvents) {\n stubs.loadingComplete(collectedEvents);\n },\n loadingCompleteForTest() {},\n };\n\n const primaryPage = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n if (!primaryPage) {\n throw new Error('Could not find primary page');\n }\n const root = SDK.TargetManager.TargetManager.instance().rootTarget();\n if (!root) {\n throw new Error('Could not find root target');\n }\n\n const controller = new Timeline.TimelineController.TimelineController(root, primaryPage, client);\n\n class TestTracingComponent extends HTMLElement {\n connectedCallback() {\n const newDiv = document.createElement('div');\n newDiv.innerHTML = 'testing';\n this.appendChild(newDiv);\n }\n }\n customElements.define('test-tracing-component', TestTracingComponent);\n const component = new TestTracingComponent();\n\n // Start a recording and inject the test component to trigger some trace events.\n await controller.startRecording({});\n renderElementIntoDOM(component);\n // Run the test for at least 0.5s to have progress events be sent.\n await new Promise(resolve => setTimeout(resolve, 1500));\n await controller.stopRecording();\n assert.strictEqual(stubs.processingStarted.callCount, 1);\n // Depending on the speed of the machine you might get more than 1 progress\n // call, hence we assert that there is at least one.\n assert.isAtLeast(stubs.recordingProgress.callCount, 1);\n assert.strictEqual(stubs.loadingStarted.callCount, 1);\n assert.isAtLeast(stubs.loadingProgress.callCount, 1);\n assert.strictEqual(stubs.loadingComplete.callCount, 1);\n const [collectedEvents] = stubs.loadingComplete.getCall(0).args as [TraceEngine.Types.TraceEvents.TraceEventData[]];\n // Ensure we collected events during tracing.\n assert.isTrue(collectedEvents.length > 0);\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"TimelineController.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineController.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as SDK from '../../core/sdk/sdk.js';\nimport type * as Trace from '../../models/trace/trace.js';\nimport {renderElementIntoDOM} from '../../testing/DOMHelpers.js';\nimport {describeWithRealConnection} from '../../testing/RealConnection.js';\n\nimport * as Timeline from './timeline.js';\n\ndescribeWithRealConnection('TimelineController', () => {\n it('calls the callback methods on the client in the expected order', async function() {\n // The test needs at least 0.5s to have progress events be sent. Set a higher timeout to avoid flakiness.\n if (this.timeout() !== 0) {\n this.timeout(5_000);\n }\n const stubs = {\n recordingProgress: sinon.stub(),\n loadingStarted: sinon.stub(),\n processingStarted: sinon.stub(),\n loadingProgress: sinon.stub(),\n loadingComplete: sinon.stub().callsFake(function(\n _collectedEvents: Trace.Types.Events.Event[],\n ) {}),\n };\n const client: Timeline.TimelineController.Client = {\n recordingProgress(usage) {\n stubs.recordingProgress(usage);\n },\n loadingStarted() {\n stubs.loadingStarted();\n },\n processingStarted() {\n stubs.processingStarted();\n },\n loadingProgress() {\n stubs.loadingProgress();\n },\n async loadingComplete(collectedEvents) {\n stubs.loadingComplete(collectedEvents);\n },\n loadingCompleteForTest() {},\n };\n\n const primaryPage = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n if (!primaryPage) {\n throw new Error('Could not find primary page');\n }\n const root = SDK.TargetManager.TargetManager.instance().rootTarget();\n if (!root) {\n throw new Error('Could not find root target');\n }\n\n const controller = new Timeline.TimelineController.TimelineController(root, primaryPage, client);\n\n class TestTracingComponent extends HTMLElement {\n connectedCallback() {\n const newDiv = document.createElement('div');\n newDiv.innerHTML = 'testing';\n this.appendChild(newDiv);\n }\n }\n customElements.define('test-tracing-component', TestTracingComponent);\n const component = new TestTracingComponent();\n\n // Start a recording and inject the test component to trigger some trace events.\n await controller.startRecording({});\n renderElementIntoDOM(component);\n // Run the test for at least 0.5s to have progress events be sent.\n await new Promise(resolve => setTimeout(resolve, 1500));\n await controller.stopRecording();\n assert.strictEqual(stubs.processingStarted.callCount, 1);\n // Depending on the speed of the machine you might get more than 1 progress\n // call, hence we assert that there is at least one.\n assert.isAtLeast(stubs.recordingProgress.callCount, 1);\n assert.strictEqual(stubs.loadingStarted.callCount, 1);\n assert.isAtLeast(stubs.loadingProgress.callCount, 1);\n assert.strictEqual(stubs.loadingComplete.callCount, 1);\n const [collectedEvents] = stubs.loadingComplete.getCall(0).args as [Trace.Types.Events.Event[]];\n // Ensure we collected events during tracing.\n assert.isTrue(collectedEvents.length > 0);\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineDetailsView.d.ts b/public/panels/timeline/TimelineDetailsView.d.ts index 0e132dadb..1f4aa66a3 100644 --- a/public/panels/timeline/TimelineDetailsView.d.ts +++ b/public/panels/timeline/TimelineDetailsView.d.ts @@ -1,4 +1,4 @@ -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as UI from '../../ui/legacy/legacy.js'; import { type TimelineModeViewDelegate } from './TimelinePanel.js'; import { TimelineSelection } from './TimelineSelection.js'; @@ -18,7 +18,7 @@ export declare class TimelineDetailsView extends UI.Widget.VBox { constructor(delegate: TimelineModeViewDelegate); private selectorStatsView; getDetailsContentElementForTest(): HTMLElement; - setModel(traceEngineData: TraceEngine.Handlers.Types.TraceParseData | null, selectedEvents: TraceEngine.Types.TraceEvents.TraceEventData[] | null, traceInsightsData: TraceEngine.Insights.Types.TraceInsightData | null): Promise; + setModel(parsedTrace: Trace.Handlers.Types.ParsedTrace | null, selectedEvents: Trace.Types.Events.Event[] | null, traceInsightsSets: Trace.Insights.Types.TraceInsightSets | null): Promise; private setContent; private updateContents; private appendTab; diff --git a/public/panels/timeline/TimelineDetailsView.js b/public/panels/timeline/TimelineDetailsView.js index fca5c395c..70674007d 100644 --- a/public/panels/timeline/TimelineDetailsView.js +++ b/public/panels/timeline/TimelineDetailsView.js @@ -6,7 +6,7 @@ import * as i18n from '../../core/i18n/i18n.js'; import * as Root from '../../core/root/root.js'; import * as SDK from '../../core/sdk/sdk.js'; import * as TimelineModel from '../../models/timeline_model/timeline_model.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as TraceBounds from '../../services/trace_bounds/trace_bounds.js'; import * as Components from '../../ui/legacy/components/utils/utils.js'; import * as UI from '../../ui/legacy/legacy.js'; @@ -72,8 +72,8 @@ export class TimelineDetailsView extends UI.Widget.VBox { selection; updateContentsScheduled; lazySelectorStatsView; - #traceEngineData = null; - #traceInsightsData = null; + #parsedTrace = null; + #traceInsightsSets = null; #filmStrip = null; #networkRequestDetails; #layoutShiftDetails; @@ -114,7 +114,7 @@ export class TimelineDetailsView extends UI.Widget.VBox { if (this.lazySelectorStatsView) { return this.lazySelectorStatsView; } - this.lazySelectorStatsView = new TimelineSelectorStatsView(this.#traceEngineData); + this.lazySelectorStatsView = new TimelineSelectorStatsView(this.#parsedTrace); return this.lazySelectorStatsView; } getDetailsContentElementForTest() { @@ -136,21 +136,21 @@ export class TimelineDetailsView extends UI.Widget.VBox { } } } - async setModel(traceEngineData, selectedEvents, traceInsightsData) { - if (this.#traceEngineData !== traceEngineData) { + async setModel(parsedTrace, selectedEvents, traceInsightsSets) { + if (this.#parsedTrace !== parsedTrace) { // Clear the selector stats view, so the next time the user views it we // reconstruct it with the new trace data. this.lazySelectorStatsView = null; - this.#traceEngineData = traceEngineData; + this.#parsedTrace = parsedTrace; } - if (traceEngineData) { - this.#filmStrip = TraceEngine.Extras.FilmStrip.fromTraceData(traceEngineData); + if (parsedTrace) { + this.#filmStrip = Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace); } this.#selectedEvents = selectedEvents; - this.#traceInsightsData = traceInsightsData; + this.#traceInsightsSets = traceInsightsSets; this.tabbedPane.closeTabs([Tab.PaintProfiler, Tab.LayerViewer], false); for (const view of this.rangeDetailViews.values()) { - view.setModelWithEvents(selectedEvents, traceEngineData); + view.setModelWithEvents(selectedEvents, parsedTrace); } this.lazyPaintProfilerView = null; this.lazyLayersView = null; @@ -199,7 +199,7 @@ export class TimelineDetailsView extends UI.Widget.VBox { * behaviour. */ scheduleUpdateContentsFromWindow(forceImmediateUpdate = false) { - if (!this.#traceEngineData) { + if (!this.#parsedTrace) { this.setContent(UI.Fragment.html `
`); return; } @@ -230,15 +230,15 @@ export class TimelineDetailsView extends UI.Widget.VBox { return null; } const screenshotTime = (frame.idle ? frame.startTime : frame.endTime); - const filmStripFrame = TraceEngine.Extras.FilmStrip.frameClosestToTimestamp(this.#filmStrip, screenshotTime); + const filmStripFrame = Trace.Extras.FilmStrip.frameClosestToTimestamp(this.#filmStrip, screenshotTime); if (!filmStripFrame) { return null; } - const frameTimeMilliSeconds = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(filmStripFrame.screenshotEvent.ts); + const frameTimeMilliSeconds = Trace.Helpers.Timing.microSecondsToMilliseconds(filmStripFrame.screenshotEvent.ts); return frameTimeMilliSeconds - frame.endTime < 10 ? filmStripFrame : null; } async setSelection(selection) { - if (!this.#traceEngineData) { + if (!this.#parsedTrace) { // You can't make a selection if we have no trace data. return; } @@ -253,20 +253,20 @@ export class TimelineDetailsView extends UI.Widget.VBox { const selectionObject = this.selection.object; if (TimelineSelection.isSyntheticNetworkRequestDetailsEventSelection(selectionObject)) { const networkRequest = selectionObject; - const maybeTarget = targetForEvent(this.#traceEngineData, networkRequest); - await this.#networkRequestDetails.setData(this.#traceEngineData, networkRequest, maybeTarget); + const maybeTarget = targetForEvent(this.#parsedTrace, networkRequest); + await this.#networkRequestDetails.setData(this.#parsedTrace, networkRequest, maybeTarget); this.setContent(this.#networkRequestDetails); } - else if (TimelineSelection.isTraceEventSelection(selectionObject)) { + else if (TimelineSelection.isSelection(selectionObject)) { const event = selectionObject; if (Root.Runtime.experiments.isEnabled("timeline-layout-shift-details" /* Root.Runtime.ExperimentName.TIMELINE_LAYOUT_SHIFT_DETAILS */) && - TraceEngine.Types.TraceEvents.isSyntheticLayoutShift(event)) { - const isFreshRecording = Boolean(this.#traceEngineData && Tracker.instance().recordingIsFresh(this.#traceEngineData)); - this.#layoutShiftDetails.setData(event, this.#traceInsightsData, this.#traceEngineData, isFreshRecording); + Trace.Types.Events.isSyntheticLayoutShift(event)) { + const isFreshRecording = Boolean(this.#parsedTrace && Tracker.instance().recordingIsFresh(this.#parsedTrace)); + this.#layoutShiftDetails.setData(event, this.#traceInsightsSets, this.#parsedTrace, isFreshRecording); this.setContent(this.#layoutShiftDetails); } else { - const traceEventDetails = await TimelineUIUtils.buildTraceEventDetails(this.#traceEngineData, event, this.detailsLinkifier, true); + const traceEventDetails = await TimelineUIUtils.buildTraceEventDetails(this.#parsedTrace, event, this.detailsLinkifier, true); this.appendDetailsTabsForTraceEventAndShowDetails(event, traceEventDetails); } } @@ -307,10 +307,10 @@ export class TimelineDetailsView extends UI.Widget.VBox { if (this.lazyPaintProfilerView) { return this.lazyPaintProfilerView; } - if (!this.#traceEngineData) { + if (!this.#parsedTrace) { return null; } - this.lazyPaintProfilerView = new TimelinePaintProfilerView(this.#traceEngineData); + this.lazyPaintProfilerView = new TimelinePaintProfilerView(this.#parsedTrace); return this.lazyPaintProfilerView; } showSnapshotInPaintProfiler(snapshot) { @@ -336,11 +336,10 @@ export class TimelineDetailsView extends UI.Widget.VBox { } appendDetailsTabsForTraceEventAndShowDetails(event, content) { this.setContent(content); - if (TraceEngine.Types.TraceEvents.isTraceEventPaint(event) || - TraceEngine.Types.TraceEvents.isTraceEventRasterTask(event)) { + if (Trace.Types.Events.isPaint(event) || Trace.Types.Events.isRasterTask(event)) { this.showEventInPaintProfiler(event); } - if (TraceEngine.Types.TraceEvents.isTraceEventUpdateLayoutTree(event)) { + if (Trace.Types.Events.isUpdateLayoutTree(event)) { this.showSelectorStatsForIndividualEvent(event); } } @@ -363,10 +362,10 @@ export class TimelineDetailsView extends UI.Widget.VBox { this.appendTab(Tab.PaintProfiler, i18nString(UIStrings.paintProfiler), paintProfilerView); } updateSelectedRangeStats(startTime, endTime) { - if (!this.#selectedEvents || !this.#traceEngineData) { + if (!this.#selectedEvents || !this.#parsedTrace) { return; } - const minBoundsMilli = TraceEngine.Helpers.Timing.traceWindowMilliSeconds(this.#traceEngineData.Meta.traceBounds).min; + const minBoundsMilli = Trace.Helpers.Timing.traceWindowMilliSeconds(this.#parsedTrace.Meta.traceBounds).min; const aggregatedStats = TimelineUIUtils.statsForTimeRange(this.#selectedEvents, startTime, endTime); const startOffset = startTime - minBoundsMilli; const endOffset = endTime - minBoundsMilli; @@ -378,7 +377,7 @@ export class TimelineDetailsView extends UI.Widget.VBox { // Find all recalculate style events data from range const isSelectorStatsEnabled = Common.Settings.Settings.instance().createSetting('timeline-capture-selector-stats', false).get(); if (this.#selectedEvents && isSelectorStatsEnabled) { - const eventsInRange = TraceEngine.Helpers.Trace.findUpdateLayoutTreeEvents(this.#selectedEvents, TraceEngine.Helpers.Timing.millisecondsToMicroseconds(startTime), TraceEngine.Helpers.Timing.millisecondsToMicroseconds(endTime)); + const eventsInRange = Trace.Helpers.Trace.findUpdateLayoutTreeEvents(this.#selectedEvents, Trace.Helpers.Timing.millisecondsToMicroseconds(startTime), Trace.Helpers.Timing.millisecondsToMicroseconds(endTime)); if (eventsInRange.length > 0) { this.showAggregatedSelectorStats(eventsInRange); } diff --git a/public/panels/timeline/TimelineDetailsView.js.map b/public/panels/timeline/TimelineDetailsView.js.map index bd6904ffa..03e6c8fc9 100644 --- a/public/panels/timeline/TimelineDetailsView.js.map +++ b/public/panels/timeline/TimelineDetailsView.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineDetailsView.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineDetailsView.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Root from '../../core/root/root.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as TraceBounds from '../../services/trace_bounds/trace_bounds.js';\nimport * as Components from '../../ui/legacy/components/utils/utils.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport * as TimelineComponents from './components/components.js';\nimport {EventsTimelineTreeView} from './EventsTimelineTreeView.js';\nimport {Tracker} from './FreshRecording.js';\nimport {targetForEvent} from './TargetForEvent.js';\nimport {TimelineLayersView} from './TimelineLayersView.js';\nimport {TimelinePaintProfilerView} from './TimelinePaintProfilerView.js';\nimport {type TimelineModeViewDelegate} from './TimelinePanel.js';\nimport {TimelineSelection} from './TimelineSelection.js';\nimport {TimelineSelectorStatsView} from './TimelineSelectorStatsView.js';\nimport {BottomUpTimelineTreeView, CallTreeTimelineTreeView, type TimelineTreeView} from './TimelineTreeView.js';\nimport {TimelineDetailsContentHelper, TimelineUIUtils} from './TimelineUIUtils.js';\n\nconst UIStrings = {\n /**\n *@description Text for the summary view\n */\n summary: 'Summary',\n /**\n *@description Text in Timeline Details View of the Performance panel\n */\n bottomup: 'Bottom-up',\n /**\n *@description Text in Timeline Details View of the Performance panel\n */\n callTree: 'Call tree',\n /**\n *@description Text in Timeline Details View of the Performance panel\n */\n eventLog: 'Event log',\n /**\n *@description Title of the paint profiler, old name of the performance pane\n */\n paintProfiler: 'Paint profiler',\n /**\n *@description Title of the Layers tool\n */\n layers: 'Layers',\n /**\n *@description Text in Timeline Details View of the Performance panel\n *@example {1ms} PH1\n *@example {10ms} PH2\n */\n rangeSS: 'Range: {PH1} – {PH2}',\n /**\n *@description Title of the selector stats tab\n */\n selectorStats: 'Selector stats',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelineDetailsView.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nexport class TimelineDetailsView extends UI.Widget.VBox {\n private readonly detailsLinkifier: Components.Linkifier.Linkifier;\n private tabbedPane: UI.TabbedPane.TabbedPane;\n private readonly defaultDetailsWidget: UI.Widget.VBox;\n private readonly defaultDetailsContentElement: HTMLElement;\n private rangeDetailViews: Map;\n #selectedEvents?: TraceEngine.Types.TraceEvents.TraceEventData[]|null;\n private lazyPaintProfilerView?: TimelinePaintProfilerView|null;\n private lazyLayersView?: TimelineLayersView|null;\n private preferredTabId?: string;\n private selection?: TimelineSelection|null;\n private updateContentsScheduled: boolean;\n private lazySelectorStatsView: TimelineSelectorStatsView|null;\n #traceEngineData: TraceEngine.Handlers.Types.TraceParseData|null = null;\n #traceInsightsData: TraceEngine.Insights.Types.TraceInsightData|null = null;\n #filmStrip: TraceEngine.Extras.FilmStrip.Data|null = null;\n #networkRequestDetails: TimelineComponents.NetworkRequestDetails.NetworkRequestDetails;\n #layoutShiftDetails: TimelineComponents.LayoutShiftDetails.LayoutShiftDetails;\n #onTraceBoundsChangeBound = this.#onTraceBoundsChange.bind(this);\n\n constructor(delegate: TimelineModeViewDelegate) {\n super();\n this.element.classList.add('timeline-details');\n\n this.detailsLinkifier = new Components.Linkifier.Linkifier();\n\n this.tabbedPane = new UI.TabbedPane.TabbedPane();\n this.tabbedPane.show(this.element);\n this.tabbedPane.headerElement().setAttribute(\n 'jslog',\n `${VisualLogging.toolbar('sidebar').track({keydown: 'ArrowUp|ArrowLeft|ArrowDown|ArrowRight|Enter|Space'})}`);\n\n this.defaultDetailsWidget = new UI.Widget.VBox();\n this.defaultDetailsWidget.element.classList.add('timeline-details-view');\n this.defaultDetailsWidget.element.setAttribute('jslog', `${VisualLogging.pane('details').track({resize: true})}`);\n this.defaultDetailsContentElement =\n this.defaultDetailsWidget.element.createChild('div', 'timeline-details-view-body vbox');\n this.appendTab(Tab.Details, i18nString(UIStrings.summary), this.defaultDetailsWidget);\n this.setPreferredTab(Tab.Details);\n\n this.rangeDetailViews = new Map();\n this.updateContentsScheduled = false;\n\n const bottomUpView = new BottomUpTimelineTreeView();\n this.appendTab(Tab.BottomUp, i18nString(UIStrings.bottomup), bottomUpView);\n this.rangeDetailViews.set(Tab.BottomUp, bottomUpView);\n\n const callTreeView = new CallTreeTimelineTreeView();\n this.appendTab(Tab.CallTree, i18nString(UIStrings.callTree), callTreeView);\n this.rangeDetailViews.set(Tab.CallTree, callTreeView);\n\n const eventsView = new EventsTimelineTreeView(delegate);\n this.appendTab(Tab.EventLog, i18nString(UIStrings.eventLog), eventsView);\n this.rangeDetailViews.set(Tab.EventLog, eventsView);\n\n this.#networkRequestDetails =\n new TimelineComponents.NetworkRequestDetails.NetworkRequestDetails(this.detailsLinkifier);\n\n this.#layoutShiftDetails = new TimelineComponents.LayoutShiftDetails.LayoutShiftDetails();\n\n this.tabbedPane.addEventListener(UI.TabbedPane.Events.TabSelected, this.tabSelected, this);\n\n TraceBounds.TraceBounds.onChange(this.#onTraceBoundsChangeBound);\n\n this.lazySelectorStatsView = null;\n }\n\n private selectorStatsView(): TimelineSelectorStatsView {\n if (this.lazySelectorStatsView) {\n return this.lazySelectorStatsView;\n }\n\n this.lazySelectorStatsView = new TimelineSelectorStatsView(\n this.#traceEngineData,\n );\n return this.lazySelectorStatsView;\n }\n\n getDetailsContentElementForTest(): HTMLElement {\n return this.defaultDetailsContentElement;\n }\n\n async #onTraceBoundsChange(event: TraceBounds.TraceBounds.StateChangedEvent): Promise {\n if (event.updateType === 'MINIMAP_BOUNDS') {\n // If new minimap bounds are set, we might need to update the selected entry summary because\n // the links to other entries (ex. initiator) might be outside of the new breadcrumb.\n if (this.selection) {\n await this.setSelection(this.selection);\n }\n }\n\n if (event.updateType === 'RESET' || event.updateType === 'VISIBLE_WINDOW') {\n // If the update type was a changing of the minimap bounds, we do not\n // need to redraw.\n if (!this.selection) {\n this.scheduleUpdateContentsFromWindow();\n }\n }\n }\n\n async setModel(\n traceEngineData: TraceEngine.Handlers.Types.TraceParseData|null,\n selectedEvents: TraceEngine.Types.TraceEvents.TraceEventData[]|null,\n traceInsightsData: TraceEngine.Insights.Types.TraceInsightData|null): Promise {\n if (this.#traceEngineData !== traceEngineData) {\n // Clear the selector stats view, so the next time the user views it we\n // reconstruct it with the new trace data.\n this.lazySelectorStatsView = null;\n\n this.#traceEngineData = traceEngineData;\n }\n if (traceEngineData) {\n this.#filmStrip = TraceEngine.Extras.FilmStrip.fromTraceData(traceEngineData);\n }\n this.#selectedEvents = selectedEvents;\n this.#traceInsightsData = traceInsightsData;\n this.tabbedPane.closeTabs([Tab.PaintProfiler, Tab.LayerViewer], false);\n for (const view of this.rangeDetailViews.values()) {\n view.setModelWithEvents(selectedEvents, traceEngineData);\n }\n this.lazyPaintProfilerView = null;\n this.lazyLayersView = null;\n await this.setSelection(null);\n }\n\n private setContent(node: Node): void {\n const allTabs = this.tabbedPane.otherTabs(Tab.Details);\n for (let i = 0; i < allTabs.length; ++i) {\n if (!this.rangeDetailViews.has(allTabs[i])) {\n this.tabbedPane.closeTab(allTabs[i]);\n }\n }\n this.defaultDetailsContentElement.removeChildren();\n this.defaultDetailsContentElement.appendChild(node);\n }\n\n private updateContents(): void {\n const view = this.rangeDetailViews.get(this.tabbedPane.selectedTabId || '');\n if (view) {\n const traceBoundsState = TraceBounds.TraceBounds.BoundsManager.instance().state();\n if (!traceBoundsState) {\n return;\n }\n const visibleWindow = traceBoundsState.milli.timelineTraceWindow;\n view.updateContents(this.selection || TimelineSelection.fromRange(visibleWindow.min, visibleWindow.max));\n }\n }\n\n private appendTab(id: string, tabTitle: string, view: UI.Widget.Widget, isCloseable?: boolean): void {\n this.tabbedPane.appendTab(id, tabTitle, view, undefined, undefined, isCloseable);\n if (this.preferredTabId !== this.tabbedPane.selectedTabId) {\n this.tabbedPane.selectTab(id);\n }\n }\n\n headerElement(): Element {\n return this.tabbedPane.headerElement();\n }\n\n setPreferredTab(tabId: string): void {\n this.preferredTabId = tabId;\n }\n\n /**\n * This forces a recalculation and rerendering of the timings\n * breakdown of a track.\n * User actions like zooming or scrolling can trigger many updates in\n * short time windows, so we debounce the calls in those cases. Single\n * sporadic calls (like selecting a new track) don't need to be\n * debounced. The forceImmediateUpdate param configures the debouncing\n * behaviour.\n */\n private scheduleUpdateContentsFromWindow(forceImmediateUpdate: boolean = false): void {\n if (!this.#traceEngineData) {\n this.setContent(UI.Fragment.html`
`);\n return;\n }\n if (forceImmediateUpdate) {\n this.updateContentsFromWindow();\n return;\n }\n\n // Debounce this update as it's not critical.\n if (!this.updateContentsScheduled) {\n this.updateContentsScheduled = true;\n setTimeout(() => {\n this.updateContentsScheduled = false;\n this.updateContentsFromWindow();\n }, 100);\n }\n }\n\n private updateContentsFromWindow(): void {\n const traceBoundsState = TraceBounds.TraceBounds.BoundsManager.instance().state();\n if (!traceBoundsState) {\n return;\n }\n const visibleWindow = traceBoundsState.milli.timelineTraceWindow;\n this.updateSelectedRangeStats(visibleWindow.min, visibleWindow.max);\n this.updateContents();\n }\n\n #getFilmStripFrame(frame: TraceEngine.Types.TraceEvents.LegacyTimelineFrame): TraceEngine.Extras.FilmStrip.Frame\n |null {\n if (!this.#filmStrip) {\n return null;\n }\n const screenshotTime = (frame.idle ? frame.startTime : frame.endTime);\n const filmStripFrame = TraceEngine.Extras.FilmStrip.frameClosestToTimestamp(this.#filmStrip, screenshotTime);\n if (!filmStripFrame) {\n return null;\n }\n const frameTimeMilliSeconds =\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds(filmStripFrame.screenshotEvent.ts);\n return frameTimeMilliSeconds - frame.endTime < 10 ? filmStripFrame : null;\n }\n\n async setSelection(selection: TimelineSelection|null): Promise {\n if (!this.#traceEngineData) {\n // You can't make a selection if we have no trace data.\n return;\n }\n this.detailsLinkifier.reset();\n this.selection = selection;\n if (!this.selection) {\n // Update instantly using forceImmediateUpdate, since we are only\n // making a single call and don't need to debounce.\n this.scheduleUpdateContentsFromWindow(/* forceImmediateUpdate */ true);\n return;\n }\n const selectionObject = this.selection.object;\n if (TimelineSelection.isSyntheticNetworkRequestDetailsEventSelection(selectionObject)) {\n const networkRequest = selectionObject;\n const maybeTarget = targetForEvent(this.#traceEngineData, networkRequest);\n await this.#networkRequestDetails.setData(this.#traceEngineData, networkRequest, maybeTarget);\n this.setContent(this.#networkRequestDetails);\n } else if (TimelineSelection.isTraceEventSelection(selectionObject)) {\n const event = selectionObject;\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_LAYOUT_SHIFT_DETAILS) &&\n TraceEngine.Types.TraceEvents.isSyntheticLayoutShift(event)) {\n const isFreshRecording =\n Boolean(this.#traceEngineData && Tracker.instance().recordingIsFresh(this.#traceEngineData));\n this.#layoutShiftDetails.setData(event, this.#traceInsightsData, this.#traceEngineData, isFreshRecording);\n this.setContent(this.#layoutShiftDetails);\n } else {\n const traceEventDetails =\n await TimelineUIUtils.buildTraceEventDetails(this.#traceEngineData, event, this.detailsLinkifier, true);\n this.appendDetailsTabsForTraceEventAndShowDetails(event, traceEventDetails);\n }\n } else if (TimelineSelection.isLegacyTimelineFrame(selectionObject)) {\n const frame = selectionObject;\n const matchedFilmStripFrame = this.#getFilmStripFrame(frame);\n this.setContent(TimelineUIUtils.generateDetailsContentForFrame(frame, this.#filmStrip, matchedFilmStripFrame));\n const target = SDK.TargetManager.TargetManager.instance().rootTarget();\n if (frame.layerTree && target) {\n const layerTreeForFrame = new TimelineModel.TracingLayerTree.TracingFrameLayerTree(target, frame.layerTree);\n const layersView = this.layersView();\n layersView.showLayerTree(layerTreeForFrame);\n if (!this.tabbedPane.hasTab(Tab.LayerViewer)) {\n this.appendTab(Tab.LayerViewer, i18nString(UIStrings.layers), layersView);\n }\n }\n } else if (TimelineSelection.isRangeSelection(selectionObject)) {\n this.updateSelectedRangeStats(this.selection.startTime, this.selection.endTime);\n }\n\n this.updateContents();\n }\n\n private tabSelected(event: Common.EventTarget.EventTargetEvent): void {\n if (!event.data.isUserGesture) {\n return;\n }\n this.setPreferredTab(event.data.tabId);\n this.updateContents();\n }\n\n private layersView(): TimelineLayersView {\n if (this.lazyLayersView) {\n return this.lazyLayersView;\n }\n this.lazyLayersView = new TimelineLayersView(this.showSnapshotInPaintProfiler.bind(this));\n return this.lazyLayersView;\n }\n\n private paintProfilerView(): TimelinePaintProfilerView|null {\n if (this.lazyPaintProfilerView) {\n return this.lazyPaintProfilerView;\n }\n if (!this.#traceEngineData) {\n return null;\n }\n this.lazyPaintProfilerView = new TimelinePaintProfilerView(this.#traceEngineData);\n return this.lazyPaintProfilerView;\n }\n\n private showSnapshotInPaintProfiler(snapshot: SDK.PaintProfiler.PaintProfilerSnapshot): void {\n const paintProfilerView = this.paintProfilerView();\n if (!paintProfilerView) {\n return;\n }\n paintProfilerView.setSnapshot(snapshot);\n if (!this.tabbedPane.hasTab(Tab.PaintProfiler)) {\n this.appendTab(Tab.PaintProfiler, i18nString(UIStrings.paintProfiler), paintProfilerView, true);\n }\n this.tabbedPane.selectTab(Tab.PaintProfiler, true);\n }\n\n private showSelectorStatsForIndividualEvent(event: TraceEngine.Types.TraceEvents.TraceEventUpdateLayoutTree): void {\n this.showAggregatedSelectorStats([event]);\n }\n\n private showAggregatedSelectorStats(events: TraceEngine.Types.TraceEvents.TraceEventUpdateLayoutTree[]): void {\n const selectorStatsView = this.selectorStatsView();\n\n selectorStatsView.setAggregatedEvents(events);\n\n if (!this.tabbedPane.hasTab(Tab.SelectorStats)) {\n this.appendTab(Tab.SelectorStats, i18nString(UIStrings.selectorStats), selectorStatsView);\n }\n }\n\n private appendDetailsTabsForTraceEventAndShowDetails(\n event: TraceEngine.Types.TraceEvents.TraceEventData, content: Node): void {\n this.setContent(content);\n if (TraceEngine.Types.TraceEvents.isTraceEventPaint(event) ||\n TraceEngine.Types.TraceEvents.isTraceEventRasterTask(event)) {\n this.showEventInPaintProfiler(event);\n }\n\n if (TraceEngine.Types.TraceEvents.isTraceEventUpdateLayoutTree(event)) {\n this.showSelectorStatsForIndividualEvent(event);\n }\n }\n\n private showEventInPaintProfiler(event: TraceEngine.Types.TraceEvents.TraceEventData): void {\n const paintProfilerModel =\n SDK.TargetManager.TargetManager.instance().models(SDK.PaintProfiler.PaintProfilerModel)[0];\n if (!paintProfilerModel) {\n return;\n }\n const paintProfilerView = this.paintProfilerView();\n if (!paintProfilerView) {\n return;\n }\n const hasProfileData = paintProfilerView.setEvent(paintProfilerModel, event);\n if (!hasProfileData) {\n return;\n }\n if (this.tabbedPane.hasTab(Tab.PaintProfiler)) {\n return;\n }\n this.appendTab(Tab.PaintProfiler, i18nString(UIStrings.paintProfiler), paintProfilerView);\n }\n\n private updateSelectedRangeStats(\n startTime: TraceEngine.Types.Timing.MilliSeconds, endTime: TraceEngine.Types.Timing.MilliSeconds): void {\n if (!this.#selectedEvents || !this.#traceEngineData) {\n return;\n }\n\n const minBoundsMilli =\n TraceEngine.Helpers.Timing.traceWindowMilliSeconds(this.#traceEngineData.Meta.traceBounds).min;\n const aggregatedStats = TimelineUIUtils.statsForTimeRange(this.#selectedEvents, startTime, endTime);\n const startOffset = startTime - minBoundsMilli;\n const endOffset = endTime - minBoundsMilli;\n\n const contentHelper = new TimelineDetailsContentHelper(null, null);\n contentHelper.addSection(i18nString(\n UIStrings.rangeSS,\n {PH1: i18n.TimeUtilities.millisToString(startOffset), PH2: i18n.TimeUtilities.millisToString(endOffset)}));\n const pieChart = TimelineUIUtils.generatePieChart(aggregatedStats);\n contentHelper.appendElementRow('', pieChart);\n this.setContent(contentHelper.fragment);\n\n // Find all recalculate style events data from range\n const isSelectorStatsEnabled =\n Common.Settings.Settings.instance().createSetting('timeline-capture-selector-stats', false).get();\n if (this.#selectedEvents && isSelectorStatsEnabled) {\n const eventsInRange = TraceEngine.Helpers.Trace.findUpdateLayoutTreeEvents(\n this.#selectedEvents,\n TraceEngine.Helpers.Timing.millisecondsToMicroseconds(startTime),\n TraceEngine.Helpers.Timing.millisecondsToMicroseconds(endTime),\n );\n if (eventsInRange.length > 0) {\n this.showAggregatedSelectorStats(eventsInRange);\n }\n }\n }\n}\n\nexport enum Tab {\n /* eslint-disable @typescript-eslint/naming-convention -- Used by web_tests. */\n Details = 'details',\n EventLog = 'event-log',\n CallTree = 'call-tree',\n BottomUp = 'bottom-up',\n PaintProfiler = 'paint-profiler',\n LayerViewer = 'layer-viewer',\n SelectorStats = 'selector-stats',\n /* eslint-enable @typescript-eslint/naming-convention */\n}\n"]} \ No newline at end of file +{"version":3,"file":"TimelineDetailsView.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineDetailsView.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Root from '../../core/root/root.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as TraceBounds from '../../services/trace_bounds/trace_bounds.js';\nimport * as Components from '../../ui/legacy/components/utils/utils.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport * as TimelineComponents from './components/components.js';\nimport {EventsTimelineTreeView} from './EventsTimelineTreeView.js';\nimport {Tracker} from './FreshRecording.js';\nimport {targetForEvent} from './TargetForEvent.js';\nimport {TimelineLayersView} from './TimelineLayersView.js';\nimport {TimelinePaintProfilerView} from './TimelinePaintProfilerView.js';\nimport {type TimelineModeViewDelegate} from './TimelinePanel.js';\nimport {TimelineSelection} from './TimelineSelection.js';\nimport {TimelineSelectorStatsView} from './TimelineSelectorStatsView.js';\nimport {BottomUpTimelineTreeView, CallTreeTimelineTreeView, type TimelineTreeView} from './TimelineTreeView.js';\nimport {TimelineDetailsContentHelper, TimelineUIUtils} from './TimelineUIUtils.js';\n\nconst UIStrings = {\n /**\n *@description Text for the summary view\n */\n summary: 'Summary',\n /**\n *@description Text in Timeline Details View of the Performance panel\n */\n bottomup: 'Bottom-up',\n /**\n *@description Text in Timeline Details View of the Performance panel\n */\n callTree: 'Call tree',\n /**\n *@description Text in Timeline Details View of the Performance panel\n */\n eventLog: 'Event log',\n /**\n *@description Title of the paint profiler, old name of the performance pane\n */\n paintProfiler: 'Paint profiler',\n /**\n *@description Title of the Layers tool\n */\n layers: 'Layers',\n /**\n *@description Text in Timeline Details View of the Performance panel\n *@example {1ms} PH1\n *@example {10ms} PH2\n */\n rangeSS: 'Range: {PH1} – {PH2}',\n /**\n *@description Title of the selector stats tab\n */\n selectorStats: 'Selector stats',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelineDetailsView.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nexport class TimelineDetailsView extends UI.Widget.VBox {\n private readonly detailsLinkifier: Components.Linkifier.Linkifier;\n private tabbedPane: UI.TabbedPane.TabbedPane;\n private readonly defaultDetailsWidget: UI.Widget.VBox;\n private readonly defaultDetailsContentElement: HTMLElement;\n private rangeDetailViews: Map;\n #selectedEvents?: Trace.Types.Events.Event[]|null;\n private lazyPaintProfilerView?: TimelinePaintProfilerView|null;\n private lazyLayersView?: TimelineLayersView|null;\n private preferredTabId?: string;\n private selection?: TimelineSelection|null;\n private updateContentsScheduled: boolean;\n private lazySelectorStatsView: TimelineSelectorStatsView|null;\n #parsedTrace: Trace.Handlers.Types.ParsedTrace|null = null;\n #traceInsightsSets: Trace.Insights.Types.TraceInsightSets|null = null;\n #filmStrip: Trace.Extras.FilmStrip.Data|null = null;\n #networkRequestDetails: TimelineComponents.NetworkRequestDetails.NetworkRequestDetails;\n #layoutShiftDetails: TimelineComponents.LayoutShiftDetails.LayoutShiftDetails;\n #onTraceBoundsChangeBound = this.#onTraceBoundsChange.bind(this);\n\n constructor(delegate: TimelineModeViewDelegate) {\n super();\n this.element.classList.add('timeline-details');\n\n this.detailsLinkifier = new Components.Linkifier.Linkifier();\n\n this.tabbedPane = new UI.TabbedPane.TabbedPane();\n this.tabbedPane.show(this.element);\n this.tabbedPane.headerElement().setAttribute(\n 'jslog',\n `${VisualLogging.toolbar('sidebar').track({keydown: 'ArrowUp|ArrowLeft|ArrowDown|ArrowRight|Enter|Space'})}`);\n\n this.defaultDetailsWidget = new UI.Widget.VBox();\n this.defaultDetailsWidget.element.classList.add('timeline-details-view');\n this.defaultDetailsWidget.element.setAttribute('jslog', `${VisualLogging.pane('details').track({resize: true})}`);\n this.defaultDetailsContentElement =\n this.defaultDetailsWidget.element.createChild('div', 'timeline-details-view-body vbox');\n this.appendTab(Tab.Details, i18nString(UIStrings.summary), this.defaultDetailsWidget);\n this.setPreferredTab(Tab.Details);\n\n this.rangeDetailViews = new Map();\n this.updateContentsScheduled = false;\n\n const bottomUpView = new BottomUpTimelineTreeView();\n this.appendTab(Tab.BottomUp, i18nString(UIStrings.bottomup), bottomUpView);\n this.rangeDetailViews.set(Tab.BottomUp, bottomUpView);\n\n const callTreeView = new CallTreeTimelineTreeView();\n this.appendTab(Tab.CallTree, i18nString(UIStrings.callTree), callTreeView);\n this.rangeDetailViews.set(Tab.CallTree, callTreeView);\n\n const eventsView = new EventsTimelineTreeView(delegate);\n this.appendTab(Tab.EventLog, i18nString(UIStrings.eventLog), eventsView);\n this.rangeDetailViews.set(Tab.EventLog, eventsView);\n\n this.#networkRequestDetails =\n new TimelineComponents.NetworkRequestDetails.NetworkRequestDetails(this.detailsLinkifier);\n\n this.#layoutShiftDetails = new TimelineComponents.LayoutShiftDetails.LayoutShiftDetails();\n\n this.tabbedPane.addEventListener(UI.TabbedPane.Events.TabSelected, this.tabSelected, this);\n\n TraceBounds.TraceBounds.onChange(this.#onTraceBoundsChangeBound);\n\n this.lazySelectorStatsView = null;\n }\n\n private selectorStatsView(): TimelineSelectorStatsView {\n if (this.lazySelectorStatsView) {\n return this.lazySelectorStatsView;\n }\n\n this.lazySelectorStatsView = new TimelineSelectorStatsView(\n this.#parsedTrace,\n );\n return this.lazySelectorStatsView;\n }\n\n getDetailsContentElementForTest(): HTMLElement {\n return this.defaultDetailsContentElement;\n }\n\n async #onTraceBoundsChange(event: TraceBounds.TraceBounds.StateChangedEvent): Promise {\n if (event.updateType === 'MINIMAP_BOUNDS') {\n // If new minimap bounds are set, we might need to update the selected entry summary because\n // the links to other entries (ex. initiator) might be outside of the new breadcrumb.\n if (this.selection) {\n await this.setSelection(this.selection);\n }\n }\n\n if (event.updateType === 'RESET' || event.updateType === 'VISIBLE_WINDOW') {\n // If the update type was a changing of the minimap bounds, we do not\n // need to redraw.\n if (!this.selection) {\n this.scheduleUpdateContentsFromWindow();\n }\n }\n }\n\n async setModel(\n parsedTrace: Trace.Handlers.Types.ParsedTrace|null, selectedEvents: Trace.Types.Events.Event[]|null,\n traceInsightsSets: Trace.Insights.Types.TraceInsightSets|null): Promise {\n if (this.#parsedTrace !== parsedTrace) {\n // Clear the selector stats view, so the next time the user views it we\n // reconstruct it with the new trace data.\n this.lazySelectorStatsView = null;\n\n this.#parsedTrace = parsedTrace;\n }\n if (parsedTrace) {\n this.#filmStrip = Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace);\n }\n this.#selectedEvents = selectedEvents;\n this.#traceInsightsSets = traceInsightsSets;\n this.tabbedPane.closeTabs([Tab.PaintProfiler, Tab.LayerViewer], false);\n for (const view of this.rangeDetailViews.values()) {\n view.setModelWithEvents(selectedEvents, parsedTrace);\n }\n this.lazyPaintProfilerView = null;\n this.lazyLayersView = null;\n await this.setSelection(null);\n }\n\n private setContent(node: Node): void {\n const allTabs = this.tabbedPane.otherTabs(Tab.Details);\n for (let i = 0; i < allTabs.length; ++i) {\n if (!this.rangeDetailViews.has(allTabs[i])) {\n this.tabbedPane.closeTab(allTabs[i]);\n }\n }\n this.defaultDetailsContentElement.removeChildren();\n this.defaultDetailsContentElement.appendChild(node);\n }\n\n private updateContents(): void {\n const view = this.rangeDetailViews.get(this.tabbedPane.selectedTabId || '');\n if (view) {\n const traceBoundsState = TraceBounds.TraceBounds.BoundsManager.instance().state();\n if (!traceBoundsState) {\n return;\n }\n const visibleWindow = traceBoundsState.milli.timelineTraceWindow;\n view.updateContents(this.selection || TimelineSelection.fromRange(visibleWindow.min, visibleWindow.max));\n }\n }\n\n private appendTab(id: string, tabTitle: string, view: UI.Widget.Widget, isCloseable?: boolean): void {\n this.tabbedPane.appendTab(id, tabTitle, view, undefined, undefined, isCloseable);\n if (this.preferredTabId !== this.tabbedPane.selectedTabId) {\n this.tabbedPane.selectTab(id);\n }\n }\n\n headerElement(): Element {\n return this.tabbedPane.headerElement();\n }\n\n setPreferredTab(tabId: string): void {\n this.preferredTabId = tabId;\n }\n\n /**\n * This forces a recalculation and rerendering of the timings\n * breakdown of a track.\n * User actions like zooming or scrolling can trigger many updates in\n * short time windows, so we debounce the calls in those cases. Single\n * sporadic calls (like selecting a new track) don't need to be\n * debounced. The forceImmediateUpdate param configures the debouncing\n * behaviour.\n */\n private scheduleUpdateContentsFromWindow(forceImmediateUpdate: boolean = false): void {\n if (!this.#parsedTrace) {\n this.setContent(UI.Fragment.html`
`);\n return;\n }\n if (forceImmediateUpdate) {\n this.updateContentsFromWindow();\n return;\n }\n\n // Debounce this update as it's not critical.\n if (!this.updateContentsScheduled) {\n this.updateContentsScheduled = true;\n setTimeout(() => {\n this.updateContentsScheduled = false;\n this.updateContentsFromWindow();\n }, 100);\n }\n }\n\n private updateContentsFromWindow(): void {\n const traceBoundsState = TraceBounds.TraceBounds.BoundsManager.instance().state();\n if (!traceBoundsState) {\n return;\n }\n const visibleWindow = traceBoundsState.milli.timelineTraceWindow;\n this.updateSelectedRangeStats(visibleWindow.min, visibleWindow.max);\n this.updateContents();\n }\n\n #getFilmStripFrame(frame: Trace.Types.Events.LegacyTimelineFrame): Trace.Extras.FilmStrip.Frame|null {\n if (!this.#filmStrip) {\n return null;\n }\n const screenshotTime = (frame.idle ? frame.startTime : frame.endTime);\n const filmStripFrame = Trace.Extras.FilmStrip.frameClosestToTimestamp(this.#filmStrip, screenshotTime);\n if (!filmStripFrame) {\n return null;\n }\n const frameTimeMilliSeconds = Trace.Helpers.Timing.microSecondsToMilliseconds(filmStripFrame.screenshotEvent.ts);\n return frameTimeMilliSeconds - frame.endTime < 10 ? filmStripFrame : null;\n }\n\n async setSelection(selection: TimelineSelection|null): Promise {\n if (!this.#parsedTrace) {\n // You can't make a selection if we have no trace data.\n return;\n }\n this.detailsLinkifier.reset();\n this.selection = selection;\n if (!this.selection) {\n // Update instantly using forceImmediateUpdate, since we are only\n // making a single call and don't need to debounce.\n this.scheduleUpdateContentsFromWindow(/* forceImmediateUpdate */ true);\n return;\n }\n const selectionObject = this.selection.object;\n if (TimelineSelection.isSyntheticNetworkRequestDetailsEventSelection(selectionObject)) {\n const networkRequest = selectionObject;\n const maybeTarget = targetForEvent(this.#parsedTrace, networkRequest);\n await this.#networkRequestDetails.setData(this.#parsedTrace, networkRequest, maybeTarget);\n this.setContent(this.#networkRequestDetails);\n } else if (TimelineSelection.isSelection(selectionObject)) {\n const event = selectionObject;\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_LAYOUT_SHIFT_DETAILS) &&\n Trace.Types.Events.isSyntheticLayoutShift(event)) {\n const isFreshRecording = Boolean(this.#parsedTrace && Tracker.instance().recordingIsFresh(this.#parsedTrace));\n this.#layoutShiftDetails.setData(event, this.#traceInsightsSets, this.#parsedTrace, isFreshRecording);\n this.setContent(this.#layoutShiftDetails);\n } else {\n const traceEventDetails =\n await TimelineUIUtils.buildTraceEventDetails(this.#parsedTrace, event, this.detailsLinkifier, true);\n this.appendDetailsTabsForTraceEventAndShowDetails(event, traceEventDetails);\n }\n } else if (TimelineSelection.isLegacyTimelineFrame(selectionObject)) {\n const frame = selectionObject;\n const matchedFilmStripFrame = this.#getFilmStripFrame(frame);\n this.setContent(TimelineUIUtils.generateDetailsContentForFrame(frame, this.#filmStrip, matchedFilmStripFrame));\n const target = SDK.TargetManager.TargetManager.instance().rootTarget();\n if (frame.layerTree && target) {\n const layerTreeForFrame = new TimelineModel.TracingLayerTree.TracingFrameLayerTree(target, frame.layerTree);\n const layersView = this.layersView();\n layersView.showLayerTree(layerTreeForFrame);\n if (!this.tabbedPane.hasTab(Tab.LayerViewer)) {\n this.appendTab(Tab.LayerViewer, i18nString(UIStrings.layers), layersView);\n }\n }\n } else if (TimelineSelection.isRangeSelection(selectionObject)) {\n this.updateSelectedRangeStats(this.selection.startTime, this.selection.endTime);\n }\n\n this.updateContents();\n }\n\n private tabSelected(event: Common.EventTarget.EventTargetEvent): void {\n if (!event.data.isUserGesture) {\n return;\n }\n this.setPreferredTab(event.data.tabId);\n this.updateContents();\n }\n\n private layersView(): TimelineLayersView {\n if (this.lazyLayersView) {\n return this.lazyLayersView;\n }\n this.lazyLayersView = new TimelineLayersView(this.showSnapshotInPaintProfiler.bind(this));\n return this.lazyLayersView;\n }\n\n private paintProfilerView(): TimelinePaintProfilerView|null {\n if (this.lazyPaintProfilerView) {\n return this.lazyPaintProfilerView;\n }\n if (!this.#parsedTrace) {\n return null;\n }\n this.lazyPaintProfilerView = new TimelinePaintProfilerView(this.#parsedTrace);\n return this.lazyPaintProfilerView;\n }\n\n private showSnapshotInPaintProfiler(snapshot: SDK.PaintProfiler.PaintProfilerSnapshot): void {\n const paintProfilerView = this.paintProfilerView();\n if (!paintProfilerView) {\n return;\n }\n paintProfilerView.setSnapshot(snapshot);\n if (!this.tabbedPane.hasTab(Tab.PaintProfiler)) {\n this.appendTab(Tab.PaintProfiler, i18nString(UIStrings.paintProfiler), paintProfilerView, true);\n }\n this.tabbedPane.selectTab(Tab.PaintProfiler, true);\n }\n\n private showSelectorStatsForIndividualEvent(event: Trace.Types.Events.UpdateLayoutTree): void {\n this.showAggregatedSelectorStats([event]);\n }\n\n private showAggregatedSelectorStats(events: Trace.Types.Events.UpdateLayoutTree[]): void {\n const selectorStatsView = this.selectorStatsView();\n\n selectorStatsView.setAggregatedEvents(events);\n\n if (!this.tabbedPane.hasTab(Tab.SelectorStats)) {\n this.appendTab(Tab.SelectorStats, i18nString(UIStrings.selectorStats), selectorStatsView);\n }\n }\n\n private appendDetailsTabsForTraceEventAndShowDetails(event: Trace.Types.Events.Event, content: Node): void {\n this.setContent(content);\n if (Trace.Types.Events.isPaint(event) || Trace.Types.Events.isRasterTask(event)) {\n this.showEventInPaintProfiler(event);\n }\n\n if (Trace.Types.Events.isUpdateLayoutTree(event)) {\n this.showSelectorStatsForIndividualEvent(event);\n }\n }\n\n private showEventInPaintProfiler(event: Trace.Types.Events.Event): void {\n const paintProfilerModel =\n SDK.TargetManager.TargetManager.instance().models(SDK.PaintProfiler.PaintProfilerModel)[0];\n if (!paintProfilerModel) {\n return;\n }\n const paintProfilerView = this.paintProfilerView();\n if (!paintProfilerView) {\n return;\n }\n const hasProfileData = paintProfilerView.setEvent(paintProfilerModel, event);\n if (!hasProfileData) {\n return;\n }\n if (this.tabbedPane.hasTab(Tab.PaintProfiler)) {\n return;\n }\n this.appendTab(Tab.PaintProfiler, i18nString(UIStrings.paintProfiler), paintProfilerView);\n }\n\n private updateSelectedRangeStats(\n startTime: Trace.Types.Timing.MilliSeconds, endTime: Trace.Types.Timing.MilliSeconds): void {\n if (!this.#selectedEvents || !this.#parsedTrace) {\n return;\n }\n\n const minBoundsMilli = Trace.Helpers.Timing.traceWindowMilliSeconds(this.#parsedTrace.Meta.traceBounds).min;\n const aggregatedStats = TimelineUIUtils.statsForTimeRange(this.#selectedEvents, startTime, endTime);\n const startOffset = startTime - minBoundsMilli;\n const endOffset = endTime - minBoundsMilli;\n\n const contentHelper = new TimelineDetailsContentHelper(null, null);\n contentHelper.addSection(i18nString(\n UIStrings.rangeSS,\n {PH1: i18n.TimeUtilities.millisToString(startOffset), PH2: i18n.TimeUtilities.millisToString(endOffset)}));\n const pieChart = TimelineUIUtils.generatePieChart(aggregatedStats);\n contentHelper.appendElementRow('', pieChart);\n this.setContent(contentHelper.fragment);\n\n // Find all recalculate style events data from range\n const isSelectorStatsEnabled =\n Common.Settings.Settings.instance().createSetting('timeline-capture-selector-stats', false).get();\n if (this.#selectedEvents && isSelectorStatsEnabled) {\n const eventsInRange = Trace.Helpers.Trace.findUpdateLayoutTreeEvents(\n this.#selectedEvents,\n Trace.Helpers.Timing.millisecondsToMicroseconds(startTime),\n Trace.Helpers.Timing.millisecondsToMicroseconds(endTime),\n );\n if (eventsInRange.length > 0) {\n this.showAggregatedSelectorStats(eventsInRange);\n }\n }\n }\n}\n\nexport enum Tab {\n /* eslint-disable @typescript-eslint/naming-convention -- Used by web_tests. */\n Details = 'details',\n EventLog = 'event-log',\n CallTree = 'call-tree',\n BottomUp = 'bottom-up',\n PaintProfiler = 'paint-profiler',\n LayerViewer = 'layer-viewer',\n SelectorStats = 'selector-stats',\n /* eslint-enable @typescript-eslint/naming-convention */\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineDetailsView.test.js b/public/panels/timeline/TimelineDetailsView.test.js index e29823f44..ecebf6b9f 100644 --- a/public/panels/timeline/TimelineDetailsView.test.js +++ b/public/panels/timeline/TimelineDetailsView.test.js @@ -26,9 +26,9 @@ function getRowDataForNetworkDetailsElement(details) { describeWithEnvironment('TimelineDetailsView', function () { const mockViewDelegate = new MockViewDelegate(); it('displays the details of a network request event correctly', async function () { - const { traceData, insights } = await TraceLoader.traceEngine(this, 'lcp-web-font.json.gz'); + const { parsedTrace, insights } = await TraceLoader.traceEngine(this, 'lcp-web-font.json.gz'); const detailsView = new Timeline.TimelineDetailsView.TimelineDetailsView(mockViewDelegate); - const networkRequests = traceData.NetworkRequests.byTime; + const networkRequests = parsedTrace.NetworkRequests.byTime; const cssRequest = networkRequests.find(request => { return request.args.data.url === 'https://chromedevtools.github.io/performance-stories/lcp-web-font/app.css'; }); @@ -36,7 +36,7 @@ describeWithEnvironment('TimelineDetailsView', function () { throw new Error('Could not find expected network request.'); } const selection = Timeline.TimelineSelection.TimelineSelection.fromTraceEvent(cssRequest); - await detailsView.setModel(traceData, null, insights); + await detailsView.setModel(parsedTrace, null, insights); await detailsView.setSelection(selection); const detailsContentElement = detailsView.getDetailsContentElementForTest(); assert.strictEqual(detailsContentElement.childNodes.length, 1); diff --git a/public/panels/timeline/TimelineDetailsView.test.js.map b/public/panels/timeline/TimelineDetailsView.test.js.map index 8d8f226d6..6db161409 100644 --- a/public/panels/timeline/TimelineDetailsView.test.js.map +++ b/public/panels/timeline/TimelineDetailsView.test.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineDetailsView.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineDetailsView.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2021 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as TraceEngine from '../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\n\nimport * as Timeline from './timeline.js';\n\nclass MockViewDelegate implements Timeline.TimelinePanel.TimelineModeViewDelegate {\n select(_selection: Timeline.TimelineSelection.TimelineSelection|null): void {\n }\n selectEntryAtTime(_events: TraceEngine.Types.TraceEvents.TraceEventData[]|null, _time: number): void {\n }\n highlightEvent(_event: TraceEngine.Types.TraceEvents.TraceEventData|null): void {\n }\n element = document.createElement('div');\n}\n\nfunction getRowDataForNetworkDetailsElement(details: ShadowRoot) {\n return Array.from(details.querySelectorAll('.network-request-details-row')).map(row => {\n const title = row.querySelector('.title')?.innerText;\n // The innerText in here will contain a `\\n` and a few space for each child
tag, so just remove these empty\n // characters for easier test.\n const regExpForLineBreakAndFollowingSpaces = /\\n[\\s]+/g;\n const value =\n row.querySelector('.value')?.innerText.replaceAll(regExpForLineBreakAndFollowingSpaces, '');\n return {title, value};\n });\n}\n\ndescribeWithEnvironment('TimelineDetailsView', function() {\n const mockViewDelegate = new MockViewDelegate();\n it('displays the details of a network request event correctly', async function() {\n const {traceData, insights} = await TraceLoader.traceEngine(this, 'lcp-web-font.json.gz');\n const detailsView = new Timeline.TimelineDetailsView.TimelineDetailsView(mockViewDelegate);\n\n const networkRequests = traceData.NetworkRequests.byTime;\n const cssRequest = networkRequests.find(request => {\n return request.args.data.url === 'https://chromedevtools.github.io/performance-stories/lcp-web-font/app.css';\n });\n if (!cssRequest) {\n throw new Error('Could not find expected network request.');\n }\n const selection = Timeline.TimelineSelection.TimelineSelection.fromTraceEvent(cssRequest);\n\n await detailsView.setModel(traceData, null, insights);\n await detailsView.setSelection(selection);\n\n const detailsContentElement = detailsView.getDetailsContentElementForTest();\n assert.strictEqual(detailsContentElement.childNodes.length, 1);\n const detailsElementShadowRoot = (detailsContentElement.childNodes[0] as HTMLElement).shadowRoot;\n if (!detailsElementShadowRoot) {\n throw new Error('Could not find expected element to test.');\n }\n const rowData = getRowDataForNetworkDetailsElement(detailsElementShadowRoot);\n\n const durationInnerText = '12.58 ms' +\n 'Queuing and connecting1.83 ms' +\n 'Request sent and waiting4.80 ms' +\n 'Content downloading1.66 ms' +\n 'Waiting on main thread4.29 ms';\n assert.deepEqual(\n rowData,\n [\n {title: 'URL', value: 'chromedevtools.github.io/performance-stories/lcp-web-font/app.css'},\n {title: 'Request method', value: 'GET'},\n {title: 'Initial priority', value: 'Highest'},\n {title: 'Priority', value: 'Highest'},\n {title: 'MIME type', value: 'text/css'},\n {title: 'Encoded data', value: ' (from cache)'},\n {title: 'Decoded body', value: '96 B'},\n {\n title: 'Initiated by',\n value: 'chromedevtools.github.io/performance-stories/lcp-web-font/index.html',\n },\n {title: 'From cache', value: 'Yes'},\n {title: 'Duration', value: durationInnerText},\n ],\n );\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"TimelineDetailsView.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineDetailsView.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2021 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Trace from '../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\n\nimport * as Timeline from './timeline.js';\n\nclass MockViewDelegate implements Timeline.TimelinePanel.TimelineModeViewDelegate {\n select(_selection: Timeline.TimelineSelection.TimelineSelection|null): void {\n }\n selectEntryAtTime(_events: Trace.Types.Events.Event[]|null, _time: number): void {\n }\n highlightEvent(_event: Trace.Types.Events.Event|null): void {\n }\n element = document.createElement('div');\n}\n\nfunction getRowDataForNetworkDetailsElement(details: ShadowRoot) {\n return Array.from(details.querySelectorAll('.network-request-details-row')).map(row => {\n const title = row.querySelector('.title')?.innerText;\n // The innerText in here will contain a `\\n` and a few space for each child
tag, so just remove these empty\n // characters for easier test.\n const regExpForLineBreakAndFollowingSpaces = /\\n[\\s]+/g;\n const value =\n row.querySelector('.value')?.innerText.replaceAll(regExpForLineBreakAndFollowingSpaces, '');\n return {title, value};\n });\n}\n\ndescribeWithEnvironment('TimelineDetailsView', function() {\n const mockViewDelegate = new MockViewDelegate();\n it('displays the details of a network request event correctly', async function() {\n const {parsedTrace, insights} = await TraceLoader.traceEngine(this, 'lcp-web-font.json.gz');\n const detailsView = new Timeline.TimelineDetailsView.TimelineDetailsView(mockViewDelegate);\n\n const networkRequests = parsedTrace.NetworkRequests.byTime;\n const cssRequest = networkRequests.find(request => {\n return request.args.data.url === 'https://chromedevtools.github.io/performance-stories/lcp-web-font/app.css';\n });\n if (!cssRequest) {\n throw new Error('Could not find expected network request.');\n }\n const selection = Timeline.TimelineSelection.TimelineSelection.fromTraceEvent(cssRequest);\n\n await detailsView.setModel(parsedTrace, null, insights);\n await detailsView.setSelection(selection);\n\n const detailsContentElement = detailsView.getDetailsContentElementForTest();\n assert.strictEqual(detailsContentElement.childNodes.length, 1);\n const detailsElementShadowRoot = (detailsContentElement.childNodes[0] as HTMLElement).shadowRoot;\n if (!detailsElementShadowRoot) {\n throw new Error('Could not find expected element to test.');\n }\n const rowData = getRowDataForNetworkDetailsElement(detailsElementShadowRoot);\n\n const durationInnerText = '12.58 ms' +\n 'Queuing and connecting1.83 ms' +\n 'Request sent and waiting4.80 ms' +\n 'Content downloading1.66 ms' +\n 'Waiting on main thread4.29 ms';\n assert.deepEqual(\n rowData,\n [\n {title: 'URL', value: 'chromedevtools.github.io/performance-stories/lcp-web-font/app.css'},\n {title: 'Request method', value: 'GET'},\n {title: 'Initial priority', value: 'Highest'},\n {title: 'Priority', value: 'Highest'},\n {title: 'MIME type', value: 'text/css'},\n {title: 'Encoded data', value: ' (from cache)'},\n {title: 'Decoded body', value: '96 B'},\n {\n title: 'Initiated by',\n value: 'chromedevtools.github.io/performance-stories/lcp-web-font/index.html',\n },\n {title: 'From cache', value: 'Yes'},\n {title: 'Duration', value: durationInnerText},\n ],\n );\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineEventOverview.d.ts b/public/panels/timeline/TimelineEventOverview.d.ts index cb4f2f93c..156a42548 100644 --- a/public/panels/timeline/TimelineEventOverview.d.ts +++ b/public/panels/timeline/TimelineEventOverview.d.ts @@ -1,4 +1,4 @@ -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; export declare abstract class TimelineEventOverview extends PerfUI.TimelineOverviewPane.TimelineOverviewBase { constructor(id: string, title: string | null); @@ -6,20 +6,20 @@ export declare abstract class TimelineEventOverview extends PerfUI.TimelineOverv } export declare class TimelineEventOverviewNetwork extends TimelineEventOverview { #private; - constructor(traceParsedData: TraceEngine.Handlers.Types.TraceParseData); - update(start?: TraceEngine.Types.Timing.MilliSeconds, end?: TraceEngine.Types.Timing.MilliSeconds): void; + constructor(parsedTrace: Trace.Handlers.Types.ParsedTrace); + update(start?: Trace.Types.Timing.MilliSeconds, end?: Trace.Types.Timing.MilliSeconds): void; } export declare class TimelineEventOverviewCPUActivity extends TimelineEventOverview { #private; private backgroundCanvas; - constructor(traceParsedData: TraceEngine.Handlers.Types.TraceParseData); + constructor(parsedTrace: Trace.Handlers.Types.ParsedTrace); resetCanvas(): void; update(): void; } export declare class TimelineEventOverviewResponsiveness extends TimelineEventOverview { #private; - constructor(traceParsedData: TraceEngine.Handlers.Types.TraceParseData); - update(start?: TraceEngine.Types.Timing.MilliSeconds, end?: TraceEngine.Types.Timing.MilliSeconds): void; + constructor(parsedTrace: Trace.Handlers.Types.ParsedTrace); + update(start?: Trace.Types.Timing.MilliSeconds, end?: Trace.Types.Timing.MilliSeconds): void; } export declare class TimelineFilmStripOverview extends TimelineEventOverview { #private; @@ -28,8 +28,8 @@ export declare class TimelineFilmStripOverview extends TimelineEventOverview { private lastElement; private drawGeneration?; private emptyImage?; - constructor(filmStrip: TraceEngine.Extras.FilmStrip.Data); - update(customStartTime?: TraceEngine.Types.Timing.MilliSeconds, customEndTime?: TraceEngine.Types.Timing.MilliSeconds): void; + constructor(filmStrip: Trace.Extras.FilmStrip.Data); + update(customStartTime?: Trace.Types.Timing.MilliSeconds, customEndTime?: Trace.Types.Timing.MilliSeconds): void; private imageByFrame; private drawFrames; overviewInfoPromise(x: number): Promise; @@ -39,9 +39,9 @@ export declare class TimelineFilmStripOverview extends TimelineEventOverview { export declare class TimelineEventOverviewMemory extends TimelineEventOverview { #private; private heapSizeLabel; - constructor(traceParsedData: TraceEngine.Handlers.Types.TraceParseData); + constructor(parsedTrace: Trace.Handlers.Types.ParsedTrace); resetHeapSizeLabels(): void; - update(start?: TraceEngine.Types.Timing.MilliSeconds, end?: TraceEngine.Types.Timing.MilliSeconds): void; + update(start?: Trace.Types.Timing.MilliSeconds, end?: Trace.Types.Timing.MilliSeconds): void; } export declare class Quantizer { private lastTime; diff --git a/public/panels/timeline/TimelineEventOverview.js b/public/panels/timeline/TimelineEventOverview.js index 4e46c4f0a..fb08f4656 100644 --- a/public/panels/timeline/TimelineEventOverview.js +++ b/public/panels/timeline/TimelineEventOverview.js @@ -29,7 +29,7 @@ */ import * as i18n from '../../core/i18n/i18n.js'; import * as Platform from '../../core/platform/platform.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as TraceBounds from '../../services/trace_bounds/trace_bounds.js'; import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; import * as UI from '../../ui/legacy/legacy.js'; @@ -80,17 +80,17 @@ const HIGH_NETWORK_PRIORITIES = new Set([ "Medium" /* Protocol.Network.ResourcePriority.Medium */, ]); export class TimelineEventOverviewNetwork extends TimelineEventOverview { - #traceParsedData; - constructor(traceParsedData) { + #parsedTrace; + constructor(parsedTrace) { super('network', i18nString(UIStrings.net)); - this.#traceParsedData = traceParsedData; + this.#parsedTrace = parsedTrace; } update(start, end) { this.resetCanvas(); - this.#renderWithTraceParsedData(start, end); + this.#renderWithParsedTrace(start, end); } - #renderWithTraceParsedData(start, end) { - if (!this.#traceParsedData) { + #renderWithParsedTrace(start, end) { + if (!this.#parsedTrace) { return; } // Because the UI is in milliseconds, we work with milliseconds through @@ -101,7 +101,7 @@ export class TimelineEventOverviewNetwork extends TimelineEventOverview { max: end, range: end - start, } : - TraceEngine.Helpers.Timing.traceWindowMilliSeconds(this.#traceParsedData.Meta.traceBounds); + Trace.Helpers.Timing.traceWindowMilliSeconds(this.#parsedTrace.Meta.traceBounds); // We draw two paths, so each can take up half the height const pathHeight = this.height() / 2; const canvasWidth = this.width(); @@ -111,9 +111,9 @@ export class TimelineEventOverviewNetwork extends TimelineEventOverview { // Other requests go onto the second path. const highPath = new Path2D(); const lowPath = new Path2D(); - for (const request of this.#traceParsedData.NetworkRequests.byTime) { + for (const request of this.#parsedTrace.NetworkRequests.byTime) { const path = HIGH_NETWORK_PRIORITIES.has(request.args.data.priority) ? highPath : lowPath; - const { startTime, endTime } = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(request); + const { startTime, endTime } = Trace.Helpers.Timing.eventTimingsMilliSeconds(request); const rectStart = Math.max(Math.floor((startTime - traceBoundsMilli.min) * scale), 0); const rectEnd = Math.min(Math.ceil((endTime - traceBoundsMilli.min) * scale + 1), canvasWidth); path.rect(rectStart, 0, rectEnd - rectStart, pathHeight - 1); @@ -133,27 +133,27 @@ export class TimelineEventOverviewNetwork extends TimelineEventOverview { const categoryToIndex = new WeakMap(); export class TimelineEventOverviewCPUActivity extends TimelineEventOverview { backgroundCanvas; - #traceParsedData; + #parsedTrace; #drawn = false; #start; #end; - constructor(traceParsedData) { + constructor(parsedTrace) { // During the sync tracks migration this component can use either legacy // Performance Model data or the new engine's data. Once the migration is // complete this will be updated to only use the new engine and mentions of // the PerformanceModel will be removed. super('cpu-activity', i18nString(UIStrings.cpu)); - this.#traceParsedData = traceParsedData; + this.#parsedTrace = parsedTrace; this.backgroundCanvas = this.element.createChild('canvas', 'fill background'); - this.#start = TraceEngine.Helpers.Timing.traceWindowMilliSeconds(traceParsedData.Meta.traceBounds).min; - this.#end = TraceEngine.Helpers.Timing.traceWindowMilliSeconds(traceParsedData.Meta.traceBounds).max; + this.#start = Trace.Helpers.Timing.traceWindowMilliSeconds(parsedTrace.Meta.traceBounds).min; + this.#end = Trace.Helpers.Timing.traceWindowMilliSeconds(parsedTrace.Meta.traceBounds).max; } #entryCategory(entry) { // Special case: in CPU Profiles we get a lot of ProfileCalls that // represent Idle time. We typically represent ProfileCalls in the // Scripting Category, but if they represent idle time, we do not want // that. - if (TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === '(idle)') { + if (Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === '(idle)') { return Components.EntryStyles.EventCategory.IDLE; } const eventStyle = Components.EntryStyles.getEventStyle(entry.name)?.category || @@ -167,7 +167,7 @@ export class TimelineEventOverviewCPUActivity extends TimelineEventOverview { this.backgroundCanvas.width = this.element.clientWidth * window.devicePixelRatio; this.backgroundCanvas.height = this.element.clientHeight * window.devicePixelRatio; } - #draw(traceParsedData) { + #draw(parsedTrace) { const quantSizePx = 4 * window.devicePixelRatio; const width = this.width(); const height = this.height(); @@ -210,33 +210,33 @@ export class TimelineEventOverviewCPUActivity extends TimelineEventOverview { // Idle event won't show in CPU activity, so just skip them. return; } - const startTimeMilli = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(entry.ts); + const startTimeMilli = Trace.Helpers.Timing.microSecondsToMilliseconds(entry.ts); const index = categoryIndexStack.length ? categoryIndexStack[categoryIndexStack.length - 1] : idleIndex; quantizer.appendInterval(startTimeMilli, index); const categoryIndex = categoryOrder.indexOf(category); categoryIndexStack.push(categoryIndex || otherIndex); }; function onEntryEnd(entry) { - const endTimeMilli = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(entry.ts) + - TraceEngine.Helpers.Timing.microSecondsToMilliseconds(TraceEngine.Types.Timing.MicroSeconds(entry.dur || 0)); + const endTimeMilli = Trace.Helpers.Timing.microSecondsToMilliseconds(entry.ts) + + Trace.Helpers.Timing.microSecondsToMilliseconds(Trace.Types.Timing.MicroSeconds(entry.dur || 0)); const lastCategoryIndex = categoryIndexStack.pop(); if (endTimeMilli !== undefined && lastCategoryIndex) { quantizer.appendInterval(endTimeMilli, lastCategoryIndex); } } - const startMicro = TraceEngine.Helpers.Timing.millisecondsToMicroseconds(this.#start); - const endMicro = TraceEngine.Helpers.Timing.millisecondsToMicroseconds(this.#end); + const startMicro = Trace.Helpers.Timing.millisecondsToMicroseconds(this.#start); + const endMicro = Trace.Helpers.Timing.millisecondsToMicroseconds(this.#end); const bounds = { min: startMicro, max: endMicro, - range: TraceEngine.Types.Timing.MicroSeconds(endMicro - startMicro), + range: Trace.Types.Timing.MicroSeconds(endMicro - startMicro), }; // Filter out tiny events - they don't make a visual impact to the // canvas as they are so small, but they do impact the time it takes // to walk the tree and render the events. // However, if the entire range we are showing is 200ms or less, then show all events. - const minDuration = TraceEngine.Types.Timing.MicroSeconds(bounds.range > 200_000 ? 16_000 : 0); - TraceEngine.Helpers.TreeHelpers.walkEntireTree(threadData.entryToNode, threadData.tree, onEntryStart, onEntryEnd, bounds, minDuration); + const minDuration = Trace.Types.Timing.MicroSeconds(bounds.range > 200_000 ? 16_000 : 0); + Trace.Helpers.TreeHelpers.walkEntireTree(threadData.entryToNode, threadData.tree, onEntryStart, onEntryEnd, bounds, minDuration); quantizer.appendInterval(this.#start + timeRange + quantTime, idleIndex); // Kick drawing the last bucket. for (let i = categoryOrder.length - 1; i > 0; --i) { paths[i].lineTo(width, height); @@ -252,12 +252,12 @@ export class TimelineEventOverviewCPUActivity extends TimelineEventOverview { if (!backgroundContext) { throw new Error('Could not find 2d canvas'); } - const threads = TraceEngine.Handlers.Threads.threadsInTrace(traceParsedData); + const threads = Trace.Handlers.Threads.threadsInTrace(parsedTrace); const mainThreadContext = this.context(); for (const thread of threads) { // We treat CPU_PROFILE as main thread because in a CPU Profile trace there is only ever one thread. - const isMainThread = thread.type === "MAIN_THREAD" /* TraceEngine.Handlers.Threads.ThreadType.MAIN_THREAD */ || - thread.type === "CPU_PROFILE" /* TraceEngine.Handlers.Threads.ThreadType.CPU_PROFILE */; + const isMainThread = thread.type === "MAIN_THREAD" /* Trace.Handlers.Threads.ThreadType.MAIN_THREAD */ || + thread.type === "CPU_PROFILE" /* Trace.Handlers.Threads.ThreadType.CPU_PROFILE */; if (isMainThread) { drawThreadEntries(mainThreadContext, thread); } @@ -293,17 +293,17 @@ export class TimelineEventOverviewCPUActivity extends TimelineEventOverview { // Order matters here, resetCanvas will set this.#drawn to false. this.resetCanvas(); this.#drawn = true; - this.#draw(this.#traceParsedData); + this.#draw(this.#parsedTrace); } } export class TimelineEventOverviewResponsiveness extends TimelineEventOverview { - #traceParsedData; - constructor(traceParsedData) { + #parsedTrace; + constructor(parsedTrace) { super('responsiveness', null); - this.#traceParsedData = traceParsedData; + this.#parsedTrace = parsedTrace; } #gatherEventsWithRelevantWarnings() { - const { topLevelRendererIds } = this.#traceParsedData.Meta; + const { topLevelRendererIds } = this.#parsedTrace.Meta; // All the warnings that we care about regarding responsiveness and want to represent on the overview. const warningsForResponsiveness = new Set([ 'LONG_TASK', @@ -312,7 +312,7 @@ export class TimelineEventOverviewResponsiveness extends TimelineEventOverview { ]); const allWarningEvents = new Set(); for (const warning of warningsForResponsiveness) { - const eventsForWarning = this.#traceParsedData.Warnings.perWarning.get(warning); + const eventsForWarning = this.#parsedTrace.Warnings.perWarning.get(warning); if (!eventsForWarning) { continue; } @@ -330,10 +330,10 @@ export class TimelineEventOverviewResponsiveness extends TimelineEventOverview { update(start, end) { this.resetCanvas(); const height = this.height(); - const visibleTimeWindow = !(start && end) ? this.#traceParsedData.Meta.traceBounds : { - min: TraceEngine.Helpers.Timing.millisecondsToMicroseconds(start), - max: TraceEngine.Helpers.Timing.millisecondsToMicroseconds(end), - range: TraceEngine.Helpers.Timing.millisecondsToMicroseconds(TraceEngine.Types.Timing.MilliSeconds(end - start)), + const visibleTimeWindow = !(start && end) ? this.#parsedTrace.Meta.traceBounds : { + min: Trace.Helpers.Timing.millisecondsToMicroseconds(start), + max: Trace.Helpers.Timing.millisecondsToMicroseconds(end), + range: Trace.Helpers.Timing.millisecondsToMicroseconds(Trace.Types.Timing.MilliSeconds(end - start)), }; const timeSpan = visibleTimeWindow.range; const scale = this.width() / timeSpan; @@ -350,7 +350,7 @@ export class TimelineEventOverviewResponsiveness extends TimelineEventOverview { ctx.fill(fillPath); ctx.stroke(markersPath); function paintWarningDecoration(event) { - const { startTime, duration } = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(event); + const { startTime, duration } = Trace.Helpers.Timing.eventTimingsMicroSeconds(event); const x = Math.round(scale * (startTime - visibleTimeWindow.min)); const width = Math.round(scale * duration); fillPath.rect(x, 0, width, height); @@ -421,17 +421,17 @@ export class TimelineFilmStripOverview extends TimelineEventOverview { } const padding = TimelineFilmStripOverview.Padding; const width = this.width(); - const zeroTime = customStartTime ?? TraceEngine.Helpers.Timing.microSecondsToMilliseconds(this.#filmStrip.zeroTime); + const zeroTime = customStartTime ?? Trace.Helpers.Timing.microSecondsToMilliseconds(this.#filmStrip.zeroTime); const spanTime = customEndTime ? customEndTime - zeroTime : - TraceEngine.Helpers.Timing.microSecondsToMilliseconds(this.#filmStrip.spanTime); + Trace.Helpers.Timing.microSecondsToMilliseconds(this.#filmStrip.spanTime); const scale = spanTime / width; const context = this.context(); const drawGeneration = this.drawGeneration; context.beginPath(); for (let x = padding; x < width; x += imageWidth + 2 * padding) { - const time = TraceEngine.Types.Timing.MilliSeconds(zeroTime + (x + imageWidth / 2) * scale); - const timeMicroSeconds = TraceEngine.Helpers.Timing.millisecondsToMicroseconds(time); - const frame = TraceEngine.Extras.FilmStrip.frameClosestToTimestamp(this.#filmStrip, timeMicroSeconds); + const time = Trace.Types.Timing.MilliSeconds(zeroTime + (x + imageWidth / 2) * scale); + const timeMicroSeconds = Trace.Helpers.Timing.millisecondsToMicroseconds(time); + const frame = Trace.Extras.FilmStrip.frameClosestToTimestamp(this.#filmStrip, timeMicroSeconds); if (!frame) { continue; } @@ -456,9 +456,9 @@ export class TimelineFilmStripOverview extends TimelineEventOverview { if (!calculator) { return null; } - const timeMilliSeconds = TraceEngine.Types.Timing.MilliSeconds(calculator.positionToTime(x)); - const timeMicroSeconds = TraceEngine.Helpers.Timing.millisecondsToMicroseconds(timeMilliSeconds); - const frame = TraceEngine.Extras.FilmStrip.frameClosestToTimestamp(this.#filmStrip, timeMicroSeconds); + const timeMilliSeconds = Trace.Types.Timing.MilliSeconds(calculator.positionToTime(x)); + const timeMicroSeconds = Trace.Helpers.Timing.millisecondsToMicroseconds(timeMilliSeconds); + const frame = Trace.Extras.FilmStrip.frameClosestToTimestamp(this.#filmStrip, timeMicroSeconds); if (frame === this.lastFrame) { return this.lastElement; } @@ -484,11 +484,11 @@ export class TimelineFilmStripOverview extends TimelineEventOverview { } export class TimelineEventOverviewMemory extends TimelineEventOverview { heapSizeLabel; - #traceParsedData; - constructor(traceParsedData) { + #parsedTrace; + constructor(parsedTrace) { super('memory', i18nString(UIStrings.heap)); this.heapSizeLabel = this.element.createChild('div', 'memory-graph-label'); - this.#traceParsedData = traceParsedData; + this.#parsedTrace = parsedTrace; } resetHeapSizeLabels() { this.heapSizeLabel.textContent = ''; @@ -496,23 +496,22 @@ export class TimelineEventOverviewMemory extends TimelineEventOverview { update(start, end) { this.resetCanvas(); const ratio = window.devicePixelRatio; - if (this.#traceParsedData.Memory.updateCountersByProcess.size === 0) { + if (this.#parsedTrace.Memory.updateCountersByProcess.size === 0) { this.resetHeapSizeLabels(); return; } - const mainRendererIds = Array.from(this.#traceParsedData.Meta.topLevelRendererIds); - const counterEventsPerTrack = mainRendererIds.map(pid => this.#traceParsedData.Memory.updateCountersByProcess.get(pid) || []) + const mainRendererIds = Array.from(this.#parsedTrace.Meta.topLevelRendererIds); + const counterEventsPerTrack = mainRendererIds.map(pid => this.#parsedTrace.Memory.updateCountersByProcess.get(pid) || []) .filter(eventsPerRenderer => eventsPerRenderer.length > 0); const lowerOffset = 3 * ratio; let maxUsedHeapSize = 0; let minUsedHeapSize = 100000000000; - const boundsMs = (start && end) ? - { - min: start, - max: end, - range: end - start, - } : - TraceEngine.Helpers.Timing.traceWindowMilliSeconds(this.#traceParsedData.Meta.traceBounds); + const boundsMs = (start && end) ? { + min: start, + max: end, + range: end - start, + } : + Trace.Helpers.Timing.traceWindowMilliSeconds(this.#parsedTrace.Meta.traceBounds); const minTime = boundsMs.min; const maxTime = boundsMs.max; function calculateMinMaxSizes(event) { @@ -538,7 +537,7 @@ export class TimelineEventOverviewMemory extends TimelineEventOverview { if (!counters || !counters.jsHeapSizeUsed) { return; } - const { startTime } = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event); + const { startTime } = Trace.Helpers.Timing.eventTimingsMilliSeconds(event); const x = Math.round((startTime - minTime) * xFactor); const y = Math.round((counters.jsHeapSizeUsed - minUsedHeapSize) * yFactor); histogram[x] = Math.max(histogram[x] || 0, y); diff --git a/public/panels/timeline/TimelineEventOverview.js.map b/public/panels/timeline/TimelineEventOverview.js.map index 2e27aa755..11e24a03e 100644 --- a/public/panels/timeline/TimelineEventOverview.js.map +++ b/public/panels/timeline/TimelineEventOverview.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineEventOverview.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineEventOverview.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (C) 2013 Google Inc. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * * Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above\n * copyright notice, this list of conditions and the following disclaimer\n * in the documentation and/or other materials provided with the\n * distribution.\n * * Neither the name of Google Inc. nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as Protocol from '../../generated/protocol.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as TraceBounds from '../../services/trace_bounds/trace_bounds.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport * as Components from './components/components.js';\n\nconst UIStrings = {\n /**\n *@description Short for Network. Label for the network requests section of the Performance panel.\n */\n net: 'NET',\n /**\n *@description Text in Timeline Event Overview of the Performance panel\n */\n cpu: 'CPU',\n /**\n *@description Text in Timeline Event Overview of the Performance panel\n */\n heap: 'HEAP',\n /**\n *@description Heap size label text content in Timeline Event Overview of the Performance panel\n *@example {10 MB} PH1\n *@example {30 MB} PH2\n */\n sSDash: '{PH1} – {PH2}',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelineEventOverview.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nexport abstract class TimelineEventOverview extends PerfUI.TimelineOverviewPane.TimelineOverviewBase {\n constructor(id: string, title: string|null) {\n super();\n this.element.id = 'timeline-overview-' + id;\n this.element.classList.add('overview-strip');\n if (title) {\n this.element.createChild('div', 'timeline-overview-strip-title').textContent = title;\n }\n }\n\n renderBar(begin: number, end: number, position: number, height: number, color: string): void {\n const x = begin;\n const width = end - begin;\n const ctx = this.context();\n ctx.fillStyle = color;\n ctx.fillRect(x, position, width, height);\n }\n}\n\nconst HIGH_NETWORK_PRIORITIES = new Set([\n Protocol.Network.ResourcePriority.VeryHigh,\n Protocol.Network.ResourcePriority.High,\n Protocol.Network.ResourcePriority.Medium,\n]);\n\nexport class TimelineEventOverviewNetwork extends TimelineEventOverview {\n #traceParsedData: TraceEngine.Handlers.Types.TraceParseData;\n constructor(traceParsedData: TraceEngine.Handlers.Types.TraceParseData) {\n super('network', i18nString(UIStrings.net));\n this.#traceParsedData = traceParsedData;\n }\n\n override update(start?: TraceEngine.Types.Timing.MilliSeconds, end?: TraceEngine.Types.Timing.MilliSeconds): void {\n this.resetCanvas();\n this.#renderWithTraceParsedData(start, end);\n }\n\n #renderWithTraceParsedData(\n start?: TraceEngine.Types.Timing.MilliSeconds, end?: TraceEngine.Types.Timing.MilliSeconds): void {\n if (!this.#traceParsedData) {\n return;\n }\n\n // Because the UI is in milliseconds, we work with milliseconds through\n // this function to get the right scale and sizing\n const traceBoundsMilli = (start && end) ?\n {\n min: start,\n max: end,\n range: end - start,\n } :\n TraceEngine.Helpers.Timing.traceWindowMilliSeconds(this.#traceParsedData.Meta.traceBounds);\n\n // We draw two paths, so each can take up half the height\n const pathHeight = this.height() / 2;\n\n const canvasWidth = this.width();\n const scale = canvasWidth / traceBoundsMilli.range;\n\n // We draw network requests in two chunks:\n // Requests with a priority of Medium or higher go onto the first path\n // Other requests go onto the second path.\n const highPath = new Path2D();\n const lowPath = new Path2D();\n\n for (const request of this.#traceParsedData.NetworkRequests.byTime) {\n const path = HIGH_NETWORK_PRIORITIES.has(request.args.data.priority) ? highPath : lowPath;\n const {startTime, endTime} = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(request);\n const rectStart = Math.max(Math.floor((startTime - traceBoundsMilli.min) * scale), 0);\n const rectEnd = Math.min(Math.ceil((endTime - traceBoundsMilli.min) * scale + 1), canvasWidth);\n\n path.rect(rectStart, 0, rectEnd - rectStart, pathHeight - 1);\n }\n\n const ctx = this.context();\n ctx.save();\n // Draw the high path onto the canvas.\n ctx.fillStyle = 'hsl(214, 60%, 60%)';\n ctx.fill(highPath);\n // Now jump down by the height of the high path, and then draw the low path.\n ctx.translate(0, pathHeight);\n ctx.fillStyle = 'hsl(214, 80%, 80%)';\n ctx.fill(lowPath);\n ctx.restore();\n }\n}\n\nconst categoryToIndex = new WeakMap();\n\nexport class TimelineEventOverviewCPUActivity extends TimelineEventOverview {\n private backgroundCanvas: HTMLCanvasElement;\n #traceParsedData: TraceEngine.Handlers.Types.TraceParseData;\n #drawn = false;\n #start: TraceEngine.Types.Timing.MilliSeconds;\n #end: TraceEngine.Types.Timing.MilliSeconds;\n\n constructor(traceParsedData: TraceEngine.Handlers.Types.TraceParseData) {\n // During the sync tracks migration this component can use either legacy\n // Performance Model data or the new engine's data. Once the migration is\n // complete this will be updated to only use the new engine and mentions of\n // the PerformanceModel will be removed.\n super('cpu-activity', i18nString(UIStrings.cpu));\n this.#traceParsedData = traceParsedData;\n this.backgroundCanvas = (this.element.createChild('canvas', 'fill background') as HTMLCanvasElement);\n this.#start = TraceEngine.Helpers.Timing.traceWindowMilliSeconds(traceParsedData.Meta.traceBounds).min;\n this.#end = TraceEngine.Helpers.Timing.traceWindowMilliSeconds(traceParsedData.Meta.traceBounds).max;\n }\n\n #entryCategory(entry: TraceEngine.Types.TraceEvents.TraceEventData): Components.EntryStyles.EventCategory|undefined {\n // Special case: in CPU Profiles we get a lot of ProfileCalls that\n // represent Idle time. We typically represent ProfileCalls in the\n // Scripting Category, but if they represent idle time, we do not want\n // that.\n if (TraceEngine.Types.TraceEvents.isProfileCall(entry) && entry.callFrame.functionName === '(idle)') {\n return Components.EntryStyles.EventCategory.IDLE;\n }\n const eventStyle =\n Components.EntryStyles.getEventStyle(entry.name as TraceEngine.Types.TraceEvents.KnownEventName)?.category ||\n Components.EntryStyles.getCategoryStyles().other;\n const categoryName = eventStyle.name;\n return categoryName;\n }\n\n override resetCanvas(): void {\n super.resetCanvas();\n this.#drawn = false;\n this.backgroundCanvas.width = this.element.clientWidth * window.devicePixelRatio;\n this.backgroundCanvas.height = this.element.clientHeight * window.devicePixelRatio;\n }\n\n #draw(traceParsedData: TraceEngine.Handlers.Types.TraceParseData): void {\n const quantSizePx = 4 * window.devicePixelRatio;\n const width = this.width();\n const height = this.height();\n const baseLine = height;\n const timeRange = this.#end - this.#start;\n const scale = width / timeRange;\n const quantTime = quantSizePx / scale;\n const categories = Components.EntryStyles.getCategoryStyles();\n const categoryOrder = Components.EntryStyles.getTimelineMainEventCategories();\n const otherIndex = categoryOrder.indexOf(Components.EntryStyles.EventCategory.OTHER);\n const idleIndex = 0;\n console.assert(idleIndex === categoryOrder.indexOf(Components.EntryStyles.EventCategory.IDLE));\n for (let i = 0; i < categoryOrder.length; ++i) {\n categoryToIndex.set(categories[categoryOrder[i]], i);\n }\n\n const drawThreadEntries =\n (context: CanvasRenderingContext2D, threadData: TraceEngine.Handlers.Threads.ThreadData): void => {\n const quantizer = new Quantizer(this.#start, quantTime, drawSample);\n let x = 0;\n const categoryIndexStack: number[] = [];\n const paths: Path2D[] = [];\n const lastY: number[] = [];\n for (let i = 0; i < categoryOrder.length; ++i) {\n paths[i] = new Path2D();\n paths[i].moveTo(0, height);\n lastY[i] = height;\n }\n\n function drawSample(counters: number[]): void {\n let y = baseLine;\n for (let i = idleIndex + 1; i < categoryOrder.length; ++i) {\n const h = (counters[i] || 0) / quantTime * height;\n y -= h;\n paths[i].bezierCurveTo(x, lastY[i], x, y, x + quantSizePx / 2, y);\n lastY[i] = y;\n }\n x += quantSizePx;\n }\n\n const onEntryStart = (entry: TraceEngine.Types.TraceEvents.TraceEventData): void => {\n const category = this.#entryCategory(entry);\n if (!category || category === 'idle') {\n // Idle event won't show in CPU activity, so just skip them.\n return;\n }\n const startTimeMilli = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(entry.ts);\n const index = categoryIndexStack.length ? categoryIndexStack[categoryIndexStack.length - 1] : idleIndex;\n quantizer.appendInterval(startTimeMilli, index);\n const categoryIndex = categoryOrder.indexOf(category);\n categoryIndexStack.push(categoryIndex || otherIndex);\n };\n\n function onEntryEnd(entry: TraceEngine.Types.TraceEvents.TraceEventData): void {\n const endTimeMilli = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(entry.ts) +\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds(\n TraceEngine.Types.Timing.MicroSeconds(entry.dur || 0));\n const lastCategoryIndex = categoryIndexStack.pop();\n if (endTimeMilli !== undefined && lastCategoryIndex) {\n quantizer.appendInterval(endTimeMilli, lastCategoryIndex);\n }\n }\n const startMicro = TraceEngine.Helpers.Timing.millisecondsToMicroseconds(this.#start);\n const endMicro = TraceEngine.Helpers.Timing.millisecondsToMicroseconds(this.#end);\n const bounds = {\n min: startMicro,\n max: endMicro,\n range: TraceEngine.Types.Timing.MicroSeconds(endMicro - startMicro),\n };\n\n // Filter out tiny events - they don't make a visual impact to the\n // canvas as they are so small, but they do impact the time it takes\n // to walk the tree and render the events.\n // However, if the entire range we are showing is 200ms or less, then show all events.\n const minDuration = TraceEngine.Types.Timing.MicroSeconds(\n bounds.range > 200_000 ? 16_000 : 0,\n );\n TraceEngine.Helpers.TreeHelpers.walkEntireTree(\n threadData.entryToNode, threadData.tree, onEntryStart, onEntryEnd, bounds, minDuration);\n quantizer.appendInterval(this.#start + timeRange + quantTime, idleIndex); // Kick drawing the last bucket.\n for (let i = categoryOrder.length - 1; i > 0; --i) {\n paths[i].lineTo(width, height);\n const computedColorValue = categories[categoryOrder[i]].getComputedColorValue();\n context.fillStyle = computedColorValue;\n context.fill(paths[i]);\n context.strokeStyle = 'white';\n context.lineWidth = 1;\n context.stroke(paths[i]);\n }\n };\n const backgroundContext = (this.backgroundCanvas.getContext('2d') as CanvasRenderingContext2D | null);\n if (!backgroundContext) {\n throw new Error('Could not find 2d canvas');\n }\n\n const threads = TraceEngine.Handlers.Threads.threadsInTrace(traceParsedData);\n const mainThreadContext = this.context();\n for (const thread of threads) {\n // We treat CPU_PROFILE as main thread because in a CPU Profile trace there is only ever one thread.\n const isMainThread = thread.type === TraceEngine.Handlers.Threads.ThreadType.MAIN_THREAD ||\n thread.type === TraceEngine.Handlers.Threads.ThreadType.CPU_PROFILE;\n if (isMainThread) {\n drawThreadEntries(mainThreadContext, thread);\n } else {\n drawThreadEntries(backgroundContext, thread);\n }\n }\n\n function applyPattern(ctx: CanvasRenderingContext2D): void {\n const step = 4 * window.devicePixelRatio;\n ctx.save();\n ctx.lineWidth = step / Math.sqrt(8);\n for (let x = 0.5; x < width + height; x += step) {\n ctx.moveTo(x, 0);\n ctx.lineTo(x - height, height);\n }\n ctx.globalCompositeOperation = 'destination-out';\n ctx.stroke();\n ctx.restore();\n }\n\n applyPattern(backgroundContext);\n }\n\n override update(): void {\n const traceBoundsState = TraceBounds.TraceBounds.BoundsManager.instance().state();\n const bounds = traceBoundsState?.milli.minimapTraceBounds;\n if (!bounds) {\n return;\n }\n if (bounds.min === this.#start && bounds.max === this.#end && this.#drawn) {\n return;\n }\n this.#start = bounds.min;\n this.#end = bounds.max;\n // Order matters here, resetCanvas will set this.#drawn to false.\n this.resetCanvas();\n this.#drawn = true;\n this.#draw(this.#traceParsedData);\n }\n}\n\nexport class TimelineEventOverviewResponsiveness extends TimelineEventOverview {\n #traceParsedData: TraceEngine.Handlers.Types.TraceParseData;\n constructor(traceParsedData: TraceEngine.Handlers.Types.TraceParseData) {\n super('responsiveness', null);\n this.#traceParsedData = traceParsedData;\n }\n\n #gatherEventsWithRelevantWarnings(): Set {\n const {topLevelRendererIds} = this.#traceParsedData.Meta;\n\n // All the warnings that we care about regarding responsiveness and want to represent on the overview.\n const warningsForResponsiveness = new Set([\n 'LONG_TASK',\n 'FORCED_REFLOW',\n 'IDLE_CALLBACK_OVER_TIME',\n ]);\n\n const allWarningEvents = new Set();\n for (const warning of warningsForResponsiveness) {\n const eventsForWarning = this.#traceParsedData.Warnings.perWarning.get(warning);\n if (!eventsForWarning) {\n continue;\n }\n\n for (const event of eventsForWarning) {\n // Only keep events whose PID is a top level renderer, which means it\n // was on the main thread. This avoids showing issues from iframes or\n // other sub-frames in the minimap overview.\n if (topLevelRendererIds.has(event.pid)) {\n allWarningEvents.add(event);\n }\n }\n }\n return allWarningEvents;\n }\n\n override update(start?: TraceEngine.Types.Timing.MilliSeconds, end?: TraceEngine.Types.Timing.MilliSeconds): void {\n this.resetCanvas();\n\n const height = this.height();\n const visibleTimeWindow = !(start && end) ? this.#traceParsedData.Meta.traceBounds : {\n min: TraceEngine.Helpers.Timing.millisecondsToMicroseconds(start),\n max: TraceEngine.Helpers.Timing.millisecondsToMicroseconds(end),\n range: TraceEngine.Helpers.Timing.millisecondsToMicroseconds(TraceEngine.Types.Timing.MilliSeconds(end - start)),\n };\n const timeSpan = visibleTimeWindow.range;\n const scale = this.width() / timeSpan;\n const ctx = this.context();\n const fillPath = new Path2D();\n const markersPath = new Path2D();\n\n const eventsWithWarning = this.#gatherEventsWithRelevantWarnings();\n for (const event of eventsWithWarning) {\n paintWarningDecoration(event);\n }\n\n ctx.fillStyle = 'hsl(0, 80%, 90%)';\n ctx.strokeStyle = 'red';\n ctx.lineWidth = 2 * window.devicePixelRatio;\n ctx.fill(fillPath);\n ctx.stroke(markersPath);\n\n function paintWarningDecoration(event: TraceEngine.Types.TraceEvents.TraceEventData): void {\n const {startTime, duration} = TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(event);\n const x = Math.round(scale * (startTime - visibleTimeWindow.min));\n const width = Math.round(scale * duration);\n fillPath.rect(x, 0, width, height);\n markersPath.moveTo(x + width, 0);\n markersPath.lineTo(x + width, height);\n }\n }\n}\n\nexport class TimelineFilmStripOverview extends TimelineEventOverview {\n private frameToImagePromise: Map>;\n private lastFrame: TraceEngine.Extras.FilmStrip.Frame|null = null;\n private lastElement: Element|null;\n private drawGeneration?: symbol;\n private emptyImage?: HTMLImageElement;\n #filmStrip: TraceEngine.Extras.FilmStrip.Data|null = null;\n\n constructor(filmStrip: TraceEngine.Extras.FilmStrip.Data) {\n super('filmstrip', null);\n this.element.setAttribute('jslog', `${VisualLogging.section('film-strip')}`);\n this.frameToImagePromise = new Map();\n this.#filmStrip = filmStrip;\n this.lastFrame = null;\n this.lastElement = null;\n this.reset();\n }\n\n override update(\n customStartTime?: TraceEngine.Types.Timing.MilliSeconds,\n customEndTime?: TraceEngine.Types.Timing.MilliSeconds): void {\n this.resetCanvas();\n const frames = this.#filmStrip ? this.#filmStrip.frames : [];\n if (!frames.length) {\n return;\n }\n\n if (this.height() === 0) {\n // Height of 0 causes the maths below to get off and generate very large\n // negative numbers that cause an extremely long loop when attempting to\n // draw images by frame. Rather than that, let's warn and exist early.\n console.warn('TimelineFilmStrip could not be drawn as its canvas height is 0');\n return;\n }\n\n const drawGeneration = Symbol('drawGeneration');\n this.drawGeneration = drawGeneration;\n void this.imageByFrame(frames[0]).then(image => {\n if (this.drawGeneration !== drawGeneration) {\n return;\n }\n if (!image || !image.naturalWidth || !image.naturalHeight) {\n return;\n }\n const imageHeight = this.height() - 2 * TimelineFilmStripOverview.Padding;\n const imageWidth = Math.ceil(imageHeight * image.naturalWidth / image.naturalHeight);\n const popoverScale = Math.min(200 / image.naturalWidth, 1);\n this.emptyImage = new Image(image.naturalWidth * popoverScale, image.naturalHeight * popoverScale);\n this.drawFrames(imageWidth, imageHeight, customStartTime, customEndTime);\n });\n }\n\n private async imageByFrame(frame: TraceEngine.Extras.FilmStrip.Frame): Promise {\n let imagePromise: Promise|undefined = this.frameToImagePromise.get(frame);\n if (!imagePromise) {\n imagePromise = UI.UIUtils.loadImage(frame.screenshotEvent.args.dataUri);\n this.frameToImagePromise.set(frame, (imagePromise as Promise));\n }\n return imagePromise;\n }\n\n private drawFrames(\n imageWidth: number, imageHeight: number, customStartTime?: TraceEngine.Types.Timing.MilliSeconds,\n customEndTime?: TraceEngine.Types.Timing.MilliSeconds): void {\n if (!imageWidth) {\n return;\n }\n if (!this.#filmStrip || this.#filmStrip.frames.length < 1) {\n return;\n }\n const padding = TimelineFilmStripOverview.Padding;\n const width = this.width();\n\n const zeroTime = customStartTime ?? TraceEngine.Helpers.Timing.microSecondsToMilliseconds(this.#filmStrip.zeroTime);\n const spanTime = customEndTime ? customEndTime - zeroTime :\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds(this.#filmStrip.spanTime);\n const scale = spanTime / width;\n const context = this.context();\n const drawGeneration = this.drawGeneration;\n\n context.beginPath();\n for (let x = padding; x < width; x += imageWidth + 2 * padding) {\n const time = TraceEngine.Types.Timing.MilliSeconds(zeroTime + (x + imageWidth / 2) * scale);\n const timeMicroSeconds = TraceEngine.Helpers.Timing.millisecondsToMicroseconds(time);\n const frame = TraceEngine.Extras.FilmStrip.frameClosestToTimestamp(this.#filmStrip, timeMicroSeconds);\n if (!frame) {\n continue;\n }\n context.rect(x - 0.5, 0.5, imageWidth + 1, imageHeight + 1);\n void this.imageByFrame(frame).then(drawFrameImage.bind(this, x));\n }\n context.strokeStyle = '#ddd';\n context.stroke();\n\n function drawFrameImage(this: TimelineFilmStripOverview, x: number, image: HTMLImageElement|null): void {\n // Ignore draws deferred from a previous update call.\n if (this.drawGeneration !== drawGeneration || !image) {\n return;\n }\n context.drawImage(image, x, 1, imageWidth, imageHeight);\n }\n }\n\n override async overviewInfoPromise(x: number): Promise {\n if (!this.#filmStrip || this.#filmStrip.frames.length === 0) {\n return null;\n }\n\n const calculator = this.calculator();\n if (!calculator) {\n return null;\n }\n const timeMilliSeconds = TraceEngine.Types.Timing.MilliSeconds(calculator.positionToTime(x));\n const timeMicroSeconds = TraceEngine.Helpers.Timing.millisecondsToMicroseconds(timeMilliSeconds);\n const frame = TraceEngine.Extras.FilmStrip.frameClosestToTimestamp(this.#filmStrip, timeMicroSeconds);\n if (frame === this.lastFrame) {\n return this.lastElement;\n }\n const imagePromise = frame ? this.imageByFrame(frame) : Promise.resolve(this.emptyImage);\n const image = await imagePromise;\n const element = document.createElement('div');\n element.classList.add('frame');\n if (image) {\n element.createChild('div', 'thumbnail').appendChild(image);\n }\n this.lastFrame = frame;\n this.lastElement = element;\n return element;\n }\n\n override reset(): void {\n this.lastFrame = null;\n this.lastElement = null;\n this.frameToImagePromise = new Map();\n }\n\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/naming-convention\n static readonly Padding = 2;\n}\n\nexport class TimelineEventOverviewMemory extends TimelineEventOverview {\n private heapSizeLabel: HTMLElement;\n #traceParsedData: TraceEngine.Handlers.Types.TraceParseData;\n\n constructor(traceParsedData: TraceEngine.Handlers.Types.TraceParseData) {\n super('memory', i18nString(UIStrings.heap));\n this.heapSizeLabel = this.element.createChild('div', 'memory-graph-label');\n this.#traceParsedData = traceParsedData;\n }\n\n resetHeapSizeLabels(): void {\n this.heapSizeLabel.textContent = '';\n }\n\n override update(start?: TraceEngine.Types.Timing.MilliSeconds, end?: TraceEngine.Types.Timing.MilliSeconds): void {\n this.resetCanvas();\n const ratio = window.devicePixelRatio;\n\n if (this.#traceParsedData.Memory.updateCountersByProcess.size === 0) {\n this.resetHeapSizeLabels();\n return;\n }\n\n const mainRendererIds = Array.from(this.#traceParsedData.Meta.topLevelRendererIds);\n const counterEventsPerTrack =\n mainRendererIds.map(pid => this.#traceParsedData.Memory.updateCountersByProcess.get(pid) || [])\n .filter(eventsPerRenderer => eventsPerRenderer.length > 0);\n\n const lowerOffset = 3 * ratio;\n let maxUsedHeapSize = 0;\n let minUsedHeapSize = 100000000000;\n\n const boundsMs = (start && end) ?\n {\n min: start,\n max: end,\n range: end - start,\n } :\n TraceEngine.Helpers.Timing.traceWindowMilliSeconds(this.#traceParsedData.Meta.traceBounds);\n const minTime = boundsMs.min;\n const maxTime = boundsMs.max;\n\n function calculateMinMaxSizes(event: TraceEngine.Types.TraceEvents.TraceEventUpdateCounters): void {\n const counters = event.args.data;\n if (!counters || !counters.jsHeapSizeUsed) {\n return;\n }\n maxUsedHeapSize = Math.max(maxUsedHeapSize, counters.jsHeapSizeUsed);\n minUsedHeapSize = Math.min(minUsedHeapSize, counters.jsHeapSizeUsed);\n }\n\n for (let i = 0; i < counterEventsPerTrack.length; i++) {\n counterEventsPerTrack[i].forEach(calculateMinMaxSizes);\n }\n\n minUsedHeapSize = Math.min(minUsedHeapSize, maxUsedHeapSize);\n\n const lineWidth = 1;\n const width = this.width();\n const height = this.height() - lowerOffset;\n const xFactor = width / (maxTime - minTime);\n const yFactor = (height - lineWidth) / Math.max(maxUsedHeapSize - minUsedHeapSize, 1);\n\n const histogram = new Array(width);\n\n function buildHistogram(event: TraceEngine.Types.TraceEvents.TraceEventUpdateCounters): void {\n const counters = event.args.data;\n if (!counters || !counters.jsHeapSizeUsed) {\n return;\n }\n const {startTime} = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event);\n const x = Math.round((startTime - minTime) * xFactor);\n const y = Math.round((counters.jsHeapSizeUsed - minUsedHeapSize) * yFactor);\n histogram[x] = Math.max(histogram[x] || 0, y);\n }\n for (let i = 0; i < counterEventsPerTrack.length; i++) {\n counterEventsPerTrack[i].forEach(buildHistogram);\n }\n\n const ctx = this.context();\n const heightBeyondView = height + lowerOffset + lineWidth;\n\n ctx.translate(0.5, 0.5);\n ctx.beginPath();\n ctx.moveTo(-lineWidth, heightBeyondView);\n let y = 0;\n let isFirstPoint = true;\n let lastX = 0;\n for (let x = 0; x < histogram.length; x++) {\n if (typeof histogram[x] === 'undefined') {\n continue;\n }\n if (isFirstPoint) {\n isFirstPoint = false;\n y = histogram[x];\n ctx.lineTo(-lineWidth, height - y);\n }\n const nextY = histogram[x];\n if (Math.abs(nextY - y) > 2 && Math.abs(x - lastX) > 1) {\n ctx.lineTo(x, height - y);\n }\n y = nextY;\n ctx.lineTo(x, height - y);\n lastX = x;\n }\n ctx.lineTo(width + lineWidth, height - y);\n ctx.lineTo(width + lineWidth, heightBeyondView);\n ctx.closePath();\n\n ctx.fillStyle = 'hsla(220, 90%, 70%, 0.2)';\n ctx.fill();\n ctx.lineWidth = lineWidth;\n ctx.strokeStyle = 'hsl(220, 90%, 70%)';\n ctx.stroke();\n\n this.heapSizeLabel.textContent = i18nString(UIStrings.sSDash, {\n PH1: Platform.NumberUtilities.bytesToString(minUsedHeapSize),\n PH2: Platform.NumberUtilities.bytesToString(maxUsedHeapSize),\n });\n }\n}\n\nexport class Quantizer {\n private lastTime: number;\n private quantDuration: number;\n private readonly callback: (arg0: Array) => void;\n private counters: number[];\n private remainder: number;\n constructor(startTime: number, quantDuration: number, callback: (arg0: Array) => void) {\n this.lastTime = startTime;\n this.quantDuration = quantDuration;\n this.callback = callback;\n this.counters = [];\n this.remainder = quantDuration;\n }\n\n appendInterval(time: number, group: number): void {\n let interval = time - this.lastTime;\n if (interval <= this.remainder) {\n this.counters[group] = (this.counters[group] || 0) + interval;\n this.remainder -= interval;\n this.lastTime = time;\n return;\n }\n this.counters[group] = (this.counters[group] || 0) + this.remainder;\n this.callback(this.counters);\n interval -= this.remainder;\n while (interval >= this.quantDuration) {\n const counters = [];\n counters[group] = this.quantDuration;\n this.callback(counters);\n interval -= this.quantDuration;\n }\n this.counters = [];\n this.counters[group] = interval;\n this.lastTime = time;\n this.remainder = this.quantDuration - interval;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"TimelineEventOverview.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineEventOverview.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (C) 2013 Google Inc. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * * Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above\n * copyright notice, this list of conditions and the following disclaimer\n * in the documentation and/or other materials provided with the\n * distribution.\n * * Neither the name of Google Inc. nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as Protocol from '../../generated/protocol.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as TraceBounds from '../../services/trace_bounds/trace_bounds.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport * as Components from './components/components.js';\n\nconst UIStrings = {\n /**\n *@description Short for Network. Label for the network requests section of the Performance panel.\n */\n net: 'NET',\n /**\n *@description Text in Timeline Event Overview of the Performance panel\n */\n cpu: 'CPU',\n /**\n *@description Text in Timeline Event Overview of the Performance panel\n */\n heap: 'HEAP',\n /**\n *@description Heap size label text content in Timeline Event Overview of the Performance panel\n *@example {10 MB} PH1\n *@example {30 MB} PH2\n */\n sSDash: '{PH1} – {PH2}',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelineEventOverview.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nexport abstract class TimelineEventOverview extends PerfUI.TimelineOverviewPane.TimelineOverviewBase {\n constructor(id: string, title: string|null) {\n super();\n this.element.id = 'timeline-overview-' + id;\n this.element.classList.add('overview-strip');\n if (title) {\n this.element.createChild('div', 'timeline-overview-strip-title').textContent = title;\n }\n }\n\n renderBar(begin: number, end: number, position: number, height: number, color: string): void {\n const x = begin;\n const width = end - begin;\n const ctx = this.context();\n ctx.fillStyle = color;\n ctx.fillRect(x, position, width, height);\n }\n}\n\nconst HIGH_NETWORK_PRIORITIES = new Set([\n Protocol.Network.ResourcePriority.VeryHigh,\n Protocol.Network.ResourcePriority.High,\n Protocol.Network.ResourcePriority.Medium,\n]);\n\nexport class TimelineEventOverviewNetwork extends TimelineEventOverview {\n #parsedTrace: Trace.Handlers.Types.ParsedTrace;\n constructor(parsedTrace: Trace.Handlers.Types.ParsedTrace) {\n super('network', i18nString(UIStrings.net));\n this.#parsedTrace = parsedTrace;\n }\n\n override update(start?: Trace.Types.Timing.MilliSeconds, end?: Trace.Types.Timing.MilliSeconds): void {\n this.resetCanvas();\n this.#renderWithParsedTrace(start, end);\n }\n\n #renderWithParsedTrace(start?: Trace.Types.Timing.MilliSeconds, end?: Trace.Types.Timing.MilliSeconds): void {\n if (!this.#parsedTrace) {\n return;\n }\n\n // Because the UI is in milliseconds, we work with milliseconds through\n // this function to get the right scale and sizing\n const traceBoundsMilli = (start && end) ?\n {\n min: start,\n max: end,\n range: end - start,\n } :\n Trace.Helpers.Timing.traceWindowMilliSeconds(this.#parsedTrace.Meta.traceBounds);\n\n // We draw two paths, so each can take up half the height\n const pathHeight = this.height() / 2;\n\n const canvasWidth = this.width();\n const scale = canvasWidth / traceBoundsMilli.range;\n\n // We draw network requests in two chunks:\n // Requests with a priority of Medium or higher go onto the first path\n // Other requests go onto the second path.\n const highPath = new Path2D();\n const lowPath = new Path2D();\n\n for (const request of this.#parsedTrace.NetworkRequests.byTime) {\n const path = HIGH_NETWORK_PRIORITIES.has(request.args.data.priority) ? highPath : lowPath;\n const {startTime, endTime} = Trace.Helpers.Timing.eventTimingsMilliSeconds(request);\n const rectStart = Math.max(Math.floor((startTime - traceBoundsMilli.min) * scale), 0);\n const rectEnd = Math.min(Math.ceil((endTime - traceBoundsMilli.min) * scale + 1), canvasWidth);\n\n path.rect(rectStart, 0, rectEnd - rectStart, pathHeight - 1);\n }\n\n const ctx = this.context();\n ctx.save();\n // Draw the high path onto the canvas.\n ctx.fillStyle = 'hsl(214, 60%, 60%)';\n ctx.fill(highPath);\n // Now jump down by the height of the high path, and then draw the low path.\n ctx.translate(0, pathHeight);\n ctx.fillStyle = 'hsl(214, 80%, 80%)';\n ctx.fill(lowPath);\n ctx.restore();\n }\n}\n\nconst categoryToIndex = new WeakMap();\n\nexport class TimelineEventOverviewCPUActivity extends TimelineEventOverview {\n private backgroundCanvas: HTMLCanvasElement;\n #parsedTrace: Trace.Handlers.Types.ParsedTrace;\n #drawn = false;\n #start: Trace.Types.Timing.MilliSeconds;\n #end: Trace.Types.Timing.MilliSeconds;\n\n constructor(parsedTrace: Trace.Handlers.Types.ParsedTrace) {\n // During the sync tracks migration this component can use either legacy\n // Performance Model data or the new engine's data. Once the migration is\n // complete this will be updated to only use the new engine and mentions of\n // the PerformanceModel will be removed.\n super('cpu-activity', i18nString(UIStrings.cpu));\n this.#parsedTrace = parsedTrace;\n this.backgroundCanvas = (this.element.createChild('canvas', 'fill background') as HTMLCanvasElement);\n this.#start = Trace.Helpers.Timing.traceWindowMilliSeconds(parsedTrace.Meta.traceBounds).min;\n this.#end = Trace.Helpers.Timing.traceWindowMilliSeconds(parsedTrace.Meta.traceBounds).max;\n }\n\n #entryCategory(entry: Trace.Types.Events.Event): Components.EntryStyles.EventCategory|undefined {\n // Special case: in CPU Profiles we get a lot of ProfileCalls that\n // represent Idle time. We typically represent ProfileCalls in the\n // Scripting Category, but if they represent idle time, we do not want\n // that.\n if (Trace.Types.Events.isProfileCall(entry) && entry.callFrame.functionName === '(idle)') {\n return Components.EntryStyles.EventCategory.IDLE;\n }\n const eventStyle = Components.EntryStyles.getEventStyle(entry.name as Trace.Types.Events.Name)?.category ||\n Components.EntryStyles.getCategoryStyles().other;\n const categoryName = eventStyle.name;\n return categoryName;\n }\n\n override resetCanvas(): void {\n super.resetCanvas();\n this.#drawn = false;\n this.backgroundCanvas.width = this.element.clientWidth * window.devicePixelRatio;\n this.backgroundCanvas.height = this.element.clientHeight * window.devicePixelRatio;\n }\n\n #draw(parsedTrace: Trace.Handlers.Types.ParsedTrace): void {\n const quantSizePx = 4 * window.devicePixelRatio;\n const width = this.width();\n const height = this.height();\n const baseLine = height;\n const timeRange = this.#end - this.#start;\n const scale = width / timeRange;\n const quantTime = quantSizePx / scale;\n const categories = Components.EntryStyles.getCategoryStyles();\n const categoryOrder = Components.EntryStyles.getTimelineMainEventCategories();\n const otherIndex = categoryOrder.indexOf(Components.EntryStyles.EventCategory.OTHER);\n const idleIndex = 0;\n console.assert(idleIndex === categoryOrder.indexOf(Components.EntryStyles.EventCategory.IDLE));\n for (let i = 0; i < categoryOrder.length; ++i) {\n categoryToIndex.set(categories[categoryOrder[i]], i);\n }\n\n const drawThreadEntries =\n (context: CanvasRenderingContext2D, threadData: Trace.Handlers.Threads.ThreadData): void => {\n const quantizer = new Quantizer(this.#start, quantTime, drawSample);\n let x = 0;\n const categoryIndexStack: number[] = [];\n const paths: Path2D[] = [];\n const lastY: number[] = [];\n for (let i = 0; i < categoryOrder.length; ++i) {\n paths[i] = new Path2D();\n paths[i].moveTo(0, height);\n lastY[i] = height;\n }\n\n function drawSample(counters: number[]): void {\n let y = baseLine;\n for (let i = idleIndex + 1; i < categoryOrder.length; ++i) {\n const h = (counters[i] || 0) / quantTime * height;\n y -= h;\n paths[i].bezierCurveTo(x, lastY[i], x, y, x + quantSizePx / 2, y);\n lastY[i] = y;\n }\n x += quantSizePx;\n }\n\n const onEntryStart = (entry: Trace.Types.Events.Event): void => {\n const category = this.#entryCategory(entry);\n if (!category || category === 'idle') {\n // Idle event won't show in CPU activity, so just skip them.\n return;\n }\n const startTimeMilli = Trace.Helpers.Timing.microSecondsToMilliseconds(entry.ts);\n const index = categoryIndexStack.length ? categoryIndexStack[categoryIndexStack.length - 1] : idleIndex;\n quantizer.appendInterval(startTimeMilli, index);\n const categoryIndex = categoryOrder.indexOf(category);\n categoryIndexStack.push(categoryIndex || otherIndex);\n };\n\n function onEntryEnd(entry: Trace.Types.Events.Event): void {\n const endTimeMilli = Trace.Helpers.Timing.microSecondsToMilliseconds(entry.ts) +\n Trace.Helpers.Timing.microSecondsToMilliseconds(Trace.Types.Timing.MicroSeconds(entry.dur || 0));\n const lastCategoryIndex = categoryIndexStack.pop();\n if (endTimeMilli !== undefined && lastCategoryIndex) {\n quantizer.appendInterval(endTimeMilli, lastCategoryIndex);\n }\n }\n const startMicro = Trace.Helpers.Timing.millisecondsToMicroseconds(this.#start);\n const endMicro = Trace.Helpers.Timing.millisecondsToMicroseconds(this.#end);\n const bounds = {\n min: startMicro,\n max: endMicro,\n range: Trace.Types.Timing.MicroSeconds(endMicro - startMicro),\n };\n\n // Filter out tiny events - they don't make a visual impact to the\n // canvas as they are so small, but they do impact the time it takes\n // to walk the tree and render the events.\n // However, if the entire range we are showing is 200ms or less, then show all events.\n const minDuration = Trace.Types.Timing.MicroSeconds(\n bounds.range > 200_000 ? 16_000 : 0,\n );\n Trace.Helpers.TreeHelpers.walkEntireTree(\n threadData.entryToNode, threadData.tree, onEntryStart, onEntryEnd, bounds, minDuration);\n quantizer.appendInterval(this.#start + timeRange + quantTime, idleIndex); // Kick drawing the last bucket.\n for (let i = categoryOrder.length - 1; i > 0; --i) {\n paths[i].lineTo(width, height);\n const computedColorValue = categories[categoryOrder[i]].getComputedColorValue();\n context.fillStyle = computedColorValue;\n context.fill(paths[i]);\n context.strokeStyle = 'white';\n context.lineWidth = 1;\n context.stroke(paths[i]);\n }\n };\n const backgroundContext = (this.backgroundCanvas.getContext('2d') as CanvasRenderingContext2D | null);\n if (!backgroundContext) {\n throw new Error('Could not find 2d canvas');\n }\n\n const threads = Trace.Handlers.Threads.threadsInTrace(parsedTrace);\n const mainThreadContext = this.context();\n for (const thread of threads) {\n // We treat CPU_PROFILE as main thread because in a CPU Profile trace there is only ever one thread.\n const isMainThread = thread.type === Trace.Handlers.Threads.ThreadType.MAIN_THREAD ||\n thread.type === Trace.Handlers.Threads.ThreadType.CPU_PROFILE;\n if (isMainThread) {\n drawThreadEntries(mainThreadContext, thread);\n } else {\n drawThreadEntries(backgroundContext, thread);\n }\n }\n\n function applyPattern(ctx: CanvasRenderingContext2D): void {\n const step = 4 * window.devicePixelRatio;\n ctx.save();\n ctx.lineWidth = step / Math.sqrt(8);\n for (let x = 0.5; x < width + height; x += step) {\n ctx.moveTo(x, 0);\n ctx.lineTo(x - height, height);\n }\n ctx.globalCompositeOperation = 'destination-out';\n ctx.stroke();\n ctx.restore();\n }\n\n applyPattern(backgroundContext);\n }\n\n override update(): void {\n const traceBoundsState = TraceBounds.TraceBounds.BoundsManager.instance().state();\n const bounds = traceBoundsState?.milli.minimapTraceBounds;\n if (!bounds) {\n return;\n }\n if (bounds.min === this.#start && bounds.max === this.#end && this.#drawn) {\n return;\n }\n this.#start = bounds.min;\n this.#end = bounds.max;\n // Order matters here, resetCanvas will set this.#drawn to false.\n this.resetCanvas();\n this.#drawn = true;\n this.#draw(this.#parsedTrace);\n }\n}\n\nexport class TimelineEventOverviewResponsiveness extends TimelineEventOverview {\n #parsedTrace: Trace.Handlers.Types.ParsedTrace;\n constructor(parsedTrace: Trace.Handlers.Types.ParsedTrace) {\n super('responsiveness', null);\n this.#parsedTrace = parsedTrace;\n }\n\n #gatherEventsWithRelevantWarnings(): Set {\n const {topLevelRendererIds} = this.#parsedTrace.Meta;\n\n // All the warnings that we care about regarding responsiveness and want to represent on the overview.\n const warningsForResponsiveness = new Set([\n 'LONG_TASK',\n 'FORCED_REFLOW',\n 'IDLE_CALLBACK_OVER_TIME',\n ]);\n\n const allWarningEvents = new Set();\n for (const warning of warningsForResponsiveness) {\n const eventsForWarning = this.#parsedTrace.Warnings.perWarning.get(warning);\n if (!eventsForWarning) {\n continue;\n }\n\n for (const event of eventsForWarning) {\n // Only keep events whose PID is a top level renderer, which means it\n // was on the main thread. This avoids showing issues from iframes or\n // other sub-frames in the minimap overview.\n if (topLevelRendererIds.has(event.pid)) {\n allWarningEvents.add(event);\n }\n }\n }\n return allWarningEvents;\n }\n\n override update(start?: Trace.Types.Timing.MilliSeconds, end?: Trace.Types.Timing.MilliSeconds): void {\n this.resetCanvas();\n\n const height = this.height();\n const visibleTimeWindow = !(start && end) ? this.#parsedTrace.Meta.traceBounds : {\n min: Trace.Helpers.Timing.millisecondsToMicroseconds(start),\n max: Trace.Helpers.Timing.millisecondsToMicroseconds(end),\n range: Trace.Helpers.Timing.millisecondsToMicroseconds(Trace.Types.Timing.MilliSeconds(end - start)),\n };\n const timeSpan = visibleTimeWindow.range;\n const scale = this.width() / timeSpan;\n const ctx = this.context();\n const fillPath = new Path2D();\n const markersPath = new Path2D();\n\n const eventsWithWarning = this.#gatherEventsWithRelevantWarnings();\n for (const event of eventsWithWarning) {\n paintWarningDecoration(event);\n }\n\n ctx.fillStyle = 'hsl(0, 80%, 90%)';\n ctx.strokeStyle = 'red';\n ctx.lineWidth = 2 * window.devicePixelRatio;\n ctx.fill(fillPath);\n ctx.stroke(markersPath);\n\n function paintWarningDecoration(event: Trace.Types.Events.Event): void {\n const {startTime, duration} = Trace.Helpers.Timing.eventTimingsMicroSeconds(event);\n const x = Math.round(scale * (startTime - visibleTimeWindow.min));\n const width = Math.round(scale * duration);\n fillPath.rect(x, 0, width, height);\n markersPath.moveTo(x + width, 0);\n markersPath.lineTo(x + width, height);\n }\n }\n}\n\nexport class TimelineFilmStripOverview extends TimelineEventOverview {\n private frameToImagePromise: Map>;\n private lastFrame: Trace.Extras.FilmStrip.Frame|null = null;\n private lastElement: Element|null;\n private drawGeneration?: symbol;\n private emptyImage?: HTMLImageElement;\n #filmStrip: Trace.Extras.FilmStrip.Data|null = null;\n\n constructor(filmStrip: Trace.Extras.FilmStrip.Data) {\n super('filmstrip', null);\n this.element.setAttribute('jslog', `${VisualLogging.section('film-strip')}`);\n this.frameToImagePromise = new Map();\n this.#filmStrip = filmStrip;\n this.lastFrame = null;\n this.lastElement = null;\n this.reset();\n }\n\n override update(customStartTime?: Trace.Types.Timing.MilliSeconds, customEndTime?: Trace.Types.Timing.MilliSeconds):\n void {\n this.resetCanvas();\n const frames = this.#filmStrip ? this.#filmStrip.frames : [];\n if (!frames.length) {\n return;\n }\n\n if (this.height() === 0) {\n // Height of 0 causes the maths below to get off and generate very large\n // negative numbers that cause an extremely long loop when attempting to\n // draw images by frame. Rather than that, let's warn and exist early.\n console.warn('TimelineFilmStrip could not be drawn as its canvas height is 0');\n return;\n }\n\n const drawGeneration = Symbol('drawGeneration');\n this.drawGeneration = drawGeneration;\n void this.imageByFrame(frames[0]).then(image => {\n if (this.drawGeneration !== drawGeneration) {\n return;\n }\n if (!image || !image.naturalWidth || !image.naturalHeight) {\n return;\n }\n const imageHeight = this.height() - 2 * TimelineFilmStripOverview.Padding;\n const imageWidth = Math.ceil(imageHeight * image.naturalWidth / image.naturalHeight);\n const popoverScale = Math.min(200 / image.naturalWidth, 1);\n this.emptyImage = new Image(image.naturalWidth * popoverScale, image.naturalHeight * popoverScale);\n this.drawFrames(imageWidth, imageHeight, customStartTime, customEndTime);\n });\n }\n\n private async imageByFrame(frame: Trace.Extras.FilmStrip.Frame): Promise {\n let imagePromise: Promise|undefined = this.frameToImagePromise.get(frame);\n if (!imagePromise) {\n imagePromise = UI.UIUtils.loadImage(frame.screenshotEvent.args.dataUri);\n this.frameToImagePromise.set(frame, (imagePromise as Promise));\n }\n return imagePromise;\n }\n\n private drawFrames(\n imageWidth: number, imageHeight: number, customStartTime?: Trace.Types.Timing.MilliSeconds,\n customEndTime?: Trace.Types.Timing.MilliSeconds): void {\n if (!imageWidth) {\n return;\n }\n if (!this.#filmStrip || this.#filmStrip.frames.length < 1) {\n return;\n }\n const padding = TimelineFilmStripOverview.Padding;\n const width = this.width();\n\n const zeroTime = customStartTime ?? Trace.Helpers.Timing.microSecondsToMilliseconds(this.#filmStrip.zeroTime);\n const spanTime = customEndTime ? customEndTime - zeroTime :\n Trace.Helpers.Timing.microSecondsToMilliseconds(this.#filmStrip.spanTime);\n const scale = spanTime / width;\n const context = this.context();\n const drawGeneration = this.drawGeneration;\n\n context.beginPath();\n for (let x = padding; x < width; x += imageWidth + 2 * padding) {\n const time = Trace.Types.Timing.MilliSeconds(zeroTime + (x + imageWidth / 2) * scale);\n const timeMicroSeconds = Trace.Helpers.Timing.millisecondsToMicroseconds(time);\n const frame = Trace.Extras.FilmStrip.frameClosestToTimestamp(this.#filmStrip, timeMicroSeconds);\n if (!frame) {\n continue;\n }\n context.rect(x - 0.5, 0.5, imageWidth + 1, imageHeight + 1);\n void this.imageByFrame(frame).then(drawFrameImage.bind(this, x));\n }\n context.strokeStyle = '#ddd';\n context.stroke();\n\n function drawFrameImage(this: TimelineFilmStripOverview, x: number, image: HTMLImageElement|null): void {\n // Ignore draws deferred from a previous update call.\n if (this.drawGeneration !== drawGeneration || !image) {\n return;\n }\n context.drawImage(image, x, 1, imageWidth, imageHeight);\n }\n }\n\n override async overviewInfoPromise(x: number): Promise {\n if (!this.#filmStrip || this.#filmStrip.frames.length === 0) {\n return null;\n }\n\n const calculator = this.calculator();\n if (!calculator) {\n return null;\n }\n const timeMilliSeconds = Trace.Types.Timing.MilliSeconds(calculator.positionToTime(x));\n const timeMicroSeconds = Trace.Helpers.Timing.millisecondsToMicroseconds(timeMilliSeconds);\n const frame = Trace.Extras.FilmStrip.frameClosestToTimestamp(this.#filmStrip, timeMicroSeconds);\n if (frame === this.lastFrame) {\n return this.lastElement;\n }\n const imagePromise = frame ? this.imageByFrame(frame) : Promise.resolve(this.emptyImage);\n const image = await imagePromise;\n const element = document.createElement('div');\n element.classList.add('frame');\n if (image) {\n element.createChild('div', 'thumbnail').appendChild(image);\n }\n this.lastFrame = frame;\n this.lastElement = element;\n return element;\n }\n\n override reset(): void {\n this.lastFrame = null;\n this.lastElement = null;\n this.frameToImagePromise = new Map();\n }\n\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/naming-convention\n static readonly Padding = 2;\n}\n\nexport class TimelineEventOverviewMemory extends TimelineEventOverview {\n private heapSizeLabel: HTMLElement;\n #parsedTrace: Trace.Handlers.Types.ParsedTrace;\n\n constructor(parsedTrace: Trace.Handlers.Types.ParsedTrace) {\n super('memory', i18nString(UIStrings.heap));\n this.heapSizeLabel = this.element.createChild('div', 'memory-graph-label');\n this.#parsedTrace = parsedTrace;\n }\n\n resetHeapSizeLabels(): void {\n this.heapSizeLabel.textContent = '';\n }\n\n override update(start?: Trace.Types.Timing.MilliSeconds, end?: Trace.Types.Timing.MilliSeconds): void {\n this.resetCanvas();\n const ratio = window.devicePixelRatio;\n\n if (this.#parsedTrace.Memory.updateCountersByProcess.size === 0) {\n this.resetHeapSizeLabels();\n return;\n }\n\n const mainRendererIds = Array.from(this.#parsedTrace.Meta.topLevelRendererIds);\n const counterEventsPerTrack =\n mainRendererIds.map(pid => this.#parsedTrace.Memory.updateCountersByProcess.get(pid) || [])\n .filter(eventsPerRenderer => eventsPerRenderer.length > 0);\n\n const lowerOffset = 3 * ratio;\n let maxUsedHeapSize = 0;\n let minUsedHeapSize = 100000000000;\n\n const boundsMs = (start && end) ? {\n min: start,\n max: end,\n range: end - start,\n } :\n Trace.Helpers.Timing.traceWindowMilliSeconds(this.#parsedTrace.Meta.traceBounds);\n const minTime = boundsMs.min;\n const maxTime = boundsMs.max;\n\n function calculateMinMaxSizes(event: Trace.Types.Events.UpdateCounters): void {\n const counters = event.args.data;\n if (!counters || !counters.jsHeapSizeUsed) {\n return;\n }\n maxUsedHeapSize = Math.max(maxUsedHeapSize, counters.jsHeapSizeUsed);\n minUsedHeapSize = Math.min(minUsedHeapSize, counters.jsHeapSizeUsed);\n }\n\n for (let i = 0; i < counterEventsPerTrack.length; i++) {\n counterEventsPerTrack[i].forEach(calculateMinMaxSizes);\n }\n\n minUsedHeapSize = Math.min(minUsedHeapSize, maxUsedHeapSize);\n\n const lineWidth = 1;\n const width = this.width();\n const height = this.height() - lowerOffset;\n const xFactor = width / (maxTime - minTime);\n const yFactor = (height - lineWidth) / Math.max(maxUsedHeapSize - minUsedHeapSize, 1);\n\n const histogram = new Array(width);\n\n function buildHistogram(event: Trace.Types.Events.UpdateCounters): void {\n const counters = event.args.data;\n if (!counters || !counters.jsHeapSizeUsed) {\n return;\n }\n const {startTime} = Trace.Helpers.Timing.eventTimingsMilliSeconds(event);\n const x = Math.round((startTime - minTime) * xFactor);\n const y = Math.round((counters.jsHeapSizeUsed - minUsedHeapSize) * yFactor);\n histogram[x] = Math.max(histogram[x] || 0, y);\n }\n for (let i = 0; i < counterEventsPerTrack.length; i++) {\n counterEventsPerTrack[i].forEach(buildHistogram);\n }\n\n const ctx = this.context();\n const heightBeyondView = height + lowerOffset + lineWidth;\n\n ctx.translate(0.5, 0.5);\n ctx.beginPath();\n ctx.moveTo(-lineWidth, heightBeyondView);\n let y = 0;\n let isFirstPoint = true;\n let lastX = 0;\n for (let x = 0; x < histogram.length; x++) {\n if (typeof histogram[x] === 'undefined') {\n continue;\n }\n if (isFirstPoint) {\n isFirstPoint = false;\n y = histogram[x];\n ctx.lineTo(-lineWidth, height - y);\n }\n const nextY = histogram[x];\n if (Math.abs(nextY - y) > 2 && Math.abs(x - lastX) > 1) {\n ctx.lineTo(x, height - y);\n }\n y = nextY;\n ctx.lineTo(x, height - y);\n lastX = x;\n }\n ctx.lineTo(width + lineWidth, height - y);\n ctx.lineTo(width + lineWidth, heightBeyondView);\n ctx.closePath();\n\n ctx.fillStyle = 'hsla(220, 90%, 70%, 0.2)';\n ctx.fill();\n ctx.lineWidth = lineWidth;\n ctx.strokeStyle = 'hsl(220, 90%, 70%)';\n ctx.stroke();\n\n this.heapSizeLabel.textContent = i18nString(UIStrings.sSDash, {\n PH1: Platform.NumberUtilities.bytesToString(minUsedHeapSize),\n PH2: Platform.NumberUtilities.bytesToString(maxUsedHeapSize),\n });\n }\n}\n\nexport class Quantizer {\n private lastTime: number;\n private quantDuration: number;\n private readonly callback: (arg0: Array) => void;\n private counters: number[];\n private remainder: number;\n constructor(startTime: number, quantDuration: number, callback: (arg0: Array) => void) {\n this.lastTime = startTime;\n this.quantDuration = quantDuration;\n this.callback = callback;\n this.counters = [];\n this.remainder = quantDuration;\n }\n\n appendInterval(time: number, group: number): void {\n let interval = time - this.lastTime;\n if (interval <= this.remainder) {\n this.counters[group] = (this.counters[group] || 0) + interval;\n this.remainder -= interval;\n this.lastTime = time;\n return;\n }\n this.counters[group] = (this.counters[group] || 0) + this.remainder;\n this.callback(this.counters);\n interval -= this.remainder;\n while (interval >= this.quantDuration) {\n const counters = [];\n counters[group] = this.quantDuration;\n this.callback(counters);\n interval -= this.quantDuration;\n }\n this.counters = [];\n this.counters[group] = interval;\n this.lastTime = time;\n this.remainder = this.quantDuration - interval;\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineFilters.d.ts b/public/panels/timeline/TimelineFilters.d.ts index 1b5428264..6956364fe 100644 --- a/public/panels/timeline/TimelineFilters.d.ts +++ b/public/panels/timeline/TimelineFilters.d.ts @@ -1,19 +1,19 @@ import * as TimelineModel from '../../models/timeline_model/timeline_model.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; export declare class IsLong extends TimelineModel.TimelineModelFilter.TimelineModelFilter { #private; constructor(); - setMinimumRecordDuration(value: TraceEngine.Types.Timing.MilliSeconds): void; - accept(event: TraceEngine.Types.TraceEvents.TraceEventData): boolean; + setMinimumRecordDuration(value: Trace.Types.Timing.MilliSeconds): void; + accept(event: Trace.Types.Events.Event): boolean; } export declare class Category extends TimelineModel.TimelineModelFilter.TimelineModelFilter { constructor(); - accept(event: TraceEngine.Types.TraceEvents.TraceEventData): boolean; + accept(event: Trace.Types.Events.Event): boolean; } export declare class TimelineRegExp extends TimelineModel.TimelineModelFilter.TimelineModelFilter { private regExpInternal; constructor(regExp?: RegExp); setRegExp(regExp: RegExp | null): void; regExp(): RegExp | null; - accept(event: TraceEngine.Types.TraceEvents.TraceEventData, traceParsedData?: TraceEngine.Handlers.Types.TraceParseData): boolean; + accept(event: Trace.Types.Events.Event, parsedTrace?: Trace.Handlers.Types.ParsedTrace): boolean; } diff --git a/public/panels/timeline/TimelineFilters.js b/public/panels/timeline/TimelineFilters.js index e5c1c3a6d..e71ceab29 100644 --- a/public/panels/timeline/TimelineFilters.js +++ b/public/panels/timeline/TimelineFilters.js @@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as TimelineModel from '../../models/timeline_model/timeline_model.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import { TimelineUIUtils } from './TimelineUIUtils.js'; export class IsLong extends TimelineModel.TimelineModelFilter.TimelineModelFilter { - #minimumRecordDurationMilli = TraceEngine.Types.Timing.MilliSeconds(0); + #minimumRecordDurationMilli = Trace.Types.Timing.MilliSeconds(0); constructor() { super(); } @@ -13,7 +13,7 @@ export class IsLong extends TimelineModel.TimelineModelFilter.TimelineModelFilte this.#minimumRecordDurationMilli = value; } accept(event) { - const { duration } = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event); + const { duration } = Trace.Helpers.Timing.eventTimingsMilliSeconds(event); return duration >= this.#minimumRecordDurationMilli; } } @@ -37,8 +37,8 @@ export class TimelineRegExp extends TimelineModel.TimelineModelFilter.TimelineMo regExp() { return this.regExpInternal; } - accept(event, traceParsedData) { - return !this.regExpInternal || TimelineUIUtils.testContentMatching(event, this.regExpInternal, traceParsedData); + accept(event, parsedTrace) { + return !this.regExpInternal || TimelineUIUtils.testContentMatching(event, this.regExpInternal, parsedTrace); } } //# sourceMappingURL=TimelineFilters.js.map \ No newline at end of file diff --git a/public/panels/timeline/TimelineFilters.js.map b/public/panels/timeline/TimelineFilters.js.map index dfd08bb89..38f47e080 100644 --- a/public/panels/timeline/TimelineFilters.js.map +++ b/public/panels/timeline/TimelineFilters.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineFilters.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineFilters.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,aAAa,MAAM,+CAA+C,CAAC;AAC/E,OAAO,KAAK,WAAW,MAAM,6BAA6B,CAAC;AAE3D,OAAO,EAAC,eAAe,EAAC,MAAM,sBAAsB,CAAC;AAErD,MAAM,OAAO,MAAO,SAAQ,aAAa,CAAC,mBAAmB,CAAC,mBAAmB;IAC/E,2BAA2B,GAAG,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACvE;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAED,wBAAwB,CAAC,KAA4C;QACnE,IAAI,CAAC,2BAA2B,GAAG,KAAK,CAAC;IAC3C,CAAC;IAED,MAAM,CAAC,KAAmD;QACxD,MAAM,EAAC,QAAQ,EAAC,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAAC;QAC9E,OAAO,QAAQ,IAAI,IAAI,CAAC,2BAA2B,CAAC;IACtD,CAAC;CACF;AAED,MAAM,OAAO,QAAS,SAAQ,aAAa,CAAC,mBAAmB,CAAC,mBAAmB;IACjF;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAED,MAAM,CAAC,KAAmD;QACxD,OAAO,CAAC,eAAe,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;IAC5D,CAAC;CACF;AAED,MAAM,OAAO,cAAe,SAAQ,aAAa,CAAC,mBAAmB,CAAC,mBAAmB;IAC/E,cAAc,CAAe;IACrC,YAAY,MAAe;QACzB,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,SAAS,CAAC,MAAmB;QAC3B,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC;IAC/B,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,MAAM,CACF,KAAmD,EACnD,eAA2D;QAC7D,OAAO,CAAC,IAAI,CAAC,cAAc,IAAI,eAAe,CAAC,mBAAmB,CAAC,KAAK,EAAE,IAAI,CAAC,cAAc,EAAE,eAAe,CAAC,CAAC;IAClH,CAAC;CACF","sourcesContent":["// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\n\nimport {TimelineUIUtils} from './TimelineUIUtils.js';\n\nexport class IsLong extends TimelineModel.TimelineModelFilter.TimelineModelFilter {\n #minimumRecordDurationMilli = TraceEngine.Types.Timing.MilliSeconds(0);\n constructor() {\n super();\n }\n\n setMinimumRecordDuration(value: TraceEngine.Types.Timing.MilliSeconds): void {\n this.#minimumRecordDurationMilli = value;\n }\n\n accept(event: TraceEngine.Types.TraceEvents.TraceEventData): boolean {\n const {duration} = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event);\n return duration >= this.#minimumRecordDurationMilli;\n }\n}\n\nexport class Category extends TimelineModel.TimelineModelFilter.TimelineModelFilter {\n constructor() {\n super();\n }\n\n accept(event: TraceEngine.Types.TraceEvents.TraceEventData): boolean {\n return !TimelineUIUtils.eventStyle(event).category.hidden;\n }\n}\n\nexport class TimelineRegExp extends TimelineModel.TimelineModelFilter.TimelineModelFilter {\n private regExpInternal!: RegExp|null;\n constructor(regExp?: RegExp) {\n super();\n this.setRegExp(regExp || null);\n }\n\n setRegExp(regExp: RegExp|null): void {\n this.regExpInternal = regExp;\n }\n\n regExp(): RegExp|null {\n return this.regExpInternal;\n }\n\n accept(\n event: TraceEngine.Types.TraceEvents.TraceEventData,\n traceParsedData?: TraceEngine.Handlers.Types.TraceParseData): boolean {\n return !this.regExpInternal || TimelineUIUtils.testContentMatching(event, this.regExpInternal, traceParsedData);\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"TimelineFilters.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineFilters.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,aAAa,MAAM,+CAA+C,CAAC;AAC/E,OAAO,KAAK,KAAK,MAAM,6BAA6B,CAAC;AAErD,OAAO,EAAC,eAAe,EAAC,MAAM,sBAAsB,CAAC;AAErD,MAAM,OAAO,MAAO,SAAQ,aAAa,CAAC,mBAAmB,CAAC,mBAAmB;IAC/E,2BAA2B,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACjE;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAED,wBAAwB,CAAC,KAAsC;QAC7D,IAAI,CAAC,2BAA2B,GAAG,KAAK,CAAC;IAC3C,CAAC;IAED,MAAM,CAAC,KAA+B;QACpC,MAAM,EAAC,QAAQ,EAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAAC;QACxE,OAAO,QAAQ,IAAI,IAAI,CAAC,2BAA2B,CAAC;IACtD,CAAC;CACF;AAED,MAAM,OAAO,QAAS,SAAQ,aAAa,CAAC,mBAAmB,CAAC,mBAAmB;IACjF;QACE,KAAK,EAAE,CAAC;IACV,CAAC;IAED,MAAM,CAAC,KAA+B;QACpC,OAAO,CAAC,eAAe,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC;IAC5D,CAAC;CACF;AAED,MAAM,OAAO,cAAe,SAAQ,aAAa,CAAC,mBAAmB,CAAC,mBAAmB;IAC/E,cAAc,CAAe;IACrC,YAAY,MAAe;QACzB,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC;IACjC,CAAC;IAED,SAAS,CAAC,MAAmB;QAC3B,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC;IAC/B,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,MAAM,CAAC,KAA+B,EAAE,WAA8C;QACpF,OAAO,CAAC,IAAI,CAAC,cAAc,IAAI,eAAe,CAAC,mBAAmB,CAAC,KAAK,EAAE,IAAI,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;IAC9G,CAAC;CACF","sourcesContent":["// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport * as Trace from '../../models/trace/trace.js';\n\nimport {TimelineUIUtils} from './TimelineUIUtils.js';\n\nexport class IsLong extends TimelineModel.TimelineModelFilter.TimelineModelFilter {\n #minimumRecordDurationMilli = Trace.Types.Timing.MilliSeconds(0);\n constructor() {\n super();\n }\n\n setMinimumRecordDuration(value: Trace.Types.Timing.MilliSeconds): void {\n this.#minimumRecordDurationMilli = value;\n }\n\n accept(event: Trace.Types.Events.Event): boolean {\n const {duration} = Trace.Helpers.Timing.eventTimingsMilliSeconds(event);\n return duration >= this.#minimumRecordDurationMilli;\n }\n}\n\nexport class Category extends TimelineModel.TimelineModelFilter.TimelineModelFilter {\n constructor() {\n super();\n }\n\n accept(event: Trace.Types.Events.Event): boolean {\n return !TimelineUIUtils.eventStyle(event).category.hidden;\n }\n}\n\nexport class TimelineRegExp extends TimelineModel.TimelineModelFilter.TimelineModelFilter {\n private regExpInternal!: RegExp|null;\n constructor(regExp?: RegExp) {\n super();\n this.setRegExp(regExp || null);\n }\n\n setRegExp(regExp: RegExp|null): void {\n this.regExpInternal = regExp;\n }\n\n regExp(): RegExp|null {\n return this.regExpInternal;\n }\n\n accept(event: Trace.Types.Events.Event, parsedTrace?: Trace.Handlers.Types.ParsedTrace): boolean {\n return !this.regExpInternal || TimelineUIUtils.testContentMatching(event, this.regExpInternal, parsedTrace);\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineFilters.test.js b/public/panels/timeline/TimelineFilters.test.js index 9db8ae746..2807c0eaa 100644 --- a/public/panels/timeline/TimelineFilters.test.js +++ b/public/panels/timeline/TimelineFilters.test.js @@ -1,7 +1,7 @@ // 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 * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import { describeWithEnvironment } from '../../testing/EnvironmentHelpers.js'; import { getMainThread } from '../../testing/TraceHelpers.js'; import { TraceLoader } from '../../testing/TraceLoader.js'; @@ -10,43 +10,40 @@ import * as Timeline from './timeline.js'; describeWithEnvironment('TimelineFilters', () => { describe('IsLong', () => { it('returns true if the event is longer than the defined duration for a new engine event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz'); - const longEvent = getMainThread(traceData.Renderer).entries.find(event => { + const { parsedTrace } = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz'); + const longEvent = getMainThread(parsedTrace.Renderer).entries.find(event => { return event.dur && - event.dur > - TraceEngine.Helpers.Timing.millisecondsToMicroseconds(TraceEngine.Types.Timing.MilliSeconds(50)); + event.dur > Trace.Helpers.Timing.millisecondsToMicroseconds(Trace.Types.Timing.MilliSeconds(50)); }); if (!longEvent) { throw new Error('Could not find expected long event.'); } const filter = new Timeline.TimelineFilters.IsLong(); - filter.setMinimumRecordDuration(TraceEngine.Types.Timing.MilliSeconds(50)); + filter.setMinimumRecordDuration(Trace.Types.Timing.MilliSeconds(50)); assert.isTrue(filter.accept(longEvent)); }); it('returns false if the event is shorter than the defined duration for a new engine event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz'); - const longEvent = getMainThread(traceData.Renderer).entries.find(event => { + const { parsedTrace } = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz'); + const longEvent = getMainThread(parsedTrace.Renderer).entries.find(event => { return event.dur && - event.dur > - TraceEngine.Helpers.Timing.millisecondsToMicroseconds(TraceEngine.Types.Timing.MilliSeconds(50)) && - event.dur < - TraceEngine.Helpers.Timing.millisecondsToMicroseconds(TraceEngine.Types.Timing.MilliSeconds(100)); + event.dur > Trace.Helpers.Timing.millisecondsToMicroseconds(Trace.Types.Timing.MilliSeconds(50)) && + event.dur < Trace.Helpers.Timing.millisecondsToMicroseconds(Trace.Types.Timing.MilliSeconds(100)); }); if (!longEvent) { throw new Error('Could not find expected long event.'); } const filter = new Timeline.TimelineFilters.IsLong(); - filter.setMinimumRecordDuration(TraceEngine.Types.Timing.MilliSeconds(101)); + filter.setMinimumRecordDuration(Trace.Types.Timing.MilliSeconds(101)); assert.isFalse(filter.accept(longEvent)); }); }); describe('Category', () => { it('returns false for a new event if it has a category that is hidden', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'user-timings.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'user-timings.json.gz'); // These events are usually visible, so make the category hidden before // running this test. Components.EntryStyles.getCategoryStyles()['scripting'].hidden = true; - const userTimingEvent = traceData.UserTimings.performanceMeasures.at(0); + const userTimingEvent = parsedTrace.UserTimings.performanceMeasures.at(0); if (!userTimingEvent) { throw new Error('Could not find expected event.'); } @@ -55,8 +52,8 @@ describeWithEnvironment('TimelineFilters', () => { Components.EntryStyles.getCategoryStyles()['scripting'].hidden = false; }); it('returns true for a new event if it has a category that is visible', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'user-timings.json.gz'); - const userTimingEvent = traceData.UserTimings.performanceMeasures.at(0); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'user-timings.json.gz'); + const userTimingEvent = parsedTrace.UserTimings.performanceMeasures.at(0); if (!userTimingEvent) { throw new Error('Could not find expected event.'); } diff --git a/public/panels/timeline/TimelineFilters.test.js.map b/public/panels/timeline/TimelineFilters.test.js.map index 5f66ee23f..4ed14857f 100644 --- a/public/panels/timeline/TimelineFilters.test.js.map +++ b/public/panels/timeline/TimelineFilters.test.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineFilters.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineFilters.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,WAAW,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAC,uBAAuB,EAAC,MAAM,qCAAqC,CAAC;AAC5E,OAAO,EAAC,aAAa,EAAC,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAC,WAAW,EAAC,MAAM,8BAA8B,CAAC;AAEzD,OAAO,KAAK,UAAU,MAAM,4BAA4B,CAAC;AACzD,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAE1C,uBAAuB,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC9C,QAAQ,CAAC,QAAQ,EAAE,GAAG,EAAE;QACtB,EAAE,CAAC,sFAAsF,EAAE,KAAK;YAC9F,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,gCAAgC,CAAC,CAAC;YAC1F,MAAM,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;gBACvE,OAAO,KAAK,CAAC,GAAG;oBACZ,KAAK,CAAC,GAAG;wBACT,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC;YACvG,CAAC,CAAC,CAAC;YACH,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;YACzD,CAAC;YAED,MAAM,MAAM,GAAG,IAAI,QAAQ,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC;YACrD,MAAM,CAAC,wBAAwB,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC;YAC3E,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wFAAwF,EAAE,KAAK;YAChG,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,gCAAgC,CAAC,CAAC;YAC1F,MAAM,SAAS,GAAG,aAAa,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;gBACvE,OAAO,KAAK,CAAC,GAAG;oBACZ,KAAK,CAAC,GAAG;wBACT,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;oBAChG,KAAK,CAAC,GAAG;wBACT,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;YACxG,CAAC,CAAC,CAAC;YACH,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;YACzD,CAAC;YAED,MAAM,MAAM,GAAG,IAAI,QAAQ,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC;YACrD,MAAM,CAAC,wBAAwB,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5E,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE;QACxB,EAAE,CAAC,mEAAmE,EAAE,KAAK;YAC3E,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC;YAChF,uEAAuE;YACvE,qBAAqB;YACrB,UAAU,CAAC,WAAW,CAAC,iBAAiB,EAAE,CAAC,WAAW,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC;YAEtE,MAAM,eAAe,GAAG,SAAS,CAAC,WAAW,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACxE,IAAI,CAAC,eAAe,EAAE,CAAC;gBACrB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;YACpD,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,QAAQ,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC;YACvD,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC;YAC/C,UAAU,CAAC,WAAW,CAAC,iBAAiB,EAAE,CAAC,WAAW,CAAC,CAAC,MAAM,GAAG,KAAK,CAAC;QACzE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mEAAmE,EAAE,KAAK;YAC3E,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,sBAAsB,CAAC,CAAC;YAChF,MAAM,eAAe,GAAG,SAAS,CAAC,WAAW,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACxE,IAAI,CAAC,eAAe,EAAE,CAAC;gBACrB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;YACpD,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,QAAQ,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC;YACvD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC;YAC9C,UAAU,CAAC,WAAW,CAAC,iBAAiB,EAAE,CAAC,WAAW,CAAC,CAAC,MAAM,GAAG,KAAK,CAAC;QACzE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {getMainThread} from '../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\n\nimport * as Components from './components/components.js';\nimport * as Timeline from './timeline.js';\n\ndescribeWithEnvironment('TimelineFilters', () => {\n describe('IsLong', () => {\n it('returns true if the event is longer than the defined duration for a new engine event', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz');\n const longEvent = getMainThread(traceData.Renderer).entries.find(event => {\n return event.dur &&\n event.dur >\n TraceEngine.Helpers.Timing.millisecondsToMicroseconds(TraceEngine.Types.Timing.MilliSeconds(50));\n });\n if (!longEvent) {\n throw new Error('Could not find expected long event.');\n }\n\n const filter = new Timeline.TimelineFilters.IsLong();\n filter.setMinimumRecordDuration(TraceEngine.Types.Timing.MilliSeconds(50));\n assert.isTrue(filter.accept(longEvent));\n });\n\n it('returns false if the event is shorter than the defined duration for a new engine event', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz');\n const longEvent = getMainThread(traceData.Renderer).entries.find(event => {\n return event.dur &&\n event.dur >\n TraceEngine.Helpers.Timing.millisecondsToMicroseconds(TraceEngine.Types.Timing.MilliSeconds(50)) &&\n event.dur <\n TraceEngine.Helpers.Timing.millisecondsToMicroseconds(TraceEngine.Types.Timing.MilliSeconds(100));\n });\n if (!longEvent) {\n throw new Error('Could not find expected long event.');\n }\n\n const filter = new Timeline.TimelineFilters.IsLong();\n filter.setMinimumRecordDuration(TraceEngine.Types.Timing.MilliSeconds(101));\n assert.isFalse(filter.accept(longEvent));\n });\n });\n\n describe('Category', () => {\n it('returns false for a new event if it has a category that is hidden', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'user-timings.json.gz');\n // These events are usually visible, so make the category hidden before\n // running this test.\n Components.EntryStyles.getCategoryStyles()['scripting'].hidden = true;\n\n const userTimingEvent = traceData.UserTimings.performanceMeasures.at(0);\n if (!userTimingEvent) {\n throw new Error('Could not find expected event.');\n }\n const filter = new Timeline.TimelineFilters.Category();\n assert.isFalse(filter.accept(userTimingEvent));\n Components.EntryStyles.getCategoryStyles()['scripting'].hidden = false;\n });\n\n it('returns true for a new event if it has a category that is visible', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'user-timings.json.gz');\n const userTimingEvent = traceData.UserTimings.performanceMeasures.at(0);\n if (!userTimingEvent) {\n throw new Error('Could not find expected event.');\n }\n const filter = new Timeline.TimelineFilters.Category();\n assert.isTrue(filter.accept(userTimingEvent));\n Components.EntryStyles.getCategoryStyles()['scripting'].hidden = false;\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"TimelineFilters.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineFilters.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {getMainThread} from '../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\n\nimport * as Components from './components/components.js';\nimport * as Timeline from './timeline.js';\n\ndescribeWithEnvironment('TimelineFilters', () => {\n describe('IsLong', () => {\n it('returns true if the event is longer than the defined duration for a new engine event', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz');\n const longEvent = getMainThread(parsedTrace.Renderer).entries.find(event => {\n return event.dur &&\n event.dur > Trace.Helpers.Timing.millisecondsToMicroseconds(Trace.Types.Timing.MilliSeconds(50));\n });\n if (!longEvent) {\n throw new Error('Could not find expected long event.');\n }\n\n const filter = new Timeline.TimelineFilters.IsLong();\n filter.setMinimumRecordDuration(Trace.Types.Timing.MilliSeconds(50));\n assert.isTrue(filter.accept(longEvent));\n });\n\n it('returns false if the event is shorter than the defined duration for a new engine event', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz');\n const longEvent = getMainThread(parsedTrace.Renderer).entries.find(event => {\n return event.dur &&\n event.dur > Trace.Helpers.Timing.millisecondsToMicroseconds(Trace.Types.Timing.MilliSeconds(50)) &&\n event.dur < Trace.Helpers.Timing.millisecondsToMicroseconds(Trace.Types.Timing.MilliSeconds(100));\n });\n if (!longEvent) {\n throw new Error('Could not find expected long event.');\n }\n\n const filter = new Timeline.TimelineFilters.IsLong();\n filter.setMinimumRecordDuration(Trace.Types.Timing.MilliSeconds(101));\n assert.isFalse(filter.accept(longEvent));\n });\n });\n\n describe('Category', () => {\n it('returns false for a new event if it has a category that is hidden', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'user-timings.json.gz');\n // These events are usually visible, so make the category hidden before\n // running this test.\n Components.EntryStyles.getCategoryStyles()['scripting'].hidden = true;\n\n const userTimingEvent = parsedTrace.UserTimings.performanceMeasures.at(0);\n if (!userTimingEvent) {\n throw new Error('Could not find expected event.');\n }\n const filter = new Timeline.TimelineFilters.Category();\n assert.isFalse(filter.accept(userTimingEvent));\n Components.EntryStyles.getCategoryStyles()['scripting'].hidden = false;\n });\n\n it('returns true for a new event if it has a category that is visible', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'user-timings.json.gz');\n const userTimingEvent = parsedTrace.UserTimings.performanceMeasures.at(0);\n if (!userTimingEvent) {\n throw new Error('Could not find expected event.');\n }\n const filter = new Timeline.TimelineFilters.Category();\n assert.isTrue(filter.accept(userTimingEvent));\n Components.EntryStyles.getCategoryStyles()['scripting'].hidden = false;\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineFlameChartDataProvider.d.ts b/public/panels/timeline/TimelineFlameChartDataProvider.d.ts index 955c083b1..db155e8e4 100644 --- a/public/panels/timeline/TimelineFlameChartDataProvider.d.ts +++ b/public/panels/timeline/TimelineFlameChartDataProvider.d.ts @@ -1,11 +1,11 @@ import * as Common from '../../core/common/common.js'; import type * as TimelineModel from '../../models/timeline_model/timeline_model.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; import * as UI from '../../ui/legacy/legacy.js'; -import { CompatibilityTracksAppender, type TrackAppenderName } from './CompatibilityTracksAppender.js'; +import { CompatibilityTracksAppender, type DrawOverride, type TrackAppenderName } from './CompatibilityTracksAppender.js'; import { TimelineSelection } from './TimelineSelection.js'; -export type TimelineFlameChartEntry = TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame | TraceEngine.Types.TraceEvents.TraceEventData; +export type TimelineFlameChartEntry = Trace.Handlers.ModelHandlers.Frames.TimelineFrame | Trace.Types.Events.Event; export declare class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectWrapper implements PerfUI.FlameChart.FlameChartDataProvider { #private; private droppedFramePatternCanvas; @@ -13,7 +13,7 @@ export declare class TimelineFlameChartDataProvider extends Common.ObjectWrapper private timelineDataInternal; private currentLevel; private compatibilityTracksAppender; - private traceEngineData; + private parsedTrace; private isCpuProfile; private minimumBoundaryInternal; private timeSpan; @@ -37,7 +37,7 @@ export declare class TimelineFlameChartDataProvider extends Common.ObjectWrapper findPossibleContextMenuActions(entryIndex: number): PerfUI.FlameChart.PossibleFilterActions | void; handleFlameChartTransformKeyboardEvent(event: KeyboardEvent, entryIndex: number, groupIndex: number): void; private buildGroupStyle; - setModel(traceEngineData: TraceEngine.Handlers.Types.TraceParseData | null, isCpuProfile?: boolean): void; + setModel(parsedTrace: Trace.Handlers.Types.ParsedTrace | null, isCpuProfile?: boolean): void; /** * Instances and caches a CompatibilityTracksAppender using the * internal flame chart data and the trace parsed data coming from the @@ -53,8 +53,8 @@ export declare class TimelineFlameChartDataProvider extends Common.ObjectWrapper filterThreadsByName?: string; expandedTracks?: Set; }): void; - groupTreeEvents(group: PerfUI.FlameChart.Group): TraceEngine.Types.TraceEvents.TraceEventData[] | null; - mainFrameNavigationStartEvents(): readonly TraceEngine.Types.TraceEvents.TraceEventNavigationStart[]; + groupTreeEvents(group: PerfUI.FlameChart.Group): Trace.Types.Events.Event[] | null; + mainFrameNavigationStartEvents(): readonly Trace.Types.Events.NavigationStart[]; entryTitle(entryIndex: number): string | null; textColor(index: number): string; entryFont(_index: number): string | null; @@ -68,13 +68,14 @@ export declare class TimelineFlameChartDataProvider extends Common.ObjectWrapper timelineData(rebuild?: boolean): PerfUI.FlameChart.FlameChartTimelineData; minimumBoundary(): number; totalTime(): number; - static timelineEntryIsTraceEvent(entry: TimelineFlameChartEntry): entry is TraceEngine.Types.TraceEvents.TraceEventData; - search(visibleWindow: TraceEngine.Types.Timing.TraceWindowMicroSeconds, filter: TimelineModel.TimelineModelFilter.TimelineModelFilter): PerfUI.FlameChart.DataProviderSearchResult[]; - isIgnoreListedEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): boolean; + static timelineEntryIsTraceEvent(entry: TimelineFlameChartEntry): entry is Trace.Types.Events.Event; + search(visibleWindow: Trace.Types.Timing.TraceWindowMicroSeconds, filter: TimelineModel.TimelineModelFilter.TimelineModelFilter): PerfUI.FlameChart.DataProviderSearchResult[]; + isIgnoreListedEvent(event: Trace.Types.Events.Event): boolean; private isIgnoreListedURL; getEntryTypeForLevel(level: number): EntryType; prepareHighlightedEntryInfo(entryIndex: number): Element | null; prepareHighlightedHiddenEntriesArrowInfo(entryIndex: number): Element | null; + getDrawOverride(entryIndex: number): DrawOverride | undefined; entryColor(entryIndex: number): string; private preparePatternCanvas; private drawFrame; @@ -92,16 +93,16 @@ export declare class TimelineFlameChartDataProvider extends Common.ObjectWrapper * timelineData() has been generated. If it hasn't, this method will return * null. */ - indexForEvent(targetEvent: TraceEngine.Types.TraceEvents.TraceEventData | TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame): number | null; + indexForEvent(targetEvent: Trace.Types.Events.Event | Trace.Handlers.ModelHandlers.Frames.TimelineFrame): number | null; /** * Build the data for initiators and initiated entries. * @param entryIndex * @returns if we should re-render the flame chart (canvas) */ buildFlowForInitiator(entryIndex: number): boolean; - eventByIndex(entryIndex: number): TraceEngine.Types.TraceEvents.TraceEventData | TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame | null; + eventByIndex(entryIndex: number): Trace.Types.Events.Event | Trace.Handlers.ModelHandlers.Frames.TimelineFrame | null; } -export declare const InstantEventVisibleDurationMs: TraceEngine.Types.Timing.MilliSeconds; +export declare const InstantEventVisibleDurationMs: Trace.Types.Timing.MilliSeconds; export declare const enum Events { DATA_CHANGED = "DataChanged" } diff --git a/public/panels/timeline/TimelineFlameChartDataProvider.js b/public/panels/timeline/TimelineFlameChartDataProvider.js index 663756f13..03e52d35f 100644 --- a/public/panels/timeline/TimelineFlameChartDataProvider.js +++ b/public/panels/timeline/TimelineFlameChartDataProvider.js @@ -31,7 +31,7 @@ import * as Common from '../../core/common/common.js'; import * as i18n from '../../core/i18n/i18n.js'; import * as Root from '../../core/root/root.js'; import * as Bindings from '../../models/bindings/bindings.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; import * as UI from '../../ui/legacy/legacy.js'; import * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js'; @@ -102,11 +102,11 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW timelineDataInternal; currentLevel; // The Performance and the Timeline models are expected to be - // deprecated in favor of using traceEngineData (new RPP engine) only + // deprecated in favor of using parsedTrace (new RPP engine) only // as part of the work in crbug.com/1386091. For this reason they // have the "legacy" prefix on their name. compatibilityTracksAppender; - traceEngineData; + parsedTrace; isCpuProfile = false; minimumBoundaryInternal; timeSpan; @@ -139,7 +139,7 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW this.timelineDataInternal = null; this.currentLevel = 0; this.compatibilityTracksAppender = null; - this.traceEngineData = null; + this.parsedTrace = null; this.minimumBoundaryInternal = 0; this.timeSpan = 0; this.headerLevel1 = this.buildGroupStyle({ shareHeaderLine: false }); @@ -225,9 +225,8 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW jslogContext: 'reset-trace', }); const entry = this.eventByIndex(entryIndex); - if (entry && entry instanceof TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame === false) { - const url = (TraceEngine.Types.TraceEvents.isProfileCall(entry)) ? - entry.callFrame.url : + if (entry && entry instanceof Trace.Handlers.ModelHandlers.Frames.TimelineFrame === false) { + const url = (Trace.Types.Events.isProfileCall(entry)) ? entry.callFrame.url : undefined; if (url) { if (Bindings.IgnoreListManager.IgnoreListManager.instance().isUserIgnoreListedURL(url)) { @@ -299,15 +298,15 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW }; return Object.assign(defaultGroupStyle, extra); } - setModel(traceEngineData, isCpuProfile = false) { + setModel(parsedTrace, isCpuProfile = false) { this.reset(); - this.traceEngineData = traceEngineData; - ExtensionDataGatherer.instance().modelChanged(traceEngineData); + this.parsedTrace = parsedTrace; + ExtensionDataGatherer.instance().modelChanged(parsedTrace); this.isCpuProfile = isCpuProfile; - if (traceEngineData) { - const { traceBounds } = traceEngineData.Meta; - const minTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceBounds.min); - const maxTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceBounds.max); + if (parsedTrace) { + const { traceBounds } = parsedTrace.Meta; + const minTime = Trace.Helpers.Timing.microSecondsToMilliseconds(traceBounds.min); + const maxTime = Trace.Helpers.Timing.microSecondsToMilliseconds(traceBounds.max); this.minimumBoundaryInternal = minTime; this.timeSpan = minTime === maxTime ? 1000 : maxTime - this.minimumBoundaryInternal; } @@ -321,11 +320,11 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW */ compatibilityTracksAppenderInstance(forceNew = false) { if (!this.compatibilityTracksAppender || forceNew) { - if (!this.traceEngineData) { + if (!this.parsedTrace) { throw new Error('Attempted to instantiate a CompatibilityTracksAppender without having set the trace parse data first.'); } this.timelineDataInternal = this.#instantiateTimelineData(); - this.compatibilityTracksAppender = new CompatibilityTracksAppender(this.timelineDataInternal, this.traceEngineData, this.entryData, this.entryTypeByLevel); + this.compatibilityTracksAppender = new CompatibilityTracksAppender(this.timelineDataInternal, this.parsedTrace, this.entryData, this.entryTypeByLevel); } return this.compatibilityTracksAppender; } @@ -361,10 +360,10 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW return this.compatibilityTracksAppender?.groupEventsForTreeView(group) ?? null; } mainFrameNavigationStartEvents() { - if (!this.traceEngineData) { + if (!this.parsedTrace) { return []; } - return this.traceEngineData.Meta.mainFrameNavigations; + return this.parsedTrace.Meta.mainFrameNavigations; } entryTitle(entryIndex) { const entryType = this.#entryTypeForIndex(entryIndex); @@ -430,9 +429,9 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW this.reset(/* resetCompatibilityTracksAppender= */ false); } this.currentLevel = 0; - if (this.traceEngineData) { + if (this.parsedTrace) { this.compatibilityTracksAppender = this.compatibilityTracksAppenderInstance(); - if (this.traceEngineData.Meta.traceIsGeneric) { + if (this.parsedTrace.Meta.traceIsGeneric) { this.#processGenericTrace(); } else { @@ -452,7 +451,7 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW const appendersByProcess = this.compatibilityTracksAppender.allThreadAppendersByProcess(); for (const [pid, threadAppenders] of appendersByProcess) { const processGroupStyle = this.buildGroupStyle({ shareHeaderLine: false }); - const processName = this.traceEngineData?.Meta.processNames.get(pid)?.args.name || 'Process'; + const processName = this.parsedTrace?.Meta.processNames.get(pid)?.args.name || 'Process'; this.appendHeader(`${processName} (${pid})`, processGroupStyle, true, false); for (const appender of threadAppenders) { appender.setHeaderNestingLevel(1); @@ -492,7 +491,7 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW const allTrackAppenders = this.compatibilityTracksAppender ? this.compatibilityTracksAppender.allVisibleTrackAppenders() : []; allTrackAppenders.sort((a, b) => weight(a) - weight(b)); for (const appender of allTrackAppenders) { - if (!this.traceEngineData) { + if (!this.parsedTrace) { continue; } this.currentLevel = appender.appendTrackAtLevel(this.currentLevel); @@ -502,8 +501,8 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW // If it is, we mark the group as selected. if (this.timelineDataInternal && !this.timelineDataInternal.selectedGroup) { if (appender instanceof ThreadAppender && - (appender.threadType === "MAIN_THREAD" /* TraceEngine.Handlers.Threads.ThreadType.MAIN_THREAD */ || - appender.threadType === "CPU_PROFILE" /* TraceEngine.Handlers.Threads.ThreadType.CPU_PROFILE */)) { + (appender.threadType === "MAIN_THREAD" /* Trace.Handlers.Threads.ThreadType.MAIN_THREAD */ || + appender.threadType === "CPU_PROFILE" /* Trace.Handlers.Threads.ThreadType.CPU_PROFILE */)) { const group = this.compatibilityTracksAppender?.groupForAppender(appender); if (group) { this.timelineDataInternal.selectedGroup = group; @@ -522,7 +521,7 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW return this.timeSpan; } static timelineEntryIsTraceEvent(entry) { - return entry instanceof TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame === false; + return entry instanceof Trace.Handlers.ModelHandlers.Frames.TimelineFrame === false; } search(visibleWindow, filter) { const results = []; @@ -536,22 +535,22 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW // We only search for events, not for frames, hence this early exit. continue; } - if (TraceEngine.Types.TraceEvents.isTraceEventScreenshot(entry)) { + if (Trace.Types.Events.isScreenshot(entry)) { // Screenshots are represented as trace events, but you can't search for them, so skip. continue; } - if (!TraceEngine.Helpers.Timing.eventIsInBounds(entry, visibleWindow)) { + if (!Trace.Helpers.Timing.eventIsInBounds(entry, visibleWindow)) { continue; } - if (filter.accept(entry, this.traceEngineData || undefined)) { - const startTimeMilli = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(entry.ts); + if (filter.accept(entry, this.parsedTrace || undefined)) { + const startTimeMilli = Trace.Helpers.Timing.microSecondsToMilliseconds(entry.ts); results.push({ index: i, startTimeMilli, provider: 'main' }); } } return results; } isIgnoreListedEvent(event) { - if (TraceEngine.Types.TraceEvents.isProfileCall(event)) { + if (Trace.Types.Events.isProfileCall(event)) { return this.isIgnoreListedURL(event.callFrame.url); } return false; @@ -570,16 +569,16 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW * because then when it comes to drawing we can decorate them differently. **/ #appendFramesAndScreenshotsTrack() { - if (!this.traceEngineData) { + if (!this.parsedTrace) { return; } - const filmStrip = TraceEngine.Extras.FilmStrip.fromTraceData(this.traceEngineData); + const filmStrip = Trace.Extras.FilmStrip.fromParsedTrace(this.parsedTrace); const hasScreenshots = filmStrip.frames.length > 0; this.framesHeader.collapsible = hasScreenshots; const expanded = Root.Runtime.Runtime.queryParam('flamechart-force-expand') === 'frames'; this.appendHeader(i18nString(UIStrings.frames), this.framesHeader, false /* selectable */, expanded); this.entryTypeByLevel[this.currentLevel] = "Frame" /* EntryType.FRAME */; - for (const frame of this.traceEngineData.Frames.frames) { + for (const frame of this.parsedTrace.Frames.frames) { this.#appendNewEngineFrame(frame); } ++this.currentLevel; @@ -589,14 +588,14 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW this.#appendScreenshots(filmStrip); } #appendScreenshots(filmStrip) { - if (!this.timelineDataInternal || !this.traceEngineData) { + if (!this.timelineDataInternal || !this.parsedTrace) { return; } this.appendHeader('', this.screenshotsHeader, false /* selectable */); this.entryTypeByLevel[this.currentLevel] = "Screenshot" /* EntryType.SCREENSHOT */; let prevTimestamp = undefined; for (const filmStripFrame of filmStrip.frames) { - const screenshotTimeInMilliSeconds = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(filmStripFrame.screenshotEvent.ts); + const screenshotTimeInMilliSeconds = Trace.Helpers.Timing.microSecondsToMilliseconds(filmStripFrame.screenshotEvent.ts); this.entryData.push(filmStripFrame.screenshotEvent); this.timelineDataInternal.entryLevels.push(this.currentLevel); this.timelineDataInternal.entryStartTimes.push(screenshotTimeInMilliSeconds); @@ -606,7 +605,7 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW prevTimestamp = screenshotTimeInMilliSeconds; } if (filmStrip.frames.length && prevTimestamp !== undefined) { - const maxRecordTimeMillis = TraceEngine.Helpers.Timing.traceWindowMilliSeconds(this.traceEngineData.Meta.traceBounds).max; + const maxRecordTimeMillis = Trace.Helpers.Timing.traceWindowMilliSeconds(this.parsedTrace.Meta.traceBounds).max; // Set the total time of the final screenshot so it takes up the remainder of the trace. this.timelineDataInternal.entryTotalTimes.push(maxRecordTimeMillis - prevTimestamp); } @@ -634,7 +633,7 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW title = highlightedEntryInfo.title; time = highlightedEntryInfo.formattedTime; warningElements = highlightedEntryInfo.warningElements || warningElements; - if (TraceEngine.Types.TraceEvents.isSyntheticInteractionEvent(event)) { + if (Trace.Types.Events.isSyntheticInteraction(event)) { const breakdown = new Components.InteractionBreakdown.InteractionBreakdown(); breakdown.entry = event; additionalContent.push(breakdown); @@ -642,7 +641,8 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW } else if (entryType === "Frame" /* EntryType.FRAME */) { const frame = this.entryData[entryIndex]; - time = i18n.TimeUtilities.preciseMillisToString(TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.duration), 1); + time = + i18n.TimeUtilities.preciseMillisToString(Trace.Helpers.Timing.microSecondsToMilliseconds(frame.duration), 1); if (frame.idle) { title = i18nString(UIStrings.idleFrame); } @@ -696,6 +696,16 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW contents.createChild('span', 'timeline-info-title').textContent = hiddenEntriesAmount + ' hidden'; return element; } + getDrawOverride(entryIndex) { + const entryType = this.#entryTypeForIndex(entryIndex); + if (entryType !== "TrackAppender" /* EntryType.TRACK_APPENDER */) { + return; + } + const timelineData = this.timelineDataInternal; + const eventLevel = timelineData.entryLevels[entryIndex]; + const event = this.entryData[entryIndex]; + return this.compatibilityTracksAppender?.getDrawOverride(event, eventLevel); + } entryColor(entryIndex) { const entryType = this.#entryTypeForIndex(entryIndex); if (entryType === "Frame" /* EntryType.FRAME */) { @@ -770,7 +780,7 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW context.fillStyle = '#d7f0d1'; } context.fillRect(barX, barY, barWidth, barHeight); - const frameDurationText = i18n.TimeUtilities.preciseMillisToString(TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.duration), 1); + const frameDurationText = i18n.TimeUtilities.preciseMillisToString(Trace.Helpers.Timing.microSecondsToMilliseconds(frame.duration), 1); const textWidth = context.measureText(frameDurationText).width; if (textWidth <= barWidth) { context.fillStyle = this.textColor(entryIndex); @@ -817,7 +827,7 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW } if (entryType === "TrackAppender" /* EntryType.TRACK_APPENDER */) { const entry = this.entryData[entryIndex]; - if (TraceEngine.Types.TraceEvents.isSyntheticInteractionEvent(entry)) { + if (Trace.Types.Events.isSyntheticInteraction(entry)) { this.#drawInteractionEventWithWhiskers(context, entryIndex, text, entry, barX, barY, unclippedBarX, barWidth, barHeight, timeToPixelRatio); return true; } @@ -852,10 +862,10 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW * replace it with the whiskers. * TODO(crbug.com/1495248): rework how we draw whiskers to avoid this inefficiency */ - const beginTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(entry.ts); + const beginTime = Trace.Helpers.Timing.microSecondsToMilliseconds(entry.ts); const entireBarEndXPixel = barX + barWidth; function timeToPixel(time) { - const timeMilli = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(time); + const timeMilli = Trace.Helpers.Timing.microSecondsToMilliseconds(time); return Math.floor(unclippedBarXStartPixel + (timeMilli - beginTime) * timeToPixelRatio); } context.save(); @@ -880,7 +890,7 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW // The left whisker starts at the enty timestamp, and continues until the start of the box (processingStart). const leftWhiskerX = timeToPixel(entry.ts); // The right whisker ends at (entry.ts + entry.dur). We draw the line from the end of the box (processingEnd). - const rightWhiskerX = timeToPixel(TraceEngine.Types.Timing.MicroSeconds(entry.ts + entry.dur)); + const rightWhiskerX = timeToPixel(Trace.Types.Timing.MicroSeconds(entry.ts + entry.dur)); context.beginPath(); context.lineWidth = 1; context.strokeStyle = '#ccc'; @@ -919,13 +929,13 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW return true; } const event = this.entryData[entryIndex]; - if (TraceEngine.Types.TraceEvents.isSyntheticInteractionEvent(event)) { + if (Trace.Types.Events.isSyntheticInteraction(event)) { // We draw interactions with whiskers, which are done via the // decorateEntry() method, hence we always want to force these to be // decorated. return true; } - return Boolean(this.traceEngineData?.Warnings.perEvent.get(event)); + return Boolean(this.parsedTrace?.Warnings.perEvent.get(event)); } appendHeader(title, style, selectable, expanded) { const group = { startLevel: this.currentLevel, name: title, style, selectable, expanded }; @@ -935,15 +945,14 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW #appendNewEngineFrame(frame) { const index = this.entryData.length; this.entryData.push(frame); - const durationMilliseconds = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.duration); + const durationMilliseconds = Trace.Helpers.Timing.microSecondsToMilliseconds(frame.duration); this.entryIndexToTitle[index] = i18n.TimeUtilities.millisToString(durationMilliseconds, true); if (!this.timelineDataInternal) { return; } this.timelineDataInternal.entryLevels[index] = this.currentLevel; this.timelineDataInternal.entryTotalTimes[index] = durationMilliseconds; - this.timelineDataInternal.entryStartTimes[index] = - TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.startTime); + this.timelineDataInternal.entryStartTimes[index] = Trace.Helpers.Timing.microSecondsToMilliseconds(frame.startTime); } createSelection(entryIndex) { const entryType = this.#entryTypeForIndex(entryIndex); @@ -991,7 +1000,7 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW // If the index is -1 and the selection is a TraceEvent, it might be // the case that this Entry is hidden by the Context Menu action. // Try revealing the entry and getting the index again. - if (this.entryData.indexOf(selection.object) === -1 && TimelineSelection.isTraceEventSelection(selection.object)) { + if (this.entryData.indexOf(selection.object) === -1 && TimelineSelection.isSelection(selection.object)) { if (this.timelineDataInternal?.selectedGroup) { ModificationsManager.activeManager()?.getEntriesFilter().revealEntry(selection.object); this.timelineData(true); @@ -1030,7 +1039,7 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW * @returns if we should re-render the flame chart (canvas) */ buildFlowForInitiator(entryIndex) { - if (!this.traceEngineData) { + if (!this.parsedTrace) { return false; } if (!this.timelineDataInternal) { @@ -1070,7 +1079,7 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW this.lastInitiatorEntry = entryIndex; const hiddenEvents = ModificationsManager.activeManager()?.getEntriesFilter().invisibleEntries() ?? []; const expandableEntries = ModificationsManager.activeManager()?.getEntriesFilter().expandableEntries() ?? []; - const initiatorsData = initiatorsDataToDraw(this.traceEngineData, event, hiddenEvents, expandableEntries); + const initiatorsData = initiatorsDataToDraw(this.parsedTrace, event, hiddenEvents, expandableEntries); // This means there is no change for arrows. if (previousInitiatorsDataLength === 0 && initiatorsData.length === 0) { return false; @@ -1105,5 +1114,5 @@ export class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectW return null; } } -export const InstantEventVisibleDurationMs = TraceEngine.Types.Timing.MilliSeconds(0.001); +export const InstantEventVisibleDurationMs = Trace.Types.Timing.MilliSeconds(0.001); //# sourceMappingURL=TimelineFlameChartDataProvider.js.map \ No newline at end of file diff --git a/public/panels/timeline/TimelineFlameChartDataProvider.js.map b/public/panels/timeline/TimelineFlameChartDataProvider.js.map index a53ceff8d..853552583 100644 --- a/public/panels/timeline/TimelineFlameChartDataProvider.js.map +++ b/public/panels/timeline/TimelineFlameChartDataProvider.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineFlameChartDataProvider.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineFlameChartDataProvider.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (C) 2014 Google Inc. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * * Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above\n * copyright notice, this list of conditions and the following disclaimer\n * in the documentation and/or other materials provided with the\n * distribution.\n * * Neither the name of Google Inc. nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport type * as Platform from '../../core/platform/platform.js';\nimport * as Root from '../../core/root/root.js';\nimport * as Bindings from '../../models/bindings/bindings.js';\nimport type * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\n\nimport {CompatibilityTracksAppender, type TrackAppenderName} from './CompatibilityTracksAppender.js';\nimport * as Components from './components/components.js';\nimport {ExtensionDataGatherer} from './ExtensionDataGatherer.js';\nimport {initiatorsDataToDraw} from './Initiators.js';\nimport {ModificationsManager} from './ModificationsManager.js';\nimport {ThreadAppender} from './ThreadAppender.js';\nimport timelineFlamechartPopoverStyles from './timelineFlamechartPopover.css.js';\nimport {FlameChartStyle, Selection} from './TimelineFlameChartView.js';\nimport {TimelineSelection} from './TimelineSelection.js';\n\nconst UIStrings = {\n /**\n *@description Text for rendering frames\n */\n frames: 'Frames',\n /**\n *@description Text in Timeline Flame Chart Data Provider of the Performance panel\n */\n idleFrame: 'Idle frame',\n /**\n *@description Text in Timeline Frame Chart Data Provider of the Performance panel\n */\n droppedFrame: 'Dropped frame',\n /**\n *@description Text in Timeline Frame Chart Data Provider of the Performance panel\n */\n partiallyPresentedFrame: 'Partially-presented frame',\n /**\n *@description Text for a rendering frame\n */\n frame: 'Frame',\n /**\n *@description Text for Hiding a function from the Flame Chart\n */\n hideFunction: 'Hide function',\n /**\n *@description Text for Hiding all children of a function from the Flame Chart\n */\n hideChildren: 'Hide children',\n /**\n *@description Text for Hiding all child entries that are identical to the selected entry from the Flame Chart\n */\n hideRepeatingChildren: 'Hide repeating children',\n /**\n *@description Text for remove script from ignore list from the Flame Chart\n */\n removeScriptFromIgnoreList: 'Remove script from ignore list',\n /**\n *@description Text for add script to ignore list from the Flame Chart\n */\n addScriptToIgnoreList: 'Add script to ignore list',\n /**\n *@description Text for an action that shows all of the hidden children of an entry\n */\n resetChildren: 'Reset children',\n /**\n *@description Text for an action that shows all of the hidden entries of the Flame Chart\n */\n resetTrace: 'Reset trace',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelineFlameChartDataProvider.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\n// Frames are special cased because we don't render them as a normal track, hence the distinction here.\nexport type TimelineFlameChartEntry =\n TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame|TraceEngine.Types.TraceEvents.TraceEventData;\n\nexport class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectWrapper implements\n PerfUI.FlameChart.FlameChartDataProvider {\n private droppedFramePatternCanvas: HTMLCanvasElement;\n private partialFramePatternCanvas: HTMLCanvasElement;\n private timelineDataInternal: PerfUI.FlameChart.FlameChartTimelineData|null;\n private currentLevel: number;\n\n // The Performance and the Timeline models are expected to be\n // deprecated in favor of using traceEngineData (new RPP engine) only\n // as part of the work in crbug.com/1386091. For this reason they\n // have the \"legacy\" prefix on their name.\n private compatibilityTracksAppender: CompatibilityTracksAppender|null;\n private traceEngineData: TraceEngine.Handlers.Types.TraceParseData|null;\n private isCpuProfile = false;\n\n private minimumBoundaryInternal: number;\n private timeSpan: number;\n private readonly headerLevel1: PerfUI.FlameChart.GroupStyle;\n private readonly headerLevel2: PerfUI.FlameChart.GroupStyle;\n private readonly staticHeader: PerfUI.FlameChart.GroupStyle;\n private framesHeader: PerfUI.FlameChart.GroupStyle;\n private readonly screenshotsHeader: PerfUI.FlameChart.GroupStyle;\n\n // Contains all the entries that are DRAWN onto the track. Entries that have\n // been hidden - either by a user action, or because they aren't visible at\n // all - will not appear in this array and it will change per-render. For\n // example, if a user collapses an icicle in the flamechart, those entries\n // that are now hidden will no longer be in this array.\n private entryData: TimelineFlameChartEntry[] = [];\n\n private entryTypeByLevel!: EntryType[];\n private screenshotImageCache!: Map;\n private entryIndexToTitle!: string[];\n private lastInitiatorEntry!: number;\n private lastInitiatorsData: PerfUI.FlameChart.FlameChartInitiatorData[] = [];\n private lastSelection?: Selection;\n #font: string;\n #eventIndexByEvent: WeakMap<\n TraceEngine.Types.TraceEvents.TraceEventData|TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame,\n number|null> = new WeakMap();\n\n constructor() {\n super();\n this.reset();\n this.#font = `${PerfUI.Font.DEFAULT_FONT_SIZE} ${PerfUI.Font.getFontFamilyForCanvas()}`;\n this.droppedFramePatternCanvas = document.createElement('canvas');\n this.partialFramePatternCanvas = document.createElement('canvas');\n this.preparePatternCanvas();\n this.timelineDataInternal = null;\n this.currentLevel = 0;\n this.compatibilityTracksAppender = null;\n this.traceEngineData = null;\n this.minimumBoundaryInternal = 0;\n this.timeSpan = 0;\n\n this.headerLevel1 = this.buildGroupStyle({shareHeaderLine: false});\n this.headerLevel2 = this.buildGroupStyle({padding: 2, nestingLevel: 1, collapsible: false});\n this.staticHeader = this.buildGroupStyle({collapsible: false});\n this.framesHeader = this.buildGroupStyle({useFirstLineForOverview: true});\n this.screenshotsHeader =\n this.buildGroupStyle({useFirstLineForOverview: true, nestingLevel: 1, collapsible: false, itemsHeight: 150});\n\n ThemeSupport.ThemeSupport.instance().addEventListener(ThemeSupport.ThemeChangeEvent.eventName, () => {\n const headers = [\n this.headerLevel1,\n this.headerLevel2,\n this.staticHeader,\n this.framesHeader,\n this.screenshotsHeader,\n ];\n for (const header of headers) {\n header.color = ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-on-surface');\n header.backgroundColor =\n ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-cdt-base-container');\n }\n });\n }\n\n hasTrackConfigurationMode(): boolean {\n return true;\n }\n\n getPossibleActions(entryIndex: number, groupIndex: number): PerfUI.FlameChart.PossibleFilterActions|void {\n const data = this.timelineData();\n if (!data) {\n return;\n }\n const group = data.groups.at(groupIndex);\n // Early exit here if there is no group or:\n // 1. The group is not expanded: it needs to be expanded to allow the\n // context menu actions to occur.\n // 2. The group does not have the showStackContextMenu flag which indicates\n // that it does not show entries that support the stack actions.\n if (!group || !group.expanded || !group.showStackContextMenu) {\n return;\n }\n\n // Check which actions are possible on an entry.\n // If an action would not change the entries (for example it has no children to collapse), we do not need to show it.\n return this.findPossibleContextMenuActions(entryIndex);\n }\n\n customizedContextMenu(event: MouseEvent, entryIndex: number, groupIndex: number): UI.ContextMenu.ContextMenu\n |undefined {\n const possibleActions = this.getPossibleActions(entryIndex, groupIndex);\n if (!possibleActions) {\n return;\n }\n\n const contextMenu = new UI.ContextMenu.ContextMenu(event, {useSoftMenu: true});\n\n const hideEntryOption = contextMenu.defaultSection().appendItem(i18nString(UIStrings.hideFunction), () => {\n this.modifyTree(PerfUI.FlameChart.FilterAction.MERGE_FUNCTION, entryIndex);\n }, {\n disabled: !possibleActions?.[PerfUI.FlameChart.FilterAction.MERGE_FUNCTION],\n jslogContext: 'hide-function',\n });\n hideEntryOption.setShortcut('H');\n\n const hideChildrenOption = contextMenu.defaultSection().appendItem(i18nString(UIStrings.hideChildren), () => {\n this.modifyTree(PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION, entryIndex);\n }, {\n disabled: !possibleActions?.[PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION],\n jslogContext: 'hide-children',\n });\n hideChildrenOption.setShortcut('C');\n\n const hideRepeatingChildrenOption =\n contextMenu.defaultSection().appendItem(i18nString(UIStrings.hideRepeatingChildren), () => {\n this.modifyTree(PerfUI.FlameChart.FilterAction.COLLAPSE_REPEATING_DESCENDANTS, entryIndex);\n }, {\n disabled: !possibleActions?.[PerfUI.FlameChart.FilterAction.COLLAPSE_REPEATING_DESCENDANTS],\n jslogContext: 'hide-repeating-children',\n });\n hideRepeatingChildrenOption.setShortcut('R');\n\n const resetChildrenOption = contextMenu.defaultSection().appendItem(i18nString(UIStrings.resetChildren), () => {\n this.modifyTree(PerfUI.FlameChart.FilterAction.RESET_CHILDREN, entryIndex);\n }, {\n disabled: !possibleActions?.[PerfUI.FlameChart.FilterAction.RESET_CHILDREN],\n jslogContext: 'reset-children',\n });\n resetChildrenOption.setShortcut('U');\n\n contextMenu.defaultSection().appendItem(i18nString(UIStrings.resetTrace), () => {\n this.modifyTree(PerfUI.FlameChart.FilterAction.UNDO_ALL_ACTIONS, entryIndex);\n }, {\n disabled: !possibleActions?.[PerfUI.FlameChart.FilterAction.UNDO_ALL_ACTIONS],\n jslogContext: 'reset-trace',\n });\n\n const entry = this.eventByIndex(entryIndex);\n if (entry && entry instanceof TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame === false) {\n const url = (TraceEngine.Types.TraceEvents.isProfileCall(entry)) ?\n entry.callFrame.url as Platform.DevToolsPath.UrlString :\n undefined;\n if (url) {\n if (Bindings.IgnoreListManager.IgnoreListManager.instance().isUserIgnoreListedURL(url)) {\n contextMenu.defaultSection().appendItem(i18nString(UIStrings.removeScriptFromIgnoreList), () => {\n Bindings.IgnoreListManager.IgnoreListManager.instance().unIgnoreListURL(url);\n this.dispatchEventToListeners(Events.DATA_CHANGED);\n }, {\n jslogContext: 'remove-from-ignore-list',\n });\n } else {\n contextMenu.defaultSection().appendItem(i18nString(UIStrings.addScriptToIgnoreList), () => {\n Bindings.IgnoreListManager.IgnoreListManager.instance().ignoreListURL(url);\n this.dispatchEventToListeners(Events.DATA_CHANGED);\n }, {\n jslogContext: 'add-to-ignore-list',\n });\n }\n }\n }\n\n return contextMenu;\n }\n\n modifyTree(action: PerfUI.FlameChart.FilterAction, entryIndex: number): void {\n const entry = this.entryData[entryIndex] as TraceEngine.Types.TraceEvents.TraceEventData;\n\n ModificationsManager.activeManager()?.getEntriesFilter().applyFilterAction({type: action, entry});\n this.timelineData(true);\n this.buildFlowForInitiator(entryIndex);\n this.dispatchEventToListeners(Events.DATA_CHANGED);\n }\n\n findPossibleContextMenuActions(entryIndex: number): PerfUI.FlameChart.PossibleFilterActions|void {\n const entry = this.entryData[entryIndex] as TraceEngine.Types.TraceEvents.TraceEventData;\n return ModificationsManager.activeManager()?.getEntriesFilter().findPossibleActions(entry);\n }\n\n handleFlameChartTransformKeyboardEvent(event: KeyboardEvent, entryIndex: number, groupIndex: number): void {\n const possibleActions = this.getPossibleActions(entryIndex, groupIndex);\n if (!possibleActions) {\n return;\n }\n\n let handled = false;\n\n if (event.code === 'KeyH' && possibleActions[PerfUI.FlameChart.FilterAction.MERGE_FUNCTION]) {\n this.modifyTree(PerfUI.FlameChart.FilterAction.MERGE_FUNCTION, entryIndex);\n handled = true;\n } else if (event.code === 'KeyC' && possibleActions[PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION]) {\n this.modifyTree(PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION, entryIndex);\n handled = true;\n } else if (\n event.code === 'KeyR' && possibleActions[PerfUI.FlameChart.FilterAction.COLLAPSE_REPEATING_DESCENDANTS]) {\n this.modifyTree(PerfUI.FlameChart.FilterAction.COLLAPSE_REPEATING_DESCENDANTS, entryIndex);\n handled = true;\n } else if (event.code === 'KeyU') {\n this.modifyTree(PerfUI.FlameChart.FilterAction.RESET_CHILDREN, entryIndex);\n handled = true;\n }\n\n if (handled) {\n event.consume(true);\n }\n }\n\n private buildGroupStyle(extra: Object): PerfUI.FlameChart.GroupStyle {\n const defaultGroupStyle = {\n padding: 4,\n height: 17,\n collapsible: true,\n color: ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-on-surface'),\n backgroundColor: ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-cdt-base-container'),\n nestingLevel: 0,\n shareHeaderLine: true,\n };\n return Object.assign(defaultGroupStyle, extra);\n }\n\n setModel(traceEngineData: TraceEngine.Handlers.Types.TraceParseData|null, isCpuProfile = false): void {\n this.reset();\n this.traceEngineData = traceEngineData;\n ExtensionDataGatherer.instance().modelChanged(traceEngineData);\n\n this.isCpuProfile = isCpuProfile;\n if (traceEngineData) {\n const {traceBounds} = traceEngineData.Meta;\n const minTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceBounds.min);\n const maxTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceBounds.max);\n this.minimumBoundaryInternal = minTime;\n this.timeSpan = minTime === maxTime ? 1000 : maxTime - this.minimumBoundaryInternal;\n }\n }\n\n /**\n * Instances and caches a CompatibilityTracksAppender using the\n * internal flame chart data and the trace parsed data coming from the\n * trace engine.\n * The model data must have been set to the data provider instance before\n * attempting to instance the CompatibilityTracksAppender.\n */\n compatibilityTracksAppenderInstance(forceNew = false): CompatibilityTracksAppender {\n if (!this.compatibilityTracksAppender || forceNew) {\n if (!this.traceEngineData) {\n throw new Error(\n 'Attempted to instantiate a CompatibilityTracksAppender without having set the trace parse data first.');\n }\n this.timelineDataInternal = this.#instantiateTimelineData();\n this.compatibilityTracksAppender = new CompatibilityTracksAppender(\n this.timelineDataInternal, this.traceEngineData, this.entryData, this.entryTypeByLevel);\n }\n return this.compatibilityTracksAppender;\n }\n\n /**\n * Returns the instance of the timeline flame chart data, without\n * adding data to it. In case the timeline data hasn't been instanced\n * creates a new instance and returns it.\n */\n #instantiateTimelineData(): PerfUI.FlameChart.FlameChartTimelineData {\n if (!this.timelineDataInternal) {\n this.timelineDataInternal = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n }\n return this.timelineDataInternal;\n }\n\n /**\n * Builds the flame chart data using the track appenders\n */\n buildFromTrackAppenders(options?: {filterThreadsByName?: string, expandedTracks?: Set}): void {\n if (!this.compatibilityTracksAppender) {\n return;\n }\n const appenders = this.compatibilityTracksAppender.allVisibleTrackAppenders();\n for (const appender of appenders) {\n const skipThreadAppenderByName =\n appender instanceof ThreadAppender && !appender.trackName().includes(options?.filterThreadsByName || '');\n if (skipThreadAppenderByName) {\n continue;\n }\n const expanded = Boolean(options?.expandedTracks?.has(appender.appenderName));\n this.currentLevel = appender.appendTrackAtLevel(this.currentLevel, expanded);\n }\n }\n\n groupTreeEvents(group: PerfUI.FlameChart.Group): TraceEngine.Types.TraceEvents.TraceEventData[]|null {\n return this.compatibilityTracksAppender?.groupEventsForTreeView(group) ?? null;\n }\n\n mainFrameNavigationStartEvents(): readonly TraceEngine.Types.TraceEvents.TraceEventNavigationStart[] {\n if (!this.traceEngineData) {\n return [];\n }\n return this.traceEngineData.Meta.mainFrameNavigations;\n }\n\n entryTitle(entryIndex: number): string|null {\n const entryType = this.#entryTypeForIndex(entryIndex);\n if (entryType === EntryType.SCREENSHOT) {\n return '';\n }\n if (entryType === EntryType.TRACK_APPENDER) {\n const timelineData = (this.timelineDataInternal as PerfUI.FlameChart.FlameChartTimelineData);\n const eventLevel = timelineData.entryLevels[entryIndex];\n const event = (this.entryData[entryIndex] as TraceEngine.Types.TraceEvents.TraceEventData);\n return this.compatibilityTracksAppender?.titleForEvent(event, eventLevel) || null;\n }\n let title: Common.UIString.LocalizedString|string = this.entryIndexToTitle[entryIndex];\n if (!title) {\n title = `Unexpected entryIndex ${entryIndex}`;\n console.error(title);\n }\n return title;\n }\n\n textColor(index: number): string {\n const event = this.entryData[index];\n if (!TimelineFlameChartDataProvider.timelineEntryIsTraceEvent(event)) {\n return FlameChartStyle.textColor;\n }\n return this.isIgnoreListedEvent(event) ? '#888' : FlameChartStyle.textColor;\n }\n\n entryFont(_index: number): string|null {\n return this.#font;\n }\n\n // resetCompatibilityTracksAppender boolean set to false does not recreate the thread appenders\n reset(resetCompatibilityTracksAppender: boolean = true): void {\n this.currentLevel = 0;\n this.entryData = [];\n this.entryTypeByLevel = [];\n this.entryIndexToTitle = [];\n this.screenshotImageCache = new Map();\n this.#eventIndexByEvent = new Map();\n if (resetCompatibilityTracksAppender) {\n this.compatibilityTracksAppender = null;\n this.timelineDataInternal = null;\n } else if (!resetCompatibilityTracksAppender && this.timelineDataInternal) {\n this.compatibilityTracksAppender?.setFlameChartDataAndEntryData(\n this.timelineDataInternal, this.entryData, this.entryTypeByLevel);\n this.compatibilityTracksAppender?.threadAppenders().forEach(\n threadAppender => threadAppender.setHeaderAppended(false));\n }\n }\n\n maxStackDepth(): number {\n return this.currentLevel;\n }\n\n /**\n * Builds the flame chart data using the tracks appender (which use\n * the new trace engine) and the legacy code paths present in this\n * file. The result built data is cached and returned.\n */\n timelineData(rebuild: boolean = false): PerfUI.FlameChart.FlameChartTimelineData {\n if (this.timelineDataInternal && this.timelineDataInternal.entryLevels.length !== 0 && !rebuild) {\n // The flame chart data is built already, so return the cached\n // data.\n return this.timelineDataInternal;\n }\n\n this.timelineDataInternal = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n\n if (rebuild) {\n this.reset(/* resetCompatibilityTracksAppender= */ false);\n }\n\n this.currentLevel = 0;\n\n if (this.traceEngineData) {\n this.compatibilityTracksAppender = this.compatibilityTracksAppenderInstance();\n if (this.traceEngineData.Meta.traceIsGeneric) {\n this.#processGenericTrace();\n } else {\n this.#processInspectorTrace();\n }\n }\n return this.timelineDataInternal;\n }\n\n /**\n * Register the groups (aka tracks) with the VisualElements framework so\n * later on we can log when an entry inside this group is selected.\n */\n #processGenericTrace(): void {\n if (!this.compatibilityTracksAppender) {\n return;\n }\n\n const appendersByProcess = this.compatibilityTracksAppender.allThreadAppendersByProcess();\n\n for (const [pid, threadAppenders] of appendersByProcess) {\n const processGroupStyle = this.buildGroupStyle({shareHeaderLine: false});\n const processName = this.traceEngineData?.Meta.processNames.get(pid)?.args.name || 'Process';\n this.appendHeader(`${processName} (${pid})`, processGroupStyle, true, false);\n for (const appender of threadAppenders) {\n appender.setHeaderNestingLevel(1);\n this.currentLevel = appender.appendTrackAtLevel(this.currentLevel);\n }\n }\n }\n\n #processInspectorTrace(): void {\n if (!this.isCpuProfile) {\n // CPU Profiles do not have frames and screenshots.\n this.#appendFramesAndScreenshotsTrack();\n }\n\n const weight = (track: {type?: string, forMainFrame?: boolean, appenderName?: TrackAppenderName}): number => {\n switch (track.appenderName) {\n case 'Animations':\n return 0;\n case 'Timings':\n return 1;\n case 'Interactions':\n return 2;\n case 'LayoutShifts':\n return 3;\n case 'Extension':\n return 4;\n case 'Thread':\n return 5;\n case 'ServerTimings':\n return 6;\n case 'GPU':\n return 7;\n case 'Thread_AuctionWorklet':\n return 8;\n default:\n return 9;\n }\n };\n\n const allTrackAppenders =\n this.compatibilityTracksAppender ? this.compatibilityTracksAppender.allVisibleTrackAppenders() : [];\n\n allTrackAppenders.sort((a, b) => weight(a) - weight(b));\n\n for (const appender of allTrackAppenders) {\n if (!this.traceEngineData) {\n continue;\n }\n\n this.currentLevel = appender.appendTrackAtLevel(this.currentLevel);\n\n // If there is not a selected group, we want to default to selecting the\n // main thread track. Therefore in this check we look to see if the\n // current appender is a ThreadAppender and represnets the Main Thread.\n // If it is, we mark the group as selected.\n if (this.timelineDataInternal && !this.timelineDataInternal.selectedGroup) {\n if (appender instanceof ThreadAppender &&\n (appender.threadType === TraceEngine.Handlers.Threads.ThreadType.MAIN_THREAD ||\n appender.threadType === TraceEngine.Handlers.Threads.ThreadType.CPU_PROFILE)) {\n const group = this.compatibilityTracksAppender?.groupForAppender(appender);\n if (group) {\n this.timelineDataInternal.selectedGroup = group;\n }\n }\n }\n }\n if (this.timelineDataInternal && this.timelineDataInternal.selectedGroup) {\n this.timelineDataInternal.selectedGroup.expanded = true;\n }\n }\n\n minimumBoundary(): number {\n return this.minimumBoundaryInternal;\n }\n\n totalTime(): number {\n return this.timeSpan;\n }\n\n static timelineEntryIsTraceEvent(entry: TimelineFlameChartEntry):\n entry is TraceEngine.Types.TraceEvents.TraceEventData {\n return entry instanceof TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame === false;\n }\n\n search(\n visibleWindow: TraceEngine.Types.Timing.TraceWindowMicroSeconds,\n filter: TimelineModel.TimelineModelFilter.TimelineModelFilter): PerfUI.FlameChart.DataProviderSearchResult[] {\n const results: PerfUI.FlameChart.DataProviderSearchResult[] = [];\n this.timelineData();\n for (let i = 0; i < this.entryData.length; ++i) {\n const entry = this.entryData[i];\n if (!entry) {\n continue;\n }\n\n if (!TimelineFlameChartDataProvider.timelineEntryIsTraceEvent(entry)) {\n // We only search for events, not for frames, hence this early exit.\n continue;\n }\n\n if (TraceEngine.Types.TraceEvents.isTraceEventScreenshot(entry)) {\n // Screenshots are represented as trace events, but you can't search for them, so skip.\n continue;\n }\n if (!TraceEngine.Helpers.Timing.eventIsInBounds(entry, visibleWindow)) {\n continue;\n }\n if (filter.accept(entry, this.traceEngineData || undefined)) {\n const startTimeMilli = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(entry.ts);\n results.push({index: i, startTimeMilli, provider: 'main'});\n }\n }\n return results;\n }\n\n isIgnoreListedEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): boolean {\n if (TraceEngine.Types.TraceEvents.isProfileCall(event)) {\n return this.isIgnoreListedURL(event.callFrame.url as Platform.DevToolsPath.UrlString);\n }\n return false;\n }\n\n private isIgnoreListedURL(url: Platform.DevToolsPath.UrlString): boolean {\n return Bindings.IgnoreListManager.IgnoreListManager.instance().isUserIgnoreListedURL(url);\n }\n\n getEntryTypeForLevel(level: number): EntryType {\n return this.entryTypeByLevel[level];\n }\n\n /**\n * The frames and screenshots track is special cased because it is rendered\n * differently to the rest of the tracks and not as a series of events. This\n * is why it is not done via the appender system; we track frames &\n * screenshots as a different EntryType to the TrackAppender entries,\n * because then when it comes to drawing we can decorate them differently.\n **/\n #appendFramesAndScreenshotsTrack(): void {\n if (!this.traceEngineData) {\n return;\n }\n const filmStrip = TraceEngine.Extras.FilmStrip.fromTraceData(this.traceEngineData);\n const hasScreenshots = filmStrip.frames.length > 0;\n\n this.framesHeader.collapsible = hasScreenshots;\n const expanded = Root.Runtime.Runtime.queryParam('flamechart-force-expand') === 'frames';\n\n this.appendHeader(i18nString(UIStrings.frames), this.framesHeader, false /* selectable */, expanded);\n\n this.entryTypeByLevel[this.currentLevel] = EntryType.FRAME;\n for (const frame of this.traceEngineData.Frames.frames) {\n this.#appendNewEngineFrame(frame);\n }\n ++this.currentLevel;\n\n if (!hasScreenshots) {\n return;\n }\n this.#appendScreenshots(filmStrip);\n }\n\n #appendScreenshots(filmStrip: TraceEngine.Extras.FilmStrip.Data): void {\n if (!this.timelineDataInternal || !this.traceEngineData) {\n return;\n }\n this.appendHeader('', this.screenshotsHeader, false /* selectable */);\n this.entryTypeByLevel[this.currentLevel] = EntryType.SCREENSHOT;\n let prevTimestamp: TraceEngine.Types.Timing.MilliSeconds|undefined = undefined;\n\n for (const filmStripFrame of filmStrip.frames) {\n const screenshotTimeInMilliSeconds =\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds(filmStripFrame.screenshotEvent.ts);\n this.entryData.push(filmStripFrame.screenshotEvent);\n (this.timelineDataInternal.entryLevels as number[]).push(this.currentLevel);\n (this.timelineDataInternal.entryStartTimes as number[]).push(screenshotTimeInMilliSeconds);\n if (prevTimestamp) {\n (this.timelineDataInternal.entryTotalTimes as number[]).push(screenshotTimeInMilliSeconds - prevTimestamp);\n }\n prevTimestamp = screenshotTimeInMilliSeconds;\n }\n if (filmStrip.frames.length && prevTimestamp !== undefined) {\n const maxRecordTimeMillis =\n TraceEngine.Helpers.Timing.traceWindowMilliSeconds(this.traceEngineData.Meta.traceBounds).max;\n\n // Set the total time of the final screenshot so it takes up the remainder of the trace.\n (this.timelineDataInternal.entryTotalTimes as number[]).push(maxRecordTimeMillis - prevTimestamp);\n }\n ++this.currentLevel;\n }\n\n #entryTypeForIndex(entryIndex: number): EntryType {\n const level = this.timelineData().entryLevels[entryIndex];\n return this.entryTypeByLevel[level];\n }\n\n prepareHighlightedEntryInfo(entryIndex: number): Element|null {\n let time = '';\n let title;\n let warningElements: Element[] = [];\n let nameSpanTimelineInfoTime = 'timeline-info-time';\n\n const additionalContent: HTMLElement[] = [];\n\n const entryType = this.#entryTypeForIndex(entryIndex);\n if (entryType === EntryType.TRACK_APPENDER) {\n if (!this.compatibilityTracksAppender) {\n return null;\n }\n const event = (this.entryData[entryIndex] as TraceEngine.Types.TraceEvents.TraceEventData);\n const timelineData = (this.timelineDataInternal as PerfUI.FlameChart.FlameChartTimelineData);\n const eventLevel = timelineData.entryLevels[entryIndex];\n const highlightedEntryInfo = this.compatibilityTracksAppender.highlightedEntryInfo(event, eventLevel);\n title = highlightedEntryInfo.title;\n time = highlightedEntryInfo.formattedTime;\n warningElements = highlightedEntryInfo.warningElements || warningElements;\n if (TraceEngine.Types.TraceEvents.isSyntheticInteractionEvent(event)) {\n const breakdown = new Components.InteractionBreakdown.InteractionBreakdown();\n breakdown.entry = event;\n additionalContent.push(breakdown);\n }\n } else if (entryType === EntryType.FRAME) {\n const frame = (this.entryData[entryIndex] as TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame);\n time = i18n.TimeUtilities.preciseMillisToString(\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.duration), 1);\n\n if (frame.idle) {\n title = i18nString(UIStrings.idleFrame);\n } else if (frame.dropped) {\n if (frame.isPartial) {\n title = i18nString(UIStrings.partiallyPresentedFrame);\n } else {\n title = i18nString(UIStrings.droppedFrame);\n }\n nameSpanTimelineInfoTime = 'timeline-info-warning';\n } else {\n title = i18nString(UIStrings.frame);\n }\n } else {\n return null;\n }\n\n const element = document.createElement('div');\n const root = UI.UIUtils.createShadowRootWithCoreStyles(element, {\n cssFile: [timelineFlamechartPopoverStyles],\n delegatesFocus: undefined,\n });\n const contents = root.createChild('div', 'timeline-flamechart-popover');\n contents.createChild('span', nameSpanTimelineInfoTime).textContent = time;\n contents.createChild('span', 'timeline-info-title').textContent = title;\n if (warningElements) {\n for (const warningElement of warningElements) {\n warningElement.classList.add('timeline-info-warning');\n contents.appendChild(warningElement);\n }\n }\n for (const elem of additionalContent) {\n contents.appendChild(elem);\n }\n return element;\n }\n\n prepareHighlightedHiddenEntriesArrowInfo(entryIndex: number): Element|null {\n const element = document.createElement('div');\n const root = UI.UIUtils.createShadowRootWithCoreStyles(element, {\n cssFile: [timelineFlamechartPopoverStyles],\n delegatesFocus: undefined,\n });\n\n const entry = this.entryData[entryIndex] as TraceEngine.Types.TraceEvents.TraceEventData;\n const hiddenEntriesAmount =\n ModificationsManager.activeManager()?.getEntriesFilter().findHiddenDescendantsAmount(entry);\n\n if (!hiddenEntriesAmount) {\n return null;\n }\n const contents = root.createChild('div', 'timeline-flamechart-popover');\n contents.createChild('span', 'timeline-info-title').textContent = hiddenEntriesAmount + ' hidden';\n\n return element;\n }\n\n entryColor(entryIndex: number): string {\n const entryType = this.#entryTypeForIndex(entryIndex);\n if (entryType === EntryType.FRAME) {\n return 'white';\n }\n if (entryType === EntryType.TRACK_APPENDER) {\n const timelineData = (this.timelineDataInternal as PerfUI.FlameChart.FlameChartTimelineData);\n const eventLevel = timelineData.entryLevels[entryIndex];\n const event = (this.entryData[entryIndex] as TraceEngine.Types.TraceEvents.TraceEventData);\n return this.compatibilityTracksAppender?.colorForEvent(event, eventLevel) || '';\n }\n return '';\n }\n\n private preparePatternCanvas(): void {\n // Set the candy stripe pattern to 17px so it repeats well.\n const size = 17;\n this.droppedFramePatternCanvas.width = size;\n this.droppedFramePatternCanvas.height = size;\n\n this.partialFramePatternCanvas.width = size;\n this.partialFramePatternCanvas.height = size;\n\n const ctx = this.droppedFramePatternCanvas.getContext('2d');\n if (ctx) {\n // Make a dense solid-line pattern.\n ctx.translate(size * 0.5, size * 0.5);\n ctx.rotate(Math.PI * 0.25);\n ctx.translate(-size * 0.5, -size * 0.5);\n\n ctx.fillStyle = 'rgb(255, 255, 255)';\n for (let x = -size; x < size * 2; x += 3) {\n ctx.fillRect(x, -size, 1, size * 3);\n }\n }\n\n const ctx2 = this.partialFramePatternCanvas.getContext('2d');\n if (ctx2) {\n // Make a sparse dashed-line pattern.\n ctx2.strokeStyle = 'rgb(255, 255, 255)';\n ctx2.lineWidth = 2;\n ctx2.beginPath();\n ctx2.moveTo(17, 0);\n ctx2.lineTo(10, 7);\n ctx2.moveTo(8, 9);\n ctx2.lineTo(2, 15);\n ctx2.stroke();\n }\n }\n\n private drawFrame(\n entryIndex: number, context: CanvasRenderingContext2D, text: string|null, barX: number, barY: number,\n barWidth: number, barHeight: number): void {\n const hPadding = 1;\n const frame = (this.entryData[entryIndex] as TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame);\n barX += hPadding;\n barWidth -= 2 * hPadding;\n if (frame.idle) {\n context.fillStyle = 'white';\n } else if (frame.dropped) {\n if (frame.isPartial) {\n // For partially presented frame boxes, paint a yellow background with\n // a sparse white dashed-line pattern overlay.\n context.fillStyle = '#f0e442';\n context.fillRect(barX, barY, barWidth, barHeight);\n\n const overlay = context.createPattern(this.partialFramePatternCanvas, 'repeat');\n context.fillStyle = overlay || context.fillStyle;\n } else {\n // For dropped frame boxes, paint a red background with a dense white\n // solid-line pattern overlay.\n context.fillStyle = '#f08080';\n context.fillRect(barX, barY, barWidth, barHeight);\n\n const overlay = context.createPattern(this.droppedFramePatternCanvas, 'repeat');\n context.fillStyle = overlay || context.fillStyle;\n }\n } else {\n context.fillStyle = '#d7f0d1';\n }\n context.fillRect(barX, barY, barWidth, barHeight);\n\n const frameDurationText = i18n.TimeUtilities.preciseMillisToString(\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.duration), 1);\n const textWidth = context.measureText(frameDurationText).width;\n if (textWidth <= barWidth) {\n context.fillStyle = this.textColor(entryIndex);\n context.fillText(frameDurationText, barX + (barWidth - textWidth) / 2, barY + barHeight - 4);\n }\n }\n\n private async drawScreenshot(\n entryIndex: number, context: CanvasRenderingContext2D, barX: number, barY: number, barWidth: number,\n barHeight: number): Promise {\n const screenshot = (this.entryData[entryIndex] as TraceEngine.Types.TraceEvents.SyntheticScreenshot);\n if (!this.screenshotImageCache.has(screenshot)) {\n this.screenshotImageCache.set(screenshot, null);\n const data = screenshot.args.dataUri;\n const image = await UI.UIUtils.loadImage(data);\n this.screenshotImageCache.set(screenshot, image);\n this.dispatchEventToListeners(Events.DATA_CHANGED);\n return;\n }\n\n const image = this.screenshotImageCache.get(screenshot);\n if (!image) {\n return;\n }\n const imageX = barX + 1;\n const imageY = barY + 1;\n const imageHeight = barHeight - 2;\n const scale = imageHeight / image.naturalHeight;\n const imageWidth = Math.floor(image.naturalWidth * scale);\n context.save();\n context.beginPath();\n context.rect(barX, barY, barWidth, barHeight);\n context.clip();\n context.drawImage(image, imageX, imageY, imageWidth, imageHeight);\n context.strokeStyle = '#ccc';\n context.strokeRect(imageX - 0.5, imageY - 0.5, Math.min(barWidth - 1, imageWidth + 1), imageHeight);\n context.restore();\n }\n\n decorateEntry(\n entryIndex: number, context: CanvasRenderingContext2D, text: string|null, barX: number, barY: number,\n barWidth: number, barHeight: number, unclippedBarX: number, timeToPixelRatio: number): boolean {\n const entryType = this.#entryTypeForIndex(entryIndex);\n\n if (entryType === EntryType.FRAME) {\n this.drawFrame(entryIndex, context, text, barX, barY, barWidth, barHeight);\n return true;\n }\n\n if (entryType === EntryType.SCREENSHOT) {\n void this.drawScreenshot(entryIndex, context, barX, barY, barWidth, barHeight);\n return true;\n }\n\n if (entryType === EntryType.TRACK_APPENDER) {\n const entry = this.entryData[entryIndex] as TraceEngine.Types.TraceEvents.TraceEventData;\n if (TraceEngine.Types.TraceEvents.isSyntheticInteractionEvent(entry)) {\n this.#drawInteractionEventWithWhiskers(\n context, entryIndex, text, entry, barX, barY, unclippedBarX, barWidth, barHeight, timeToPixelRatio);\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Draws the left and right whiskers around an interaction in the timeline.\n * @param context - the canvas that will be drawn onto\n * @param entryIndex\n * @param entryTitle - the title of the entry\n * @param entry - the entry itself\n * @param barX - the starting X pixel position of the bar representing this event. This is clipped: if the bar is off the left side of the screen, this value will be 0\n * @param barY - the starting Y pixel position of the bar representing this event.\n * @param unclippedBarXStartPixel - the starting X pixel position of the bar representing this event, not clipped. This means if the bar is off the left of the screen this will be a negative number.\n * @param barWidth - the width of the full bar in pixels\n * @param barHeight - the height of the full bar in pixels\n * @param timeToPixelRatio - the ratio required to convert a millisecond time to a pixel value.\n **/\n #drawInteractionEventWithWhiskers(\n context: CanvasRenderingContext2D, entryIndex: number, entryTitle: string|null,\n entry: TraceEngine.Types.TraceEvents.SyntheticInteractionPair, barX: number, barY: number,\n unclippedBarXStartPixel: number, barWidth: number, barHeight: number, timeToPixelRatio: number): void {\n /**\n * An interaction is drawn with whiskers as so:\n * |----------[=======]-------------|\n * => The left whisker is the event's start time (event.ts)\n * => The box start is the event's processingStart time\n * => The box end is the event's processingEnd time\n * => The right whisker is the event's end time (event.ts + event.dur)\n *\n * When we draw the event in the InteractionsAppender, we draw a huge box\n * that spans the entire of the above. So here we need to draw over the\n * rectangle that is outside of {processingStart, processingEnd} and\n * replace it with the whiskers.\n * TODO(crbug.com/1495248): rework how we draw whiskers to avoid this inefficiency\n */\n\n const beginTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(entry.ts);\n const entireBarEndXPixel = barX + barWidth;\n\n function timeToPixel(time: TraceEngine.Types.Timing.MicroSeconds): number {\n const timeMilli = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(time);\n return Math.floor(unclippedBarXStartPixel + (timeMilli - beginTime) * timeToPixelRatio);\n }\n\n context.save();\n\n // Clear portions of initial rect to prepare for the ticks.\n context.fillStyle = ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-cdt-base-container');\n let desiredBoxStartX = timeToPixel(entry.processingStart);\n const desiredBoxEndX = timeToPixel(entry.processingEnd);\n\n // If the entry has no processing duration, ensure the box is 1px wide so at least it is visible.\n if (entry.processingEnd - entry.processingStart === 0) {\n desiredBoxStartX -= 1;\n }\n\n context.fillRect(barX, barY - 0.5, desiredBoxStartX - barX, barHeight);\n context.fillRect(desiredBoxEndX, barY - 0.5, entireBarEndXPixel - desiredBoxEndX, barHeight);\n\n // Draws left and right whiskers\n function drawTick(begin: number, end: number, y: number): void {\n const tickHeightPx = 6;\n context.moveTo(begin, y - tickHeightPx / 2);\n context.lineTo(begin, y + tickHeightPx / 2);\n context.moveTo(begin, y);\n context.lineTo(end, y);\n }\n\n // The left whisker starts at the enty timestamp, and continues until the start of the box (processingStart).\n const leftWhiskerX = timeToPixel(entry.ts);\n // The right whisker ends at (entry.ts + entry.dur). We draw the line from the end of the box (processingEnd).\n const rightWhiskerX = timeToPixel(TraceEngine.Types.Timing.MicroSeconds(entry.ts + entry.dur));\n context.beginPath();\n context.lineWidth = 1;\n context.strokeStyle = '#ccc';\n const lineY = Math.floor(barY + barHeight / 2) + 0.5;\n const leftTick = leftWhiskerX + 0.5;\n const rightTick = rightWhiskerX - 0.5;\n drawTick(leftTick, desiredBoxStartX, lineY);\n drawTick(rightTick, desiredBoxEndX, lineY);\n context.stroke();\n\n if (entryTitle) {\n // BarX will be set to 0 if the start of the box if off the screen to the\n // left. If this happens, the desiredBoxStartX will be negative. In that\n // case, we fallback to the BarX. This ensures that even if the box\n // starts off-screen, we draw the text at the first visible on screen\n // pixels, so the user can still see the event's title.\n const textStartX = desiredBoxStartX > 0 ? desiredBoxStartX : barX;\n context.font = this.#font;\n const textWidth = UI.UIUtils.measureTextWidth(context, entryTitle);\n\n // These numbers are duplicated from FlameChart.ts.\n const textPadding = 5;\n const textBaseline = 5;\n\n // Only draw the text if it can fit in the amount of box that is visible.\n if (textWidth <= desiredBoxEndX - textStartX + textPadding) {\n context.fillStyle = this.textColor(entryIndex);\n context.fillText(entryTitle, textStartX + textPadding, barY + barHeight - textBaseline);\n }\n }\n context.restore();\n }\n\n forceDecoration(entryIndex: number): boolean {\n const entryType = this.#entryTypeForIndex(entryIndex);\n if (entryType === EntryType.FRAME) {\n return true;\n }\n if (entryType === EntryType.SCREENSHOT) {\n return true;\n }\n const event = (this.entryData[entryIndex] as TraceEngine.Types.TraceEvents.TraceEventData);\n\n if (TraceEngine.Types.TraceEvents.isSyntheticInteractionEvent(event)) {\n // We draw interactions with whiskers, which are done via the\n // decorateEntry() method, hence we always want to force these to be\n // decorated.\n return true;\n }\n return Boolean(this.traceEngineData?.Warnings.perEvent.get(event));\n }\n\n private appendHeader(title: string, style: PerfUI.FlameChart.GroupStyle, selectable: boolean, expanded?: boolean):\n PerfUI.FlameChart.Group {\n const group =\n ({startLevel: this.currentLevel, name: title, style, selectable, expanded} as PerfUI.FlameChart.Group);\n (this.timelineDataInternal as PerfUI.FlameChart.FlameChartTimelineData).groups.push(group);\n return group;\n }\n\n #appendNewEngineFrame(frame: TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame): void {\n const index = this.entryData.length;\n this.entryData.push(frame);\n const durationMilliseconds = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.duration);\n this.entryIndexToTitle[index] = i18n.TimeUtilities.millisToString(durationMilliseconds, true);\n if (!this.timelineDataInternal) {\n return;\n }\n this.timelineDataInternal.entryLevels[index] = this.currentLevel;\n this.timelineDataInternal.entryTotalTimes[index] = durationMilliseconds;\n this.timelineDataInternal.entryStartTimes[index] =\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.startTime);\n }\n\n createSelection(entryIndex: number): TimelineSelection|null {\n const entryType = this.#entryTypeForIndex(entryIndex);\n let timelineSelection: TimelineSelection|null = null;\n const entry = this.entryData[entryIndex];\n if (entry && TimelineFlameChartDataProvider.timelineEntryIsTraceEvent(entry)) {\n timelineSelection = TimelineSelection.fromTraceEvent(entry);\n } else if (entryType === EntryType.FRAME) {\n timelineSelection = TimelineSelection.fromFrame(\n (this.entryData[entryIndex] as TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame));\n }\n if (timelineSelection) {\n this.lastSelection = new Selection(timelineSelection, entryIndex);\n }\n return timelineSelection;\n }\n\n formatValue(value: number, precision?: number): string {\n return i18n.TimeUtilities.preciseMillisToString(value, precision);\n }\n\n groupForEvent(entryIndex: number): PerfUI.FlameChart.Group|null {\n if (!this.compatibilityTracksAppender) {\n return null;\n }\n const level = this.timelineDataInternal?.entryLevels[entryIndex] ?? null;\n if (level === null) {\n return null;\n }\n const groupForLevel = this.compatibilityTracksAppender.groupForLevel(level);\n if (!groupForLevel) {\n return null;\n }\n return groupForLevel;\n }\n\n canJumpToEntry(_entryIndex: number): boolean {\n return false;\n }\n\n entryIndexForSelection(selection: TimelineSelection|null): number {\n if (!selection || TimelineSelection.isRangeSelection(selection.object) ||\n TimelineSelection.isSyntheticNetworkRequestDetailsEventSelection(selection.object)) {\n return -1;\n }\n\n if (this.lastSelection && this.lastSelection.timelineSelection.object === selection.object) {\n return this.lastSelection.entryIndex;\n }\n\n // If the index is -1 and the selection is a TraceEvent, it might be\n // the case that this Entry is hidden by the Context Menu action.\n // Try revealing the entry and getting the index again.\n if (this.entryData.indexOf(selection.object) === -1 && TimelineSelection.isTraceEventSelection(selection.object)) {\n if (this.timelineDataInternal?.selectedGroup) {\n ModificationsManager.activeManager()?.getEntriesFilter().revealEntry(\n selection.object as TraceEngine.Types.TraceEvents.TraceEventData);\n this.timelineData(true);\n }\n }\n\n const index = this.entryData.indexOf(selection.object);\n if (index !== -1) {\n this.lastSelection = new Selection(selection, index);\n }\n return index;\n }\n\n /**\n * Return the index for the given entry. Note that this method assumes that\n * timelineData() has been generated. If it hasn't, this method will return\n * null.\n */\n indexForEvent(targetEvent: TraceEngine.Types.TraceEvents.TraceEventData|\n TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame): number|null {\n // Gets the index for the given event by walking through the array of entryData.\n // This may seem inefficient - but we have seen that by building up large\n // maps keyed by trace events that this has a significant impact on the\n // performance of the panel.\n // Therefore, we strike a middle ground: look up the event the first time,\n // but then cache the result.\n const fromCache = this.#eventIndexByEvent.get(targetEvent);\n if (typeof fromCache === 'number') {\n return fromCache;\n }\n const index = this.entryData.indexOf(targetEvent);\n const result = index > -1 ? index : null;\n this.#eventIndexByEvent.set(targetEvent, result);\n return result;\n }\n\n /**\n * Build the data for initiators and initiated entries.\n * @param entryIndex\n * @returns if we should re-render the flame chart (canvas)\n */\n buildFlowForInitiator(entryIndex: number): boolean {\n if (!this.traceEngineData) {\n return false;\n }\n if (!this.timelineDataInternal) {\n return false;\n }\n if (this.lastInitiatorEntry === entryIndex) {\n if (this.lastInitiatorsData) {\n this.timelineDataInternal.initiatorsData = this.lastInitiatorsData;\n }\n return false;\n }\n if (!this.compatibilityTracksAppender) {\n return false;\n }\n\n // Remove all previously assigned decorations indicating that the flow event entries are hidden\n const previousInitiatorsDataLength = this.timelineDataInternal.initiatorsData.length;\n // |entryIndex| equals -1 means there is no entry selected, just clear the\n // initiator cache if there is any previous arrow and return true to\n // re-render.\n if (entryIndex === -1) {\n this.lastInitiatorEntry = entryIndex;\n if (previousInitiatorsDataLength === 0) {\n // This means there is no arrow before, so we don't need to re-render.\n return false;\n }\n // Reset to clear any previous arrows from the last event.\n this.timelineDataInternal.resetFlowData();\n return true;\n }\n\n const entryType = this.#entryTypeForIndex(entryIndex);\n if (entryType !== EntryType.TRACK_APPENDER) {\n return false;\n }\n const event = this.entryData[entryIndex] as TraceEngine.Types.TraceEvents.TraceEventData;\n // Reset to clear any previous arrows from the last event.\n this.timelineDataInternal.resetFlowData();\n this.lastInitiatorEntry = entryIndex;\n\n const hiddenEvents: TraceEngine.Types.TraceEvents.TraceEventData[] =\n ModificationsManager.activeManager()?.getEntriesFilter().invisibleEntries() ?? [];\n const expandableEntries: TraceEngine.Types.TraceEvents.TraceEventData[] =\n ModificationsManager.activeManager()?.getEntriesFilter().expandableEntries() ?? [];\n\n const initiatorsData = initiatorsDataToDraw(\n this.traceEngineData,\n event,\n hiddenEvents,\n expandableEntries,\n );\n // This means there is no change for arrows.\n if (previousInitiatorsDataLength === 0 && initiatorsData.length === 0) {\n return false;\n }\n for (const initiatorData of initiatorsData) {\n const eventIndex = this.indexForEvent(initiatorData.event);\n const initiatorIndex = this.indexForEvent(initiatorData.initiator);\n if (eventIndex === null || initiatorIndex === null) {\n continue;\n }\n this.timelineDataInternal.initiatorsData.push({\n initiatorIndex,\n eventIndex,\n isInitiatorHidden: initiatorData.isInitiatorHidden,\n isEntryHidden: initiatorData.isEntryHidden,\n });\n }\n this.lastInitiatorsData = this.timelineDataInternal.initiatorsData;\n return true;\n }\n\n eventByIndex(entryIndex: number): TraceEngine.Types.TraceEvents.TraceEventData\n |TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame|null {\n if (entryIndex < 0) {\n return null;\n }\n const entryType = this.#entryTypeForIndex(entryIndex);\n if (entryType === EntryType.TRACK_APPENDER) {\n return this.entryData[entryIndex] as TraceEngine.Types.TraceEvents.TraceEventData;\n }\n if (entryType === EntryType.FRAME) {\n return this.entryData[entryIndex] as TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame;\n }\n return null;\n }\n}\n\nexport const InstantEventVisibleDurationMs = TraceEngine.Types.Timing.MilliSeconds(0.001);\n\nexport const enum Events {\n DATA_CHANGED = 'DataChanged',\n}\n\nexport type EventTypes = {\n [Events.DATA_CHANGED]: void,\n};\n\n// an entry is a trace event, they are classified into \"entry types\"\n// because some events are rendered differently. For example, screenshot\n// events are rendered as images. Checks for entry types allow to have\n// different styles, names, etc. for events that look differently.\n// In the future we won't have this checks: instead we will forward\n// the event to the corresponding \"track appender\" and it will determine\n// how the event shall be rendered.\nexport const enum EntryType {\n FRAME = 'Frame',\n TRACK_APPENDER = 'TrackAppender',\n SCREENSHOT = 'Screenshot',\n}\n"]} \ No newline at end of file +{"version":3,"file":"TimelineFlameChartDataProvider.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineFlameChartDataProvider.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Copyright (C) 2014 Google Inc. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * * Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above\n * copyright notice, this list of conditions and the following disclaimer\n * in the documentation and/or other materials provided with the\n * distribution.\n * * Neither the name of Google Inc. nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport type * as Platform from '../../core/platform/platform.js';\nimport * as Root from '../../core/root/root.js';\nimport * as Bindings from '../../models/bindings/bindings.js';\nimport type * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\n\nimport {CompatibilityTracksAppender, type DrawOverride, type TrackAppenderName} from './CompatibilityTracksAppender.js';\nimport * as Components from './components/components.js';\nimport {ExtensionDataGatherer} from './ExtensionDataGatherer.js';\nimport {initiatorsDataToDraw} from './Initiators.js';\nimport {ModificationsManager} from './ModificationsManager.js';\nimport {ThreadAppender} from './ThreadAppender.js';\nimport timelineFlamechartPopoverStyles from './timelineFlamechartPopover.css.js';\nimport {FlameChartStyle, Selection} from './TimelineFlameChartView.js';\nimport {TimelineSelection} from './TimelineSelection.js';\n\nconst UIStrings = {\n /**\n *@description Text for rendering frames\n */\n frames: 'Frames',\n /**\n *@description Text in Timeline Flame Chart Data Provider of the Performance panel\n */\n idleFrame: 'Idle frame',\n /**\n *@description Text in Timeline Frame Chart Data Provider of the Performance panel\n */\n droppedFrame: 'Dropped frame',\n /**\n *@description Text in Timeline Frame Chart Data Provider of the Performance panel\n */\n partiallyPresentedFrame: 'Partially-presented frame',\n /**\n *@description Text for a rendering frame\n */\n frame: 'Frame',\n /**\n *@description Text for Hiding a function from the Flame Chart\n */\n hideFunction: 'Hide function',\n /**\n *@description Text for Hiding all children of a function from the Flame Chart\n */\n hideChildren: 'Hide children',\n /**\n *@description Text for Hiding all child entries that are identical to the selected entry from the Flame Chart\n */\n hideRepeatingChildren: 'Hide repeating children',\n /**\n *@description Text for remove script from ignore list from the Flame Chart\n */\n removeScriptFromIgnoreList: 'Remove script from ignore list',\n /**\n *@description Text for add script to ignore list from the Flame Chart\n */\n addScriptToIgnoreList: 'Add script to ignore list',\n /**\n *@description Text for an action that shows all of the hidden children of an entry\n */\n resetChildren: 'Reset children',\n /**\n *@description Text for an action that shows all of the hidden entries of the Flame Chart\n */\n resetTrace: 'Reset trace',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelineFlameChartDataProvider.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\n// Frames are special cased because we don't render them as a normal track, hence the distinction here.\nexport type TimelineFlameChartEntry = Trace.Handlers.ModelHandlers.Frames.TimelineFrame|Trace.Types.Events.Event;\n\nexport class TimelineFlameChartDataProvider extends Common.ObjectWrapper.ObjectWrapper implements\n PerfUI.FlameChart.FlameChartDataProvider {\n private droppedFramePatternCanvas: HTMLCanvasElement;\n private partialFramePatternCanvas: HTMLCanvasElement;\n private timelineDataInternal: PerfUI.FlameChart.FlameChartTimelineData|null;\n private currentLevel: number;\n\n // The Performance and the Timeline models are expected to be\n // deprecated in favor of using parsedTrace (new RPP engine) only\n // as part of the work in crbug.com/1386091. For this reason they\n // have the \"legacy\" prefix on their name.\n private compatibilityTracksAppender: CompatibilityTracksAppender|null;\n private parsedTrace: Trace.Handlers.Types.ParsedTrace|null;\n private isCpuProfile = false;\n\n private minimumBoundaryInternal: number;\n private timeSpan: number;\n private readonly headerLevel1: PerfUI.FlameChart.GroupStyle;\n private readonly headerLevel2: PerfUI.FlameChart.GroupStyle;\n private readonly staticHeader: PerfUI.FlameChart.GroupStyle;\n private framesHeader: PerfUI.FlameChart.GroupStyle;\n private readonly screenshotsHeader: PerfUI.FlameChart.GroupStyle;\n\n // Contains all the entries that are DRAWN onto the track. Entries that have\n // been hidden - either by a user action, or because they aren't visible at\n // all - will not appear in this array and it will change per-render. For\n // example, if a user collapses an icicle in the flamechart, those entries\n // that are now hidden will no longer be in this array.\n private entryData: TimelineFlameChartEntry[] = [];\n\n private entryTypeByLevel!: EntryType[];\n private screenshotImageCache!: Map;\n private entryIndexToTitle!: string[];\n private lastInitiatorEntry!: number;\n private lastInitiatorsData: PerfUI.FlameChart.FlameChartInitiatorData[] = [];\n private lastSelection?: Selection;\n #font: string;\n #eventIndexByEvent: WeakMap =\n new WeakMap();\n\n constructor() {\n super();\n this.reset();\n this.#font = `${PerfUI.Font.DEFAULT_FONT_SIZE} ${PerfUI.Font.getFontFamilyForCanvas()}`;\n this.droppedFramePatternCanvas = document.createElement('canvas');\n this.partialFramePatternCanvas = document.createElement('canvas');\n this.preparePatternCanvas();\n this.timelineDataInternal = null;\n this.currentLevel = 0;\n this.compatibilityTracksAppender = null;\n this.parsedTrace = null;\n this.minimumBoundaryInternal = 0;\n this.timeSpan = 0;\n\n this.headerLevel1 = this.buildGroupStyle({shareHeaderLine: false});\n this.headerLevel2 = this.buildGroupStyle({padding: 2, nestingLevel: 1, collapsible: false});\n this.staticHeader = this.buildGroupStyle({collapsible: false});\n this.framesHeader = this.buildGroupStyle({useFirstLineForOverview: true});\n this.screenshotsHeader =\n this.buildGroupStyle({useFirstLineForOverview: true, nestingLevel: 1, collapsible: false, itemsHeight: 150});\n\n ThemeSupport.ThemeSupport.instance().addEventListener(ThemeSupport.ThemeChangeEvent.eventName, () => {\n const headers = [\n this.headerLevel1,\n this.headerLevel2,\n this.staticHeader,\n this.framesHeader,\n this.screenshotsHeader,\n ];\n for (const header of headers) {\n header.color = ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-on-surface');\n header.backgroundColor =\n ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-cdt-base-container');\n }\n });\n }\n\n hasTrackConfigurationMode(): boolean {\n return true;\n }\n\n getPossibleActions(entryIndex: number, groupIndex: number): PerfUI.FlameChart.PossibleFilterActions|void {\n const data = this.timelineData();\n if (!data) {\n return;\n }\n const group = data.groups.at(groupIndex);\n // Early exit here if there is no group or:\n // 1. The group is not expanded: it needs to be expanded to allow the\n // context menu actions to occur.\n // 2. The group does not have the showStackContextMenu flag which indicates\n // that it does not show entries that support the stack actions.\n if (!group || !group.expanded || !group.showStackContextMenu) {\n return;\n }\n\n // Check which actions are possible on an entry.\n // If an action would not change the entries (for example it has no children to collapse), we do not need to show it.\n return this.findPossibleContextMenuActions(entryIndex);\n }\n\n customizedContextMenu(event: MouseEvent, entryIndex: number, groupIndex: number): UI.ContextMenu.ContextMenu\n |undefined {\n const possibleActions = this.getPossibleActions(entryIndex, groupIndex);\n if (!possibleActions) {\n return;\n }\n\n const contextMenu = new UI.ContextMenu.ContextMenu(event, {useSoftMenu: true});\n\n const hideEntryOption = contextMenu.defaultSection().appendItem(i18nString(UIStrings.hideFunction), () => {\n this.modifyTree(PerfUI.FlameChart.FilterAction.MERGE_FUNCTION, entryIndex);\n }, {\n disabled: !possibleActions?.[PerfUI.FlameChart.FilterAction.MERGE_FUNCTION],\n jslogContext: 'hide-function',\n });\n hideEntryOption.setShortcut('H');\n\n const hideChildrenOption = contextMenu.defaultSection().appendItem(i18nString(UIStrings.hideChildren), () => {\n this.modifyTree(PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION, entryIndex);\n }, {\n disabled: !possibleActions?.[PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION],\n jslogContext: 'hide-children',\n });\n hideChildrenOption.setShortcut('C');\n\n const hideRepeatingChildrenOption =\n contextMenu.defaultSection().appendItem(i18nString(UIStrings.hideRepeatingChildren), () => {\n this.modifyTree(PerfUI.FlameChart.FilterAction.COLLAPSE_REPEATING_DESCENDANTS, entryIndex);\n }, {\n disabled: !possibleActions?.[PerfUI.FlameChart.FilterAction.COLLAPSE_REPEATING_DESCENDANTS],\n jslogContext: 'hide-repeating-children',\n });\n hideRepeatingChildrenOption.setShortcut('R');\n\n const resetChildrenOption = contextMenu.defaultSection().appendItem(i18nString(UIStrings.resetChildren), () => {\n this.modifyTree(PerfUI.FlameChart.FilterAction.RESET_CHILDREN, entryIndex);\n }, {\n disabled: !possibleActions?.[PerfUI.FlameChart.FilterAction.RESET_CHILDREN],\n jslogContext: 'reset-children',\n });\n resetChildrenOption.setShortcut('U');\n\n contextMenu.defaultSection().appendItem(i18nString(UIStrings.resetTrace), () => {\n this.modifyTree(PerfUI.FlameChart.FilterAction.UNDO_ALL_ACTIONS, entryIndex);\n }, {\n disabled: !possibleActions?.[PerfUI.FlameChart.FilterAction.UNDO_ALL_ACTIONS],\n jslogContext: 'reset-trace',\n });\n\n const entry = this.eventByIndex(entryIndex);\n if (entry && entry instanceof Trace.Handlers.ModelHandlers.Frames.TimelineFrame === false) {\n const url = (Trace.Types.Events.isProfileCall(entry)) ? entry.callFrame.url as Platform.DevToolsPath.UrlString :\n undefined;\n if (url) {\n if (Bindings.IgnoreListManager.IgnoreListManager.instance().isUserIgnoreListedURL(url)) {\n contextMenu.defaultSection().appendItem(i18nString(UIStrings.removeScriptFromIgnoreList), () => {\n Bindings.IgnoreListManager.IgnoreListManager.instance().unIgnoreListURL(url);\n this.dispatchEventToListeners(Events.DATA_CHANGED);\n }, {\n jslogContext: 'remove-from-ignore-list',\n });\n } else {\n contextMenu.defaultSection().appendItem(i18nString(UIStrings.addScriptToIgnoreList), () => {\n Bindings.IgnoreListManager.IgnoreListManager.instance().ignoreListURL(url);\n this.dispatchEventToListeners(Events.DATA_CHANGED);\n }, {\n jslogContext: 'add-to-ignore-list',\n });\n }\n }\n }\n\n return contextMenu;\n }\n\n modifyTree(action: PerfUI.FlameChart.FilterAction, entryIndex: number): void {\n const entry = this.entryData[entryIndex] as Trace.Types.Events.Event;\n\n ModificationsManager.activeManager()?.getEntriesFilter().applyFilterAction({type: action, entry});\n this.timelineData(true);\n this.buildFlowForInitiator(entryIndex);\n this.dispatchEventToListeners(Events.DATA_CHANGED);\n }\n\n findPossibleContextMenuActions(entryIndex: number): PerfUI.FlameChart.PossibleFilterActions|void {\n const entry = this.entryData[entryIndex] as Trace.Types.Events.Event;\n return ModificationsManager.activeManager()?.getEntriesFilter().findPossibleActions(entry);\n }\n\n handleFlameChartTransformKeyboardEvent(event: KeyboardEvent, entryIndex: number, groupIndex: number): void {\n const possibleActions = this.getPossibleActions(entryIndex, groupIndex);\n if (!possibleActions) {\n return;\n }\n\n let handled = false;\n\n if (event.code === 'KeyH' && possibleActions[PerfUI.FlameChart.FilterAction.MERGE_FUNCTION]) {\n this.modifyTree(PerfUI.FlameChart.FilterAction.MERGE_FUNCTION, entryIndex);\n handled = true;\n } else if (event.code === 'KeyC' && possibleActions[PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION]) {\n this.modifyTree(PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION, entryIndex);\n handled = true;\n } else if (\n event.code === 'KeyR' && possibleActions[PerfUI.FlameChart.FilterAction.COLLAPSE_REPEATING_DESCENDANTS]) {\n this.modifyTree(PerfUI.FlameChart.FilterAction.COLLAPSE_REPEATING_DESCENDANTS, entryIndex);\n handled = true;\n } else if (event.code === 'KeyU') {\n this.modifyTree(PerfUI.FlameChart.FilterAction.RESET_CHILDREN, entryIndex);\n handled = true;\n }\n\n if (handled) {\n event.consume(true);\n }\n }\n\n private buildGroupStyle(extra: Object): PerfUI.FlameChart.GroupStyle {\n const defaultGroupStyle = {\n padding: 4,\n height: 17,\n collapsible: true,\n color: ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-on-surface'),\n backgroundColor: ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-cdt-base-container'),\n nestingLevel: 0,\n shareHeaderLine: true,\n };\n return Object.assign(defaultGroupStyle, extra);\n }\n\n setModel(parsedTrace: Trace.Handlers.Types.ParsedTrace|null, isCpuProfile = false): void {\n this.reset();\n this.parsedTrace = parsedTrace;\n ExtensionDataGatherer.instance().modelChanged(parsedTrace);\n\n this.isCpuProfile = isCpuProfile;\n if (parsedTrace) {\n const {traceBounds} = parsedTrace.Meta;\n const minTime = Trace.Helpers.Timing.microSecondsToMilliseconds(traceBounds.min);\n const maxTime = Trace.Helpers.Timing.microSecondsToMilliseconds(traceBounds.max);\n this.minimumBoundaryInternal = minTime;\n this.timeSpan = minTime === maxTime ? 1000 : maxTime - this.minimumBoundaryInternal;\n }\n }\n\n /**\n * Instances and caches a CompatibilityTracksAppender using the\n * internal flame chart data and the trace parsed data coming from the\n * trace engine.\n * The model data must have been set to the data provider instance before\n * attempting to instance the CompatibilityTracksAppender.\n */\n compatibilityTracksAppenderInstance(forceNew = false): CompatibilityTracksAppender {\n if (!this.compatibilityTracksAppender || forceNew) {\n if (!this.parsedTrace) {\n throw new Error(\n 'Attempted to instantiate a CompatibilityTracksAppender without having set the trace parse data first.');\n }\n this.timelineDataInternal = this.#instantiateTimelineData();\n this.compatibilityTracksAppender = new CompatibilityTracksAppender(\n this.timelineDataInternal, this.parsedTrace, this.entryData, this.entryTypeByLevel);\n }\n return this.compatibilityTracksAppender;\n }\n\n /**\n * Returns the instance of the timeline flame chart data, without\n * adding data to it. In case the timeline data hasn't been instanced\n * creates a new instance and returns it.\n */\n #instantiateTimelineData(): PerfUI.FlameChart.FlameChartTimelineData {\n if (!this.timelineDataInternal) {\n this.timelineDataInternal = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n }\n return this.timelineDataInternal;\n }\n\n /**\n * Builds the flame chart data using the track appenders\n */\n buildFromTrackAppenders(options?: {filterThreadsByName?: string, expandedTracks?: Set}): void {\n if (!this.compatibilityTracksAppender) {\n return;\n }\n const appenders = this.compatibilityTracksAppender.allVisibleTrackAppenders();\n for (const appender of appenders) {\n const skipThreadAppenderByName =\n appender instanceof ThreadAppender && !appender.trackName().includes(options?.filterThreadsByName || '');\n if (skipThreadAppenderByName) {\n continue;\n }\n const expanded = Boolean(options?.expandedTracks?.has(appender.appenderName));\n this.currentLevel = appender.appendTrackAtLevel(this.currentLevel, expanded);\n }\n }\n\n groupTreeEvents(group: PerfUI.FlameChart.Group): Trace.Types.Events.Event[]|null {\n return this.compatibilityTracksAppender?.groupEventsForTreeView(group) ?? null;\n }\n\n mainFrameNavigationStartEvents(): readonly Trace.Types.Events.NavigationStart[] {\n if (!this.parsedTrace) {\n return [];\n }\n return this.parsedTrace.Meta.mainFrameNavigations;\n }\n\n entryTitle(entryIndex: number): string|null {\n const entryType = this.#entryTypeForIndex(entryIndex);\n if (entryType === EntryType.SCREENSHOT) {\n return '';\n }\n if (entryType === EntryType.TRACK_APPENDER) {\n const timelineData = (this.timelineDataInternal as PerfUI.FlameChart.FlameChartTimelineData);\n const eventLevel = timelineData.entryLevels[entryIndex];\n const event = (this.entryData[entryIndex] as Trace.Types.Events.Event);\n return this.compatibilityTracksAppender?.titleForEvent(event, eventLevel) || null;\n }\n let title: Common.UIString.LocalizedString|string = this.entryIndexToTitle[entryIndex];\n if (!title) {\n title = `Unexpected entryIndex ${entryIndex}`;\n console.error(title);\n }\n return title;\n }\n\n textColor(index: number): string {\n const event = this.entryData[index];\n if (!TimelineFlameChartDataProvider.timelineEntryIsTraceEvent(event)) {\n return FlameChartStyle.textColor;\n }\n return this.isIgnoreListedEvent(event) ? '#888' : FlameChartStyle.textColor;\n }\n\n entryFont(_index: number): string|null {\n return this.#font;\n }\n\n // resetCompatibilityTracksAppender boolean set to false does not recreate the thread appenders\n reset(resetCompatibilityTracksAppender: boolean = true): void {\n this.currentLevel = 0;\n this.entryData = [];\n this.entryTypeByLevel = [];\n this.entryIndexToTitle = [];\n this.screenshotImageCache = new Map();\n this.#eventIndexByEvent = new Map();\n if (resetCompatibilityTracksAppender) {\n this.compatibilityTracksAppender = null;\n this.timelineDataInternal = null;\n } else if (!resetCompatibilityTracksAppender && this.timelineDataInternal) {\n this.compatibilityTracksAppender?.setFlameChartDataAndEntryData(\n this.timelineDataInternal, this.entryData, this.entryTypeByLevel);\n this.compatibilityTracksAppender?.threadAppenders().forEach(\n threadAppender => threadAppender.setHeaderAppended(false));\n }\n }\n\n maxStackDepth(): number {\n return this.currentLevel;\n }\n\n /**\n * Builds the flame chart data using the tracks appender (which use\n * the new trace engine) and the legacy code paths present in this\n * file. The result built data is cached and returned.\n */\n timelineData(rebuild: boolean = false): PerfUI.FlameChart.FlameChartTimelineData {\n if (this.timelineDataInternal && this.timelineDataInternal.entryLevels.length !== 0 && !rebuild) {\n // The flame chart data is built already, so return the cached\n // data.\n return this.timelineDataInternal;\n }\n\n this.timelineDataInternal = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n\n if (rebuild) {\n this.reset(/* resetCompatibilityTracksAppender= */ false);\n }\n\n this.currentLevel = 0;\n\n if (this.parsedTrace) {\n this.compatibilityTracksAppender = this.compatibilityTracksAppenderInstance();\n if (this.parsedTrace.Meta.traceIsGeneric) {\n this.#processGenericTrace();\n } else {\n this.#processInspectorTrace();\n }\n }\n return this.timelineDataInternal;\n }\n\n /**\n * Register the groups (aka tracks) with the VisualElements framework so\n * later on we can log when an entry inside this group is selected.\n */\n #processGenericTrace(): void {\n if (!this.compatibilityTracksAppender) {\n return;\n }\n\n const appendersByProcess = this.compatibilityTracksAppender.allThreadAppendersByProcess();\n\n for (const [pid, threadAppenders] of appendersByProcess) {\n const processGroupStyle = this.buildGroupStyle({shareHeaderLine: false});\n const processName = this.parsedTrace?.Meta.processNames.get(pid)?.args.name || 'Process';\n this.appendHeader(`${processName} (${pid})`, processGroupStyle, true, false);\n for (const appender of threadAppenders) {\n appender.setHeaderNestingLevel(1);\n this.currentLevel = appender.appendTrackAtLevel(this.currentLevel);\n }\n }\n }\n\n #processInspectorTrace(): void {\n if (!this.isCpuProfile) {\n // CPU Profiles do not have frames and screenshots.\n this.#appendFramesAndScreenshotsTrack();\n }\n\n const weight = (track: {type?: string, forMainFrame?: boolean, appenderName?: TrackAppenderName}): number => {\n switch (track.appenderName) {\n case 'Animations':\n return 0;\n case 'Timings':\n return 1;\n case 'Interactions':\n return 2;\n case 'LayoutShifts':\n return 3;\n case 'Extension':\n return 4;\n case 'Thread':\n return 5;\n case 'ServerTimings':\n return 6;\n case 'GPU':\n return 7;\n case 'Thread_AuctionWorklet':\n return 8;\n default:\n return 9;\n }\n };\n\n const allTrackAppenders =\n this.compatibilityTracksAppender ? this.compatibilityTracksAppender.allVisibleTrackAppenders() : [];\n\n allTrackAppenders.sort((a, b) => weight(a) - weight(b));\n\n for (const appender of allTrackAppenders) {\n if (!this.parsedTrace) {\n continue;\n }\n\n this.currentLevel = appender.appendTrackAtLevel(this.currentLevel);\n\n // If there is not a selected group, we want to default to selecting the\n // main thread track. Therefore in this check we look to see if the\n // current appender is a ThreadAppender and represnets the Main Thread.\n // If it is, we mark the group as selected.\n if (this.timelineDataInternal && !this.timelineDataInternal.selectedGroup) {\n if (appender instanceof ThreadAppender &&\n (appender.threadType === Trace.Handlers.Threads.ThreadType.MAIN_THREAD ||\n appender.threadType === Trace.Handlers.Threads.ThreadType.CPU_PROFILE)) {\n const group = this.compatibilityTracksAppender?.groupForAppender(appender);\n if (group) {\n this.timelineDataInternal.selectedGroup = group;\n }\n }\n }\n }\n if (this.timelineDataInternal && this.timelineDataInternal.selectedGroup) {\n this.timelineDataInternal.selectedGroup.expanded = true;\n }\n }\n\n minimumBoundary(): number {\n return this.minimumBoundaryInternal;\n }\n\n totalTime(): number {\n return this.timeSpan;\n }\n\n static timelineEntryIsTraceEvent(entry: TimelineFlameChartEntry): entry is Trace.Types.Events.Event {\n return entry instanceof Trace.Handlers.ModelHandlers.Frames.TimelineFrame === false;\n }\n\n search(\n visibleWindow: Trace.Types.Timing.TraceWindowMicroSeconds,\n filter: TimelineModel.TimelineModelFilter.TimelineModelFilter): PerfUI.FlameChart.DataProviderSearchResult[] {\n const results: PerfUI.FlameChart.DataProviderSearchResult[] = [];\n this.timelineData();\n for (let i = 0; i < this.entryData.length; ++i) {\n const entry = this.entryData[i];\n if (!entry) {\n continue;\n }\n\n if (!TimelineFlameChartDataProvider.timelineEntryIsTraceEvent(entry)) {\n // We only search for events, not for frames, hence this early exit.\n continue;\n }\n\n if (Trace.Types.Events.isScreenshot(entry)) {\n // Screenshots are represented as trace events, but you can't search for them, so skip.\n continue;\n }\n if (!Trace.Helpers.Timing.eventIsInBounds(entry, visibleWindow)) {\n continue;\n }\n if (filter.accept(entry, this.parsedTrace || undefined)) {\n const startTimeMilli = Trace.Helpers.Timing.microSecondsToMilliseconds(entry.ts);\n results.push({index: i, startTimeMilli, provider: 'main'});\n }\n }\n return results;\n }\n\n isIgnoreListedEvent(event: Trace.Types.Events.Event): boolean {\n if (Trace.Types.Events.isProfileCall(event)) {\n return this.isIgnoreListedURL(event.callFrame.url as Platform.DevToolsPath.UrlString);\n }\n return false;\n }\n\n private isIgnoreListedURL(url: Platform.DevToolsPath.UrlString): boolean {\n return Bindings.IgnoreListManager.IgnoreListManager.instance().isUserIgnoreListedURL(url);\n }\n\n getEntryTypeForLevel(level: number): EntryType {\n return this.entryTypeByLevel[level];\n }\n\n /**\n * The frames and screenshots track is special cased because it is rendered\n * differently to the rest of the tracks and not as a series of events. This\n * is why it is not done via the appender system; we track frames &\n * screenshots as a different EntryType to the TrackAppender entries,\n * because then when it comes to drawing we can decorate them differently.\n **/\n #appendFramesAndScreenshotsTrack(): void {\n if (!this.parsedTrace) {\n return;\n }\n const filmStrip = Trace.Extras.FilmStrip.fromParsedTrace(this.parsedTrace);\n const hasScreenshots = filmStrip.frames.length > 0;\n\n this.framesHeader.collapsible = hasScreenshots;\n const expanded = Root.Runtime.Runtime.queryParam('flamechart-force-expand') === 'frames';\n\n this.appendHeader(i18nString(UIStrings.frames), this.framesHeader, false /* selectable */, expanded);\n\n this.entryTypeByLevel[this.currentLevel] = EntryType.FRAME;\n for (const frame of this.parsedTrace.Frames.frames) {\n this.#appendNewEngineFrame(frame);\n }\n ++this.currentLevel;\n\n if (!hasScreenshots) {\n return;\n }\n this.#appendScreenshots(filmStrip);\n }\n\n #appendScreenshots(filmStrip: Trace.Extras.FilmStrip.Data): void {\n if (!this.timelineDataInternal || !this.parsedTrace) {\n return;\n }\n this.appendHeader('', this.screenshotsHeader, false /* selectable */);\n this.entryTypeByLevel[this.currentLevel] = EntryType.SCREENSHOT;\n let prevTimestamp: Trace.Types.Timing.MilliSeconds|undefined = undefined;\n\n for (const filmStripFrame of filmStrip.frames) {\n const screenshotTimeInMilliSeconds =\n Trace.Helpers.Timing.microSecondsToMilliseconds(filmStripFrame.screenshotEvent.ts);\n this.entryData.push(filmStripFrame.screenshotEvent);\n (this.timelineDataInternal.entryLevels as number[]).push(this.currentLevel);\n (this.timelineDataInternal.entryStartTimes as number[]).push(screenshotTimeInMilliSeconds);\n if (prevTimestamp) {\n (this.timelineDataInternal.entryTotalTimes as number[]).push(screenshotTimeInMilliSeconds - prevTimestamp);\n }\n prevTimestamp = screenshotTimeInMilliSeconds;\n }\n if (filmStrip.frames.length && prevTimestamp !== undefined) {\n const maxRecordTimeMillis = Trace.Helpers.Timing.traceWindowMilliSeconds(this.parsedTrace.Meta.traceBounds).max;\n\n // Set the total time of the final screenshot so it takes up the remainder of the trace.\n (this.timelineDataInternal.entryTotalTimes as number[]).push(maxRecordTimeMillis - prevTimestamp);\n }\n ++this.currentLevel;\n }\n\n #entryTypeForIndex(entryIndex: number): EntryType {\n const level = this.timelineData().entryLevels[entryIndex];\n return this.entryTypeByLevel[level];\n }\n\n prepareHighlightedEntryInfo(entryIndex: number): Element|null {\n let time = '';\n let title;\n let warningElements: Element[] = [];\n let nameSpanTimelineInfoTime = 'timeline-info-time';\n\n const additionalContent: HTMLElement[] = [];\n\n const entryType = this.#entryTypeForIndex(entryIndex);\n if (entryType === EntryType.TRACK_APPENDER) {\n if (!this.compatibilityTracksAppender) {\n return null;\n }\n const event = (this.entryData[entryIndex] as Trace.Types.Events.Event);\n const timelineData = (this.timelineDataInternal as PerfUI.FlameChart.FlameChartTimelineData);\n const eventLevel = timelineData.entryLevels[entryIndex];\n const highlightedEntryInfo = this.compatibilityTracksAppender.highlightedEntryInfo(event, eventLevel);\n title = highlightedEntryInfo.title;\n time = highlightedEntryInfo.formattedTime;\n warningElements = highlightedEntryInfo.warningElements || warningElements;\n if (Trace.Types.Events.isSyntheticInteraction(event)) {\n const breakdown = new Components.InteractionBreakdown.InteractionBreakdown();\n breakdown.entry = event;\n additionalContent.push(breakdown);\n }\n } else if (entryType === EntryType.FRAME) {\n const frame = (this.entryData[entryIndex] as Trace.Handlers.ModelHandlers.Frames.TimelineFrame);\n time =\n i18n.TimeUtilities.preciseMillisToString(Trace.Helpers.Timing.microSecondsToMilliseconds(frame.duration), 1);\n\n if (frame.idle) {\n title = i18nString(UIStrings.idleFrame);\n } else if (frame.dropped) {\n if (frame.isPartial) {\n title = i18nString(UIStrings.partiallyPresentedFrame);\n } else {\n title = i18nString(UIStrings.droppedFrame);\n }\n nameSpanTimelineInfoTime = 'timeline-info-warning';\n } else {\n title = i18nString(UIStrings.frame);\n }\n } else {\n return null;\n }\n\n const element = document.createElement('div');\n const root = UI.UIUtils.createShadowRootWithCoreStyles(element, {\n cssFile: [timelineFlamechartPopoverStyles],\n delegatesFocus: undefined,\n });\n const contents = root.createChild('div', 'timeline-flamechart-popover');\n contents.createChild('span', nameSpanTimelineInfoTime).textContent = time;\n contents.createChild('span', 'timeline-info-title').textContent = title;\n if (warningElements) {\n for (const warningElement of warningElements) {\n warningElement.classList.add('timeline-info-warning');\n contents.appendChild(warningElement);\n }\n }\n for (const elem of additionalContent) {\n contents.appendChild(elem);\n }\n return element;\n }\n\n prepareHighlightedHiddenEntriesArrowInfo(entryIndex: number): Element|null {\n const element = document.createElement('div');\n const root = UI.UIUtils.createShadowRootWithCoreStyles(element, {\n cssFile: [timelineFlamechartPopoverStyles],\n delegatesFocus: undefined,\n });\n\n const entry = this.entryData[entryIndex] as Trace.Types.Events.Event;\n const hiddenEntriesAmount =\n ModificationsManager.activeManager()?.getEntriesFilter().findHiddenDescendantsAmount(entry);\n\n if (!hiddenEntriesAmount) {\n return null;\n }\n const contents = root.createChild('div', 'timeline-flamechart-popover');\n contents.createChild('span', 'timeline-info-title').textContent = hiddenEntriesAmount + ' hidden';\n\n return element;\n }\n\n getDrawOverride(entryIndex: number): DrawOverride|undefined {\n const entryType = this.#entryTypeForIndex(entryIndex);\n if (entryType !== EntryType.TRACK_APPENDER) {\n return;\n }\n\n const timelineData = (this.timelineDataInternal as PerfUI.FlameChart.FlameChartTimelineData);\n const eventLevel = timelineData.entryLevels[entryIndex];\n const event = (this.entryData[entryIndex] as Trace.Types.Events.Event);\n return this.compatibilityTracksAppender?.getDrawOverride(event, eventLevel);\n }\n\n entryColor(entryIndex: number): string {\n const entryType = this.#entryTypeForIndex(entryIndex);\n if (entryType === EntryType.FRAME) {\n return 'white';\n }\n if (entryType === EntryType.TRACK_APPENDER) {\n const timelineData = (this.timelineDataInternal as PerfUI.FlameChart.FlameChartTimelineData);\n const eventLevel = timelineData.entryLevels[entryIndex];\n const event = (this.entryData[entryIndex] as Trace.Types.Events.Event);\n return this.compatibilityTracksAppender?.colorForEvent(event, eventLevel) || '';\n }\n return '';\n }\n\n private preparePatternCanvas(): void {\n // Set the candy stripe pattern to 17px so it repeats well.\n const size = 17;\n this.droppedFramePatternCanvas.width = size;\n this.droppedFramePatternCanvas.height = size;\n\n this.partialFramePatternCanvas.width = size;\n this.partialFramePatternCanvas.height = size;\n\n const ctx = this.droppedFramePatternCanvas.getContext('2d');\n if (ctx) {\n // Make a dense solid-line pattern.\n ctx.translate(size * 0.5, size * 0.5);\n ctx.rotate(Math.PI * 0.25);\n ctx.translate(-size * 0.5, -size * 0.5);\n\n ctx.fillStyle = 'rgb(255, 255, 255)';\n for (let x = -size; x < size * 2; x += 3) {\n ctx.fillRect(x, -size, 1, size * 3);\n }\n }\n\n const ctx2 = this.partialFramePatternCanvas.getContext('2d');\n if (ctx2) {\n // Make a sparse dashed-line pattern.\n ctx2.strokeStyle = 'rgb(255, 255, 255)';\n ctx2.lineWidth = 2;\n ctx2.beginPath();\n ctx2.moveTo(17, 0);\n ctx2.lineTo(10, 7);\n ctx2.moveTo(8, 9);\n ctx2.lineTo(2, 15);\n ctx2.stroke();\n }\n }\n\n private drawFrame(\n entryIndex: number, context: CanvasRenderingContext2D, text: string|null, barX: number, barY: number,\n barWidth: number, barHeight: number): void {\n const hPadding = 1;\n const frame = (this.entryData[entryIndex] as Trace.Handlers.ModelHandlers.Frames.TimelineFrame);\n barX += hPadding;\n barWidth -= 2 * hPadding;\n if (frame.idle) {\n context.fillStyle = 'white';\n } else if (frame.dropped) {\n if (frame.isPartial) {\n // For partially presented frame boxes, paint a yellow background with\n // a sparse white dashed-line pattern overlay.\n context.fillStyle = '#f0e442';\n context.fillRect(barX, barY, barWidth, barHeight);\n\n const overlay = context.createPattern(this.partialFramePatternCanvas, 'repeat');\n context.fillStyle = overlay || context.fillStyle;\n } else {\n // For dropped frame boxes, paint a red background with a dense white\n // solid-line pattern overlay.\n context.fillStyle = '#f08080';\n context.fillRect(barX, barY, barWidth, barHeight);\n\n const overlay = context.createPattern(this.droppedFramePatternCanvas, 'repeat');\n context.fillStyle = overlay || context.fillStyle;\n }\n } else {\n context.fillStyle = '#d7f0d1';\n }\n context.fillRect(barX, barY, barWidth, barHeight);\n\n const frameDurationText =\n i18n.TimeUtilities.preciseMillisToString(Trace.Helpers.Timing.microSecondsToMilliseconds(frame.duration), 1);\n const textWidth = context.measureText(frameDurationText).width;\n if (textWidth <= barWidth) {\n context.fillStyle = this.textColor(entryIndex);\n context.fillText(frameDurationText, barX + (barWidth - textWidth) / 2, barY + barHeight - 4);\n }\n }\n\n private async drawScreenshot(\n entryIndex: number, context: CanvasRenderingContext2D, barX: number, barY: number, barWidth: number,\n barHeight: number): Promise {\n const screenshot = (this.entryData[entryIndex] as Trace.Types.Events.SyntheticScreenshot);\n if (!this.screenshotImageCache.has(screenshot)) {\n this.screenshotImageCache.set(screenshot, null);\n const data = screenshot.args.dataUri;\n const image = await UI.UIUtils.loadImage(data);\n this.screenshotImageCache.set(screenshot, image);\n this.dispatchEventToListeners(Events.DATA_CHANGED);\n return;\n }\n\n const image = this.screenshotImageCache.get(screenshot);\n if (!image) {\n return;\n }\n const imageX = barX + 1;\n const imageY = barY + 1;\n const imageHeight = barHeight - 2;\n const scale = imageHeight / image.naturalHeight;\n const imageWidth = Math.floor(image.naturalWidth * scale);\n context.save();\n context.beginPath();\n context.rect(barX, barY, barWidth, barHeight);\n context.clip();\n context.drawImage(image, imageX, imageY, imageWidth, imageHeight);\n context.strokeStyle = '#ccc';\n context.strokeRect(imageX - 0.5, imageY - 0.5, Math.min(barWidth - 1, imageWidth + 1), imageHeight);\n context.restore();\n }\n\n decorateEntry(\n entryIndex: number, context: CanvasRenderingContext2D, text: string|null, barX: number, barY: number,\n barWidth: number, barHeight: number, unclippedBarX: number, timeToPixelRatio: number): boolean {\n const entryType = this.#entryTypeForIndex(entryIndex);\n\n if (entryType === EntryType.FRAME) {\n this.drawFrame(entryIndex, context, text, barX, barY, barWidth, barHeight);\n return true;\n }\n\n if (entryType === EntryType.SCREENSHOT) {\n void this.drawScreenshot(entryIndex, context, barX, barY, barWidth, barHeight);\n return true;\n }\n\n if (entryType === EntryType.TRACK_APPENDER) {\n const entry = this.entryData[entryIndex] as Trace.Types.Events.Event;\n if (Trace.Types.Events.isSyntheticInteraction(entry)) {\n this.#drawInteractionEventWithWhiskers(\n context, entryIndex, text, entry, barX, barY, unclippedBarX, barWidth, barHeight, timeToPixelRatio);\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Draws the left and right whiskers around an interaction in the timeline.\n * @param context - the canvas that will be drawn onto\n * @param entryIndex\n * @param entryTitle - the title of the entry\n * @param entry - the entry itself\n * @param barX - the starting X pixel position of the bar representing this event. This is clipped: if the bar is off the left side of the screen, this value will be 0\n * @param barY - the starting Y pixel position of the bar representing this event.\n * @param unclippedBarXStartPixel - the starting X pixel position of the bar representing this event, not clipped. This means if the bar is off the left of the screen this will be a negative number.\n * @param barWidth - the width of the full bar in pixels\n * @param barHeight - the height of the full bar in pixels\n * @param timeToPixelRatio - the ratio required to convert a millisecond time to a pixel value.\n **/\n #drawInteractionEventWithWhiskers(\n context: CanvasRenderingContext2D, entryIndex: number, entryTitle: string|null,\n entry: Trace.Types.Events.SyntheticInteractionPair, barX: number, barY: number, unclippedBarXStartPixel: number,\n barWidth: number, barHeight: number, timeToPixelRatio: number): void {\n /**\n * An interaction is drawn with whiskers as so:\n * |----------[=======]-------------|\n * => The left whisker is the event's start time (event.ts)\n * => The box start is the event's processingStart time\n * => The box end is the event's processingEnd time\n * => The right whisker is the event's end time (event.ts + event.dur)\n *\n * When we draw the event in the InteractionsAppender, we draw a huge box\n * that spans the entire of the above. So here we need to draw over the\n * rectangle that is outside of {processingStart, processingEnd} and\n * replace it with the whiskers.\n * TODO(crbug.com/1495248): rework how we draw whiskers to avoid this inefficiency\n */\n\n const beginTime = Trace.Helpers.Timing.microSecondsToMilliseconds(entry.ts);\n const entireBarEndXPixel = barX + barWidth;\n\n function timeToPixel(time: Trace.Types.Timing.MicroSeconds): number {\n const timeMilli = Trace.Helpers.Timing.microSecondsToMilliseconds(time);\n return Math.floor(unclippedBarXStartPixel + (timeMilli - beginTime) * timeToPixelRatio);\n }\n\n context.save();\n\n // Clear portions of initial rect to prepare for the ticks.\n context.fillStyle = ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-cdt-base-container');\n let desiredBoxStartX = timeToPixel(entry.processingStart);\n const desiredBoxEndX = timeToPixel(entry.processingEnd);\n\n // If the entry has no processing duration, ensure the box is 1px wide so at least it is visible.\n if (entry.processingEnd - entry.processingStart === 0) {\n desiredBoxStartX -= 1;\n }\n\n context.fillRect(barX, barY - 0.5, desiredBoxStartX - barX, barHeight);\n context.fillRect(desiredBoxEndX, barY - 0.5, entireBarEndXPixel - desiredBoxEndX, barHeight);\n\n // Draws left and right whiskers\n function drawTick(begin: number, end: number, y: number): void {\n const tickHeightPx = 6;\n context.moveTo(begin, y - tickHeightPx / 2);\n context.lineTo(begin, y + tickHeightPx / 2);\n context.moveTo(begin, y);\n context.lineTo(end, y);\n }\n\n // The left whisker starts at the enty timestamp, and continues until the start of the box (processingStart).\n const leftWhiskerX = timeToPixel(entry.ts);\n // The right whisker ends at (entry.ts + entry.dur). We draw the line from the end of the box (processingEnd).\n const rightWhiskerX = timeToPixel(Trace.Types.Timing.MicroSeconds(entry.ts + entry.dur));\n context.beginPath();\n context.lineWidth = 1;\n context.strokeStyle = '#ccc';\n const lineY = Math.floor(barY + barHeight / 2) + 0.5;\n const leftTick = leftWhiskerX + 0.5;\n const rightTick = rightWhiskerX - 0.5;\n drawTick(leftTick, desiredBoxStartX, lineY);\n drawTick(rightTick, desiredBoxEndX, lineY);\n context.stroke();\n\n if (entryTitle) {\n // BarX will be set to 0 if the start of the box if off the screen to the\n // left. If this happens, the desiredBoxStartX will be negative. In that\n // case, we fallback to the BarX. This ensures that even if the box\n // starts off-screen, we draw the text at the first visible on screen\n // pixels, so the user can still see the event's title.\n const textStartX = desiredBoxStartX > 0 ? desiredBoxStartX : barX;\n context.font = this.#font;\n const textWidth = UI.UIUtils.measureTextWidth(context, entryTitle);\n\n // These numbers are duplicated from FlameChart.ts.\n const textPadding = 5;\n const textBaseline = 5;\n\n // Only draw the text if it can fit in the amount of box that is visible.\n if (textWidth <= desiredBoxEndX - textStartX + textPadding) {\n context.fillStyle = this.textColor(entryIndex);\n context.fillText(entryTitle, textStartX + textPadding, barY + barHeight - textBaseline);\n }\n }\n context.restore();\n }\n\n forceDecoration(entryIndex: number): boolean {\n const entryType = this.#entryTypeForIndex(entryIndex);\n if (entryType === EntryType.FRAME) {\n return true;\n }\n if (entryType === EntryType.SCREENSHOT) {\n return true;\n }\n const event = (this.entryData[entryIndex] as Trace.Types.Events.Event);\n\n if (Trace.Types.Events.isSyntheticInteraction(event)) {\n // We draw interactions with whiskers, which are done via the\n // decorateEntry() method, hence we always want to force these to be\n // decorated.\n return true;\n }\n return Boolean(this.parsedTrace?.Warnings.perEvent.get(event));\n }\n\n private appendHeader(title: string, style: PerfUI.FlameChart.GroupStyle, selectable: boolean, expanded?: boolean):\n PerfUI.FlameChart.Group {\n const group =\n ({startLevel: this.currentLevel, name: title, style, selectable, expanded} as PerfUI.FlameChart.Group);\n (this.timelineDataInternal as PerfUI.FlameChart.FlameChartTimelineData).groups.push(group);\n return group;\n }\n\n #appendNewEngineFrame(frame: Trace.Handlers.ModelHandlers.Frames.TimelineFrame): void {\n const index = this.entryData.length;\n this.entryData.push(frame);\n const durationMilliseconds = Trace.Helpers.Timing.microSecondsToMilliseconds(frame.duration);\n this.entryIndexToTitle[index] = i18n.TimeUtilities.millisToString(durationMilliseconds, true);\n if (!this.timelineDataInternal) {\n return;\n }\n this.timelineDataInternal.entryLevels[index] = this.currentLevel;\n this.timelineDataInternal.entryTotalTimes[index] = durationMilliseconds;\n this.timelineDataInternal.entryStartTimes[index] = Trace.Helpers.Timing.microSecondsToMilliseconds(frame.startTime);\n }\n\n createSelection(entryIndex: number): TimelineSelection|null {\n const entryType = this.#entryTypeForIndex(entryIndex);\n let timelineSelection: TimelineSelection|null = null;\n const entry = this.entryData[entryIndex];\n if (entry && TimelineFlameChartDataProvider.timelineEntryIsTraceEvent(entry)) {\n timelineSelection = TimelineSelection.fromTraceEvent(entry);\n } else if (entryType === EntryType.FRAME) {\n timelineSelection = TimelineSelection.fromFrame(\n (this.entryData[entryIndex] as Trace.Handlers.ModelHandlers.Frames.TimelineFrame));\n }\n if (timelineSelection) {\n this.lastSelection = new Selection(timelineSelection, entryIndex);\n }\n return timelineSelection;\n }\n\n formatValue(value: number, precision?: number): string {\n return i18n.TimeUtilities.preciseMillisToString(value, precision);\n }\n\n groupForEvent(entryIndex: number): PerfUI.FlameChart.Group|null {\n if (!this.compatibilityTracksAppender) {\n return null;\n }\n const level = this.timelineDataInternal?.entryLevels[entryIndex] ?? null;\n if (level === null) {\n return null;\n }\n const groupForLevel = this.compatibilityTracksAppender.groupForLevel(level);\n if (!groupForLevel) {\n return null;\n }\n return groupForLevel;\n }\n\n canJumpToEntry(_entryIndex: number): boolean {\n return false;\n }\n\n entryIndexForSelection(selection: TimelineSelection|null): number {\n if (!selection || TimelineSelection.isRangeSelection(selection.object) ||\n TimelineSelection.isSyntheticNetworkRequestDetailsEventSelection(selection.object)) {\n return -1;\n }\n\n if (this.lastSelection && this.lastSelection.timelineSelection.object === selection.object) {\n return this.lastSelection.entryIndex;\n }\n\n // If the index is -1 and the selection is a TraceEvent, it might be\n // the case that this Entry is hidden by the Context Menu action.\n // Try revealing the entry and getting the index again.\n if (this.entryData.indexOf(selection.object) === -1 && TimelineSelection.isSelection(selection.object)) {\n if (this.timelineDataInternal?.selectedGroup) {\n ModificationsManager.activeManager()?.getEntriesFilter().revealEntry(\n selection.object as Trace.Types.Events.Event);\n this.timelineData(true);\n }\n }\n\n const index = this.entryData.indexOf(selection.object);\n if (index !== -1) {\n this.lastSelection = new Selection(selection, index);\n }\n return index;\n }\n\n /**\n * Return the index for the given entry. Note that this method assumes that\n * timelineData() has been generated. If it hasn't, this method will return\n * null.\n */\n indexForEvent(targetEvent: Trace.Types.Events.Event|Trace.Handlers.ModelHandlers.Frames.TimelineFrame): number|null {\n // Gets the index for the given event by walking through the array of entryData.\n // This may seem inefficient - but we have seen that by building up large\n // maps keyed by trace events that this has a significant impact on the\n // performance of the panel.\n // Therefore, we strike a middle ground: look up the event the first time,\n // but then cache the result.\n const fromCache = this.#eventIndexByEvent.get(targetEvent);\n if (typeof fromCache === 'number') {\n return fromCache;\n }\n const index = this.entryData.indexOf(targetEvent);\n const result = index > -1 ? index : null;\n this.#eventIndexByEvent.set(targetEvent, result);\n return result;\n }\n\n /**\n * Build the data for initiators and initiated entries.\n * @param entryIndex\n * @returns if we should re-render the flame chart (canvas)\n */\n buildFlowForInitiator(entryIndex: number): boolean {\n if (!this.parsedTrace) {\n return false;\n }\n if (!this.timelineDataInternal) {\n return false;\n }\n if (this.lastInitiatorEntry === entryIndex) {\n if (this.lastInitiatorsData) {\n this.timelineDataInternal.initiatorsData = this.lastInitiatorsData;\n }\n return false;\n }\n if (!this.compatibilityTracksAppender) {\n return false;\n }\n\n // Remove all previously assigned decorations indicating that the flow event entries are hidden\n const previousInitiatorsDataLength = this.timelineDataInternal.initiatorsData.length;\n // |entryIndex| equals -1 means there is no entry selected, just clear the\n // initiator cache if there is any previous arrow and return true to\n // re-render.\n if (entryIndex === -1) {\n this.lastInitiatorEntry = entryIndex;\n if (previousInitiatorsDataLength === 0) {\n // This means there is no arrow before, so we don't need to re-render.\n return false;\n }\n // Reset to clear any previous arrows from the last event.\n this.timelineDataInternal.resetFlowData();\n return true;\n }\n\n const entryType = this.#entryTypeForIndex(entryIndex);\n if (entryType !== EntryType.TRACK_APPENDER) {\n return false;\n }\n const event = this.entryData[entryIndex] as Trace.Types.Events.Event;\n // Reset to clear any previous arrows from the last event.\n this.timelineDataInternal.resetFlowData();\n this.lastInitiatorEntry = entryIndex;\n\n const hiddenEvents: Trace.Types.Events.Event[] =\n ModificationsManager.activeManager()?.getEntriesFilter().invisibleEntries() ?? [];\n const expandableEntries: Trace.Types.Events.Event[] =\n ModificationsManager.activeManager()?.getEntriesFilter().expandableEntries() ?? [];\n\n const initiatorsData = initiatorsDataToDraw(\n this.parsedTrace,\n event,\n hiddenEvents,\n expandableEntries,\n );\n // This means there is no change for arrows.\n if (previousInitiatorsDataLength === 0 && initiatorsData.length === 0) {\n return false;\n }\n for (const initiatorData of initiatorsData) {\n const eventIndex = this.indexForEvent(initiatorData.event);\n const initiatorIndex = this.indexForEvent(initiatorData.initiator);\n if (eventIndex === null || initiatorIndex === null) {\n continue;\n }\n this.timelineDataInternal.initiatorsData.push({\n initiatorIndex,\n eventIndex,\n isInitiatorHidden: initiatorData.isInitiatorHidden,\n isEntryHidden: initiatorData.isEntryHidden,\n });\n }\n this.lastInitiatorsData = this.timelineDataInternal.initiatorsData;\n return true;\n }\n\n eventByIndex(entryIndex: number): Trace.Types.Events.Event|Trace.Handlers.ModelHandlers.Frames.TimelineFrame|null {\n if (entryIndex < 0) {\n return null;\n }\n const entryType = this.#entryTypeForIndex(entryIndex);\n if (entryType === EntryType.TRACK_APPENDER) {\n return this.entryData[entryIndex] as Trace.Types.Events.Event;\n }\n if (entryType === EntryType.FRAME) {\n return this.entryData[entryIndex] as Trace.Handlers.ModelHandlers.Frames.TimelineFrame;\n }\n return null;\n }\n}\n\nexport const InstantEventVisibleDurationMs = Trace.Types.Timing.MilliSeconds(0.001);\n\nexport const enum Events {\n DATA_CHANGED = 'DataChanged',\n}\n\nexport type EventTypes = {\n [Events.DATA_CHANGED]: void,\n};\n\n// an entry is a trace event, they are classified into \"entry types\"\n// because some events are rendered differently. For example, screenshot\n// events are rendered as images. Checks for entry types allow to have\n// different styles, names, etc. for events that look differently.\n// In the future we won't have this checks: instead we will forward\n// the event to the corresponding \"track appender\" and it will determine\n// how the event shall be rendered.\nexport const enum EntryType {\n FRAME = 'Frame',\n TRACK_APPENDER = 'TrackAppender',\n SCREENSHOT = 'Screenshot',\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineFlameChartDataProvider.test.js b/public/panels/timeline/TimelineFlameChartDataProvider.test.js index abb3267d1..c30802545 100644 --- a/public/panels/timeline/TimelineFlameChartDataProvider.test.js +++ b/public/panels/timeline/TimelineFlameChartDataProvider.test.js @@ -1,7 +1,7 @@ // 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 * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import { describeWithEnvironment } from '../../testing/EnvironmentHelpers.js'; import { setupIgnoreListManagerEnvironment } from '../../testing/TraceHelpers.js'; import { TraceLoader } from '../../testing/TraceLoader.js'; @@ -11,19 +11,19 @@ describeWithEnvironment('TimelineFlameChartDataProvider', function () { describe('groupTreeEvents', function () { it('returns the correct events for tree views given a flame chart group', async function () { const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider(); - const { traceData } = await TraceLoader.traceEngine(this, 'sync-like-timings.json.gz'); - dataProvider.setModel(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'sync-like-timings.json.gz'); + dataProvider.setModel(parsedTrace); const timingsTrackGroup = dataProvider.timelineData().groups.find(g => g.name === 'Timings'); if (!timingsTrackGroup) { assert.fail('Could not find Timings track flame chart group'); } const groupTreeEvents = dataProvider.groupTreeEvents(timingsTrackGroup); const allTimingEvents = [ - ...traceData.UserTimings.consoleTimings, - ...traceData.UserTimings.timestampEvents, - ...traceData.UserTimings.performanceMarks, - ...traceData.UserTimings.performanceMeasures, - ...traceData.PageLoadMetrics.allMarkerEvents.toSorted((m1, m2) => { + ...parsedTrace.UserTimings.consoleTimings, + ...parsedTrace.UserTimings.timestampEvents, + ...parsedTrace.UserTimings.performanceMarks, + ...parsedTrace.UserTimings.performanceMeasures, + ...parsedTrace.PageLoadMetrics.allMarkerEvents.toSorted((m1, m2) => { // These get sorted based on the metric so we have to replicate // that for this assertion. return Timeline.TimingsTrackAppender.SORT_ORDER_PAGE_LOAD_MARKERS[m1.name] - @@ -34,23 +34,23 @@ describeWithEnvironment('TimelineFlameChartDataProvider', function () { }); it('filters out async events if they cannot be added to the tree', async function () { const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider(); - const { traceData } = await TraceLoader.traceEngine(this, 'timings-track.json.gz'); - dataProvider.setModel(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'timings-track.json.gz'); + dataProvider.setModel(parsedTrace); const timingsTrackGroup = dataProvider.timelineData().groups.find(g => g.name === 'Timings'); if (!timingsTrackGroup) { assert.fail('Could not find Timings track flame chart group'); } const groupTreeEvents = dataProvider.groupTreeEvents(timingsTrackGroup); assert.strictEqual(groupTreeEvents?.length, 12); - const allEventsAreSync = groupTreeEvents?.every(event => !TraceEngine.Types.TraceEvents.isAsyncPhase(event.ph)); + const allEventsAreSync = groupTreeEvents?.every(event => !Trace.Types.Events.isPhaseAsync(event.ph)); assert.isTrue(allEventsAreSync); }); }); it('can provide the index for an event and the event for a given index', async function () { setupIgnoreListManagerEnvironment(); const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider(); - const { traceData } = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz'); - dataProvider.setModel(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz'); + dataProvider.setModel(parsedTrace); // Need to use an index that is not a frame, so jump past the frames. const event = dataProvider.eventByIndex(100); assert.isOk(event); @@ -59,8 +59,8 @@ describeWithEnvironment('TimelineFlameChartDataProvider', function () { it('renders track in the correct order by default', async function () { setupIgnoreListManagerEnvironment(); const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider(); - const { traceData } = await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz'); - dataProvider.setModel(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz'); + dataProvider.setModel(parsedTrace); const groupNames = dataProvider.timelineData().groups.map(g => g.name); assert.deepEqual(groupNames, [ 'Frames', @@ -81,11 +81,11 @@ describeWithEnvironment('TimelineFlameChartDataProvider', function () { it('can return the FlameChart group for a given event', async function () { setupIgnoreListManagerEnvironment(); const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider(); - const { traceData } = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz'); - dataProvider.setModel(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz'); + dataProvider.setModel(parsedTrace); // Force the track appenders to run and populate the chart data. dataProvider.timelineData(); - const longest = traceData.UserInteractions.longestInteractionEvent; + const longest = parsedTrace.UserInteractions.longestInteractionEvent; assert.isOk(longest); const index = dataProvider.indexForEvent(longest); assert.isNotNull(index); @@ -95,8 +95,8 @@ describeWithEnvironment('TimelineFlameChartDataProvider', function () { it('adds candy stripe and triangle decorations to long tasks in the main thread', async function () { setupIgnoreListManagerEnvironment(); const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider(); - const { traceData } = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz'); - dataProvider.setModel(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz'); + dataProvider.setModel(parsedTrace); dataProvider.timelineData(); const { entryDecorations } = dataProvider.timelineData(); const stripingTitles = []; @@ -123,8 +123,8 @@ describeWithEnvironment('TimelineFlameChartDataProvider', function () { }); it('populates the frames track with frames and screenshots', async function () { const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider(); - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - dataProvider.setModel(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + dataProvider.setModel(parsedTrace); const framesTrack = dataProvider.timelineData().groups.find(g => { return g.name.includes('Frames'); }); @@ -144,8 +144,8 @@ describeWithEnvironment('TimelineFlameChartDataProvider', function () { it('removes entries from the data that match the ignored URL', async function () { const { ignoreListManager } = setupIgnoreListManagerEnvironment(); const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider(); - const { traceData } = await TraceLoader.traceEngine(this, 'react-hello-world.json.gz'); - dataProvider.setModel(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'react-hello-world.json.gz'); + dataProvider.setModel(parsedTrace); const eventCountBeforeIgnoreList = dataProvider.timelineData().entryStartTimes.length; const SCRIPT_TO_IGNORE = 'https://unpkg.com/react@18.2.0/umd/react.development.js'; // Clear the data provider cache and add the React script to the ignore list. @@ -164,9 +164,9 @@ describeWithEnvironment('TimelineFlameChartDataProvider', function () { }); it('filters navigations to only return those that happen on the main frame', async function () { const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider(); - const { traceData } = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz'); - dataProvider.setModel(traceData); - const mainFrameID = traceData.Meta.mainFrameId; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz'); + dataProvider.setModel(parsedTrace); + const mainFrameID = parsedTrace.Meta.mainFrameId; const navigationEvents = dataProvider.mainFrameNavigationStartEvents(); // Ensure that every navigation event that we return is for the main frame. assert.isTrue(navigationEvents.every(navEvent => { @@ -175,9 +175,9 @@ describeWithEnvironment('TimelineFlameChartDataProvider', function () { }); it('can search for entries within a given time-range', async function () { const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider(); - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); - dataProvider.setModel(traceData); - const bounds = traceData.Meta.traceBounds; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); + dataProvider.setModel(parsedTrace); + const bounds = parsedTrace.Meta.traceBounds; const filter = new Timeline.TimelineFilters.TimelineRegExp(/Evaluate script/); const results = dataProvider.search(bounds, filter); assert.lengthOf(results, 12); diff --git a/public/panels/timeline/TimelineFlameChartDataProvider.test.js.map b/public/panels/timeline/TimelineFlameChartDataProvider.test.js.map index 3fbcd05ee..68b99d9c3 100644 --- a/public/panels/timeline/TimelineFlameChartDataProvider.test.js.map +++ b/public/panels/timeline/TimelineFlameChartDataProvider.test.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineFlameChartDataProvider.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineFlameChartDataProvider.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Platform from '../../core/platform/platform.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {setupIgnoreListManagerEnvironment} from '../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\nimport * as PerfUi from '../../ui/legacy/components/perf_ui/perf_ui.js';\n\nimport * as Timeline from './timeline.js';\n\ndescribeWithEnvironment('TimelineFlameChartDataProvider', function() {\n describe('groupTreeEvents', function() {\n it('returns the correct events for tree views given a flame chart group', async function() {\n const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();\n const {traceData} = await TraceLoader.traceEngine(this, 'sync-like-timings.json.gz');\n dataProvider.setModel(traceData);\n const timingsTrackGroup = dataProvider.timelineData().groups.find(g => g.name === 'Timings');\n if (!timingsTrackGroup) {\n assert.fail('Could not find Timings track flame chart group');\n }\n const groupTreeEvents = dataProvider.groupTreeEvents(timingsTrackGroup);\n const allTimingEvents = [\n ...traceData.UserTimings.consoleTimings,\n ...traceData.UserTimings.timestampEvents,\n ...traceData.UserTimings.performanceMarks,\n ...traceData.UserTimings.performanceMeasures,\n ...traceData.PageLoadMetrics.allMarkerEvents.toSorted((m1, m2) => {\n // These get sorted based on the metric so we have to replicate\n // that for this assertion.\n return Timeline.TimingsTrackAppender.SORT_ORDER_PAGE_LOAD_MARKERS[m1.name] -\n Timeline.TimingsTrackAppender.SORT_ORDER_PAGE_LOAD_MARKERS[m2.name];\n }),\n ].sort((a, b) => a.ts - b.ts);\n assert.deepEqual(groupTreeEvents, allTimingEvents);\n });\n\n it('filters out async events if they cannot be added to the tree', async function() {\n const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();\n const {traceData} = await TraceLoader.traceEngine(this, 'timings-track.json.gz');\n dataProvider.setModel(traceData);\n const timingsTrackGroup = dataProvider.timelineData().groups.find(g => g.name === 'Timings');\n if (!timingsTrackGroup) {\n assert.fail('Could not find Timings track flame chart group');\n }\n const groupTreeEvents = dataProvider.groupTreeEvents(timingsTrackGroup);\n assert.strictEqual(groupTreeEvents?.length, 12);\n const allEventsAreSync = groupTreeEvents?.every(event => !TraceEngine.Types.TraceEvents.isAsyncPhase(event.ph));\n assert.isTrue(allEventsAreSync);\n });\n });\n\n it('can provide the index for an event and the event for a given index', async function() {\n setupIgnoreListManagerEnvironment();\n const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();\n const {traceData} = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz');\n dataProvider.setModel(traceData);\n\n // Need to use an index that is not a frame, so jump past the frames.\n const event = dataProvider.eventByIndex(100);\n assert.isOk(event);\n assert.strictEqual(dataProvider.indexForEvent(event), 100);\n });\n it('renders track in the correct order by default', async function() {\n setupIgnoreListManagerEnvironment();\n const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();\n const {traceData} = await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz');\n dataProvider.setModel(traceData);\n const groupNames = dataProvider.timelineData().groups.map(g => g.name);\n assert.deepEqual(\n groupNames,\n [\n 'Frames',\n 'Timings',\n 'Interactions',\n 'A track group — Custom track',\n 'Another Extension Track',\n 'An Extension Track — Custom track',\n 'Main — http://localhost:3000/',\n 'Thread pool',\n 'Thread pool worker 1',\n 'Thread pool worker 2',\n 'Thread pool worker 3',\n 'StackSamplingProfiler',\n 'GPU',\n ],\n );\n });\n\n it('can return the FlameChart group for a given event', async function() {\n setupIgnoreListManagerEnvironment();\n const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();\n const {traceData} = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz');\n dataProvider.setModel(traceData);\n // Force the track appenders to run and populate the chart data.\n dataProvider.timelineData();\n\n const longest = traceData.UserInteractions.longestInteractionEvent;\n assert.isOk(longest);\n const index = dataProvider.indexForEvent(longest);\n assert.isNotNull(index);\n const group = dataProvider.groupForEvent(index);\n assert.strictEqual(group?.name, 'Interactions');\n });\n\n it('adds candy stripe and triangle decorations to long tasks in the main thread', async function() {\n setupIgnoreListManagerEnvironment();\n const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();\n const {traceData} = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz');\n dataProvider.setModel(traceData);\n dataProvider.timelineData();\n\n const {entryDecorations} = dataProvider.timelineData();\n const stripingTitles: string[] = [];\n const triangleTitles: string[] = [];\n\n Object.entries(entryDecorations).forEach(([index, decorationsForEvent]) => {\n const entryTitle = dataProvider.entryTitle(parseInt(index, 10)) ?? '';\n for (const decoration of decorationsForEvent) {\n if (decoration.type === PerfUi.FlameChart.FlameChartDecorationType.CANDY) {\n stripingTitles.push(entryTitle);\n }\n if (decoration.type === PerfUi.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE) {\n triangleTitles.push(entryTitle);\n }\n }\n });\n\n assert.deepEqual(stripingTitles, [\n 'Pointer', // The interaction event in the Interactions track for the pointer event.\n 'Task', // The same long task as above, but rendered by the new engine.\n ]);\n assert.deepEqual(triangleTitles, [\n 'Pointer', // The interaction event in the Interactions track for the pointer event.\n 'Task', // The same long task as above, but rendered by the new engine.\n ]);\n });\n\n it('populates the frames track with frames and screenshots', async function() {\n const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n dataProvider.setModel(traceData);\n const framesTrack = dataProvider.timelineData().groups.find(g => {\n return g.name.includes('Frames');\n });\n if (!framesTrack) {\n throw new Error('Could not find expected Frames track');\n }\n const framesLevel = framesTrack.startLevel;\n const screenshotsLevel = framesLevel + 1;\n // The frames track first shows the frames, and then shows screenhots just below it.\n assert.strictEqual(\n dataProvider.getEntryTypeForLevel(framesLevel), Timeline.TimelineFlameChartDataProvider.EntryType.FRAME);\n assert.strictEqual(\n dataProvider.getEntryTypeForLevel(screenshotsLevel),\n Timeline.TimelineFlameChartDataProvider.EntryType.SCREENSHOT);\n\n // There are 5 screenshots in this trace, so we expect there to be 5 events on the screenshots track level.\n const eventsOnScreenshotsLevel = dataProvider.timelineData().entryLevels.filter(e => e === screenshotsLevel);\n assert.lengthOf(eventsOnScreenshotsLevel, 5);\n });\n\n describe('ignoring frames', function() {\n it('removes entries from the data that match the ignored URL', async function() {\n const {ignoreListManager} = setupIgnoreListManagerEnvironment();\n\n const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();\n const {traceData} = await TraceLoader.traceEngine(this, 'react-hello-world.json.gz');\n dataProvider.setModel(traceData);\n\n const eventCountBeforeIgnoreList = dataProvider.timelineData().entryStartTimes.length;\n\n const SCRIPT_TO_IGNORE =\n 'https://unpkg.com/react@18.2.0/umd/react.development.js' as Platform.DevToolsPath.UrlString;\n // Clear the data provider cache and add the React script to the ignore list.\n dataProvider.reset();\n ignoreListManager.ignoreListURL(SCRIPT_TO_IGNORE);\n\n const eventCountAfterIgnoreList = dataProvider.timelineData().entryStartTimes.length;\n // Ensure that the amount of events we show on the flame chart is less\n // than before, now we have added the React URL to the ignore list.\n assert.isBelow(eventCountAfterIgnoreList, eventCountBeforeIgnoreList);\n\n // Clear the data provider cache and unignore the script again\n dataProvider.reset();\n ignoreListManager.unIgnoreListURL(SCRIPT_TO_IGNORE);\n // Ensure that now we have un-ignored the URL that we get the full set of events again.\n assert.strictEqual(dataProvider.timelineData().entryStartTimes.length, eventCountBeforeIgnoreList);\n });\n });\n\n it('filters navigations to only return those that happen on the main frame', async function() {\n const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();\n const {traceData} = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz');\n\n dataProvider.setModel(traceData);\n\n const mainFrameID = traceData.Meta.mainFrameId;\n const navigationEvents = dataProvider.mainFrameNavigationStartEvents();\n // Ensure that every navigation event that we return is for the main frame.\n assert.isTrue(navigationEvents.every(navEvent => {\n return navEvent.args.frame === mainFrameID;\n }));\n });\n\n it('can search for entries within a given time-range', async function() {\n const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n dataProvider.setModel(traceData);\n\n const bounds = traceData.Meta.traceBounds;\n const filter = new Timeline.TimelineFilters.TimelineRegExp(/Evaluate script/);\n const results = dataProvider.search(bounds, filter);\n assert.lengthOf(results, 12);\n assert.deepEqual(results[0], {index: 154, startTimeMilli: 122411041.395, provider: 'main'});\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"TimelineFlameChartDataProvider.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineFlameChartDataProvider.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Platform from '../../core/platform/platform.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {setupIgnoreListManagerEnvironment} from '../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\nimport * as PerfUi from '../../ui/legacy/components/perf_ui/perf_ui.js';\n\nimport * as Timeline from './timeline.js';\n\ndescribeWithEnvironment('TimelineFlameChartDataProvider', function() {\n describe('groupTreeEvents', function() {\n it('returns the correct events for tree views given a flame chart group', async function() {\n const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'sync-like-timings.json.gz');\n dataProvider.setModel(parsedTrace);\n const timingsTrackGroup = dataProvider.timelineData().groups.find(g => g.name === 'Timings');\n if (!timingsTrackGroup) {\n assert.fail('Could not find Timings track flame chart group');\n }\n const groupTreeEvents = dataProvider.groupTreeEvents(timingsTrackGroup);\n const allTimingEvents = [\n ...parsedTrace.UserTimings.consoleTimings,\n ...parsedTrace.UserTimings.timestampEvents,\n ...parsedTrace.UserTimings.performanceMarks,\n ...parsedTrace.UserTimings.performanceMeasures,\n ...parsedTrace.PageLoadMetrics.allMarkerEvents.toSorted((m1, m2) => {\n // These get sorted based on the metric so we have to replicate\n // that for this assertion.\n return Timeline.TimingsTrackAppender.SORT_ORDER_PAGE_LOAD_MARKERS[m1.name] -\n Timeline.TimingsTrackAppender.SORT_ORDER_PAGE_LOAD_MARKERS[m2.name];\n }),\n ].sort((a, b) => a.ts - b.ts);\n assert.deepEqual(groupTreeEvents, allTimingEvents);\n });\n\n it('filters out async events if they cannot be added to the tree', async function() {\n const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'timings-track.json.gz');\n dataProvider.setModel(parsedTrace);\n const timingsTrackGroup = dataProvider.timelineData().groups.find(g => g.name === 'Timings');\n if (!timingsTrackGroup) {\n assert.fail('Could not find Timings track flame chart group');\n }\n const groupTreeEvents = dataProvider.groupTreeEvents(timingsTrackGroup);\n assert.strictEqual(groupTreeEvents?.length, 12);\n const allEventsAreSync = groupTreeEvents?.every(event => !Trace.Types.Events.isPhaseAsync(event.ph));\n assert.isTrue(allEventsAreSync);\n });\n });\n\n it('can provide the index for an event and the event for a given index', async function() {\n setupIgnoreListManagerEnvironment();\n const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz');\n dataProvider.setModel(parsedTrace);\n\n // Need to use an index that is not a frame, so jump past the frames.\n const event = dataProvider.eventByIndex(100);\n assert.isOk(event);\n assert.strictEqual(dataProvider.indexForEvent(event), 100);\n });\n it('renders track in the correct order by default', async function() {\n setupIgnoreListManagerEnvironment();\n const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz');\n dataProvider.setModel(parsedTrace);\n const groupNames = dataProvider.timelineData().groups.map(g => g.name);\n assert.deepEqual(\n groupNames,\n [\n 'Frames',\n 'Timings',\n 'Interactions',\n 'A track group — Custom track',\n 'Another Extension Track',\n 'An Extension Track — Custom track',\n 'Main — http://localhost:3000/',\n 'Thread pool',\n 'Thread pool worker 1',\n 'Thread pool worker 2',\n 'Thread pool worker 3',\n 'StackSamplingProfiler',\n 'GPU',\n ],\n );\n });\n\n it('can return the FlameChart group for a given event', async function() {\n setupIgnoreListManagerEnvironment();\n const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz');\n dataProvider.setModel(parsedTrace);\n // Force the track appenders to run and populate the chart data.\n dataProvider.timelineData();\n\n const longest = parsedTrace.UserInteractions.longestInteractionEvent;\n assert.isOk(longest);\n const index = dataProvider.indexForEvent(longest);\n assert.isNotNull(index);\n const group = dataProvider.groupForEvent(index);\n assert.strictEqual(group?.name, 'Interactions');\n });\n\n it('adds candy stripe and triangle decorations to long tasks in the main thread', async function() {\n setupIgnoreListManagerEnvironment();\n const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz');\n dataProvider.setModel(parsedTrace);\n dataProvider.timelineData();\n\n const {entryDecorations} = dataProvider.timelineData();\n const stripingTitles: string[] = [];\n const triangleTitles: string[] = [];\n\n Object.entries(entryDecorations).forEach(([index, decorationsForEvent]) => {\n const entryTitle = dataProvider.entryTitle(parseInt(index, 10)) ?? '';\n for (const decoration of decorationsForEvent) {\n if (decoration.type === PerfUi.FlameChart.FlameChartDecorationType.CANDY) {\n stripingTitles.push(entryTitle);\n }\n if (decoration.type === PerfUi.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE) {\n triangleTitles.push(entryTitle);\n }\n }\n });\n\n assert.deepEqual(stripingTitles, [\n 'Pointer', // The interaction event in the Interactions track for the pointer event.\n 'Task', // The same long task as above, but rendered by the new engine.\n ]);\n assert.deepEqual(triangleTitles, [\n 'Pointer', // The interaction event in the Interactions track for the pointer event.\n 'Task', // The same long task as above, but rendered by the new engine.\n ]);\n });\n\n it('populates the frames track with frames and screenshots', async function() {\n const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n dataProvider.setModel(parsedTrace);\n const framesTrack = dataProvider.timelineData().groups.find(g => {\n return g.name.includes('Frames');\n });\n if (!framesTrack) {\n throw new Error('Could not find expected Frames track');\n }\n const framesLevel = framesTrack.startLevel;\n const screenshotsLevel = framesLevel + 1;\n // The frames track first shows the frames, and then shows screenhots just below it.\n assert.strictEqual(\n dataProvider.getEntryTypeForLevel(framesLevel), Timeline.TimelineFlameChartDataProvider.EntryType.FRAME);\n assert.strictEqual(\n dataProvider.getEntryTypeForLevel(screenshotsLevel),\n Timeline.TimelineFlameChartDataProvider.EntryType.SCREENSHOT);\n\n // There are 5 screenshots in this trace, so we expect there to be 5 events on the screenshots track level.\n const eventsOnScreenshotsLevel = dataProvider.timelineData().entryLevels.filter(e => e === screenshotsLevel);\n assert.lengthOf(eventsOnScreenshotsLevel, 5);\n });\n\n describe('ignoring frames', function() {\n it('removes entries from the data that match the ignored URL', async function() {\n const {ignoreListManager} = setupIgnoreListManagerEnvironment();\n\n const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'react-hello-world.json.gz');\n dataProvider.setModel(parsedTrace);\n\n const eventCountBeforeIgnoreList = dataProvider.timelineData().entryStartTimes.length;\n\n const SCRIPT_TO_IGNORE =\n 'https://unpkg.com/react@18.2.0/umd/react.development.js' as Platform.DevToolsPath.UrlString;\n // Clear the data provider cache and add the React script to the ignore list.\n dataProvider.reset();\n ignoreListManager.ignoreListURL(SCRIPT_TO_IGNORE);\n\n const eventCountAfterIgnoreList = dataProvider.timelineData().entryStartTimes.length;\n // Ensure that the amount of events we show on the flame chart is less\n // than before, now we have added the React URL to the ignore list.\n assert.isBelow(eventCountAfterIgnoreList, eventCountBeforeIgnoreList);\n\n // Clear the data provider cache and unignore the script again\n dataProvider.reset();\n ignoreListManager.unIgnoreListURL(SCRIPT_TO_IGNORE);\n // Ensure that now we have un-ignored the URL that we get the full set of events again.\n assert.strictEqual(dataProvider.timelineData().entryStartTimes.length, eventCountBeforeIgnoreList);\n });\n });\n\n it('filters navigations to only return those that happen on the main frame', async function() {\n const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz');\n\n dataProvider.setModel(parsedTrace);\n\n const mainFrameID = parsedTrace.Meta.mainFrameId;\n const navigationEvents = dataProvider.mainFrameNavigationStartEvents();\n // Ensure that every navigation event that we return is for the main frame.\n assert.isTrue(navigationEvents.every(navEvent => {\n return navEvent.args.frame === mainFrameID;\n }));\n });\n\n it('can search for entries within a given time-range', async function() {\n const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n dataProvider.setModel(parsedTrace);\n\n const bounds = parsedTrace.Meta.traceBounds;\n const filter = new Timeline.TimelineFilters.TimelineRegExp(/Evaluate script/);\n const results = dataProvider.search(bounds, filter);\n assert.lengthOf(results, 12);\n assert.deepEqual(results[0], {index: 154, startTimeMilli: 122411041.395, provider: 'main'});\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineFlameChartNetworkDataProvider.d.ts b/public/panels/timeline/TimelineFlameChartNetworkDataProvider.d.ts index 235d3b7dd..f17d2ddae 100644 --- a/public/panels/timeline/TimelineFlameChartNetworkDataProvider.d.ts +++ b/public/panels/timeline/TimelineFlameChartNetworkDataProvider.d.ts @@ -1,24 +1,24 @@ import type * as TimelineModel from '../../models/timeline_model/timeline_model.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; import * as UI from '../../ui/legacy/legacy.js'; import { TimelineSelection } from './TimelineSelection.js'; export declare class TimelineFlameChartNetworkDataProvider implements PerfUI.FlameChart.FlameChartDataProvider { #private; constructor(); - setModel(traceEngineData: TraceEngine.Handlers.Types.TraceParseData | null): void; - setEvents(traceEngineData: TraceEngine.Handlers.Types.TraceParseData): void; + setModel(parsedTrace: Trace.Handlers.Types.ParsedTrace | null): void; + setEvents(parsedTrace: Trace.Handlers.Types.ParsedTrace): void; isEmpty(): boolean; maxStackDepth(): number; hasTrackConfigurationMode(): boolean; timelineData(): PerfUI.FlameChart.FlameChartTimelineData; minimumBoundary(): number; totalTime(): number; - setWindowTimes(startTime: TraceEngine.Types.Timing.MilliSeconds, endTime: TraceEngine.Types.Timing.MilliSeconds): void; + setWindowTimes(startTime: Trace.Types.Timing.MilliSeconds, endTime: Trace.Types.Timing.MilliSeconds): void; createSelection(index: number): TimelineSelection | null; customizedContextMenu(event: MouseEvent, eventIndex: number, _groupIndex: number): UI.ContextMenu.ContextMenu | undefined; - indexForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData | TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame): number | null; - eventByIndex(entryIndex: number): TraceEngine.Types.TraceEvents.SyntheticNetworkRequest | TraceEngine.Types.TraceEvents.WebSocketEvent | null; + indexForEvent(event: Trace.Types.Events.Event | Trace.Handlers.ModelHandlers.Frames.TimelineFrame): number | null; + eventByIndex(entryIndex: number): Trace.Types.Events.SyntheticNetworkRequest | Trace.Types.Events.WebSocketEvent | null; entryIndexForSelection(selection: TimelineSelection | null): number; groupForEvent(_entryIndex: number): PerfUI.FlameChart.Group | null; entryColor(index: number): string; @@ -38,7 +38,7 @@ export declare class TimelineFlameChartNetworkDataProvider implements PerfUI.Fla * @param timeToPixelRatio * @returns the pixels to draw waiting time and left and right whiskers and url text */ - getDecorationPixels(event: TraceEngine.Types.TraceEvents.SyntheticNetworkRequest, unclippedBarX: number, timeToPixelRatio: number): { + getDecorationPixels(event: Trace.Types.Events.SyntheticNetworkRequest, unclippedBarX: number, timeToPixelRatio: number): { sendStart: number; headersEnd: number; finish: number; @@ -78,12 +78,12 @@ export declare class TimelineFlameChartNetworkDataProvider implements PerfUI.Fla * searches entries within the specified time and returns a list of entry * indexes */ - search(visibleWindow: TraceEngine.Types.Timing.TraceWindowMicroSeconds, filter: TimelineModel.TimelineModelFilter.TimelineModelFilter): PerfUI.FlameChart.DataProviderSearchResult[]; + search(visibleWindow: Trace.Types.Timing.TraceWindowMicroSeconds, filter: TimelineModel.TimelineModelFilter.TimelineModelFilter): PerfUI.FlameChart.DataProviderSearchResult[]; /** * Returns a map of navigations that happened in the main frame, ignoring any * that happened in other frames. * The map's key is the frame ID. **/ - mainFrameNavigationStartEvents(): readonly TraceEngine.Types.TraceEvents.TraceEventNavigationStart[]; + mainFrameNavigationStartEvents(): readonly Trace.Types.Events.NavigationStart[]; buildFlowForInitiator(entryIndex: number): boolean; } diff --git a/public/panels/timeline/TimelineFlameChartNetworkDataProvider.js b/public/panels/timeline/TimelineFlameChartNetworkDataProvider.js index 19e8e4bcd..1d886c6f3 100644 --- a/public/panels/timeline/TimelineFlameChartNetworkDataProvider.js +++ b/public/panels/timeline/TimelineFlameChartNetworkDataProvider.js @@ -3,7 +3,7 @@ // found in the LICENSE file. import * as i18n from '../../core/i18n/i18n.js'; import * as Platform from '../../core/platform/platform.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; import * as UI from '../../ui/legacy/legacy.js'; import * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js'; @@ -22,7 +22,7 @@ export class TimelineFlameChartNetworkDataProvider { #networkTrackAppender; #timelineDataInternal; #lastSelection; - #traceParseData; + #parsedTrace; #eventIndexByEvent = new Map(); // -1 means no entry is selected. #lastInitiatorEntry = -1; @@ -33,29 +33,29 @@ export class TimelineFlameChartNetworkDataProvider { this.#events = []; this.#maxLevel = 0; this.#networkTrackAppender = null; - this.#traceParseData = null; + this.#parsedTrace = null; } - setModel(traceEngineData) { + setModel(parsedTrace) { this.#timelineDataInternal = null; this.#events = []; - this.#traceParseData = traceEngineData; + this.#parsedTrace = parsedTrace; this.#eventIndexByEvent.clear(); - if (this.#traceParseData) { - this.setEvents(this.#traceParseData); - this.#setTimingBoundsData(this.#traceParseData); + if (this.#parsedTrace) { + this.setEvents(this.#parsedTrace); + this.#setTimingBoundsData(this.#parsedTrace); } } - setEvents(traceEngineData) { - if (traceEngineData.NetworkRequests.webSocket) { - traceEngineData.NetworkRequests.webSocket.forEach(webSocketData => { - if (webSocketData.syntheticConnectionEvent) { - this.#events.push(webSocketData.syntheticConnectionEvent); + setEvents(parsedTrace) { + if (parsedTrace.NetworkRequests.webSocket) { + parsedTrace.NetworkRequests.webSocket.forEach(webSocketData => { + if (webSocketData.syntheticConnection) { + this.#events.push(webSocketData.syntheticConnection); } this.#events.push(...webSocketData.events); }); } - if (traceEngineData.NetworkRequests.byTime) { - this.#events.push(...traceEngineData.NetworkRequests.byTime); + if (parsedTrace.NetworkRequests.byTime) { + this.#events.push(...parsedTrace.NetworkRequests.byTime); } } isEmpty() { @@ -74,11 +74,11 @@ export class TimelineFlameChartNetworkDataProvider { return this.#timelineDataInternal; } this.#timelineDataInternal = PerfUI.FlameChart.FlameChartTimelineData.createEmpty(); - if (!this.#traceParseData) { + if (!this.#parsedTrace) { return this.#timelineDataInternal; } if (!this.#events.length) { - this.setEvents(this.#traceParseData); + this.setEvents(this.#parsedTrace); } this.#networkTrackAppender = new NetworkTrackAppender(this.#timelineDataInternal, this.#events); this.#maxLevel = this.#networkTrackAppender.appendTrackAtLevel(0); @@ -103,7 +103,7 @@ export class TimelineFlameChartNetworkDataProvider { } customizedContextMenu(event, eventIndex, _groupIndex) { const networkRequest = this.eventByIndex(eventIndex); - if (!networkRequest || !TraceEngine.Types.TraceEvents.isSyntheticNetworkRequestEvent(networkRequest)) { + if (!networkRequest || !Trace.Types.Events.isSyntheticNetworkRequest(networkRequest)) { return; } const timelineNetworkRequest = TimelineUtils.NetworkRequest.createTimelineNetworkRequest(networkRequest); @@ -113,10 +113,10 @@ export class TimelineFlameChartNetworkDataProvider { } indexForEvent(event) { // In the NetworkDataProvider we will never be dealing with frames, but we need to satisfy the interface for a DataProvider. - if (event instanceof TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame) { + if (event instanceof Trace.Handlers.ModelHandlers.Frames.TimelineFrame) { return null; } - if (!TraceEngine.Types.TraceEvents.isNetworkTrackEntry(event)) { + if (!Trace.Types.Events.isNetworkTrackEntry(event)) { return null; } const fromCache = this.#eventIndexByEvent.get(event); @@ -184,15 +184,15 @@ export class TimelineFlameChartNetworkDataProvider { * @returns the pixels to draw waiting time and left and right whiskers and url text */ getDecorationPixels(event, unclippedBarX, timeToPixelRatio) { - const beginTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.ts); + const beginTime = Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts); const timeToPixel = (time) => unclippedBarX + (time - beginTime) * timeToPixelRatio; - const startTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.ts); - const endTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds((event.ts + event.dur)); - const sendStartTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.args.data.syntheticData.sendStartTime); - const headersEndTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.args.data.syntheticData.downloadStart); + const startTime = Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts); + const endTime = Trace.Helpers.Timing.microSecondsToMilliseconds((event.ts + event.dur)); + const sendStartTime = Trace.Helpers.Timing.microSecondsToMilliseconds(event.args.data.syntheticData.sendStartTime); + const headersEndTime = Trace.Helpers.Timing.microSecondsToMilliseconds(event.args.data.syntheticData.downloadStart); const sendStart = Math.max(timeToPixel(sendStartTime), unclippedBarX); const headersEnd = Math.max(timeToPixel(headersEndTime), sendStart); - const finish = Math.max(timeToPixel(TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.args.data.syntheticData.finishTime)), headersEnd); + const finish = Math.max(timeToPixel(Trace.Helpers.Timing.microSecondsToMilliseconds(event.args.data.syntheticData.finishTime)), headersEnd); const start = timeToPixel(startTime); const end = Math.max(timeToPixel(endTime), finish); return { sendStart, headersEnd, finish, start, end }; @@ -211,10 +211,10 @@ export class TimelineFlameChartNetworkDataProvider { */ decorateEntry(index, context, _text, barX, barY, barWidth, barHeight, unclippedBarX, timeToPixelRatio) { const event = this.#events[index]; - if (TraceEngine.Types.TraceEvents.isSyntheticWebSocketConnectionEvent(event)) { - return this.#decorateSyntheticWebSocketConnectionEvent(index, context, barY, barHeight, unclippedBarX, timeToPixelRatio); + if (Trace.Types.Events.isSyntheticWebSocketConnection(event)) { + return this.#decorateSyntheticWebSocketConnection(index, context, barY, barHeight, unclippedBarX, timeToPixelRatio); } - if (!TraceEngine.Types.TraceEvents.isSyntheticNetworkRequestEvent(event)) { + if (!Trace.Types.Events.isSyntheticNetworkRequest(event)) { return false; } return this.#decorateNetworkRequest(index, context, _text, barX, barY, barWidth, barHeight, unclippedBarX, timeToPixelRatio); @@ -234,7 +234,7 @@ export class TimelineFlameChartNetworkDataProvider { * */ #decorateNetworkRequest(index, context, _text, barX, barY, barWidth, barHeight, unclippedBarX, timeToPixelRatio) { const event = this.#events[index]; - if (!TraceEngine.Types.TraceEvents.isSyntheticNetworkRequestEvent(event)) { + if (!Trace.Types.Events.isSyntheticNetworkRequest(event)) { return false; } const { sendStart, headersEnd, finish, start, end } = this.getDecorationPixels(event, unclippedBarX, timeToPixelRatio); @@ -287,12 +287,12 @@ export class TimelineFlameChartNetworkDataProvider { * ------------------------ * ^start ^end * */ - #decorateSyntheticWebSocketConnectionEvent(index, context, barY, barHeight, unclippedBarX, timeToPixelRatio) { + #decorateSyntheticWebSocketConnection(index, context, barY, barHeight, unclippedBarX, timeToPixelRatio) { context.save(); const event = this.#events[index]; - const beginTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.ts); + const beginTime = Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts); const timeToPixel = (time) => Math.floor(unclippedBarX + (time - beginTime) * timeToPixelRatio); - const endTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds((event.ts + event.dur)); + const endTime = Trace.Helpers.Timing.microSecondsToMilliseconds((event.ts + event.dur)); const start = timeToPixel(beginTime) + 0.5; const end = timeToPixel(endTime) - 0.5; context.strokeStyle = ThemeSupport.ThemeSupport.instance().getComputedValue('--app-color-rendering'); @@ -323,7 +323,7 @@ export class TimelineFlameChartNetworkDataProvider { } prepareHighlightedEntryInfo(index) { const event = this.#events[index]; - if (TraceEngine.Types.TraceEvents.isSyntheticNetworkRequestEvent(event)) { + if (Trace.Types.Events.isSyntheticNetworkRequest(event)) { const element = document.createElement('div'); const root = UI.UIUtils.createShadowRootWithCoreStyles(element, { cssFile: [timelineFlamechartPopoverStyles], @@ -341,10 +341,10 @@ export class TimelineFlameChartNetworkDataProvider { * Sets the minimum time and total time span of a trace using the * new engine data. */ - #setTimingBoundsData(newTraceEngineData) { - const { traceBounds } = newTraceEngineData.Meta; - const minTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceBounds.min); - const maxTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceBounds.max); + #setTimingBoundsData(newParsedTrace) { + const { traceBounds } = newParsedTrace.Meta; + const minTime = Trace.Helpers.Timing.microSecondsToMilliseconds(traceBounds.min); + const maxTime = Trace.Helpers.Timing.microSecondsToMilliseconds(traceBounds.max); this.#minimumBoundaryInternal = minTime; this.#timeSpan = minTime === maxTime ? 1000 : maxTime - this.#minimumBoundaryInternal; } @@ -403,11 +403,11 @@ export class TimelineFlameChartNetworkDataProvider { if (!entry) { continue; } - if (!TraceEngine.Helpers.Timing.eventIsInBounds(entry, visibleWindow)) { + if (!Trace.Helpers.Timing.eventIsInBounds(entry, visibleWindow)) { continue; } - if (filter.accept(entry, this.#traceParseData ?? undefined)) { - const startTimeMilli = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(entry.ts); + if (filter.accept(entry, this.#parsedTrace ?? undefined)) { + const startTimeMilli = Trace.Helpers.Timing.microSecondsToMilliseconds(entry.ts); results.push({ startTimeMilli, index: i, provider: 'network' }); } } @@ -419,13 +419,13 @@ export class TimelineFlameChartNetworkDataProvider { * The map's key is the frame ID. **/ mainFrameNavigationStartEvents() { - if (!this.#traceParseData) { + if (!this.#parsedTrace) { return []; } - return this.#traceParseData.Meta.mainFrameNavigations; + return this.#parsedTrace.Meta.mainFrameNavigations; } buildFlowForInitiator(entryIndex) { - if (!this.#traceParseData) { + if (!this.#parsedTrace) { return false; } if (!this.#timelineDataInternal) { @@ -459,7 +459,7 @@ export class TimelineFlameChartNetworkDataProvider { // Reset to clear any previous arrows from the last event. this.#timelineDataInternal.resetFlowData(); this.#lastInitiatorEntry = entryIndex; - const initiatorsData = initiatorsDataToDrawForNetwork(this.#traceParseData, event); + const initiatorsData = initiatorsDataToDrawForNetwork(this.#parsedTrace, event); // This means there is no change for arrows. if (previousInitiatorsDataLength === 0 && initiatorsData.length === 0) { return false; diff --git a/public/panels/timeline/TimelineFlameChartNetworkDataProvider.js.map b/public/panels/timeline/TimelineFlameChartNetworkDataProvider.js.map index 1e7cb53cf..b44c1f30f 100644 --- a/public/panels/timeline/TimelineFlameChartNetworkDataProvider.js.map +++ b/public/panels/timeline/TimelineFlameChartNetworkDataProvider.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineFlameChartNetworkDataProvider.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineFlameChartNetworkDataProvider.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2016 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport type * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\n\nimport * as TimelineComponents from './components/components.js';\nimport {initiatorsDataToDrawForNetwork} from './Initiators.js';\nimport {NetworkTrackAppender, type NetworkTrackEvent} from './NetworkTrackAppender.js';\nimport timelineFlamechartPopoverStyles from './timelineFlamechartPopover.css.js';\nimport {FlameChartStyle, Selection} from './TimelineFlameChartView.js';\nimport {TimelineSelection} from './TimelineSelection.js';\nimport * as TimelineUtils from './utils/utils.js';\n\nexport class TimelineFlameChartNetworkDataProvider implements PerfUI.FlameChart.FlameChartDataProvider {\n #minimumBoundaryInternal: number;\n #timeSpan: number;\n #events: NetworkTrackEvent[];\n #maxLevel: number;\n #networkTrackAppender: NetworkTrackAppender|null;\n\n #timelineDataInternal?: PerfUI.FlameChart.FlameChartTimelineData|null;\n #lastSelection?: Selection;\n #traceParseData: TraceEngine.Handlers.Types.TraceParseData|null;\n #eventIndexByEvent: Map = new Map();\n // -1 means no entry is selected.\n #lastInitiatorEntry: number = -1;\n #lastInitiatorsData: PerfUI.FlameChart.FlameChartInitiatorData[] = [];\n\n constructor() {\n this.#minimumBoundaryInternal = 0;\n this.#timeSpan = 0;\n this.#events = [];\n this.#maxLevel = 0;\n\n this.#networkTrackAppender = null;\n this.#traceParseData = null;\n }\n\n setModel(traceEngineData: TraceEngine.Handlers.Types.TraceParseData|null): void {\n this.#timelineDataInternal = null;\n this.#events = [];\n this.#traceParseData = traceEngineData;\n this.#eventIndexByEvent.clear();\n\n if (this.#traceParseData) {\n this.setEvents(this.#traceParseData);\n this.#setTimingBoundsData(this.#traceParseData);\n }\n }\n\n setEvents(traceEngineData: TraceEngine.Handlers.Types.TraceParseData): void {\n if (traceEngineData.NetworkRequests.webSocket) {\n traceEngineData.NetworkRequests.webSocket.forEach(webSocketData => {\n if (webSocketData.syntheticConnectionEvent) {\n this.#events.push(webSocketData.syntheticConnectionEvent);\n }\n this.#events.push(...webSocketData.events);\n });\n }\n if (traceEngineData.NetworkRequests.byTime) {\n this.#events.push(...traceEngineData.NetworkRequests.byTime);\n }\n }\n\n isEmpty(): boolean {\n this.timelineData();\n return !this.#events.length;\n }\n\n maxStackDepth(): number {\n return this.#maxLevel;\n }\n\n hasTrackConfigurationMode(): boolean {\n return false;\n }\n\n timelineData(): PerfUI.FlameChart.FlameChartTimelineData {\n if (this.#timelineDataInternal && this.#timelineDataInternal.entryLevels.length !== 0) {\n // The flame chart data is built already, so return the cached data.\n return this.#timelineDataInternal;\n }\n\n this.#timelineDataInternal = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n if (!this.#traceParseData) {\n return this.#timelineDataInternal;\n }\n\n if (!this.#events.length) {\n this.setEvents(this.#traceParseData);\n }\n this.#networkTrackAppender = new NetworkTrackAppender(this.#timelineDataInternal, this.#events);\n this.#maxLevel = this.#networkTrackAppender.appendTrackAtLevel(0);\n\n return this.#timelineDataInternal;\n }\n\n minimumBoundary(): number {\n return this.#minimumBoundaryInternal;\n }\n\n totalTime(): number {\n return this.#timeSpan;\n }\n\n setWindowTimes(startTime: TraceEngine.Types.Timing.MilliSeconds, endTime: TraceEngine.Types.Timing.MilliSeconds):\n void {\n this.#updateTimelineData(startTime, endTime);\n }\n\n createSelection(index: number): TimelineSelection|null {\n if (index === -1) {\n return null;\n }\n const event = this.#events[index];\n this.#lastSelection = new Selection(TimelineSelection.fromTraceEvent(event), index);\n return this.#lastSelection.timelineSelection;\n }\n\n customizedContextMenu(event: MouseEvent, eventIndex: number, _groupIndex: number): UI.ContextMenu.ContextMenu\n |undefined {\n const networkRequest = this.eventByIndex(eventIndex);\n if (!networkRequest || !TraceEngine.Types.TraceEvents.isSyntheticNetworkRequestEvent(networkRequest)) {\n return;\n }\n const timelineNetworkRequest = TimelineUtils.NetworkRequest.createTimelineNetworkRequest(networkRequest);\n const contextMenu = new UI.ContextMenu.ContextMenu(event, {useSoftMenu: true});\n contextMenu.appendApplicableItems(timelineNetworkRequest);\n return contextMenu;\n }\n\n indexForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData|\n TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame): number|null {\n // In the NetworkDataProvider we will never be dealing with frames, but we need to satisfy the interface for a DataProvider.\n if (event instanceof TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame) {\n return null;\n }\n if (!TraceEngine.Types.TraceEvents.isNetworkTrackEntry(event)) {\n return null;\n }\n const fromCache = this.#eventIndexByEvent.get(event);\n // Cached value might be null, which is OK.\n if (fromCache !== undefined) {\n return fromCache;\n }\n const index = this.#events.indexOf(event);\n const result = index > -1 ? index : null;\n this.#eventIndexByEvent.set(event, result);\n return result;\n }\n\n eventByIndex(entryIndex: number): TraceEngine.Types.TraceEvents.SyntheticNetworkRequest\n |TraceEngine.Types.TraceEvents.WebSocketEvent|null {\n return this.#events.at(entryIndex) ?? null;\n }\n\n entryIndexForSelection(selection: TimelineSelection|null): number {\n if (!selection) {\n return -1;\n }\n\n if (this.#lastSelection && this.#lastSelection.timelineSelection.object === selection.object) {\n return this.#lastSelection.entryIndex;\n }\n\n if (!TimelineSelection.isNetworkEventSelection(selection.object)) {\n return -1;\n }\n\n const index = this.#events.indexOf(selection.object);\n if (index !== -1) {\n this.#lastSelection = new Selection(TimelineSelection.fromTraceEvent(selection.object), index);\n }\n return index;\n }\n\n groupForEvent(_entryIndex: number): PerfUI.FlameChart.Group|null {\n // Because the network track only contains one group, we don't actually\n // need to do any lookups here.\n const group = this.#networkTrackAppender?.group() ?? null;\n return group;\n }\n\n entryColor(index: number): string {\n if (!this.#networkTrackAppender) {\n throw new Error('networkTrackAppender should not be empty');\n }\n return this.#networkTrackAppender.colorForEvent(this.#events[index]);\n }\n\n textColor(_index: number): string {\n return FlameChartStyle.textColor;\n }\n\n entryTitle(index: number): string|null {\n const event = this.#events[index];\n return TimelineComponents.EntryName.nameForEntry(event);\n }\n\n entryFont(_index: number): string|null {\n return this.#networkTrackAppender?.font() || null;\n }\n\n /**\n * Returns the pixels needed to decorate the event.\n * The pixels compare to the start of the earliest event of the request.\n *\n * Request.beginTime(), which is used in FlameChart to calculate the unclippedBarX\n * v\n * |----------------[ (URL text) waiting time | request ]--------|\n * ^start ^sendStart ^headersEnd ^Finish ^end\n * @param request\n * @param unclippedBarX The start pixel of the request. It is calculated with request.beginTime() in FlameChart.\n * @param timeToPixelRatio\n * @returns the pixels to draw waiting time and left and right whiskers and url text\n */\n getDecorationPixels(\n event: TraceEngine.Types.TraceEvents.SyntheticNetworkRequest, unclippedBarX: number,\n timeToPixelRatio: number): {sendStart: number, headersEnd: number, finish: number, start: number, end: number} {\n const beginTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.ts);\n const timeToPixel = (time: number): number => unclippedBarX + (time - beginTime) * timeToPixelRatio;\n const startTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.ts);\n const endTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(\n (event.ts + event.dur) as TraceEngine.Types.Timing.MicroSeconds);\n const sendStartTime =\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.args.data.syntheticData.sendStartTime);\n const headersEndTime =\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.args.data.syntheticData.downloadStart);\n const sendStart = Math.max(timeToPixel(sendStartTime), unclippedBarX);\n const headersEnd = Math.max(timeToPixel(headersEndTime), sendStart);\n const finish = Math.max(\n timeToPixel(TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.args.data.syntheticData.finishTime)),\n headersEnd);\n const start = timeToPixel(startTime);\n const end = Math.max(timeToPixel(endTime), finish);\n\n return {sendStart, headersEnd, finish, start, end};\n }\n\n /**\n * Decorates the entry depends on the type of the event:\n * @param index\n * @param context\n * @param barX The x pixel of the visible part request\n * @param barY The y pixel of the visible part request\n * @param barWidth The width of the visible part request\n * @param barHeight The height of the visible part request\n * @param unclippedBarX The start pixel of the request compare to the visible area. It is calculated with request.beginTime() in FlameChart.\n * @param timeToPixelRatio\n * @returns if the entry needs to be decorate, which is alway true if the request has \"timing\" field\n */\n decorateEntry(\n index: number, context: CanvasRenderingContext2D, _text: string|null, barX: number, barY: number,\n barWidth: number, barHeight: number, unclippedBarX: number, timeToPixelRatio: number): boolean {\n const event = this.#events[index];\n if (TraceEngine.Types.TraceEvents.isSyntheticWebSocketConnectionEvent(event)) {\n return this.#decorateSyntheticWebSocketConnectionEvent(\n index, context, barY, barHeight, unclippedBarX, timeToPixelRatio);\n }\n if (!TraceEngine.Types.TraceEvents.isSyntheticNetworkRequestEvent(event)) {\n return false;\n }\n return this.#decorateNetworkRequest(\n index, context, _text, barX, barY, barWidth, barHeight, unclippedBarX, timeToPixelRatio);\n }\n\n /**\n * Decorates the Network Request entry with the following steps:\n * Draw a waiting time between |sendStart| and |headersEnd|\n * By adding a extra transparent white layer\n * Draw a whisk between |start| and |sendStart|\n * Draw a whisk between |finish| and |end|\n * By draw another layer of background color to \"clear\" the area\n * Then draw the whisk\n * Draw the URL after the |sendStart|\n *\n * |----------------[ (URL text) waiting time | request ]--------|\n * ^start ^sendStart ^headersEnd ^Finish ^end\n * */\n #decorateNetworkRequest(\n index: number, context: CanvasRenderingContext2D, _text: string|null, barX: number, barY: number,\n barWidth: number, barHeight: number, unclippedBarX: number, timeToPixelRatio: number): boolean {\n const event = this.#events[index];\n if (!TraceEngine.Types.TraceEvents.isSyntheticNetworkRequestEvent(event)) {\n return false;\n }\n const {sendStart, headersEnd, finish, start, end} =\n this.getDecorationPixels(event, unclippedBarX, timeToPixelRatio);\n\n // Draw waiting time.\n context.fillStyle = 'hsla(0, 100%, 100%, 0.8)';\n context.fillRect(sendStart + 0.5, barY + 0.5, headersEnd - sendStart - 0.5, barHeight - 2);\n // Clear portions of initial rect to prepare for the ticks.\n context.fillStyle = ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-cdt-base-container');\n context.fillRect(barX, barY - 0.5, sendStart - barX, barHeight);\n context.fillRect(finish, barY - 0.5, barX + barWidth - finish, barHeight);\n\n // Draws left and right whiskers\n function drawTick(begin: number, end: number, y: number): void {\n const /** @const */ tickHeightPx = 6;\n context.moveTo(begin, y - tickHeightPx / 2);\n context.lineTo(begin, y + tickHeightPx / 2);\n context.moveTo(begin, y);\n context.lineTo(end, y);\n }\n\n context.beginPath();\n context.lineWidth = 1;\n context.strokeStyle = '#ccc';\n const lineY = Math.floor(barY + barHeight / 2) + 0.5;\n const leftTick = start + 0.5;\n const rightTick = end - 0.5;\n drawTick(leftTick, sendStart, lineY);\n drawTick(rightTick, finish, lineY);\n context.stroke();\n\n // Draw request URL as text\n const textStart = Math.max(sendStart, 0);\n const textWidth = finish - textStart;\n const /** @const */ minTextWidthPx = 20;\n if (textWidth >= minTextWidthPx) {\n let title = this.entryTitle(index) || '';\n if (event.args.data.fromServiceWorker) {\n title = '⚙ ' + title;\n }\n if (title) {\n const /** @const */ textPadding = 4;\n const /** @const */ textBaseline = 5;\n const textBaseHeight = barHeight - textBaseline;\n const trimmedText = UI.UIUtils.trimTextEnd(context, title, textWidth - 2 * textPadding);\n context.fillStyle = '#333';\n context.fillText(trimmedText, textStart + textPadding, barY + textBaseHeight);\n }\n }\n\n return true;\n }\n\n /**\n * Decorates the synthetic websocket event entry with a whisk from the start to the end.\n * ------------------------\n * ^start ^end\n * */\n #decorateSyntheticWebSocketConnectionEvent(\n index: number, context: CanvasRenderingContext2D, barY: number, barHeight: number, unclippedBarX: number,\n timeToPixelRatio: number): boolean {\n context.save();\n const event = this.#events[index] as TraceEngine.Types.TraceEvents.SyntheticWebSocketConnectionEvent;\n const beginTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.ts);\n const timeToPixel = (time: number): number => Math.floor(unclippedBarX + (time - beginTime) * timeToPixelRatio);\n const endTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(\n (event.ts + event.dur) as TraceEngine.Types.Timing.MicroSeconds);\n const start = timeToPixel(beginTime) + 0.5;\n const end = timeToPixel(endTime) - 0.5;\n context.strokeStyle = ThemeSupport.ThemeSupport.instance().getComputedValue('--app-color-rendering');\n\n const lineY = Math.floor(barY + barHeight / 2) + 0.5;\n context.setLineDash([3, 2]);\n context.moveTo(start, lineY - 1);\n context.lineTo(end, lineY - 1);\n context.moveTo(start, lineY + 1);\n context.lineTo(end, lineY + 1);\n context.stroke();\n context.restore();\n return true;\n }\n\n forceDecoration(_index: number): boolean {\n return true;\n }\n\n /**\n *In the FlameChart.ts, when filtering through the events for a level, it starts\n * from the last event of that level and stops when it hit an event that has start\n * time greater than the filtering window.\n * For example, in this websocket level we have A(socket event), B, C, D. If C\n * event has start time greater than the window, the rest of the events (A and B)\n * wont be drawn. So if this level is the force Drawable level, we wont stop at\n * event C and will include the socket event A.\n * */\n forceDrawableLevel(levelIndex: number): boolean {\n return this.#networkTrackAppender?.webSocketIdToLevel.has(levelIndex) || false;\n }\n\n prepareHighlightedEntryInfo(index: number): Element|null {\n const event = this.#events[index];\n if (TraceEngine.Types.TraceEvents.isSyntheticNetworkRequestEvent(event)) {\n const element = document.createElement('div');\n const root = UI.UIUtils.createShadowRootWithCoreStyles(element, {\n cssFile: [timelineFlamechartPopoverStyles],\n delegatesFocus: undefined,\n });\n\n const contents = root.createChild('div', 'timeline-flamechart-popover');\n const infoElement = new TimelineComponents.NetworkRequestTooltip.NetworkRequestTooltip();\n infoElement.networkRequest = event;\n contents.appendChild(infoElement);\n return element;\n }\n return null;\n }\n\n /**\n * Sets the minimum time and total time span of a trace using the\n * new engine data.\n */\n #setTimingBoundsData(newTraceEngineData: TraceEngine.Handlers.Types.TraceParseData): void {\n const {traceBounds} = newTraceEngineData.Meta;\n const minTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceBounds.min);\n const maxTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceBounds.max);\n this.#minimumBoundaryInternal = minTime;\n this.#timeSpan = minTime === maxTime ? 1000 : maxTime - this.#minimumBoundaryInternal;\n }\n\n /**\n * When users zoom in the flamechart, we only want to show them the network\n * requests between startTime and endTime. This function will call the\n * trackAppender to update the timeline data, and then force to create a new\n * PerfUI.FlameChart.FlameChartTimelineData instance to force the flamechart\n * to re-render.\n */\n #updateTimelineData(startTime: TraceEngine.Types.Timing.MilliSeconds, endTime: TraceEngine.Types.Timing.MilliSeconds):\n void {\n if (!this.#networkTrackAppender || !this.#timelineDataInternal) {\n return;\n }\n this.#maxLevel = this.#networkTrackAppender.relayoutEntriesWithinBounds(this.#events, startTime, endTime);\n\n // TODO(crbug.com/1459225): Remove this recreating code.\n // Force to create a new PerfUI.FlameChart.FlameChartTimelineData instance\n // to force the flamechart to re-render. This also causes crbug.com/1459225.\n this.#timelineDataInternal = PerfUI.FlameChart.FlameChartTimelineData.create({\n entryLevels: this.#timelineDataInternal?.entryLevels,\n entryTotalTimes: this.#timelineDataInternal?.entryTotalTimes,\n entryStartTimes: this.#timelineDataInternal?.entryStartTimes,\n groups: this.#timelineDataInternal?.groups,\n initiatorsData: this.#timelineDataInternal.initiatorsData,\n entryDecorations: this.#timelineDataInternal.entryDecorations,\n });\n }\n\n preferredHeight(): number {\n if (!this.#networkTrackAppender || this.#maxLevel === 0) {\n return 0;\n }\n const group = this.#networkTrackAppender.group();\n if (!group) {\n return 0;\n }\n // Bump up to 7 because the tooltip is around 7 rows' height.\n return group.style.height * (this.isExpanded() ? Platform.NumberUtilities.clamp(this.#maxLevel + 1, 7, 8.5) : 1);\n }\n\n isExpanded(): boolean {\n return Boolean(this.#networkTrackAppender?.group()?.expanded);\n }\n\n formatValue(value: number, precision?: number): string {\n return i18n.TimeUtilities.preciseMillisToString(value, precision);\n }\n\n canJumpToEntry(_entryIndex: number): boolean {\n return false;\n }\n\n /**\n * searches entries within the specified time and returns a list of entry\n * indexes\n */\n search(\n visibleWindow: TraceEngine.Types.Timing.TraceWindowMicroSeconds,\n filter: TimelineModel.TimelineModelFilter.TimelineModelFilter,\n ): PerfUI.FlameChart.DataProviderSearchResult[] {\n const results: PerfUI.FlameChart.DataProviderSearchResult[] = [];\n for (let i = 0; i < this.#events.length; i++) {\n const entry = this.#events.at(i);\n if (!entry) {\n continue;\n }\n\n if (!TraceEngine.Helpers.Timing.eventIsInBounds(entry, visibleWindow)) {\n continue;\n }\n\n if (filter.accept(entry, this.#traceParseData ?? undefined)) {\n const startTimeMilli = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(entry.ts);\n results.push({startTimeMilli, index: i, provider: 'network'});\n }\n }\n return results;\n }\n\n /**\n * Returns a map of navigations that happened in the main frame, ignoring any\n * that happened in other frames.\n * The map's key is the frame ID.\n **/\n mainFrameNavigationStartEvents(): readonly TraceEngine.Types.TraceEvents.TraceEventNavigationStart[] {\n if (!this.#traceParseData) {\n return [];\n }\n return this.#traceParseData.Meta.mainFrameNavigations;\n }\n\n buildFlowForInitiator(entryIndex: number): boolean {\n if (!this.#traceParseData) {\n return false;\n }\n if (!this.#timelineDataInternal) {\n return false;\n }\n if (this.#lastInitiatorEntry === entryIndex) {\n if (this.#lastInitiatorsData) {\n this.#timelineDataInternal.initiatorsData = this.#lastInitiatorsData;\n }\n return true;\n }\n if (!this.#networkTrackAppender) {\n return false;\n }\n\n // Remove all previously assigned decorations indicating that the flow event entries are hidden\n const previousInitiatorsDataLength = this.#timelineDataInternal.initiatorsData.length;\n // |entryIndex| equals -1 means there is no entry selected, just clear the\n // initiator cache if there is any previous arrow and return true to\n // re-render.\n if (entryIndex === -1) {\n this.#lastInitiatorEntry = entryIndex;\n if (previousInitiatorsDataLength === 0) {\n // This means there is no arrow before, so we don't need to re-render.\n return false;\n }\n // Reset to clear any previous arrows from the last event.\n this.#timelineDataInternal.resetFlowData();\n return true;\n }\n\n const event = this.#events[entryIndex];\n // Reset to clear any previous arrows from the last event.\n this.#timelineDataInternal.resetFlowData();\n this.#lastInitiatorEntry = entryIndex;\n\n const initiatorsData = initiatorsDataToDrawForNetwork(this.#traceParseData, event);\n // This means there is no change for arrows.\n if (previousInitiatorsDataLength === 0 && initiatorsData.length === 0) {\n return false;\n }\n for (const initiatorData of initiatorsData) {\n const eventIndex = this.indexForEvent(initiatorData.event);\n const initiatorIndex = this.indexForEvent(initiatorData.initiator);\n if (eventIndex === null || initiatorIndex === null) {\n continue;\n }\n this.#timelineDataInternal.initiatorsData.push({\n initiatorIndex,\n eventIndex,\n });\n }\n this.#lastInitiatorsData = this.#timelineDataInternal.initiatorsData;\n return true;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"TimelineFlameChartNetworkDataProvider.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineFlameChartNetworkDataProvider.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2016 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport type * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\n\nimport * as TimelineComponents from './components/components.js';\nimport {initiatorsDataToDrawForNetwork} from './Initiators.js';\nimport {NetworkTrackAppender, type NetworkTrackEvent} from './NetworkTrackAppender.js';\nimport timelineFlamechartPopoverStyles from './timelineFlamechartPopover.css.js';\nimport {FlameChartStyle, Selection} from './TimelineFlameChartView.js';\nimport {TimelineSelection} from './TimelineSelection.js';\nimport * as TimelineUtils from './utils/utils.js';\n\nexport class TimelineFlameChartNetworkDataProvider implements PerfUI.FlameChart.FlameChartDataProvider {\n #minimumBoundaryInternal: number;\n #timeSpan: number;\n #events: NetworkTrackEvent[];\n #maxLevel: number;\n #networkTrackAppender: NetworkTrackAppender|null;\n\n #timelineDataInternal?: PerfUI.FlameChart.FlameChartTimelineData|null;\n #lastSelection?: Selection;\n #parsedTrace: Trace.Handlers.Types.ParsedTrace|null;\n #eventIndexByEvent: Map = new Map();\n // -1 means no entry is selected.\n #lastInitiatorEntry: number = -1;\n #lastInitiatorsData: PerfUI.FlameChart.FlameChartInitiatorData[] = [];\n\n constructor() {\n this.#minimumBoundaryInternal = 0;\n this.#timeSpan = 0;\n this.#events = [];\n this.#maxLevel = 0;\n\n this.#networkTrackAppender = null;\n this.#parsedTrace = null;\n }\n\n setModel(parsedTrace: Trace.Handlers.Types.ParsedTrace|null): void {\n this.#timelineDataInternal = null;\n this.#events = [];\n this.#parsedTrace = parsedTrace;\n this.#eventIndexByEvent.clear();\n\n if (this.#parsedTrace) {\n this.setEvents(this.#parsedTrace);\n this.#setTimingBoundsData(this.#parsedTrace);\n }\n }\n\n setEvents(parsedTrace: Trace.Handlers.Types.ParsedTrace): void {\n if (parsedTrace.NetworkRequests.webSocket) {\n parsedTrace.NetworkRequests.webSocket.forEach(webSocketData => {\n if (webSocketData.syntheticConnection) {\n this.#events.push(webSocketData.syntheticConnection);\n }\n this.#events.push(...webSocketData.events);\n });\n }\n if (parsedTrace.NetworkRequests.byTime) {\n this.#events.push(...parsedTrace.NetworkRequests.byTime);\n }\n }\n\n isEmpty(): boolean {\n this.timelineData();\n return !this.#events.length;\n }\n\n maxStackDepth(): number {\n return this.#maxLevel;\n }\n\n hasTrackConfigurationMode(): boolean {\n return false;\n }\n\n timelineData(): PerfUI.FlameChart.FlameChartTimelineData {\n if (this.#timelineDataInternal && this.#timelineDataInternal.entryLevels.length !== 0) {\n // The flame chart data is built already, so return the cached data.\n return this.#timelineDataInternal;\n }\n\n this.#timelineDataInternal = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n if (!this.#parsedTrace) {\n return this.#timelineDataInternal;\n }\n\n if (!this.#events.length) {\n this.setEvents(this.#parsedTrace);\n }\n this.#networkTrackAppender = new NetworkTrackAppender(this.#timelineDataInternal, this.#events);\n this.#maxLevel = this.#networkTrackAppender.appendTrackAtLevel(0);\n\n return this.#timelineDataInternal;\n }\n\n minimumBoundary(): number {\n return this.#minimumBoundaryInternal;\n }\n\n totalTime(): number {\n return this.#timeSpan;\n }\n\n setWindowTimes(startTime: Trace.Types.Timing.MilliSeconds, endTime: Trace.Types.Timing.MilliSeconds): void {\n this.#updateTimelineData(startTime, endTime);\n }\n\n createSelection(index: number): TimelineSelection|null {\n if (index === -1) {\n return null;\n }\n const event = this.#events[index];\n this.#lastSelection = new Selection(TimelineSelection.fromTraceEvent(event), index);\n return this.#lastSelection.timelineSelection;\n }\n\n customizedContextMenu(event: MouseEvent, eventIndex: number, _groupIndex: number): UI.ContextMenu.ContextMenu\n |undefined {\n const networkRequest = this.eventByIndex(eventIndex);\n if (!networkRequest || !Trace.Types.Events.isSyntheticNetworkRequest(networkRequest)) {\n return;\n }\n const timelineNetworkRequest = TimelineUtils.NetworkRequest.createTimelineNetworkRequest(networkRequest);\n const contextMenu = new UI.ContextMenu.ContextMenu(event, {useSoftMenu: true});\n contextMenu.appendApplicableItems(timelineNetworkRequest);\n return contextMenu;\n }\n\n indexForEvent(event: Trace.Types.Events.Event|Trace.Handlers.ModelHandlers.Frames.TimelineFrame): number|null {\n // In the NetworkDataProvider we will never be dealing with frames, but we need to satisfy the interface for a DataProvider.\n if (event instanceof Trace.Handlers.ModelHandlers.Frames.TimelineFrame) {\n return null;\n }\n if (!Trace.Types.Events.isNetworkTrackEntry(event)) {\n return null;\n }\n const fromCache = this.#eventIndexByEvent.get(event);\n // Cached value might be null, which is OK.\n if (fromCache !== undefined) {\n return fromCache;\n }\n const index = this.#events.indexOf(event);\n const result = index > -1 ? index : null;\n this.#eventIndexByEvent.set(event, result);\n return result;\n }\n\n eventByIndex(entryIndex: number): Trace.Types.Events.SyntheticNetworkRequest|Trace.Types.Events.WebSocketEvent|null {\n return this.#events.at(entryIndex) ?? null;\n }\n\n entryIndexForSelection(selection: TimelineSelection|null): number {\n if (!selection) {\n return -1;\n }\n\n if (this.#lastSelection && this.#lastSelection.timelineSelection.object === selection.object) {\n return this.#lastSelection.entryIndex;\n }\n\n if (!TimelineSelection.isNetworkEventSelection(selection.object)) {\n return -1;\n }\n\n const index = this.#events.indexOf(selection.object);\n if (index !== -1) {\n this.#lastSelection = new Selection(TimelineSelection.fromTraceEvent(selection.object), index);\n }\n return index;\n }\n\n groupForEvent(_entryIndex: number): PerfUI.FlameChart.Group|null {\n // Because the network track only contains one group, we don't actually\n // need to do any lookups here.\n const group = this.#networkTrackAppender?.group() ?? null;\n return group;\n }\n\n entryColor(index: number): string {\n if (!this.#networkTrackAppender) {\n throw new Error('networkTrackAppender should not be empty');\n }\n return this.#networkTrackAppender.colorForEvent(this.#events[index]);\n }\n\n textColor(_index: number): string {\n return FlameChartStyle.textColor;\n }\n\n entryTitle(index: number): string|null {\n const event = this.#events[index];\n return TimelineComponents.EntryName.nameForEntry(event);\n }\n\n entryFont(_index: number): string|null {\n return this.#networkTrackAppender?.font() || null;\n }\n\n /**\n * Returns the pixels needed to decorate the event.\n * The pixels compare to the start of the earliest event of the request.\n *\n * Request.beginTime(), which is used in FlameChart to calculate the unclippedBarX\n * v\n * |----------------[ (URL text) waiting time | request ]--------|\n * ^start ^sendStart ^headersEnd ^Finish ^end\n * @param request\n * @param unclippedBarX The start pixel of the request. It is calculated with request.beginTime() in FlameChart.\n * @param timeToPixelRatio\n * @returns the pixels to draw waiting time and left and right whiskers and url text\n */\n getDecorationPixels(\n event: Trace.Types.Events.SyntheticNetworkRequest, unclippedBarX: number,\n timeToPixelRatio: number): {sendStart: number, headersEnd: number, finish: number, start: number, end: number} {\n const beginTime = Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts);\n const timeToPixel = (time: number): number => unclippedBarX + (time - beginTime) * timeToPixelRatio;\n const startTime = Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts);\n const endTime =\n Trace.Helpers.Timing.microSecondsToMilliseconds((event.ts + event.dur) as Trace.Types.Timing.MicroSeconds);\n const sendStartTime = Trace.Helpers.Timing.microSecondsToMilliseconds(event.args.data.syntheticData.sendStartTime);\n const headersEndTime = Trace.Helpers.Timing.microSecondsToMilliseconds(event.args.data.syntheticData.downloadStart);\n const sendStart = Math.max(timeToPixel(sendStartTime), unclippedBarX);\n const headersEnd = Math.max(timeToPixel(headersEndTime), sendStart);\n const finish = Math.max(\n timeToPixel(Trace.Helpers.Timing.microSecondsToMilliseconds(event.args.data.syntheticData.finishTime)),\n headersEnd);\n const start = timeToPixel(startTime);\n const end = Math.max(timeToPixel(endTime), finish);\n\n return {sendStart, headersEnd, finish, start, end};\n }\n\n /**\n * Decorates the entry depends on the type of the event:\n * @param index\n * @param context\n * @param barX The x pixel of the visible part request\n * @param barY The y pixel of the visible part request\n * @param barWidth The width of the visible part request\n * @param barHeight The height of the visible part request\n * @param unclippedBarX The start pixel of the request compare to the visible area. It is calculated with request.beginTime() in FlameChart.\n * @param timeToPixelRatio\n * @returns if the entry needs to be decorate, which is alway true if the request has \"timing\" field\n */\n decorateEntry(\n index: number, context: CanvasRenderingContext2D, _text: string|null, barX: number, barY: number,\n barWidth: number, barHeight: number, unclippedBarX: number, timeToPixelRatio: number): boolean {\n const event = this.#events[index];\n if (Trace.Types.Events.isSyntheticWebSocketConnection(event)) {\n return this.#decorateSyntheticWebSocketConnection(\n index, context, barY, barHeight, unclippedBarX, timeToPixelRatio);\n }\n if (!Trace.Types.Events.isSyntheticNetworkRequest(event)) {\n return false;\n }\n return this.#decorateNetworkRequest(\n index, context, _text, barX, barY, barWidth, barHeight, unclippedBarX, timeToPixelRatio);\n }\n\n /**\n * Decorates the Network Request entry with the following steps:\n * Draw a waiting time between |sendStart| and |headersEnd|\n * By adding a extra transparent white layer\n * Draw a whisk between |start| and |sendStart|\n * Draw a whisk between |finish| and |end|\n * By draw another layer of background color to \"clear\" the area\n * Then draw the whisk\n * Draw the URL after the |sendStart|\n *\n * |----------------[ (URL text) waiting time | request ]--------|\n * ^start ^sendStart ^headersEnd ^Finish ^end\n * */\n #decorateNetworkRequest(\n index: number, context: CanvasRenderingContext2D, _text: string|null, barX: number, barY: number,\n barWidth: number, barHeight: number, unclippedBarX: number, timeToPixelRatio: number): boolean {\n const event = this.#events[index];\n if (!Trace.Types.Events.isSyntheticNetworkRequest(event)) {\n return false;\n }\n const {sendStart, headersEnd, finish, start, end} =\n this.getDecorationPixels(event, unclippedBarX, timeToPixelRatio);\n\n // Draw waiting time.\n context.fillStyle = 'hsla(0, 100%, 100%, 0.8)';\n context.fillRect(sendStart + 0.5, barY + 0.5, headersEnd - sendStart - 0.5, barHeight - 2);\n // Clear portions of initial rect to prepare for the ticks.\n context.fillStyle = ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-cdt-base-container');\n context.fillRect(barX, barY - 0.5, sendStart - barX, barHeight);\n context.fillRect(finish, barY - 0.5, barX + barWidth - finish, barHeight);\n\n // Draws left and right whiskers\n function drawTick(begin: number, end: number, y: number): void {\n const /** @const */ tickHeightPx = 6;\n context.moveTo(begin, y - tickHeightPx / 2);\n context.lineTo(begin, y + tickHeightPx / 2);\n context.moveTo(begin, y);\n context.lineTo(end, y);\n }\n\n context.beginPath();\n context.lineWidth = 1;\n context.strokeStyle = '#ccc';\n const lineY = Math.floor(barY + barHeight / 2) + 0.5;\n const leftTick = start + 0.5;\n const rightTick = end - 0.5;\n drawTick(leftTick, sendStart, lineY);\n drawTick(rightTick, finish, lineY);\n context.stroke();\n\n // Draw request URL as text\n const textStart = Math.max(sendStart, 0);\n const textWidth = finish - textStart;\n const /** @const */ minTextWidthPx = 20;\n if (textWidth >= minTextWidthPx) {\n let title = this.entryTitle(index) || '';\n if (event.args.data.fromServiceWorker) {\n title = '⚙ ' + title;\n }\n if (title) {\n const /** @const */ textPadding = 4;\n const /** @const */ textBaseline = 5;\n const textBaseHeight = barHeight - textBaseline;\n const trimmedText = UI.UIUtils.trimTextEnd(context, title, textWidth - 2 * textPadding);\n context.fillStyle = '#333';\n context.fillText(trimmedText, textStart + textPadding, barY + textBaseHeight);\n }\n }\n\n return true;\n }\n\n /**\n * Decorates the synthetic websocket event entry with a whisk from the start to the end.\n * ------------------------\n * ^start ^end\n * */\n #decorateSyntheticWebSocketConnection(\n index: number, context: CanvasRenderingContext2D, barY: number, barHeight: number, unclippedBarX: number,\n timeToPixelRatio: number): boolean {\n context.save();\n const event = this.#events[index] as Trace.Types.Events.SyntheticWebSocketConnection;\n const beginTime = Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts);\n const timeToPixel = (time: number): number => Math.floor(unclippedBarX + (time - beginTime) * timeToPixelRatio);\n const endTime =\n Trace.Helpers.Timing.microSecondsToMilliseconds((event.ts + event.dur) as Trace.Types.Timing.MicroSeconds);\n const start = timeToPixel(beginTime) + 0.5;\n const end = timeToPixel(endTime) - 0.5;\n context.strokeStyle = ThemeSupport.ThemeSupport.instance().getComputedValue('--app-color-rendering');\n\n const lineY = Math.floor(barY + barHeight / 2) + 0.5;\n context.setLineDash([3, 2]);\n context.moveTo(start, lineY - 1);\n context.lineTo(end, lineY - 1);\n context.moveTo(start, lineY + 1);\n context.lineTo(end, lineY + 1);\n context.stroke();\n context.restore();\n return true;\n }\n\n forceDecoration(_index: number): boolean {\n return true;\n }\n\n /**\n *In the FlameChart.ts, when filtering through the events for a level, it starts\n * from the last event of that level and stops when it hit an event that has start\n * time greater than the filtering window.\n * For example, in this websocket level we have A(socket event), B, C, D. If C\n * event has start time greater than the window, the rest of the events (A and B)\n * wont be drawn. So if this level is the force Drawable level, we wont stop at\n * event C and will include the socket event A.\n * */\n forceDrawableLevel(levelIndex: number): boolean {\n return this.#networkTrackAppender?.webSocketIdToLevel.has(levelIndex) || false;\n }\n\n prepareHighlightedEntryInfo(index: number): Element|null {\n const event = this.#events[index];\n if (Trace.Types.Events.isSyntheticNetworkRequest(event)) {\n const element = document.createElement('div');\n const root = UI.UIUtils.createShadowRootWithCoreStyles(element, {\n cssFile: [timelineFlamechartPopoverStyles],\n delegatesFocus: undefined,\n });\n\n const contents = root.createChild('div', 'timeline-flamechart-popover');\n const infoElement = new TimelineComponents.NetworkRequestTooltip.NetworkRequestTooltip();\n infoElement.networkRequest = event;\n contents.appendChild(infoElement);\n return element;\n }\n return null;\n }\n\n /**\n * Sets the minimum time and total time span of a trace using the\n * new engine data.\n */\n #setTimingBoundsData(newParsedTrace: Trace.Handlers.Types.ParsedTrace): void {\n const {traceBounds} = newParsedTrace.Meta;\n const minTime = Trace.Helpers.Timing.microSecondsToMilliseconds(traceBounds.min);\n const maxTime = Trace.Helpers.Timing.microSecondsToMilliseconds(traceBounds.max);\n this.#minimumBoundaryInternal = minTime;\n this.#timeSpan = minTime === maxTime ? 1000 : maxTime - this.#minimumBoundaryInternal;\n }\n\n /**\n * When users zoom in the flamechart, we only want to show them the network\n * requests between startTime and endTime. This function will call the\n * trackAppender to update the timeline data, and then force to create a new\n * PerfUI.FlameChart.FlameChartTimelineData instance to force the flamechart\n * to re-render.\n */\n #updateTimelineData(startTime: Trace.Types.Timing.MilliSeconds, endTime: Trace.Types.Timing.MilliSeconds): void {\n if (!this.#networkTrackAppender || !this.#timelineDataInternal) {\n return;\n }\n this.#maxLevel = this.#networkTrackAppender.relayoutEntriesWithinBounds(this.#events, startTime, endTime);\n\n // TODO(crbug.com/1459225): Remove this recreating code.\n // Force to create a new PerfUI.FlameChart.FlameChartTimelineData instance\n // to force the flamechart to re-render. This also causes crbug.com/1459225.\n this.#timelineDataInternal = PerfUI.FlameChart.FlameChartTimelineData.create({\n entryLevels: this.#timelineDataInternal?.entryLevels,\n entryTotalTimes: this.#timelineDataInternal?.entryTotalTimes,\n entryStartTimes: this.#timelineDataInternal?.entryStartTimes,\n groups: this.#timelineDataInternal?.groups,\n initiatorsData: this.#timelineDataInternal.initiatorsData,\n entryDecorations: this.#timelineDataInternal.entryDecorations,\n });\n }\n\n preferredHeight(): number {\n if (!this.#networkTrackAppender || this.#maxLevel === 0) {\n return 0;\n }\n const group = this.#networkTrackAppender.group();\n if (!group) {\n return 0;\n }\n // Bump up to 7 because the tooltip is around 7 rows' height.\n return group.style.height * (this.isExpanded() ? Platform.NumberUtilities.clamp(this.#maxLevel + 1, 7, 8.5) : 1);\n }\n\n isExpanded(): boolean {\n return Boolean(this.#networkTrackAppender?.group()?.expanded);\n }\n\n formatValue(value: number, precision?: number): string {\n return i18n.TimeUtilities.preciseMillisToString(value, precision);\n }\n\n canJumpToEntry(_entryIndex: number): boolean {\n return false;\n }\n\n /**\n * searches entries within the specified time and returns a list of entry\n * indexes\n */\n search(\n visibleWindow: Trace.Types.Timing.TraceWindowMicroSeconds,\n filter: TimelineModel.TimelineModelFilter.TimelineModelFilter,\n ): PerfUI.FlameChart.DataProviderSearchResult[] {\n const results: PerfUI.FlameChart.DataProviderSearchResult[] = [];\n for (let i = 0; i < this.#events.length; i++) {\n const entry = this.#events.at(i);\n if (!entry) {\n continue;\n }\n\n if (!Trace.Helpers.Timing.eventIsInBounds(entry, visibleWindow)) {\n continue;\n }\n\n if (filter.accept(entry, this.#parsedTrace ?? undefined)) {\n const startTimeMilli = Trace.Helpers.Timing.microSecondsToMilliseconds(entry.ts);\n results.push({startTimeMilli, index: i, provider: 'network'});\n }\n }\n return results;\n }\n\n /**\n * Returns a map of navigations that happened in the main frame, ignoring any\n * that happened in other frames.\n * The map's key is the frame ID.\n **/\n mainFrameNavigationStartEvents(): readonly Trace.Types.Events.NavigationStart[] {\n if (!this.#parsedTrace) {\n return [];\n }\n return this.#parsedTrace.Meta.mainFrameNavigations;\n }\n\n buildFlowForInitiator(entryIndex: number): boolean {\n if (!this.#parsedTrace) {\n return false;\n }\n if (!this.#timelineDataInternal) {\n return false;\n }\n if (this.#lastInitiatorEntry === entryIndex) {\n if (this.#lastInitiatorsData) {\n this.#timelineDataInternal.initiatorsData = this.#lastInitiatorsData;\n }\n return true;\n }\n if (!this.#networkTrackAppender) {\n return false;\n }\n\n // Remove all previously assigned decorations indicating that the flow event entries are hidden\n const previousInitiatorsDataLength = this.#timelineDataInternal.initiatorsData.length;\n // |entryIndex| equals -1 means there is no entry selected, just clear the\n // initiator cache if there is any previous arrow and return true to\n // re-render.\n if (entryIndex === -1) {\n this.#lastInitiatorEntry = entryIndex;\n if (previousInitiatorsDataLength === 0) {\n // This means there is no arrow before, so we don't need to re-render.\n return false;\n }\n // Reset to clear any previous arrows from the last event.\n this.#timelineDataInternal.resetFlowData();\n return true;\n }\n\n const event = this.#events[entryIndex];\n // Reset to clear any previous arrows from the last event.\n this.#timelineDataInternal.resetFlowData();\n this.#lastInitiatorEntry = entryIndex;\n\n const initiatorsData = initiatorsDataToDrawForNetwork(this.#parsedTrace, event);\n // This means there is no change for arrows.\n if (previousInitiatorsDataLength === 0 && initiatorsData.length === 0) {\n return false;\n }\n for (const initiatorData of initiatorsData) {\n const eventIndex = this.indexForEvent(initiatorData.event);\n const initiatorIndex = this.indexForEvent(initiatorData.initiator);\n if (eventIndex === null || initiatorIndex === null) {\n continue;\n }\n this.#timelineDataInternal.initiatorsData.push({\n initiatorIndex,\n eventIndex,\n });\n }\n this.#lastInitiatorsData = this.#timelineDataInternal.initiatorsData;\n return true;\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineFlameChartNetworkDataProvider.test.js b/public/panels/timeline/TimelineFlameChartNetworkDataProvider.test.js index 2701f9413..6aaac8960 100644 --- a/public/panels/timeline/TimelineFlameChartNetworkDataProvider.test.js +++ b/public/panels/timeline/TimelineFlameChartNetworkDataProvider.test.js @@ -1,27 +1,27 @@ // 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 * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import { describeWithEnvironment } from '../../testing/EnvironmentHelpers.js'; import { TraceLoader } from '../../testing/TraceLoader.js'; import * as Timeline from './timeline.js'; describeWithEnvironment('TimelineFlameChartNetworkDataProvider', function () { it('renders the network track correctly', async function () { const dataProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider(); - const { traceData } = await TraceLoader.traceEngine(this, 'load-simple.json.gz'); - const minTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min); - const maxTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max); - dataProvider.setModel(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'load-simple.json.gz'); + const minTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min); + const maxTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max); + dataProvider.setModel(parsedTrace); dataProvider.setWindowTimes(minTime, maxTime); // TimelineFlameChartNetworkDataProvider only has network track, so should always be one track group. assert.strictEqual(dataProvider.timelineData().groups.length, 1); const networkTrackGroup = dataProvider.timelineData().groups[0]; assert.deepEqual(dataProvider.minimumBoundary(), minTime); assert.deepEqual(dataProvider.totalTime(), maxTime - minTime); - const networkEvents = traceData.NetworkRequests.byTime; - const networkEventsStartTimes = networkEvents.map(request => TraceEngine.Helpers.Timing.microSecondsToMilliseconds(request.ts)); + const networkEvents = parsedTrace.NetworkRequests.byTime; + const networkEventsStartTimes = networkEvents.map(request => Trace.Helpers.Timing.microSecondsToMilliseconds(request.ts)); const networkEventsTotalTimes = networkEvents.map(request => { - const { startTime, endTime } = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(request); + const { startTime, endTime } = Trace.Helpers.Timing.eventTimingsMilliSeconds(request); return endTime - startTime; }); assert.deepEqual(dataProvider.timelineData().entryLevels.length, 6); @@ -43,19 +43,19 @@ describeWithEnvironment('TimelineFlameChartNetworkDataProvider', function () { }); it('can return the group for a given entryIndex', async function () { const dataProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider(); - const { traceData } = await TraceLoader.traceEngine(this, 'load-simple.json.gz'); - dataProvider.setModel(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'load-simple.json.gz'); + dataProvider.setModel(parsedTrace); dataProvider.timelineData(); assert.strictEqual(dataProvider.groupForEvent(0)?.name, 'Network'); }); it('filters navigations to only return those that happen on the main frame', async function () { const dataProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider(); - const { traceData } = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz'); - const minTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min); - const maxTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max); - dataProvider.setModel(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz'); + const minTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min); + const maxTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max); + dataProvider.setModel(parsedTrace); dataProvider.setWindowTimes(minTime, maxTime); - const mainFrameID = traceData.Meta.mainFrameId; + const mainFrameID = parsedTrace.Meta.mainFrameId; const navigationEvents = dataProvider.mainFrameNavigationStartEvents(); // Ensure that every navigation event that we return is for the main frame. assert.isTrue(navigationEvents.every(navEvent => { @@ -64,18 +64,18 @@ describeWithEnvironment('TimelineFlameChartNetworkDataProvider', function () { }); it('can provide the index for an event and the event for a given index', async function () { const dataProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider(); - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - dataProvider.setModel(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + dataProvider.setModel(parsedTrace); const event = dataProvider.eventByIndex(0); assert.isOk(event); assert.strictEqual(dataProvider.indexForEvent(event), 0); }); it('does not render the network track if there is no network requests', async function () { const dataProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider(); - const { traceData } = await TraceLoader.traceEngine(this, 'basic.json.gz'); - const minTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min); - const maxTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max); - dataProvider.setModel(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'basic.json.gz'); + const minTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min); + const maxTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max); + dataProvider.setModel(parsedTrace); dataProvider.setWindowTimes(minTime, maxTime); // Network track appender won't append the network track if there is no network requests. assert.strictEqual(dataProvider.timelineData().groups.length, 0); @@ -93,7 +93,7 @@ describeWithEnvironment('TimelineFlameChartNetworkDataProvider', function () { }); it('decorate a event correctly', async function () { const dataProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider(); - const { traceData } = await TraceLoader.traceEngine(this, 'cls-cluster-max-timeout.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'cls-cluster-max-timeout.json.gz'); // The field that is important of this test: // { // "ts": 183752441.977, @@ -112,7 +112,7 @@ describeWithEnvironment('TimelineFlameChartNetworkDataProvider', function () { // "responseTime": 1634222299.776 // ... // } - const event = traceData.NetworkRequests.byTime[1]; + const event = parsedTrace.NetworkRequests.byTime[1]; // So for this request: // The earliest event belonging to this request starts at 183752441.977. // This is used in flamechart to calculate unclippedBarX. @@ -142,12 +142,12 @@ describeWithEnvironment('TimelineFlameChartNetworkDataProvider', function () { }); it('can search for entries within a given time-range', async function () { const dataProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider(); - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); - dataProvider.setModel(traceData); - const boundsMs = TraceEngine.Helpers.Timing.traceWindowMilliSeconds(traceData.Meta.traceBounds); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); + dataProvider.setModel(parsedTrace); + const boundsMs = Trace.Helpers.Timing.traceWindowMilliSeconds(parsedTrace.Meta.traceBounds); dataProvider.setWindowTimes(boundsMs.min, boundsMs.max); const filter = new Timeline.TimelineFilters.TimelineRegExp(/app\.js/i); - const results = dataProvider.search(traceData.Meta.traceBounds, filter); + const results = dataProvider.search(parsedTrace.Meta.traceBounds, filter); assert.lengthOf(results, 1); assert.deepEqual(results[0], { index: 8, startTimeMilli: 122411056.533, provider: 'network' }); }); diff --git a/public/panels/timeline/TimelineFlameChartNetworkDataProvider.test.js.map b/public/panels/timeline/TimelineFlameChartNetworkDataProvider.test.js.map index 7cb698eb1..3bfdcd55f 100644 --- a/public/panels/timeline/TimelineFlameChartNetworkDataProvider.test.js.map +++ b/public/panels/timeline/TimelineFlameChartNetworkDataProvider.test.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineFlameChartNetworkDataProvider.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineFlameChartNetworkDataProvider.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\n\nimport * as Timeline from './timeline.js';\n\ndescribeWithEnvironment('TimelineFlameChartNetworkDataProvider', function() {\n it('renders the network track correctly', async function() {\n const dataProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider();\n const {traceData} = await TraceLoader.traceEngine(this, 'load-simple.json.gz');\n\n const minTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min);\n const maxTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max);\n\n dataProvider.setModel(traceData);\n dataProvider.setWindowTimes(minTime, maxTime);\n\n // TimelineFlameChartNetworkDataProvider only has network track, so should always be one track group.\n assert.strictEqual(dataProvider.timelineData().groups.length, 1);\n const networkTrackGroup = dataProvider.timelineData().groups[0];\n\n assert.deepEqual(dataProvider.minimumBoundary(), minTime);\n assert.deepEqual(dataProvider.totalTime(), maxTime - minTime);\n\n const networkEvents = traceData.NetworkRequests.byTime;\n const networkEventsStartTimes =\n networkEvents.map(request => TraceEngine.Helpers.Timing.microSecondsToMilliseconds(request.ts));\n const networkEventsTotalTimes = networkEvents.map(request => {\n const {startTime, endTime} = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(request);\n return endTime - startTime;\n });\n assert.deepEqual(dataProvider.timelineData().entryLevels.length, 6);\n assert.deepEqual(dataProvider.timelineData().entryLevels, [0, 1, 1, 1, 1, 2]);\n assertTimestampsEqual(dataProvider.timelineData().entryStartTimes, networkEventsStartTimes);\n assertTimestampsEqual(dataProvider.timelineData().entryTotalTimes, networkEventsTotalTimes);\n\n assert.deepEqual(dataProvider.maxStackDepth(), 3);\n\n // The decorateEntry() will be handled in the TimelineFlameChartNetworkDataProvider, so this function always returns true.\n assert.isTrue(dataProvider.forceDecoration(0));\n\n assert.isFalse(dataProvider.isEmpty());\n\n // The network track is default to collapsed.\n assert.isFalse(dataProvider.isExpanded());\n // The height of collapsed network track style is 17.\n assert.strictEqual(dataProvider.preferredHeight(), 17);\n networkTrackGroup.expanded = true;\n assert.isTrue(dataProvider.isExpanded());\n // The max level here is 3, so `clamp(this.#maxLevel + 1, 7, 8.5)` = 7\n assert.strictEqual(dataProvider.preferredHeight(), 17 * 7);\n });\n\n it('can return the group for a given entryIndex', async function() {\n const dataProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider();\n const {traceData} = await TraceLoader.traceEngine(this, 'load-simple.json.gz');\n dataProvider.setModel(traceData);\n dataProvider.timelineData();\n\n assert.strictEqual(\n dataProvider.groupForEvent(0)?.name,\n 'Network',\n );\n });\n\n it('filters navigations to only return those that happen on the main frame', async function() {\n const dataProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider();\n const {traceData} = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz');\n\n const minTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min);\n const maxTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max);\n\n dataProvider.setModel(traceData);\n dataProvider.setWindowTimes(minTime, maxTime);\n\n const mainFrameID = traceData.Meta.mainFrameId;\n const navigationEvents = dataProvider.mainFrameNavigationStartEvents();\n // Ensure that every navigation event that we return is for the main frame.\n assert.isTrue(navigationEvents.every(navEvent => {\n return navEvent.args.frame === mainFrameID;\n }));\n });\n\n it('can provide the index for an event and the event for a given index', async function() {\n const dataProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider();\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n dataProvider.setModel(traceData);\n\n const event = dataProvider.eventByIndex(0);\n assert.isOk(event);\n assert.strictEqual(dataProvider.indexForEvent(event), 0);\n });\n\n it('does not render the network track if there is no network requests', async function() {\n const dataProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider();\n const {traceData} = await TraceLoader.traceEngine(this, 'basic.json.gz');\n\n const minTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min);\n const maxTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max);\n\n dataProvider.setModel(traceData);\n dataProvider.setWindowTimes(minTime, maxTime);\n\n // Network track appender won't append the network track if there is no network requests.\n assert.strictEqual(dataProvider.timelineData().groups.length, 0);\n\n assert.deepEqual(dataProvider.minimumBoundary(), minTime);\n assert.deepEqual(dataProvider.totalTime(), maxTime - minTime);\n\n assert.deepEqual(dataProvider.timelineData().entryLevels, []);\n assert.deepEqual(dataProvider.timelineData().entryStartTimes, []);\n assert.deepEqual(dataProvider.timelineData().entryTotalTimes, []);\n\n assert.deepEqual(dataProvider.maxStackDepth(), 0);\n\n // The decorateEntry() will be handled in the TimelineFlameChartNetworkDataProvider, so this function always returns true.\n assert.isTrue(dataProvider.forceDecoration(0));\n\n // The network track won't show if it is empty.\n assert.isTrue(dataProvider.isEmpty());\n\n assert.strictEqual(dataProvider.preferredHeight(), 0);\n });\n\n it('decorate a event correctly', async function() {\n const dataProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider();\n const {traceData} = await TraceLoader.traceEngine(this, 'cls-cluster-max-timeout.json.gz');\n // The field that is important of this test:\n // {\n // \"ts\": 183752441.977,\n // \"dur\": 183752670.454,\n // \"finishTime\": 183752669.23299998,\n // ...\n // \"timing\": {\n // \"pushStart\": 0,\n // \"receiveHeadersEnd\": 218.084,\n // \"requestTime\": 183752.449687,\n // \"sendEnd\": 13.01,\n // \"sendStart\": 12.792,\n // ...\n // },\n // \"priority\": \"VeryHigh\",\n // \"responseTime\": 1634222299.776\n // ...\n // }\n const event = traceData.NetworkRequests.byTime[1];\n // So for this request:\n // The earliest event belonging to this request starts at 183752441.977.\n // This is used in flamechart to calculate unclippedBarX.\n // Start time is 183752441.977\n // End time is 183752670.454\n // Finish time is 183752669.233\n // request time is 183752.449687, but it is in second, so 183752449.687\n // in milliseconds.\n // sendStartTime is requestTime + sendStart = 183752462.479\n // headersEndTime is requestTime + receiveHeadersEnd = 183752667.771\n //\n // To calculate the pixel of a timestamp, we substrate the begin time from\n // it, then multiple the timeToPixelRatio and then add the unclippedBarX.\n // Then get the floor of the pixel.\n // So the pixel of sendStart is (183752462.479 - 183752441.977) + 10, in ts it will be 30.502000004053116.\n // So the pixel of headersEnd is (183752667.771 - 183752441.977) + 10, in ts it will be 235.79399999976158.\n // So the pixel of finish is (183752669.233 - 183752441.977) + 10, in ts it will be 237.25600001215935.\n // So the pixel of start is (183752441.977 - 183752441.977) + 10 = 10.\n // So the pixel of end is (183752670.454 - 183752441.977) + 10, in ts it will be 238.47699999809265.\n assert.deepEqual(dataProvider.getDecorationPixels(event, /* unclippedBarX= */ 10, /* timeToPixelRatio= */ 1), {\n sendStart: (183752462.479 - 183752441.977) + 10,\n headersEnd: (183752667.771 - 183752441.977) + 10,\n finish: (183752669.233 - 183752441.977) + 10,\n start: 10,\n end: (183752670.454 - 183752441.977) + 10,\n });\n });\n\n it('can search for entries within a given time-range', async function() {\n const dataProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider();\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n dataProvider.setModel(traceData);\n const boundsMs = TraceEngine.Helpers.Timing.traceWindowMilliSeconds(traceData.Meta.traceBounds);\n dataProvider.setWindowTimes(boundsMs.min, boundsMs.max);\n\n const filter = new Timeline.TimelineFilters.TimelineRegExp(/app\\.js/i);\n const results = dataProvider.search(traceData.Meta.traceBounds, filter);\n assert.lengthOf(results, 1);\n assert.deepEqual(results[0], {index: 8, startTimeMilli: 122411056.533, provider: 'network'});\n });\n});\n\nfunction assertTimestampEqual(actual: number, expected: number): void {\n assert.strictEqual(actual.toFixed(2), expected.toFixed(2));\n}\n\nfunction assertTimestampsEqual(actual: number[]|Float32Array|Float64Array, expected: number[]): void {\n assert.strictEqual(actual.length, expected.length);\n\n for (let i = 0; i < actual.length; i++) {\n assertTimestampEqual(actual[i], expected[i]);\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"TimelineFlameChartNetworkDataProvider.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineFlameChartNetworkDataProvider.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\n\nimport * as Timeline from './timeline.js';\n\ndescribeWithEnvironment('TimelineFlameChartNetworkDataProvider', function() {\n it('renders the network track correctly', async function() {\n const dataProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider();\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'load-simple.json.gz');\n\n const minTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min);\n const maxTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max);\n\n dataProvider.setModel(parsedTrace);\n dataProvider.setWindowTimes(minTime, maxTime);\n\n // TimelineFlameChartNetworkDataProvider only has network track, so should always be one track group.\n assert.strictEqual(dataProvider.timelineData().groups.length, 1);\n const networkTrackGroup = dataProvider.timelineData().groups[0];\n\n assert.deepEqual(dataProvider.minimumBoundary(), minTime);\n assert.deepEqual(dataProvider.totalTime(), maxTime - minTime);\n\n const networkEvents = parsedTrace.NetworkRequests.byTime;\n const networkEventsStartTimes =\n networkEvents.map(request => Trace.Helpers.Timing.microSecondsToMilliseconds(request.ts));\n const networkEventsTotalTimes = networkEvents.map(request => {\n const {startTime, endTime} = Trace.Helpers.Timing.eventTimingsMilliSeconds(request);\n return endTime - startTime;\n });\n assert.deepEqual(dataProvider.timelineData().entryLevels.length, 6);\n assert.deepEqual(dataProvider.timelineData().entryLevels, [0, 1, 1, 1, 1, 2]);\n assertTimestampsEqual(dataProvider.timelineData().entryStartTimes, networkEventsStartTimes);\n assertTimestampsEqual(dataProvider.timelineData().entryTotalTimes, networkEventsTotalTimes);\n\n assert.deepEqual(dataProvider.maxStackDepth(), 3);\n\n // The decorateEntry() will be handled in the TimelineFlameChartNetworkDataProvider, so this function always returns true.\n assert.isTrue(dataProvider.forceDecoration(0));\n\n assert.isFalse(dataProvider.isEmpty());\n\n // The network track is default to collapsed.\n assert.isFalse(dataProvider.isExpanded());\n // The height of collapsed network track style is 17.\n assert.strictEqual(dataProvider.preferredHeight(), 17);\n networkTrackGroup.expanded = true;\n assert.isTrue(dataProvider.isExpanded());\n // The max level here is 3, so `clamp(this.#maxLevel + 1, 7, 8.5)` = 7\n assert.strictEqual(dataProvider.preferredHeight(), 17 * 7);\n });\n\n it('can return the group for a given entryIndex', async function() {\n const dataProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider();\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'load-simple.json.gz');\n dataProvider.setModel(parsedTrace);\n dataProvider.timelineData();\n\n assert.strictEqual(\n dataProvider.groupForEvent(0)?.name,\n 'Network',\n );\n });\n\n it('filters navigations to only return those that happen on the main frame', async function() {\n const dataProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider();\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'multiple-navigations-with-iframes.json.gz');\n\n const minTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min);\n const maxTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max);\n\n dataProvider.setModel(parsedTrace);\n dataProvider.setWindowTimes(minTime, maxTime);\n\n const mainFrameID = parsedTrace.Meta.mainFrameId;\n const navigationEvents = dataProvider.mainFrameNavigationStartEvents();\n // Ensure that every navigation event that we return is for the main frame.\n assert.isTrue(navigationEvents.every(navEvent => {\n return navEvent.args.frame === mainFrameID;\n }));\n });\n\n it('can provide the index for an event and the event for a given index', async function() {\n const dataProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider();\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n dataProvider.setModel(parsedTrace);\n\n const event = dataProvider.eventByIndex(0);\n assert.isOk(event);\n assert.strictEqual(dataProvider.indexForEvent(event), 0);\n });\n\n it('does not render the network track if there is no network requests', async function() {\n const dataProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider();\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'basic.json.gz');\n\n const minTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min);\n const maxTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max);\n\n dataProvider.setModel(parsedTrace);\n dataProvider.setWindowTimes(minTime, maxTime);\n\n // Network track appender won't append the network track if there is no network requests.\n assert.strictEqual(dataProvider.timelineData().groups.length, 0);\n\n assert.deepEqual(dataProvider.minimumBoundary(), minTime);\n assert.deepEqual(dataProvider.totalTime(), maxTime - minTime);\n\n assert.deepEqual(dataProvider.timelineData().entryLevels, []);\n assert.deepEqual(dataProvider.timelineData().entryStartTimes, []);\n assert.deepEqual(dataProvider.timelineData().entryTotalTimes, []);\n\n assert.deepEqual(dataProvider.maxStackDepth(), 0);\n\n // The decorateEntry() will be handled in the TimelineFlameChartNetworkDataProvider, so this function always returns true.\n assert.isTrue(dataProvider.forceDecoration(0));\n\n // The network track won't show if it is empty.\n assert.isTrue(dataProvider.isEmpty());\n\n assert.strictEqual(dataProvider.preferredHeight(), 0);\n });\n\n it('decorate a event correctly', async function() {\n const dataProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider();\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'cls-cluster-max-timeout.json.gz');\n // The field that is important of this test:\n // {\n // \"ts\": 183752441.977,\n // \"dur\": 183752670.454,\n // \"finishTime\": 183752669.23299998,\n // ...\n // \"timing\": {\n // \"pushStart\": 0,\n // \"receiveHeadersEnd\": 218.084,\n // \"requestTime\": 183752.449687,\n // \"sendEnd\": 13.01,\n // \"sendStart\": 12.792,\n // ...\n // },\n // \"priority\": \"VeryHigh\",\n // \"responseTime\": 1634222299.776\n // ...\n // }\n const event = parsedTrace.NetworkRequests.byTime[1];\n // So for this request:\n // The earliest event belonging to this request starts at 183752441.977.\n // This is used in flamechart to calculate unclippedBarX.\n // Start time is 183752441.977\n // End time is 183752670.454\n // Finish time is 183752669.233\n // request time is 183752.449687, but it is in second, so 183752449.687\n // in milliseconds.\n // sendStartTime is requestTime + sendStart = 183752462.479\n // headersEndTime is requestTime + receiveHeadersEnd = 183752667.771\n //\n // To calculate the pixel of a timestamp, we substrate the begin time from\n // it, then multiple the timeToPixelRatio and then add the unclippedBarX.\n // Then get the floor of the pixel.\n // So the pixel of sendStart is (183752462.479 - 183752441.977) + 10, in ts it will be 30.502000004053116.\n // So the pixel of headersEnd is (183752667.771 - 183752441.977) + 10, in ts it will be 235.79399999976158.\n // So the pixel of finish is (183752669.233 - 183752441.977) + 10, in ts it will be 237.25600001215935.\n // So the pixel of start is (183752441.977 - 183752441.977) + 10 = 10.\n // So the pixel of end is (183752670.454 - 183752441.977) + 10, in ts it will be 238.47699999809265.\n assert.deepEqual(dataProvider.getDecorationPixels(event, /* unclippedBarX= */ 10, /* timeToPixelRatio= */ 1), {\n sendStart: (183752462.479 - 183752441.977) + 10,\n headersEnd: (183752667.771 - 183752441.977) + 10,\n finish: (183752669.233 - 183752441.977) + 10,\n start: 10,\n end: (183752670.454 - 183752441.977) + 10,\n });\n });\n\n it('can search for entries within a given time-range', async function() {\n const dataProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider();\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n dataProvider.setModel(parsedTrace);\n const boundsMs = Trace.Helpers.Timing.traceWindowMilliSeconds(parsedTrace.Meta.traceBounds);\n dataProvider.setWindowTimes(boundsMs.min, boundsMs.max);\n\n const filter = new Timeline.TimelineFilters.TimelineRegExp(/app\\.js/i);\n const results = dataProvider.search(parsedTrace.Meta.traceBounds, filter);\n assert.lengthOf(results, 1);\n assert.deepEqual(results[0], {index: 8, startTimeMilli: 122411056.533, provider: 'network'});\n });\n});\n\nfunction assertTimestampEqual(actual: number, expected: number): void {\n assert.strictEqual(actual.toFixed(2), expected.toFixed(2));\n}\n\nfunction assertTimestampsEqual(actual: number[]|Float32Array|Float64Array, expected: number[]): void {\n assert.strictEqual(actual.length, expected.length);\n\n for (let i = 0; i < actual.length; i++) {\n assertTimestampEqual(actual[i], expected[i]);\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineFlameChartView.d.ts b/public/panels/timeline/TimelineFlameChartView.d.ts index 45bb549e3..3622bf6d7 100644 --- a/public/panels/timeline/TimelineFlameChartView.d.ts +++ b/public/panels/timeline/TimelineFlameChartView.d.ts @@ -1,4 +1,4 @@ -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; import * as UI from '../../ui/legacy/legacy.js'; import type * as TimelineComponents from './components/components.js'; @@ -32,8 +32,6 @@ export declare class TimelineFlameChartView extends UI.Widget.VBox implements Pe private readonly detailsView; private readonly onMainAddEntryLabelAnnotation; private readonly onNetworkAddEntryLabelAnnotation; - private readonly onMainEntriesLinkAnnotationCreated; - private readonly onNetworkEntriesLinkAnnotationCreated; private readonly onMainEntrySelected; private readonly onNetworkEntrySelected; private readonly groupBySetting; @@ -42,15 +40,22 @@ export declare class TimelineFlameChartView extends UI.Widget.VBox implements Pe private selectedSearchResult?; private searchRegex?; constructor(delegate: TimelineModeViewDelegate); + revealAnnotation(annotation: Trace.Types.File.Annotation): void; setActiveInsight(insight: TimelineComponents.Sidebar.ActiveInsight | null): void; + /** + * Replaces any existing overlays with the ones provided to this method. + * If `overlays` is null, reverts back to the original overlays provided by + * the insight. + */ + setOverlaysOverride(overlays: Overlays.Overlays.TimelineOverlay[] | null): void; runBrickBreakerGame(): void; isNetworkTrackShownForTests(): boolean; - getLinkSelectionAnnotation(): TraceEngine.Types.File.EntriesLinkAnnotation | null; + getLinkSelectionAnnotation(): Trace.Types.File.EntriesLinkAnnotation | null; getMainDataProvider(): TimelineFlameChartDataProvider; getNetworkDataProvider(): TimelineFlameChartNetworkDataProvider; refreshMainFlameChart(): void; extensionDataVisibilityChanged(): void; - windowChanged(windowStartTime: TraceEngine.Types.Timing.MilliSeconds, windowEndTime: TraceEngine.Types.Timing.MilliSeconds, animate: boolean): void; + windowChanged(windowStartTime: Trace.Types.Timing.MilliSeconds, windowEndTime: Trace.Types.Timing.MilliSeconds, animate: boolean): void; /** * @param startTime - the start time of the selection in MilliSeconds * @param endTime - the end time of the selection in MilliSeconds @@ -60,20 +65,26 @@ export declare class TimelineFlameChartView extends UI.Widget.VBox implements Pe getMainFlameChart(): PerfUI.FlameChart.FlameChart; getNetworkFlameChart(): PerfUI.FlameChart.FlameChart; updateSelectedGroup(flameChart: PerfUI.FlameChart.FlameChart, group: PerfUI.FlameChart.Group | null): void; - setModel(newTraceEngineData: TraceEngine.Handlers.Types.TraceParseData | null, isCpuProfile?: boolean): void; - setInsights(insights: TraceEngine.Insights.Types.TraceInsightData | null): void; + setModel(newParsedTrace: Trace.Handlers.Types.ParsedTrace | null, isCpuProfile?: boolean): void; + setInsights(insights: Trace.Insights.Types.TraceInsightSets | null): void; updateLinkSelectionAnnotation(dataProvider: TimelineFlameChartDataProvider | TimelineFlameChartNetworkDataProvider, entryIndex: number): void; private onEntryHovered; - highlightEvent(event: TraceEngine.Types.TraceEvents.TraceEventData | null): void; + highlightEvent(event: Trace.Types.Events.Event | null): void; willHide(): void; wasShown(): void; updateCountersGraphToggle(showMemoryGraph: boolean): void; - revealEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): void; - revealEventVertically(event: TraceEngine.Types.TraceEvents.TraceEventData): void; + revealEvent(event: Trace.Types.Events.Event): void; + revealEventVertically(event: Trace.Types.Events.Event): void; setSelectionAndReveal(selection: TimelineSelection | null): void; + /** + * Used to create multiple overlays at once without triggering a redraw for each one. + */ + bulkAddOverlays(overlays: Overlays.Overlays.TimelineOverlay[]): void; addOverlay(newOverlay: T): T; + bulkRemoveOverlays(overlays: Overlays.Overlays.TimelineOverlay[]): void; removeOverlay(removedOverlay: Overlays.Overlays.TimelineOverlay): void; updateExistingOverlay(existingOverlay: T, newData: Partial): void; + enterLabelEditMode(overlay: Overlays.Overlays.EntryLabel): void; private onAddEntryLabelAnnotation; onEntriesLinkAnnotationCreate(dataProvider: TimelineFlameChartDataProvider | TimelineFlameChartNetworkDataProvider, entryFromIndex: number): void; private onEntrySelected; diff --git a/public/panels/timeline/TimelineFlameChartView.js b/public/panels/timeline/TimelineFlameChartView.js index c4d1d4557..9b10a791f 100644 --- a/public/panels/timeline/TimelineFlameChartView.js +++ b/public/panels/timeline/TimelineFlameChartView.js @@ -7,11 +7,12 @@ import * as Platform from '../../core/platform/platform.js'; import * as Root from '../../core/root/root.js'; import * as SDK from '../../core/sdk/sdk.js'; import * as Bindings from '../../models/bindings/bindings.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as TraceBounds from '../../services/trace_bounds/trace_bounds.js'; import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; import * as UI from '../../ui/legacy/legacy.js'; import * as VisualLogging from '../../ui/visual_logging/visual_logging.js'; +import { getAnnotationEntries, getAnnotationWindow } from './AnnotationHelpers.js'; import { CountersGraph } from './CountersGraph.js'; import { SHOULD_SHOW_EASTER_EGG } from './EasterEgg.js'; import { ModificationsManager } from './ModificationsManager.js'; @@ -61,8 +62,8 @@ export class TimelineFlameChartView extends UI.Widget.VBox { detailsView; onMainAddEntryLabelAnnotation; onNetworkAddEntryLabelAnnotation; - onMainEntriesLinkAnnotationCreated; - onNetworkEntriesLinkAnnotationCreated; + #onMainEntriesLinkAnnotationCreated; + #onNetworkEntriesLinkAnnotationCreated; onMainEntrySelected; onNetworkEntrySelected; #boundRefreshAfterIgnoreList; @@ -74,8 +75,8 @@ export class TimelineFlameChartView extends UI.Widget.VBox { needsResizeToPreferredHeights; selectedSearchResult; searchRegex; - #traceEngineData; - #traceInsightsData = null; + #parsedTrace; + #traceInsightsSets = null; #selectedGroupName = null; #onTraceBoundsChangeBound = this.#onTraceBoundsChange.bind(this); #gameKeyMatches = 0; @@ -88,6 +89,7 @@ export class TimelineFlameChartView extends UI.Widget.VBox { // 'EntryTo' selection still needs to be updated. #linkSelectionAnnotation = null; #currentInsightOverlays = []; + #currentStoredOverlays = null; #activeInsight = null; #tooltipElement = document.createElement('div'); // We use an symbol as the loggable for each group. This is because @@ -101,7 +103,7 @@ export class TimelineFlameChartView extends UI.Widget.VBox { this.element.classList.add('timeline-flamechart'); this.delegate = delegate; this.eventListeners = []; - this.#traceEngineData = null; + this.#parsedTrace = null; const flameChartsContainer = new UI.Widget.VBox(); flameChartsContainer.element.classList.add('flame-charts-container'); // Create main and network flamecharts. @@ -193,6 +195,17 @@ export class TimelineFlameChartView extends UI.Widget.VBox { else if (action === 'Update') { ModificationsManager.activeManager()?.updateAnnotationOverlay(overlay); } + else if (action === 'CreateLink') { + console.assert(overlay.type === 'ENTRIES_LINK_CREATE_BUTTON', 'CreateLink should only be dispatched by ENTRIES_LINK_CREATE_BUTTON type overlay'); + if (overlay.type === 'ENTRIES_LINK_CREATE_BUTTON') { + this.removeOverlay(overlay); + this.#linkSelectionAnnotation = { + type: 'ENTRIES_LINK', + entryFrom: overlay.entry, + }; + ModificationsManager.activeManager()?.createAnnotation(this.#linkSelectionAnnotation); + } + } }); this.networkPane = new UI.Widget.VBox(); this.networkPane.setMinimumSize(23, 23); @@ -219,17 +232,13 @@ export class TimelineFlameChartView extends UI.Widget.VBox { this.detailsSplitWidget.show(this.element); this.onMainAddEntryLabelAnnotation = this.onAddEntryLabelAnnotation.bind(this, this.mainDataProvider); this.onNetworkAddEntryLabelAnnotation = this.onAddEntryLabelAnnotation.bind(this, this.networkDataProvider); - this.onMainEntriesLinkAnnotationCreated = event => { - this.onEntriesLinkAnnotationCreate(this.mainDataProvider, event.data.entryFromIndex); - }, this; - this.onNetworkEntriesLinkAnnotationCreated = event => { - this.onEntriesLinkAnnotationCreate(this.networkDataProvider, event.data.entryFromIndex); - }, this; + this.#onMainEntriesLinkAnnotationCreated = event => this.onEntriesLinkAnnotationCreate(this.mainDataProvider, event.data.entryFromIndex); + this.#onNetworkEntriesLinkAnnotationCreated = event => this.onEntriesLinkAnnotationCreate(this.networkDataProvider, event.data.entryFromIndex); if (Root.Runtime.experiments.isEnabled("perf-panel-annotations" /* Root.Runtime.ExperimentName.TIMELINE_ANNOTATIONS */)) { this.mainFlameChart.addEventListener("EntryLabelAnnotationAdded" /* PerfUI.FlameChart.Events.ENTRY_LABEL_ANNOTATION_ADDED */, this.onMainAddEntryLabelAnnotation, this); this.networkFlameChart.addEventListener("EntryLabelAnnotationAdded" /* PerfUI.FlameChart.Events.ENTRY_LABEL_ANNOTATION_ADDED */, this.onNetworkAddEntryLabelAnnotation, this); - this.mainFlameChart.addEventListener("EntriesLinkAnnotationCreated" /* PerfUI.FlameChart.Events.ENTRIES_LINK_ANNOTATION_CREATED */, this.onMainEntriesLinkAnnotationCreated, this); - this.networkFlameChart.addEventListener("EntriesLinkAnnotationCreated" /* PerfUI.FlameChart.Events.ENTRIES_LINK_ANNOTATION_CREATED */, this.onNetworkEntriesLinkAnnotationCreated, this); + this.mainFlameChart.addEventListener("EntriesLinkAnnotationCreated" /* PerfUI.FlameChart.Events.ENTRIES_LINK_ANNOTATION_CREATED */, this.#onMainEntriesLinkAnnotationCreated, this); + this.networkFlameChart.addEventListener("EntriesLinkAnnotationCreated" /* PerfUI.FlameChart.Events.ENTRIES_LINK_ANNOTATION_CREATED */, this.#onNetworkEntriesLinkAnnotationCreated, this); } this.onMainEntrySelected = this.onEntrySelected.bind(this, this.mainDataProvider); this.onNetworkEntrySelected = this.onEntrySelected.bind(this, this.networkDataProvider); @@ -245,6 +254,7 @@ export class TimelineFlameChartView extends UI.Widget.VBox { this.updateLinkSelectionAnnotation(this.networkDataProvider, event.data); }, this); this.element.addEventListener('keydown', this.#keydownHandler.bind(this)); + this.element.addEventListener('pointerdown', this.#pointerDownHandler.bind(this)); this.#boundRefreshAfterIgnoreList = this.#refreshAfterIgnoreList.bind(this); this.#selectedEvents = null; this.groupBySetting = Common.Settings.Settings.instance().createSetting('timeline-tree-group-by', AggregatedTimelineTreeView.GroupBy.None); @@ -252,46 +262,86 @@ export class TimelineFlameChartView extends UI.Widget.VBox { this.refreshMainFlameChart(); TraceBounds.TraceBounds.onChange(this.#onTraceBoundsChangeBound); } - setActiveInsight(insight) { - this.#activeInsight = insight; + #setOverlays(overlays) { + this.#currentInsightOverlays = overlays; + if (this.#currentInsightOverlays.length === 0) { + return; + } const traceBounds = TraceBounds.TraceBounds.BoundsManager.instance().state()?.micro.entireTraceBounds; + if (!traceBounds) { + return; + } + this.bulkAddOverlays(this.#currentInsightOverlays); + const entries = []; for (const overlay of this.#currentInsightOverlays) { - this.removeOverlay(overlay); + entries.push(...Overlays.Overlays.entriesForOverlay(overlay)); + } + for (const entry of entries) { + // Ensure that the track for the entries are open. + this.#expandEntryTrack(entry); + } + const overlaysBounds = Overlays.Overlays.traceWindowContainingOverlays(this.#currentInsightOverlays); + // Trace window covering all overlays expanded by 100% so that the overlays cover 50% of the visible window. + const expandedBounds = Trace.Helpers.Timing.expandWindowByPercentOrToOneMillisecond(overlaysBounds, traceBounds, 100); + // Set the timeline visible window and ignore the minimap bounds. This + // allows us to pick a visible window even if the overlays are outside of + // the current breadcrumb. If this happens, the event listener for + // BoundsManager changes in TimelineMiniMap will detect it and activate + // the correct breadcrumb for us. + TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(expandedBounds, { ignoreMiniMapBounds: true, shouldAnimate: true }); + // Reveal entry if we have one. + if (entries.length !== 0) { + const earliestEntry = entries.reduce((earliest, current) => (earliest.ts < current.ts ? earliest : current), entries[0]); + this.revealEventVertically(earliestEntry); + } + } + revealAnnotation(annotation) { + const traceBounds = TraceBounds.TraceBounds.BoundsManager.instance().state()?.micro.entireTraceBounds; + if (!traceBounds) { + return; } + const annotationWindow = getAnnotationWindow(annotation); + if (!annotationWindow) { + return; + } + const annotationEntries = getAnnotationEntries(annotation); + for (const entry of annotationEntries) { + this.#expandEntryTrack(entry); + } + const firstEntry = annotationEntries.at(0); + if (firstEntry) { + this.revealEventVertically(firstEntry); + } + // Trace window covering all overlays expanded by 100% so that the overlays cover 50% of the visible window. + const expandedBounds = Trace.Helpers.Timing.expandWindowByPercentOrToOneMillisecond(annotationWindow, traceBounds, 100); + TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(expandedBounds, { ignoreMiniMapBounds: true, shouldAnimate: true }); + } + setActiveInsight(insight) { + this.#activeInsight = insight; + this.#currentStoredOverlays = null; + const traceBounds = TraceBounds.TraceBounds.BoundsManager.instance().state()?.micro.entireTraceBounds; + this.bulkRemoveOverlays(this.#currentInsightOverlays); if (!this.#activeInsight || !traceBounds) { return; } if (insight) { const newInsightOverlays = insight.createOverlayFn(); - this.#currentInsightOverlays = newInsightOverlays; - if (this.#currentInsightOverlays.length === 0) { - return; - } - const entries = []; - for (const overlay of this.#currentInsightOverlays) { - this.addOverlay(overlay); - entries.push(...Overlays.Overlays.entriesForOverlay(overlay)); - } - for (const entry of entries) { - // Ensure that the track for the entries are open. - this.#expandEntryTrack(entry); - } - const overlaysBounds = Overlays.Overlays.traceWindowContainingOverlays(this.#currentInsightOverlays); - // Trace window covering all overlays expanded by 100% so that the overlays cover 50% of the visible window. - const expandedBounds = TraceEngine.Helpers.Timing.expandWindowByPercentOrToOneMillisecond(overlaysBounds, traceBounds, 100); - // Set the timeline visible window and ignore the minimap bounds. This - // allows us to pick a visible window even if the overlays are outside of - // the current breadcrumb. If this happens, the event listener for - // BoundsManager changes in TimelineMiniMap will detect it and activate - // the correct breadcrumb for us. - TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(expandedBounds, { ignoreMiniMapBounds: true, shouldAnimate: true }); - // Reveal entry if we have one. - if (entries.length !== 0) { - const earliestEntry = entries.reduce((earliest, current) => (earliest.ts < current.ts ? earliest : current), entries[0]); - this.revealEventVertically(earliestEntry); - } + this.#setOverlays(newInsightOverlays); } } + /** + * Replaces any existing overlays with the ones provided to this method. + * If `overlays` is null, reverts back to the original overlays provided by + * the insight. + */ + setOverlaysOverride(overlays) { + this.bulkRemoveOverlays(this.#currentInsightOverlays); + if (!this.#currentStoredOverlays) { + // This allows us to not need to call `createOverlayFn` multiple times. + this.#currentStoredOverlays = this.#currentInsightOverlays; + } + this.#setOverlays(overlays ?? this.#currentStoredOverlays); + } /** * Expands the track / group that the given entry is in. */ @@ -332,8 +382,29 @@ export class TimelineFlameChartView extends UI.Widget.VBox { }); } } + #pointerDownHandler(event) { + /** + * If the user is in the middle of creating an entry link annotation and + * right clicks, let's take that as a sign to exit and cancel. + * (buttons === 2 indicates a right click) + */ + if (event.buttons === 2 && this.#linkSelectionAnnotation) { + ModificationsManager.activeManager()?.removeAnnotation(this.#linkSelectionAnnotation); + this.#linkSelectionAnnotation = null; + event.stopPropagation(); + } + } #keydownHandler(event) { const keyCombo = 'fixme'; + /** + * If the user is in the middle of creating an entry link and hits Esc, + * cancel and clear out the pending annotation. + */ + if (event.key === 'Escape' && this.#linkSelectionAnnotation) { + ModificationsManager.activeManager()?.removeAnnotation(this.#linkSelectionAnnotation); + this.#linkSelectionAnnotation = null; + event.stopPropagation(); + } if (event.key === keyCombo[this.#gameKeyMatches]) { this.#gameKeyMatches++; clearTimeout(this.#gameTimeout); @@ -400,7 +471,7 @@ export class TimelineFlameChartView extends UI.Widget.VBox { this.refreshMainFlameChart(); } windowChanged(windowStartTime, windowEndTime, animate) { - TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(TraceEngine.Helpers.Timing.traceWindowFromMilliSeconds(TraceEngine.Types.Timing.MilliSeconds(windowStartTime), TraceEngine.Types.Timing.MilliSeconds(windowEndTime)), { shouldAnimate: animate }); + TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(Trace.Helpers.Timing.traceWindowFromMilliSeconds(Trace.Types.Timing.MilliSeconds(windowStartTime), Trace.Types.Timing.MilliSeconds(windowEndTime)), { shouldAnimate: animate }); } /** * @param startTime - the start time of the selection in MilliSeconds @@ -410,7 +481,7 @@ export class TimelineFlameChartView extends UI.Widget.VBox { updateRangeSelection(startTime, endTime) { this.delegate.select(TimelineSelection.fromRange(startTime, endTime)); if (Root.Runtime.experiments.isEnabled("perf-panel-annotations" /* Root.Runtime.ExperimentName.TIMELINE_ANNOTATIONS */)) { - const bounds = TraceEngine.Helpers.Timing.traceWindowFromMilliSeconds(TraceEngine.Types.Timing.MilliSeconds(startTime), TraceEngine.Types.Timing.MilliSeconds(endTime)); + const bounds = Trace.Helpers.Timing.traceWindowFromMilliSeconds(Trace.Types.Timing.MilliSeconds(startTime), Trace.Types.Timing.MilliSeconds(endTime)); // If the current time range annotation has a label, the range selection // for it is finished and we need to create a new time range annotations. if (this.#timeRangeSelectionAnnotation && !this.#timeRangeSelectionAnnotation?.label) { @@ -442,24 +513,24 @@ export class TimelineFlameChartView extends UI.Widget.VBox { this.#selectedEvents = group ? this.mainDataProvider.groupTreeEvents(group) : null; this.#updateDetailViews(); } - setModel(newTraceEngineData, isCpuProfile = false) { - if (newTraceEngineData === this.#traceEngineData) { + setModel(newParsedTrace, isCpuProfile = false) { + if (newParsedTrace === this.#parsedTrace) { return; } this.#selectedGroupName = null; - this.#traceEngineData = newTraceEngineData; + this.#parsedTrace = newParsedTrace; Common.EventTarget.removeEventListeners(this.eventListeners); this.#selectedEvents = null; - this.mainDataProvider.setModel(newTraceEngineData, isCpuProfile); - this.networkDataProvider.setModel(newTraceEngineData); + this.mainDataProvider.setModel(newParsedTrace, isCpuProfile); + this.networkDataProvider.setModel(newParsedTrace); this.#reset(); this.updateSearchResults(false, false); this.refreshMainFlameChart(); this.#updateFlameCharts(); } setInsights(insights) { - if (this.#traceInsightsData !== insights) { - this.#traceInsightsData = insights; + if (this.#traceInsightsSets !== insights) { + this.#traceInsightsSets = insights; } } #reset() { @@ -492,8 +563,8 @@ export class TimelineFlameChartView extends UI.Widget.VBox { this.mainFlameChart.scheduleUpdate(); } #updateDetailViews() { - this.countersView.setModel(this.#traceEngineData, this.#selectedEvents); - void this.detailsView.setModel(this.#traceEngineData, this.#selectedEvents, this.#traceInsightsData); + this.countersView.setModel(this.#parsedTrace, this.#selectedEvents); + void this.detailsView.setModel(this.#parsedTrace, this.#selectedEvents, this.#traceInsightsSets); } #updateFlameCharts() { this.mainFlameChart.scheduleUpdate(); @@ -535,17 +606,17 @@ export class TimelineFlameChartView extends UI.Widget.VBox { SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight(); const entryIndex = commonEvent.data; const event = this.mainDataProvider.eventByIndex(entryIndex); - if (!event || !this.#traceEngineData) { + if (!event || !this.#parsedTrace) { return; } - if (event instanceof TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame) { + if (event instanceof Trace.Handlers.ModelHandlers.Frames.TimelineFrame) { return; } - const target = targetForEvent(this.#traceEngineData, event); + const target = targetForEvent(this.#parsedTrace, event); if (!target) { return; } - const nodeIds = TraceEngine.Extras.FetchNodes.nodeIdsForEvent(this.#traceEngineData, event); + const nodeIds = Trace.Extras.FetchNodes.nodeIdsForEvent(this.#parsedTrace, event); for (const nodeId of nodeIds) { new SDK.DOMModel.DeferredDOMNode(target, nodeId).highlight(); } @@ -608,6 +679,7 @@ export class TimelineFlameChartView extends UI.Widget.VBox { this.networkFlameChart.setSelectedEntry(networkIndex); // Clear any existing entry selection. this.#overlays.removeOverlaysOfType('ENTRY_SELECTED'); + this.#overlays.removeOverlaysOfType('ENTRIES_LINK_CREATE_BUTTON'); // If: // 1. There is no selection, or the selection is not a range selection // AND 2. we have an active time range selection overlay @@ -628,7 +700,7 @@ export class TimelineFlameChartView extends UI.Widget.VBox { } // Create the entry selected overlay if the selection represents a frame or trace event (either network, or anything else) if (selection && - (TimelineSelection.isTraceEventSelection(selection.object) || + (TimelineSelection.isSelection(selection.object) || TimelineSelection.isSyntheticNetworkRequestDetailsEventSelection(selection.object) || TimelineSelection.isLegacyTimelineFrame(selection.object))) { this.addOverlay({ @@ -637,11 +709,26 @@ export class TimelineFlameChartView extends UI.Widget.VBox { }); } } + /** + * Used to create multiple overlays at once without triggering a redraw for each one. + */ + bulkAddOverlays(overlays) { + for (const overlay of overlays) { + this.#overlays.add(overlay); + } + this.#overlays.update(); + } addOverlay(newOverlay) { const overlay = this.#overlays.add(newOverlay); this.#overlays.update(); return overlay; } + bulkRemoveOverlays(overlays) { + for (const overlay of overlays) { + this.#overlays.remove(overlay); + } + this.#overlays.update(); + } removeOverlay(removedOverlay) { this.#overlays.remove(removedOverlay); this.#overlays.update(); @@ -650,10 +737,13 @@ export class TimelineFlameChartView extends UI.Widget.VBox { this.#overlays.updateExisting(existingOverlay, newData); this.#overlays.update(); } + enterLabelEditMode(overlay) { + this.#overlays.enterLabelEditMode(overlay); + } onAddEntryLabelAnnotation(dataProvider, event) { - const selection = dataProvider.createSelection(event.data); + const selection = dataProvider.createSelection(event.data.entryIndex); if (selection && - (TimelineSelection.isTraceEventSelection(selection.object) || + (TimelineSelection.isSelection(selection.object) || TimelineSelection.isSyntheticNetworkRequestDetailsEventSelection(selection.object) || TimelineSelection.isLegacyTimelineFrame(selection.object))) { this.setSelectionAndReveal(selection); @@ -662,6 +752,12 @@ export class TimelineFlameChartView extends UI.Widget.VBox { entry: selection.object, label: '', }); + if (event.data.withLinkCreationButton) { + this.addOverlay({ + type: 'ENTRIES_LINK_CREATE_BUTTON', + entry: selection.object, + }); + } } } onEntriesLinkAnnotationCreate(dataProvider, entryFromIndex) { @@ -679,7 +775,7 @@ export class TimelineFlameChartView extends UI.Widget.VBox { if (!selection) { return null; } - if (TimelineSelection.isTraceEventSelection(selection.object) || + if (TimelineSelection.isSelection(selection.object) || TimelineSelection.isSyntheticNetworkRequestDetailsEventSelection(selection.object)) { return selection.object; } diff --git a/public/panels/timeline/TimelineFlameChartView.js.map b/public/panels/timeline/TimelineFlameChartView.js.map index 58787a78f..847c3eb03 100644 --- a/public/panels/timeline/TimelineFlameChartView.js.map +++ b/public/panels/timeline/TimelineFlameChartView.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineFlameChartView.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineFlameChartView.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2016 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as Root from '../../core/root/root.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as Bindings from '../../models/bindings/bindings.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as TraceBounds from '../../services/trace_bounds/trace_bounds.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport type * as TimelineComponents from './components/components.js';\nimport {CountersGraph} from './CountersGraph.js';\nimport {SHOULD_SHOW_EASTER_EGG} from './EasterEgg.js';\nimport {ModificationsManager} from './ModificationsManager.js';\nimport * as Overlays from './overlays/overlays.js';\nimport {targetForEvent} from './TargetForEvent.js';\nimport {TimelineDetailsView} from './TimelineDetailsView.js';\nimport {TimelineRegExp} from './TimelineFilters.js';\nimport {\n Events as TimelineFlameChartDataProviderEvents,\n TimelineFlameChartDataProvider,\n} from './TimelineFlameChartDataProvider.js';\nimport {TimelineFlameChartNetworkDataProvider} from './TimelineFlameChartNetworkDataProvider.js';\nimport timelineFlameChartViewStyles from './timelineFlameChartView.css.js';\nimport {type TimelineModeViewDelegate} from './TimelinePanel.js';\nimport {TimelineSelection} from './TimelineSelection.js';\nimport {AggregatedTimelineTreeView} from './TimelineTreeView.js';\nimport {type TimelineMarkerStyle} from './TimelineUIUtils.js';\n\nconst UIStrings = {\n /**\n *@description Text in Timeline Flame Chart View of the Performance panel\n *@example {Frame} PH1\n *@example {10ms} PH2\n */\n sAtS: '{PH1} at {PH2}',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelineFlameChartView.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nconst MAX_HIGHLIGHTED_SEARCH_ELEMENTS: number = 200;\n\nexport class TimelineFlameChartView extends UI.Widget.VBox implements PerfUI.FlameChart.FlameChartDelegate,\n UI.SearchableView.Searchable {\n private readonly delegate: TimelineModeViewDelegate;\n /**\n * Tracks the indexes of matched entries when the user searches the panel.\n * Defaults to undefined which indicates the user has not searched.\n */\n private searchResults: PerfUI.FlameChart.DataProviderSearchResult[]|undefined = undefined;\n private eventListeners: Common.EventTarget.EventDescriptor[];\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n private readonly networkSplitWidget: UI.SplitWidget.SplitWidget;\n private mainDataProvider: TimelineFlameChartDataProvider;\n private readonly mainFlameChart: PerfUI.FlameChart.FlameChart;\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly networkFlameChartGroupExpansionSetting: Common.Settings.Setting;\n private networkDataProvider: TimelineFlameChartNetworkDataProvider;\n private readonly networkFlameChart: PerfUI.FlameChart.FlameChart;\n private readonly networkPane: UI.Widget.VBox;\n private readonly splitResizer: HTMLElement;\n private readonly chartSplitWidget: UI.SplitWidget.SplitWidget;\n private brickGame?: PerfUI.BrickBreaker.BrickBreaker;\n private readonly countersView: CountersGraph;\n private readonly detailsSplitWidget: UI.SplitWidget.SplitWidget;\n private readonly detailsView: TimelineDetailsView;\n private readonly onMainAddEntryLabelAnnotation: (event: Common.EventTarget.EventTargetEvent) => void;\n private readonly onNetworkAddEntryLabelAnnotation: (event: Common.EventTarget.EventTargetEvent) => void;\n private readonly onMainEntriesLinkAnnotationCreated:\n (event: Common.EventTarget.EventTargetEvent<{entryFromIndex: number}>) => void;\n private readonly onNetworkEntriesLinkAnnotationCreated:\n (event: Common.EventTarget.EventTargetEvent<{entryFromIndex: number}>) => void;\n private readonly onMainEntrySelected: (event: Common.EventTarget.EventTargetEvent) => void;\n private readonly onNetworkEntrySelected: (event: Common.EventTarget.EventTargetEvent) => void;\n readonly #boundRefreshAfterIgnoreList: () => void;\n #selectedEvents: TraceEngine.Types.TraceEvents.TraceEventData[]|null;\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly groupBySetting: Common.Settings.Setting;\n private searchableView!: UI.SearchableView.SearchableView;\n private needsResizeToPreferredHeights?: boolean;\n private selectedSearchResult?: PerfUI.FlameChart.DataProviderSearchResult;\n private searchRegex?: RegExp;\n #traceEngineData: TraceEngine.Handlers.Types.TraceParseData|null;\n #traceInsightsData: TraceEngine.Insights.Types.TraceInsightData|null = null;\n #selectedGroupName: string|null = null;\n #onTraceBoundsChangeBound = this.#onTraceBoundsChange.bind(this);\n #gameKeyMatches = 0;\n #gameTimeout = setTimeout(() => ({}), 0);\n\n #overlaysContainer: HTMLElement = document.createElement('div');\n #overlays: Overlays.Overlays.Overlays;\n\n #timeRangeSelectionAnnotation: TraceEngine.Types.File.TimeRangeAnnotation|null = null;\n // Keep track of the link annotation that hasn't been fully selected yet.\n // We only store it here when only 'entryFrom' has been selected and\n // 'EntryTo' selection still needs to be updated.\n #linkSelectionAnnotation: TraceEngine.Types.File.EntriesLinkAnnotation|null = null;\n\n #currentInsightOverlays: Array = [];\n #activeInsight: TimelineComponents.Sidebar.ActiveInsight|null = null;\n\n #tooltipElement = document.createElement('div');\n\n // We use an symbol as the loggable for each group. This is because\n // groups can get re-built at times and we need a common reference to act as\n // the reference for each group that we log. By storing these symbols in\n // a map keyed off the context of the group, we ensure we persist the\n // loggable even if the group gets rebuilt at some point in time.\n #loggableForGroupByLogContext: Map = new Map();\n\n constructor(delegate: TimelineModeViewDelegate) {\n super();\n this.element.classList.add('timeline-flamechart');\n\n this.delegate = delegate;\n this.eventListeners = [];\n this.#traceEngineData = null;\n\n const flameChartsContainer = new UI.Widget.VBox();\n flameChartsContainer.element.classList.add('flame-charts-container');\n\n // Create main and network flamecharts.\n this.networkSplitWidget = new UI.SplitWidget.SplitWidget(false, false, 'timeline-flamechart-main-view', 150);\n this.networkSplitWidget.show(flameChartsContainer.element);\n\n this.#overlaysContainer.classList.add('timeline-overlays-container');\n flameChartsContainer.element.appendChild(this.#overlaysContainer);\n\n this.#tooltipElement.classList.add('timeline-entry-tooltip-element');\n flameChartsContainer.element.appendChild(this.#tooltipElement);\n\n // Ensure that the network panel & resizer appears above the main thread.\n this.networkSplitWidget.sidebarElement().style.zIndex = '120';\n\n const mainViewGroupExpansionSetting =\n Common.Settings.Settings.instance().createSetting('timeline-flamechart-main-view-group-expansion', {});\n this.mainDataProvider = new TimelineFlameChartDataProvider();\n this.mainDataProvider.addEventListener(\n TimelineFlameChartDataProviderEvents.DATA_CHANGED, () => this.mainFlameChart.scheduleUpdate());\n this.mainFlameChart = new PerfUI.FlameChart.FlameChart(this.mainDataProvider, this, {\n groupExpansionSetting: mainViewGroupExpansionSetting,\n // The TimelineOverlays are used for selected elements\n selectedElementOutline: false,\n tooltipElement: this.#tooltipElement,\n useOverlaysForCursorRuler: true,\n });\n this.mainFlameChart.alwaysShowVerticalScroll();\n this.mainFlameChart.enableRuler(false);\n\n this.mainFlameChart.addEventListener(PerfUI.FlameChart.Events.LATEST_DRAW_DIMENSIONS, dimensions => {\n this.#overlays.updateChartDimensions('main', dimensions.data.chart);\n this.#overlays.updateVisibleWindow(dimensions.data.traceWindow);\n this.#overlays.update();\n });\n\n this.networkFlameChartGroupExpansionSetting =\n Common.Settings.Settings.instance().createSetting('timeline-flamechart-network-view-group-expansion', {});\n this.networkDataProvider = new TimelineFlameChartNetworkDataProvider();\n this.networkFlameChart = new PerfUI.FlameChart.FlameChart(this.networkDataProvider, this, {\n groupExpansionSetting: this.networkFlameChartGroupExpansionSetting,\n // The TimelineOverlays are used for selected elements\n selectedElementOutline: false,\n tooltipElement: this.#tooltipElement,\n useOverlaysForCursorRuler: true,\n });\n this.networkFlameChart.alwaysShowVerticalScroll();\n this.networkFlameChart.addEventListener(PerfUI.FlameChart.Events.LATEST_DRAW_DIMENSIONS, dimensions => {\n this.#overlays.updateChartDimensions('network', dimensions.data.chart);\n this.#overlays.updateVisibleWindow(dimensions.data.traceWindow);\n this.#overlays.update();\n\n // If the height of the network chart has changed, we need to tell the\n // main flame chart because its tooltips are positioned based in part on\n // the height of the network chart.\n this.mainFlameChart.setTooltipYPixelAdjustment(this.#overlays.networkChartOffsetHeight());\n });\n\n this.mainFlameChart.addEventListener(PerfUI.FlameChart.Events.MOUSE_MOVE, event => {\n this.#processFlameChartMouseMoveEvent(event.data);\n });\n\n this.networkFlameChart.addEventListener(PerfUI.FlameChart.Events.MOUSE_MOVE, event => {\n this.#processFlameChartMouseMoveEvent(event.data);\n });\n\n this.#overlays = new Overlays.Overlays.Overlays({\n container: this.#overlaysContainer,\n flameChartsContainers: {\n main: this.mainFlameChart.element,\n network: this.networkFlameChart.element,\n },\n charts: {\n mainChart: this.mainFlameChart,\n mainProvider: this.mainDataProvider,\n networkChart: this.networkFlameChart,\n networkProvider: this.networkDataProvider,\n },\n entryQueries: {\n isEntryCollapsedByUser: (entry: TraceEngine.Types.TraceEvents.TraceEventData): boolean => {\n return ModificationsManager.activeManager()?.getEntriesFilter().entryIsInvisible(entry) ?? false;\n },\n firstVisibleParentForEntry(entry) {\n return ModificationsManager.activeManager()?.getEntriesFilter().firstVisibleParentEntryForEntry(entry) ??\n null;\n },\n },\n });\n\n this.#overlays.addEventListener(Overlays.Overlays.AnnotationOverlayActionEvent.eventName, event => {\n const {overlay, action} = (event as Overlays.Overlays.AnnotationOverlayActionEvent);\n if (action === 'Remove') {\n // If the overlay removed is the current time range, set it to null so that\n // we would create a new time range overlay and annotation on the next time range selection instead\n // of trying to update the current overlay that does not exist.\n if (ModificationsManager.activeManager()?.getAnnotationByOverlay(overlay) ===\n this.#timeRangeSelectionAnnotation) {\n this.#timeRangeSelectionAnnotation = null;\n }\n ModificationsManager.activeManager()?.removeAnnotationOverlay(overlay);\n } else if (action === 'Update') {\n ModificationsManager.activeManager()?.updateAnnotationOverlay(overlay);\n }\n });\n\n this.networkPane = new UI.Widget.VBox();\n this.networkPane.setMinimumSize(23, 23);\n this.networkFlameChart.show(this.networkPane.element);\n this.splitResizer = this.networkPane.element.createChild('div', 'timeline-flamechart-resizer');\n this.networkSplitWidget.hideDefaultResizer(true);\n this.networkSplitWidget.installResizer(this.splitResizer);\n this.networkSplitWidget.setMainWidget(this.mainFlameChart);\n this.networkSplitWidget.setSidebarWidget(this.networkPane);\n\n // Create counters chart splitter.\n this.chartSplitWidget = new UI.SplitWidget.SplitWidget(false, true, 'timeline-counters-split-view-state');\n this.countersView = new CountersGraph(this.delegate);\n this.chartSplitWidget.setMainWidget(flameChartsContainer);\n this.chartSplitWidget.setSidebarWidget(this.countersView);\n this.chartSplitWidget.hideDefaultResizer();\n this.chartSplitWidget.installResizer((this.countersView.resizerElement() as Element));\n\n // Create top level properties splitter.\n this.detailsSplitWidget = new UI.SplitWidget.SplitWidget(false, true, 'timeline-panel-details-split-view-state');\n this.detailsSplitWidget.element.classList.add('timeline-details-split');\n this.detailsView = new TimelineDetailsView(delegate);\n this.detailsSplitWidget.installResizer(this.detailsView.headerElement());\n this.detailsSplitWidget.setMainWidget(this.chartSplitWidget);\n this.detailsSplitWidget.setSidebarWidget(this.detailsView);\n this.detailsSplitWidget.show(this.element);\n\n this.onMainAddEntryLabelAnnotation = this.onAddEntryLabelAnnotation.bind(this, this.mainDataProvider);\n this.onNetworkAddEntryLabelAnnotation = this.onAddEntryLabelAnnotation.bind(this, this.networkDataProvider);\n this.onMainEntriesLinkAnnotationCreated = event => {\n this.onEntriesLinkAnnotationCreate(this.mainDataProvider, event.data.entryFromIndex);\n }, this;\n this.onNetworkEntriesLinkAnnotationCreated = event => {\n this.onEntriesLinkAnnotationCreate(this.networkDataProvider, event.data.entryFromIndex);\n }, this;\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_ANNOTATIONS)) {\n this.mainFlameChart.addEventListener(\n PerfUI.FlameChart.Events.ENTRY_LABEL_ANNOTATION_ADDED, this.onMainAddEntryLabelAnnotation, this);\n this.networkFlameChart.addEventListener(\n PerfUI.FlameChart.Events.ENTRY_LABEL_ANNOTATION_ADDED, this.onNetworkAddEntryLabelAnnotation, this);\n\n this.mainFlameChart.addEventListener(\n PerfUI.FlameChart.Events.ENTRIES_LINK_ANNOTATION_CREATED, this.onMainEntriesLinkAnnotationCreated, this);\n this.networkFlameChart.addEventListener(\n PerfUI.FlameChart.Events.ENTRIES_LINK_ANNOTATION_CREATED, this.onNetworkEntriesLinkAnnotationCreated, this);\n }\n this.onMainEntrySelected = this.onEntrySelected.bind(this, this.mainDataProvider);\n this.onNetworkEntrySelected = this.onEntrySelected.bind(this, this.networkDataProvider);\n this.mainFlameChart.addEventListener(PerfUI.FlameChart.Events.ENTRY_SELECTED, this.onMainEntrySelected, this);\n this.mainFlameChart.addEventListener(PerfUI.FlameChart.Events.ENTRY_INVOKED, this.onMainEntrySelected, this);\n this.networkFlameChart.addEventListener(PerfUI.FlameChart.Events.ENTRY_SELECTED, this.onNetworkEntrySelected, this);\n this.networkFlameChart.addEventListener(PerfUI.FlameChart.Events.ENTRY_INVOKED, this.onNetworkEntrySelected, this);\n this.mainFlameChart.addEventListener(PerfUI.FlameChart.Events.ENTRY_HOVERED, event => {\n this.onEntryHovered(event);\n this.updateLinkSelectionAnnotation(this.mainDataProvider, event.data);\n }, this);\n this.networkFlameChart.addEventListener(PerfUI.FlameChart.Events.ENTRY_HOVERED, event => {\n this.updateLinkSelectionAnnotation(this.networkDataProvider, event.data);\n }, this);\n\n this.element.addEventListener('keydown', this.#keydownHandler.bind(this));\n this.#boundRefreshAfterIgnoreList = this.#refreshAfterIgnoreList.bind(this);\n this.#selectedEvents = null;\n\n this.groupBySetting = Common.Settings.Settings.instance().createSetting(\n 'timeline-tree-group-by', AggregatedTimelineTreeView.GroupBy.None);\n this.groupBySetting.addChangeListener(this.refreshMainFlameChart, this);\n this.refreshMainFlameChart();\n\n TraceBounds.TraceBounds.onChange(this.#onTraceBoundsChangeBound);\n }\n\n setActiveInsight(insight: TimelineComponents.Sidebar.ActiveInsight|null): void {\n this.#activeInsight = insight;\n const traceBounds = TraceBounds.TraceBounds.BoundsManager.instance().state()?.micro.entireTraceBounds;\n\n for (const overlay of this.#currentInsightOverlays) {\n this.removeOverlay(overlay);\n }\n\n if (!this.#activeInsight || !traceBounds) {\n return;\n }\n\n if (insight) {\n const newInsightOverlays = insight.createOverlayFn();\n this.#currentInsightOverlays = newInsightOverlays;\n if (this.#currentInsightOverlays.length === 0) {\n return;\n }\n\n const entries: TraceEngine.Types.TraceEvents.TraceEventData[] = [];\n\n for (const overlay of this.#currentInsightOverlays) {\n this.addOverlay(overlay);\n\n entries.push(...Overlays.Overlays.entriesForOverlay(overlay));\n }\n\n for (const entry of entries) {\n // Ensure that the track for the entries are open.\n this.#expandEntryTrack(entry);\n }\n\n const overlaysBounds = Overlays.Overlays.traceWindowContainingOverlays(this.#currentInsightOverlays);\n // Trace window covering all overlays expanded by 100% so that the overlays cover 50% of the visible window.\n const expandedBounds =\n TraceEngine.Helpers.Timing.expandWindowByPercentOrToOneMillisecond(overlaysBounds, traceBounds, 100);\n\n // Set the timeline visible window and ignore the minimap bounds. This\n // allows us to pick a visible window even if the overlays are outside of\n // the current breadcrumb. If this happens, the event listener for\n // BoundsManager changes in TimelineMiniMap will detect it and activate\n // the correct breadcrumb for us.\n TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(\n expandedBounds, {ignoreMiniMapBounds: true, shouldAnimate: true});\n\n // Reveal entry if we have one.\n if (entries.length !== 0) {\n const earliestEntry =\n entries.reduce((earliest, current) => (earliest.ts < current.ts ? earliest : current), entries[0]);\n this.revealEventVertically(earliestEntry);\n }\n }\n }\n\n /**\n * Expands the track / group that the given entry is in.\n */\n #expandEntryTrack(entry: TraceEngine.Types.TraceEvents.TraceEventData): void {\n const chartName = Overlays.Overlays.chartForEntry(entry);\n const provider = chartName === 'main' ? this.mainDataProvider : this.networkDataProvider;\n const entryChart = chartName === 'main' ? this.mainFlameChart : this.networkFlameChart;\n\n const entryIndex = provider.indexForEvent?.(entry) ?? null;\n if (entryIndex === null) {\n return;\n }\n\n const group = provider.groupForEvent?.(entryIndex) ?? null;\n if (!group) {\n return;\n }\n const groupIndex = provider.timelineData().groups.indexOf(group);\n\n if (!group.expanded && groupIndex > -1) {\n entryChart.toggleGroupExpand(groupIndex);\n }\n }\n\n #processFlameChartMouseMoveEvent(data: PerfUI.FlameChart.EventTypes['MouseMove']): void {\n const {mouseEvent, timeInMicroSeconds} = data;\n\n // If the user is no longer holding shift, remove any existing marker.\n if (!mouseEvent.shiftKey) {\n const removedCount = this.#overlays.removeOverlaysOfType('CURSOR_TIMESTAMP_MARKER');\n if (removedCount > 0) {\n // Don't trigger lots of updates on a mouse move if we didn't actually\n // remove any overlays.\n this.#overlays.update();\n }\n }\n\n if (!mouseEvent.metaKey && mouseEvent.shiftKey) {\n // CURSOR_TIMESTAMP_MARKER is a singleton; if one already exists it will\n // be updated rather than create an entirely new one.\n this.addOverlay({\n type: 'CURSOR_TIMESTAMP_MARKER',\n timestamp: timeInMicroSeconds,\n });\n }\n }\n\n #keydownHandler(event: KeyboardEvent): void {\n const keyCombo = 'fixme';\n if (event.key === keyCombo[this.#gameKeyMatches]) {\n this.#gameKeyMatches++;\n clearTimeout(this.#gameTimeout);\n this.#gameTimeout = setTimeout(() => {\n this.#gameKeyMatches = 0;\n }, 2000);\n } else {\n this.#gameKeyMatches = 0;\n clearTimeout(this.#gameTimeout);\n }\n if (this.#gameKeyMatches !== keyCombo.length) {\n return;\n }\n this.runBrickBreakerGame();\n }\n\n runBrickBreakerGame(): void {\n if (!SHOULD_SHOW_EASTER_EGG) {\n return;\n }\n if ([...this.element.childNodes].find(child => child instanceof PerfUI.BrickBreaker.BrickBreaker)) {\n return;\n }\n this.brickGame = new PerfUI.BrickBreaker.BrickBreaker(this.mainFlameChart);\n this.brickGame.classList.add('brick-game');\n this.element.append(this.brickGame);\n }\n\n #onTraceBoundsChange(event: TraceBounds.TraceBounds.StateChangedEvent): void {\n if (event.updateType === 'MINIMAP_BOUNDS') {\n // If the update type was a changing of the minimap bounds, we do not\n // need to redraw the timeline.\n return;\n }\n\n const visibleWindow = event.state.milli.timelineTraceWindow;\n const shouldAnimate = Boolean(event.options.shouldAnimate);\n this.mainFlameChart.setWindowTimes(visibleWindow.min, visibleWindow.max, shouldAnimate);\n this.networkDataProvider.setWindowTimes(visibleWindow.min, visibleWindow.max);\n this.networkFlameChart.setWindowTimes(visibleWindow.min, visibleWindow.max, shouldAnimate);\n // Updating search results can be very expensive. Debounce to avoid over-calling it.\n const debouncedUpdate = Common.Debouncer.debounce(() => {\n this.updateSearchResults(false, false);\n }, 100);\n debouncedUpdate();\n }\n\n isNetworkTrackShownForTests(): boolean {\n return this.networkSplitWidget.showMode() !== UI.SplitWidget.ShowMode.ONLY_MAIN;\n }\n\n getLinkSelectionAnnotation(): TraceEngine.Types.File.EntriesLinkAnnotation|null {\n return this.#linkSelectionAnnotation;\n }\n\n getMainDataProvider(): TimelineFlameChartDataProvider {\n return this.mainDataProvider;\n }\n\n getNetworkDataProvider(): TimelineFlameChartNetworkDataProvider {\n return this.networkDataProvider;\n }\n\n refreshMainFlameChart(): void {\n this.mainFlameChart.update();\n }\n\n extensionDataVisibilityChanged(): void {\n this.#reset();\n this.mainDataProvider.reset(true);\n this.mainDataProvider.timelineData(true);\n this.refreshMainFlameChart();\n }\n\n windowChanged(\n windowStartTime: TraceEngine.Types.Timing.MilliSeconds, windowEndTime: TraceEngine.Types.Timing.MilliSeconds,\n animate: boolean): void {\n TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(\n TraceEngine.Helpers.Timing.traceWindowFromMilliSeconds(\n TraceEngine.Types.Timing.MilliSeconds(windowStartTime),\n TraceEngine.Types.Timing.MilliSeconds(windowEndTime),\n ),\n {shouldAnimate: animate},\n );\n }\n\n /**\n * @param startTime - the start time of the selection in MilliSeconds\n * @param endTime - the end time of the selection in MilliSeconds\n * TODO(crbug.com/346312365): update the type definitions in ChartViewport.ts\n */\n updateRangeSelection(startTime: number, endTime: number): void {\n this.delegate.select(TimelineSelection.fromRange(startTime, endTime));\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_ANNOTATIONS)) {\n const bounds = TraceEngine.Helpers.Timing.traceWindowFromMilliSeconds(\n TraceEngine.Types.Timing.MilliSeconds(startTime),\n TraceEngine.Types.Timing.MilliSeconds(endTime),\n );\n\n // If the current time range annotation has a label, the range selection\n // for it is finished and we need to create a new time range annotations.\n if (this.#timeRangeSelectionAnnotation && !this.#timeRangeSelectionAnnotation?.label) {\n this.#timeRangeSelectionAnnotation.bounds = bounds;\n ModificationsManager.activeManager()?.updateAnnotation(this.#timeRangeSelectionAnnotation);\n } else {\n this.#timeRangeSelectionAnnotation = {\n type: 'TIME_RANGE',\n label: '',\n bounds,\n };\n ModificationsManager.activeManager()?.createAnnotation(this.#timeRangeSelectionAnnotation);\n }\n }\n }\n\n getMainFlameChart(): PerfUI.FlameChart.FlameChart {\n return this.mainFlameChart;\n }\n\n // This function is public for test purpose.\n getNetworkFlameChart(): PerfUI.FlameChart.FlameChart {\n return this.networkFlameChart;\n }\n\n updateSelectedGroup(flameChart: PerfUI.FlameChart.FlameChart, group: PerfUI.FlameChart.Group|null): void {\n if (flameChart !== this.mainFlameChart || this.#selectedGroupName === group?.name) {\n return;\n }\n this.#selectedGroupName = group?.name || null;\n this.#selectedEvents = group ? this.mainDataProvider.groupTreeEvents(group) : null;\n this.#updateDetailViews();\n }\n\n setModel(newTraceEngineData: TraceEngine.Handlers.Types.TraceParseData|null, isCpuProfile = false): void {\n if (newTraceEngineData === this.#traceEngineData) {\n return;\n }\n this.#selectedGroupName = null;\n this.#traceEngineData = newTraceEngineData;\n Common.EventTarget.removeEventListeners(this.eventListeners);\n this.#selectedEvents = null;\n this.mainDataProvider.setModel(newTraceEngineData, isCpuProfile);\n this.networkDataProvider.setModel(newTraceEngineData);\n this.#reset();\n this.updateSearchResults(false, false);\n this.refreshMainFlameChart();\n this.#updateFlameCharts();\n }\n\n setInsights(insights: TraceEngine.Insights.Types.TraceInsightData|null): void {\n if (this.#traceInsightsData !== insights) {\n this.#traceInsightsData = insights;\n }\n }\n\n #reset(): void {\n if (this.networkDataProvider.isEmpty()) {\n this.mainFlameChart.enableRuler(true);\n this.networkSplitWidget.hideSidebar();\n } else {\n this.mainFlameChart.enableRuler(false);\n this.networkSplitWidget.showBoth();\n this.resizeToPreferredHeights();\n }\n this.#overlays.reset();\n this.mainFlameChart.reset();\n this.networkFlameChart.reset();\n this.updateSearchResults(false, false);\n\n const traceBoundsState = TraceBounds.TraceBounds.BoundsManager.instance().state();\n if (!traceBoundsState) {\n throw new Error('TimelineFlameChartView could not set the window bounds.');\n }\n const visibleWindow = traceBoundsState.milli.timelineTraceWindow;\n this.mainFlameChart.setWindowTimes(visibleWindow.min, visibleWindow.max);\n this.networkDataProvider.setWindowTimes(visibleWindow.min, visibleWindow.max);\n this.networkFlameChart.setWindowTimes(visibleWindow.min, visibleWindow.max);\n }\n\n #refreshAfterIgnoreList(): void {\n // The ignore list will only affect Thread tracks, which will only be in main flame chart.\n // So just force recalculate and redraw the main flame chart here.\n this.mainDataProvider.timelineData(true);\n this.mainFlameChart.scheduleUpdate();\n }\n\n #updateDetailViews(): void {\n this.countersView.setModel(this.#traceEngineData, this.#selectedEvents);\n void this.detailsView.setModel(this.#traceEngineData, this.#selectedEvents, this.#traceInsightsData);\n }\n\n #updateFlameCharts(): void {\n this.mainFlameChart.scheduleUpdate();\n this.networkFlameChart.scheduleUpdate();\n\n this.#registerLoggableGroups();\n }\n\n #registerLoggableGroups(): void {\n const groups = [\n ...this.mainFlameChart.timelineData()?.groups ?? [],\n ...this.networkFlameChart.timelineData()?.groups ?? [],\n ];\n for (const group of groups) {\n if (!group.jslogContext) {\n continue;\n }\n const loggable = this.#loggableForGroupByLogContext.get(group.jslogContext) ?? Symbol(group.jslogContext);\n\n if (!this.#loggableForGroupByLogContext.has(group.jslogContext)) {\n // This is the first time this group has been created, so register its loggable.\n this.#loggableForGroupByLogContext.set(group.jslogContext, loggable);\n VisualLogging.registerLoggable(\n loggable, `${VisualLogging.section().context(`timeline.${group.jslogContext}`)}`, this.delegate.element);\n }\n }\n }\n\n // If an entry is hovered over and a creation of link annotation is in progress, update that annotation with a hovered entry.\n updateLinkSelectionAnnotation(\n dataProvider: TimelineFlameChartDataProvider|TimelineFlameChartNetworkDataProvider, entryIndex: number): void {\n if (!this.#linkSelectionAnnotation) {\n return;\n }\n const toSelectionObject = this.#selectionIfTraceEvent(entryIndex, dataProvider);\n\n if (toSelectionObject) {\n this.#linkSelectionAnnotation.entryTo = toSelectionObject;\n } else {\n delete this.#linkSelectionAnnotation['entryTo'];\n }\n ModificationsManager.activeManager()?.updateAnnotation(this.#linkSelectionAnnotation);\n }\n\n private onEntryHovered(commonEvent: Common.EventTarget.EventTargetEvent): void {\n SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight();\n const entryIndex = commonEvent.data;\n const event = this.mainDataProvider.eventByIndex(entryIndex);\n if (!event || !this.#traceEngineData) {\n return;\n }\n if (event instanceof TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame) {\n return;\n }\n\n const target = targetForEvent(this.#traceEngineData, event);\n if (!target) {\n return;\n }\n\n const nodeIds = TraceEngine.Extras.FetchNodes.nodeIdsForEvent(this.#traceEngineData, event);\n for (const nodeId of nodeIds) {\n new SDK.DOMModel.DeferredDOMNode(target, nodeId).highlight();\n }\n }\n\n highlightEvent(event: TraceEngine.Types.TraceEvents.TraceEventData|null): void {\n const entryIndex =\n event ? this.mainDataProvider.entryIndexForSelection(TimelineSelection.fromTraceEvent(event)) : -1;\n if (entryIndex >= 0) {\n this.mainFlameChart.highlightEntry(entryIndex);\n } else {\n this.mainFlameChart.hideHighlight();\n }\n }\n\n override willHide(): void {\n this.networkFlameChartGroupExpansionSetting.removeChangeListener(this.resizeToPreferredHeights, this);\n Bindings.IgnoreListManager.IgnoreListManager.instance().removeChangeListener(this.#boundRefreshAfterIgnoreList);\n }\n\n override wasShown(): void {\n this.registerCSSFiles([timelineFlameChartViewStyles]);\n this.networkFlameChartGroupExpansionSetting.addChangeListener(this.resizeToPreferredHeights, this);\n Bindings.IgnoreListManager.IgnoreListManager.instance().addChangeListener(this.#boundRefreshAfterIgnoreList);\n if (this.needsResizeToPreferredHeights) {\n this.resizeToPreferredHeights();\n }\n this.#updateFlameCharts();\n }\n\n updateCountersGraphToggle(showMemoryGraph: boolean): void {\n if (showMemoryGraph) {\n this.chartSplitWidget.showBoth();\n } else {\n this.chartSplitWidget.hideSidebar();\n }\n }\n\n revealEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): void {\n const mainIndex = this.mainDataProvider.indexForEvent(event);\n const networkIndex = this.networkDataProvider.indexForEvent(event);\n if (mainIndex) {\n this.mainFlameChart.revealEntry(mainIndex);\n } else if (networkIndex) {\n this.networkFlameChart.revealEntry(networkIndex);\n }\n }\n\n // Given an event, it reveals its position vertically\n revealEventVertically(event: TraceEngine.Types.TraceEvents.TraceEventData): void {\n const mainIndex = this.mainDataProvider.indexForEvent(event);\n const networkIndex = this.networkDataProvider.indexForEvent(event);\n if (mainIndex) {\n this.mainFlameChart.revealEntryVertically(mainIndex);\n } else if (networkIndex) {\n this.networkFlameChart.revealEntryVertically(networkIndex);\n }\n }\n\n setSelectionAndReveal(selection: TimelineSelection|null): void {\n const mainIndex = this.mainDataProvider.entryIndexForSelection(selection);\n const networkIndex = this.networkDataProvider.entryIndexForSelection(selection);\n this.mainFlameChart.setSelectedEntry(mainIndex);\n this.networkFlameChart.setSelectedEntry(networkIndex);\n\n // Clear any existing entry selection.\n this.#overlays.removeOverlaysOfType('ENTRY_SELECTED');\n // If:\n // 1. There is no selection, or the selection is not a range selection\n // AND 2. we have an active time range selection overlay\n // AND 3. The label of the selection is not empty\n // then we need to remove it.\n if ((selection === null || !TimelineSelection.isRangeSelection(selection.object)) &&\n this.#timeRangeSelectionAnnotation && !this.#timeRangeSelectionAnnotation.label) {\n ModificationsManager.activeManager()?.removeAnnotation(this.#timeRangeSelectionAnnotation);\n this.#timeRangeSelectionAnnotation = null;\n }\n\n let index = this.mainDataProvider.entryIndexForSelection(selection);\n this.mainFlameChart.setSelectedEntry(index);\n index = this.networkDataProvider.entryIndexForSelection(selection);\n this.networkFlameChart.setSelectedEntry(index);\n if (this.detailsView) {\n // TODO(crbug.com/1459265): Change to await after migration work.\n void this.detailsView.setSelection(selection);\n }\n\n // Create the entry selected overlay if the selection represents a frame or trace event (either network, or anything else)\n if (selection &&\n (TimelineSelection.isTraceEventSelection(selection.object) ||\n TimelineSelection.isSyntheticNetworkRequestDetailsEventSelection(selection.object) ||\n TimelineSelection.isLegacyTimelineFrame(selection.object))) {\n this.addOverlay({\n type: 'ENTRY_SELECTED',\n entry: selection.object,\n });\n }\n }\n\n addOverlay(newOverlay: T): T {\n const overlay = this.#overlays.add(newOverlay);\n this.#overlays.update();\n return overlay;\n }\n\n removeOverlay(removedOverlay: Overlays.Overlays.TimelineOverlay): void {\n this.#overlays.remove(removedOverlay);\n this.#overlays.update();\n }\n\n updateExistingOverlay(existingOverlay: T, newData: Partial): void {\n this.#overlays.updateExisting(existingOverlay, newData);\n this.#overlays.update();\n }\n\n private onAddEntryLabelAnnotation(\n dataProvider: TimelineFlameChartDataProvider|TimelineFlameChartNetworkDataProvider,\n event: Common.EventTarget.EventTargetEvent): void {\n const selection = dataProvider.createSelection(event.data);\n if (selection &&\n (TimelineSelection.isTraceEventSelection(selection.object) ||\n TimelineSelection.isSyntheticNetworkRequestDetailsEventSelection(selection.object) ||\n TimelineSelection.isLegacyTimelineFrame(selection.object))) {\n this.setSelectionAndReveal(selection);\n ModificationsManager.activeManager()?.createAnnotation({\n type: 'ENTRY_LABEL',\n entry: selection.object,\n label: '',\n });\n }\n }\n\n onEntriesLinkAnnotationCreate(\n dataProvider: TimelineFlameChartDataProvider|TimelineFlameChartNetworkDataProvider,\n entryFromIndex: number): void {\n const fromSelectionObject = (entryFromIndex) ? this.#selectionIfTraceEvent(entryFromIndex, dataProvider) : null;\n\n if (fromSelectionObject) {\n this.#linkSelectionAnnotation = {\n type: 'ENTRIES_LINK',\n entryFrom: fromSelectionObject,\n };\n ModificationsManager.activeManager()?.createAnnotation(this.#linkSelectionAnnotation);\n }\n }\n\n #selectionIfTraceEvent(\n index: number, dataProvider: TimelineFlameChartDataProvider|TimelineFlameChartNetworkDataProvider):\n TraceEngine.Types.TraceEvents.TraceEventData|TraceEngine.Types.TraceEvents.SyntheticNetworkRequest|null {\n const selection = dataProvider.createSelection(index);\n if (!selection) {\n return null;\n }\n\n if (TimelineSelection.isTraceEventSelection(selection.object) ||\n TimelineSelection.isSyntheticNetworkRequestDetailsEventSelection(selection.object)) {\n return selection.object;\n }\n\n if (TimelineSelection.isLegacyTimelineFrame(selection.object)) {\n return selection.object as TraceEngine.Types.TraceEvents.LegacyTimelineFrame;\n }\n\n return null;\n }\n\n private onEntrySelected(\n dataProvider: TimelineFlameChartDataProvider|TimelineFlameChartNetworkDataProvider,\n event: Common.EventTarget.EventTargetEvent): void {\n const data = dataProvider.timelineData();\n if (!data) {\n return;\n }\n const entryIndex = event.data;\n\n const entryLevel = data.entryLevels[entryIndex];\n\n // Find the group that contains this level and log a click for it.\n const group = groupForLevel(data.groups, entryLevel);\n if (group && group.jslogContext) {\n const loggable = this.#loggableForGroupByLogContext.get(group.jslogContext) ?? null;\n if (loggable) {\n VisualLogging.logClick(loggable, new MouseEvent('click'));\n }\n }\n\n dataProvider.buildFlowForInitiator(entryIndex);\n this.delegate.select(dataProvider.createSelection(entryIndex));\n\n if (this.#linkSelectionAnnotation) {\n this.handleToEntryOfLinkBetweenEntriesSelection(entryIndex);\n }\n }\n\n handleToEntryOfLinkBetweenEntriesSelection(toIndex: number): void {\n // If there is a link annotation in the process of being created when an empty\n // space in the Flamechart is clicked, delete the link being created.\n //\n // If an entry is clicked when a link between entries in created and the entry that an arrow\n // is pointing to is earlier than the one it starts from, switch 'to' and 'from' entries to\n // reverse the arrow.\n if (this.#linkSelectionAnnotation && toIndex === -1) {\n ModificationsManager.activeManager()?.removeAnnotation(this.#linkSelectionAnnotation);\n } else if (\n this.#linkSelectionAnnotation && this.#linkSelectionAnnotation?.entryTo &&\n (this.#linkSelectionAnnotation?.entryFrom.ts > this.#linkSelectionAnnotation?.entryTo.ts)) {\n const entryFrom = this.#linkSelectionAnnotation.entryFrom;\n const entryTo = this.#linkSelectionAnnotation.entryTo;\n this.#linkSelectionAnnotation.entryTo = entryFrom;\n this.#linkSelectionAnnotation.entryFrom = entryTo;\n ModificationsManager.activeManager()?.updateAnnotation(this.#linkSelectionAnnotation);\n }\n // Regardless of if the link in progress was deleted or the clicked entry is the final selection,\n // set the link selection in progress to null so a new one is created if the an event to create\n // of update the current link is dispatched.\n this.#linkSelectionAnnotation = null;\n }\n\n resizeToPreferredHeights(): void {\n if (!this.isShowing()) {\n this.needsResizeToPreferredHeights = true;\n return;\n }\n this.needsResizeToPreferredHeights = false;\n this.networkPane.element.classList.toggle(\n 'timeline-network-resizer-disabled', !this.networkDataProvider.isExpanded());\n this.networkSplitWidget.setSidebarSize(\n this.networkDataProvider.preferredHeight() + this.splitResizer.clientHeight + PerfUI.FlameChart.RulerHeight +\n 2);\n }\n\n setSearchableView(searchableView: UI.SearchableView.SearchableView): void {\n this.searchableView = searchableView;\n }\n\n // UI.SearchableView.Searchable implementation\n\n searchResultIndexForEntryIndex(index: number): number {\n if (!this.searchResults) {\n return -1;\n }\n return this.searchResults.findIndex(result => result.index === index);\n }\n\n jumpToNextSearchResult(): void {\n if (!this.searchResults || !this.searchResults.length) {\n return;\n }\n const index =\n typeof this.selectedSearchResult !== 'undefined' ? this.searchResults.indexOf(this.selectedSearchResult) : -1;\n this.#selectSearchResult(Platform.NumberUtilities.mod(index + 1, this.searchResults.length));\n }\n\n jumpToPreviousSearchResult(): void {\n if (!this.searchResults || !this.searchResults.length) {\n return;\n }\n const index =\n typeof this.selectedSearchResult !== 'undefined' ? this.searchResults.indexOf(this.selectedSearchResult) : 0;\n this.#selectSearchResult(Platform.NumberUtilities.mod(index - 1, this.searchResults.length));\n }\n\n supportsCaseSensitiveSearch(): boolean {\n return true;\n }\n\n supportsRegexSearch(): boolean {\n return true;\n }\n\n #selectSearchResult(searchResultIndex: number): void {\n this.searchableView.updateCurrentMatchIndex(searchResultIndex);\n const matchedResult = this.searchResults?.at(searchResultIndex) ?? null;\n if (!matchedResult) {\n return;\n }\n\n switch (matchedResult.provider) {\n case 'main': {\n this.delegate.select(this.mainDataProvider.createSelection(matchedResult.index));\n this.mainFlameChart.showPopoverForSearchResult(matchedResult.index);\n break;\n }\n case 'network': {\n this.delegate.select(this.networkDataProvider.createSelection(matchedResult.index));\n this.networkFlameChart.showPopoverForSearchResult(matchedResult.index);\n break;\n }\n case 'other':\n // TimelineFlameChartView only has main/network so we can ignore.\n break;\n default:\n Platform.assertNever(matchedResult.provider, `Unknown SearchResult[provider]: ${matchedResult.provider}`);\n }\n this.selectedSearchResult = matchedResult;\n }\n\n private updateSearchResults(shouldJump: boolean, jumpBackwards?: boolean): void {\n const traceBoundsState = TraceBounds.TraceBounds.BoundsManager.instance().state();\n if (!traceBoundsState) {\n return;\n }\n\n const oldSelectedSearchResult = this.selectedSearchResult;\n delete this.selectedSearchResult;\n this.searchResults = [];\n this.mainFlameChart.removeSearchResultHighlights();\n this.networkFlameChart.removeSearchResultHighlights();\n if (!this.searchRegex) {\n return;\n }\n const regExpFilter = new TimelineRegExp(this.searchRegex);\n const visibleWindow = traceBoundsState.micro.timelineTraceWindow;\n\n /**\n * Get the matches for the user's search result. We search both providers\n * but before storing the results we need to \"tag\" the results with the\n * provider they came from. We do this so that when the user highlights a\n * search result we know which flame chart to talk to to highlight it.\n */\n const mainMatches = this.mainDataProvider.search(visibleWindow, regExpFilter);\n const networkMatches = this.networkDataProvider.search(visibleWindow, regExpFilter);\n\n // Merge both result sets into one, sorted by start time. This means as the\n // user navigates back/forwards they will do so in time order and not do\n // all the main results before the network results, or some other\n // unexpected ordering.\n this.searchResults = mainMatches.concat(networkMatches).sort((m1, m2) => {\n return m1.startTimeMilli - m2.startTimeMilli;\n });\n\n this.searchableView.updateSearchMatchesCount(this.searchResults.length);\n\n // To avoid too many highlights when the search regex matches too many entries,\n // for example, when user only types in \"e\" as the search query,\n // We only highlight the search results when the number of matches is less than or equal to 200.\n if (this.searchResults.length <= MAX_HIGHLIGHTED_SEARCH_ELEMENTS) {\n this.mainFlameChart.highlightAllEntries(mainMatches.map(m => m.index));\n this.networkFlameChart.highlightAllEntries(networkMatches.map(m => m.index));\n }\n if (!shouldJump || !this.searchResults.length) {\n return;\n }\n let selectedIndex = this.#indexOfSearchResult(oldSelectedSearchResult);\n if (selectedIndex === -1) {\n selectedIndex = jumpBackwards ? this.searchResults.length - 1 : 0;\n }\n this.#selectSearchResult(selectedIndex);\n }\n\n #indexOfSearchResult(target?: PerfUI.FlameChart.DataProviderSearchResult): number {\n if (!target) {\n return -1;\n }\n\n return this.searchResults?.findIndex(result => {\n return result.provider === target.provider && result.index === target.index;\n }) ??\n -1;\n }\n\n /**\n * Returns the indexes of the elements that matched the most recent\n * query. Elements are indexed by the data provider and correspond\n * to their position in the data provider entry data array.\n * Public only for tests.\n */\n getSearchResults(): PerfUI.FlameChart.DataProviderSearchResult[]|undefined {\n return this.searchResults;\n }\n\n onSearchCanceled(): void {\n if (typeof this.selectedSearchResult !== 'undefined') {\n this.delegate.select(null);\n }\n delete this.searchResults;\n delete this.selectedSearchResult;\n delete this.searchRegex;\n this.mainFlameChart.showPopoverForSearchResult(-1);\n this.mainFlameChart.removeSearchResultHighlights();\n this.networkFlameChart.showPopoverForSearchResult(-1);\n this.networkFlameChart.removeSearchResultHighlights();\n }\n\n performSearch(searchConfig: UI.SearchableView.SearchConfig, shouldJump: boolean, jumpBackwards?: boolean): void {\n this.searchRegex = searchConfig.toSearchRegex().regex;\n this.updateSearchResults(shouldJump, jumpBackwards);\n }\n}\n\nexport class Selection {\n timelineSelection: TimelineSelection;\n entryIndex: number;\n constructor(selection: TimelineSelection, entryIndex: number) {\n this.timelineSelection = selection;\n this.entryIndex = entryIndex;\n }\n}\n\nexport const FlameChartStyle = {\n textColor: '#333',\n};\n\nexport class TimelineFlameChartMarker implements PerfUI.FlameChart.FlameChartMarker {\n private readonly startTimeInternal: number;\n private readonly startOffset: number;\n private style: TimelineMarkerStyle;\n constructor(startTime: number, startOffset: number, style: TimelineMarkerStyle) {\n this.startTimeInternal = startTime;\n this.startOffset = startOffset;\n this.style = style;\n }\n\n startTime(): number {\n return this.startTimeInternal;\n }\n\n color(): string {\n return this.style.color;\n }\n\n title(): string|null {\n if (this.style.lowPriority) {\n return null;\n }\n const startTime = i18n.TimeUtilities.millisToString(this.startOffset);\n return i18nString(UIStrings.sAtS, {PH1: this.style.title, PH2: startTime});\n }\n\n draw(context: CanvasRenderingContext2D, x: number, height: number, pixelsPerMillisecond: number): void {\n const lowPriorityVisibilityThresholdInPixelsPerMs = 4;\n\n if (this.style.lowPriority && pixelsPerMillisecond < lowPriorityVisibilityThresholdInPixelsPerMs) {\n return;\n }\n\n context.save();\n if (this.style.tall) {\n context.strokeStyle = this.style.color;\n context.lineWidth = this.style.lineWidth;\n context.translate(this.style.lineWidth < 1 || (this.style.lineWidth & 1) ? 0.5 : 0, 0.5);\n context.beginPath();\n context.moveTo(x, 0);\n context.setLineDash(this.style.dashStyle);\n context.lineTo(x, context.canvas.height);\n context.stroke();\n }\n context.restore();\n }\n}\n\nexport const enum ColorBy {\n URL = 'URL',\n}\n\n/**\n * Find the Group that contains the provided level, or `null` if no group is\n * found.\n */\nexport function groupForLevel(groups: PerfUI.FlameChart.Group[], level: number): PerfUI.FlameChart.Group|null {\n const groupForLevel = groups.find((group, groupIndex) => {\n const nextGroup = groups.at(groupIndex + 1);\n const groupEndLevel = nextGroup ? nextGroup.startLevel - 1 : Infinity;\n\n return group.startLevel <= level && groupEndLevel >= level;\n });\n return groupForLevel ?? null;\n}\n"]} \ No newline at end of file +{"version":3,"file":"TimelineFlameChartView.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineFlameChartView.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2016 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as Root from '../../core/root/root.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as Bindings from '../../models/bindings/bindings.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as TraceBounds from '../../services/trace_bounds/trace_bounds.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport {getAnnotationEntries, getAnnotationWindow} from './AnnotationHelpers.js';\nimport type * as TimelineComponents from './components/components.js';\nimport {CountersGraph} from './CountersGraph.js';\nimport {SHOULD_SHOW_EASTER_EGG} from './EasterEgg.js';\nimport {ModificationsManager} from './ModificationsManager.js';\nimport * as Overlays from './overlays/overlays.js';\nimport {targetForEvent} from './TargetForEvent.js';\nimport {TimelineDetailsView} from './TimelineDetailsView.js';\nimport {TimelineRegExp} from './TimelineFilters.js';\nimport {\n Events as TimelineFlameChartDataProviderEvents,\n TimelineFlameChartDataProvider,\n} from './TimelineFlameChartDataProvider.js';\nimport {TimelineFlameChartNetworkDataProvider} from './TimelineFlameChartNetworkDataProvider.js';\nimport timelineFlameChartViewStyles from './timelineFlameChartView.css.js';\nimport {type TimelineModeViewDelegate} from './TimelinePanel.js';\nimport {TimelineSelection} from './TimelineSelection.js';\nimport {AggregatedTimelineTreeView} from './TimelineTreeView.js';\nimport {type TimelineMarkerStyle} from './TimelineUIUtils.js';\n\nconst UIStrings = {\n /**\n *@description Text in Timeline Flame Chart View of the Performance panel\n *@example {Frame} PH1\n *@example {10ms} PH2\n */\n sAtS: '{PH1} at {PH2}',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelineFlameChartView.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nconst MAX_HIGHLIGHTED_SEARCH_ELEMENTS: number = 200;\n\nexport class TimelineFlameChartView extends UI.Widget.VBox implements PerfUI.FlameChart.FlameChartDelegate,\n UI.SearchableView.Searchable {\n private readonly delegate: TimelineModeViewDelegate;\n /**\n * Tracks the indexes of matched entries when the user searches the panel.\n * Defaults to undefined which indicates the user has not searched.\n */\n private searchResults: PerfUI.FlameChart.DataProviderSearchResult[]|undefined = undefined;\n private eventListeners: Common.EventTarget.EventDescriptor[];\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n private readonly networkSplitWidget: UI.SplitWidget.SplitWidget;\n private mainDataProvider: TimelineFlameChartDataProvider;\n private readonly mainFlameChart: PerfUI.FlameChart.FlameChart;\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly networkFlameChartGroupExpansionSetting: Common.Settings.Setting;\n private networkDataProvider: TimelineFlameChartNetworkDataProvider;\n private readonly networkFlameChart: PerfUI.FlameChart.FlameChart;\n private readonly networkPane: UI.Widget.VBox;\n private readonly splitResizer: HTMLElement;\n private readonly chartSplitWidget: UI.SplitWidget.SplitWidget;\n private brickGame?: PerfUI.BrickBreaker.BrickBreaker;\n private readonly countersView: CountersGraph;\n private readonly detailsSplitWidget: UI.SplitWidget.SplitWidget;\n private readonly detailsView: TimelineDetailsView;\n private readonly onMainAddEntryLabelAnnotation: (event: Common.EventTarget.EventTargetEvent<{\n entryIndex: number,\n withLinkCreationButton: boolean,\n }>) => void;\n private readonly onNetworkAddEntryLabelAnnotation: (event: Common.EventTarget.EventTargetEvent<{\n entryIndex: number,\n withLinkCreationButton: boolean,\n }>) => void;\n readonly #onMainEntriesLinkAnnotationCreated:\n (event: Common.EventTarget.EventTargetEvent<{entryFromIndex: number}>) => void;\n readonly #onNetworkEntriesLinkAnnotationCreated:\n (event: Common.EventTarget.EventTargetEvent<{entryFromIndex: number}>) => void;\n private readonly onMainEntrySelected: (event: Common.EventTarget.EventTargetEvent) => void;\n private readonly onNetworkEntrySelected: (event: Common.EventTarget.EventTargetEvent) => void;\n readonly #boundRefreshAfterIgnoreList: () => void;\n #selectedEvents: Trace.Types.Events.Event[]|null;\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private readonly groupBySetting: Common.Settings.Setting;\n private searchableView!: UI.SearchableView.SearchableView;\n private needsResizeToPreferredHeights?: boolean;\n private selectedSearchResult?: PerfUI.FlameChart.DataProviderSearchResult;\n private searchRegex?: RegExp;\n #parsedTrace: Trace.Handlers.Types.ParsedTrace|null;\n #traceInsightsSets: Trace.Insights.Types.TraceInsightSets|null = null;\n #selectedGroupName: string|null = null;\n #onTraceBoundsChangeBound = this.#onTraceBoundsChange.bind(this);\n #gameKeyMatches = 0;\n #gameTimeout = setTimeout(() => ({}), 0);\n\n #overlaysContainer: HTMLElement = document.createElement('div');\n #overlays: Overlays.Overlays.Overlays;\n\n #timeRangeSelectionAnnotation: Trace.Types.File.TimeRangeAnnotation|null = null;\n // Keep track of the link annotation that hasn't been fully selected yet.\n // We only store it here when only 'entryFrom' has been selected and\n // 'EntryTo' selection still needs to be updated.\n #linkSelectionAnnotation: Trace.Types.File.EntriesLinkAnnotation|null = null;\n\n #currentInsightOverlays: Array = [];\n #currentStoredOverlays: Array|null = null;\n #activeInsight: TimelineComponents.Sidebar.ActiveInsight|null = null;\n\n #tooltipElement = document.createElement('div');\n\n // We use an symbol as the loggable for each group. This is because\n // groups can get re-built at times and we need a common reference to act as\n // the reference for each group that we log. By storing these symbols in\n // a map keyed off the context of the group, we ensure we persist the\n // loggable even if the group gets rebuilt at some point in time.\n #loggableForGroupByLogContext: Map = new Map();\n\n constructor(delegate: TimelineModeViewDelegate) {\n super();\n this.element.classList.add('timeline-flamechart');\n\n this.delegate = delegate;\n this.eventListeners = [];\n this.#parsedTrace = null;\n\n const flameChartsContainer = new UI.Widget.VBox();\n flameChartsContainer.element.classList.add('flame-charts-container');\n\n // Create main and network flamecharts.\n this.networkSplitWidget = new UI.SplitWidget.SplitWidget(false, false, 'timeline-flamechart-main-view', 150);\n this.networkSplitWidget.show(flameChartsContainer.element);\n\n this.#overlaysContainer.classList.add('timeline-overlays-container');\n flameChartsContainer.element.appendChild(this.#overlaysContainer);\n\n this.#tooltipElement.classList.add('timeline-entry-tooltip-element');\n flameChartsContainer.element.appendChild(this.#tooltipElement);\n\n // Ensure that the network panel & resizer appears above the main thread.\n this.networkSplitWidget.sidebarElement().style.zIndex = '120';\n\n const mainViewGroupExpansionSetting =\n Common.Settings.Settings.instance().createSetting('timeline-flamechart-main-view-group-expansion', {});\n this.mainDataProvider = new TimelineFlameChartDataProvider();\n this.mainDataProvider.addEventListener(\n TimelineFlameChartDataProviderEvents.DATA_CHANGED, () => this.mainFlameChart.scheduleUpdate());\n this.mainFlameChart = new PerfUI.FlameChart.FlameChart(this.mainDataProvider, this, {\n groupExpansionSetting: mainViewGroupExpansionSetting,\n // The TimelineOverlays are used for selected elements\n selectedElementOutline: false,\n tooltipElement: this.#tooltipElement,\n useOverlaysForCursorRuler: true,\n });\n this.mainFlameChart.alwaysShowVerticalScroll();\n this.mainFlameChart.enableRuler(false);\n\n this.mainFlameChart.addEventListener(PerfUI.FlameChart.Events.LATEST_DRAW_DIMENSIONS, dimensions => {\n this.#overlays.updateChartDimensions('main', dimensions.data.chart);\n this.#overlays.updateVisibleWindow(dimensions.data.traceWindow);\n this.#overlays.update();\n });\n\n this.networkFlameChartGroupExpansionSetting =\n Common.Settings.Settings.instance().createSetting('timeline-flamechart-network-view-group-expansion', {});\n this.networkDataProvider = new TimelineFlameChartNetworkDataProvider();\n this.networkFlameChart = new PerfUI.FlameChart.FlameChart(this.networkDataProvider, this, {\n groupExpansionSetting: this.networkFlameChartGroupExpansionSetting,\n // The TimelineOverlays are used for selected elements\n selectedElementOutline: false,\n tooltipElement: this.#tooltipElement,\n useOverlaysForCursorRuler: true,\n });\n this.networkFlameChart.alwaysShowVerticalScroll();\n this.networkFlameChart.addEventListener(PerfUI.FlameChart.Events.LATEST_DRAW_DIMENSIONS, dimensions => {\n this.#overlays.updateChartDimensions('network', dimensions.data.chart);\n this.#overlays.updateVisibleWindow(dimensions.data.traceWindow);\n this.#overlays.update();\n\n // If the height of the network chart has changed, we need to tell the\n // main flame chart because its tooltips are positioned based in part on\n // the height of the network chart.\n this.mainFlameChart.setTooltipYPixelAdjustment(this.#overlays.networkChartOffsetHeight());\n });\n\n this.mainFlameChart.addEventListener(PerfUI.FlameChart.Events.MOUSE_MOVE, event => {\n this.#processFlameChartMouseMoveEvent(event.data);\n });\n\n this.networkFlameChart.addEventListener(PerfUI.FlameChart.Events.MOUSE_MOVE, event => {\n this.#processFlameChartMouseMoveEvent(event.data);\n });\n\n this.#overlays = new Overlays.Overlays.Overlays({\n container: this.#overlaysContainer,\n flameChartsContainers: {\n main: this.mainFlameChart.element,\n network: this.networkFlameChart.element,\n },\n charts: {\n mainChart: this.mainFlameChart,\n mainProvider: this.mainDataProvider,\n networkChart: this.networkFlameChart,\n networkProvider: this.networkDataProvider,\n },\n entryQueries: {\n isEntryCollapsedByUser: (entry: Trace.Types.Events.Event): boolean => {\n return ModificationsManager.activeManager()?.getEntriesFilter().entryIsInvisible(entry) ?? false;\n },\n firstVisibleParentForEntry(entry) {\n return ModificationsManager.activeManager()?.getEntriesFilter().firstVisibleParentEntryForEntry(entry) ??\n null;\n },\n },\n });\n\n this.#overlays.addEventListener(Overlays.Overlays.AnnotationOverlayActionEvent.eventName, event => {\n const {overlay, action} = (event as Overlays.Overlays.AnnotationOverlayActionEvent);\n if (action === 'Remove') {\n // If the overlay removed is the current time range, set it to null so that\n // we would create a new time range overlay and annotation on the next time range selection instead\n // of trying to update the current overlay that does not exist.\n if (ModificationsManager.activeManager()?.getAnnotationByOverlay(overlay) ===\n this.#timeRangeSelectionAnnotation) {\n this.#timeRangeSelectionAnnotation = null;\n }\n ModificationsManager.activeManager()?.removeAnnotationOverlay(overlay);\n } else if (action === 'Update') {\n ModificationsManager.activeManager()?.updateAnnotationOverlay(overlay);\n } else if (action === 'CreateLink') {\n console.assert(\n overlay.type === 'ENTRIES_LINK_CREATE_BUTTON',\n 'CreateLink should only be dispatched by ENTRIES_LINK_CREATE_BUTTON type overlay');\n if (overlay.type === 'ENTRIES_LINK_CREATE_BUTTON') {\n this.removeOverlay(overlay);\n\n this.#linkSelectionAnnotation = {\n type: 'ENTRIES_LINK',\n entryFrom: overlay.entry,\n };\n ModificationsManager.activeManager()?.createAnnotation(this.#linkSelectionAnnotation);\n }\n }\n });\n\n this.networkPane = new UI.Widget.VBox();\n this.networkPane.setMinimumSize(23, 23);\n this.networkFlameChart.show(this.networkPane.element);\n this.splitResizer = this.networkPane.element.createChild('div', 'timeline-flamechart-resizer');\n this.networkSplitWidget.hideDefaultResizer(true);\n this.networkSplitWidget.installResizer(this.splitResizer);\n this.networkSplitWidget.setMainWidget(this.mainFlameChart);\n this.networkSplitWidget.setSidebarWidget(this.networkPane);\n\n // Create counters chart splitter.\n this.chartSplitWidget = new UI.SplitWidget.SplitWidget(false, true, 'timeline-counters-split-view-state');\n this.countersView = new CountersGraph(this.delegate);\n this.chartSplitWidget.setMainWidget(flameChartsContainer);\n this.chartSplitWidget.setSidebarWidget(this.countersView);\n this.chartSplitWidget.hideDefaultResizer();\n this.chartSplitWidget.installResizer((this.countersView.resizerElement() as Element));\n\n // Create top level properties splitter.\n this.detailsSplitWidget = new UI.SplitWidget.SplitWidget(false, true, 'timeline-panel-details-split-view-state');\n this.detailsSplitWidget.element.classList.add('timeline-details-split');\n this.detailsView = new TimelineDetailsView(delegate);\n this.detailsSplitWidget.installResizer(this.detailsView.headerElement());\n this.detailsSplitWidget.setMainWidget(this.chartSplitWidget);\n this.detailsSplitWidget.setSidebarWidget(this.detailsView);\n this.detailsSplitWidget.show(this.element);\n\n this.onMainAddEntryLabelAnnotation = this.onAddEntryLabelAnnotation.bind(this, this.mainDataProvider);\n this.onNetworkAddEntryLabelAnnotation = this.onAddEntryLabelAnnotation.bind(this, this.networkDataProvider);\n this.#onMainEntriesLinkAnnotationCreated = event =>\n this.onEntriesLinkAnnotationCreate(this.mainDataProvider, event.data.entryFromIndex);\n this.#onNetworkEntriesLinkAnnotationCreated = event =>\n this.onEntriesLinkAnnotationCreate(this.networkDataProvider, event.data.entryFromIndex);\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_ANNOTATIONS)) {\n this.mainFlameChart.addEventListener(\n PerfUI.FlameChart.Events.ENTRY_LABEL_ANNOTATION_ADDED, this.onMainAddEntryLabelAnnotation, this);\n this.networkFlameChart.addEventListener(\n PerfUI.FlameChart.Events.ENTRY_LABEL_ANNOTATION_ADDED, this.onNetworkAddEntryLabelAnnotation, this);\n\n this.mainFlameChart.addEventListener(\n PerfUI.FlameChart.Events.ENTRIES_LINK_ANNOTATION_CREATED, this.#onMainEntriesLinkAnnotationCreated, this);\n this.networkFlameChart.addEventListener(\n PerfUI.FlameChart.Events.ENTRIES_LINK_ANNOTATION_CREATED, this.#onNetworkEntriesLinkAnnotationCreated, this);\n }\n this.onMainEntrySelected = this.onEntrySelected.bind(this, this.mainDataProvider);\n this.onNetworkEntrySelected = this.onEntrySelected.bind(this, this.networkDataProvider);\n this.mainFlameChart.addEventListener(PerfUI.FlameChart.Events.ENTRY_SELECTED, this.onMainEntrySelected, this);\n this.mainFlameChart.addEventListener(PerfUI.FlameChart.Events.ENTRY_INVOKED, this.onMainEntrySelected, this);\n this.networkFlameChart.addEventListener(PerfUI.FlameChart.Events.ENTRY_SELECTED, this.onNetworkEntrySelected, this);\n this.networkFlameChart.addEventListener(PerfUI.FlameChart.Events.ENTRY_INVOKED, this.onNetworkEntrySelected, this);\n this.mainFlameChart.addEventListener(PerfUI.FlameChart.Events.ENTRY_HOVERED, event => {\n this.onEntryHovered(event);\n this.updateLinkSelectionAnnotation(this.mainDataProvider, event.data);\n }, this);\n this.networkFlameChart.addEventListener(PerfUI.FlameChart.Events.ENTRY_HOVERED, event => {\n this.updateLinkSelectionAnnotation(this.networkDataProvider, event.data);\n }, this);\n\n this.element.addEventListener('keydown', this.#keydownHandler.bind(this));\n this.element.addEventListener('pointerdown', this.#pointerDownHandler.bind(this));\n this.#boundRefreshAfterIgnoreList = this.#refreshAfterIgnoreList.bind(this);\n this.#selectedEvents = null;\n\n this.groupBySetting = Common.Settings.Settings.instance().createSetting(\n 'timeline-tree-group-by', AggregatedTimelineTreeView.GroupBy.None);\n this.groupBySetting.addChangeListener(this.refreshMainFlameChart, this);\n this.refreshMainFlameChart();\n\n TraceBounds.TraceBounds.onChange(this.#onTraceBoundsChangeBound);\n }\n\n #setOverlays(overlays: Overlays.Overlays.TimelineOverlay[]): void {\n this.#currentInsightOverlays = overlays;\n if (this.#currentInsightOverlays.length === 0) {\n return;\n }\n\n const traceBounds = TraceBounds.TraceBounds.BoundsManager.instance().state()?.micro.entireTraceBounds;\n if (!traceBounds) {\n return;\n }\n\n this.bulkAddOverlays(this.#currentInsightOverlays);\n\n const entries: Trace.Types.Events.Event[] = [];\n for (const overlay of this.#currentInsightOverlays) {\n entries.push(...Overlays.Overlays.entriesForOverlay(overlay));\n }\n\n for (const entry of entries) {\n // Ensure that the track for the entries are open.\n this.#expandEntryTrack(entry);\n }\n\n const overlaysBounds = Overlays.Overlays.traceWindowContainingOverlays(this.#currentInsightOverlays);\n // Trace window covering all overlays expanded by 100% so that the overlays cover 50% of the visible window.\n const expandedBounds =\n Trace.Helpers.Timing.expandWindowByPercentOrToOneMillisecond(overlaysBounds, traceBounds, 100);\n\n // Set the timeline visible window and ignore the minimap bounds. This\n // allows us to pick a visible window even if the overlays are outside of\n // the current breadcrumb. If this happens, the event listener for\n // BoundsManager changes in TimelineMiniMap will detect it and activate\n // the correct breadcrumb for us.\n TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(\n expandedBounds, {ignoreMiniMapBounds: true, shouldAnimate: true});\n\n // Reveal entry if we have one.\n if (entries.length !== 0) {\n const earliestEntry =\n entries.reduce((earliest, current) => (earliest.ts < current.ts ? earliest : current), entries[0]);\n this.revealEventVertically(earliestEntry);\n }\n }\n\n revealAnnotation(annotation: Trace.Types.File.Annotation): void {\n const traceBounds = TraceBounds.TraceBounds.BoundsManager.instance().state()?.micro.entireTraceBounds;\n if (!traceBounds) {\n return;\n }\n\n const annotationWindow = getAnnotationWindow(annotation);\n if (!annotationWindow) {\n return;\n }\n\n const annotationEntries = getAnnotationEntries(annotation);\n\n for (const entry of annotationEntries) {\n this.#expandEntryTrack(entry);\n }\n const firstEntry = annotationEntries.at(0);\n if (firstEntry) {\n this.revealEventVertically(firstEntry);\n }\n\n // Trace window covering all overlays expanded by 100% so that the overlays cover 50% of the visible window.\n const expandedBounds =\n Trace.Helpers.Timing.expandWindowByPercentOrToOneMillisecond(annotationWindow, traceBounds, 100);\n TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(\n expandedBounds, {ignoreMiniMapBounds: true, shouldAnimate: true});\n }\n\n setActiveInsight(insight: TimelineComponents.Sidebar.ActiveInsight|null): void {\n this.#activeInsight = insight;\n this.#currentStoredOverlays = null;\n const traceBounds = TraceBounds.TraceBounds.BoundsManager.instance().state()?.micro.entireTraceBounds;\n this.bulkRemoveOverlays(this.#currentInsightOverlays);\n\n if (!this.#activeInsight || !traceBounds) {\n return;\n }\n\n if (insight) {\n const newInsightOverlays = insight.createOverlayFn();\n this.#setOverlays(newInsightOverlays);\n }\n }\n\n /**\n * Replaces any existing overlays with the ones provided to this method.\n * If `overlays` is null, reverts back to the original overlays provided by\n * the insight.\n */\n setOverlaysOverride(overlays: Overlays.Overlays.TimelineOverlay[]|null): void {\n this.bulkRemoveOverlays(this.#currentInsightOverlays);\n\n if (!this.#currentStoredOverlays) {\n // This allows us to not need to call `createOverlayFn` multiple times.\n this.#currentStoredOverlays = this.#currentInsightOverlays;\n }\n\n this.#setOverlays(overlays ?? this.#currentStoredOverlays);\n }\n\n /**\n * Expands the track / group that the given entry is in.\n */\n #expandEntryTrack(entry: Trace.Types.Events.Event): void {\n const chartName = Overlays.Overlays.chartForEntry(entry);\n const provider = chartName === 'main' ? this.mainDataProvider : this.networkDataProvider;\n const entryChart = chartName === 'main' ? this.mainFlameChart : this.networkFlameChart;\n\n const entryIndex = provider.indexForEvent?.(entry) ?? null;\n if (entryIndex === null) {\n return;\n }\n\n const group = provider.groupForEvent?.(entryIndex) ?? null;\n if (!group) {\n return;\n }\n const groupIndex = provider.timelineData().groups.indexOf(group);\n\n if (!group.expanded && groupIndex > -1) {\n entryChart.toggleGroupExpand(groupIndex);\n }\n }\n\n #processFlameChartMouseMoveEvent(data: PerfUI.FlameChart.EventTypes['MouseMove']): void {\n const {mouseEvent, timeInMicroSeconds} = data;\n\n // If the user is no longer holding shift, remove any existing marker.\n if (!mouseEvent.shiftKey) {\n const removedCount = this.#overlays.removeOverlaysOfType('CURSOR_TIMESTAMP_MARKER');\n if (removedCount > 0) {\n // Don't trigger lots of updates on a mouse move if we didn't actually\n // remove any overlays.\n this.#overlays.update();\n }\n }\n\n if (!mouseEvent.metaKey && mouseEvent.shiftKey) {\n // CURSOR_TIMESTAMP_MARKER is a singleton; if one already exists it will\n // be updated rather than create an entirely new one.\n this.addOverlay({\n type: 'CURSOR_TIMESTAMP_MARKER',\n timestamp: timeInMicroSeconds,\n });\n }\n }\n\n #pointerDownHandler(event: PointerEvent): void {\n /**\n * If the user is in the middle of creating an entry link annotation and\n * right clicks, let's take that as a sign to exit and cancel.\n * (buttons === 2 indicates a right click)\n */\n if (event.buttons === 2 && this.#linkSelectionAnnotation) {\n ModificationsManager.activeManager()?.removeAnnotation(this.#linkSelectionAnnotation);\n this.#linkSelectionAnnotation = null;\n event.stopPropagation();\n }\n }\n\n #keydownHandler(event: KeyboardEvent): void {\n const keyCombo = 'fixme';\n\n /**\n * If the user is in the middle of creating an entry link and hits Esc,\n * cancel and clear out the pending annotation.\n */\n if (event.key === 'Escape' && this.#linkSelectionAnnotation) {\n ModificationsManager.activeManager()?.removeAnnotation(this.#linkSelectionAnnotation);\n this.#linkSelectionAnnotation = null;\n event.stopPropagation();\n }\n\n if (event.key === keyCombo[this.#gameKeyMatches]) {\n this.#gameKeyMatches++;\n clearTimeout(this.#gameTimeout);\n this.#gameTimeout = setTimeout(() => {\n this.#gameKeyMatches = 0;\n }, 2000);\n } else {\n this.#gameKeyMatches = 0;\n clearTimeout(this.#gameTimeout);\n }\n if (this.#gameKeyMatches !== keyCombo.length) {\n return;\n }\n this.runBrickBreakerGame();\n }\n\n runBrickBreakerGame(): void {\n if (!SHOULD_SHOW_EASTER_EGG) {\n return;\n }\n if ([...this.element.childNodes].find(child => child instanceof PerfUI.BrickBreaker.BrickBreaker)) {\n return;\n }\n this.brickGame = new PerfUI.BrickBreaker.BrickBreaker(this.mainFlameChart);\n this.brickGame.classList.add('brick-game');\n this.element.append(this.brickGame);\n }\n\n #onTraceBoundsChange(event: TraceBounds.TraceBounds.StateChangedEvent): void {\n if (event.updateType === 'MINIMAP_BOUNDS') {\n // If the update type was a changing of the minimap bounds, we do not\n // need to redraw the timeline.\n return;\n }\n\n const visibleWindow = event.state.milli.timelineTraceWindow;\n const shouldAnimate = Boolean(event.options.shouldAnimate);\n this.mainFlameChart.setWindowTimes(visibleWindow.min, visibleWindow.max, shouldAnimate);\n this.networkDataProvider.setWindowTimes(visibleWindow.min, visibleWindow.max);\n this.networkFlameChart.setWindowTimes(visibleWindow.min, visibleWindow.max, shouldAnimate);\n // Updating search results can be very expensive. Debounce to avoid over-calling it.\n const debouncedUpdate = Common.Debouncer.debounce(() => {\n this.updateSearchResults(false, false);\n }, 100);\n debouncedUpdate();\n }\n\n isNetworkTrackShownForTests(): boolean {\n return this.networkSplitWidget.showMode() !== UI.SplitWidget.ShowMode.ONLY_MAIN;\n }\n\n getLinkSelectionAnnotation(): Trace.Types.File.EntriesLinkAnnotation|null {\n return this.#linkSelectionAnnotation;\n }\n\n getMainDataProvider(): TimelineFlameChartDataProvider {\n return this.mainDataProvider;\n }\n\n getNetworkDataProvider(): TimelineFlameChartNetworkDataProvider {\n return this.networkDataProvider;\n }\n\n refreshMainFlameChart(): void {\n this.mainFlameChart.update();\n }\n\n extensionDataVisibilityChanged(): void {\n this.#reset();\n this.mainDataProvider.reset(true);\n this.mainDataProvider.timelineData(true);\n this.refreshMainFlameChart();\n }\n\n windowChanged(\n windowStartTime: Trace.Types.Timing.MilliSeconds, windowEndTime: Trace.Types.Timing.MilliSeconds,\n animate: boolean): void {\n TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(\n Trace.Helpers.Timing.traceWindowFromMilliSeconds(\n Trace.Types.Timing.MilliSeconds(windowStartTime),\n Trace.Types.Timing.MilliSeconds(windowEndTime),\n ),\n {shouldAnimate: animate},\n );\n }\n\n /**\n * @param startTime - the start time of the selection in MilliSeconds\n * @param endTime - the end time of the selection in MilliSeconds\n * TODO(crbug.com/346312365): update the type definitions in ChartViewport.ts\n */\n updateRangeSelection(startTime: number, endTime: number): void {\n this.delegate.select(TimelineSelection.fromRange(startTime, endTime));\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_ANNOTATIONS)) {\n const bounds = Trace.Helpers.Timing.traceWindowFromMilliSeconds(\n Trace.Types.Timing.MilliSeconds(startTime),\n Trace.Types.Timing.MilliSeconds(endTime),\n );\n\n // If the current time range annotation has a label, the range selection\n // for it is finished and we need to create a new time range annotations.\n if (this.#timeRangeSelectionAnnotation && !this.#timeRangeSelectionAnnotation?.label) {\n this.#timeRangeSelectionAnnotation.bounds = bounds;\n ModificationsManager.activeManager()?.updateAnnotation(this.#timeRangeSelectionAnnotation);\n } else {\n this.#timeRangeSelectionAnnotation = {\n type: 'TIME_RANGE',\n label: '',\n bounds,\n };\n ModificationsManager.activeManager()?.createAnnotation(this.#timeRangeSelectionAnnotation);\n }\n }\n }\n\n getMainFlameChart(): PerfUI.FlameChart.FlameChart {\n return this.mainFlameChart;\n }\n\n // This function is public for test purpose.\n getNetworkFlameChart(): PerfUI.FlameChart.FlameChart {\n return this.networkFlameChart;\n }\n\n updateSelectedGroup(flameChart: PerfUI.FlameChart.FlameChart, group: PerfUI.FlameChart.Group|null): void {\n if (flameChart !== this.mainFlameChart || this.#selectedGroupName === group?.name) {\n return;\n }\n this.#selectedGroupName = group?.name || null;\n this.#selectedEvents = group ? this.mainDataProvider.groupTreeEvents(group) : null;\n this.#updateDetailViews();\n }\n\n setModel(newParsedTrace: Trace.Handlers.Types.ParsedTrace|null, isCpuProfile = false): void {\n if (newParsedTrace === this.#parsedTrace) {\n return;\n }\n this.#selectedGroupName = null;\n this.#parsedTrace = newParsedTrace;\n Common.EventTarget.removeEventListeners(this.eventListeners);\n this.#selectedEvents = null;\n this.mainDataProvider.setModel(newParsedTrace, isCpuProfile);\n this.networkDataProvider.setModel(newParsedTrace);\n this.#reset();\n this.updateSearchResults(false, false);\n this.refreshMainFlameChart();\n this.#updateFlameCharts();\n }\n\n setInsights(insights: Trace.Insights.Types.TraceInsightSets|null): void {\n if (this.#traceInsightsSets !== insights) {\n this.#traceInsightsSets = insights;\n }\n }\n\n #reset(): void {\n if (this.networkDataProvider.isEmpty()) {\n this.mainFlameChart.enableRuler(true);\n this.networkSplitWidget.hideSidebar();\n } else {\n this.mainFlameChart.enableRuler(false);\n this.networkSplitWidget.showBoth();\n this.resizeToPreferredHeights();\n }\n this.#overlays.reset();\n this.mainFlameChart.reset();\n this.networkFlameChart.reset();\n this.updateSearchResults(false, false);\n\n const traceBoundsState = TraceBounds.TraceBounds.BoundsManager.instance().state();\n if (!traceBoundsState) {\n throw new Error('TimelineFlameChartView could not set the window bounds.');\n }\n const visibleWindow = traceBoundsState.milli.timelineTraceWindow;\n this.mainFlameChart.setWindowTimes(visibleWindow.min, visibleWindow.max);\n this.networkDataProvider.setWindowTimes(visibleWindow.min, visibleWindow.max);\n this.networkFlameChart.setWindowTimes(visibleWindow.min, visibleWindow.max);\n }\n\n #refreshAfterIgnoreList(): void {\n // The ignore list will only affect Thread tracks, which will only be in main flame chart.\n // So just force recalculate and redraw the main flame chart here.\n this.mainDataProvider.timelineData(true);\n this.mainFlameChart.scheduleUpdate();\n }\n\n #updateDetailViews(): void {\n this.countersView.setModel(this.#parsedTrace, this.#selectedEvents);\n void this.detailsView.setModel(this.#parsedTrace, this.#selectedEvents, this.#traceInsightsSets);\n }\n\n #updateFlameCharts(): void {\n this.mainFlameChart.scheduleUpdate();\n this.networkFlameChart.scheduleUpdate();\n\n this.#registerLoggableGroups();\n }\n\n #registerLoggableGroups(): void {\n const groups = [\n ...this.mainFlameChart.timelineData()?.groups ?? [],\n ...this.networkFlameChart.timelineData()?.groups ?? [],\n ];\n for (const group of groups) {\n if (!group.jslogContext) {\n continue;\n }\n const loggable = this.#loggableForGroupByLogContext.get(group.jslogContext) ?? Symbol(group.jslogContext);\n\n if (!this.#loggableForGroupByLogContext.has(group.jslogContext)) {\n // This is the first time this group has been created, so register its loggable.\n this.#loggableForGroupByLogContext.set(group.jslogContext, loggable);\n VisualLogging.registerLoggable(\n loggable, `${VisualLogging.section().context(`timeline.${group.jslogContext}`)}`, this.delegate.element);\n }\n }\n }\n\n // If an entry is hovered over and a creation of link annotation is in progress, update that annotation with a hovered entry.\n updateLinkSelectionAnnotation(\n dataProvider: TimelineFlameChartDataProvider|TimelineFlameChartNetworkDataProvider, entryIndex: number): void {\n if (!this.#linkSelectionAnnotation) {\n return;\n }\n const toSelectionObject = this.#selectionIfTraceEvent(entryIndex, dataProvider);\n\n if (toSelectionObject) {\n this.#linkSelectionAnnotation.entryTo = toSelectionObject;\n } else {\n delete this.#linkSelectionAnnotation['entryTo'];\n }\n ModificationsManager.activeManager()?.updateAnnotation(this.#linkSelectionAnnotation);\n }\n\n private onEntryHovered(commonEvent: Common.EventTarget.EventTargetEvent): void {\n SDK.OverlayModel.OverlayModel.hideDOMNodeHighlight();\n const entryIndex = commonEvent.data;\n const event = this.mainDataProvider.eventByIndex(entryIndex);\n if (!event || !this.#parsedTrace) {\n return;\n }\n if (event instanceof Trace.Handlers.ModelHandlers.Frames.TimelineFrame) {\n return;\n }\n\n const target = targetForEvent(this.#parsedTrace, event);\n if (!target) {\n return;\n }\n\n const nodeIds = Trace.Extras.FetchNodes.nodeIdsForEvent(this.#parsedTrace, event);\n for (const nodeId of nodeIds) {\n new SDK.DOMModel.DeferredDOMNode(target, nodeId).highlight();\n }\n }\n\n highlightEvent(event: Trace.Types.Events.Event|null): void {\n const entryIndex =\n event ? this.mainDataProvider.entryIndexForSelection(TimelineSelection.fromTraceEvent(event)) : -1;\n if (entryIndex >= 0) {\n this.mainFlameChart.highlightEntry(entryIndex);\n } else {\n this.mainFlameChart.hideHighlight();\n }\n }\n\n override willHide(): void {\n this.networkFlameChartGroupExpansionSetting.removeChangeListener(this.resizeToPreferredHeights, this);\n Bindings.IgnoreListManager.IgnoreListManager.instance().removeChangeListener(this.#boundRefreshAfterIgnoreList);\n }\n\n override wasShown(): void {\n this.registerCSSFiles([timelineFlameChartViewStyles]);\n this.networkFlameChartGroupExpansionSetting.addChangeListener(this.resizeToPreferredHeights, this);\n Bindings.IgnoreListManager.IgnoreListManager.instance().addChangeListener(this.#boundRefreshAfterIgnoreList);\n if (this.needsResizeToPreferredHeights) {\n this.resizeToPreferredHeights();\n }\n this.#updateFlameCharts();\n }\n\n updateCountersGraphToggle(showMemoryGraph: boolean): void {\n if (showMemoryGraph) {\n this.chartSplitWidget.showBoth();\n } else {\n this.chartSplitWidget.hideSidebar();\n }\n }\n\n revealEvent(event: Trace.Types.Events.Event): void {\n const mainIndex = this.mainDataProvider.indexForEvent(event);\n const networkIndex = this.networkDataProvider.indexForEvent(event);\n if (mainIndex) {\n this.mainFlameChart.revealEntry(mainIndex);\n } else if (networkIndex) {\n this.networkFlameChart.revealEntry(networkIndex);\n }\n }\n\n // Given an event, it reveals its position vertically\n revealEventVertically(event: Trace.Types.Events.Event): void {\n const mainIndex = this.mainDataProvider.indexForEvent(event);\n const networkIndex = this.networkDataProvider.indexForEvent(event);\n if (mainIndex) {\n this.mainFlameChart.revealEntryVertically(mainIndex);\n } else if (networkIndex) {\n this.networkFlameChart.revealEntryVertically(networkIndex);\n }\n }\n\n setSelectionAndReveal(selection: TimelineSelection|null): void {\n const mainIndex = this.mainDataProvider.entryIndexForSelection(selection);\n const networkIndex = this.networkDataProvider.entryIndexForSelection(selection);\n this.mainFlameChart.setSelectedEntry(mainIndex);\n this.networkFlameChart.setSelectedEntry(networkIndex);\n\n // Clear any existing entry selection.\n this.#overlays.removeOverlaysOfType('ENTRY_SELECTED');\n this.#overlays.removeOverlaysOfType('ENTRIES_LINK_CREATE_BUTTON');\n // If:\n // 1. There is no selection, or the selection is not a range selection\n // AND 2. we have an active time range selection overlay\n // AND 3. The label of the selection is not empty\n // then we need to remove it.\n if ((selection === null || !TimelineSelection.isRangeSelection(selection.object)) &&\n this.#timeRangeSelectionAnnotation && !this.#timeRangeSelectionAnnotation.label) {\n ModificationsManager.activeManager()?.removeAnnotation(this.#timeRangeSelectionAnnotation);\n this.#timeRangeSelectionAnnotation = null;\n }\n\n let index = this.mainDataProvider.entryIndexForSelection(selection);\n this.mainFlameChart.setSelectedEntry(index);\n index = this.networkDataProvider.entryIndexForSelection(selection);\n this.networkFlameChart.setSelectedEntry(index);\n if (this.detailsView) {\n // TODO(crbug.com/1459265): Change to await after migration work.\n void this.detailsView.setSelection(selection);\n }\n\n // Create the entry selected overlay if the selection represents a frame or trace event (either network, or anything else)\n if (selection &&\n (TimelineSelection.isSelection(selection.object) ||\n TimelineSelection.isSyntheticNetworkRequestDetailsEventSelection(selection.object) ||\n TimelineSelection.isLegacyTimelineFrame(selection.object))) {\n this.addOverlay({\n type: 'ENTRY_SELECTED',\n entry: selection.object,\n });\n }\n }\n\n /**\n * Used to create multiple overlays at once without triggering a redraw for each one.\n */\n bulkAddOverlays(overlays: Overlays.Overlays.TimelineOverlay[]): void {\n for (const overlay of overlays) {\n this.#overlays.add(overlay);\n }\n this.#overlays.update();\n }\n\n addOverlay(newOverlay: T): T {\n const overlay = this.#overlays.add(newOverlay);\n this.#overlays.update();\n return overlay;\n }\n\n bulkRemoveOverlays(overlays: Overlays.Overlays.TimelineOverlay[]): void {\n for (const overlay of overlays) {\n this.#overlays.remove(overlay);\n }\n this.#overlays.update();\n }\n removeOverlay(removedOverlay: Overlays.Overlays.TimelineOverlay): void {\n this.#overlays.remove(removedOverlay);\n this.#overlays.update();\n }\n\n updateExistingOverlay(existingOverlay: T, newData: Partial): void {\n this.#overlays.updateExisting(existingOverlay, newData);\n this.#overlays.update();\n }\n\n enterLabelEditMode(overlay: Overlays.Overlays.EntryLabel): void {\n this.#overlays.enterLabelEditMode(overlay);\n }\n\n private onAddEntryLabelAnnotation(\n dataProvider: TimelineFlameChartDataProvider|TimelineFlameChartNetworkDataProvider,\n event: Common.EventTarget.EventTargetEvent<{entryIndex: number, withLinkCreationButton: boolean}>): void {\n const selection = dataProvider.createSelection(event.data.entryIndex);\n if (selection &&\n (TimelineSelection.isSelection(selection.object) ||\n TimelineSelection.isSyntheticNetworkRequestDetailsEventSelection(selection.object) ||\n TimelineSelection.isLegacyTimelineFrame(selection.object))) {\n this.setSelectionAndReveal(selection);\n ModificationsManager.activeManager()?.createAnnotation({\n type: 'ENTRY_LABEL',\n entry: selection.object,\n label: '',\n });\n if (event.data.withLinkCreationButton) {\n this.addOverlay({\n type: 'ENTRIES_LINK_CREATE_BUTTON',\n entry: selection.object,\n });\n }\n }\n }\n\n onEntriesLinkAnnotationCreate(\n dataProvider: TimelineFlameChartDataProvider|TimelineFlameChartNetworkDataProvider,\n entryFromIndex: number): void {\n const fromSelectionObject = (entryFromIndex) ? this.#selectionIfTraceEvent(entryFromIndex, dataProvider) : null;\n\n if (fromSelectionObject) {\n this.#linkSelectionAnnotation = {\n type: 'ENTRIES_LINK',\n entryFrom: fromSelectionObject,\n };\n ModificationsManager.activeManager()?.createAnnotation(this.#linkSelectionAnnotation);\n }\n }\n\n #selectionIfTraceEvent(\n index: number, dataProvider: TimelineFlameChartDataProvider|TimelineFlameChartNetworkDataProvider):\n Trace.Types.Events.Event|Trace.Types.Events.SyntheticNetworkRequest|null {\n const selection = dataProvider.createSelection(index);\n if (!selection) {\n return null;\n }\n\n if (TimelineSelection.isSelection(selection.object) ||\n TimelineSelection.isSyntheticNetworkRequestDetailsEventSelection(selection.object)) {\n return selection.object;\n }\n\n if (TimelineSelection.isLegacyTimelineFrame(selection.object)) {\n return selection.object as Trace.Types.Events.LegacyTimelineFrame;\n }\n\n return null;\n }\n\n private onEntrySelected(\n dataProvider: TimelineFlameChartDataProvider|TimelineFlameChartNetworkDataProvider,\n event: Common.EventTarget.EventTargetEvent): void {\n const data = dataProvider.timelineData();\n if (!data) {\n return;\n }\n const entryIndex = event.data;\n\n const entryLevel = data.entryLevels[entryIndex];\n\n // Find the group that contains this level and log a click for it.\n const group = groupForLevel(data.groups, entryLevel);\n if (group && group.jslogContext) {\n const loggable = this.#loggableForGroupByLogContext.get(group.jslogContext) ?? null;\n if (loggable) {\n VisualLogging.logClick(loggable, new MouseEvent('click'));\n }\n }\n\n dataProvider.buildFlowForInitiator(entryIndex);\n this.delegate.select(dataProvider.createSelection(entryIndex));\n\n if (this.#linkSelectionAnnotation) {\n this.handleToEntryOfLinkBetweenEntriesSelection(entryIndex);\n }\n }\n\n handleToEntryOfLinkBetweenEntriesSelection(toIndex: number): void {\n // If there is a link annotation in the process of being created when an empty\n // space in the Flamechart is clicked, delete the link being created.\n //\n // If an entry is clicked when a link between entries in created and the entry that an arrow\n // is pointing to is earlier than the one it starts from, switch 'to' and 'from' entries to\n // reverse the arrow.\n if (this.#linkSelectionAnnotation && toIndex === -1) {\n ModificationsManager.activeManager()?.removeAnnotation(this.#linkSelectionAnnotation);\n } else if (\n this.#linkSelectionAnnotation && this.#linkSelectionAnnotation?.entryTo &&\n (this.#linkSelectionAnnotation?.entryFrom.ts > this.#linkSelectionAnnotation?.entryTo.ts)) {\n const entryFrom = this.#linkSelectionAnnotation.entryFrom;\n const entryTo = this.#linkSelectionAnnotation.entryTo;\n this.#linkSelectionAnnotation.entryTo = entryFrom;\n this.#linkSelectionAnnotation.entryFrom = entryTo;\n ModificationsManager.activeManager()?.updateAnnotation(this.#linkSelectionAnnotation);\n }\n // Regardless of if the link in progress was deleted or the clicked entry is the final selection,\n // set the link selection in progress to null so a new one is created if the an event to create\n // of update the current link is dispatched.\n this.#linkSelectionAnnotation = null;\n }\n\n resizeToPreferredHeights(): void {\n if (!this.isShowing()) {\n this.needsResizeToPreferredHeights = true;\n return;\n }\n this.needsResizeToPreferredHeights = false;\n this.networkPane.element.classList.toggle(\n 'timeline-network-resizer-disabled', !this.networkDataProvider.isExpanded());\n this.networkSplitWidget.setSidebarSize(\n this.networkDataProvider.preferredHeight() + this.splitResizer.clientHeight + PerfUI.FlameChart.RulerHeight +\n 2);\n }\n\n setSearchableView(searchableView: UI.SearchableView.SearchableView): void {\n this.searchableView = searchableView;\n }\n\n // UI.SearchableView.Searchable implementation\n\n searchResultIndexForEntryIndex(index: number): number {\n if (!this.searchResults) {\n return -1;\n }\n return this.searchResults.findIndex(result => result.index === index);\n }\n\n jumpToNextSearchResult(): void {\n if (!this.searchResults || !this.searchResults.length) {\n return;\n }\n const index =\n typeof this.selectedSearchResult !== 'undefined' ? this.searchResults.indexOf(this.selectedSearchResult) : -1;\n this.#selectSearchResult(Platform.NumberUtilities.mod(index + 1, this.searchResults.length));\n }\n\n jumpToPreviousSearchResult(): void {\n if (!this.searchResults || !this.searchResults.length) {\n return;\n }\n const index =\n typeof this.selectedSearchResult !== 'undefined' ? this.searchResults.indexOf(this.selectedSearchResult) : 0;\n this.#selectSearchResult(Platform.NumberUtilities.mod(index - 1, this.searchResults.length));\n }\n\n supportsCaseSensitiveSearch(): boolean {\n return true;\n }\n\n supportsRegexSearch(): boolean {\n return true;\n }\n\n #selectSearchResult(searchResultIndex: number): void {\n this.searchableView.updateCurrentMatchIndex(searchResultIndex);\n const matchedResult = this.searchResults?.at(searchResultIndex) ?? null;\n if (!matchedResult) {\n return;\n }\n\n switch (matchedResult.provider) {\n case 'main': {\n this.delegate.select(this.mainDataProvider.createSelection(matchedResult.index));\n this.mainFlameChart.showPopoverForSearchResult(matchedResult.index);\n break;\n }\n case 'network': {\n this.delegate.select(this.networkDataProvider.createSelection(matchedResult.index));\n this.networkFlameChart.showPopoverForSearchResult(matchedResult.index);\n break;\n }\n case 'other':\n // TimelineFlameChartView only has main/network so we can ignore.\n break;\n default:\n Platform.assertNever(matchedResult.provider, `Unknown SearchResult[provider]: ${matchedResult.provider}`);\n }\n this.selectedSearchResult = matchedResult;\n }\n\n private updateSearchResults(shouldJump: boolean, jumpBackwards?: boolean): void {\n const traceBoundsState = TraceBounds.TraceBounds.BoundsManager.instance().state();\n if (!traceBoundsState) {\n return;\n }\n\n const oldSelectedSearchResult = this.selectedSearchResult;\n delete this.selectedSearchResult;\n this.searchResults = [];\n this.mainFlameChart.removeSearchResultHighlights();\n this.networkFlameChart.removeSearchResultHighlights();\n if (!this.searchRegex) {\n return;\n }\n const regExpFilter = new TimelineRegExp(this.searchRegex);\n const visibleWindow = traceBoundsState.micro.timelineTraceWindow;\n\n /**\n * Get the matches for the user's search result. We search both providers\n * but before storing the results we need to \"tag\" the results with the\n * provider they came from. We do this so that when the user highlights a\n * search result we know which flame chart to talk to to highlight it.\n */\n const mainMatches = this.mainDataProvider.search(visibleWindow, regExpFilter);\n const networkMatches = this.networkDataProvider.search(visibleWindow, regExpFilter);\n\n // Merge both result sets into one, sorted by start time. This means as the\n // user navigates back/forwards they will do so in time order and not do\n // all the main results before the network results, or some other\n // unexpected ordering.\n this.searchResults = mainMatches.concat(networkMatches).sort((m1, m2) => {\n return m1.startTimeMilli - m2.startTimeMilli;\n });\n\n this.searchableView.updateSearchMatchesCount(this.searchResults.length);\n\n // To avoid too many highlights when the search regex matches too many entries,\n // for example, when user only types in \"e\" as the search query,\n // We only highlight the search results when the number of matches is less than or equal to 200.\n if (this.searchResults.length <= MAX_HIGHLIGHTED_SEARCH_ELEMENTS) {\n this.mainFlameChart.highlightAllEntries(mainMatches.map(m => m.index));\n this.networkFlameChart.highlightAllEntries(networkMatches.map(m => m.index));\n }\n if (!shouldJump || !this.searchResults.length) {\n return;\n }\n let selectedIndex = this.#indexOfSearchResult(oldSelectedSearchResult);\n if (selectedIndex === -1) {\n selectedIndex = jumpBackwards ? this.searchResults.length - 1 : 0;\n }\n this.#selectSearchResult(selectedIndex);\n }\n\n #indexOfSearchResult(target?: PerfUI.FlameChart.DataProviderSearchResult): number {\n if (!target) {\n return -1;\n }\n\n return this.searchResults?.findIndex(result => {\n return result.provider === target.provider && result.index === target.index;\n }) ??\n -1;\n }\n\n /**\n * Returns the indexes of the elements that matched the most recent\n * query. Elements are indexed by the data provider and correspond\n * to their position in the data provider entry data array.\n * Public only for tests.\n */\n getSearchResults(): PerfUI.FlameChart.DataProviderSearchResult[]|undefined {\n return this.searchResults;\n }\n\n onSearchCanceled(): void {\n if (typeof this.selectedSearchResult !== 'undefined') {\n this.delegate.select(null);\n }\n delete this.searchResults;\n delete this.selectedSearchResult;\n delete this.searchRegex;\n this.mainFlameChart.showPopoverForSearchResult(-1);\n this.mainFlameChart.removeSearchResultHighlights();\n this.networkFlameChart.showPopoverForSearchResult(-1);\n this.networkFlameChart.removeSearchResultHighlights();\n }\n\n performSearch(searchConfig: UI.SearchableView.SearchConfig, shouldJump: boolean, jumpBackwards?: boolean): void {\n this.searchRegex = searchConfig.toSearchRegex().regex;\n this.updateSearchResults(shouldJump, jumpBackwards);\n }\n}\n\nexport class Selection {\n timelineSelection: TimelineSelection;\n entryIndex: number;\n constructor(selection: TimelineSelection, entryIndex: number) {\n this.timelineSelection = selection;\n this.entryIndex = entryIndex;\n }\n}\n\nexport const FlameChartStyle = {\n textColor: '#333',\n};\n\nexport class TimelineFlameChartMarker implements PerfUI.FlameChart.FlameChartMarker {\n private readonly startTimeInternal: number;\n private readonly startOffset: number;\n private style: TimelineMarkerStyle;\n constructor(startTime: number, startOffset: number, style: TimelineMarkerStyle) {\n this.startTimeInternal = startTime;\n this.startOffset = startOffset;\n this.style = style;\n }\n\n startTime(): number {\n return this.startTimeInternal;\n }\n\n color(): string {\n return this.style.color;\n }\n\n title(): string|null {\n if (this.style.lowPriority) {\n return null;\n }\n const startTime = i18n.TimeUtilities.millisToString(this.startOffset);\n return i18nString(UIStrings.sAtS, {PH1: this.style.title, PH2: startTime});\n }\n\n draw(context: CanvasRenderingContext2D, x: number, height: number, pixelsPerMillisecond: number): void {\n const lowPriorityVisibilityThresholdInPixelsPerMs = 4;\n\n if (this.style.lowPriority && pixelsPerMillisecond < lowPriorityVisibilityThresholdInPixelsPerMs) {\n return;\n }\n\n context.save();\n if (this.style.tall) {\n context.strokeStyle = this.style.color;\n context.lineWidth = this.style.lineWidth;\n context.translate(this.style.lineWidth < 1 || (this.style.lineWidth & 1) ? 0.5 : 0, 0.5);\n context.beginPath();\n context.moveTo(x, 0);\n context.setLineDash(this.style.dashStyle);\n context.lineTo(x, context.canvas.height);\n context.stroke();\n }\n context.restore();\n }\n}\n\nexport const enum ColorBy {\n URL = 'URL',\n}\n\n/**\n * Find the Group that contains the provided level, or `null` if no group is\n * found.\n */\nexport function groupForLevel(groups: PerfUI.FlameChart.Group[], level: number): PerfUI.FlameChart.Group|null {\n const groupForLevel = groups.find((group, groupIndex) => {\n const nextGroup = groups.at(groupIndex + 1);\n const groupEndLevel = nextGroup ? nextGroup.startLevel - 1 : Infinity;\n\n return group.startLevel <= level && groupEndLevel >= level;\n });\n return groupForLevel ?? null;\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineFlameChartView.test.js b/public/panels/timeline/TimelineFlameChartView.test.js index 23dc7667a..bf5aac071 100644 --- a/public/panels/timeline/TimelineFlameChartView.test.js +++ b/public/panels/timeline/TimelineFlameChartView.test.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as Bindings from '../../models/bindings/bindings.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import { describeWithEnvironment } from '../../testing/EnvironmentHelpers.js'; import { setupIgnoreListManagerEnvironment } from '../../testing/TraceHelpers.js'; import { TraceLoader } from '../../testing/TraceLoader.js'; @@ -52,14 +52,14 @@ describeWithEnvironment('TimelineFlameChartView', function () { }); }); it('Can search for events by name in the timeline', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'lcp-images.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'lcp-images.json.gz'); // The timeline flamechart view will invoke the `select` method // of this delegate every time an event has matched on a search. const mockViewDelegate = new MockViewDelegate(); const flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate); const searchableView = new UI.SearchableView.SearchableView(flameChartView, null); flameChartView.setSearchableView(searchableView); - flameChartView.setModel(traceData); + flameChartView.setModel(parsedTrace); const searchQuery = 'Paint'; const searchConfig = new UI.SearchableView.SearchConfig(/* query */ searchQuery, /* caseSensitive */ false, /* isRegex */ false); flameChartView.performSearch(searchConfig, true); @@ -75,7 +75,7 @@ describeWithEnvironment('TimelineFlameChartView', function () { assertSelectionName('PrePaint'); function assertSelectionName(name) { const selection = mockViewDelegate.selection; - if (!selection || !Timeline.TimelineSelection.TimelineSelection.isTraceEventSelection(selection.object)) { + if (!selection || !Timeline.TimelineSelection.TimelineSelection.isSelection(selection.object)) { throw new Error('Selection is not present or not a Trace Event'); } const object = selection.object; @@ -83,14 +83,14 @@ describeWithEnvironment('TimelineFlameChartView', function () { } }); it('can search across both flame charts for events', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); // The timeline flamechart view will invoke the `select` method // of this delegate every time an event has matched on a search. const mockViewDelegate = new MockViewDelegate(); const flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate); const searchableView = new UI.SearchableView.SearchableView(flameChartView, null); flameChartView.setSearchableView(searchableView); - flameChartView.setModel(traceData); + flameChartView.setModel(parsedTrace); const searchQuery = 'app.js'; const searchConfig = new UI.SearchableView.SearchConfig(/* query */ searchQuery, /* caseSensitive */ false, /* isRegex */ false); flameChartView.performSearch(searchConfig, true); @@ -104,28 +104,28 @@ describeWithEnvironment('TimelineFlameChartView', function () { // This test is still failing after bumping up the timeout to 20 seconds. So // skip it while we work on a fix for the trace load speed. it.skip('[crbug.com/1492405] Shows the network track correctly', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'load-simple.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'load-simple.json.gz'); // The timeline flamechart view will invoke the `select` method // of this delegate every time an event has matched on a search. const mockViewDelegate = new MockViewDelegate(); const flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate); - flameChartView.setModel(traceData); + flameChartView.setModel(parsedTrace); assert.isTrue(flameChartView.isNetworkTrackShownForTests()); }); it('Does not show the network track when there is no network request', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'basic.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'basic.json.gz'); // The timeline flamechart view will invoke the `select` method // of this delegate every time an event has matched on a search. const mockViewDelegate = new MockViewDelegate(); const flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate); - flameChartView.setModel(traceData); + flameChartView.setModel(parsedTrace); assert.isFalse(flameChartView.isNetworkTrackShownForTests()); }); it('Adds Hidden Descendants Arrow as a decoration when a Context Menu action is applied on a node', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'load-simple.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'load-simple.json.gz'); const mockViewDelegate = new MockViewDelegate(); const flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate); - flameChartView.setModel(traceData); + flameChartView.setModel(parsedTrace); // Find the main track to later collapse entries of const mainTrack = flameChartView.getMainFlameChart().timelineData()?.groups.find(group => { return group.name === 'Main — http://localhost:8080/'; @@ -136,13 +136,13 @@ describeWithEnvironment('TimelineFlameChartView', function () { // Find the first node that has children to collapse and is visible in the timeline const nodeOfGroup = flameChartView.getMainDataProvider().groupTreeEvents(mainTrack); const firstNodeWithChildren = nodeOfGroup?.find(node => { - const childrenAmount = traceData.Renderer.entryToNode.get(node)?.children.length; + const childrenAmount = parsedTrace.Renderer.entryToNode.get(node)?.children.length; if (!childrenAmount) { return false; } return childrenAmount > 0 && node.cat === 'devtools.timeline'; }); - const node = traceData.Renderer.entryToNode.get(firstNodeWithChildren); + const node = parsedTrace.Renderer.entryToNode.get(firstNodeWithChildren); if (!node) { throw new Error('Could not find a visible node with children'); } @@ -156,10 +156,10 @@ describeWithEnvironment('TimelineFlameChartView', function () { ]); }); it('Adds Hidden Descendants Arrow as a decoration when a Context Menu action is applied on a selected node with a key shortcut event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'load-simple.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'load-simple.json.gz'); const mockViewDelegate = new MockViewDelegate(); const flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate); - flameChartView.setModel(traceData); + flameChartView.setModel(parsedTrace); // Find the main track to later collapse entries of const mainTrack = flameChartView.getMainFlameChart().timelineData()?.groups.find(group => { return group.name === 'Main — http://localhost:8080/'; @@ -170,13 +170,13 @@ describeWithEnvironment('TimelineFlameChartView', function () { // Find the first node that has children to collapse and is visible in the timeline const nodeOfGroup = flameChartView.getMainDataProvider().groupTreeEvents(mainTrack); const firstNodeWithChildren = nodeOfGroup?.find(node => { - const childrenAmount = traceData.Renderer.entryToNode.get(node)?.children.length; + const childrenAmount = parsedTrace.Renderer.entryToNode.get(node)?.children.length; if (!childrenAmount) { return false; } return childrenAmount > 0 && node.cat === 'devtools.timeline'; }); - const node = traceData.Renderer.entryToNode.get(firstNodeWithChildren); + const node = parsedTrace.Renderer.entryToNode.get(firstNodeWithChildren); if (!node) { throw new Error('Could not find a visible node with children'); } @@ -192,10 +192,10 @@ describeWithEnvironment('TimelineFlameChartView', function () { ]); }); it('Removes Hidden Descendants Arrow as a decoration when Reset Children action is applied on a node', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'load-simple.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'load-simple.json.gz'); const mockViewDelegate = new MockViewDelegate(); const flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate); - flameChartView.setModel(traceData); + flameChartView.setModel(parsedTrace); Timeline.ModificationsManager.ModificationsManager.activeManager(); // Find the main track to later collapse entries of let mainTrack = flameChartView.getMainFlameChart().timelineData()?.groups.find(group => { @@ -207,13 +207,13 @@ describeWithEnvironment('TimelineFlameChartView', function () { // Find the first node that has children to collapse and is visible in the timeline const nodeOfGroup = flameChartView.getMainDataProvider().groupTreeEvents(mainTrack); const firstNodeWithChildren = nodeOfGroup?.find(node => { - const childrenAmount = traceData.Renderer.entryToNode.get(node)?.children.length; + const childrenAmount = parsedTrace.Renderer.entryToNode.get(node)?.children.length; if (!childrenAmount) { return false; } return childrenAmount > 0 && node.cat === 'devtools.timeline'; }); - const node = traceData.Renderer.entryToNode.get(firstNodeWithChildren); + const node = parsedTrace.Renderer.entryToNode.get(firstNodeWithChildren); if (!node) { throw new Error('Could not find a visible node with children'); } @@ -240,12 +240,12 @@ describeWithEnvironment('TimelineFlameChartView', function () { }); describe('Context Menu', function () { let flameChartView; - let traceData; + let parsedTrace; this.beforeEach(async () => { - ({ traceData } = await TraceLoader.traceEngine(this, 'recursive-blocking-js.json.gz')); + ({ parsedTrace } = await TraceLoader.traceEngine(this, 'recursive-blocking-js.json.gz')); const mockViewDelegate = new MockViewDelegate(); flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate); - flameChartView.setModel(traceData); + flameChartView.setModel(parsedTrace); Timeline.ModificationsManager.ModificationsManager.activeManager(); }); it('Does not create customized Context Menu for network track', async function () { @@ -585,10 +585,10 @@ describeWithEnvironment('TimelineFlameChartView', function () { .enabled, true); }); it('When an entry has URL and is not ignored, correctly show the Add script to ignore list in the Context Menu action', async function () { - const mainThread = getMainThread(traceData.Renderer); + const mainThread = getMainThread(parsedTrace.Renderer); const entryWithUrl = findFirstEntry(mainThread.entries, entry => { // Let's find the first entry with URL. - return TraceEngine.Types.TraceEvents.isProfileCall(entry) && Boolean(entry.callFrame.url); + return Trace.Types.Events.isProfileCall(entry) && Boolean(entry.callFrame.url); }); generateContextMenuForNode(entryWithUrl); assert.strictEqual(flameChartView.getMainFlameChart().getContextMenu()?.defaultSection().items.length, 6); @@ -600,10 +600,10 @@ describeWithEnvironment('TimelineFlameChartView', function () { .label, 'Add script to ignore list'); }); it('When an entry has URL and is ignored, correctly show the Remove script from ignore list in the Context Menu action', async function () { - const mainThread = getMainThread(traceData.Renderer); + const mainThread = getMainThread(parsedTrace.Renderer); const entryWithIgnoredUrl = findFirstEntry(mainThread.entries, entry => { // Let's find the first entry with URL. - return TraceEngine.Types.TraceEvents.isProfileCall(entry) && Boolean(entry.callFrame.url); + return Trace.Types.Events.isProfileCall(entry) && Boolean(entry.callFrame.url); }); Bindings.IgnoreListManager.IgnoreListManager.instance().ignoreListURL(entryWithIgnoredUrl.callFrame.url); generateContextMenuForNode(entryWithIgnoredUrl); @@ -619,12 +619,12 @@ describeWithEnvironment('TimelineFlameChartView', function () { }); describe('Link between entries annotation in progress', function () { let flameChartView; - let traceData; + let parsedTrace; this.beforeEach(async () => { - ({ traceData } = await TraceLoader.traceEngine(this, 'recursive-blocking-js.json.gz')); + ({ parsedTrace } = await TraceLoader.traceEngine(this, 'recursive-blocking-js.json.gz')); const mockViewDelegate = new MockViewDelegate(); flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate); - flameChartView.setModel(traceData); + flameChartView.setModel(parsedTrace); Timeline.ModificationsManager.ModificationsManager.activeManager(); }); it('Creates a `link between entries Annotation in progress` tracking object', async function () { diff --git a/public/panels/timeline/TimelineFlameChartView.test.js.map b/public/panels/timeline/TimelineFlameChartView.test.js.map index 269c16116..d75273c3f 100644 --- a/public/panels/timeline/TimelineFlameChartView.test.js.map +++ b/public/panels/timeline/TimelineFlameChartView.test.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineFlameChartView.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineFlameChartView.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Common from '../../core/common/common.js';\nimport type * as Platform from '../../core/platform/platform.js';\nimport * as Bindings from '../../models/bindings/bindings.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {setupIgnoreListManagerEnvironment} from '../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport * as Timeline from './timeline.js';\n\nclass MockViewDelegate implements Timeline.TimelinePanel.TimelineModeViewDelegate {\n selection: Timeline.TimelineSelection.TimelineSelection|null = null;\n select(selection: Timeline.TimelineSelection.TimelineSelection|null): void {\n this.selection = selection;\n }\n selectEntryAtTime(_events: TraceEngine.Types.TraceEvents.TraceEventData[]|null, _time: number): void {\n }\n highlightEvent(_event: TraceEngine.Types.TraceEvents.TraceEventData|null): void {\n }\n element = document.createElement('div');\n}\n\ndescribeWithEnvironment('TimelineFlameChartView', function() {\n beforeEach(() => {\n setupIgnoreListManagerEnvironment();\n });\n\n describe('groupForLevel', () => {\n const {groupForLevel} = Timeline.TimelineFlameChartView;\n\n it('finds the right group for the given level', async () => {\n const groups: PerfUI.FlameChart.Group[] = [\n {\n name: 'group-1' as Common.UIString.LocalizedString,\n startLevel: 0,\n style: {} as PerfUI.FlameChart.GroupStyle,\n },\n {\n name: 'group-2' as Common.UIString.LocalizedString,\n startLevel: 10,\n style: {} as PerfUI.FlameChart.GroupStyle,\n },\n {\n name: 'group-3' as Common.UIString.LocalizedString,\n startLevel: 12,\n style: {} as PerfUI.FlameChart.GroupStyle,\n },\n ];\n\n assert.strictEqual(groupForLevel(groups, 1), groups[0]);\n assert.strictEqual(groupForLevel(groups, 10), groups[1]);\n assert.strictEqual(groupForLevel(groups, 11), groups[1]);\n assert.strictEqual(groupForLevel(groups, 12), groups[2]);\n assert.strictEqual(groupForLevel(groups, 999), groups[2]);\n });\n });\n\n it('Can search for events by name in the timeline', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'lcp-images.json.gz');\n // The timeline flamechart view will invoke the `select` method\n // of this delegate every time an event has matched on a search.\n const mockViewDelegate = new MockViewDelegate();\n\n const flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate);\n const searchableView = new UI.SearchableView.SearchableView(flameChartView, null);\n flameChartView.setSearchableView(searchableView);\n flameChartView.setModel(traceData);\n\n const searchQuery = 'Paint';\n const searchConfig =\n new UI.SearchableView.SearchConfig(/* query */ searchQuery, /* caseSensitive */ false, /* isRegex */ false);\n flameChartView.performSearch(searchConfig, true);\n\n assert.strictEqual(flameChartView.getSearchResults()?.length, 17);\n assertSelectionName('PrePaint');\n\n flameChartView.jumpToNextSearchResult();\n assertSelectionName('Paint');\n\n flameChartView.jumpToNextSearchResult();\n assertSelectionName('Paint');\n\n flameChartView.jumpToPreviousSearchResult();\n assertSelectionName('Paint');\n flameChartView.jumpToPreviousSearchResult();\n assertSelectionName('PrePaint');\n\n function assertSelectionName(name: string) {\n const selection = mockViewDelegate.selection;\n if (!selection || !Timeline.TimelineSelection.TimelineSelection.isTraceEventSelection(selection.object)) {\n throw new Error('Selection is not present or not a Trace Event');\n }\n const object = selection.object;\n assert.strictEqual(object.name, name);\n }\n });\n\n it('can search across both flame charts for events', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n // The timeline flamechart view will invoke the `select` method\n // of this delegate every time an event has matched on a search.\n const mockViewDelegate = new MockViewDelegate();\n\n const flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate);\n const searchableView = new UI.SearchableView.SearchableView(flameChartView, null);\n flameChartView.setSearchableView(searchableView);\n flameChartView.setModel(traceData);\n\n const searchQuery = 'app.js';\n const searchConfig =\n new UI.SearchableView.SearchConfig(/* query */ searchQuery, /* caseSensitive */ false, /* isRegex */ false);\n flameChartView.performSearch(searchConfig, true);\n\n const results = flameChartView.getSearchResults();\n assert.isOk(results);\n assert.lengthOf(results, 6);\n // We should have 5 results from the main provider, and 1 from the network\n assert.lengthOf(results.filter(r => r.provider === 'main'), 5);\n assert.lengthOf(results.filter(r => r.provider === 'network'), 1);\n });\n\n // This test is still failing after bumping up the timeout to 20 seconds. So\n // skip it while we work on a fix for the trace load speed.\n it.skip('[crbug.com/1492405] Shows the network track correctly', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'load-simple.json.gz');\n // The timeline flamechart view will invoke the `select` method\n // of this delegate every time an event has matched on a search.\n const mockViewDelegate = new MockViewDelegate();\n\n const flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate);\n flameChartView.setModel(traceData);\n\n assert.isTrue(flameChartView.isNetworkTrackShownForTests());\n });\n\n it('Does not show the network track when there is no network request', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'basic.json.gz');\n // The timeline flamechart view will invoke the `select` method\n // of this delegate every time an event has matched on a search.\n const mockViewDelegate = new MockViewDelegate();\n\n const flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate);\n flameChartView.setModel(traceData);\n\n assert.isFalse(flameChartView.isNetworkTrackShownForTests());\n });\n\n it('Adds Hidden Descendants Arrow as a decoration when a Context Menu action is applied on a node', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'load-simple.json.gz');\n const mockViewDelegate = new MockViewDelegate();\n\n const flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate);\n flameChartView.setModel(traceData);\n\n // Find the main track to later collapse entries of\n const mainTrack = flameChartView.getMainFlameChart().timelineData()?.groups.find(group => {\n return group.name === 'Main — http://localhost:8080/';\n });\n if (!mainTrack) {\n throw new Error('Could not find main track');\n }\n\n // Find the first node that has children to collapse and is visible in the timeline\n const nodeOfGroup = flameChartView.getMainDataProvider().groupTreeEvents(mainTrack);\n const firstNodeWithChildren = nodeOfGroup?.find(node => {\n const childrenAmount =\n traceData.Renderer.entryToNode.get(node as TraceEngine.Types.TraceEvents.TraceEventData)?.children.length;\n if (!childrenAmount) {\n return false;\n }\n return childrenAmount > 0 && node.cat === 'devtools.timeline';\n });\n const node =\n traceData.Renderer.entryToNode.get(firstNodeWithChildren as TraceEngine.Types.TraceEvents.TraceEventData);\n if (!node) {\n throw new Error('Could not find a visible node with children');\n }\n\n // Apply COLLAPSE_FUNCTION action to the node. This action will hide all the children of the passed node and add HIDDEN_DESCENDANTS_ARROW decoration to it.\n flameChartView.getMainFlameChart().modifyTree(PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION, node?.id);\n\n const decorationsForEntry = flameChartView.getMainFlameChart().timelineData()?.entryDecorations[node?.id];\n assert.deepEqual(decorationsForEntry, [\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW,\n },\n ]);\n });\n\n it('Adds Hidden Descendants Arrow as a decoration when a Context Menu action is applied on a selected node with a key shortcut event',\n async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'load-simple.json.gz');\n const mockViewDelegate = new MockViewDelegate();\n\n const flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate);\n flameChartView.setModel(traceData);\n\n // Find the main track to later collapse entries of\n const mainTrack = flameChartView.getMainFlameChart().timelineData()?.groups.find(group => {\n return group.name === 'Main — http://localhost:8080/';\n });\n if (!mainTrack) {\n throw new Error('Could not find main track');\n }\n\n // Find the first node that has children to collapse and is visible in the timeline\n const nodeOfGroup = flameChartView.getMainDataProvider().groupTreeEvents(mainTrack);\n const firstNodeWithChildren = nodeOfGroup?.find(node => {\n const childrenAmount =\n traceData.Renderer.entryToNode.get(node as TraceEngine.Types.TraceEvents.TraceEventData)?.children.length;\n if (!childrenAmount) {\n return false;\n }\n return childrenAmount > 0 && node.cat === 'devtools.timeline';\n });\n const node =\n traceData.Renderer.entryToNode.get(firstNodeWithChildren as TraceEngine.Types.TraceEvents.TraceEventData);\n if (!node) {\n throw new Error('Could not find a visible node with children');\n }\n\n flameChartView.getMainFlameChart().setSelectedEntry(node?.id);\n\n // Dispatch a shortcut keydown event that applies 'Hide Children' Context menu action\n const event = new KeyboardEvent('keydown', {code: 'KeyC'});\n flameChartView.getMainFlameChart().getCanvas().dispatchEvent(event);\n\n const decorationsForEntry = flameChartView.getMainFlameChart().timelineData()?.entryDecorations[node?.id];\n assert.deepEqual(decorationsForEntry, [\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW,\n },\n ]);\n });\n\n it('Removes Hidden Descendants Arrow as a decoration when Reset Children action is applied on a node',\n async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'load-simple.json.gz');\n const mockViewDelegate = new MockViewDelegate();\n\n const flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate);\n flameChartView.setModel(traceData);\n Timeline.ModificationsManager.ModificationsManager.activeManager();\n\n // Find the main track to later collapse entries of\n let mainTrack = flameChartView.getMainFlameChart().timelineData()?.groups.find(group => {\n return group.name === 'Main — http://localhost:8080/';\n });\n if (!mainTrack) {\n throw new Error('Could not find main track');\n }\n\n // Find the first node that has children to collapse and is visible in the timeline\n const nodeOfGroup = flameChartView.getMainDataProvider().groupTreeEvents(mainTrack);\n const firstNodeWithChildren = nodeOfGroup?.find(node => {\n const childrenAmount =\n traceData.Renderer.entryToNode.get(node as TraceEngine.Types.TraceEvents.TraceEventData)?.children.length;\n if (!childrenAmount) {\n return false;\n }\n return childrenAmount > 0 && node.cat === 'devtools.timeline';\n });\n const node =\n traceData.Renderer.entryToNode.get(firstNodeWithChildren as TraceEngine.Types.TraceEvents.TraceEventData);\n if (!node) {\n throw new Error('Could not find a visible node with children');\n }\n\n // Apply COLLAPSE_FUNCTION Context Menu action to the node.\n // This action will hide all the children of the passed node and add HIDDEN_DESCENDANTS_ARROW decoration to it.\n flameChartView.getMainFlameChart().modifyTree(PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION, node?.id);\n\n let decorationsForEntry = flameChartView.getMainFlameChart().timelineData()?.entryDecorations[node?.id];\n assert.deepEqual(decorationsForEntry, [\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW,\n },\n ]);\n\n mainTrack = flameChartView.getMainFlameChart().timelineData()?.groups.find(group => {\n return group.name === 'Main — http://localhost:8080/';\n });\n if (!mainTrack) {\n throw new Error('Could not find main track');\n }\n // Apply a RESET_CHILDREN action that will reveal all of the hidden children of the passed node and remove HIDDEN_DESCENDANTS_ARROW decoration from it.\n flameChartView.getMainFlameChart().modifyTree(PerfUI.FlameChart.FilterAction.RESET_CHILDREN, node?.id);\n\n // No decorations should exist on the node\n decorationsForEntry = flameChartView.getMainFlameChart().timelineData()?.entryDecorations[node?.id];\n assert.isUndefined(decorationsForEntry);\n });\n\n describe('Context Menu', function() {\n let flameChartView: Timeline.TimelineFlameChartView.TimelineFlameChartView;\n let traceData: TraceEngine.Handlers.Types.TraceParseData;\n\n this.beforeEach(async () => {\n ({traceData} = await TraceLoader.traceEngine(this, 'recursive-blocking-js.json.gz'));\n const mockViewDelegate = new MockViewDelegate();\n\n flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate);\n flameChartView.setModel(traceData);\n Timeline.ModificationsManager.ModificationsManager.activeManager();\n });\n\n it('Does not create customized Context Menu for network track', async function() {\n // The mouse event passed to the Context Menu is used to indicate where the menu should appear. Since we don't\n // need it to actually appear for this test, pass an event with coordinates that is not in the track header.\n flameChartView.getNetworkFlameChart().onContextMenu(new MouseEvent('contextmenu', {clientX: 100, clientY: 100}));\n assert.isUndefined(flameChartView.getNetworkFlameChart().getContextMenu());\n });\n\n it('Does not create Context Menu for Network track header', async function() {\n // So for the first track header, its x will start from beginning.\n // And its y will start after the ruler (ruler's height is 17).\n flameChartView.getNetworkFlameChart().onContextMenu(new MouseEvent('contextmenu', {clientX: 0, clientY: 17}));\n assert.isUndefined(flameChartView.getNetworkFlameChart().getContextMenu());\n });\n\n it('Create correct Context Menu for track headers in main flame chart', async function() {\n // So for the first track header, its x will start from beginning.\n // And its y will start after the ruler (ruler's height is 17).\n flameChartView.getMainFlameChart().onContextMenu(new MouseEvent('contextmenu', {clientX: 0, clientY: 17}));\n\n assert.strictEqual(flameChartView.getMainFlameChart().getContextMenu()?.defaultSection().items.length, 1);\n assert.strictEqual(\n flameChartView.getMainFlameChart().getContextMenu()?.defaultSection().items.at(0)?.buildDescriptor().label,\n 'Configure tracks…');\n });\n\n describe('Context Menu Actions For Thread tracks', function() {\n this.beforeEach(async () => {\n // Find the Main track to later collapse entries of\n const mainTrack = flameChartView.getMainFlameChart().timelineData()?.groups.find(group => {\n return group.name === 'Main — http://127.0.0.1:8080/';\n });\n if (!mainTrack) {\n throw new Error('Could not find main track');\n }\n });\n\n function getMainThread(data: TraceEngine.Handlers.ModelHandlers.Renderer.RendererHandlerData):\n TraceEngine.Handlers.ModelHandlers.Renderer.RendererThread {\n let mainThread: TraceEngine.Handlers.ModelHandlers.Renderer.RendererThread|null = null;\n for (const [, process] of data.processes) {\n for (const [, thread] of process.threads) {\n if (thread.name === 'CrRendererMain') {\n mainThread = thread;\n break;\n }\n }\n }\n if (!mainThread) {\n throw new Error('Could not find main thread.');\n }\n return mainThread;\n }\n\n function findFirstEntry(\n allEntries: readonly TraceEngine.Types.TraceEvents.TraceEventData[],\n predicate: (entry: TraceEngine.Types.TraceEvents.TraceEventData) =>\n boolean): TraceEngine.Types.TraceEvents.TraceEventData {\n const entry = allEntries.find(entry => predicate(entry));\n if (!entry) {\n throw new Error('Could not find expected entry.');\n }\n return entry;\n }\n\n function generateContextMenuForNodeId(nodeId: number): void {\n // Highlight the node to make the Context Menu dispatch on this node\n flameChartView.getMainFlameChart().highlightEntry(nodeId);\n\n const eventCoordinates = flameChartView.getMainFlameChart().entryIndexToCoordinates(nodeId);\n if (!eventCoordinates) {\n throw new Error('Coordinates were not found');\n }\n\n // The mouse event passed to the Context Menu is used to indicate where the menu should appear. So just simply\n // use the pixels of top left corner of the event.\n flameChartView.getMainFlameChart().onContextMenu(\n new MouseEvent('contextmenu', {clientX: eventCoordinates.x, clientY: eventCoordinates.y}));\n }\n\n function generateContextMenuForNode(node: TraceEngine.Types.TraceEvents.TraceEventData): void {\n const nodeId = flameChartView.getMainDataProvider().indexForEvent(node);\n assert.isNotNull(nodeId);\n generateContextMenuForNodeId(nodeId);\n }\n\n it('When an entry has no children, correctly make only Hide Entry enabled in the Context Menu action',\n async function() {\n /** Part of this stack looks roughly like so (with some events omitted):\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * == now == == updateCounters == <-- ID=245\n *\n * In this test we want to test that the Context Menu option available\n * for an entry with no children and a parent is to hide given entry only.\n * Since there are no children to hide, we don't want to show 'hide children' option.\n *\n * To achieve that, we will dispatch the context menu on the 'updateCounters' function that does not have\n * children.\n * The ID of 'updateCounters' is 245.\n **/\n\n const nodeIdWithNoChildren = 245;\n generateContextMenuForNodeId(nodeIdWithNoChildren);\n\n assert.strictEqual(flameChartView.getMainFlameChart().getContextMenu()?.defaultSection().items.length, 5);\n // Hide function enabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(0)\n ?.buildDescriptor()\n .enabled,\n true);\n // Rest of the actions disabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(1)\n ?.buildDescriptor()\n .enabled,\n false);\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(2)\n ?.buildDescriptor()\n .enabled,\n false);\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(3)\n ?.buildDescriptor()\n .enabled,\n false);\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(4)\n ?.buildDescriptor()\n .enabled,\n false);\n });\n\n it('When an entry has children, correctly make only Hide Entry and Hide Children enabled in the Context Menu action',\n async function() {\n /** Part of this stack looks roughly like so (with some events omitted):\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * ===== wait ===== ===== wait ===== <-- ID=204\n * = now = = now = = now = = now =\n *\n * In this test we want to test that the Context Menu option available\n * for an entry with children and a parent is to hide given entry, and hide children only.\n * Since there are no repeating children to hide, we don't want to show 'hide repeating children' option.\n *\n * To achieve that, we will dispatch the context menu on the 'wait' function that has only non-repeating\n * children.\n * The ID of the first 'wait' is 204.\n **/\n\n const nodeIdWithNoChildren = 204;\n generateContextMenuForNodeId(nodeIdWithNoChildren);\n\n // This entry has URL, so there are 5 always-shown actions, and one to add script to ignore list.\n assert.strictEqual(flameChartView.getMainFlameChart().getContextMenu()?.defaultSection().items.length, 6);\n // Hide function enabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(0)\n ?.buildDescriptor()\n .enabled,\n true);\n // Hide children enabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(1)\n ?.buildDescriptor()\n .enabled,\n true);\n // Rest of the actions disabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(2)\n ?.buildDescriptor()\n .enabled,\n false);\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(3)\n ?.buildDescriptor()\n .enabled,\n false);\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(4)\n ?.buildDescriptor()\n .enabled,\n false);\n });\n\n it('When an entry has repeating children, correctly make only Hide Entry, Hide Children and Hide repeating children enabled in the Context Menu action',\n async function() {\n /** Part of this stack looks roughly like so (with some events omitted):\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo =============== <-- ID=200\n * =============== foo ===============\n * =============== foo ===============\n * ===== wait ===== ===== wait =====\n * = now = = now = = now = = now =\n *\n * In this test we want to test that the Context Menu option available\n * for an entry with children repeating children and a parent is to hide given entry, hide children and hide\n * repeating children.\n *\n * To achieve that, we will dispatch the context menu on the 'foo' function that has child 'foo' calls.\n * The ID of the a matching 'foo' is 200.\n **/\n\n const nodeIdWithNoChildren = 200;\n generateContextMenuForNodeId(nodeIdWithNoChildren);\n\n // This entry has URL, so there are 5 always-shown actions, and one to add script to ignore list.\n assert.strictEqual(flameChartView.getMainFlameChart().getContextMenu()?.defaultSection().items.length, 6);\n // Hide function enabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(0)\n ?.buildDescriptor()\n .enabled,\n true);\n // Hide children enabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(1)\n ?.buildDescriptor()\n .enabled,\n true);\n // Hide repeating children enabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(2)\n ?.buildDescriptor()\n .enabled,\n true);\n // Rest of the actions disabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(3)\n ?.buildDescriptor()\n .enabled,\n false);\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(4)\n ?.buildDescriptor()\n .enabled,\n false);\n });\n\n it('When an entry has no parent and has children, correctly make only Hide Children enabled in the Context Menu action',\n async function() {\n /** Part of this stack looks roughly like so (with some events omitted):\n * =============== Task ============== <-- ID=62\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * ===== wait ===== ===== wait =====\n * = now = = now = = now = = now =\n *\n * In this test we want to test that the Context Menu option available for an entry with no parent is only to\n * hide children.\n * If an entry has no parent, we don't want to show an option to hide the entry since when an entry is hidden,\n * it is indicated by adding a decoration to the parent and if there is no parent, there is no way to show it\n * is hidden.\n *\n * To achieve that, we will dispatch the context menu on the 'Task' function that is on the top of the stack\n * and has no parent.\n * The ID of the a matching 'Task' is 62.\n **/\n\n const nodeIdWithNoChildren = 62;\n generateContextMenuForNodeId(nodeIdWithNoChildren);\n\n // Hide function disabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(0)\n ?.buildDescriptor()\n .enabled,\n false);\n // Hide children enabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(1)\n ?.buildDescriptor()\n .enabled,\n true);\n // Rest of the actions disabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(2)\n ?.buildDescriptor()\n .enabled,\n false);\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(3)\n ?.buildDescriptor()\n .enabled,\n false);\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(4)\n ?.buildDescriptor()\n .enabled,\n false);\n });\n\n it('Reset Trace Context Menu action is disabled before some action has been applied', async function() {\n /** Part of this stack looks roughly like so (with some events omitted):\n * =============== Task ============== <-- ID=62\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * ===== wait ===== ===== wait =====\n * = now = = now = = now = = now =\n *\n * In this test we want to test that the Reset Trace Context Menu option is disabled by default and enabled after\n * some action has been applied.\n *\n * To achieve that, we will first check if Reset Trace is disabled and then dispatch a Context Menu action on\n * \"Task\" entry and then check if Reset Trace is enabled.\n * The ID of the a matching 'Task' is 62.\n **/\n\n const nodeId = 62;\n generateContextMenuForNodeId(nodeId);\n assert.strictEqual(flameChartView.getMainFlameChart().getContextMenu()?.defaultSection().items.length, 5);\n assert.strictEqual(\n flameChartView.getMainFlameChart().getContextMenu()?.defaultSection().items.at(4)?.buildDescriptor().label,\n 'Reset trace');\n // Check that Reset Trace is disabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(4)\n ?.buildDescriptor()\n .enabled,\n false);\n\n flameChartView.getMainFlameChart().modifyTree(PerfUI.FlameChart.FilterAction.MERGE_FUNCTION, nodeId);\n generateContextMenuForNodeId(nodeId);\n\n // Check that Reset Trace is enabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(4)\n ?.buildDescriptor()\n .enabled,\n true);\n });\n\n it('When an entry has URL and is not ignored, correctly show the Add script to ignore list in the Context Menu action',\n async function() {\n const mainThread = getMainThread(traceData.Renderer);\n const entryWithUrl = findFirstEntry(mainThread.entries, entry => {\n // Let's find the first entry with URL.\n return TraceEngine.Types.TraceEvents.isProfileCall(entry) && Boolean(entry.callFrame.url);\n });\n generateContextMenuForNode(entryWithUrl);\n\n assert.strictEqual(flameChartView.getMainFlameChart().getContextMenu()?.defaultSection().items.length, 6);\n\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(5)\n ?.buildDescriptor()\n .label,\n 'Add script to ignore list');\n });\n\n it('When an entry has URL and is ignored, correctly show the Remove script from ignore list in the Context Menu action',\n async function() {\n const mainThread = getMainThread(traceData.Renderer);\n const entryWithIgnoredUrl = findFirstEntry(mainThread.entries, entry => {\n // Let's find the first entry with URL.\n return TraceEngine.Types.TraceEvents.isProfileCall(entry) && Boolean(entry.callFrame.url);\n });\n Bindings.IgnoreListManager.IgnoreListManager.instance().ignoreListURL(\n (entryWithIgnoredUrl as TraceEngine.Types.TraceEvents.SyntheticProfileCall).callFrame.url as\n Platform.DevToolsPath.UrlString);\n\n generateContextMenuForNode(entryWithIgnoredUrl);\n\n assert.strictEqual(flameChartView.getMainFlameChart().getContextMenu()?.defaultSection().items.length, 6);\n\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(5)\n ?.buildDescriptor()\n .label,\n 'Remove script from ignore list');\n });\n });\n });\n\n describe('Link between entries annotation in progress', function() {\n let flameChartView: Timeline.TimelineFlameChartView.TimelineFlameChartView;\n let traceData: TraceEngine.Handlers.Types.TraceParseData;\n\n this.beforeEach(async () => {\n ({traceData} = await TraceLoader.traceEngine(this, 'recursive-blocking-js.json.gz'));\n const mockViewDelegate = new MockViewDelegate();\n\n flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate);\n flameChartView.setModel(traceData);\n Timeline.ModificationsManager.ModificationsManager.activeManager();\n });\n\n it('Creates a `link between entries Annotation in progress` tracking object', async function() {\n // Make sure the link annotation in the progress of creation does not exist\n assert.isNull(flameChartView.getLinkSelectionAnnotation());\n\n // Start creating a link between entries from an entry with ID 204\n flameChartView.onEntriesLinkAnnotationCreate(flameChartView.getMainDataProvider(), 204);\n\n // Make sure the link is started and only has 'from' entry set\n assert.isNotNull(flameChartView.getLinkSelectionAnnotation());\n assert.isNotNull(flameChartView.getLinkSelectionAnnotation()?.entryFrom);\n assert.isUndefined(flameChartView.getLinkSelectionAnnotation()?.entryTo);\n\n // Make sure the annotation exists in the ModificationsManager\n const annotations = Timeline.ModificationsManager.ModificationsManager.activeManager()?.getAnnotations();\n assert.exists(annotations);\n assert.strictEqual(annotations?.length, 1);\n assert.strictEqual(annotations[0].type, 'ENTRIES_LINK');\n });\n\n it('Sets the link between entries annotation in progress to null when the second entry is selected',\n async function() {\n // Make sure the link annotation in the progress of creation does not exist\n assert.isNull(flameChartView.getLinkSelectionAnnotation());\n\n // Start creating a link between entries from an entry with ID 204\n flameChartView.onEntriesLinkAnnotationCreate(flameChartView.getMainDataProvider(), 204);\n const entryFrom = flameChartView.getMainDataProvider().eventByIndex(204);\n\n // Hover on another entry to complete the link\n flameChartView.updateLinkSelectionAnnotation(flameChartView.getMainDataProvider(), 245);\n const entryTo = flameChartView.getMainDataProvider().eventByIndex(245);\n // Make sure the entry 'to' is set\n assert.exists(flameChartView.getLinkSelectionAnnotation()?.entryTo);\n\n // Select the other entry to complete the link and set the one in progress to null\n flameChartView.handleToEntryOfLinkBetweenEntriesSelection(245);\n // Make sure the link annotation in progress is set to null\n assert.isNull(flameChartView.getLinkSelectionAnnotation());\n\n // Make sure the annotation exists in the ModificationsManager\n const annotations = Timeline.ModificationsManager.ModificationsManager.activeManager()?.getAnnotations();\n assert.exists(annotations);\n assert.strictEqual(annotations?.length, 1);\n assert.strictEqual(annotations[0].type, 'ENTRIES_LINK');\n const entriesLink = annotations[0] as TraceEngine.Types.File.EntriesLinkAnnotation;\n\n assert.strictEqual(entriesLink.entryFrom, entryFrom);\n assert.strictEqual(entriesLink.entryTo, entryTo);\n });\n\n it('Reverses entries in the link if `to` entry timestamp is earlier than `from` entry timestamo', async function() {\n // Make sure the link annotation in the progress of creation does not exist\n assert.isNull(flameChartView.getLinkSelectionAnnotation());\n\n // Start creating a link between entries from an entry with ID 245\n flameChartView.onEntriesLinkAnnotationCreate(flameChartView.getMainDataProvider(), 245);\n const entryFrom = flameChartView.getMainDataProvider().eventByIndex(245);\n\n // Hover on another entry that starts before the entry that the link is being created from\n flameChartView.updateLinkSelectionAnnotation(flameChartView.getMainDataProvider(), 204);\n const entryTo = flameChartView.getMainDataProvider().eventByIndex(204);\n\n // Select the other entry to complete the link and set the one in progress to null\n flameChartView.handleToEntryOfLinkBetweenEntriesSelection(204);\n\n // Make sure the annotation exists in the ModificationsManager\n const annotations = Timeline.ModificationsManager.ModificationsManager.activeManager()?.getAnnotations();\n assert.exists(annotations);\n assert.strictEqual(annotations?.length, 1);\n assert.strictEqual(annotations[0].type, 'ENTRIES_LINK');\n const entriesLink = annotations[0] as TraceEngine.Types.File.EntriesLinkAnnotation;\n\n // Make 'entryFrom' has an earlier timestamp and the entries `to` and `from` got switched up\n assert.strictEqual(entriesLink.entryFrom, entryTo);\n assert.strictEqual(entriesLink.entryTo, entryFrom);\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"TimelineFlameChartView.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineFlameChartView.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Common from '../../core/common/common.js';\nimport type * as Platform from '../../core/platform/platform.js';\nimport * as Bindings from '../../models/bindings/bindings.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {setupIgnoreListManagerEnvironment} from '../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport * as Timeline from './timeline.js';\n\nclass MockViewDelegate implements Timeline.TimelinePanel.TimelineModeViewDelegate {\n selection: Timeline.TimelineSelection.TimelineSelection|null = null;\n select(selection: Timeline.TimelineSelection.TimelineSelection|null): void {\n this.selection = selection;\n }\n selectEntryAtTime(_events: Trace.Types.Events.Event[]|null, _time: number): void {\n }\n highlightEvent(_event: Trace.Types.Events.Event|null): void {\n }\n element = document.createElement('div');\n}\n\ndescribeWithEnvironment('TimelineFlameChartView', function() {\n beforeEach(() => {\n setupIgnoreListManagerEnvironment();\n });\n\n describe('groupForLevel', () => {\n const {groupForLevel} = Timeline.TimelineFlameChartView;\n\n it('finds the right group for the given level', async () => {\n const groups: PerfUI.FlameChart.Group[] = [\n {\n name: 'group-1' as Common.UIString.LocalizedString,\n startLevel: 0,\n style: {} as PerfUI.FlameChart.GroupStyle,\n },\n {\n name: 'group-2' as Common.UIString.LocalizedString,\n startLevel: 10,\n style: {} as PerfUI.FlameChart.GroupStyle,\n },\n {\n name: 'group-3' as Common.UIString.LocalizedString,\n startLevel: 12,\n style: {} as PerfUI.FlameChart.GroupStyle,\n },\n ];\n\n assert.strictEqual(groupForLevel(groups, 1), groups[0]);\n assert.strictEqual(groupForLevel(groups, 10), groups[1]);\n assert.strictEqual(groupForLevel(groups, 11), groups[1]);\n assert.strictEqual(groupForLevel(groups, 12), groups[2]);\n assert.strictEqual(groupForLevel(groups, 999), groups[2]);\n });\n });\n\n it('Can search for events by name in the timeline', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'lcp-images.json.gz');\n // The timeline flamechart view will invoke the `select` method\n // of this delegate every time an event has matched on a search.\n const mockViewDelegate = new MockViewDelegate();\n\n const flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate);\n const searchableView = new UI.SearchableView.SearchableView(flameChartView, null);\n flameChartView.setSearchableView(searchableView);\n flameChartView.setModel(parsedTrace);\n\n const searchQuery = 'Paint';\n const searchConfig =\n new UI.SearchableView.SearchConfig(/* query */ searchQuery, /* caseSensitive */ false, /* isRegex */ false);\n flameChartView.performSearch(searchConfig, true);\n\n assert.strictEqual(flameChartView.getSearchResults()?.length, 17);\n assertSelectionName('PrePaint');\n\n flameChartView.jumpToNextSearchResult();\n assertSelectionName('Paint');\n\n flameChartView.jumpToNextSearchResult();\n assertSelectionName('Paint');\n\n flameChartView.jumpToPreviousSearchResult();\n assertSelectionName('Paint');\n flameChartView.jumpToPreviousSearchResult();\n assertSelectionName('PrePaint');\n\n function assertSelectionName(name: string) {\n const selection = mockViewDelegate.selection;\n if (!selection || !Timeline.TimelineSelection.TimelineSelection.isSelection(selection.object)) {\n throw new Error('Selection is not present or not a Trace Event');\n }\n const object = selection.object;\n assert.strictEqual(object.name, name);\n }\n });\n\n it('can search across both flame charts for events', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n // The timeline flamechart view will invoke the `select` method\n // of this delegate every time an event has matched on a search.\n const mockViewDelegate = new MockViewDelegate();\n\n const flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate);\n const searchableView = new UI.SearchableView.SearchableView(flameChartView, null);\n flameChartView.setSearchableView(searchableView);\n flameChartView.setModel(parsedTrace);\n\n const searchQuery = 'app.js';\n const searchConfig =\n new UI.SearchableView.SearchConfig(/* query */ searchQuery, /* caseSensitive */ false, /* isRegex */ false);\n flameChartView.performSearch(searchConfig, true);\n\n const results = flameChartView.getSearchResults();\n assert.isOk(results);\n assert.lengthOf(results, 6);\n // We should have 5 results from the main provider, and 1 from the network\n assert.lengthOf(results.filter(r => r.provider === 'main'), 5);\n assert.lengthOf(results.filter(r => r.provider === 'network'), 1);\n });\n\n // This test is still failing after bumping up the timeout to 20 seconds. So\n // skip it while we work on a fix for the trace load speed.\n it.skip('[crbug.com/1492405] Shows the network track correctly', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'load-simple.json.gz');\n // The timeline flamechart view will invoke the `select` method\n // of this delegate every time an event has matched on a search.\n const mockViewDelegate = new MockViewDelegate();\n\n const flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate);\n flameChartView.setModel(parsedTrace);\n\n assert.isTrue(flameChartView.isNetworkTrackShownForTests());\n });\n\n it('Does not show the network track when there is no network request', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'basic.json.gz');\n // The timeline flamechart view will invoke the `select` method\n // of this delegate every time an event has matched on a search.\n const mockViewDelegate = new MockViewDelegate();\n\n const flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate);\n flameChartView.setModel(parsedTrace);\n\n assert.isFalse(flameChartView.isNetworkTrackShownForTests());\n });\n\n it('Adds Hidden Descendants Arrow as a decoration when a Context Menu action is applied on a node', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'load-simple.json.gz');\n const mockViewDelegate = new MockViewDelegate();\n\n const flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate);\n flameChartView.setModel(parsedTrace);\n\n // Find the main track to later collapse entries of\n const mainTrack = flameChartView.getMainFlameChart().timelineData()?.groups.find(group => {\n return group.name === 'Main — http://localhost:8080/';\n });\n if (!mainTrack) {\n throw new Error('Could not find main track');\n }\n\n // Find the first node that has children to collapse and is visible in the timeline\n const nodeOfGroup = flameChartView.getMainDataProvider().groupTreeEvents(mainTrack);\n const firstNodeWithChildren = nodeOfGroup?.find(node => {\n const childrenAmount = parsedTrace.Renderer.entryToNode.get(node as Trace.Types.Events.Event)?.children.length;\n if (!childrenAmount) {\n return false;\n }\n return childrenAmount > 0 && node.cat === 'devtools.timeline';\n });\n const node = parsedTrace.Renderer.entryToNode.get(firstNodeWithChildren as Trace.Types.Events.Event);\n if (!node) {\n throw new Error('Could not find a visible node with children');\n }\n\n // Apply COLLAPSE_FUNCTION action to the node. This action will hide all the children of the passed node and add HIDDEN_DESCENDANTS_ARROW decoration to it.\n flameChartView.getMainFlameChart().modifyTree(PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION, node?.id);\n\n const decorationsForEntry = flameChartView.getMainFlameChart().timelineData()?.entryDecorations[node?.id];\n assert.deepEqual(decorationsForEntry, [\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW,\n },\n ]);\n });\n\n it('Adds Hidden Descendants Arrow as a decoration when a Context Menu action is applied on a selected node with a key shortcut event',\n async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'load-simple.json.gz');\n const mockViewDelegate = new MockViewDelegate();\n\n const flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate);\n flameChartView.setModel(parsedTrace);\n\n // Find the main track to later collapse entries of\n const mainTrack = flameChartView.getMainFlameChart().timelineData()?.groups.find(group => {\n return group.name === 'Main — http://localhost:8080/';\n });\n if (!mainTrack) {\n throw new Error('Could not find main track');\n }\n\n // Find the first node that has children to collapse and is visible in the timeline\n const nodeOfGroup = flameChartView.getMainDataProvider().groupTreeEvents(mainTrack);\n const firstNodeWithChildren = nodeOfGroup?.find(node => {\n const childrenAmount = parsedTrace.Renderer.entryToNode.get(node as Trace.Types.Events.Event)?.children.length;\n if (!childrenAmount) {\n return false;\n }\n return childrenAmount > 0 && node.cat === 'devtools.timeline';\n });\n const node = parsedTrace.Renderer.entryToNode.get(firstNodeWithChildren as Trace.Types.Events.Event);\n if (!node) {\n throw new Error('Could not find a visible node with children');\n }\n\n flameChartView.getMainFlameChart().setSelectedEntry(node?.id);\n\n // Dispatch a shortcut keydown event that applies 'Hide Children' Context menu action\n const event = new KeyboardEvent('keydown', {code: 'KeyC'});\n flameChartView.getMainFlameChart().getCanvas().dispatchEvent(event);\n\n const decorationsForEntry = flameChartView.getMainFlameChart().timelineData()?.entryDecorations[node?.id];\n assert.deepEqual(decorationsForEntry, [\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW,\n },\n ]);\n });\n\n it('Removes Hidden Descendants Arrow as a decoration when Reset Children action is applied on a node',\n async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'load-simple.json.gz');\n const mockViewDelegate = new MockViewDelegate();\n\n const flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate);\n flameChartView.setModel(parsedTrace);\n Timeline.ModificationsManager.ModificationsManager.activeManager();\n\n // Find the main track to later collapse entries of\n let mainTrack = flameChartView.getMainFlameChart().timelineData()?.groups.find(group => {\n return group.name === 'Main — http://localhost:8080/';\n });\n if (!mainTrack) {\n throw new Error('Could not find main track');\n }\n\n // Find the first node that has children to collapse and is visible in the timeline\n const nodeOfGroup = flameChartView.getMainDataProvider().groupTreeEvents(mainTrack);\n const firstNodeWithChildren = nodeOfGroup?.find(node => {\n const childrenAmount = parsedTrace.Renderer.entryToNode.get(node as Trace.Types.Events.Event)?.children.length;\n if (!childrenAmount) {\n return false;\n }\n return childrenAmount > 0 && node.cat === 'devtools.timeline';\n });\n const node = parsedTrace.Renderer.entryToNode.get(firstNodeWithChildren as Trace.Types.Events.Event);\n if (!node) {\n throw new Error('Could not find a visible node with children');\n }\n\n // Apply COLLAPSE_FUNCTION Context Menu action to the node.\n // This action will hide all the children of the passed node and add HIDDEN_DESCENDANTS_ARROW decoration to it.\n flameChartView.getMainFlameChart().modifyTree(PerfUI.FlameChart.FilterAction.COLLAPSE_FUNCTION, node?.id);\n\n let decorationsForEntry = flameChartView.getMainFlameChart().timelineData()?.entryDecorations[node?.id];\n assert.deepEqual(decorationsForEntry, [\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW,\n },\n ]);\n\n mainTrack = flameChartView.getMainFlameChart().timelineData()?.groups.find(group => {\n return group.name === 'Main — http://localhost:8080/';\n });\n if (!mainTrack) {\n throw new Error('Could not find main track');\n }\n // Apply a RESET_CHILDREN action that will reveal all of the hidden children of the passed node and remove HIDDEN_DESCENDANTS_ARROW decoration from it.\n flameChartView.getMainFlameChart().modifyTree(PerfUI.FlameChart.FilterAction.RESET_CHILDREN, node?.id);\n\n // No decorations should exist on the node\n decorationsForEntry = flameChartView.getMainFlameChart().timelineData()?.entryDecorations[node?.id];\n assert.isUndefined(decorationsForEntry);\n });\n\n describe('Context Menu', function() {\n let flameChartView: Timeline.TimelineFlameChartView.TimelineFlameChartView;\n let parsedTrace: Trace.Handlers.Types.ParsedTrace;\n\n this.beforeEach(async () => {\n ({parsedTrace} = await TraceLoader.traceEngine(this, 'recursive-blocking-js.json.gz'));\n const mockViewDelegate = new MockViewDelegate();\n\n flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate);\n flameChartView.setModel(parsedTrace);\n Timeline.ModificationsManager.ModificationsManager.activeManager();\n });\n\n it('Does not create customized Context Menu for network track', async function() {\n // The mouse event passed to the Context Menu is used to indicate where the menu should appear. Since we don't\n // need it to actually appear for this test, pass an event with coordinates that is not in the track header.\n flameChartView.getNetworkFlameChart().onContextMenu(new MouseEvent('contextmenu', {clientX: 100, clientY: 100}));\n assert.isUndefined(flameChartView.getNetworkFlameChart().getContextMenu());\n });\n\n it('Does not create Context Menu for Network track header', async function() {\n // So for the first track header, its x will start from beginning.\n // And its y will start after the ruler (ruler's height is 17).\n flameChartView.getNetworkFlameChart().onContextMenu(new MouseEvent('contextmenu', {clientX: 0, clientY: 17}));\n assert.isUndefined(flameChartView.getNetworkFlameChart().getContextMenu());\n });\n\n it('Create correct Context Menu for track headers in main flame chart', async function() {\n // So for the first track header, its x will start from beginning.\n // And its y will start after the ruler (ruler's height is 17).\n flameChartView.getMainFlameChart().onContextMenu(new MouseEvent('contextmenu', {clientX: 0, clientY: 17}));\n\n assert.strictEqual(flameChartView.getMainFlameChart().getContextMenu()?.defaultSection().items.length, 1);\n assert.strictEqual(\n flameChartView.getMainFlameChart().getContextMenu()?.defaultSection().items.at(0)?.buildDescriptor().label,\n 'Configure tracks…');\n });\n\n describe('Context Menu Actions For Thread tracks', function() {\n this.beforeEach(async () => {\n // Find the Main track to later collapse entries of\n const mainTrack = flameChartView.getMainFlameChart().timelineData()?.groups.find(group => {\n return group.name === 'Main — http://127.0.0.1:8080/';\n });\n if (!mainTrack) {\n throw new Error('Could not find main track');\n }\n });\n\n function getMainThread(data: Trace.Handlers.ModelHandlers.Renderer.RendererHandlerData):\n Trace.Handlers.ModelHandlers.Renderer.RendererThread {\n let mainThread: Trace.Handlers.ModelHandlers.Renderer.RendererThread|null = null;\n for (const [, process] of data.processes) {\n for (const [, thread] of process.threads) {\n if (thread.name === 'CrRendererMain') {\n mainThread = thread;\n break;\n }\n }\n }\n if (!mainThread) {\n throw new Error('Could not find main thread.');\n }\n return mainThread;\n }\n\n function findFirstEntry(\n allEntries: readonly Trace.Types.Events.Event[],\n predicate: (entry: Trace.Types.Events.Event) => boolean): Trace.Types.Events.Event {\n const entry = allEntries.find(entry => predicate(entry));\n if (!entry) {\n throw new Error('Could not find expected entry.');\n }\n return entry;\n }\n\n function generateContextMenuForNodeId(nodeId: number): void {\n // Highlight the node to make the Context Menu dispatch on this node\n flameChartView.getMainFlameChart().highlightEntry(nodeId);\n\n const eventCoordinates = flameChartView.getMainFlameChart().entryIndexToCoordinates(nodeId);\n if (!eventCoordinates) {\n throw new Error('Coordinates were not found');\n }\n\n // The mouse event passed to the Context Menu is used to indicate where the menu should appear. So just simply\n // use the pixels of top left corner of the event.\n flameChartView.getMainFlameChart().onContextMenu(\n new MouseEvent('contextmenu', {clientX: eventCoordinates.x, clientY: eventCoordinates.y}));\n }\n\n function generateContextMenuForNode(node: Trace.Types.Events.Event): void {\n const nodeId = flameChartView.getMainDataProvider().indexForEvent(node);\n assert.isNotNull(nodeId);\n generateContextMenuForNodeId(nodeId);\n }\n\n it('When an entry has no children, correctly make only Hide Entry enabled in the Context Menu action',\n async function() {\n /** Part of this stack looks roughly like so (with some events omitted):\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * == now == == updateCounters == <-- ID=245\n *\n * In this test we want to test that the Context Menu option available\n * for an entry with no children and a parent is to hide given entry only.\n * Since there are no children to hide, we don't want to show 'hide children' option.\n *\n * To achieve that, we will dispatch the context menu on the 'updateCounters' function that does not have\n * children.\n * The ID of 'updateCounters' is 245.\n **/\n\n const nodeIdWithNoChildren = 245;\n generateContextMenuForNodeId(nodeIdWithNoChildren);\n\n assert.strictEqual(flameChartView.getMainFlameChart().getContextMenu()?.defaultSection().items.length, 5);\n // Hide function enabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(0)\n ?.buildDescriptor()\n .enabled,\n true);\n // Rest of the actions disabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(1)\n ?.buildDescriptor()\n .enabled,\n false);\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(2)\n ?.buildDescriptor()\n .enabled,\n false);\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(3)\n ?.buildDescriptor()\n .enabled,\n false);\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(4)\n ?.buildDescriptor()\n .enabled,\n false);\n });\n\n it('When an entry has children, correctly make only Hide Entry and Hide Children enabled in the Context Menu action',\n async function() {\n /** Part of this stack looks roughly like so (with some events omitted):\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * ===== wait ===== ===== wait ===== <-- ID=204\n * = now = = now = = now = = now =\n *\n * In this test we want to test that the Context Menu option available\n * for an entry with children and a parent is to hide given entry, and hide children only.\n * Since there are no repeating children to hide, we don't want to show 'hide repeating children' option.\n *\n * To achieve that, we will dispatch the context menu on the 'wait' function that has only non-repeating\n * children.\n * The ID of the first 'wait' is 204.\n **/\n\n const nodeIdWithNoChildren = 204;\n generateContextMenuForNodeId(nodeIdWithNoChildren);\n\n // This entry has URL, so there are 5 always-shown actions, and one to add script to ignore list.\n assert.strictEqual(flameChartView.getMainFlameChart().getContextMenu()?.defaultSection().items.length, 6);\n // Hide function enabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(0)\n ?.buildDescriptor()\n .enabled,\n true);\n // Hide children enabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(1)\n ?.buildDescriptor()\n .enabled,\n true);\n // Rest of the actions disabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(2)\n ?.buildDescriptor()\n .enabled,\n false);\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(3)\n ?.buildDescriptor()\n .enabled,\n false);\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(4)\n ?.buildDescriptor()\n .enabled,\n false);\n });\n\n it('When an entry has repeating children, correctly make only Hide Entry, Hide Children and Hide repeating children enabled in the Context Menu action',\n async function() {\n /** Part of this stack looks roughly like so (with some events omitted):\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo =============== <-- ID=200\n * =============== foo ===============\n * =============== foo ===============\n * ===== wait ===== ===== wait =====\n * = now = = now = = now = = now =\n *\n * In this test we want to test that the Context Menu option available\n * for an entry with children repeating children and a parent is to hide given entry, hide children and hide\n * repeating children.\n *\n * To achieve that, we will dispatch the context menu on the 'foo' function that has child 'foo' calls.\n * The ID of the a matching 'foo' is 200.\n **/\n\n const nodeIdWithNoChildren = 200;\n generateContextMenuForNodeId(nodeIdWithNoChildren);\n\n // This entry has URL, so there are 5 always-shown actions, and one to add script to ignore list.\n assert.strictEqual(flameChartView.getMainFlameChart().getContextMenu()?.defaultSection().items.length, 6);\n // Hide function enabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(0)\n ?.buildDescriptor()\n .enabled,\n true);\n // Hide children enabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(1)\n ?.buildDescriptor()\n .enabled,\n true);\n // Hide repeating children enabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(2)\n ?.buildDescriptor()\n .enabled,\n true);\n // Rest of the actions disabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(3)\n ?.buildDescriptor()\n .enabled,\n false);\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(4)\n ?.buildDescriptor()\n .enabled,\n false);\n });\n\n it('When an entry has no parent and has children, correctly make only Hide Children enabled in the Context Menu action',\n async function() {\n /** Part of this stack looks roughly like so (with some events omitted):\n * =============== Task ============== <-- ID=62\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * ===== wait ===== ===== wait =====\n * = now = = now = = now = = now =\n *\n * In this test we want to test that the Context Menu option available for an entry with no parent is only to\n * hide children.\n * If an entry has no parent, we don't want to show an option to hide the entry since when an entry is hidden,\n * it is indicated by adding a decoration to the parent and if there is no parent, there is no way to show it\n * is hidden.\n *\n * To achieve that, we will dispatch the context menu on the 'Task' function that is on the top of the stack\n * and has no parent.\n * The ID of the a matching 'Task' is 62.\n **/\n\n const nodeIdWithNoChildren = 62;\n generateContextMenuForNodeId(nodeIdWithNoChildren);\n\n // Hide function disabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(0)\n ?.buildDescriptor()\n .enabled,\n false);\n // Hide children enabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(1)\n ?.buildDescriptor()\n .enabled,\n true);\n // Rest of the actions disabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(2)\n ?.buildDescriptor()\n .enabled,\n false);\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(3)\n ?.buildDescriptor()\n .enabled,\n false);\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(4)\n ?.buildDescriptor()\n .enabled,\n false);\n });\n\n it('Reset Trace Context Menu action is disabled before some action has been applied', async function() {\n /** Part of this stack looks roughly like so (with some events omitted):\n * =============== Task ============== <-- ID=62\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * =============== foo ===============\n * ===== wait ===== ===== wait =====\n * = now = = now = = now = = now =\n *\n * In this test we want to test that the Reset Trace Context Menu option is disabled by default and enabled after\n * some action has been applied.\n *\n * To achieve that, we will first check if Reset Trace is disabled and then dispatch a Context Menu action on\n * \"Task\" entry and then check if Reset Trace is enabled.\n * The ID of the a matching 'Task' is 62.\n **/\n\n const nodeId = 62;\n generateContextMenuForNodeId(nodeId);\n assert.strictEqual(flameChartView.getMainFlameChart().getContextMenu()?.defaultSection().items.length, 5);\n assert.strictEqual(\n flameChartView.getMainFlameChart().getContextMenu()?.defaultSection().items.at(4)?.buildDescriptor().label,\n 'Reset trace');\n // Check that Reset Trace is disabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(4)\n ?.buildDescriptor()\n .enabled,\n false);\n\n flameChartView.getMainFlameChart().modifyTree(PerfUI.FlameChart.FilterAction.MERGE_FUNCTION, nodeId);\n generateContextMenuForNodeId(nodeId);\n\n // Check that Reset Trace is enabled\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(4)\n ?.buildDescriptor()\n .enabled,\n true);\n });\n\n it('When an entry has URL and is not ignored, correctly show the Add script to ignore list in the Context Menu action',\n async function() {\n const mainThread = getMainThread(parsedTrace.Renderer);\n const entryWithUrl = findFirstEntry(mainThread.entries, entry => {\n // Let's find the first entry with URL.\n return Trace.Types.Events.isProfileCall(entry) && Boolean(entry.callFrame.url);\n });\n generateContextMenuForNode(entryWithUrl);\n\n assert.strictEqual(flameChartView.getMainFlameChart().getContextMenu()?.defaultSection().items.length, 6);\n\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(5)\n ?.buildDescriptor()\n .label,\n 'Add script to ignore list');\n });\n\n it('When an entry has URL and is ignored, correctly show the Remove script from ignore list in the Context Menu action',\n async function() {\n const mainThread = getMainThread(parsedTrace.Renderer);\n const entryWithIgnoredUrl = findFirstEntry(mainThread.entries, entry => {\n // Let's find the first entry with URL.\n return Trace.Types.Events.isProfileCall(entry) && Boolean(entry.callFrame.url);\n });\n Bindings.IgnoreListManager.IgnoreListManager.instance().ignoreListURL(\n (entryWithIgnoredUrl as Trace.Types.Events.SyntheticProfileCall).callFrame.url as\n Platform.DevToolsPath.UrlString);\n\n generateContextMenuForNode(entryWithIgnoredUrl);\n\n assert.strictEqual(flameChartView.getMainFlameChart().getContextMenu()?.defaultSection().items.length, 6);\n\n assert.strictEqual(\n flameChartView.getMainFlameChart()\n .getContextMenu()\n ?.defaultSection()\n .items.at(5)\n ?.buildDescriptor()\n .label,\n 'Remove script from ignore list');\n });\n });\n });\n\n describe('Link between entries annotation in progress', function() {\n let flameChartView: Timeline.TimelineFlameChartView.TimelineFlameChartView;\n let parsedTrace: Trace.Handlers.Types.ParsedTrace;\n\n this.beforeEach(async () => {\n ({parsedTrace} = await TraceLoader.traceEngine(this, 'recursive-blocking-js.json.gz'));\n const mockViewDelegate = new MockViewDelegate();\n\n flameChartView = new Timeline.TimelineFlameChartView.TimelineFlameChartView(mockViewDelegate);\n flameChartView.setModel(parsedTrace);\n Timeline.ModificationsManager.ModificationsManager.activeManager();\n });\n\n it('Creates a `link between entries Annotation in progress` tracking object', async function() {\n // Make sure the link annotation in the progress of creation does not exist\n assert.isNull(flameChartView.getLinkSelectionAnnotation());\n\n // Start creating a link between entries from an entry with ID 204\n flameChartView.onEntriesLinkAnnotationCreate(flameChartView.getMainDataProvider(), 204);\n\n // Make sure the link is started and only has 'from' entry set\n assert.isNotNull(flameChartView.getLinkSelectionAnnotation());\n assert.isNotNull(flameChartView.getLinkSelectionAnnotation()?.entryFrom);\n assert.isUndefined(flameChartView.getLinkSelectionAnnotation()?.entryTo);\n\n // Make sure the annotation exists in the ModificationsManager\n const annotations = Timeline.ModificationsManager.ModificationsManager.activeManager()?.getAnnotations();\n assert.exists(annotations);\n assert.strictEqual(annotations?.length, 1);\n assert.strictEqual(annotations[0].type, 'ENTRIES_LINK');\n });\n\n it('Sets the link between entries annotation in progress to null when the second entry is selected',\n async function() {\n // Make sure the link annotation in the progress of creation does not exist\n assert.isNull(flameChartView.getLinkSelectionAnnotation());\n\n // Start creating a link between entries from an entry with ID 204\n flameChartView.onEntriesLinkAnnotationCreate(flameChartView.getMainDataProvider(), 204);\n const entryFrom = flameChartView.getMainDataProvider().eventByIndex(204);\n\n // Hover on another entry to complete the link\n flameChartView.updateLinkSelectionAnnotation(flameChartView.getMainDataProvider(), 245);\n const entryTo = flameChartView.getMainDataProvider().eventByIndex(245);\n // Make sure the entry 'to' is set\n assert.exists(flameChartView.getLinkSelectionAnnotation()?.entryTo);\n\n // Select the other entry to complete the link and set the one in progress to null\n flameChartView.handleToEntryOfLinkBetweenEntriesSelection(245);\n // Make sure the link annotation in progress is set to null\n assert.isNull(flameChartView.getLinkSelectionAnnotation());\n\n // Make sure the annotation exists in the ModificationsManager\n const annotations = Timeline.ModificationsManager.ModificationsManager.activeManager()?.getAnnotations();\n assert.exists(annotations);\n assert.strictEqual(annotations?.length, 1);\n assert.strictEqual(annotations[0].type, 'ENTRIES_LINK');\n const entriesLink = annotations[0] as Trace.Types.File.EntriesLinkAnnotation;\n\n assert.strictEqual(entriesLink.entryFrom, entryFrom);\n assert.strictEqual(entriesLink.entryTo, entryTo);\n });\n\n it('Reverses entries in the link if `to` entry timestamp is earlier than `from` entry timestamo', async function() {\n // Make sure the link annotation in the progress of creation does not exist\n assert.isNull(flameChartView.getLinkSelectionAnnotation());\n\n // Start creating a link between entries from an entry with ID 245\n flameChartView.onEntriesLinkAnnotationCreate(flameChartView.getMainDataProvider(), 245);\n const entryFrom = flameChartView.getMainDataProvider().eventByIndex(245);\n\n // Hover on another entry that starts before the entry that the link is being created from\n flameChartView.updateLinkSelectionAnnotation(flameChartView.getMainDataProvider(), 204);\n const entryTo = flameChartView.getMainDataProvider().eventByIndex(204);\n\n // Select the other entry to complete the link and set the one in progress to null\n flameChartView.handleToEntryOfLinkBetweenEntriesSelection(204);\n\n // Make sure the annotation exists in the ModificationsManager\n const annotations = Timeline.ModificationsManager.ModificationsManager.activeManager()?.getAnnotations();\n assert.exists(annotations);\n assert.strictEqual(annotations?.length, 1);\n assert.strictEqual(annotations[0].type, 'ENTRIES_LINK');\n const entriesLink = annotations[0] as Trace.Types.File.EntriesLinkAnnotation;\n\n // Make 'entryFrom' has an earlier timestamp and the entries `to` and `from` got switched up\n assert.strictEqual(entriesLink.entryFrom, entryTo);\n assert.strictEqual(entriesLink.entryTo, entryFrom);\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineHistoryManager.d.ts b/public/panels/timeline/TimelineHistoryManager.d.ts index a885ca62a..a3244bf04 100644 --- a/public/panels/timeline/TimelineHistoryManager.d.ts +++ b/public/panels/timeline/TimelineHistoryManager.d.ts @@ -1,4 +1,4 @@ -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as UI from '../../ui/legacy/legacy.js'; import { type TimelineMiniMap } from './TimelineMiniMap.js'; /** @@ -15,7 +15,7 @@ export declare const LANDING_PAGE_INDEX_DROPDOWN_CHOICE: number; */ interface TraceRecordingHistoryItem { type: 'TRACE_INDEX'; - traceParseDataIndex: number; + parsedTraceIndex: number; } interface LandingPageHistoryItem { type: 'LANDING_PAGE'; @@ -23,8 +23,8 @@ interface LandingPageHistoryItem { export type RecordingData = TraceRecordingHistoryItem | LandingPageHistoryItem; export interface NewHistoryRecordingData { data: TraceRecordingHistoryItem; - filmStripForPreview: TraceEngine.Extras.FilmStrip.Data | null; - traceParsedData: TraceEngine.Handlers.Types.TraceParseData; + filmStripForPreview: Trace.Extras.FilmStrip.Data | null; + parsedTrace: Trace.Handlers.Types.ParsedTrace; startTime: number | null; } export declare class TimelineHistoryManager { @@ -51,7 +51,7 @@ export declare class TimelineHistoryManager { */ navigate(direction: number): TraceRecordingHistoryItem | null; private updateState; - static previewElement(traceDataIndex: number): Element; + static previewElement(parsedTraceIndex: number): Element; private static coarseAge; private title; private static dataForTraceIndex; @@ -71,17 +71,17 @@ export declare class DropDown implements UI.ListControl.ListDelegate { private readonly listControl; private readonly focusRestorer; private selectionDone; - constructor(availableTraceDataIndexes: number[]); - static show(availableTraceDataIndexes: number[], activeTraceDataIndex: number, anchor: Element): Promise; + constructor(availableparsedTraceIndexes: number[]); + static show(availableparsedTraceIndexes: number[], activeparsedTraceIndex: number, anchor: Element): Promise; static cancelIfShowing(): void; private show; private onMouseMove; private onClick; private onKeyDown; private close; - createElementForItem(traceDataIndex: number): Element; - heightForItem(_traceDataIndex: number): number; - isItemSelectable(_traceDataIndex: number): boolean; + createElementForItem(parsedTraceIndex: number): Element; + heightForItem(_parsedTraceIndex: number): number; + isItemSelectable(_parsedTraceIndex: number): boolean; selectedItemChanged(_from: number | null, _to: number | null, fromElement: Element | null, toElement: Element | null): void; updateSelectedItemARIA(_fromElement: Element | null, _toElement: Element | null): boolean; private static instance; diff --git a/public/panels/timeline/TimelineHistoryManager.js b/public/panels/timeline/TimelineHistoryManager.js index 02e8686d5..9628a5a5d 100644 --- a/public/panels/timeline/TimelineHistoryManager.js +++ b/public/panels/timeline/TimelineHistoryManager.js @@ -6,7 +6,7 @@ import * as i18n from '../../core/i18n/i18n.js'; import * as Platform from '../../core/platform/platform.js'; import * as Root from '../../core/root/root.js'; import * as CrUXManager from '../../models/crux-manager/crux-manager.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as IconButton from '../../ui/components/icon_button/icon_button.js'; import * as UI from '../../ui/legacy/legacy.js'; import * as VisualLogging from '../../ui/visual_logging/visual_logging.js'; @@ -90,26 +90,26 @@ export class TimelineHistoryManager { // before creating new instances. this.allOverviews = [ { - constructor: traceParsedData => { + constructor: parsedTrace => { const responsivenessOverviewFromMinimap = this.#minimapComponent?.getControls().find(control => control instanceof TimelineEventOverviewResponsiveness); - return responsivenessOverviewFromMinimap || new TimelineEventOverviewResponsiveness(traceParsedData); + return responsivenessOverviewFromMinimap || new TimelineEventOverviewResponsiveness(parsedTrace); }, height: 3, }, { - constructor: traceParsedData => { + constructor: parsedTrace => { const cpuOverviewFromMinimap = this.#minimapComponent?.getControls().find(control => control instanceof TimelineEventOverviewCPUActivity); if (cpuOverviewFromMinimap) { return cpuOverviewFromMinimap; } - return new TimelineEventOverviewCPUActivity(traceParsedData); + return new TimelineEventOverviewCPUActivity(parsedTrace); }, height: 20, }, { - constructor: traceParsedData => { + constructor: parsedTrace => { const networkOverviewFromMinimap = this.#minimapComponent?.getControls().find(control => control instanceof TimelineEventOverviewNetwork); - return networkOverviewFromMinimap || new TimelineEventOverviewNetwork(traceParsedData); + return networkOverviewFromMinimap || new TimelineEventOverviewNetwork(parsedTrace); }, height: 8, }, @@ -140,7 +140,7 @@ export class TimelineHistoryManager { this.recordings.unshift(newInput.data); // Order is important: this needs to happen first because lots of the // subsequent code depends on us storing the preview data into the map. - this.#buildAndStorePreviewData(newInput.data.traceParseDataIndex, newInput.traceParsedData, filmStrip, newInput.startTime); + this.#buildAndStorePreviewData(newInput.data.parsedTraceIndex, newInput.parsedTrace, filmStrip, newInput.startTime); const modelTitle = this.title(newInput.data); this.buttonInternal.setText(modelTitle); const buttonTitle = this.action.title(); @@ -149,7 +149,7 @@ export class TimelineHistoryManager { if (this.recordings.length <= maxRecordings) { return; } - const modelUsedMoreTimeAgo = this.recordings.reduce((a, b) => lastUsedTime(a.traceParseDataIndex) < lastUsedTime(b.traceParseDataIndex) ? a : b); + const modelUsedMoreTimeAgo = this.recordings.reduce((a, b) => lastUsedTime(a.parsedTraceIndex) < lastUsedTime(b.parsedTraceIndex) ? a : b); this.recordings.splice(this.recordings.indexOf(modelUsedMoreTimeAgo), 1); function lastUsedTime(index) { const data = TimelineHistoryManager.dataForTraceIndex(index); @@ -193,14 +193,14 @@ export class TimelineHistoryManager { if (this.lastActiveTrace.type === 'LANDING_PAGE') { return LANDING_PAGE_INDEX_DROPDOWN_CHOICE; } - return this.lastActiveTrace.traceParseDataIndex; + return this.lastActiveTrace.parsedTraceIndex; } async showHistoryDropDown() { if (this.recordings.length < this.#minimumRequiredRecordings() || !this.enabled) { return null; } // DropDown.show() function finishes when the dropdown menu is closed via selection or losing focus - const activeTraceIndex = await DropDown.show(this.recordings.map(recording => recording.traceParseDataIndex), this.#getActiveTraceIndexForListControl(), this.buttonInternal.element); + const activeTraceIndex = await DropDown.show(this.recordings.map(recording => recording.parsedTraceIndex), this.#getActiveTraceIndexForListControl(), this.buttonInternal.element); if (activeTraceIndex === null) { return null; } @@ -210,7 +210,7 @@ export class TimelineHistoryManager { this.#setActiveTrace({ type: 'LANDING_PAGE' }); return { type: 'LANDING_PAGE' }; } - const index = this.recordings.findIndex(recording => recording.traceParseDataIndex === activeTraceIndex); + const index = this.recordings.findIndex(recording => recording.parsedTraceIndex === activeTraceIndex); if (index < 0) { console.assert(false, 'selected recording not found'); return null; @@ -235,7 +235,7 @@ export class TimelineHistoryManager { } const index = this.recordings.findIndex(recording => { return this.lastActiveTrace?.type === 'TRACE_INDEX' && recording.type === 'TRACE_INDEX' && - recording.traceParseDataIndex === this.lastActiveTrace.traceParseDataIndex; + recording.parsedTraceIndex === this.lastActiveTrace.parsedTraceIndex; }); if (index < 0) { return null; @@ -246,7 +246,7 @@ export class TimelineHistoryManager { } #setActiveTrace(item) { if (item.type === 'TRACE_INDEX') { - const data = TimelineHistoryManager.dataForTraceIndex(item.traceParseDataIndex); + const data = TimelineHistoryManager.dataForTraceIndex(item.parsedTraceIndex); if (!data) { throw new Error('Unable to find data for model'); } @@ -261,8 +261,8 @@ export class TimelineHistoryManager { updateState() { this.action.setEnabled(this.recordings.length >= this.#minimumRequiredRecordings() && this.enabled); } - static previewElement(traceDataIndex) { - const data = TimelineHistoryManager.dataForTraceIndex(traceDataIndex); + static previewElement(parsedTraceIndex) { + const data = TimelineHistoryManager.dataForTraceIndex(parsedTraceIndex); if (!data) { throw new Error('Unable to find data for model'); } @@ -287,14 +287,14 @@ export class TimelineHistoryManager { if (item.type === 'LANDING_PAGE') { return i18nString(UIStrings.landingPageTitle); } - const data = TimelineHistoryManager.dataForTraceIndex(item.traceParseDataIndex); + const data = TimelineHistoryManager.dataForTraceIndex(item.parsedTraceIndex); if (!data) { throw new Error('Unable to find data for model'); } return data.title; } - #buildAndStorePreviewData(traceParseDataIndex, traceParsedData, filmStrip, startTime) { - const parsedURL = Common.ParsedURL.ParsedURL.fromString(traceParsedData.Meta.mainFrameURL); + #buildAndStorePreviewData(parsedTraceIndex, parsedTrace, filmStrip, startTime) { + const parsedURL = Common.ParsedURL.ParsedURL.fromString(parsedTrace.Meta.mainFrameURL); const domain = parsedURL ? parsedURL.host : ''; const sequenceNumber = this.nextNumberByDomain.get(domain) || 1; const titleWithSequenceNumber = i18nString(UIStrings.sD, { PH1: domain, PH2: sequenceNumber }); @@ -311,21 +311,21 @@ export class TimelineHistoryManager { lastUsed: Date.now(), startTime, }; - traceDataIndexToPerformancePreviewData.set(traceParseDataIndex, data); - preview.appendChild(this.#buildTextDetails(traceParsedData, domain, timeElement)); + parsedTraceIndexToPerformancePreviewData.set(parsedTraceIndex, data); + preview.appendChild(this.#buildTextDetails(parsedTrace, domain, timeElement)); const screenshotAndOverview = preview.createChild('div', 'hbox'); screenshotAndOverview.appendChild(this.#buildScreenshotThumbnail(filmStrip)); - screenshotAndOverview.appendChild(this.#buildOverview(traceParsedData)); + screenshotAndOverview.appendChild(this.#buildOverview(parsedTrace)); return data.preview; } - #buildTextDetails(traceParsedData, title, timeElement) { + #buildTextDetails(parsedTrace, title, timeElement) { const container = document.createElement('div'); container.classList.add('text-details'); container.classList.add('hbox'); const nameSpan = container.createChild('span', 'name'); nameSpan.textContent = title; UI.ARIAUtils.setLabel(nameSpan, title); - const bounds = TraceEngine.Helpers.Timing.traceWindowMilliSeconds(traceParsedData.Meta.traceBounds); + const bounds = Trace.Helpers.Timing.traceWindowMilliSeconds(parsedTrace.Meta.traceBounds); const duration = i18n.TimeUtilities.millisToString(bounds.range, false); const timeContainer = container.createChild('span', 'time'); timeContainer.appendChild(document.createTextNode(duration)); @@ -352,7 +352,7 @@ export class TimelineHistoryManager { }); return container; } - #buildOverview(traceParsedData) { + #buildOverview(parsedTrace) { const container = document.createElement('div'); const dPR = window.devicePixelRatio; container.style.width = previewWidth + 'px'; @@ -363,7 +363,7 @@ export class TimelineHistoryManager { const ctx = canvas.getContext('2d'); let yOffset = 0; for (const overview of this.allOverviews) { - const timelineOverviewComponent = overview.constructor(traceParsedData); + const timelineOverviewComponent = overview.constructor(parsedTrace); timelineOverviewComponent.update(); if (ctx) { ctx.drawImage(timelineOverviewComponent.context().canvas, 0, yOffset, dPR * previewWidth, overview.height * dPR); @@ -373,20 +373,20 @@ export class TimelineHistoryManager { return container; } static dataForTraceIndex(index) { - return traceDataIndexToPerformancePreviewData.get(index) || null; + return parsedTraceIndexToPerformancePreviewData.get(index) || null; } } export const maxRecordings = 5; export const previewWidth = 450; // The reason we store a global map is because the Dropdown component needs to // be able to read the preview data in order to show a preview in the dropdown. -const traceDataIndexToPerformancePreviewData = new Map(); +const parsedTraceIndexToPerformancePreviewData = new Map(); export class DropDown { glassPane; listControl; focusRestorer; selectionDone; - constructor(availableTraceDataIndexes) { + constructor(availableparsedTraceIndexes) { this.glassPane = new UI.GlassPane.GlassPane(); this.glassPane.setSizeBehavior("MeasureContent" /* UI.GlassPane.SizeBehavior.MEASURE_CONTENT */); this.glassPane.setOutsideClickCallback(() => this.close(null)); @@ -401,7 +401,7 @@ export class DropDown { const listModel = new UI.ListModel.ListModel(); this.listControl = new UI.ListControl.ListControl(listModel, this, UI.ListControl.ListMode.NonViewport); this.listControl.element.addEventListener('mousemove', this.onMouseMove.bind(this), false); - listModel.replaceAll(availableTraceDataIndexes); + listModel.replaceAll(availableparsedTraceIndexes); UI.ARIAUtils.markAsMenu(this.listControl.element); UI.ARIAUtils.setLabel(this.listControl.element, i18nString(UIStrings.selectTimelineSession)); contentElement.appendChild(this.listControl.element); @@ -410,16 +410,16 @@ export class DropDown { this.focusRestorer = new UI.UIUtils.ElementFocusRestorer(this.listControl.element); this.selectionDone = null; } - static show(availableTraceDataIndexes, activeTraceDataIndex, anchor) { + static show(availableparsedTraceIndexes, activeparsedTraceIndex, anchor) { if (DropDown.instance) { return Promise.resolve(null); } - const availableDropdownChoices = [...availableTraceDataIndexes]; + const availableDropdownChoices = [...availableparsedTraceIndexes]; if (Root.Runtime.experiments.isEnabled("timeline-observations" /* Root.Runtime.ExperimentName.TIMELINE_OBSERVATIONS */)) { availableDropdownChoices.unshift(LANDING_PAGE_INDEX_DROPDOWN_CHOICE); } const instance = new DropDown(availableDropdownChoices); - return instance.show(anchor, activeTraceDataIndex); + return instance.show(anchor, activeparsedTraceIndex); } static cancelIfShowing() { if (!DropDown.instance) { @@ -427,12 +427,12 @@ export class DropDown { } DropDown.instance.close(null); } - show(anchor, activeTraceDataIndex) { + show(anchor, activeparsedTraceIndex) { DropDown.instance = this; this.glassPane.setContentAnchorBox(anchor.boxInWindow()); this.glassPane.show(this.glassPane.contentElement.ownerDocument); this.listControl.element.focus(); - this.listControl.selectItem(activeTraceDataIndex); + this.listControl.selectItem(activeparsedTraceIndex); return new Promise(fulfill => { this.selectionDone = fulfill; }); @@ -475,11 +475,11 @@ export class DropDown { this.glassPane.hide(); DropDown.instance = null; } - createElementForItem(traceDataIndex) { - if (traceDataIndex === LANDING_PAGE_INDEX_DROPDOWN_CHOICE) { + createElementForItem(parsedTraceIndex) { + if (parsedTraceIndex === LANDING_PAGE_INDEX_DROPDOWN_CHOICE) { return this.#createLandingPageListItem(); } - const element = TimelineHistoryManager.previewElement(traceDataIndex); + const element = TimelineHistoryManager.previewElement(parsedTraceIndex); UI.ARIAUtils.markAsMenuItem(element); element.classList.remove('selected'); return element; @@ -497,11 +497,11 @@ export class DropDown { div.appendChild(text); return div; } - heightForItem(_traceDataIndex) { + heightForItem(_parsedTraceIndex) { console.assert(false, 'Should not be called'); return 0; } - isItemSelectable(_traceDataIndex) { + isItemSelectable(_parsedTraceIndex) { return true; } selectedItemChanged(_from, _to, fromElement, toElement) { diff --git a/public/panels/timeline/TimelineHistoryManager.js.map b/public/panels/timeline/TimelineHistoryManager.js.map index eff909998..b086e7302 100644 --- a/public/panels/timeline/TimelineHistoryManager.js.map +++ b/public/panels/timeline/TimelineHistoryManager.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineHistoryManager.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineHistoryManager.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as Root from '../../core/root/root.js';\nimport * as CrUXManager from '../../models/crux-manager/crux-manager.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as IconButton from '../../ui/components/icon_button/icon_button.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport {\n type TimelineEventOverview,\n TimelineEventOverviewCPUActivity,\n TimelineEventOverviewNetwork,\n TimelineEventOverviewResponsiveness,\n} from './TimelineEventOverview.js';\nimport timelineHistoryManagerStyles from './timelineHistoryManager.css.js';\nimport {type TimelineMiniMap} from './TimelineMiniMap.js';\n\n/**\n * The dropdown works by returning an index which is the trace index; but we\n * also need a way to signify that the user picked the \"Landing Page\" option. We\n * represent that as Infinity so we never accidentally collide with an actual\n * trace (in reality a large number like 99 would probably suffice...)\n */\nexport const LANDING_PAGE_INDEX_DROPDOWN_CHOICE = Infinity;\n\nconst UIStrings = {\n /**\n *@description Screen reader label for the Timeline History dropdown button\n *@example {example.com #3} PH1\n *@example {Show recent timeline sessions} PH2\n */\n currentSessionSS: 'Current session: {PH1}. {PH2}',\n /**\n *@description the title shown when the user is viewing the landing page which is showing live performance metrics that are updated automatically.\n */\n landingPageTitle: 'Live metrics',\n /**\n *@description Text that shows there is no recording\n */\n noRecordings: '(no recordings)',\n /**\n *@description Text in Timeline History Manager of the Performance panel\n *@example {2s} PH1\n */\n sAgo: '({PH1} ago)',\n /**\n *@description Text in Timeline History Manager of the Performance panel\n */\n moments: 'moments',\n /**\n * @description Text in Timeline History Manager of the Performance panel.\n * Placeholder is a number and the 'm' is the short form for 'minutes'.\n * @example {2} PH1\n */\n sM: '{PH1} m',\n /**\n * @description Text in Timeline History Manager of the Performance panel.\n * Placeholder is a number and the 'h' is the short form for 'hours'.\n * @example {2} PH1\n */\n sH: '{PH1} h',\n /**\n *@description Text in Timeline History Manager of the Performance panel\n *@example {example.com} PH1\n *@example {2} PH2\n */\n sD: '{PH1} #{PH2}',\n /**\n *@description Accessible label for the timeline session selection menu\n */\n selectTimelineSession: 'Select timeline session',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelineHistoryManager.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\n/**\n * The dropdown includes an option to navigate to the landing page; hence the\n * two types for storing recordings. The TimelineHistoryManager automatically\n * includes a link to go back to the landing page.\n */\ninterface TraceRecordingHistoryItem {\n type: 'TRACE_INDEX';\n // By storing only the index of this trace, the TimelinePanel can then look\n // up this trace's data (and metadata) via this index.\n traceParseDataIndex: number;\n}\ninterface LandingPageHistoryItem {\n type: 'LANDING_PAGE';\n}\nexport type RecordingData = TraceRecordingHistoryItem|LandingPageHistoryItem;\n\nexport interface NewHistoryRecordingData {\n // The data we will save to restore later.\n data: TraceRecordingHistoryItem;\n // We do not store this, but need it to build the thumbnail preview.\n filmStripForPreview: TraceEngine.Extras.FilmStrip.Data|null;\n // Also not stored, but used to create the preview overview for a new trace.\n traceParsedData: TraceEngine.Handlers.Types.TraceParseData;\n // Used for the preview text\n startTime: number|null;\n}\n\nexport class TimelineHistoryManager {\n private recordings: TraceRecordingHistoryItem[];\n private readonly action: UI.ActionRegistration.Action;\n private readonly nextNumberByDomain: Map;\n private readonly buttonInternal: ToolbarButton;\n private readonly allOverviews: {\n constructor: (traceParsedData: TraceEngine.Handlers.Types.TraceParseData) => TimelineEventOverview,\n height: number,\n }[];\n private totalHeight: number;\n private enabled: boolean;\n private lastActiveTrace: RecordingData|null = null;\n #minimapComponent?: TimelineMiniMap;\n constructor(minimapComponent?: TimelineMiniMap) {\n this.recordings = [];\n this.#minimapComponent = minimapComponent;\n this.action = UI.ActionRegistry.ActionRegistry.instance().getAction('timeline.show-history');\n this.nextNumberByDomain = new Map();\n this.buttonInternal = new ToolbarButton(this.action);\n\n UI.ARIAUtils.markAsMenuButton(this.buttonInternal.element);\n this.clear();\n\n // Attempt to reuse the overviews coming from the panel's minimap\n // before creating new instances.\n this.allOverviews = [\n {\n\n constructor: traceParsedData => {\n const responsivenessOverviewFromMinimap =\n this.#minimapComponent?.getControls().find(\n control => control instanceof TimelineEventOverviewResponsiveness) as\n TimelineEventOverviewResponsiveness;\n return responsivenessOverviewFromMinimap || new TimelineEventOverviewResponsiveness(traceParsedData);\n },\n height: 3,\n },\n {\n constructor: traceParsedData => {\n const cpuOverviewFromMinimap =\n this.#minimapComponent?.getControls().find(\n control => control instanceof TimelineEventOverviewCPUActivity) as TimelineEventOverviewCPUActivity;\n if (cpuOverviewFromMinimap) {\n return cpuOverviewFromMinimap;\n }\n return new TimelineEventOverviewCPUActivity(traceParsedData);\n },\n height: 20,\n },\n {\n constructor: traceParsedData => {\n const networkOverviewFromMinimap =\n this.#minimapComponent?.getControls().find(control => control instanceof TimelineEventOverviewNetwork) as\n TimelineEventOverviewNetwork;\n return networkOverviewFromMinimap || new TimelineEventOverviewNetwork(traceParsedData);\n },\n height: 8,\n },\n ];\n this.totalHeight = this.allOverviews.reduce((acc, entry) => acc + entry.height, 0);\n this.enabled = true;\n\n CrUXManager.CrUXManager.instance().addEventListener(CrUXManager.Events.FIELD_DATA_CHANGED, () => {\n this.#updateLandingPageTitleIfActive();\n });\n }\n\n /**\n * If the user changes the CrUX consent status, the title shown in the\n * dropdown could be outdated, as we show \"Local\" or \"Local and field\"\n * depending on if the user has consented.\n * This method will be called whenever the CrUXManager detects a change, and\n * we use it as a chance to re-evaluate if the title needs changing or not.\n */\n #updateLandingPageTitleIfActive(): void {\n if (this.lastActiveTrace?.type === 'LANDING_PAGE') {\n const title = this.title(this.lastActiveTrace);\n this.buttonInternal.setTitle(title);\n this.buttonInternal.setText(title);\n }\n }\n\n addRecording(newInput: NewHistoryRecordingData): void {\n const filmStrip = newInput.filmStripForPreview;\n this.lastActiveTrace = newInput.data;\n this.recordings.unshift(newInput.data);\n\n // Order is important: this needs to happen first because lots of the\n // subsequent code depends on us storing the preview data into the map.\n this.#buildAndStorePreviewData(\n newInput.data.traceParseDataIndex, newInput.traceParsedData, filmStrip, newInput.startTime);\n\n const modelTitle = this.title(newInput.data);\n this.buttonInternal.setText(modelTitle);\n const buttonTitle = this.action.title();\n UI.ARIAUtils.setLabel(\n this.buttonInternal.element, i18nString(UIStrings.currentSessionSS, {PH1: modelTitle, PH2: buttonTitle}));\n this.updateState();\n if (this.recordings.length <= maxRecordings) {\n return;\n }\n const modelUsedMoreTimeAgo = this.recordings.reduce(\n (a, b) => lastUsedTime(a.traceParseDataIndex) < lastUsedTime(b.traceParseDataIndex) ? a : b);\n this.recordings.splice(this.recordings.indexOf(modelUsedMoreTimeAgo), 1);\n\n function lastUsedTime(index: number): number {\n const data = TimelineHistoryManager.dataForTraceIndex(index);\n if (!data) {\n throw new Error('Unable to find data for model');\n }\n return data.lastUsed;\n }\n }\n\n setEnabled(enabled: boolean): void {\n this.enabled = enabled;\n this.updateState();\n }\n\n button(): ToolbarButton {\n return this.buttonInternal;\n }\n\n clear(): void {\n this.recordings = [];\n this.lastActiveTrace = null;\n this.updateState();\n this.buttonInternal.setText(i18nString(UIStrings.noRecordings));\n this.nextNumberByDomain.clear();\n }\n\n /**\n * If the observations landing page experiment is enabled, we show the\n * dropdown when there is 1 or more traces active, as even with 1 trace we\n * need to give the user a way to get back to the index page. However, if that\n * experiment is disabled, there is no need to show the dropdown until there\n * are 2+ traces.\n */\n #minimumRequiredRecordings(): number {\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_OBSERVATIONS)) {\n return 1;\n }\n return 2;\n }\n\n #getActiveTraceIndexForListControl(): number {\n if (!this.lastActiveTrace) {\n return -1;\n }\n if (this.lastActiveTrace.type === 'LANDING_PAGE') {\n return LANDING_PAGE_INDEX_DROPDOWN_CHOICE;\n }\n return this.lastActiveTrace.traceParseDataIndex;\n }\n\n async showHistoryDropDown(): Promise {\n if (this.recordings.length < this.#minimumRequiredRecordings() || !this.enabled) {\n return null;\n }\n\n // DropDown.show() function finishes when the dropdown menu is closed via selection or losing focus\n const activeTraceIndex = await DropDown.show(\n this.recordings.map(recording => recording.traceParseDataIndex), this.#getActiveTraceIndexForListControl(),\n this.buttonInternal.element);\n\n if (activeTraceIndex === null) {\n return null;\n }\n\n // The ListControl class that backs the dropdown uses indexes; we represent\n // the landing page choice via this special index.\n if (activeTraceIndex === LANDING_PAGE_INDEX_DROPDOWN_CHOICE) {\n this.#setActiveTrace({type: 'LANDING_PAGE'});\n return {type: 'LANDING_PAGE'};\n }\n\n const index = this.recordings.findIndex(recording => recording.traceParseDataIndex === activeTraceIndex);\n if (index < 0) {\n console.assert(false, 'selected recording not found');\n return null;\n }\n\n this.#setActiveTrace(this.recordings[index]);\n return this.recordings[index];\n }\n\n cancelIfShowing(): void {\n DropDown.cancelIfShowing();\n }\n\n /**\n * Navigate by 1 in either direction to the next trace.\n * Navigating in this way does not include the landing page; it will loop\n * over only the traces.\n */\n navigate(direction: number): TraceRecordingHistoryItem|null {\n if (!this.enabled || this.lastActiveTrace === null) {\n return null;\n }\n if (!this.lastActiveTrace || this.lastActiveTrace.type === 'LANDING_PAGE') {\n return null;\n }\n\n const index = this.recordings.findIndex(recording => {\n return this.lastActiveTrace?.type === 'TRACE_INDEX' && recording.type === 'TRACE_INDEX' &&\n recording.traceParseDataIndex === this.lastActiveTrace.traceParseDataIndex;\n });\n\n if (index < 0) {\n return null;\n }\n\n const newIndex = Platform.NumberUtilities.clamp(index + direction, 0, this.recordings.length - 1);\n this.#setActiveTrace(this.recordings[newIndex]);\n return this.recordings[newIndex];\n }\n\n #setActiveTrace(item: RecordingData): void {\n if (item.type === 'TRACE_INDEX') {\n const data = TimelineHistoryManager.dataForTraceIndex(item.traceParseDataIndex);\n if (!data) {\n throw new Error('Unable to find data for model');\n }\n data.lastUsed = Date.now();\n }\n\n this.lastActiveTrace = item;\n const modelTitle = this.title(item);\n const buttonTitle = this.action.title();\n this.buttonInternal.setText(modelTitle);\n UI.ARIAUtils.setLabel(\n this.buttonInternal.element, i18nString(UIStrings.currentSessionSS, {PH1: modelTitle, PH2: buttonTitle}));\n }\n\n private updateState(): void {\n this.action.setEnabled(this.recordings.length >= this.#minimumRequiredRecordings() && this.enabled);\n }\n\n static previewElement(traceDataIndex: number): Element {\n const data = TimelineHistoryManager.dataForTraceIndex(traceDataIndex);\n if (!data) {\n throw new Error('Unable to find data for model');\n }\n const startedAt = data.startTime;\n data.time.textContent =\n startedAt ? i18nString(UIStrings.sAgo, {PH1: TimelineHistoryManager.coarseAge(startedAt)}) : '';\n return data.preview;\n }\n\n private static coarseAge(time: number): string {\n const seconds = Math.round((Date.now() - time) / 1000);\n if (seconds < 50) {\n return i18nString(UIStrings.moments);\n }\n const minutes = Math.round(seconds / 60);\n if (minutes < 50) {\n return i18nString(UIStrings.sM, {PH1: minutes});\n }\n const hours = Math.round(minutes / 60);\n return i18nString(UIStrings.sH, {PH1: hours});\n }\n\n private title(item: RecordingData): string {\n if (item.type === 'LANDING_PAGE') {\n return i18nString(UIStrings.landingPageTitle);\n }\n\n const data = TimelineHistoryManager.dataForTraceIndex(item.traceParseDataIndex);\n if (!data) {\n throw new Error('Unable to find data for model');\n }\n return data.title;\n }\n\n #buildAndStorePreviewData(\n traceParseDataIndex: number, traceParsedData: TraceEngine.Handlers.Types.TraceParseData,\n filmStrip: TraceEngine.Extras.FilmStrip.Data|null, startTime: number|null): HTMLDivElement {\n const parsedURL = Common.ParsedURL.ParsedURL.fromString(traceParsedData.Meta.mainFrameURL);\n const domain = parsedURL ? parsedURL.host : '';\n\n const sequenceNumber = this.nextNumberByDomain.get(domain) || 1;\n const titleWithSequenceNumber = i18nString(UIStrings.sD, {PH1: domain, PH2: sequenceNumber});\n this.nextNumberByDomain.set(domain, sequenceNumber + 1);\n const timeElement = document.createElement('span');\n\n const preview = document.createElement('div');\n preview.classList.add('preview-item');\n preview.classList.add('vbox');\n preview.setAttribute('jslog', `${VisualLogging.dropDown('timeline.history-item').track({click: true})}`);\n const data = {\n preview,\n title: titleWithSequenceNumber,\n time: timeElement,\n lastUsed: Date.now(),\n startTime,\n };\n traceDataIndexToPerformancePreviewData.set(traceParseDataIndex, data);\n\n preview.appendChild(this.#buildTextDetails(traceParsedData, domain, timeElement));\n const screenshotAndOverview = preview.createChild('div', 'hbox');\n screenshotAndOverview.appendChild(this.#buildScreenshotThumbnail(filmStrip));\n screenshotAndOverview.appendChild(this.#buildOverview(traceParsedData));\n return data.preview;\n }\n\n #buildTextDetails(traceParsedData: TraceEngine.Handlers.Types.TraceParseData, title: string, timeElement: Element):\n Element {\n const container = document.createElement('div');\n container.classList.add('text-details');\n container.classList.add('hbox');\n const nameSpan = container.createChild('span', 'name');\n nameSpan.textContent = title;\n UI.ARIAUtils.setLabel(nameSpan, title);\n const bounds = TraceEngine.Helpers.Timing.traceWindowMilliSeconds(traceParsedData.Meta.traceBounds);\n const duration = i18n.TimeUtilities.millisToString(bounds.range, false);\n const timeContainer = container.createChild('span', 'time');\n timeContainer.appendChild(document.createTextNode(duration));\n timeContainer.appendChild(timeElement);\n return container;\n }\n\n #buildScreenshotThumbnail(filmStrip: TraceEngine.Extras.FilmStrip.Data|null): Element {\n const container = document.createElement('div');\n container.classList.add('screenshot-thumb');\n const thumbnailAspectRatio = 3 / 2;\n container.style.width = this.totalHeight * thumbnailAspectRatio + 'px';\n container.style.height = this.totalHeight + 'px';\n if (!filmStrip) {\n return container;\n }\n const lastFrame = filmStrip.frames.at(-1);\n if (!lastFrame) {\n return container;\n }\n void UI.UIUtils.loadImage(lastFrame.screenshotEvent.args.dataUri).then(img => {\n if (img) {\n container.appendChild(img);\n }\n });\n return container;\n }\n\n #buildOverview(traceParsedData: TraceEngine.Handlers.Types.TraceParseData): Element {\n const container = document.createElement('div');\n const dPR = window.devicePixelRatio;\n container.style.width = previewWidth + 'px';\n container.style.height = this.totalHeight + 'px';\n const canvas = (container.createChild('canvas') as HTMLCanvasElement);\n canvas.width = dPR * previewWidth;\n canvas.height = dPR * this.totalHeight;\n\n const ctx = canvas.getContext('2d');\n let yOffset = 0;\n\n for (const overview of this.allOverviews) {\n const timelineOverviewComponent = overview.constructor(traceParsedData);\n timelineOverviewComponent.update();\n if (ctx) {\n ctx.drawImage(\n timelineOverviewComponent.context().canvas, 0, yOffset, dPR * previewWidth, overview.height * dPR);\n }\n yOffset += overview.height * dPR;\n }\n return container;\n }\n\n private static dataForTraceIndex(index: number): PreviewData|null {\n return traceDataIndexToPerformancePreviewData.get(index) || null;\n }\n}\n\nexport const maxRecordings = 5;\nexport const previewWidth = 450;\n// The reason we store a global map is because the Dropdown component needs to\n// be able to read the preview data in order to show a preview in the dropdown.\nconst traceDataIndexToPerformancePreviewData = new Map();\n\nexport interface PreviewData {\n preview: Element;\n time: Element;\n lastUsed: number;\n startTime: number|null;\n title: string;\n}\n\nexport class DropDown implements UI.ListControl.ListDelegate {\n private readonly glassPane: UI.GlassPane.GlassPane;\n private readonly listControl: UI.ListControl.ListControl;\n private readonly focusRestorer: UI.UIUtils.ElementFocusRestorer;\n private selectionDone: ((arg0: number|null) => void)|null;\n\n constructor(availableTraceDataIndexes: number[]) {\n this.glassPane = new UI.GlassPane.GlassPane();\n this.glassPane.setSizeBehavior(UI.GlassPane.SizeBehavior.MEASURE_CONTENT);\n this.glassPane.setOutsideClickCallback(() => this.close(null));\n this.glassPane.setPointerEventsBehavior(UI.GlassPane.PointerEventsBehavior.BLOCKED_BY_GLASS_PANE);\n this.glassPane.setAnchorBehavior(UI.GlassPane.AnchorBehavior.PREFER_BOTTOM);\n this.glassPane.element.addEventListener('blur', () => this.close(null));\n\n const shadowRoot = UI.UIUtils.createShadowRootWithCoreStyles(this.glassPane.contentElement, {\n cssFile: [timelineHistoryManagerStyles],\n delegatesFocus: undefined,\n });\n const contentElement = shadowRoot.createChild('div', 'drop-down');\n\n const listModel = new UI.ListModel.ListModel();\n this.listControl = new UI.ListControl.ListControl(listModel, this, UI.ListControl.ListMode.NonViewport);\n this.listControl.element.addEventListener('mousemove', this.onMouseMove.bind(this), false);\n listModel.replaceAll(availableTraceDataIndexes);\n\n UI.ARIAUtils.markAsMenu(this.listControl.element);\n UI.ARIAUtils.setLabel(this.listControl.element, i18nString(UIStrings.selectTimelineSession));\n contentElement.appendChild(this.listControl.element);\n contentElement.addEventListener('keydown', this.onKeyDown.bind(this), false);\n contentElement.addEventListener('click', this.onClick.bind(this), false);\n\n this.focusRestorer = new UI.UIUtils.ElementFocusRestorer(this.listControl.element);\n this.selectionDone = null;\n }\n\n static show(availableTraceDataIndexes: number[], activeTraceDataIndex: number, anchor: Element):\n Promise {\n if (DropDown.instance) {\n return Promise.resolve(null);\n }\n const availableDropdownChoices = [...availableTraceDataIndexes];\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_OBSERVATIONS)) {\n availableDropdownChoices.unshift(LANDING_PAGE_INDEX_DROPDOWN_CHOICE);\n }\n const instance = new DropDown(availableDropdownChoices);\n return instance.show(anchor, activeTraceDataIndex);\n }\n\n static cancelIfShowing(): void {\n if (!DropDown.instance) {\n return;\n }\n DropDown.instance.close(null);\n }\n\n private show(anchor: Element, activeTraceDataIndex: number): Promise {\n DropDown.instance = this;\n this.glassPane.setContentAnchorBox(anchor.boxInWindow());\n this.glassPane.show(this.glassPane.contentElement.ownerDocument);\n this.listControl.element.focus();\n this.listControl.selectItem(activeTraceDataIndex);\n\n return new Promise(fulfill => {\n this.selectionDone = fulfill;\n });\n }\n\n private onMouseMove(event: Event): void {\n const node = (event.target as HTMLElement).enclosingNodeOrSelfWithClass('preview-item');\n const listItem = node && this.listControl.itemForNode(node);\n if (listItem === null) {\n return;\n }\n this.listControl.selectItem(listItem);\n }\n\n private onClick(event: Event): void {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // @ts-expect-error\n if (!(event.target).enclosingNodeOrSelfWithClass('preview-item')) {\n return;\n }\n this.close(this.listControl.selectedItem());\n }\n\n private onKeyDown(event: Event): void {\n switch ((event as KeyboardEvent).key) {\n case 'Tab':\n case 'Escape':\n this.close(null);\n break;\n case 'Enter':\n this.close(this.listControl.selectedItem());\n break;\n default:\n return;\n }\n event.consume(true);\n }\n\n private close(traceIndex: number|null): void {\n if (this.selectionDone) {\n this.selectionDone(traceIndex);\n }\n this.focusRestorer.restore();\n this.glassPane.hide();\n DropDown.instance = null;\n }\n\n createElementForItem(traceDataIndex: number): Element {\n if (traceDataIndex === LANDING_PAGE_INDEX_DROPDOWN_CHOICE) {\n return this.#createLandingPageListItem();\n }\n const element = TimelineHistoryManager.previewElement(traceDataIndex);\n UI.ARIAUtils.markAsMenuItem(element);\n element.classList.remove('selected');\n return element;\n }\n\n #createLandingPageListItem(): HTMLElement {\n const div = document.createElement('div');\n UI.ARIAUtils.markAsMenuItem(div);\n div.classList.remove('selected');\n div.classList.add('preview-item');\n div.classList.add('landing-page-item');\n\n const icon = IconButton.Icon.create('arrow-back');\n div.appendChild(icon);\n\n const text = document.createElement('span');\n text.innerText = i18nString(UIStrings.landingPageTitle);\n div.appendChild(text);\n return div;\n }\n\n heightForItem(_traceDataIndex: number): number {\n console.assert(false, 'Should not be called');\n return 0;\n }\n\n isItemSelectable(_traceDataIndex: number): boolean {\n return true;\n }\n\n selectedItemChanged(_from: number|null, _to: number|null, fromElement: Element|null, toElement: Element|null): void {\n if (fromElement) {\n fromElement.classList.remove('selected');\n }\n if (toElement) {\n toElement.classList.add('selected');\n }\n }\n\n updateSelectedItemARIA(_fromElement: Element|null, _toElement: Element|null): boolean {\n return false;\n }\n\n private static instance: DropDown|null = null;\n}\n\nexport class ToolbarButton extends UI.Toolbar.ToolbarItem {\n private contentElement: HTMLElement;\n\n constructor(action: UI.ActionRegistration.Action) {\n const element = document.createElement('button');\n element.classList.add('history-dropdown-button');\n element.setAttribute('jslog', `${VisualLogging.dropDown('history')}`);\n super(element);\n this.contentElement = this.element.createChild('span', 'content');\n this.element.addEventListener('click', () => void action.execute(), false);\n this.setEnabled(action.enabled());\n action.addEventListener(UI.ActionRegistration.Events.ENABLED, event => this.setEnabled(event.data));\n this.setTitle(action.title());\n }\n\n setText(text: string): void {\n this.contentElement.textContent = text;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"TimelineHistoryManager.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineHistoryManager.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,MAAM,MAAM,6BAA6B,CAAC;AACtD,OAAO,KAAK,IAAI,MAAM,yBAAyB,CAAC;AAChD,OAAO,KAAK,QAAQ,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,IAAI,MAAM,yBAAyB,CAAC;AAChD,OAAO,KAAK,WAAW,MAAM,2CAA2C,CAAC;AACzE,OAAO,KAAK,KAAK,MAAM,6BAA6B,CAAC;AACrD,OAAO,KAAK,UAAU,MAAM,gDAAgD,CAAC;AAC7E,OAAO,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAChD,OAAO,KAAK,aAAa,MAAM,2CAA2C,CAAC;AAE3E,OAAO,EAEL,gCAAgC,EAChC,4BAA4B,EAC5B,mCAAmC,GACpC,MAAM,4BAA4B,CAAC;AACpC,OAAO,4BAA4B,MAAM,iCAAiC,CAAC;AAG3E;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kCAAkC,GAAG,QAAQ,CAAC;AAE3D,MAAM,SAAS,GAAG;IAChB;;;;OAIG;IACH,gBAAgB,EAAE,+BAA+B;IACjD;;OAEG;IACH,gBAAgB,EAAE,cAAc;IAChC;;OAEG;IACH,YAAY,EAAE,iBAAiB;IAC/B;;;OAGG;IACH,IAAI,EAAE,aAAa;IACnB;;OAEG;IACH,OAAO,EAAE,SAAS;IAClB;;;;OAIG;IACH,EAAE,EAAE,SAAS;IACb;;;;OAIG;IACH,EAAE,EAAE,SAAS;IACb;;;;OAIG;IACH,EAAE,EAAE,cAAc;IAClB;;OAEG;IACH,qBAAqB,EAAE,yBAAyB;CACjD,CAAC;AACF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,2CAA2C,EAAE,SAAS,CAAC,CAAC;AACjG,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AA6BtE,MAAM,OAAO,sBAAsB;IACzB,UAAU,CAA8B;IAC/B,MAAM,CAA+B;IACrC,kBAAkB,CAAsB;IACxC,cAAc,CAAgB;IAC9B,YAAY,CAGzB;IACI,WAAW,CAAS;IACpB,OAAO,CAAU;IACjB,eAAe,GAAuB,IAAI,CAAC;IACnD,iBAAiB,CAAmB;IACpC,YAAY,gBAAkC;QAC5C,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;QACrB,IAAI,CAAC,iBAAiB,GAAG,gBAAgB,CAAC;QAC1C,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,cAAc,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC;QAC7F,IAAI,CAAC,kBAAkB,GAAG,IAAI,GAAG,EAAE,CAAC;QACpC,IAAI,CAAC,cAAc,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAErD,EAAE,CAAC,SAAS,CAAC,gBAAgB,CAAC,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAC3D,IAAI,CAAC,KAAK,EAAE,CAAC;QAEb,iEAAiE;QACjE,iCAAiC;QACjC,IAAI,CAAC,YAAY,GAAG;YAClB;gBAEE,WAAW,EAAE,WAAW,CAAC,EAAE;oBACzB,MAAM,iCAAiC,GACnC,IAAI,CAAC,iBAAiB,EAAE,WAAW,EAAE,CAAC,IAAI,CACtC,OAAO,CAAC,EAAE,CAAC,OAAO,YAAY,mCAAmC,CAClC,CAAC;oBACxC,OAAO,iCAAiC,IAAI,IAAI,mCAAmC,CAAC,WAAW,CAAC,CAAC;gBACnG,CAAC;gBACD,MAAM,EAAE,CAAC;aACV;YACD;gBACE,WAAW,EAAE,WAAW,CAAC,EAAE;oBACzB,MAAM,sBAAsB,GACxB,IAAI,CAAC,iBAAiB,EAAE,WAAW,EAAE,CAAC,IAAI,CACtC,OAAO,CAAC,EAAE,CAAC,OAAO,YAAY,gCAAgC,CAAqC,CAAC;oBAC5G,IAAI,sBAAsB,EAAE,CAAC;wBAC3B,OAAO,sBAAsB,CAAC;oBAChC,CAAC;oBACD,OAAO,IAAI,gCAAgC,CAAC,WAAW,CAAC,CAAC;gBAC3D,CAAC;gBACD,MAAM,EAAE,EAAE;aACX;YACD;gBACE,WAAW,EAAE,WAAW,CAAC,EAAE;oBACzB,MAAM,0BAA0B,GAC5B,IAAI,CAAC,iBAAiB,EAAE,WAAW,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,YAAY,4BAA4B,CACzE,CAAC;oBACjC,OAAO,0BAA0B,IAAI,IAAI,4BAA4B,CAAC,WAAW,CAAC,CAAC;gBACrF,CAAC;gBACD,MAAM,EAAE,CAAC;aACV;SACF,CAAC;QACF,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACnF,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QAEpB,WAAW,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC,gBAAgB,mEAAwC,GAAG,EAAE;YAC9F,IAAI,CAAC,+BAA+B,EAAE,CAAC;QACzC,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;;;;;OAMG;IACH,+BAA+B;QAC7B,IAAI,IAAI,CAAC,eAAe,EAAE,IAAI,KAAK,cAAc,EAAE,CAAC;YAClD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YAC/C,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YACpC,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACrC,CAAC;IACH,CAAC;IAED,YAAY,CAAC,QAAiC;QAC5C,MAAM,SAAS,GAAG,QAAQ,CAAC,mBAAmB,CAAC;QAC/C,IAAI,CAAC,eAAe,GAAG,QAAQ,CAAC,IAAI,CAAC;QACrC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEvC,qEAAqE;QACrE,uEAAuE;QACvE,IAAI,CAAC,yBAAyB,CAAC,QAAQ,CAAC,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC,WAAW,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;QAEpH,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACxC,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACxC,EAAE,CAAC,SAAS,CAAC,QAAQ,CACjB,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,UAAU,CAAC,SAAS,CAAC,gBAAgB,EAAE,EAAC,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;QAC9G,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,IAAI,aAAa,EAAE,CAAC;YAC5C,OAAO;QACT,CAAC;QACD,MAAM,oBAAoB,GACtB,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,gBAAgB,CAAC,GAAG,YAAY,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAClH,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,oBAAoB,CAAC,EAAE,CAAC,CAAC,CAAC;QAEzE,SAAS,YAAY,CAAC,KAAa;YACjC,MAAM,IAAI,GAAG,sBAAsB,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;YAC7D,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;YACnD,CAAC;YACD,OAAO,IAAI,CAAC,QAAQ,CAAC;QACvB,CAAC;IACH,CAAC;IAED,UAAU,CAAC,OAAgB;QACzB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,cAAc,CAAC;IAC7B,CAAC;IAED,KAAK;QACH,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;QACrB,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC5B,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;QAChE,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC;IAClC,CAAC;IAED;;;;;;OAMG;IACH,0BAA0B;QACxB,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,SAAS,iFAAmD,EAAE,CAAC;YAC1F,OAAO,CAAC,CAAC;QACX,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC;IAED,kCAAkC;QAChC,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;YAC1B,OAAO,CAAC,CAAC,CAAC;QACZ,CAAC;QACD,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YACjD,OAAO,kCAAkC,CAAC;QAC5C,CAAC;QACD,OAAO,IAAI,CAAC,eAAe,CAAC,gBAAgB,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,mBAAmB;QACvB,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,IAAI,CAAC,0BAA0B,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAChF,OAAO,IAAI,CAAC;QACd,CAAC;QAED,mGAAmG;QACnG,MAAM,gBAAgB,GAAG,MAAM,QAAQ,CAAC,IAAI,CACxC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,gBAAgB,CAAC,EAAE,IAAI,CAAC,kCAAkC,EAAE,EACvG,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAEjC,IAAI,gBAAgB,KAAK,IAAI,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,2EAA2E;QAC3E,kDAAkD;QAClD,IAAI,gBAAgB,KAAK,kCAAkC,EAAE,CAAC;YAC5D,IAAI,CAAC,eAAe,CAAC,EAAC,IAAI,EAAE,cAAc,EAAC,CAAC,CAAC;YAC7C,OAAO,EAAC,IAAI,EAAE,cAAc,EAAC,CAAC;QAChC,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,gBAAgB,KAAK,gBAAgB,CAAC,CAAC;QACtG,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,8BAA8B,CAAC,CAAC;YACtD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;QAC7C,OAAO,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;IAED,eAAe;QACb,QAAQ,CAAC,eAAe,EAAE,CAAC;IAC7B,CAAC;IAED;;;;OAIG;IACH,QAAQ,CAAC,SAAiB;QACxB,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,eAAe,KAAK,IAAI,EAAE,CAAC;YACnD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,eAAe,IAAI,IAAI,CAAC,eAAe,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YAC1E,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE;YAClD,OAAO,IAAI,CAAC,eAAe,EAAE,IAAI,KAAK,aAAa,IAAI,SAAS,CAAC,IAAI,KAAK,aAAa;gBACnF,SAAS,CAAC,gBAAgB,KAAK,IAAI,CAAC,eAAe,CAAC,gBAAgB,CAAC;QAC3E,CAAC,CAAC,CAAC;QAEH,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,QAAQ,GAAG,QAAQ,CAAC,eAAe,CAAC,KAAK,CAAC,KAAK,GAAG,SAAS,EAAE,CAAC,EAAE,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAClG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC;QAChD,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACnC,CAAC;IAED,eAAe,CAAC,IAAmB;QACjC,IAAI,IAAI,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YAChC,MAAM,IAAI,GAAG,sBAAsB,CAAC,iBAAiB,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YAC7E,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;YACnD,CAAC;YACD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7B,CAAC;QAED,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC;QAC5B,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;QACxC,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACxC,EAAE,CAAC,SAAS,CAAC,QAAQ,CACjB,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,UAAU,CAAC,SAAS,CAAC,gBAAgB,EAAE,EAAC,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,WAAW,EAAC,CAAC,CAAC,CAAC;IAChH,CAAC;IAEO,WAAW;QACjB,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,IAAI,IAAI,CAAC,0BAA0B,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,CAAC;IACtG,CAAC;IAED,MAAM,CAAC,cAAc,CAAC,gBAAwB;QAC5C,MAAM,IAAI,GAAG,sBAAsB,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,CAAC;QACxE,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACnD,CAAC;QACD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QACjC,IAAI,CAAC,IAAI,CAAC,WAAW;YACjB,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,EAAE,EAAC,GAAG,EAAE,sBAAsB,CAAC,SAAS,CAAC,SAAS,CAAC,EAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACpG,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAEO,MAAM,CAAC,SAAS,CAAC,IAAY;QACnC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QACvD,IAAI,OAAO,GAAG,EAAE,EAAE,CAAC;YACjB,OAAO,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QACvC,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;QACzC,IAAI,OAAO,GAAG,EAAE,EAAE,CAAC;YACjB,OAAO,UAAU,CAAC,SAAS,CAAC,EAAE,EAAE,EAAC,GAAG,EAAE,OAAO,EAAC,CAAC,CAAC;QAClD,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC,CAAC;QACvC,OAAO,UAAU,CAAC,SAAS,CAAC,EAAE,EAAE,EAAC,GAAG,EAAE,KAAK,EAAC,CAAC,CAAC;IAChD,CAAC;IAEO,KAAK,CAAC,IAAmB;QAC/B,IAAI,IAAI,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YACjC,OAAO,UAAU,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;QAChD,CAAC;QAED,MAAM,IAAI,GAAG,sBAAsB,CAAC,iBAAiB,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC7E,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACnD,CAAC;QACD,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,yBAAyB,CACrB,gBAAwB,EAAE,WAA6C,EACvE,SAA2C,EAAE,SAAsB;QACrE,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACvF,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAE/C,MAAM,cAAc,GAAG,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAChE,MAAM,uBAAuB,GAAG,UAAU,CAAC,SAAS,CAAC,EAAE,EAAE,EAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,cAAc,EAAC,CAAC,CAAC;QAC7F,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,MAAM,EAAE,cAAc,GAAG,CAAC,CAAC,CAAC;QACxD,MAAM,WAAW,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAEnD,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC9C,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QACtC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC9B,OAAO,CAAC,YAAY,CAAC,OAAO,EAAE,GAAG,aAAa,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC,KAAK,CAAC,EAAC,KAAK,EAAE,IAAI,EAAC,CAAC,EAAE,CAAC,CAAC;QACzG,MAAM,IAAI,GAAG;YACX,OAAO;YACP,KAAK,EAAE,uBAAuB;YAC9B,IAAI,EAAE,WAAW;YACjB,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE;YACpB,SAAS;SACV,CAAC;QACF,wCAAwC,CAAC,GAAG,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;QAErE,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;QAC9E,MAAM,qBAAqB,GAAG,OAAO,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACjE,qBAAqB,CAAC,WAAW,CAAC,IAAI,CAAC,yBAAyB,CAAC,SAAS,CAAC,CAAC,CAAC;QAC7E,qBAAqB,CAAC,WAAW,CAAC,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,CAAC;QACpE,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED,iBAAiB,CAAC,WAA6C,EAAE,KAAa,EAAE,WAAoB;QAClG,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAChD,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QACxC,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAChC,MAAM,QAAQ,GAAG,SAAS,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACvD,QAAQ,CAAC,WAAW,GAAG,KAAK,CAAC;QAC7B,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,uBAAuB,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC1F,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACxE,MAAM,aAAa,GAAG,SAAS,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC5D,aAAa,CAAC,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC7D,aAAa,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QACvC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,yBAAyB,CAAC,SAA2C;QACnE,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAChD,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QAC5C,MAAM,oBAAoB,GAAG,CAAC,GAAG,CAAC,CAAC;QACnC,SAAS,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,WAAW,GAAG,oBAAoB,GAAG,IAAI,CAAC;QACvE,SAAS,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACjD,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,MAAM,SAAS,GAAG,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1C,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,KAAK,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;YAC3E,IAAI,GAAG,EAAE,CAAC;gBACR,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC,CAAC,CAAC;QACH,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,cAAc,CAAC,WAA6C;QAC1D,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAChD,MAAM,GAAG,GAAG,MAAM,CAAC,gBAAgB,CAAC;QACpC,SAAS,CAAC,KAAK,CAAC,KAAK,GAAG,YAAY,GAAG,IAAI,CAAC;QAC5C,SAAS,CAAC,KAAK,CAAC,MAAM,GAAG,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACjD,MAAM,MAAM,GAAI,SAAS,CAAC,WAAW,CAAC,QAAQ,CAAuB,CAAC;QACtE,MAAM,CAAC,KAAK,GAAG,GAAG,GAAG,YAAY,CAAC;QAClC,MAAM,CAAC,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC;QAEvC,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,OAAO,GAAG,CAAC,CAAC;QAEhB,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YACzC,MAAM,yBAAyB,GAAG,QAAQ,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;YACpE,yBAAyB,CAAC,MAAM,EAAE,CAAC;YACnC,IAAI,GAAG,EAAE,CAAC;gBACR,GAAG,CAAC,SAAS,CACT,yBAAyB,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,GAAG,YAAY,EAAE,QAAQ,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;YACzG,CAAC;YACD,OAAO,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,CAAC;QACnC,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAEO,MAAM,CAAC,iBAAiB,CAAC,KAAa;QAC5C,OAAO,wCAAwC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;IACrE,CAAC;CACF;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAC;AAC/B,MAAM,CAAC,MAAM,YAAY,GAAG,GAAG,CAAC;AAChC,8EAA8E;AAC9E,+EAA+E;AAC/E,MAAM,wCAAwC,GAAG,IAAI,GAAG,EAAuB,CAAC;AAUhF,MAAM,OAAO,QAAQ;IACF,SAAS,CAAyB;IAClC,WAAW,CAAqC;IAChD,aAAa,CAAkC;IACxD,aAAa,CAAqC;IAE1D,YAAY,2BAAqC;QAC/C,IAAI,CAAC,SAAS,GAAG,IAAI,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC;QAC9C,IAAI,CAAC,SAAS,CAAC,eAAe,kEAA2C,CAAC;QAC1E,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAC/D,IAAI,CAAC,SAAS,CAAC,wBAAwB,qFAA0D,CAAC;QAClG,IAAI,CAAC,SAAS,CAAC,iBAAiB,gEAA2C,CAAC;QAC5E,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAExE,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO,CAAC,8BAA8B,CAAC,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE;YAC1F,OAAO,EAAE,CAAC,4BAA4B,CAAC;YACvC,cAAc,EAAE,SAAS;SAC1B,CAAC,CAAC;QACH,MAAM,cAAc,GAAG,UAAU,CAAC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QAElE,MAAM,SAAS,GAAG,IAAI,EAAE,CAAC,SAAS,CAAC,SAAS,EAAU,CAAC;QACvD,IAAI,CAAC,WAAW,GAAG,IAAI,EAAE,CAAC,WAAW,CAAC,WAAW,CAAS,SAAS,EAAE,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAChH,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;QAC3F,SAAS,CAAC,UAAU,CAAC,2BAA2B,CAAC,CAAC;QAElD,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAClD,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,UAAU,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC,CAAC;QAC7F,cAAc,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QACrD,cAAc,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;QAC7E,cAAc,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;QAEzE,IAAI,CAAC,aAAa,GAAG,IAAI,EAAE,CAAC,OAAO,CAAC,oBAAoB,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QACnF,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;IAC5B,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,2BAAqC,EAAE,sBAA8B,EAAE,MAAe;QAEhG,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACtB,OAAO,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/B,CAAC;QACD,MAAM,wBAAwB,GAAG,CAAC,GAAG,2BAA2B,CAAC,CAAC;QAClE,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,SAAS,iFAAmD,EAAE,CAAC;YAC1F,wBAAwB,CAAC,OAAO,CAAC,kCAAkC,CAAC,CAAC;QACvE,CAAC;QACD,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,wBAAwB,CAAC,CAAC;QACxD,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,CAAC,eAAe;QACpB,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;YACvB,OAAO;QACT,CAAC;QACD,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAEO,IAAI,CAAC,MAAe,EAAE,sBAA8B;QAC1D,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,SAAS,CAAC,mBAAmB,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;QACzD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;QACjE,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACjC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,sBAAsB,CAAC,CAAC;QAEpD,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;YAC3B,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC;QAC/B,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,WAAW,CAAC,KAAY;QAC9B,MAAM,IAAI,GAAI,KAAK,CAAC,MAAsB,CAAC,4BAA4B,CAAC,cAAc,CAAC,CAAC;QACxF,MAAM,QAAQ,GAAG,IAAI,IAAI,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAC5D,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IACxC,CAAC;IAEO,OAAO,CAAC,KAAY;QAC1B,mEAAmE;QACnE,mBAAmB;QACnB,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,4BAA4B,CAAC,cAAc,CAAC,EAAE,CAAC;YACjE,OAAO;QACT,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC,CAAC;IAC9C,CAAC;IAEO,SAAS,CAAC,KAAY;QAC5B,QAAS,KAAuB,CAAC,GAAG,EAAE,CAAC;YACrC,KAAK,KAAK,CAAC;YACX,KAAK,QAAQ;gBACX,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACjB,MAAM;YACR,KAAK,OAAO;gBACV,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC,CAAC;gBAC5C,MAAM;YACR;gBACE,OAAO;QACX,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;IAEO,KAAK,CAAC,UAAuB;QACnC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;QACjC,CAAC;QACD,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;QACtB,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAAC;IAC3B,CAAC;IAED,oBAAoB,CAAC,gBAAwB;QAC3C,IAAI,gBAAgB,KAAK,kCAAkC,EAAE,CAAC;YAC5D,OAAO,IAAI,CAAC,0BAA0B,EAAE,CAAC;QAC3C,CAAC;QACD,MAAM,OAAO,GAAG,sBAAsB,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC;QACxE,EAAE,CAAC,SAAS,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QACrC,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACrC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,0BAA0B;QACxB,MAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC1C,EAAE,CAAC,SAAS,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;QACjC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACjC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;QAClC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QAEvC,MAAM,IAAI,GAAG,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAClD,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAEtB,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAC5C,IAAI,CAAC,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC;QACxD,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACtB,OAAO,GAAG,CAAC;IACb,CAAC;IAED,aAAa,CAAC,iBAAyB;QACrC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,sBAAsB,CAAC,CAAC;QAC9C,OAAO,CAAC,CAAC;IACX,CAAC;IAED,gBAAgB,CAAC,iBAAyB;QACxC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,mBAAmB,CAAC,KAAkB,EAAE,GAAgB,EAAE,WAAyB,EAAE,SAAuB;QAC1G,IAAI,WAAW,EAAE,CAAC;YAChB,WAAW,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QAC3C,CAAC;QACD,IAAI,SAAS,EAAE,CAAC;YACd,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;IAED,sBAAsB,CAAC,YAA0B,EAAE,UAAwB;QACzE,OAAO,KAAK,CAAC;IACf,CAAC;IAEO,MAAM,CAAC,QAAQ,GAAkB,IAAI,CAAC;;AAGhD,MAAM,OAAO,aAAc,SAAQ,EAAE,CAAC,OAAO,CAAC,WAAW;IAC/C,cAAc,CAAc;IAEpC,YAAY,MAAoC;QAC9C,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACjD,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;QACjD,OAAO,CAAC,YAAY,CAAC,OAAO,EAAE,GAAG,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACtE,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QAClE,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,MAAM,CAAC,OAAO,EAAE,EAAE,KAAK,CAAC,CAAC;QAC3E,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAClC,MAAM,CAAC,gBAAgB,uDAAuC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QACpG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;IAChC,CAAC;IAED,OAAO,CAAC,IAAY;QAClB,IAAI,CAAC,cAAc,CAAC,WAAW,GAAG,IAAI,CAAC;IACzC,CAAC;CACF","sourcesContent":["// Copyright 2017 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as Root from '../../core/root/root.js';\nimport * as CrUXManager from '../../models/crux-manager/crux-manager.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as IconButton from '../../ui/components/icon_button/icon_button.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport {\n type TimelineEventOverview,\n TimelineEventOverviewCPUActivity,\n TimelineEventOverviewNetwork,\n TimelineEventOverviewResponsiveness,\n} from './TimelineEventOverview.js';\nimport timelineHistoryManagerStyles from './timelineHistoryManager.css.js';\nimport {type TimelineMiniMap} from './TimelineMiniMap.js';\n\n/**\n * The dropdown works by returning an index which is the trace index; but we\n * also need a way to signify that the user picked the \"Landing Page\" option. We\n * represent that as Infinity so we never accidentally collide with an actual\n * trace (in reality a large number like 99 would probably suffice...)\n */\nexport const LANDING_PAGE_INDEX_DROPDOWN_CHOICE = Infinity;\n\nconst UIStrings = {\n /**\n *@description Screen reader label for the Timeline History dropdown button\n *@example {example.com #3} PH1\n *@example {Show recent timeline sessions} PH2\n */\n currentSessionSS: 'Current session: {PH1}. {PH2}',\n /**\n *@description the title shown when the user is viewing the landing page which is showing live performance metrics that are updated automatically.\n */\n landingPageTitle: 'Live metrics',\n /**\n *@description Text that shows there is no recording\n */\n noRecordings: '(no recordings)',\n /**\n *@description Text in Timeline History Manager of the Performance panel\n *@example {2s} PH1\n */\n sAgo: '({PH1} ago)',\n /**\n *@description Text in Timeline History Manager of the Performance panel\n */\n moments: 'moments',\n /**\n * @description Text in Timeline History Manager of the Performance panel.\n * Placeholder is a number and the 'm' is the short form for 'minutes'.\n * @example {2} PH1\n */\n sM: '{PH1} m',\n /**\n * @description Text in Timeline History Manager of the Performance panel.\n * Placeholder is a number and the 'h' is the short form for 'hours'.\n * @example {2} PH1\n */\n sH: '{PH1} h',\n /**\n *@description Text in Timeline History Manager of the Performance panel\n *@example {example.com} PH1\n *@example {2} PH2\n */\n sD: '{PH1} #{PH2}',\n /**\n *@description Accessible label for the timeline session selection menu\n */\n selectTimelineSession: 'Select timeline session',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelineHistoryManager.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\n/**\n * The dropdown includes an option to navigate to the landing page; hence the\n * two types for storing recordings. The TimelineHistoryManager automatically\n * includes a link to go back to the landing page.\n */\ninterface TraceRecordingHistoryItem {\n type: 'TRACE_INDEX';\n // By storing only the index of this trace, the TimelinePanel can then look\n // up this trace's data (and metadata) via this index.\n parsedTraceIndex: number;\n}\ninterface LandingPageHistoryItem {\n type: 'LANDING_PAGE';\n}\nexport type RecordingData = TraceRecordingHistoryItem|LandingPageHistoryItem;\n\nexport interface NewHistoryRecordingData {\n // The data we will save to restore later.\n data: TraceRecordingHistoryItem;\n // We do not store this, but need it to build the thumbnail preview.\n filmStripForPreview: Trace.Extras.FilmStrip.Data|null;\n // Also not stored, but used to create the preview overview for a new trace.\n parsedTrace: Trace.Handlers.Types.ParsedTrace;\n // Used for the preview text\n startTime: number|null;\n}\n\nexport class TimelineHistoryManager {\n private recordings: TraceRecordingHistoryItem[];\n private readonly action: UI.ActionRegistration.Action;\n private readonly nextNumberByDomain: Map;\n private readonly buttonInternal: ToolbarButton;\n private readonly allOverviews: {\n constructor: (parsedTrace: Trace.Handlers.Types.ParsedTrace) => TimelineEventOverview,\n height: number,\n }[];\n private totalHeight: number;\n private enabled: boolean;\n private lastActiveTrace: RecordingData|null = null;\n #minimapComponent?: TimelineMiniMap;\n constructor(minimapComponent?: TimelineMiniMap) {\n this.recordings = [];\n this.#minimapComponent = minimapComponent;\n this.action = UI.ActionRegistry.ActionRegistry.instance().getAction('timeline.show-history');\n this.nextNumberByDomain = new Map();\n this.buttonInternal = new ToolbarButton(this.action);\n\n UI.ARIAUtils.markAsMenuButton(this.buttonInternal.element);\n this.clear();\n\n // Attempt to reuse the overviews coming from the panel's minimap\n // before creating new instances.\n this.allOverviews = [\n {\n\n constructor: parsedTrace => {\n const responsivenessOverviewFromMinimap =\n this.#minimapComponent?.getControls().find(\n control => control instanceof TimelineEventOverviewResponsiveness) as\n TimelineEventOverviewResponsiveness;\n return responsivenessOverviewFromMinimap || new TimelineEventOverviewResponsiveness(parsedTrace);\n },\n height: 3,\n },\n {\n constructor: parsedTrace => {\n const cpuOverviewFromMinimap =\n this.#minimapComponent?.getControls().find(\n control => control instanceof TimelineEventOverviewCPUActivity) as TimelineEventOverviewCPUActivity;\n if (cpuOverviewFromMinimap) {\n return cpuOverviewFromMinimap;\n }\n return new TimelineEventOverviewCPUActivity(parsedTrace);\n },\n height: 20,\n },\n {\n constructor: parsedTrace => {\n const networkOverviewFromMinimap =\n this.#minimapComponent?.getControls().find(control => control instanceof TimelineEventOverviewNetwork) as\n TimelineEventOverviewNetwork;\n return networkOverviewFromMinimap || new TimelineEventOverviewNetwork(parsedTrace);\n },\n height: 8,\n },\n ];\n this.totalHeight = this.allOverviews.reduce((acc, entry) => acc + entry.height, 0);\n this.enabled = true;\n\n CrUXManager.CrUXManager.instance().addEventListener(CrUXManager.Events.FIELD_DATA_CHANGED, () => {\n this.#updateLandingPageTitleIfActive();\n });\n }\n\n /**\n * If the user changes the CrUX consent status, the title shown in the\n * dropdown could be outdated, as we show \"Local\" or \"Local and field\"\n * depending on if the user has consented.\n * This method will be called whenever the CrUXManager detects a change, and\n * we use it as a chance to re-evaluate if the title needs changing or not.\n */\n #updateLandingPageTitleIfActive(): void {\n if (this.lastActiveTrace?.type === 'LANDING_PAGE') {\n const title = this.title(this.lastActiveTrace);\n this.buttonInternal.setTitle(title);\n this.buttonInternal.setText(title);\n }\n }\n\n addRecording(newInput: NewHistoryRecordingData): void {\n const filmStrip = newInput.filmStripForPreview;\n this.lastActiveTrace = newInput.data;\n this.recordings.unshift(newInput.data);\n\n // Order is important: this needs to happen first because lots of the\n // subsequent code depends on us storing the preview data into the map.\n this.#buildAndStorePreviewData(newInput.data.parsedTraceIndex, newInput.parsedTrace, filmStrip, newInput.startTime);\n\n const modelTitle = this.title(newInput.data);\n this.buttonInternal.setText(modelTitle);\n const buttonTitle = this.action.title();\n UI.ARIAUtils.setLabel(\n this.buttonInternal.element, i18nString(UIStrings.currentSessionSS, {PH1: modelTitle, PH2: buttonTitle}));\n this.updateState();\n if (this.recordings.length <= maxRecordings) {\n return;\n }\n const modelUsedMoreTimeAgo =\n this.recordings.reduce((a, b) => lastUsedTime(a.parsedTraceIndex) < lastUsedTime(b.parsedTraceIndex) ? a : b);\n this.recordings.splice(this.recordings.indexOf(modelUsedMoreTimeAgo), 1);\n\n function lastUsedTime(index: number): number {\n const data = TimelineHistoryManager.dataForTraceIndex(index);\n if (!data) {\n throw new Error('Unable to find data for model');\n }\n return data.lastUsed;\n }\n }\n\n setEnabled(enabled: boolean): void {\n this.enabled = enabled;\n this.updateState();\n }\n\n button(): ToolbarButton {\n return this.buttonInternal;\n }\n\n clear(): void {\n this.recordings = [];\n this.lastActiveTrace = null;\n this.updateState();\n this.buttonInternal.setText(i18nString(UIStrings.noRecordings));\n this.nextNumberByDomain.clear();\n }\n\n /**\n * If the observations landing page experiment is enabled, we show the\n * dropdown when there is 1 or more traces active, as even with 1 trace we\n * need to give the user a way to get back to the index page. However, if that\n * experiment is disabled, there is no need to show the dropdown until there\n * are 2+ traces.\n */\n #minimumRequiredRecordings(): number {\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_OBSERVATIONS)) {\n return 1;\n }\n return 2;\n }\n\n #getActiveTraceIndexForListControl(): number {\n if (!this.lastActiveTrace) {\n return -1;\n }\n if (this.lastActiveTrace.type === 'LANDING_PAGE') {\n return LANDING_PAGE_INDEX_DROPDOWN_CHOICE;\n }\n return this.lastActiveTrace.parsedTraceIndex;\n }\n\n async showHistoryDropDown(): Promise {\n if (this.recordings.length < this.#minimumRequiredRecordings() || !this.enabled) {\n return null;\n }\n\n // DropDown.show() function finishes when the dropdown menu is closed via selection or losing focus\n const activeTraceIndex = await DropDown.show(\n this.recordings.map(recording => recording.parsedTraceIndex), this.#getActiveTraceIndexForListControl(),\n this.buttonInternal.element);\n\n if (activeTraceIndex === null) {\n return null;\n }\n\n // The ListControl class that backs the dropdown uses indexes; we represent\n // the landing page choice via this special index.\n if (activeTraceIndex === LANDING_PAGE_INDEX_DROPDOWN_CHOICE) {\n this.#setActiveTrace({type: 'LANDING_PAGE'});\n return {type: 'LANDING_PAGE'};\n }\n\n const index = this.recordings.findIndex(recording => recording.parsedTraceIndex === activeTraceIndex);\n if (index < 0) {\n console.assert(false, 'selected recording not found');\n return null;\n }\n\n this.#setActiveTrace(this.recordings[index]);\n return this.recordings[index];\n }\n\n cancelIfShowing(): void {\n DropDown.cancelIfShowing();\n }\n\n /**\n * Navigate by 1 in either direction to the next trace.\n * Navigating in this way does not include the landing page; it will loop\n * over only the traces.\n */\n navigate(direction: number): TraceRecordingHistoryItem|null {\n if (!this.enabled || this.lastActiveTrace === null) {\n return null;\n }\n if (!this.lastActiveTrace || this.lastActiveTrace.type === 'LANDING_PAGE') {\n return null;\n }\n\n const index = this.recordings.findIndex(recording => {\n return this.lastActiveTrace?.type === 'TRACE_INDEX' && recording.type === 'TRACE_INDEX' &&\n recording.parsedTraceIndex === this.lastActiveTrace.parsedTraceIndex;\n });\n\n if (index < 0) {\n return null;\n }\n\n const newIndex = Platform.NumberUtilities.clamp(index + direction, 0, this.recordings.length - 1);\n this.#setActiveTrace(this.recordings[newIndex]);\n return this.recordings[newIndex];\n }\n\n #setActiveTrace(item: RecordingData): void {\n if (item.type === 'TRACE_INDEX') {\n const data = TimelineHistoryManager.dataForTraceIndex(item.parsedTraceIndex);\n if (!data) {\n throw new Error('Unable to find data for model');\n }\n data.lastUsed = Date.now();\n }\n\n this.lastActiveTrace = item;\n const modelTitle = this.title(item);\n const buttonTitle = this.action.title();\n this.buttonInternal.setText(modelTitle);\n UI.ARIAUtils.setLabel(\n this.buttonInternal.element, i18nString(UIStrings.currentSessionSS, {PH1: modelTitle, PH2: buttonTitle}));\n }\n\n private updateState(): void {\n this.action.setEnabled(this.recordings.length >= this.#minimumRequiredRecordings() && this.enabled);\n }\n\n static previewElement(parsedTraceIndex: number): Element {\n const data = TimelineHistoryManager.dataForTraceIndex(parsedTraceIndex);\n if (!data) {\n throw new Error('Unable to find data for model');\n }\n const startedAt = data.startTime;\n data.time.textContent =\n startedAt ? i18nString(UIStrings.sAgo, {PH1: TimelineHistoryManager.coarseAge(startedAt)}) : '';\n return data.preview;\n }\n\n private static coarseAge(time: number): string {\n const seconds = Math.round((Date.now() - time) / 1000);\n if (seconds < 50) {\n return i18nString(UIStrings.moments);\n }\n const minutes = Math.round(seconds / 60);\n if (minutes < 50) {\n return i18nString(UIStrings.sM, {PH1: minutes});\n }\n const hours = Math.round(minutes / 60);\n return i18nString(UIStrings.sH, {PH1: hours});\n }\n\n private title(item: RecordingData): string {\n if (item.type === 'LANDING_PAGE') {\n return i18nString(UIStrings.landingPageTitle);\n }\n\n const data = TimelineHistoryManager.dataForTraceIndex(item.parsedTraceIndex);\n if (!data) {\n throw new Error('Unable to find data for model');\n }\n return data.title;\n }\n\n #buildAndStorePreviewData(\n parsedTraceIndex: number, parsedTrace: Trace.Handlers.Types.ParsedTrace,\n filmStrip: Trace.Extras.FilmStrip.Data|null, startTime: number|null): HTMLDivElement {\n const parsedURL = Common.ParsedURL.ParsedURL.fromString(parsedTrace.Meta.mainFrameURL);\n const domain = parsedURL ? parsedURL.host : '';\n\n const sequenceNumber = this.nextNumberByDomain.get(domain) || 1;\n const titleWithSequenceNumber = i18nString(UIStrings.sD, {PH1: domain, PH2: sequenceNumber});\n this.nextNumberByDomain.set(domain, sequenceNumber + 1);\n const timeElement = document.createElement('span');\n\n const preview = document.createElement('div');\n preview.classList.add('preview-item');\n preview.classList.add('vbox');\n preview.setAttribute('jslog', `${VisualLogging.dropDown('timeline.history-item').track({click: true})}`);\n const data = {\n preview,\n title: titleWithSequenceNumber,\n time: timeElement,\n lastUsed: Date.now(),\n startTime,\n };\n parsedTraceIndexToPerformancePreviewData.set(parsedTraceIndex, data);\n\n preview.appendChild(this.#buildTextDetails(parsedTrace, domain, timeElement));\n const screenshotAndOverview = preview.createChild('div', 'hbox');\n screenshotAndOverview.appendChild(this.#buildScreenshotThumbnail(filmStrip));\n screenshotAndOverview.appendChild(this.#buildOverview(parsedTrace));\n return data.preview;\n }\n\n #buildTextDetails(parsedTrace: Trace.Handlers.Types.ParsedTrace, title: string, timeElement: Element): Element {\n const container = document.createElement('div');\n container.classList.add('text-details');\n container.classList.add('hbox');\n const nameSpan = container.createChild('span', 'name');\n nameSpan.textContent = title;\n UI.ARIAUtils.setLabel(nameSpan, title);\n const bounds = Trace.Helpers.Timing.traceWindowMilliSeconds(parsedTrace.Meta.traceBounds);\n const duration = i18n.TimeUtilities.millisToString(bounds.range, false);\n const timeContainer = container.createChild('span', 'time');\n timeContainer.appendChild(document.createTextNode(duration));\n timeContainer.appendChild(timeElement);\n return container;\n }\n\n #buildScreenshotThumbnail(filmStrip: Trace.Extras.FilmStrip.Data|null): Element {\n const container = document.createElement('div');\n container.classList.add('screenshot-thumb');\n const thumbnailAspectRatio = 3 / 2;\n container.style.width = this.totalHeight * thumbnailAspectRatio + 'px';\n container.style.height = this.totalHeight + 'px';\n if (!filmStrip) {\n return container;\n }\n const lastFrame = filmStrip.frames.at(-1);\n if (!lastFrame) {\n return container;\n }\n void UI.UIUtils.loadImage(lastFrame.screenshotEvent.args.dataUri).then(img => {\n if (img) {\n container.appendChild(img);\n }\n });\n return container;\n }\n\n #buildOverview(parsedTrace: Trace.Handlers.Types.ParsedTrace): Element {\n const container = document.createElement('div');\n const dPR = window.devicePixelRatio;\n container.style.width = previewWidth + 'px';\n container.style.height = this.totalHeight + 'px';\n const canvas = (container.createChild('canvas') as HTMLCanvasElement);\n canvas.width = dPR * previewWidth;\n canvas.height = dPR * this.totalHeight;\n\n const ctx = canvas.getContext('2d');\n let yOffset = 0;\n\n for (const overview of this.allOverviews) {\n const timelineOverviewComponent = overview.constructor(parsedTrace);\n timelineOverviewComponent.update();\n if (ctx) {\n ctx.drawImage(\n timelineOverviewComponent.context().canvas, 0, yOffset, dPR * previewWidth, overview.height * dPR);\n }\n yOffset += overview.height * dPR;\n }\n return container;\n }\n\n private static dataForTraceIndex(index: number): PreviewData|null {\n return parsedTraceIndexToPerformancePreviewData.get(index) || null;\n }\n}\n\nexport const maxRecordings = 5;\nexport const previewWidth = 450;\n// The reason we store a global map is because the Dropdown component needs to\n// be able to read the preview data in order to show a preview in the dropdown.\nconst parsedTraceIndexToPerformancePreviewData = new Map();\n\nexport interface PreviewData {\n preview: Element;\n time: Element;\n lastUsed: number;\n startTime: number|null;\n title: string;\n}\n\nexport class DropDown implements UI.ListControl.ListDelegate {\n private readonly glassPane: UI.GlassPane.GlassPane;\n private readonly listControl: UI.ListControl.ListControl;\n private readonly focusRestorer: UI.UIUtils.ElementFocusRestorer;\n private selectionDone: ((arg0: number|null) => void)|null;\n\n constructor(availableparsedTraceIndexes: number[]) {\n this.glassPane = new UI.GlassPane.GlassPane();\n this.glassPane.setSizeBehavior(UI.GlassPane.SizeBehavior.MEASURE_CONTENT);\n this.glassPane.setOutsideClickCallback(() => this.close(null));\n this.glassPane.setPointerEventsBehavior(UI.GlassPane.PointerEventsBehavior.BLOCKED_BY_GLASS_PANE);\n this.glassPane.setAnchorBehavior(UI.GlassPane.AnchorBehavior.PREFER_BOTTOM);\n this.glassPane.element.addEventListener('blur', () => this.close(null));\n\n const shadowRoot = UI.UIUtils.createShadowRootWithCoreStyles(this.glassPane.contentElement, {\n cssFile: [timelineHistoryManagerStyles],\n delegatesFocus: undefined,\n });\n const contentElement = shadowRoot.createChild('div', 'drop-down');\n\n const listModel = new UI.ListModel.ListModel();\n this.listControl = new UI.ListControl.ListControl(listModel, this, UI.ListControl.ListMode.NonViewport);\n this.listControl.element.addEventListener('mousemove', this.onMouseMove.bind(this), false);\n listModel.replaceAll(availableparsedTraceIndexes);\n\n UI.ARIAUtils.markAsMenu(this.listControl.element);\n UI.ARIAUtils.setLabel(this.listControl.element, i18nString(UIStrings.selectTimelineSession));\n contentElement.appendChild(this.listControl.element);\n contentElement.addEventListener('keydown', this.onKeyDown.bind(this), false);\n contentElement.addEventListener('click', this.onClick.bind(this), false);\n\n this.focusRestorer = new UI.UIUtils.ElementFocusRestorer(this.listControl.element);\n this.selectionDone = null;\n }\n\n static show(availableparsedTraceIndexes: number[], activeparsedTraceIndex: number, anchor: Element):\n Promise {\n if (DropDown.instance) {\n return Promise.resolve(null);\n }\n const availableDropdownChoices = [...availableparsedTraceIndexes];\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_OBSERVATIONS)) {\n availableDropdownChoices.unshift(LANDING_PAGE_INDEX_DROPDOWN_CHOICE);\n }\n const instance = new DropDown(availableDropdownChoices);\n return instance.show(anchor, activeparsedTraceIndex);\n }\n\n static cancelIfShowing(): void {\n if (!DropDown.instance) {\n return;\n }\n DropDown.instance.close(null);\n }\n\n private show(anchor: Element, activeparsedTraceIndex: number): Promise {\n DropDown.instance = this;\n this.glassPane.setContentAnchorBox(anchor.boxInWindow());\n this.glassPane.show(this.glassPane.contentElement.ownerDocument);\n this.listControl.element.focus();\n this.listControl.selectItem(activeparsedTraceIndex);\n\n return new Promise(fulfill => {\n this.selectionDone = fulfill;\n });\n }\n\n private onMouseMove(event: Event): void {\n const node = (event.target as HTMLElement).enclosingNodeOrSelfWithClass('preview-item');\n const listItem = node && this.listControl.itemForNode(node);\n if (listItem === null) {\n return;\n }\n this.listControl.selectItem(listItem);\n }\n\n private onClick(event: Event): void {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // @ts-expect-error\n if (!(event.target).enclosingNodeOrSelfWithClass('preview-item')) {\n return;\n }\n this.close(this.listControl.selectedItem());\n }\n\n private onKeyDown(event: Event): void {\n switch ((event as KeyboardEvent).key) {\n case 'Tab':\n case 'Escape':\n this.close(null);\n break;\n case 'Enter':\n this.close(this.listControl.selectedItem());\n break;\n default:\n return;\n }\n event.consume(true);\n }\n\n private close(traceIndex: number|null): void {\n if (this.selectionDone) {\n this.selectionDone(traceIndex);\n }\n this.focusRestorer.restore();\n this.glassPane.hide();\n DropDown.instance = null;\n }\n\n createElementForItem(parsedTraceIndex: number): Element {\n if (parsedTraceIndex === LANDING_PAGE_INDEX_DROPDOWN_CHOICE) {\n return this.#createLandingPageListItem();\n }\n const element = TimelineHistoryManager.previewElement(parsedTraceIndex);\n UI.ARIAUtils.markAsMenuItem(element);\n element.classList.remove('selected');\n return element;\n }\n\n #createLandingPageListItem(): HTMLElement {\n const div = document.createElement('div');\n UI.ARIAUtils.markAsMenuItem(div);\n div.classList.remove('selected');\n div.classList.add('preview-item');\n div.classList.add('landing-page-item');\n\n const icon = IconButton.Icon.create('arrow-back');\n div.appendChild(icon);\n\n const text = document.createElement('span');\n text.innerText = i18nString(UIStrings.landingPageTitle);\n div.appendChild(text);\n return div;\n }\n\n heightForItem(_parsedTraceIndex: number): number {\n console.assert(false, 'Should not be called');\n return 0;\n }\n\n isItemSelectable(_parsedTraceIndex: number): boolean {\n return true;\n }\n\n selectedItemChanged(_from: number|null, _to: number|null, fromElement: Element|null, toElement: Element|null): void {\n if (fromElement) {\n fromElement.classList.remove('selected');\n }\n if (toElement) {\n toElement.classList.add('selected');\n }\n }\n\n updateSelectedItemARIA(_fromElement: Element|null, _toElement: Element|null): boolean {\n return false;\n }\n\n private static instance: DropDown|null = null;\n}\n\nexport class ToolbarButton extends UI.Toolbar.ToolbarItem {\n private contentElement: HTMLElement;\n\n constructor(action: UI.ActionRegistration.Action) {\n const element = document.createElement('button');\n element.classList.add('history-dropdown-button');\n element.setAttribute('jslog', `${VisualLogging.dropDown('history')}`);\n super(element);\n this.contentElement = this.element.createChild('span', 'content');\n this.element.addEventListener('click', () => void action.execute(), false);\n this.setEnabled(action.enabled());\n action.addEventListener(UI.ActionRegistration.Events.ENABLED, event => this.setEnabled(event.data));\n this.setTitle(action.title());\n }\n\n setText(text: string): void {\n this.contentElement.textContent = text;\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineHistoryManager.test.js b/public/panels/timeline/TimelineHistoryManager.test.js index a77f92c79..8b5dfa489 100644 --- a/public/panels/timeline/TimelineHistoryManager.test.js +++ b/public/panels/timeline/TimelineHistoryManager.test.js @@ -18,14 +18,14 @@ describeWithEnvironment('TimelineHistoryManager', function () { }); it('shows the dropdown including a landing page link if the observations experiment is enabled', async function () { Root.Runtime.experiments.enableForTest("timeline-observations" /* Root.Runtime.ExperimentName.TIMELINE_OBSERVATIONS */); - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); historyManager.addRecording({ data: { - traceParseDataIndex: 1, + parsedTraceIndex: 1, type: 'TRACE_INDEX', }, filmStripForPreview: null, - traceParsedData: traceData, + parsedTrace, startTime: null, }); const showPromise = historyManager.showHistoryDropDown(); @@ -42,14 +42,14 @@ describeWithEnvironment('TimelineHistoryManager', function () { await showPromise; }); it('does not show if observations experiment is disabled + the user has not imported 2 traces', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); historyManager.addRecording({ data: { - traceParseDataIndex: 1, + parsedTraceIndex: 1, type: 'TRACE_INDEX', }, filmStripForPreview: null, - traceParsedData: traceData, + parsedTrace, startTime: null, }); const promise = historyManager.showHistoryDropDown(); @@ -60,24 +60,24 @@ describeWithEnvironment('TimelineHistoryManager', function () { assert.isNull(result); }); it('does not show the landing page link if the observations experiment is disabled', async function () { - const { traceData: traceData1 } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); + const { parsedTrace: parsedTrace1 } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); historyManager.addRecording({ data: { - traceParseDataIndex: 1, + parsedTraceIndex: 1, type: 'TRACE_INDEX', }, filmStripForPreview: null, - traceParsedData: traceData1, + parsedTrace: parsedTrace1, startTime: null, }); - const { traceData: traceData2 } = await TraceLoader.traceEngine(this, 'timings-track.json.gz'); + const { parsedTrace: parsedTrace2 } = await TraceLoader.traceEngine(this, 'timings-track.json.gz'); historyManager.addRecording({ data: { - traceParseDataIndex: 2, + parsedTraceIndex: 2, type: 'TRACE_INDEX', }, filmStripForPreview: null, - traceParsedData: traceData2, + parsedTrace: parsedTrace2, startTime: null, }); const showPromise = historyManager.showHistoryDropDown(); @@ -98,32 +98,32 @@ describeWithEnvironment('TimelineHistoryManager', function () { }); it('can select from multiple parsed data objects', async function () { // Add two parsed data objects to the history manager. - const { traceData: trace1Data } = await TraceLoader.traceEngine(this, 'slow-interaction-button-click.json.gz'); + const { parsedTrace: trace1Data } = await TraceLoader.traceEngine(this, 'slow-interaction-button-click.json.gz'); historyManager.addRecording({ data: { - traceParseDataIndex: 1, + parsedTraceIndex: 1, type: 'TRACE_INDEX', }, filmStripForPreview: null, - traceParsedData: trace1Data, + parsedTrace: trace1Data, startTime: null, }); - const { traceData: trace2Data } = await TraceLoader.traceEngine(this, 'slow-interaction-keydown.json.gz'); + const { parsedTrace: trace2Data } = await TraceLoader.traceEngine(this, 'slow-interaction-keydown.json.gz'); historyManager.addRecording({ data: { - traceParseDataIndex: 2, + parsedTraceIndex: 2, type: 'TRACE_INDEX', }, filmStripForPreview: null, - traceParsedData: trace2Data, + parsedTrace: trace2Data, startTime: null, }); // Make sure the correct model is returned when // using the history manager to navigate between trace files.. const previousRecording = historyManager.navigate(1); - assert.strictEqual(previousRecording?.traceParseDataIndex, 1); + assert.strictEqual(previousRecording?.parsedTraceIndex, 1); const nextRecording = historyManager.navigate(-1); - assert.strictEqual(nextRecording?.traceParseDataIndex, 2); + assert.strictEqual(nextRecording?.parsedTraceIndex, 2); }); }); //# sourceMappingURL=TimelineHistoryManager.test.js.map \ No newline at end of file diff --git a/public/panels/timeline/TimelineHistoryManager.test.js.map b/public/panels/timeline/TimelineHistoryManager.test.js.map index b68ca2011..402b8053b 100644 --- a/public/panels/timeline/TimelineHistoryManager.test.js.map +++ b/public/panels/timeline/TimelineHistoryManager.test.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineHistoryManager.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineHistoryManager.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Root from '../../core/root/root.js';\nimport {\n describeWithEnvironment,\n registerNoopActions,\n} from '../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport * as Timeline from './timeline.js';\n\ndescribeWithEnvironment('TimelineHistoryManager', function() {\n let historyManager: Timeline.TimelineHistoryManager.TimelineHistoryManager;\n beforeEach(() => {\n registerNoopActions(['timeline.show-history']);\n historyManager = new Timeline.TimelineHistoryManager.TimelineHistoryManager();\n });\n\n afterEach(() => {\n UI.ActionRegistry.ActionRegistry.reset();\n Root.Runtime.experiments.disableForTest(Root.Runtime.ExperimentName.TIMELINE_OBSERVATIONS);\n });\n\n it('shows the dropdown including a landing page link if the observations experiment is enabled', async function() {\n Root.Runtime.experiments.enableForTest(Root.Runtime.ExperimentName.TIMELINE_OBSERVATIONS);\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n historyManager.addRecording(\n {\n data: {\n traceParseDataIndex: 1,\n type: 'TRACE_INDEX',\n },\n filmStripForPreview: null,\n traceParsedData: traceData,\n startTime: null,\n },\n );\n\n const showPromise = historyManager.showHistoryDropDown();\n const glassPane = document.querySelector('div[data-devtools-glass-pane]');\n const dropdown =\n glassPane?.shadowRoot?.querySelector('.widget')?.shadowRoot?.querySelector('.drop-down');\n assert.isOk(dropdown);\n\n const menuItemText = Array.from(dropdown.querySelectorAll('[role=\"menuitem\"]'), elem => {\n return elem.innerText.replaceAll('\\n', '');\n });\n assert.deepEqual(menuItemText, ['Live metrics', 'web.dev5.39 s']);\n\n // Cancel the dropdown, which also resolves the show() promise, meaning we\n // don't leak it into other tests.\n historyManager.cancelIfShowing();\n await showPromise;\n });\n\n it('does not show if observations experiment is disabled + the user has not imported 2 traces', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n historyManager.addRecording(\n {\n data: {\n traceParseDataIndex: 1,\n type: 'TRACE_INDEX',\n },\n filmStripForPreview: null,\n traceParsedData: traceData,\n startTime: null,\n },\n );\n\n const promise = historyManager.showHistoryDropDown();\n const glassPane = document.querySelector('div[data-devtools-glass-pane]');\n assert.isNull(glassPane); // check that no DOM for the dropdown got created\n // check the result of calling showHistoryDropDown which should be `null` if it didn't show\n const result = await promise;\n assert.isNull(result);\n });\n\n it('does not show the landing page link if the observations experiment is disabled', async function() {\n const {traceData: traceData1} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n historyManager.addRecording(\n {\n data: {\n traceParseDataIndex: 1,\n type: 'TRACE_INDEX',\n },\n filmStripForPreview: null,\n traceParsedData: traceData1,\n startTime: null,\n },\n );\n const {traceData: traceData2} = await TraceLoader.traceEngine(this, 'timings-track.json.gz');\n historyManager.addRecording(\n {\n data: {\n traceParseDataIndex: 2,\n type: 'TRACE_INDEX',\n },\n filmStripForPreview: null,\n traceParsedData: traceData2,\n startTime: null,\n },\n );\n\n const showPromise = historyManager.showHistoryDropDown();\n const glassPane = document.querySelector('div[data-devtools-glass-pane]');\n const dropdown =\n glassPane?.shadowRoot?.querySelector('.widget')?.shadowRoot?.querySelector('.drop-down');\n assert.isOk(dropdown);\n\n const menuItemText = Array.from(dropdown.querySelectorAll('[role=\"menuitem\"]'), elem => {\n return elem.innerText.replaceAll('\\n', '');\n });\n assert.deepEqual(menuItemText, [\n 'localhost3.16 s',\n 'web.dev5.39 s',\n ]);\n\n // Cancel the dropdown, which also resolves the show() promise, meaning we\n // don't leak it into other tests.\n historyManager.cancelIfShowing();\n await showPromise;\n });\n\n it('can select from multiple parsed data objects', async function() {\n // Add two parsed data objects to the history manager.\n const {traceData: trace1Data} = await TraceLoader.traceEngine(this, 'slow-interaction-button-click.json.gz');\n historyManager.addRecording(\n {\n data: {\n traceParseDataIndex: 1,\n type: 'TRACE_INDEX',\n },\n filmStripForPreview: null,\n traceParsedData: trace1Data,\n startTime: null,\n },\n );\n\n const {traceData: trace2Data} = await TraceLoader.traceEngine(this, 'slow-interaction-keydown.json.gz');\n historyManager.addRecording({\n data: {\n traceParseDataIndex: 2,\n type: 'TRACE_INDEX',\n },\n filmStripForPreview: null,\n traceParsedData: trace2Data,\n startTime: null,\n });\n\n // Make sure the correct model is returned when\n // using the history manager to navigate between trace files..\n const previousRecording = historyManager.navigate(1);\n assert.strictEqual(previousRecording?.traceParseDataIndex, 1);\n\n const nextRecording = historyManager.navigate(-1);\n assert.strictEqual(nextRecording?.traceParseDataIndex, 2);\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"TimelineHistoryManager.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineHistoryManager.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Root from '../../core/root/root.js';\nimport {\n describeWithEnvironment,\n registerNoopActions,\n} from '../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport * as Timeline from './timeline.js';\n\ndescribeWithEnvironment('TimelineHistoryManager', function() {\n let historyManager: Timeline.TimelineHistoryManager.TimelineHistoryManager;\n beforeEach(() => {\n registerNoopActions(['timeline.show-history']);\n historyManager = new Timeline.TimelineHistoryManager.TimelineHistoryManager();\n });\n\n afterEach(() => {\n UI.ActionRegistry.ActionRegistry.reset();\n Root.Runtime.experiments.disableForTest(Root.Runtime.ExperimentName.TIMELINE_OBSERVATIONS);\n });\n\n it('shows the dropdown including a landing page link if the observations experiment is enabled', async function() {\n Root.Runtime.experiments.enableForTest(Root.Runtime.ExperimentName.TIMELINE_OBSERVATIONS);\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n historyManager.addRecording(\n {\n data: {\n parsedTraceIndex: 1,\n type: 'TRACE_INDEX',\n },\n filmStripForPreview: null,\n parsedTrace,\n startTime: null,\n },\n );\n\n const showPromise = historyManager.showHistoryDropDown();\n const glassPane = document.querySelector('div[data-devtools-glass-pane]');\n const dropdown =\n glassPane?.shadowRoot?.querySelector('.widget')?.shadowRoot?.querySelector('.drop-down');\n assert.isOk(dropdown);\n\n const menuItemText = Array.from(dropdown.querySelectorAll('[role=\"menuitem\"]'), elem => {\n return elem.innerText.replaceAll('\\n', '');\n });\n assert.deepEqual(menuItemText, ['Live metrics', 'web.dev5.39 s']);\n\n // Cancel the dropdown, which also resolves the show() promise, meaning we\n // don't leak it into other tests.\n historyManager.cancelIfShowing();\n await showPromise;\n });\n\n it('does not show if observations experiment is disabled + the user has not imported 2 traces', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n historyManager.addRecording(\n {\n data: {\n parsedTraceIndex: 1,\n type: 'TRACE_INDEX',\n },\n filmStripForPreview: null,\n parsedTrace,\n startTime: null,\n },\n );\n\n const promise = historyManager.showHistoryDropDown();\n const glassPane = document.querySelector('div[data-devtools-glass-pane]');\n assert.isNull(glassPane); // check that no DOM for the dropdown got created\n // check the result of calling showHistoryDropDown which should be `null` if it didn't show\n const result = await promise;\n assert.isNull(result);\n });\n\n it('does not show the landing page link if the observations experiment is disabled', async function() {\n const {parsedTrace: parsedTrace1} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n historyManager.addRecording(\n {\n data: {\n parsedTraceIndex: 1,\n type: 'TRACE_INDEX',\n },\n filmStripForPreview: null,\n parsedTrace: parsedTrace1,\n startTime: null,\n },\n );\n const {parsedTrace: parsedTrace2} = await TraceLoader.traceEngine(this, 'timings-track.json.gz');\n historyManager.addRecording(\n {\n data: {\n parsedTraceIndex: 2,\n type: 'TRACE_INDEX',\n },\n filmStripForPreview: null,\n parsedTrace: parsedTrace2,\n startTime: null,\n },\n );\n\n const showPromise = historyManager.showHistoryDropDown();\n const glassPane = document.querySelector('div[data-devtools-glass-pane]');\n const dropdown =\n glassPane?.shadowRoot?.querySelector('.widget')?.shadowRoot?.querySelector('.drop-down');\n assert.isOk(dropdown);\n\n const menuItemText = Array.from(dropdown.querySelectorAll('[role=\"menuitem\"]'), elem => {\n return elem.innerText.replaceAll('\\n', '');\n });\n assert.deepEqual(menuItemText, [\n 'localhost3.16 s',\n 'web.dev5.39 s',\n ]);\n\n // Cancel the dropdown, which also resolves the show() promise, meaning we\n // don't leak it into other tests.\n historyManager.cancelIfShowing();\n await showPromise;\n });\n\n it('can select from multiple parsed data objects', async function() {\n // Add two parsed data objects to the history manager.\n const {parsedTrace: trace1Data} = await TraceLoader.traceEngine(this, 'slow-interaction-button-click.json.gz');\n historyManager.addRecording(\n {\n data: {\n parsedTraceIndex: 1,\n type: 'TRACE_INDEX',\n },\n filmStripForPreview: null,\n parsedTrace: trace1Data,\n startTime: null,\n },\n );\n\n const {parsedTrace: trace2Data} = await TraceLoader.traceEngine(this, 'slow-interaction-keydown.json.gz');\n historyManager.addRecording({\n data: {\n parsedTraceIndex: 2,\n type: 'TRACE_INDEX',\n },\n filmStripForPreview: null,\n parsedTrace: trace2Data,\n startTime: null,\n });\n\n // Make sure the correct model is returned when\n // using the history manager to navigate between trace files..\n const previousRecording = historyManager.navigate(1);\n assert.strictEqual(previousRecording?.parsedTraceIndex, 1);\n\n const nextRecording = historyManager.navigate(-1);\n assert.strictEqual(nextRecording?.parsedTraceIndex, 2);\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineLoader.d.ts b/public/panels/timeline/TimelineLoader.d.ts index 51be57a63..d7e9195b0 100644 --- a/public/panels/timeline/TimelineLoader.d.ts +++ b/public/panels/timeline/TimelineLoader.d.ts @@ -1,7 +1,7 @@ import * as Common from '../../core/common/common.js'; import type * as Platform from '../../core/platform/platform.js'; import type * as Protocol from '../../generated/protocol.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import { type Client } from './TimelineController.js'; /** * This class handles loading traces from file and URL, and from the Lighthouse panel @@ -20,10 +20,10 @@ export declare class TimelineLoader implements Common.StringOutputStream.OutputS private filter; constructor(client: Client); static loadFromFile(file: File, client: Client): Promise; - static loadFromEvents(events: TraceEngine.Types.TraceEvents.TraceEventData[], client: Client): TimelineLoader; + static loadFromEvents(events: Trace.Types.Events.Event[], client: Client): TimelineLoader; static loadFromCpuProfile(profile: Protocol.Profiler.Profile, client: Client): TimelineLoader; static loadFromURL(url: Platform.DevToolsPath.UrlString, client: Client): Promise; - addEvents(events: TraceEngine.Types.TraceEvents.TraceEventData[]): Promise; + addEvents(events: Trace.Types.Events.Event[]): Promise; cancel(): Promise; /** * As TimelineLoader implements `Common.StringOutputStream.OutputStream`, `write()` is called when a diff --git a/public/panels/timeline/TimelineLoader.js b/public/panels/timeline/TimelineLoader.js index efe9d74ce..f603ccc15 100644 --- a/public/panels/timeline/TimelineLoader.js +++ b/public/panels/timeline/TimelineLoader.js @@ -6,7 +6,7 @@ import * as Host from '../../core/host/host.js'; import * as i18n from '../../core/i18n/i18n.js'; import * as Bindings from '../../models/bindings/bindings.js'; import * as TimelineModel from '../../models/timeline_model/timeline_model.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; const UIStrings = { /** *@description Text in Timeline Loader of the Performance panel @@ -74,7 +74,7 @@ export class TimelineLoader { const loader = new TimelineLoader(client); loader.#traceIsCPUProfile = true; try { - const events = TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.createFakeTraceFromCpuProfile(profile, TraceEngine.Types.TraceEvents.ThreadID(1)); + const events = TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.createFakeTraceFromCpuProfile(profile, Trace.Types.Events.ThreadID(1)); window.setTimeout(async () => { void loader.addEvents(events); }); @@ -218,7 +218,7 @@ export class TimelineLoader { return this.#traceFinalizedPromiseForTest; } #parseCPUProfileFormatFromFile(parsedTrace) { - const traceEvents = TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.createFakeTraceFromCpuProfile(parsedTrace, TraceEngine.Types.TraceEvents.ThreadID(1)); + const traceEvents = TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.createFakeTraceFromCpuProfile(parsedTrace, Trace.Types.Events.ThreadID(1)); this.#collectEvents(traceEvents); } #collectEvents(events) { diff --git a/public/panels/timeline/TimelineLoader.js.map b/public/panels/timeline/TimelineLoader.js.map index 5a47d243b..aeb979355 100644 --- a/public/panels/timeline/TimelineLoader.js.map +++ b/public/panels/timeline/TimelineLoader.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineLoader.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineLoader.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2016 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as Host from '../../core/host/host.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport type * as Platform from '../../core/platform/platform.js';\nimport type * as Protocol from '../../generated/protocol.js';\nimport * as Bindings from '../../models/bindings/bindings.js';\nimport * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\n\nimport {type Client} from './TimelineController.js';\n\nconst UIStrings = {\n /**\n *@description Text in Timeline Loader of the Performance panel\n *@example {Unknown JSON format} PH1\n */\n malformedTimelineDataS: 'Malformed timeline data: {PH1}',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelineLoader.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\n/**\n * This class handles loading traces from file and URL, and from the Lighthouse panel\n * It also handles loading cpuprofiles from file, url and console.profileEnd()\n *\n * Meanwhile, the normal trace recording flow bypasses TimelineLoader entirely,\n * as it's handled from TracingManager => TimelineController.\n */\nexport class TimelineLoader implements Common.StringOutputStream.OutputStream {\n private client: Client|null;\n private canceledCallback: (() => void)|null;\n private buffer: string;\n private firstRawChunk: boolean;\n private totalSize!: number;\n private filter: TimelineModel.TimelineModelFilter.TimelineModelFilter|null;\n #traceIsCPUProfile: boolean;\n #collectedEvents: TraceEngine.Types.TraceEvents.TraceEventData[] = [];\n #metadata: TraceEngine.Types.File.MetaData|null;\n\n #traceFinalizedCallbackForTest?: () => void;\n #traceFinalizedPromiseForTest: Promise;\n\n constructor(client: Client) {\n this.client = client;\n this.canceledCallback = null;\n this.buffer = '';\n this.firstRawChunk = true;\n this.filter = null;\n this.#traceIsCPUProfile = false;\n this.#metadata = null;\n\n this.#traceFinalizedPromiseForTest = new Promise(resolve => {\n this.#traceFinalizedCallbackForTest = resolve;\n });\n }\n\n static async loadFromFile(file: File, client: Client): Promise {\n const loader = new TimelineLoader(client);\n const fileReader = new Bindings.FileUtils.ChunkedFileReader(file);\n loader.canceledCallback = fileReader.cancel.bind(fileReader);\n loader.totalSize = file.size;\n // We'll resolve and return the loader instance before finalizing the trace.\n setTimeout(async () => {\n const success = await fileReader.read(loader);\n if (!success && fileReader.error()) {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n loader.reportErrorAndCancelLoading((fileReader.error() as any).message);\n }\n });\n return loader;\n }\n\n static loadFromEvents(events: TraceEngine.Types.TraceEvents.TraceEventData[], client: Client): TimelineLoader {\n const loader = new TimelineLoader(client);\n window.setTimeout(async () => {\n void loader.addEvents(events);\n });\n return loader;\n }\n\n static loadFromCpuProfile(profile: Protocol.Profiler.Profile, client: Client): TimelineLoader {\n const loader = new TimelineLoader(client);\n loader.#traceIsCPUProfile = true;\n\n try {\n const events = TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.createFakeTraceFromCpuProfile(\n profile, TraceEngine.Types.TraceEvents.ThreadID(1));\n\n window.setTimeout(async () => {\n void loader.addEvents(events);\n });\n } catch (e) {\n console.error(e.stack);\n }\n return loader;\n }\n\n static async loadFromURL(url: Platform.DevToolsPath.UrlString, client: Client): Promise {\n const loader = new TimelineLoader(client);\n const stream = new Common.StringOutputStream.StringOutputStream();\n await client.loadingStarted();\n\n const allowRemoteFilePaths =\n Common.Settings.Settings.instance().moduleSetting('network.enable-remote-file-loading').get();\n Host.ResourceLoader.loadAsStream(url, null, stream, finishedCallback, allowRemoteFilePaths);\n\n async function finishedCallback(\n success: boolean, _headers: {[x: string]: string},\n errorDescription: Host.ResourceLoader.LoadErrorDescription): Promise {\n if (!success) {\n return loader.reportErrorAndCancelLoading(errorDescription.message);\n }\n try {\n const txt = stream.data();\n const trace = JSON.parse(txt);\n loader.#processParsedFile(trace);\n await loader.close();\n } catch (e: unknown) {\n await loader.close();\n const message = e instanceof Error ? e.message : '';\n return loader.reportErrorAndCancelLoading(i18nString(UIStrings.malformedTimelineDataS, {PH1: message}));\n }\n }\n\n return loader;\n }\n\n #processParsedFile(trace: ParsedJSONFile): void {\n if ('traceEvents' in trace || Array.isArray(trace)) {\n // We know that this is NOT a raw CPU Profile because it has traceEvents\n // (either at the top level, or nested under the traceEvents key)\n const items = Array.isArray(trace) ? trace : trace.traceEvents;\n\n this.#collectEvents(items);\n } else if (trace.nodes) {\n // We know it's a raw Protocol CPU Profile.\n this.#parseCPUProfileFormatFromFile(trace);\n this.#traceIsCPUProfile = true;\n } else {\n this.reportErrorAndCancelLoading(i18nString(UIStrings.malformedTimelineDataS));\n return;\n }\n\n if ('metadata' in trace) {\n this.#metadata = trace.metadata;\n }\n }\n\n async addEvents(events: TraceEngine.Types.TraceEvents.TraceEventData[]): Promise {\n await this.client?.loadingStarted();\n /**\n * See the `eventsPerChunk` comment in `models/trace/types/Configuration.ts`.\n *\n * This value is different though. Why? `The addEvents()` work below is different\n * (and much faster!) than running `handleEvent()` on all handlers.\n */\n const eventsPerChunk = 150_000;\n for (let i = 0; i < events.length; i += eventsPerChunk) {\n const chunk = events.slice(i, i + eventsPerChunk);\n this.#collectEvents(chunk as unknown as TraceEngine.Types.TraceEvents.TraceEventData[]);\n await this.client?.loadingProgress((i + chunk.length) / events.length);\n await new Promise(r => window.setTimeout(r, 0)); // Yield event loop to paint.\n }\n void this.close();\n }\n\n async cancel(): Promise {\n if (this.client) {\n await this.client.loadingComplete(\n /* collectedEvents */[], /* exclusiveFilter= */ null, /* isCpuProfile= */ false,\n /* recordingStartTime= */ null, /* metadata= */ null);\n this.client = null;\n }\n if (this.canceledCallback) {\n this.canceledCallback();\n }\n }\n\n /**\n * As TimelineLoader implements `Common.StringOutputStream.OutputStream`, `write()` is called when a\n * Common.StringOutputStream.StringOutputStream instance has decoded a chunk. This path is only used\n * by `loadFromFile()`; it's NOT used by `loadFromEvents` or `loadFromURL`.\n */\n async write(chunk: string, endOfFile: boolean): Promise {\n if (!this.client) {\n return Promise.resolve();\n }\n this.buffer += chunk;\n if (this.firstRawChunk) {\n await this.client.loadingStarted();\n // Ensure we paint the loading dialog before continuing\n await new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve)));\n this.firstRawChunk = false;\n } else {\n let progress = undefined;\n progress = this.buffer.length / this.totalSize;\n // For compressed traces, we can't provide a definite progress percentage. So, just keep it moving.\n // For other traces, calculate a loaded part.\n progress = progress > 1 ? progress - Math.floor(progress) : progress;\n await this.client.loadingProgress(progress);\n }\n\n if (endOfFile) {\n let trace;\n try {\n trace = JSON.parse(this.buffer) as ParsedJSONFile;\n this.#processParsedFile(trace);\n return Promise.resolve();\n } catch (e) {\n this.reportErrorAndCancelLoading(i18nString(UIStrings.malformedTimelineDataS, {PH1: e.toString()}));\n return;\n }\n }\n }\n\n private reportErrorAndCancelLoading(message?: string): void {\n if (message) {\n Common.Console.Console.instance().error(message);\n }\n void this.cancel();\n }\n\n async close(): Promise {\n if (!this.client) {\n return;\n }\n await this.client.processingStarted();\n await this.finalizeTrace();\n }\n\n private isCpuProfile(): boolean {\n return this.#traceIsCPUProfile;\n }\n\n private async finalizeTrace(): Promise {\n await (this.client as Client)\n .loadingComplete(\n this.#collectedEvents, this.filter, this.isCpuProfile(), /* recordingStartTime=*/ null, this.#metadata);\n this.#traceFinalizedCallbackForTest?.();\n }\n\n traceFinalizedForTest(): Promise {\n return this.#traceFinalizedPromiseForTest;\n }\n\n #parseCPUProfileFormatFromFile(parsedTrace: Protocol.Profiler.Profile): void {\n const traceEvents = TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.createFakeTraceFromCpuProfile(\n parsedTrace, TraceEngine.Types.TraceEvents.ThreadID(1));\n\n this.#collectEvents(traceEvents);\n }\n\n #collectEvents(events: readonly TraceEngine.Types.TraceEvents.TraceEventData[]): void {\n this.#collectedEvents = this.#collectedEvents.concat(events);\n }\n}\n\n/**\n * Used when we parse the input, but do not yet know if it is a raw CPU Profile or a Trace\n **/\ntype ParsedJSONFile = TraceEngine.Types.File.Contents|Protocol.Profiler.Profile;\n"]} \ No newline at end of file +{"version":3,"file":"TimelineLoader.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineLoader.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2016 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as Host from '../../core/host/host.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport type * as Platform from '../../core/platform/platform.js';\nimport type * as Protocol from '../../generated/protocol.js';\nimport * as Bindings from '../../models/bindings/bindings.js';\nimport * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport * as Trace from '../../models/trace/trace.js';\n\nimport {type Client} from './TimelineController.js';\n\nconst UIStrings = {\n /**\n *@description Text in Timeline Loader of the Performance panel\n *@example {Unknown JSON format} PH1\n */\n malformedTimelineDataS: 'Malformed timeline data: {PH1}',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelineLoader.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\n/**\n * This class handles loading traces from file and URL, and from the Lighthouse panel\n * It also handles loading cpuprofiles from file, url and console.profileEnd()\n *\n * Meanwhile, the normal trace recording flow bypasses TimelineLoader entirely,\n * as it's handled from TracingManager => TimelineController.\n */\nexport class TimelineLoader implements Common.StringOutputStream.OutputStream {\n private client: Client|null;\n private canceledCallback: (() => void)|null;\n private buffer: string;\n private firstRawChunk: boolean;\n private totalSize!: number;\n private filter: TimelineModel.TimelineModelFilter.TimelineModelFilter|null;\n #traceIsCPUProfile: boolean;\n #collectedEvents: Trace.Types.Events.Event[] = [];\n #metadata: Trace.Types.File.MetaData|null;\n\n #traceFinalizedCallbackForTest?: () => void;\n #traceFinalizedPromiseForTest: Promise;\n\n constructor(client: Client) {\n this.client = client;\n this.canceledCallback = null;\n this.buffer = '';\n this.firstRawChunk = true;\n this.filter = null;\n this.#traceIsCPUProfile = false;\n this.#metadata = null;\n\n this.#traceFinalizedPromiseForTest = new Promise(resolve => {\n this.#traceFinalizedCallbackForTest = resolve;\n });\n }\n\n static async loadFromFile(file: File, client: Client): Promise {\n const loader = new TimelineLoader(client);\n const fileReader = new Bindings.FileUtils.ChunkedFileReader(file);\n loader.canceledCallback = fileReader.cancel.bind(fileReader);\n loader.totalSize = file.size;\n // We'll resolve and return the loader instance before finalizing the trace.\n setTimeout(async () => {\n const success = await fileReader.read(loader);\n if (!success && fileReader.error()) {\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n loader.reportErrorAndCancelLoading((fileReader.error() as any).message);\n }\n });\n return loader;\n }\n\n static loadFromEvents(events: Trace.Types.Events.Event[], client: Client): TimelineLoader {\n const loader = new TimelineLoader(client);\n window.setTimeout(async () => {\n void loader.addEvents(events);\n });\n return loader;\n }\n\n static loadFromCpuProfile(profile: Protocol.Profiler.Profile, client: Client): TimelineLoader {\n const loader = new TimelineLoader(client);\n loader.#traceIsCPUProfile = true;\n\n try {\n const events = TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.createFakeTraceFromCpuProfile(\n profile, Trace.Types.Events.ThreadID(1));\n\n window.setTimeout(async () => {\n void loader.addEvents(events);\n });\n } catch (e) {\n console.error(e.stack);\n }\n return loader;\n }\n\n static async loadFromURL(url: Platform.DevToolsPath.UrlString, client: Client): Promise {\n const loader = new TimelineLoader(client);\n const stream = new Common.StringOutputStream.StringOutputStream();\n await client.loadingStarted();\n\n const allowRemoteFilePaths =\n Common.Settings.Settings.instance().moduleSetting('network.enable-remote-file-loading').get();\n Host.ResourceLoader.loadAsStream(url, null, stream, finishedCallback, allowRemoteFilePaths);\n\n async function finishedCallback(\n success: boolean, _headers: {[x: string]: string},\n errorDescription: Host.ResourceLoader.LoadErrorDescription): Promise {\n if (!success) {\n return loader.reportErrorAndCancelLoading(errorDescription.message);\n }\n try {\n const txt = stream.data();\n const trace = JSON.parse(txt);\n loader.#processParsedFile(trace);\n await loader.close();\n } catch (e: unknown) {\n await loader.close();\n const message = e instanceof Error ? e.message : '';\n return loader.reportErrorAndCancelLoading(i18nString(UIStrings.malformedTimelineDataS, {PH1: message}));\n }\n }\n\n return loader;\n }\n\n #processParsedFile(trace: ParsedJSONFile): void {\n if ('traceEvents' in trace || Array.isArray(trace)) {\n // We know that this is NOT a raw CPU Profile because it has traceEvents\n // (either at the top level, or nested under the traceEvents key)\n const items = Array.isArray(trace) ? trace : trace.traceEvents;\n\n this.#collectEvents(items);\n } else if (trace.nodes) {\n // We know it's a raw Protocol CPU Profile.\n this.#parseCPUProfileFormatFromFile(trace);\n this.#traceIsCPUProfile = true;\n } else {\n this.reportErrorAndCancelLoading(i18nString(UIStrings.malformedTimelineDataS));\n return;\n }\n\n if ('metadata' in trace) {\n this.#metadata = trace.metadata;\n }\n }\n\n async addEvents(events: Trace.Types.Events.Event[]): Promise {\n await this.client?.loadingStarted();\n /**\n * See the `eventsPerChunk` comment in `models/trace/types/Configuration.ts`.\n *\n * This value is different though. Why? `The addEvents()` work below is different\n * (and much faster!) than running `handleEvent()` on all handlers.\n */\n const eventsPerChunk = 150_000;\n for (let i = 0; i < events.length; i += eventsPerChunk) {\n const chunk = events.slice(i, i + eventsPerChunk);\n this.#collectEvents(chunk as unknown as Trace.Types.Events.Event[]);\n await this.client?.loadingProgress((i + chunk.length) / events.length);\n await new Promise(r => window.setTimeout(r, 0)); // Yield event loop to paint.\n }\n void this.close();\n }\n\n async cancel(): Promise {\n if (this.client) {\n await this.client.loadingComplete(\n /* collectedEvents */[], /* exclusiveFilter= */ null, /* isCpuProfile= */ false,\n /* recordingStartTime= */ null, /* metadata= */ null);\n this.client = null;\n }\n if (this.canceledCallback) {\n this.canceledCallback();\n }\n }\n\n /**\n * As TimelineLoader implements `Common.StringOutputStream.OutputStream`, `write()` is called when a\n * Common.StringOutputStream.StringOutputStream instance has decoded a chunk. This path is only used\n * by `loadFromFile()`; it's NOT used by `loadFromEvents` or `loadFromURL`.\n */\n async write(chunk: string, endOfFile: boolean): Promise {\n if (!this.client) {\n return Promise.resolve();\n }\n this.buffer += chunk;\n if (this.firstRawChunk) {\n await this.client.loadingStarted();\n // Ensure we paint the loading dialog before continuing\n await new Promise(resolve => requestAnimationFrame(() => requestAnimationFrame(resolve)));\n this.firstRawChunk = false;\n } else {\n let progress = undefined;\n progress = this.buffer.length / this.totalSize;\n // For compressed traces, we can't provide a definite progress percentage. So, just keep it moving.\n // For other traces, calculate a loaded part.\n progress = progress > 1 ? progress - Math.floor(progress) : progress;\n await this.client.loadingProgress(progress);\n }\n\n if (endOfFile) {\n let trace;\n try {\n trace = JSON.parse(this.buffer) as ParsedJSONFile;\n this.#processParsedFile(trace);\n return Promise.resolve();\n } catch (e) {\n this.reportErrorAndCancelLoading(i18nString(UIStrings.malformedTimelineDataS, {PH1: e.toString()}));\n return;\n }\n }\n }\n\n private reportErrorAndCancelLoading(message?: string): void {\n if (message) {\n Common.Console.Console.instance().error(message);\n }\n void this.cancel();\n }\n\n async close(): Promise {\n if (!this.client) {\n return;\n }\n await this.client.processingStarted();\n await this.finalizeTrace();\n }\n\n private isCpuProfile(): boolean {\n return this.#traceIsCPUProfile;\n }\n\n private async finalizeTrace(): Promise {\n await (this.client as Client)\n .loadingComplete(\n this.#collectedEvents, this.filter, this.isCpuProfile(), /* recordingStartTime=*/ null, this.#metadata);\n this.#traceFinalizedCallbackForTest?.();\n }\n\n traceFinalizedForTest(): Promise {\n return this.#traceFinalizedPromiseForTest;\n }\n\n #parseCPUProfileFormatFromFile(parsedTrace: Protocol.Profiler.Profile): void {\n const traceEvents = TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.createFakeTraceFromCpuProfile(\n parsedTrace, Trace.Types.Events.ThreadID(1));\n\n this.#collectEvents(traceEvents);\n }\n\n #collectEvents(events: readonly Trace.Types.Events.Event[]): void {\n this.#collectedEvents = this.#collectedEvents.concat(events);\n }\n}\n\n/**\n * Used when we parse the input, but do not yet know if it is a raw CPU Profile or a Trace\n **/\ntype ParsedJSONFile = Trace.Types.File.Contents|Protocol.Profiler.Profile;\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineLoader.test.js.map b/public/panels/timeline/TimelineLoader.test.js.map index 4921a8fe7..9968c83e1 100644 --- a/public/panels/timeline/TimelineLoader.test.js.map +++ b/public/panels/timeline/TimelineLoader.test.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineLoader.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineLoader.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Protocol from '../../generated/protocol.js';\nimport type * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport type * as TraceEngine from '../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {makeInstantEvent} from '../../testing/TraceHelpers.js';\n\nimport * as Timeline from './timeline.js';\n\nasync function loadWebDevTraceAsFile(): Promise {\n const file = new URL('./fixtures/traces/web-dev.json.gz', import.meta.url);\n const response = await fetch(file);\n const asBlob = await response.blob();\n const asFile = new File([asBlob], 'web-dev.json.gz', {\n type: 'application/gzip',\n });\n return asFile;\n}\n\nasync function loadBasicCpuProfileAsFile(): Promise {\n const file = new URL('./fixtures/traces/node-fibonacci-website.cpuprofile.gz', import.meta.url);\n const response = await fetch(file);\n const asBlob = await response.blob();\n const asFile = new File([asBlob], 'node-fibonacci-website.cpuprofile.gz', {\n type: 'application/gzip',\n });\n return asFile;\n}\n\ndescribeWithEnvironment('TimelineLoader', () => {\n const loadingStartedSpy = sinon.spy();\n const loadingProgressSpy = sinon.spy();\n const processingStartedSpy = sinon.spy();\n const loadingCompleteSpy = sinon.spy();\n const recordingProgressSpy = sinon.spy();\n const loadingCompleteForTestSpy = sinon.spy();\n\n const client: Timeline.TimelineController.Client = {\n async loadingStarted() {\n loadingStartedSpy();\n },\n async loadingProgress(progress?: number) {\n loadingProgressSpy(progress);\n },\n async processingStarted() {\n processingStartedSpy();\n },\n async loadingComplete(\n collectedEvents: TraceEngine.Types.TraceEvents.TraceEventData[],\n exclusiveFilter: TimelineModel.TimelineModelFilter.TimelineModelFilter|null,\n isCpuProfile: boolean,\n ) {\n loadingCompleteSpy(collectedEvents, exclusiveFilter, isCpuProfile);\n },\n recordingProgress: function(usage: number): void {\n recordingProgressSpy(usage);\n },\n loadingCompleteForTest: function(): void {\n loadingCompleteForTestSpy();\n },\n };\n\n beforeEach(() => {\n loadingStartedSpy.resetHistory();\n loadingProgressSpy.resetHistory();\n processingStartedSpy.resetHistory();\n loadingCompleteSpy.resetHistory();\n recordingProgressSpy.resetHistory();\n loadingCompleteForTestSpy.resetHistory();\n });\n\n it('can load a saved trace file', async () => {\n const file = await loadWebDevTraceAsFile();\n const loader = await Timeline.TimelineLoader.TimelineLoader.loadFromFile(file, client);\n await loader.traceFinalizedForTest();\n assert.isTrue(loadingStartedSpy.calledOnce);\n // Exact number is deterministic so we can assert, but the fact it was 29\n // calls doesn't really matter. We just want to check it got called \"a\n // bunch of times\".\n assert.strictEqual(loadingProgressSpy.callCount, 29);\n assert.isTrue(processingStartedSpy.calledOnce);\n assert.isTrue(loadingCompleteSpy.calledOnce);\n\n // Get the arguments of the first (and only) call to the loadingComplete\n // function. TS doesn't know what the types are (they are [any, any] by\n // default), so we tell it that they align with the types of the\n // loadingComplete parameters.\n const [collectedEvents, exclusiveFilter, isCpuProfile] =\n loadingCompleteSpy.args[0] as Parameters;\n assert.isNull(exclusiveFilter); // We are not filtering out any events for this trace.\n // Ensure that we loaded something that looks about right!\n assert.lengthOf(collectedEvents, 8252);\n assert.isFalse(isCpuProfile);\n });\n\n it('can load a saved CPUProfile file', async () => {\n const file = await loadBasicCpuProfileAsFile();\n const loader = await Timeline.TimelineLoader.TimelineLoader.loadFromFile(file, client);\n await loader.traceFinalizedForTest();\n assert.isTrue(loadingStartedSpy.calledOnce);\n // For the CPU Profile we are testing, loadingProgress will be called three times, because the\n // file is not that big.\n assert.strictEqual(loadingProgressSpy.callCount, 3);\n assert.isTrue(processingStartedSpy.calledOnce);\n assert.isTrue(loadingCompleteSpy.calledOnce);\n\n // Get the arguments of the first (and only) call to the loadingComplete\n // function. TS doesn't know what the types are (they are [any, any] by\n // default), so we tell it that they align with the types of the\n // loadingComplete parameters.\n const [collectedEvents, /* exclusiveFilter */, isCpuProfile] =\n loadingCompleteSpy.args[0] as Parameters;\n // We create fake trace event for CPU profile, includes one for\n // TracingStartedInPage, one for metadata, one for root, and one for CPU\n // profile\n assert.lengthOf(collectedEvents, 4);\n assert.isTrue(isCpuProfile);\n });\n\n it('can load recorded trace events correctly', async () => {\n const testTraceEvents: TraceEngine.Types.TraceEvents.TraceEventData[] = [\n makeInstantEvent('test-event-1', 1),\n makeInstantEvent('test-event-2', 2),\n ];\n const loader = Timeline.TimelineLoader.TimelineLoader.loadFromEvents(testTraceEvents, client);\n await loader.traceFinalizedForTest();\n assert.isTrue(loadingStartedSpy.calledOnce);\n // For the trace events we are testing, loadingProgress will be called only once, because the\n // fake trace events array is very short.\n assert.isTrue(loadingProgressSpy.calledOnce);\n assert.isTrue(processingStartedSpy.calledOnce);\n assert.isTrue(loadingCompleteSpy.calledOnce);\n\n // Get the arguments of the first (and only) call to the loadingComplete\n // function. TS doesn't know what the types are (they are [any, any] by\n // default), so we tell it that they align with the types of the\n // loadingComplete parameters.\n const [collectedEvents, exclusiveFilter, isCpuProfile] =\n loadingCompleteSpy.args[0] as Parameters;\n assert.isNull(exclusiveFilter);\n // Ensure that we loaded something that looks about right!\n assert.lengthOf(collectedEvents, testTraceEvents.length);\n assert.isFalse(isCpuProfile);\n });\n\n it('can load recorded CPUProfile correctly', async () => {\n const testProfile: Protocol.Profiler.Profile = {nodes: [], startTime: 0, endTime: 0};\n const loader = Timeline.TimelineLoader.TimelineLoader.loadFromCpuProfile(testProfile, client);\n await loader.traceFinalizedForTest();\n assert.isTrue(loadingStartedSpy.calledOnce);\n // For the CPU Profile we are testing, loadingProgress will be called only once, because the\n // fake Profile is basically empty.\n assert.strictEqual(loadingProgressSpy.callCount, 1);\n assert.isTrue(processingStartedSpy.calledOnce);\n assert.isTrue(loadingCompleteSpy.calledOnce);\n\n // Get the arguments of the first (and only) call to the loadingComplete\n // function. TS doesn't know what the types are (they are [any, any] by\n // default), so we tell it that they align with the types of the\n // loadingComplete parameters.\n const [collectedEvents, /* exclusiveFilter */, isCpuProfile] =\n loadingCompleteSpy.args[0] as Parameters;\n // We create fake trace event for CPU profile, includes one for TracingStartedInPage,\n // one for metadata, one for root, and one for CPU profile\n assert.lengthOf(collectedEvents, 4);\n assert.isTrue(isCpuProfile);\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"TimelineLoader.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineLoader.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Protocol from '../../generated/protocol.js';\nimport type * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport type * as Trace from '../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {makeInstantEvent} from '../../testing/TraceHelpers.js';\n\nimport * as Timeline from './timeline.js';\n\nasync function loadWebDevTraceAsFile(): Promise {\n const file = new URL('./fixtures/traces/web-dev.json.gz', import.meta.url);\n const response = await fetch(file);\n const asBlob = await response.blob();\n const asFile = new File([asBlob], 'web-dev.json.gz', {\n type: 'application/gzip',\n });\n return asFile;\n}\n\nasync function loadBasicCpuProfileAsFile(): Promise {\n const file = new URL('./fixtures/traces/node-fibonacci-website.cpuprofile.gz', import.meta.url);\n const response = await fetch(file);\n const asBlob = await response.blob();\n const asFile = new File([asBlob], 'node-fibonacci-website.cpuprofile.gz', {\n type: 'application/gzip',\n });\n return asFile;\n}\n\ndescribeWithEnvironment('TimelineLoader', () => {\n const loadingStartedSpy = sinon.spy();\n const loadingProgressSpy = sinon.spy();\n const processingStartedSpy = sinon.spy();\n const loadingCompleteSpy = sinon.spy();\n const recordingProgressSpy = sinon.spy();\n const loadingCompleteForTestSpy = sinon.spy();\n\n const client: Timeline.TimelineController.Client = {\n async loadingStarted() {\n loadingStartedSpy();\n },\n async loadingProgress(progress?: number) {\n loadingProgressSpy(progress);\n },\n async processingStarted() {\n processingStartedSpy();\n },\n async loadingComplete(\n collectedEvents: Trace.Types.Events.Event[],\n exclusiveFilter: TimelineModel.TimelineModelFilter.TimelineModelFilter|null,\n isCpuProfile: boolean,\n ) {\n loadingCompleteSpy(collectedEvents, exclusiveFilter, isCpuProfile);\n },\n recordingProgress: function(usage: number): void {\n recordingProgressSpy(usage);\n },\n loadingCompleteForTest: function(): void {\n loadingCompleteForTestSpy();\n },\n };\n\n beforeEach(() => {\n loadingStartedSpy.resetHistory();\n loadingProgressSpy.resetHistory();\n processingStartedSpy.resetHistory();\n loadingCompleteSpy.resetHistory();\n recordingProgressSpy.resetHistory();\n loadingCompleteForTestSpy.resetHistory();\n });\n\n it('can load a saved trace file', async () => {\n const file = await loadWebDevTraceAsFile();\n const loader = await Timeline.TimelineLoader.TimelineLoader.loadFromFile(file, client);\n await loader.traceFinalizedForTest();\n assert.isTrue(loadingStartedSpy.calledOnce);\n // Exact number is deterministic so we can assert, but the fact it was 29\n // calls doesn't really matter. We just want to check it got called \"a\n // bunch of times\".\n assert.strictEqual(loadingProgressSpy.callCount, 29);\n assert.isTrue(processingStartedSpy.calledOnce);\n assert.isTrue(loadingCompleteSpy.calledOnce);\n\n // Get the arguments of the first (and only) call to the loadingComplete\n // function. TS doesn't know what the types are (they are [any, any] by\n // default), so we tell it that they align with the types of the\n // loadingComplete parameters.\n const [collectedEvents, exclusiveFilter, isCpuProfile] =\n loadingCompleteSpy.args[0] as Parameters;\n assert.isNull(exclusiveFilter); // We are not filtering out any events for this trace.\n // Ensure that we loaded something that looks about right!\n assert.lengthOf(collectedEvents, 8252);\n assert.isFalse(isCpuProfile);\n });\n\n it('can load a saved CPUProfile file', async () => {\n const file = await loadBasicCpuProfileAsFile();\n const loader = await Timeline.TimelineLoader.TimelineLoader.loadFromFile(file, client);\n await loader.traceFinalizedForTest();\n assert.isTrue(loadingStartedSpy.calledOnce);\n // For the CPU Profile we are testing, loadingProgress will be called three times, because the\n // file is not that big.\n assert.strictEqual(loadingProgressSpy.callCount, 3);\n assert.isTrue(processingStartedSpy.calledOnce);\n assert.isTrue(loadingCompleteSpy.calledOnce);\n\n // Get the arguments of the first (and only) call to the loadingComplete\n // function. TS doesn't know what the types are (they are [any, any] by\n // default), so we tell it that they align with the types of the\n // loadingComplete parameters.\n const [collectedEvents, /* exclusiveFilter */, isCpuProfile] =\n loadingCompleteSpy.args[0] as Parameters;\n // We create fake trace event for CPU profile, includes one for\n // TracingStartedInPage, one for metadata, one for root, and one for CPU\n // profile\n assert.lengthOf(collectedEvents, 4);\n assert.isTrue(isCpuProfile);\n });\n\n it('can load recorded trace events correctly', async () => {\n const testTraceEvents: Trace.Types.Events.Event[] = [\n makeInstantEvent('test-event-1', 1),\n makeInstantEvent('test-event-2', 2),\n ];\n const loader = Timeline.TimelineLoader.TimelineLoader.loadFromEvents(testTraceEvents, client);\n await loader.traceFinalizedForTest();\n assert.isTrue(loadingStartedSpy.calledOnce);\n // For the trace events we are testing, loadingProgress will be called only once, because the\n // fake trace events array is very short.\n assert.isTrue(loadingProgressSpy.calledOnce);\n assert.isTrue(processingStartedSpy.calledOnce);\n assert.isTrue(loadingCompleteSpy.calledOnce);\n\n // Get the arguments of the first (and only) call to the loadingComplete\n // function. TS doesn't know what the types are (they are [any, any] by\n // default), so we tell it that they align with the types of the\n // loadingComplete parameters.\n const [collectedEvents, exclusiveFilter, isCpuProfile] =\n loadingCompleteSpy.args[0] as Parameters;\n assert.isNull(exclusiveFilter);\n // Ensure that we loaded something that looks about right!\n assert.lengthOf(collectedEvents, testTraceEvents.length);\n assert.isFalse(isCpuProfile);\n });\n\n it('can load recorded CPUProfile correctly', async () => {\n const testProfile: Protocol.Profiler.Profile = {nodes: [], startTime: 0, endTime: 0};\n const loader = Timeline.TimelineLoader.TimelineLoader.loadFromCpuProfile(testProfile, client);\n await loader.traceFinalizedForTest();\n assert.isTrue(loadingStartedSpy.calledOnce);\n // For the CPU Profile we are testing, loadingProgress will be called only once, because the\n // fake Profile is basically empty.\n assert.strictEqual(loadingProgressSpy.callCount, 1);\n assert.isTrue(processingStartedSpy.calledOnce);\n assert.isTrue(loadingCompleteSpy.calledOnce);\n\n // Get the arguments of the first (and only) call to the loadingComplete\n // function. TS doesn't know what the types are (they are [any, any] by\n // default), so we tell it that they align with the types of the\n // loadingComplete parameters.\n const [collectedEvents, /* exclusiveFilter */, isCpuProfile] =\n loadingCompleteSpy.args[0] as Parameters;\n // We create fake trace event for CPU profile, includes one for TracingStartedInPage,\n // one for metadata, one for root, and one for CPU profile\n assert.lengthOf(collectedEvents, 4);\n assert.isTrue(isCpuProfile);\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineMiniMap.d.ts b/public/panels/timeline/TimelineMiniMap.d.ts index f54747a8d..32aecb7bb 100644 --- a/public/panels/timeline/TimelineMiniMap.d.ts +++ b/public/panels/timeline/TimelineMiniMap.d.ts @@ -1,11 +1,11 @@ import * as Common from '../../core/common/common.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; import * as UI from '../../ui/legacy/legacy.js'; import * as TimelineComponents from './components/components.js'; import { type TimelineEventOverview } from './TimelineEventOverview.js'; export interface OverviewData { - traceParsedData: TraceEngine.Handlers.Types.TraceParseData; + parsedTrace: Trace.Handlers.Types.ParsedTrace; isCpuProfile?: boolean; settings: { showScreenshots: boolean; @@ -34,6 +34,8 @@ export declare class TimelineMiniMap extends TimelineMiniMap_base { breadcrumbs: TimelineComponents.Breadcrumbs.Breadcrumbs | null; constructor(); addBreadcrumb({ startTime, endTime }: PerfUI.TimelineOverviewPane.OverviewPaneBreadcrumbAddedEvent): void; + highlightBounds(bounds: Trace.Types.Timing.TraceWindowMicroSeconds): void; + clearBoundsHighlight(): void; wasShown(): void; reset(): void; getControls(): TimelineEventOverview[]; diff --git a/public/panels/timeline/TimelineMiniMap.js b/public/panels/timeline/TimelineMiniMap.js index bac171a1d..6681bb125 100644 --- a/public/panels/timeline/TimelineMiniMap.js +++ b/public/panels/timeline/TimelineMiniMap.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as Common from '../../core/common/common.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as TraceBounds from '../../services/trace_bounds/trace_bounds.js'; import * as IconButton from '../../ui/components/icon_button/icon_button.js'; import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; @@ -55,8 +55,8 @@ export class TimelineMiniMap extends Common.ObjectWrapper.eventMixin(UI.Widget.V TraceBounds.TraceBounds.onChange(this.#onTraceBoundsChangeBound); } #onOverviewPanelWindowChanged(event) { - const traceData = this.#data?.traceParsedData; - if (!traceData) { + const parsedTrace = this.#data?.parsedTrace; + if (!parsedTrace) { return; } const traceBoundsState = TraceBounds.TraceBounds.BoundsManager.instance().state(); @@ -65,7 +65,7 @@ export class TimelineMiniMap extends Common.ObjectWrapper.eventMixin(UI.Widget.V } const left = (event.data.startTime > 0) ? event.data.startTime : traceBoundsState.milli.entireTraceBounds.min; const right = Number.isFinite(event.data.endTime) ? event.data.endTime : traceBoundsState.milli.entireTraceBounds.max; - TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(TraceEngine.Helpers.Timing.traceWindowFromMilliSeconds(TraceEngine.Types.Timing.MilliSeconds(left), TraceEngine.Types.Timing.MilliSeconds(right)), { + TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(Trace.Helpers.Timing.traceWindowFromMilliSeconds(Trace.Types.Timing.MilliSeconds(left), Trace.Types.Timing.MilliSeconds(right)), { shouldAnimate: true, }); } @@ -79,7 +79,7 @@ export class TimelineMiniMap extends Common.ObjectWrapper.eventMixin(UI.Widget.V // applies if the user has created breadcrumbs, which scope the // minimap. If they have not, the entire trace is the minimap, and // therefore there is no work to be done. - const newWindowFitsBounds = TraceEngine.Helpers.Timing.windowFitsInsideBounds({ + const newWindowFitsBounds = Trace.Helpers.Timing.windowFitsInsideBounds({ window: event.state.micro.timelineTraceWindow, bounds: event.state.micro.minimapTraceBounds, }); @@ -102,7 +102,7 @@ export class TimelineMiniMap extends Common.ObjectWrapper.eventMixin(UI.Widget.V let currentBreadcrumb = this.breadcrumbs.initialBreadcrumb; let lastBreadcrumbThatFits = this.breadcrumbs.initialBreadcrumb; while (currentBreadcrumb) { - const fits = TraceEngine.Helpers.Timing.windowFitsInsideBounds({ + const fits = Trace.Helpers.Timing.windowFitsInsideBounds({ window: newWindow, bounds: currentBreadcrumb.window, }); @@ -135,16 +135,22 @@ export class TimelineMiniMap extends Common.ObjectWrapper.eventMixin(UI.Widget.V // this case we change them to be the min and max values of the minimap // bounds. const breadcrumbTimes = { - startTime: TraceEngine.Types.Timing.MilliSeconds(Math.max(startTime, bounds.min)), - endTime: TraceEngine.Types.Timing.MilliSeconds(Math.min(endTime, bounds.max)), + startTime: Trace.Types.Timing.MilliSeconds(Math.max(startTime, bounds.min)), + endTime: Trace.Types.Timing.MilliSeconds(Math.min(endTime, bounds.max)), }; - const newVisibleTraceWindow = TraceEngine.Helpers.Timing.traceWindowFromMilliSeconds(breadcrumbTimes.startTime, breadcrumbTimes.endTime); + const newVisibleTraceWindow = Trace.Helpers.Timing.traceWindowFromMilliSeconds(breadcrumbTimes.startTime, breadcrumbTimes.endTime); const addedBreadcrumb = this.breadcrumbs.add(newVisibleTraceWindow); this.#breadcrumbsUI.data = { initialBreadcrumb: this.breadcrumbs.initialBreadcrumb, activeBreadcrumb: addedBreadcrumb, }; } + highlightBounds(bounds) { + this.#overviewComponent.highlightBounds(bounds); + } + clearBoundsHighlight() { + this.#overviewComponent.clearBoundsHighlight(); + } /** * Activates a given breadcrumb. * @param options.removeChildBreadcrumbs - if true, any child breadcrumbs will be removed. @@ -169,48 +175,48 @@ export class TimelineMiniMap extends Common.ObjectWrapper.eventMixin(UI.Widget.V this.#data = null; this.#overviewComponent.reset(); } - #setMarkers(traceParsedData) { + #setMarkers(parsedTrace) { const markers = new Map(); - const { Meta, PageLoadMetrics } = traceParsedData; + const { Meta, PageLoadMetrics } = parsedTrace; // Add markers for navigation start times. const navStartEvents = Meta.mainFrameNavigations; - const minTimeInMilliseconds = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(Meta.traceBounds.min); + const minTimeInMilliseconds = Trace.Helpers.Timing.microSecondsToMilliseconds(Meta.traceBounds.min); for (const event of navStartEvents) { - const { startTime } = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event); + const { startTime } = Trace.Helpers.Timing.eventTimingsMilliSeconds(event); markers.set(startTime, TimelineUIUtils.createEventDivider(event, minTimeInMilliseconds)); } // Now add markers for the page load events for (const event of PageLoadMetrics.allMarkerEvents) { - const { startTime } = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event); + const { startTime } = Trace.Helpers.Timing.eventTimingsMilliSeconds(event); markers.set(startTime, TimelineUIUtils.createEventDivider(event, minTimeInMilliseconds)); } this.#overviewComponent.setMarkers(markers); } - #setNavigationStartEvents(traceParsedData) { - this.#overviewComponent.setNavStartTimes(traceParsedData.Meta.mainFrameNavigations); + #setNavigationStartEvents(parsedTrace) { + this.#overviewComponent.setNavStartTimes(parsedTrace.Meta.mainFrameNavigations); } getControls() { return this.#controls; } setData(data) { - if (this.#data?.traceParsedData === data.traceParsedData) { + if (this.#data?.parsedTrace === data.parsedTrace) { return; } this.#data = data; this.#controls = []; - this.#setMarkers(data.traceParsedData); - this.#setNavigationStartEvents(data.traceParsedData); - this.#controls.push(new TimelineEventOverviewResponsiveness(data.traceParsedData)); - this.#controls.push(new TimelineEventOverviewCPUActivity(data.traceParsedData)); - this.#controls.push(new TimelineEventOverviewNetwork(data.traceParsedData)); + this.#setMarkers(data.parsedTrace); + this.#setNavigationStartEvents(data.parsedTrace); + this.#controls.push(new TimelineEventOverviewResponsiveness(data.parsedTrace)); + this.#controls.push(new TimelineEventOverviewCPUActivity(data.parsedTrace)); + this.#controls.push(new TimelineEventOverviewNetwork(data.parsedTrace)); if (data.settings.showScreenshots) { - const filmStrip = TraceEngine.Extras.FilmStrip.fromTraceData(data.traceParsedData); + const filmStrip = Trace.Extras.FilmStrip.fromParsedTrace(data.parsedTrace); if (filmStrip.frames.length) { this.#controls.push(new TimelineFilmStripOverview(filmStrip)); } } if (data.settings.showMemory) { - this.#controls.push(new TimelineEventOverviewMemory(data.traceParsedData)); + this.#controls.push(new TimelineEventOverviewMemory(data.parsedTrace)); } this.#overviewComponent.setOverviewControls(this.#controls); this.#overviewComponent.showingScreenshots = data.settings.showScreenshots; diff --git a/public/panels/timeline/TimelineMiniMap.js.map b/public/panels/timeline/TimelineMiniMap.js.map index 5253b147c..6e9e1fa96 100644 --- a/public/panels/timeline/TimelineMiniMap.js.map +++ b/public/panels/timeline/TimelineMiniMap.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineMiniMap.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineMiniMap.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as TraceBounds from '../../services/trace_bounds/trace_bounds.js';\nimport * as IconButton from '../../ui/components/icon_button/icon_button.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport * as TimelineComponents from './components/components.js';\nimport {ModificationsManager} from './ModificationsManager.js';\nimport {\n type TimelineEventOverview,\n TimelineEventOverviewCPUActivity,\n TimelineEventOverviewMemory,\n TimelineEventOverviewNetwork,\n TimelineEventOverviewResponsiveness,\n TimelineFilmStripOverview,\n} from './TimelineEventOverview.js';\nimport miniMapStyles from './timelineMiniMap.css.js';\nimport {TimelineUIUtils} from './TimelineUIUtils.js';\n\nexport interface OverviewData {\n traceParsedData: TraceEngine.Handlers.Types.TraceParseData;\n isCpuProfile?: boolean;\n settings: {\n showScreenshots: boolean,\n showMemory: boolean,\n };\n}\n\n/**\n * This component wraps the generic PerfUI Overview component and configures it\n * specifically for the Performance Panel, including injecting the CSS we use\n * to customise how the components render within the Performance Panel.\n *\n * It is also responsible for listening to events from the OverviewPane to\n * update the visible trace window, and when this happens it will update the\n * TraceBounds service with the new values.\n */\nexport class TimelineMiniMap extends\n Common.ObjectWrapper.eventMixin(UI.Widget.VBox) {\n #overviewComponent = new PerfUI.TimelineOverviewPane.TimelineOverviewPane('timeline');\n #controls: TimelineEventOverview[] = [];\n breadcrumbs: TimelineComponents.Breadcrumbs.Breadcrumbs|null = null;\n #breadcrumbsUI: TimelineComponents.BreadcrumbsUI.BreadcrumbsUI;\n #data: OverviewData|null = null;\n\n #onTraceBoundsChangeBound = this.#onTraceBoundsChange.bind(this);\n\n constructor() {\n super();\n this.element.classList.add('timeline-minimap');\n this.#breadcrumbsUI = new TimelineComponents.BreadcrumbsUI.BreadcrumbsUI();\n this.element.prepend(this.#breadcrumbsUI);\n\n const icon = new IconButton.Icon.Icon();\n icon.setAttribute('name', 'left-panel-open');\n icon.setAttribute('jslog', `${VisualLogging.action('timeline.sidebar-open').track({click: true})}`);\n icon.addEventListener('click', () => {\n this.dispatchEventToListeners(PerfUI.TimelineOverviewPane.Events.OPEN_SIDEBAR_BUTTON_CLICKED, {});\n });\n this.#overviewComponent.show(this.element);\n\n this.#overviewComponent.addEventListener(PerfUI.TimelineOverviewPane.Events.OVERVIEW_PANE_WINDOW_CHANGED, event => {\n this.#onOverviewPanelWindowChanged(event);\n });\n this.#overviewComponent.addEventListener(\n PerfUI.TimelineOverviewPane.Events.OVERVIEW_PANE_BREADCRUMB_ADDED, event => {\n this.addBreadcrumb(event.data);\n });\n\n this.#breadcrumbsUI.addEventListener(TimelineComponents.BreadcrumbsUI.BreadcrumbActivatedEvent.eventName, event => {\n const {breadcrumb, childBreadcrumbsRemoved} =\n (event as TimelineComponents.BreadcrumbsUI.BreadcrumbActivatedEvent);\n this.#activateBreadcrumb(\n breadcrumb, {removeChildBreadcrumbs: Boolean(childBreadcrumbsRemoved), updateVisibleWindow: true});\n });\n this.#overviewComponent.enableCreateBreadcrumbsButton();\n\n TraceBounds.TraceBounds.onChange(this.#onTraceBoundsChangeBound);\n }\n\n #onOverviewPanelWindowChanged(\n event: Common.EventTarget.EventTargetEvent): void {\n const traceData = this.#data?.traceParsedData;\n if (!traceData) {\n return;\n }\n\n const traceBoundsState = TraceBounds.TraceBounds.BoundsManager.instance().state();\n if (!traceBoundsState) {\n return;\n }\n\n const left = (event.data.startTime > 0) ? event.data.startTime : traceBoundsState.milli.entireTraceBounds.min;\n const right =\n Number.isFinite(event.data.endTime) ? event.data.endTime : traceBoundsState.milli.entireTraceBounds.max;\n\n TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(\n TraceEngine.Helpers.Timing.traceWindowFromMilliSeconds(\n TraceEngine.Types.Timing.MilliSeconds(left),\n TraceEngine.Types.Timing.MilliSeconds(right),\n ),\n {\n shouldAnimate: true,\n },\n );\n }\n\n #onTraceBoundsChange(event: TraceBounds.TraceBounds.StateChangedEvent): void {\n if (event.updateType === 'RESET' || event.updateType === 'VISIBLE_WINDOW') {\n this.#overviewComponent.setWindowTimes(\n event.state.milli.timelineTraceWindow.min, event.state.milli.timelineTraceWindow.max);\n\n // If the visible window has changed because we are revealing a certain\n // time period to the user, we need to ensure that this new time\n // period fits within the current minimap bounds. If it doesn't, we\n // do some work to update the minimap bounds. Note that this only\n // applies if the user has created breadcrumbs, which scope the\n // minimap. If they have not, the entire trace is the minimap, and\n // therefore there is no work to be done.\n const newWindowFitsBounds = TraceEngine.Helpers.Timing.windowFitsInsideBounds({\n window: event.state.micro.timelineTraceWindow,\n bounds: event.state.micro.minimapTraceBounds,\n });\n\n if (!newWindowFitsBounds) {\n this.#updateMiniMapBoundsToFitNewWindow(event.state.micro.timelineTraceWindow);\n }\n }\n if (event.updateType === 'RESET' || event.updateType === 'MINIMAP_BOUNDS') {\n this.#overviewComponent.setBounds(\n event.state.milli.minimapTraceBounds.min, event.state.milli.minimapTraceBounds.max);\n }\n }\n\n #updateMiniMapBoundsToFitNewWindow(newWindow: TraceEngine.Types.Timing.TraceWindowMicroSeconds): void {\n if (!this.breadcrumbs) {\n return;\n }\n // Find the smallest breadcrumb that fits this window.\n // Breadcrumbs are a linked list from largest to smallest so we have to\n // walk through until we find one that does not fit, and pick the last\n // before that.\n let currentBreadcrumb: TraceEngine.Types.File.Breadcrumb|null = this.breadcrumbs.initialBreadcrumb;\n let lastBreadcrumbThatFits: TraceEngine.Types.File.Breadcrumb = this.breadcrumbs.initialBreadcrumb;\n\n while (currentBreadcrumb) {\n const fits = TraceEngine.Helpers.Timing.windowFitsInsideBounds({\n window: newWindow,\n bounds: currentBreadcrumb.window,\n });\n if (fits) {\n lastBreadcrumbThatFits = currentBreadcrumb;\n } else {\n // If this breadcrumb does not fit, none of its children (which are all\n // smaller by definition) will, so we can exit the loop early.\n break;\n }\n currentBreadcrumb = currentBreadcrumb.child;\n }\n\n // Activate the breadcrumb that fits the visible window. We do not update\n // the visible window here as we are doing this work as a reaction to\n // something else triggering a change in the window visibility.\n this.#activateBreadcrumb(lastBreadcrumbThatFits, {removeChildBreadcrumbs: false, updateVisibleWindow: false});\n }\n\n addBreadcrumb({startTime, endTime}: PerfUI.TimelineOverviewPane.OverviewPaneBreadcrumbAddedEvent): void {\n if (!this.breadcrumbs) {\n console.warn('ModificationsManager has not been created, therefore Breadcrumbs can not be added');\n return;\n }\n const traceBoundsState = TraceBounds.TraceBounds.BoundsManager.instance().state();\n if (!traceBoundsState) {\n return;\n }\n const bounds = traceBoundsState.milli.minimapTraceBounds;\n\n // The OverviewPane can emit 0 and Infinity as numbers for the range; in\n // this case we change them to be the min and max values of the minimap\n // bounds.\n const breadcrumbTimes = {\n startTime: TraceEngine.Types.Timing.MilliSeconds(Math.max(startTime, bounds.min)),\n endTime: TraceEngine.Types.Timing.MilliSeconds(Math.min(endTime, bounds.max)),\n };\n\n const newVisibleTraceWindow =\n TraceEngine.Helpers.Timing.traceWindowFromMilliSeconds(breadcrumbTimes.startTime, breadcrumbTimes.endTime);\n\n const addedBreadcrumb = this.breadcrumbs.add(newVisibleTraceWindow);\n\n this.#breadcrumbsUI.data = {\n initialBreadcrumb: this.breadcrumbs.initialBreadcrumb,\n activeBreadcrumb: addedBreadcrumb,\n };\n }\n\n /**\n * Activates a given breadcrumb.\n * @param options.removeChildBreadcrumbs - if true, any child breadcrumbs will be removed.\n * @param options.updateVisibleWindow - if true, the visible window will be updated to match the bounds of the breadcrumb\n */\n #activateBreadcrumb(\n breadcrumb: TraceEngine.Types.File.Breadcrumb,\n options: TimelineComponents.Breadcrumbs.SetActiveBreadcrumbOptions): void {\n if (!this.breadcrumbs) {\n return;\n }\n\n this.breadcrumbs.setActiveBreadcrumb(breadcrumb, options);\n // Only the initial breadcrumb is passed in because breadcrumbs are stored in a linked list and breadcrumbsUI component iterates through them\n this.#breadcrumbsUI.data = {\n initialBreadcrumb: this.breadcrumbs.initialBreadcrumb,\n activeBreadcrumb: breadcrumb,\n };\n }\n\n override wasShown(): void {\n super.wasShown();\n this.registerCSSFiles([miniMapStyles]);\n }\n\n reset(): void {\n this.#data = null;\n this.#overviewComponent.reset();\n }\n\n #setMarkers(traceParsedData: TraceEngine.Handlers.Types.TraceParseData): void {\n const markers = new Map();\n\n const {Meta, PageLoadMetrics} = traceParsedData;\n\n // Add markers for navigation start times.\n const navStartEvents = Meta.mainFrameNavigations;\n const minTimeInMilliseconds = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(Meta.traceBounds.min);\n\n for (const event of navStartEvents) {\n const {startTime} = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event);\n markers.set(startTime, TimelineUIUtils.createEventDivider(event, minTimeInMilliseconds));\n }\n\n // Now add markers for the page load events\n for (const event of PageLoadMetrics.allMarkerEvents) {\n const {startTime} = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event);\n markers.set(startTime, TimelineUIUtils.createEventDivider(event, minTimeInMilliseconds));\n }\n\n this.#overviewComponent.setMarkers(markers);\n }\n\n #setNavigationStartEvents(traceParsedData: TraceEngine.Handlers.Types.TraceParseData): void {\n this.#overviewComponent.setNavStartTimes(traceParsedData.Meta.mainFrameNavigations);\n }\n\n getControls(): TimelineEventOverview[] {\n return this.#controls;\n }\n\n setData(data: OverviewData): void {\n if (this.#data?.traceParsedData === data.traceParsedData) {\n return;\n }\n this.#data = data;\n this.#controls = [];\n\n this.#setMarkers(data.traceParsedData);\n this.#setNavigationStartEvents(data.traceParsedData);\n this.#controls.push(new TimelineEventOverviewResponsiveness(data.traceParsedData));\n this.#controls.push(new TimelineEventOverviewCPUActivity(data.traceParsedData));\n\n this.#controls.push(new TimelineEventOverviewNetwork(data.traceParsedData));\n if (data.settings.showScreenshots) {\n const filmStrip = TraceEngine.Extras.FilmStrip.fromTraceData(data.traceParsedData);\n if (filmStrip.frames.length) {\n this.#controls.push(new TimelineFilmStripOverview(filmStrip));\n }\n }\n if (data.settings.showMemory) {\n this.#controls.push(new TimelineEventOverviewMemory(data.traceParsedData));\n }\n this.#overviewComponent.setOverviewControls(this.#controls);\n this.#overviewComponent.showingScreenshots = data.settings.showScreenshots;\n this.#setInitialBreadcrumb();\n }\n\n #setInitialBreadcrumb(): void {\n // Set the initial breadcrumb that ModificationsManager created from the initial full window\n // or loaded from the file.\n this.breadcrumbs = ModificationsManager.activeManager()?.getTimelineBreadcrumbs() ?? null;\n\n if (!this.breadcrumbs) {\n return;\n }\n\n let lastBreadcrumb = this.breadcrumbs.initialBreadcrumb;\n while (lastBreadcrumb.child !== null) {\n lastBreadcrumb = lastBreadcrumb.child;\n }\n\n this.#breadcrumbsUI.data = {\n initialBreadcrumb: this.breadcrumbs.initialBreadcrumb,\n activeBreadcrumb: lastBreadcrumb,\n };\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"TimelineMiniMap.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineMiniMap.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,MAAM,MAAM,6BAA6B,CAAC;AACtD,OAAO,KAAK,KAAK,MAAM,6BAA6B,CAAC;AACrD,OAAO,KAAK,WAAW,MAAM,6CAA6C,CAAC;AAC3E,OAAO,KAAK,UAAU,MAAM,gDAAgD,CAAC;AAC7E,OAAO,KAAK,MAAM,MAAM,+CAA+C,CAAC;AACxE,OAAO,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAChD,OAAO,KAAK,aAAa,MAAM,2CAA2C,CAAC;AAE3E,OAAO,KAAK,kBAAkB,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAC,oBAAoB,EAAC,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAEL,gCAAgC,EAChC,2BAA2B,EAC3B,4BAA4B,EAC5B,mCAAmC,EACnC,yBAAyB,GAC1B,MAAM,4BAA4B,CAAC;AACpC,OAAO,aAAa,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAC,eAAe,EAAC,MAAM,sBAAsB,CAAC;AAWrD;;;;;;;;GAQG;AACH,MAAM,OAAO,eAAgB,SACzB,MAAM,CAAC,aAAa,CAAC,UAAU,CAAgE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC;IAChH,kBAAkB,GAAG,IAAI,MAAM,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,UAAU,CAAC,CAAC;IACtF,SAAS,GAA4B,EAAE,CAAC;IACxC,WAAW,GAAoD,IAAI,CAAC;IACpE,cAAc,CAAiD;IAC/D,KAAK,GAAsB,IAAI,CAAC;IAEhC,yBAAyB,GAAG,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEjE;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;QAC/C,IAAI,CAAC,cAAc,GAAG,IAAI,kBAAkB,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC;QAC3E,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAE1C,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACxC,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;QAC7C,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,GAAG,aAAa,CAAC,MAAM,CAAC,uBAAuB,CAAC,CAAC,KAAK,CAAC,EAAC,KAAK,EAAE,IAAI,EAAC,CAAC,EAAE,CAAC,CAAC;QACpG,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE;YAClC,IAAI,CAAC,wBAAwB,kGAAiE,EAAE,CAAC,CAAC;QACpG,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAE3C,IAAI,CAAC,kBAAkB,CAAC,gBAAgB,oGAAkE,KAAK,CAAC,EAAE;YAChH,IAAI,CAAC,6BAA6B,CAAC,KAAK,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,kBAAkB,CAAC,gBAAgB,wGAC+B,KAAK,CAAC,EAAE;YACzE,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QAEP,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,aAAa,CAAC,wBAAwB,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE;YAChH,MAAM,EAAC,UAAU,EAAE,uBAAuB,EAAC,GACtC,KAAmE,CAAC;YACzE,IAAI,CAAC,mBAAmB,CACpB,UAAU,EAAE,EAAC,sBAAsB,EAAE,OAAO,CAAC,uBAAuB,CAAC,EAAE,mBAAmB,EAAE,IAAI,EAAC,CAAC,CAAC;QACzG,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,kBAAkB,CAAC,6BAA6B,EAAE,CAAC;QAExD,WAAW,CAAC,WAAW,CAAC,QAAQ,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IACnE,CAAC;IAED,6BAA6B,CACzB,KAAsG;QACxG,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,EAAE,WAAW,CAAC;QAC5C,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QAED,MAAM,gBAAgB,GAAG,WAAW,CAAC,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC;QAClF,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,KAAK,CAAC,iBAAiB,CAAC,GAAG,CAAC;QAC9G,MAAM,KAAK,GACP,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC,KAAK,CAAC,iBAAiB,CAAC,GAAG,CAAC;QAE5G,WAAW,CAAC,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,wBAAwB,CACrE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,2BAA2B,CAC5C,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,EACrC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,KAAK,CAAC,CACrC,EACL;YACE,aAAa,EAAE,IAAI;SACpB,CACJ,CAAC;IACJ,CAAC;IAED,oBAAoB,CAAC,KAAgD;QACnE,IAAI,KAAK,CAAC,UAAU,KAAK,OAAO,IAAI,KAAK,CAAC,UAAU,KAAK,gBAAgB,EAAE,CAAC;YAC1E,IAAI,CAAC,kBAAkB,CAAC,cAAc,CAClC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,mBAAmB,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC;YAE1F,uEAAuE;YACvE,gEAAgE;YAChE,mEAAmE;YACnE,iEAAiE;YACjE,+DAA+D;YAC/D,kEAAkE;YAClE,yCAAyC;YACzC,MAAM,mBAAmB,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,sBAAsB,CAAC;gBACtE,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,mBAAmB;gBAC7C,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,kBAAkB;aAC7C,CAAC,CAAC;YAEH,IAAI,CAAC,mBAAmB,EAAE,CAAC;gBACzB,IAAI,CAAC,kCAAkC,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC;YACjF,CAAC;QACH,CAAC;QACD,IAAI,KAAK,CAAC,UAAU,KAAK,OAAO,IAAI,KAAK,CAAC,UAAU,KAAK,gBAAgB,EAAE,CAAC;YAC1E,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAC7B,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC;QAC1F,CAAC;IACH,CAAC;IAED,kCAAkC,CAAC,SAAqD;QACtF,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QACD,sDAAsD;QACtD,uEAAuE;QACvE,sEAAsE;QACtE,eAAe;QACf,IAAI,iBAAiB,GAAqC,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC;QAC7F,IAAI,sBAAsB,GAAgC,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC;QAE7F,OAAO,iBAAiB,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,sBAAsB,CAAC;gBACvD,MAAM,EAAE,SAAS;gBACjB,MAAM,EAAE,iBAAiB,CAAC,MAAM;aACjC,CAAC,CAAC;YACH,IAAI,IAAI,EAAE,CAAC;gBACT,sBAAsB,GAAG,iBAAiB,CAAC;YAC7C,CAAC;iBAAM,CAAC;gBACN,uEAAuE;gBACvE,8DAA8D;gBAC9D,MAAM;YACR,CAAC;YACD,iBAAiB,GAAG,iBAAiB,CAAC,KAAK,CAAC;QAC9C,CAAC;QAED,yEAAyE;QACzE,qEAAqE;QACrE,+DAA+D;QAC/D,IAAI,CAAC,mBAAmB,CAAC,sBAAsB,EAAE,EAAC,sBAAsB,EAAE,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAC,CAAC,CAAC;IAChH,CAAC;IAED,aAAa,CAAC,EAAC,SAAS,EAAE,OAAO,EAA+D;QAC9F,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,OAAO,CAAC,IAAI,CAAC,mFAAmF,CAAC,CAAC;YAClG,OAAO;QACT,CAAC;QACD,MAAM,gBAAgB,GAAG,WAAW,CAAC,WAAW,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,CAAC;QAClF,IAAI,CAAC,gBAAgB,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,CAAC,kBAAkB,CAAC;QAEzD,wEAAwE;QACxE,uEAAuE;QACvE,UAAU;QACV,MAAM,eAAe,GAAG;YACtB,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;YAC3E,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;SACxE,CAAC;QAEF,MAAM,qBAAqB,GACvB,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,2BAA2B,CAAC,eAAe,CAAC,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC;QAEzG,MAAM,eAAe,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QAEpE,IAAI,CAAC,cAAc,CAAC,IAAI,GAAG;YACzB,iBAAiB,EAAE,IAAI,CAAC,WAAW,CAAC,iBAAiB;YACrD,gBAAgB,EAAE,eAAe;SAClC,CAAC;IACJ,CAAC;IAED,eAAe,CAAC,MAAkD;QAChE,IAAI,CAAC,kBAAkB,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IAClD,CAAC;IACD,oBAAoB;QAClB,IAAI,CAAC,kBAAkB,CAAC,oBAAoB,EAAE,CAAC;IACjD,CAAC;IAED;;;;OAIG;IACH,mBAAmB,CACf,UAAuC,EACvC,OAAkE;QACpE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QAED,IAAI,CAAC,WAAW,CAAC,mBAAmB,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC1D,6IAA6I;QAC7I,IAAI,CAAC,cAAc,CAAC,IAAI,GAAG;YACzB,iBAAiB,EAAE,IAAI,CAAC,WAAW,CAAC,iBAAiB;YACrD,gBAAgB,EAAE,UAAU;SAC7B,CAAC;IACJ,CAAC;IAEQ,QAAQ;QACf,KAAK,CAAC,QAAQ,EAAE,CAAC;QACjB,IAAI,CAAC,gBAAgB,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;IACzC,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC;IAClC,CAAC;IAED,WAAW,CAAC,WAA6C;QACvD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAmB,CAAC;QAE3C,MAAM,EAAC,IAAI,EAAE,eAAe,EAAC,GAAG,WAAW,CAAC;QAE5C,0CAA0C;QAC1C,MAAM,cAAc,GAAG,IAAI,CAAC,oBAAoB,CAAC;QACjD,MAAM,qBAAqB,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QAEpG,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;YACnC,MAAM,EAAC,SAAS,EAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAAC;YACzE,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,eAAe,CAAC,kBAAkB,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC,CAAC;QAC3F,CAAC;QAED,2CAA2C;QAC3C,KAAK,MAAM,KAAK,IAAI,eAAe,CAAC,eAAe,EAAE,CAAC;YACpD,MAAM,EAAC,SAAS,EAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAAC;YACzE,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,eAAe,CAAC,kBAAkB,CAAC,KAAK,EAAE,qBAAqB,CAAC,CAAC,CAAC;QAC3F,CAAC;QAED,IAAI,CAAC,kBAAkB,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IAC9C,CAAC;IAED,yBAAyB,CAAC,WAA6C;QACrE,IAAI,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,WAAW,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAClF,CAAC;IAED,WAAW;QACT,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,OAAO,CAAC,IAAkB;QACxB,IAAI,IAAI,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC,WAAW,EAAE,CAAC;YACjD,OAAO;QACT,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;QAEpB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACnC,IAAI,CAAC,yBAAyB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACjD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,mCAAmC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;QAC/E,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,gCAAgC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;QAE5E,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,4BAA4B,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;QACxE,IAAI,IAAI,CAAC,QAAQ,CAAC,eAAe,EAAE,CAAC;YAClC,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC3E,IAAI,SAAS,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;gBAC5B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,yBAAyB,CAAC,SAAS,CAAC,CAAC,CAAC;YAChE,CAAC;QACH,CAAC;QACD,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;YAC7B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,2BAA2B,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;QACzE,CAAC;QACD,IAAI,CAAC,kBAAkB,CAAC,mBAAmB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC5D,IAAI,CAAC,kBAAkB,CAAC,kBAAkB,GAAG,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC;QAC3E,IAAI,CAAC,qBAAqB,EAAE,CAAC;IAC/B,CAAC;IAED,qBAAqB;QACnB,4FAA4F;QAC5F,2BAA2B;QAC3B,IAAI,CAAC,WAAW,GAAG,oBAAoB,CAAC,aAAa,EAAE,EAAE,sBAAsB,EAAE,IAAI,IAAI,CAAC;QAE1F,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QAED,IAAI,cAAc,GAAG,IAAI,CAAC,WAAW,CAAC,iBAAiB,CAAC;QACxD,OAAO,cAAc,CAAC,KAAK,KAAK,IAAI,EAAE,CAAC;YACrC,cAAc,GAAG,cAAc,CAAC,KAAK,CAAC;QACxC,CAAC;QAED,IAAI,CAAC,cAAc,CAAC,IAAI,GAAG;YACzB,iBAAiB,EAAE,IAAI,CAAC,WAAW,CAAC,iBAAiB;YACrD,gBAAgB,EAAE,cAAc;SACjC,CAAC;IACJ,CAAC;CACF","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as TraceBounds from '../../services/trace_bounds/trace_bounds.js';\nimport * as IconButton from '../../ui/components/icon_button/icon_button.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport * as TimelineComponents from './components/components.js';\nimport {ModificationsManager} from './ModificationsManager.js';\nimport {\n type TimelineEventOverview,\n TimelineEventOverviewCPUActivity,\n TimelineEventOverviewMemory,\n TimelineEventOverviewNetwork,\n TimelineEventOverviewResponsiveness,\n TimelineFilmStripOverview,\n} from './TimelineEventOverview.js';\nimport miniMapStyles from './timelineMiniMap.css.js';\nimport {TimelineUIUtils} from './TimelineUIUtils.js';\n\nexport interface OverviewData {\n parsedTrace: Trace.Handlers.Types.ParsedTrace;\n isCpuProfile?: boolean;\n settings: {\n showScreenshots: boolean,\n showMemory: boolean,\n };\n}\n\n/**\n * This component wraps the generic PerfUI Overview component and configures it\n * specifically for the Performance Panel, including injecting the CSS we use\n * to customise how the components render within the Performance Panel.\n *\n * It is also responsible for listening to events from the OverviewPane to\n * update the visible trace window, and when this happens it will update the\n * TraceBounds service with the new values.\n */\nexport class TimelineMiniMap extends\n Common.ObjectWrapper.eventMixin(UI.Widget.VBox) {\n #overviewComponent = new PerfUI.TimelineOverviewPane.TimelineOverviewPane('timeline');\n #controls: TimelineEventOverview[] = [];\n breadcrumbs: TimelineComponents.Breadcrumbs.Breadcrumbs|null = null;\n #breadcrumbsUI: TimelineComponents.BreadcrumbsUI.BreadcrumbsUI;\n #data: OverviewData|null = null;\n\n #onTraceBoundsChangeBound = this.#onTraceBoundsChange.bind(this);\n\n constructor() {\n super();\n this.element.classList.add('timeline-minimap');\n this.#breadcrumbsUI = new TimelineComponents.BreadcrumbsUI.BreadcrumbsUI();\n this.element.prepend(this.#breadcrumbsUI);\n\n const icon = new IconButton.Icon.Icon();\n icon.setAttribute('name', 'left-panel-open');\n icon.setAttribute('jslog', `${VisualLogging.action('timeline.sidebar-open').track({click: true})}`);\n icon.addEventListener('click', () => {\n this.dispatchEventToListeners(PerfUI.TimelineOverviewPane.Events.OPEN_SIDEBAR_BUTTON_CLICKED, {});\n });\n this.#overviewComponent.show(this.element);\n\n this.#overviewComponent.addEventListener(PerfUI.TimelineOverviewPane.Events.OVERVIEW_PANE_WINDOW_CHANGED, event => {\n this.#onOverviewPanelWindowChanged(event);\n });\n this.#overviewComponent.addEventListener(\n PerfUI.TimelineOverviewPane.Events.OVERVIEW_PANE_BREADCRUMB_ADDED, event => {\n this.addBreadcrumb(event.data);\n });\n\n this.#breadcrumbsUI.addEventListener(TimelineComponents.BreadcrumbsUI.BreadcrumbActivatedEvent.eventName, event => {\n const {breadcrumb, childBreadcrumbsRemoved} =\n (event as TimelineComponents.BreadcrumbsUI.BreadcrumbActivatedEvent);\n this.#activateBreadcrumb(\n breadcrumb, {removeChildBreadcrumbs: Boolean(childBreadcrumbsRemoved), updateVisibleWindow: true});\n });\n this.#overviewComponent.enableCreateBreadcrumbsButton();\n\n TraceBounds.TraceBounds.onChange(this.#onTraceBoundsChangeBound);\n }\n\n #onOverviewPanelWindowChanged(\n event: Common.EventTarget.EventTargetEvent): void {\n const parsedTrace = this.#data?.parsedTrace;\n if (!parsedTrace) {\n return;\n }\n\n const traceBoundsState = TraceBounds.TraceBounds.BoundsManager.instance().state();\n if (!traceBoundsState) {\n return;\n }\n\n const left = (event.data.startTime > 0) ? event.data.startTime : traceBoundsState.milli.entireTraceBounds.min;\n const right =\n Number.isFinite(event.data.endTime) ? event.data.endTime : traceBoundsState.milli.entireTraceBounds.max;\n\n TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(\n Trace.Helpers.Timing.traceWindowFromMilliSeconds(\n Trace.Types.Timing.MilliSeconds(left),\n Trace.Types.Timing.MilliSeconds(right),\n ),\n {\n shouldAnimate: true,\n },\n );\n }\n\n #onTraceBoundsChange(event: TraceBounds.TraceBounds.StateChangedEvent): void {\n if (event.updateType === 'RESET' || event.updateType === 'VISIBLE_WINDOW') {\n this.#overviewComponent.setWindowTimes(\n event.state.milli.timelineTraceWindow.min, event.state.milli.timelineTraceWindow.max);\n\n // If the visible window has changed because we are revealing a certain\n // time period to the user, we need to ensure that this new time\n // period fits within the current minimap bounds. If it doesn't, we\n // do some work to update the minimap bounds. Note that this only\n // applies if the user has created breadcrumbs, which scope the\n // minimap. If they have not, the entire trace is the minimap, and\n // therefore there is no work to be done.\n const newWindowFitsBounds = Trace.Helpers.Timing.windowFitsInsideBounds({\n window: event.state.micro.timelineTraceWindow,\n bounds: event.state.micro.minimapTraceBounds,\n });\n\n if (!newWindowFitsBounds) {\n this.#updateMiniMapBoundsToFitNewWindow(event.state.micro.timelineTraceWindow);\n }\n }\n if (event.updateType === 'RESET' || event.updateType === 'MINIMAP_BOUNDS') {\n this.#overviewComponent.setBounds(\n event.state.milli.minimapTraceBounds.min, event.state.milli.minimapTraceBounds.max);\n }\n }\n\n #updateMiniMapBoundsToFitNewWindow(newWindow: Trace.Types.Timing.TraceWindowMicroSeconds): void {\n if (!this.breadcrumbs) {\n return;\n }\n // Find the smallest breadcrumb that fits this window.\n // Breadcrumbs are a linked list from largest to smallest so we have to\n // walk through until we find one that does not fit, and pick the last\n // before that.\n let currentBreadcrumb: Trace.Types.File.Breadcrumb|null = this.breadcrumbs.initialBreadcrumb;\n let lastBreadcrumbThatFits: Trace.Types.File.Breadcrumb = this.breadcrumbs.initialBreadcrumb;\n\n while (currentBreadcrumb) {\n const fits = Trace.Helpers.Timing.windowFitsInsideBounds({\n window: newWindow,\n bounds: currentBreadcrumb.window,\n });\n if (fits) {\n lastBreadcrumbThatFits = currentBreadcrumb;\n } else {\n // If this breadcrumb does not fit, none of its children (which are all\n // smaller by definition) will, so we can exit the loop early.\n break;\n }\n currentBreadcrumb = currentBreadcrumb.child;\n }\n\n // Activate the breadcrumb that fits the visible window. We do not update\n // the visible window here as we are doing this work as a reaction to\n // something else triggering a change in the window visibility.\n this.#activateBreadcrumb(lastBreadcrumbThatFits, {removeChildBreadcrumbs: false, updateVisibleWindow: false});\n }\n\n addBreadcrumb({startTime, endTime}: PerfUI.TimelineOverviewPane.OverviewPaneBreadcrumbAddedEvent): void {\n if (!this.breadcrumbs) {\n console.warn('ModificationsManager has not been created, therefore Breadcrumbs can not be added');\n return;\n }\n const traceBoundsState = TraceBounds.TraceBounds.BoundsManager.instance().state();\n if (!traceBoundsState) {\n return;\n }\n const bounds = traceBoundsState.milli.minimapTraceBounds;\n\n // The OverviewPane can emit 0 and Infinity as numbers for the range; in\n // this case we change them to be the min and max values of the minimap\n // bounds.\n const breadcrumbTimes = {\n startTime: Trace.Types.Timing.MilliSeconds(Math.max(startTime, bounds.min)),\n endTime: Trace.Types.Timing.MilliSeconds(Math.min(endTime, bounds.max)),\n };\n\n const newVisibleTraceWindow =\n Trace.Helpers.Timing.traceWindowFromMilliSeconds(breadcrumbTimes.startTime, breadcrumbTimes.endTime);\n\n const addedBreadcrumb = this.breadcrumbs.add(newVisibleTraceWindow);\n\n this.#breadcrumbsUI.data = {\n initialBreadcrumb: this.breadcrumbs.initialBreadcrumb,\n activeBreadcrumb: addedBreadcrumb,\n };\n }\n\n highlightBounds(bounds: Trace.Types.Timing.TraceWindowMicroSeconds): void {\n this.#overviewComponent.highlightBounds(bounds);\n }\n clearBoundsHighlight(): void {\n this.#overviewComponent.clearBoundsHighlight();\n }\n\n /**\n * Activates a given breadcrumb.\n * @param options.removeChildBreadcrumbs - if true, any child breadcrumbs will be removed.\n * @param options.updateVisibleWindow - if true, the visible window will be updated to match the bounds of the breadcrumb\n */\n #activateBreadcrumb(\n breadcrumb: Trace.Types.File.Breadcrumb,\n options: TimelineComponents.Breadcrumbs.SetActiveBreadcrumbOptions): void {\n if (!this.breadcrumbs) {\n return;\n }\n\n this.breadcrumbs.setActiveBreadcrumb(breadcrumb, options);\n // Only the initial breadcrumb is passed in because breadcrumbs are stored in a linked list and breadcrumbsUI component iterates through them\n this.#breadcrumbsUI.data = {\n initialBreadcrumb: this.breadcrumbs.initialBreadcrumb,\n activeBreadcrumb: breadcrumb,\n };\n }\n\n override wasShown(): void {\n super.wasShown();\n this.registerCSSFiles([miniMapStyles]);\n }\n\n reset(): void {\n this.#data = null;\n this.#overviewComponent.reset();\n }\n\n #setMarkers(parsedTrace: Trace.Handlers.Types.ParsedTrace): void {\n const markers = new Map();\n\n const {Meta, PageLoadMetrics} = parsedTrace;\n\n // Add markers for navigation start times.\n const navStartEvents = Meta.mainFrameNavigations;\n const minTimeInMilliseconds = Trace.Helpers.Timing.microSecondsToMilliseconds(Meta.traceBounds.min);\n\n for (const event of navStartEvents) {\n const {startTime} = Trace.Helpers.Timing.eventTimingsMilliSeconds(event);\n markers.set(startTime, TimelineUIUtils.createEventDivider(event, minTimeInMilliseconds));\n }\n\n // Now add markers for the page load events\n for (const event of PageLoadMetrics.allMarkerEvents) {\n const {startTime} = Trace.Helpers.Timing.eventTimingsMilliSeconds(event);\n markers.set(startTime, TimelineUIUtils.createEventDivider(event, minTimeInMilliseconds));\n }\n\n this.#overviewComponent.setMarkers(markers);\n }\n\n #setNavigationStartEvents(parsedTrace: Trace.Handlers.Types.ParsedTrace): void {\n this.#overviewComponent.setNavStartTimes(parsedTrace.Meta.mainFrameNavigations);\n }\n\n getControls(): TimelineEventOverview[] {\n return this.#controls;\n }\n\n setData(data: OverviewData): void {\n if (this.#data?.parsedTrace === data.parsedTrace) {\n return;\n }\n this.#data = data;\n this.#controls = [];\n\n this.#setMarkers(data.parsedTrace);\n this.#setNavigationStartEvents(data.parsedTrace);\n this.#controls.push(new TimelineEventOverviewResponsiveness(data.parsedTrace));\n this.#controls.push(new TimelineEventOverviewCPUActivity(data.parsedTrace));\n\n this.#controls.push(new TimelineEventOverviewNetwork(data.parsedTrace));\n if (data.settings.showScreenshots) {\n const filmStrip = Trace.Extras.FilmStrip.fromParsedTrace(data.parsedTrace);\n if (filmStrip.frames.length) {\n this.#controls.push(new TimelineFilmStripOverview(filmStrip));\n }\n }\n if (data.settings.showMemory) {\n this.#controls.push(new TimelineEventOverviewMemory(data.parsedTrace));\n }\n this.#overviewComponent.setOverviewControls(this.#controls);\n this.#overviewComponent.showingScreenshots = data.settings.showScreenshots;\n this.#setInitialBreadcrumb();\n }\n\n #setInitialBreadcrumb(): void {\n // Set the initial breadcrumb that ModificationsManager created from the initial full window\n // or loaded from the file.\n this.breadcrumbs = ModificationsManager.activeManager()?.getTimelineBreadcrumbs() ?? null;\n\n if (!this.breadcrumbs) {\n return;\n }\n\n let lastBreadcrumb = this.breadcrumbs.initialBreadcrumb;\n while (lastBreadcrumb.child !== null) {\n lastBreadcrumb = lastBreadcrumb.child;\n }\n\n this.#breadcrumbsUI.data = {\n initialBreadcrumb: this.breadcrumbs.initialBreadcrumb,\n activeBreadcrumb: lastBreadcrumb,\n };\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineMiniMap.test.js b/public/panels/timeline/TimelineMiniMap.test.js index 4e2832229..a25740bc4 100644 --- a/public/panels/timeline/TimelineMiniMap.test.js +++ b/public/panels/timeline/TimelineMiniMap.test.js @@ -1,7 +1,7 @@ // 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 * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import { raf, renderElementIntoDOM } from '../../testing/DOMHelpers.js'; import { describeWithEnvironment } from '../../testing/EnvironmentHelpers.js'; import { TraceLoader } from '../../testing/TraceLoader.js'; @@ -9,14 +9,14 @@ import * as TimelineComponents from './components/components.js'; import * as Timeline from './timeline.js'; describeWithEnvironment('TimelineMiniMap', function () { it('always shows the responsiveness, CPU activity and network panel', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); const container = document.createElement('div'); renderElementIntoDOM(container); const minimap = new Timeline.TimelineMiniMap.TimelineMiniMap(); minimap.markAsRoot(); minimap.show(container); minimap.setData({ - traceParsedData: traceData, + parsedTrace, settings: { showMemory: false, showScreenshots: false, @@ -31,14 +31,14 @@ describeWithEnvironment('TimelineMiniMap', function () { minimap.detach(); }); it('will show the other panels if they are set to visible', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); const container = document.createElement('div'); renderElementIntoDOM(container); const minimap = new Timeline.TimelineMiniMap.TimelineMiniMap(); minimap.markAsRoot(); minimap.show(container); minimap.setData({ - traceParsedData: traceData, + parsedTrace, settings: { showMemory: true, showScreenshots: true, @@ -53,14 +53,14 @@ describeWithEnvironment('TimelineMiniMap', function () { minimap.detach(); }); it('creates the first breadcrumb', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); const container = document.createElement('div'); renderElementIntoDOM(container); const minimap = new Timeline.TimelineMiniMap.TimelineMiniMap(); minimap.markAsRoot(); minimap.show(container); minimap.setData({ - traceParsedData: traceData, + parsedTrace, settings: { showMemory: true, showScreenshots: true, @@ -71,22 +71,22 @@ describeWithEnvironment('TimelineMiniMap', function () { throw new Error('The MiniMap unexpectedly did not create any breadcrumbs'); } assert.strictEqual(TimelineComponents.Breadcrumbs.flattenBreadcrumbs(minimap.breadcrumbs.initialBreadcrumb).length, 1); - assert.deepEqual(minimap.breadcrumbs.initialBreadcrumb, { window: traceData.Meta.traceBounds, child: null }); + assert.deepEqual(minimap.breadcrumbs.initialBreadcrumb, { window: parsedTrace.Meta.traceBounds, child: null }); }); it('stores breadcrumbs to be serialized', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); const minimap = new Timeline.TimelineMiniMap.TimelineMiniMap(); minimap.setData({ - traceParsedData: traceData, + parsedTrace, settings: { showMemory: true, showScreenshots: true, }, }); - const entireTraceBounds = traceData.Meta.traceBounds; + const entireTraceBounds = parsedTrace.Meta.traceBounds; const newBounds = { ...entireTraceBounds, - min: TraceEngine.Types.Timing.MicroSeconds((entireTraceBounds.max + entireTraceBounds.min) / 2), + min: Trace.Types.Timing.MicroSeconds((entireTraceBounds.max + entireTraceBounds.min) / 2), }; minimap.breadcrumbs?.add(newBounds); const serializableModifications = Timeline.ModificationsManager.ModificationsManager.activeManager()?.toJSON(); diff --git a/public/panels/timeline/TimelineMiniMap.test.js.map b/public/panels/timeline/TimelineMiniMap.test.js.map index d22719013..9e17d3c4c 100644 --- a/public/panels/timeline/TimelineMiniMap.test.js.map +++ b/public/panels/timeline/TimelineMiniMap.test.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineMiniMap.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineMiniMap.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport {raf, renderElementIntoDOM} from '../../testing/DOMHelpers.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\n\nimport * as TimelineComponents from './components/components.js';\nimport * as Timeline from './timeline.js';\n\ndescribeWithEnvironment('TimelineMiniMap', function() {\n it('always shows the responsiveness, CPU activity and network panel', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n\n const container = document.createElement('div');\n renderElementIntoDOM(container);\n\n const minimap = new Timeline.TimelineMiniMap.TimelineMiniMap();\n minimap.markAsRoot();\n minimap.show(container);\n\n minimap.setData({\n traceParsedData: traceData,\n settings: {\n showMemory: false,\n showScreenshots: false,\n },\n });\n\n await raf();\n assert.exists(container.querySelector('#timeline-overview-responsiveness'));\n assert.exists(container.querySelector('#timeline-overview-cpu-activity'));\n assert.exists(container.querySelector('#timeline-overview-network'));\n assert.isNull(container.querySelector('#timeline-overview-filmstrip'));\n assert.isNull(container.querySelector('#timeline-overview-memory'));\n minimap.detach();\n });\n\n it('will show the other panels if they are set to visible', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n\n const container = document.createElement('div');\n renderElementIntoDOM(container);\n\n const minimap = new Timeline.TimelineMiniMap.TimelineMiniMap();\n minimap.markAsRoot();\n minimap.show(container);\n\n minimap.setData({\n traceParsedData: traceData,\n settings: {\n showMemory: true,\n showScreenshots: true,\n },\n });\n\n await raf();\n assert.exists(container.querySelector('#timeline-overview-responsiveness'));\n assert.exists(container.querySelector('#timeline-overview-cpu-activity'));\n assert.exists(container.querySelector('#timeline-overview-network'));\n assert.exists(container.querySelector('#timeline-overview-filmstrip'));\n assert.exists(container.querySelector('#timeline-overview-memory'));\n minimap.detach();\n });\n\n it('creates the first breadcrumb', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n\n const container = document.createElement('div');\n renderElementIntoDOM(container);\n\n const minimap = new Timeline.TimelineMiniMap.TimelineMiniMap();\n minimap.markAsRoot();\n minimap.show(container);\n\n minimap.setData({\n traceParsedData: traceData,\n settings: {\n showMemory: true,\n showScreenshots: true,\n },\n });\n\n await raf();\n\n if (!minimap.breadcrumbs) {\n throw new Error('The MiniMap unexpectedly did not create any breadcrumbs');\n }\n\n assert.strictEqual(\n TimelineComponents.Breadcrumbs.flattenBreadcrumbs(minimap.breadcrumbs.initialBreadcrumb).length, 1);\n assert.deepEqual(minimap.breadcrumbs.initialBreadcrumb, {window: traceData.Meta.traceBounds, child: null});\n });\n it('stores breadcrumbs to be serialized', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const minimap = new Timeline.TimelineMiniMap.TimelineMiniMap();\n minimap.setData({\n traceParsedData: traceData,\n settings: {\n showMemory: true,\n showScreenshots: true,\n },\n });\n const entireTraceBounds = traceData.Meta.traceBounds;\n const newBounds = {\n ...entireTraceBounds,\n min: TraceEngine.Types.Timing.MicroSeconds((entireTraceBounds.max + entireTraceBounds.min) / 2),\n };\n minimap.breadcrumbs?.add(newBounds);\n const serializableModifications = Timeline.ModificationsManager.ModificationsManager.activeManager()?.toJSON();\n assert.deepEqual(\n serializableModifications?.initialBreadcrumb.child,\n {window: {min: 1020035455504, max: 1020036087961, range: 1264914}, child: null} as\n TraceEngine.Types.File.Breadcrumb);\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"TimelineMiniMap.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineMiniMap.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../models/trace/trace.js';\nimport {raf, renderElementIntoDOM} from '../../testing/DOMHelpers.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\n\nimport * as TimelineComponents from './components/components.js';\nimport * as Timeline from './timeline.js';\n\ndescribeWithEnvironment('TimelineMiniMap', function() {\n it('always shows the responsiveness, CPU activity and network panel', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n\n const container = document.createElement('div');\n renderElementIntoDOM(container);\n\n const minimap = new Timeline.TimelineMiniMap.TimelineMiniMap();\n minimap.markAsRoot();\n minimap.show(container);\n\n minimap.setData({\n parsedTrace,\n settings: {\n showMemory: false,\n showScreenshots: false,\n },\n });\n\n await raf();\n assert.exists(container.querySelector('#timeline-overview-responsiveness'));\n assert.exists(container.querySelector('#timeline-overview-cpu-activity'));\n assert.exists(container.querySelector('#timeline-overview-network'));\n assert.isNull(container.querySelector('#timeline-overview-filmstrip'));\n assert.isNull(container.querySelector('#timeline-overview-memory'));\n minimap.detach();\n });\n\n it('will show the other panels if they are set to visible', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n\n const container = document.createElement('div');\n renderElementIntoDOM(container);\n\n const minimap = new Timeline.TimelineMiniMap.TimelineMiniMap();\n minimap.markAsRoot();\n minimap.show(container);\n\n minimap.setData({\n parsedTrace,\n settings: {\n showMemory: true,\n showScreenshots: true,\n },\n });\n\n await raf();\n assert.exists(container.querySelector('#timeline-overview-responsiveness'));\n assert.exists(container.querySelector('#timeline-overview-cpu-activity'));\n assert.exists(container.querySelector('#timeline-overview-network'));\n assert.exists(container.querySelector('#timeline-overview-filmstrip'));\n assert.exists(container.querySelector('#timeline-overview-memory'));\n minimap.detach();\n });\n\n it('creates the first breadcrumb', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n\n const container = document.createElement('div');\n renderElementIntoDOM(container);\n\n const minimap = new Timeline.TimelineMiniMap.TimelineMiniMap();\n minimap.markAsRoot();\n minimap.show(container);\n\n minimap.setData({\n parsedTrace,\n settings: {\n showMemory: true,\n showScreenshots: true,\n },\n });\n\n await raf();\n\n if (!minimap.breadcrumbs) {\n throw new Error('The MiniMap unexpectedly did not create any breadcrumbs');\n }\n\n assert.strictEqual(\n TimelineComponents.Breadcrumbs.flattenBreadcrumbs(minimap.breadcrumbs.initialBreadcrumb).length, 1);\n assert.deepEqual(minimap.breadcrumbs.initialBreadcrumb, {window: parsedTrace.Meta.traceBounds, child: null});\n });\n it('stores breadcrumbs to be serialized', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const minimap = new Timeline.TimelineMiniMap.TimelineMiniMap();\n minimap.setData({\n parsedTrace,\n settings: {\n showMemory: true,\n showScreenshots: true,\n },\n });\n const entireTraceBounds = parsedTrace.Meta.traceBounds;\n const newBounds = {\n ...entireTraceBounds,\n min: Trace.Types.Timing.MicroSeconds((entireTraceBounds.max + entireTraceBounds.min) / 2),\n };\n minimap.breadcrumbs?.add(newBounds);\n const serializableModifications = Timeline.ModificationsManager.ModificationsManager.activeManager()?.toJSON();\n assert.deepEqual(\n serializableModifications?.initialBreadcrumb.child,\n {window: {min: 1020035455504, max: 1020036087961, range: 1264914}, child: null} as Trace.Types.File.Breadcrumb);\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelinePaintProfilerView.d.ts b/public/panels/timeline/TimelinePaintProfilerView.d.ts index b833c826d..cd3e64d21 100644 --- a/public/panels/timeline/TimelinePaintProfilerView.d.ts +++ b/public/panels/timeline/TimelinePaintProfilerView.d.ts @@ -1,6 +1,6 @@ import * as SDK from '../../core/sdk/sdk.js'; import type * as Protocol from '../../generated/protocol.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as UI from '../../ui/legacy/legacy.js'; export declare class TimelinePaintProfilerView extends UI.SplitWidget.SplitWidget { #private; @@ -13,10 +13,10 @@ export declare class TimelinePaintProfilerView extends UI.SplitWidget.SplitWidge private event; private paintProfilerModel; private lastLoadedSnapshot; - constructor(traceEngineData: TraceEngine.Handlers.Types.TraceParseData); + constructor(parsedTrace: Trace.Handlers.Types.ParsedTrace); wasShown(): void; setSnapshot(snapshot: SDK.PaintProfiler.PaintProfilerSnapshot): void; - setEvent(paintProfilerModel: SDK.PaintProfiler.PaintProfilerModel, event: TraceEngine.Types.TraceEvents.TraceEventData): boolean; + setEvent(paintProfilerModel: SDK.PaintProfiler.PaintProfilerModel, event: Trace.Types.Events.Event): boolean; private updateWhenVisible; private update; private releaseSnapshot; diff --git a/public/panels/timeline/TimelinePaintProfilerView.js b/public/panels/timeline/TimelinePaintProfilerView.js index 574241292..d755023b1 100644 --- a/public/panels/timeline/TimelinePaintProfilerView.js +++ b/public/panels/timeline/TimelinePaintProfilerView.js @@ -3,7 +3,7 @@ // found in the LICENSE file. import * as SDK from '../../core/sdk/sdk.js'; import * as TimelineModel from '../../models/timeline_model/timeline_model.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as UI from '../../ui/legacy/legacy.js'; import * as LayerViewer from '../layer_viewer/layer_viewer.js'; import timelinePaintProfilerStyles from './timelinePaintProfiler.css.js'; @@ -17,13 +17,13 @@ export class TimelinePaintProfilerView extends UI.SplitWidget.SplitWidget { event; paintProfilerModel; lastLoadedSnapshot; - #traceEngineData; - constructor(traceEngineData) { + #parsedTrace; + constructor(parsedTrace) { super(false, false); this.element.classList.add('timeline-paint-profiler-view'); this.setSidebarSize(60); this.setResizable(false); - this.#traceEngineData = traceEngineData; + this.#parsedTrace = parsedTrace; this.logAndImageSplitWidget = new UI.SplitWidget.SplitWidget(true, false); this.logAndImageSplitWidget.element.classList.add('timeline-paint-profiler-log-split'); this.setMainWidget(this.logAndImageSplitWidget); @@ -59,7 +59,7 @@ export class TimelinePaintProfilerView extends UI.SplitWidget.SplitWidget { if (!data) { return false; } - const frame = this.#traceEngineData.Frames.framesById[data.sourceFrameNumber]; + const frame = this.#parsedTrace.Frames.framesById[data.sourceFrameNumber]; if (!frame || !frame.layerTree) { return false; } @@ -71,11 +71,11 @@ export class TimelinePaintProfilerView extends UI.SplitWidget.SplitWidget { this.pendingSnapshot = null; this.event = event; this.updateWhenVisible(); - if (TraceEngine.Types.TraceEvents.isTraceEventPaint(event)) { - const snapshot = this.#traceEngineData.LayerTree.paintsToSnapshots.get(event); + if (Trace.Types.Events.isPaint(event)) { + const snapshot = this.#parsedTrace.LayerTree.paintsToSnapshots.get(event); return Boolean(snapshot); } - if (TraceEngine.Types.TraceEvents.isTraceEventRasterTask(event)) { + if (Trace.Types.Events.isRasterTask(event)) { return this.#rasterEventHasTile(event); } return false; @@ -100,7 +100,7 @@ export class TimelinePaintProfilerView extends UI.SplitWidget.SplitWidget { if (!target) { return null; } - const frame = this.#traceEngineData.Frames.framesById[data.sourceFrameNumber]; + const frame = this.#parsedTrace.Frames.framesById[data.sourceFrameNumber]; if (!frame || !frame.layerTree) { return null; } @@ -115,13 +115,13 @@ export class TimelinePaintProfilerView extends UI.SplitWidget.SplitWidget { if (this.pendingSnapshot) { snapshotPromise = Promise.resolve({ rect: null, snapshot: this.pendingSnapshot }); } - else if (this.event && this.paintProfilerModel && TraceEngine.Types.TraceEvents.isTraceEventPaint(this.event)) { + else if (this.event && this.paintProfilerModel && Trace.Types.Events.isPaint(this.event)) { // When we process events (TimelineModel#processEvent) and find a // snapshot event, we look for the last paint that occurred and link the // snapshot to that paint event. That is why here if the event is a Paint // event, we look to see if it has had a matching picture event set for // it. - const snapshotEvent = this.#traceEngineData.LayerTree.paintsToSnapshots.get(this.event); + const snapshotEvent = this.#parsedTrace.LayerTree.paintsToSnapshots.get(this.event); if (snapshotEvent) { const encodedData = snapshotEvent.args.snapshot.skp64; snapshotPromise = this.paintProfilerModel.loadSnapshot(encodedData).then(snapshot => { @@ -132,7 +132,7 @@ export class TimelinePaintProfilerView extends UI.SplitWidget.SplitWidget { snapshotPromise = Promise.resolve(null); } } - else if (this.event && TraceEngine.Types.TraceEvents.isTraceEventRasterTask(this.event)) { + else if (this.event && Trace.Types.Events.isRasterTask(this.event)) { snapshotPromise = this.#rasterTilePromise(this.event); } else { diff --git a/public/panels/timeline/TimelinePaintProfilerView.js.map b/public/panels/timeline/TimelinePaintProfilerView.js.map index dffedd491..13a8b24ae 100644 --- a/public/panels/timeline/TimelinePaintProfilerView.js.map +++ b/public/panels/timeline/TimelinePaintProfilerView.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelinePaintProfilerView.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelinePaintProfilerView.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2014 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as SDK from '../../core/sdk/sdk.js';\nimport type * as Protocol from '../../generated/protocol.js';\nimport * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as LayerViewer from '../layer_viewer/layer_viewer.js';\n\nimport timelinePaintProfilerStyles from './timelinePaintProfiler.css.js';\n\nexport class TimelinePaintProfilerView extends UI.SplitWidget.SplitWidget {\n private readonly logAndImageSplitWidget: UI.SplitWidget.SplitWidget;\n private readonly imageView: TimelinePaintImageView;\n private readonly paintProfilerView: LayerViewer.PaintProfilerView.PaintProfilerView;\n private readonly logTreeView: LayerViewer.PaintProfilerView.PaintProfilerCommandLogView;\n private needsUpdateWhenVisible: boolean;\n private pendingSnapshot: SDK.PaintProfiler.PaintProfilerSnapshot|null;\n private event: TraceEngine.Types.TraceEvents.TraceEventData|null;\n private paintProfilerModel: SDK.PaintProfiler.PaintProfilerModel|null;\n private lastLoadedSnapshot: SDK.PaintProfiler.PaintProfilerSnapshot|null;\n #traceEngineData: TraceEngine.Handlers.Types.TraceParseData;\n\n constructor(traceEngineData: TraceEngine.Handlers.Types.TraceParseData) {\n super(false, false);\n this.element.classList.add('timeline-paint-profiler-view');\n this.setSidebarSize(60);\n this.setResizable(false);\n\n this.#traceEngineData = traceEngineData;\n\n this.logAndImageSplitWidget = new UI.SplitWidget.SplitWidget(true, false);\n this.logAndImageSplitWidget.element.classList.add('timeline-paint-profiler-log-split');\n this.setMainWidget(this.logAndImageSplitWidget);\n this.imageView = new TimelinePaintImageView();\n this.logAndImageSplitWidget.setMainWidget(this.imageView);\n\n this.paintProfilerView =\n new LayerViewer.PaintProfilerView.PaintProfilerView(this.imageView.showImage.bind(this.imageView));\n this.paintProfilerView.addEventListener(\n LayerViewer.PaintProfilerView.Events.WINDOW_CHANGED, this.onWindowChanged, this);\n this.setSidebarWidget(this.paintProfilerView);\n\n this.logTreeView = new LayerViewer.PaintProfilerView.PaintProfilerCommandLogView();\n this.logAndImageSplitWidget.setSidebarWidget(this.logTreeView);\n\n this.needsUpdateWhenVisible = false;\n this.pendingSnapshot = null;\n this.event = null;\n this.paintProfilerModel = null;\n this.lastLoadedSnapshot = null;\n }\n\n override wasShown(): void {\n super.wasShown();\n if (this.needsUpdateWhenVisible) {\n this.needsUpdateWhenVisible = false;\n this.update();\n }\n }\n\n setSnapshot(snapshot: SDK.PaintProfiler.PaintProfilerSnapshot): void {\n this.releaseSnapshot();\n this.pendingSnapshot = snapshot;\n this.event = null;\n this.updateWhenVisible();\n }\n\n #rasterEventHasTile(event: TraceEngine.Types.TraceEvents.TraceEventRasterTask): boolean {\n const data = event.args.tileData;\n if (!data) {\n return false;\n }\n\n const frame = this.#traceEngineData.Frames.framesById[data.sourceFrameNumber];\n if (!frame || !frame.layerTree) {\n return false;\n }\n return true;\n }\n\n setEvent(\n paintProfilerModel: SDK.PaintProfiler.PaintProfilerModel,\n event: TraceEngine.Types.TraceEvents.TraceEventData): boolean {\n this.releaseSnapshot();\n this.paintProfilerModel = paintProfilerModel;\n this.pendingSnapshot = null;\n this.event = event;\n\n this.updateWhenVisible();\n if (TraceEngine.Types.TraceEvents.isTraceEventPaint(event)) {\n const snapshot = this.#traceEngineData.LayerTree.paintsToSnapshots.get(event);\n return Boolean(snapshot);\n }\n if (TraceEngine.Types.TraceEvents.isTraceEventRasterTask(event)) {\n return this.#rasterEventHasTile(event);\n }\n return false;\n }\n\n private updateWhenVisible(): void {\n if (this.isShowing()) {\n this.update();\n } else {\n this.needsUpdateWhenVisible = true;\n }\n }\n\n async #rasterTilePromise(rasterEvent: TraceEngine.Types.TraceEvents.TraceEventRasterTask): Promise<{\n rect: Protocol.DOM.Rect,\n snapshot: SDK.PaintProfiler.PaintProfilerSnapshot,\n }|null> {\n const data = rasterEvent.args.tileData;\n if (!data) {\n return null;\n }\n\n if (!data.tileId.id_ref) {\n return null;\n }\n\n const target = SDK.TargetManager.TargetManager.instance().rootTarget();\n if (!target) {\n return null;\n }\n\n const frame = this.#traceEngineData.Frames.framesById[data.sourceFrameNumber];\n if (!frame || !frame.layerTree) {\n return null;\n }\n\n const layerTree = new TimelineModel.TracingLayerTree.TracingFrameLayerTree(\n target,\n frame.layerTree,\n );\n const tracingLayerTree = await layerTree.layerTreePromise();\n return tracingLayerTree ? tracingLayerTree.pictureForRasterTile(data.tileId.id_ref) : null;\n }\n\n private update(): void {\n this.logTreeView.setCommandLog([]);\n void this.paintProfilerView.setSnapshotAndLog(null, [], null);\n\n let snapshotPromise: Promise<{\n rect: Protocol.DOM.Rect | null,\n snapshot: SDK.PaintProfiler.PaintProfilerSnapshot,\n }|null>;\n if (this.pendingSnapshot) {\n snapshotPromise = Promise.resolve({rect: null, snapshot: this.pendingSnapshot});\n } else if (this.event && this.paintProfilerModel && TraceEngine.Types.TraceEvents.isTraceEventPaint(this.event)) {\n // When we process events (TimelineModel#processEvent) and find a\n // snapshot event, we look for the last paint that occurred and link the\n // snapshot to that paint event. That is why here if the event is a Paint\n // event, we look to see if it has had a matching picture event set for\n // it.\n const snapshotEvent = this.#traceEngineData.LayerTree.paintsToSnapshots.get(this.event);\n if (snapshotEvent) {\n const encodedData = snapshotEvent.args.snapshot.skp64;\n snapshotPromise = this.paintProfilerModel.loadSnapshot(encodedData).then(snapshot => {\n return snapshot && {rect: null, snapshot};\n });\n } else {\n snapshotPromise = Promise.resolve(null);\n }\n\n } else if (this.event && TraceEngine.Types.TraceEvents.isTraceEventRasterTask(this.event)) {\n snapshotPromise = this.#rasterTilePromise(this.event);\n } else {\n console.assert(false, 'Unexpected event type or no snapshot');\n return;\n }\n void snapshotPromise.then(snapshotWithRect => {\n this.releaseSnapshot();\n if (!snapshotWithRect) {\n this.imageView.showImage();\n return;\n }\n const snapshot = snapshotWithRect.snapshot;\n this.lastLoadedSnapshot = snapshot;\n this.imageView.setMask(snapshotWithRect.rect);\n void snapshot.commandLog().then(log => onCommandLogDone.call(this, snapshot, snapshotWithRect.rect, log || []));\n });\n\n function onCommandLogDone(\n this: TimelinePaintProfilerView, snapshot: SDK.PaintProfiler.PaintProfilerSnapshot,\n clipRect: Protocol.DOM.Rect|null, log?: SDK.PaintProfiler.PaintProfilerLogItem[]): void {\n this.logTreeView.setCommandLog(log || []);\n void this.paintProfilerView.setSnapshotAndLog(snapshot, log || [], clipRect);\n }\n }\n\n private releaseSnapshot(): void {\n if (!this.lastLoadedSnapshot) {\n return;\n }\n this.lastLoadedSnapshot.release();\n this.lastLoadedSnapshot = null;\n }\n\n private onWindowChanged(): void {\n this.logTreeView.updateWindow(this.paintProfilerView.selectionWindow());\n }\n}\n\nexport class TimelinePaintImageView extends UI.Widget.Widget {\n private imageContainer: HTMLElement;\n private imageElement: HTMLImageElement;\n private readonly maskElement: HTMLElement;\n private transformController: LayerViewer.TransformController.TransformController;\n private maskRectangle?: Protocol.DOM.Rect|null;\n constructor() {\n super(true);\n\n this.contentElement.classList.add('fill', 'paint-profiler-image-view');\n this.imageContainer = this.contentElement.createChild('div', 'paint-profiler-image-container');\n this.imageElement = (this.imageContainer.createChild('img') as HTMLImageElement);\n this.maskElement = this.imageContainer.createChild('div');\n this.imageElement.addEventListener('load', this.updateImagePosition.bind(this), false);\n this.transformController =\n new LayerViewer.TransformController.TransformController((this.contentElement as HTMLElement), true);\n this.transformController.addEventListener(\n LayerViewer.TransformController.Events.TRANSFORM_CHANGED, this.updateImagePosition, this);\n }\n\n override onResize(): void {\n if (this.imageElement.src) {\n this.updateImagePosition();\n }\n }\n\n private updateImagePosition(): void {\n const width = this.imageElement.naturalWidth;\n const height = this.imageElement.naturalHeight;\n const clientWidth = this.contentElement.clientWidth;\n const clientHeight = this.contentElement.clientHeight;\n\n const paddingFraction = 0.1;\n const paddingX = clientWidth * paddingFraction;\n const paddingY = clientHeight * paddingFraction;\n const scaleX = (clientWidth - paddingX) / width;\n const scaleY = (clientHeight - paddingY) / height;\n const scale = Math.min(scaleX, scaleY);\n\n if (this.maskRectangle) {\n const style = this.maskElement.style;\n style.width = width + 'px';\n style.height = height + 'px';\n style.borderLeftWidth = this.maskRectangle.x + 'px';\n style.borderTopWidth = this.maskRectangle.y + 'px';\n style.borderRightWidth = (width - this.maskRectangle.x - this.maskRectangle.width) + 'px';\n style.borderBottomWidth = (height - this.maskRectangle.y - this.maskRectangle.height) + 'px';\n }\n this.transformController.setScaleConstraints(0.5, 10 / scale);\n let matrix = new WebKitCSSMatrix()\n .scale(this.transformController.scale(), this.transformController.scale())\n .translate(clientWidth / 2, clientHeight / 2)\n .scale(scale, scale)\n .translate(-width / 2, -height / 2);\n const bounds = UI.Geometry.boundsForTransformedPoints(matrix, [0, 0, 0, width, height, 0]);\n this.transformController.clampOffsets(\n paddingX - bounds.maxX, clientWidth - paddingX - bounds.minX, paddingY - bounds.maxY,\n clientHeight - paddingY - bounds.minY);\n matrix = new WebKitCSSMatrix()\n .translate(this.transformController.offsetX(), this.transformController.offsetY())\n .multiply(matrix);\n this.imageContainer.style.webkitTransform = matrix.toString();\n }\n\n showImage(imageURL?: string): void {\n this.imageContainer.classList.toggle('hidden', !imageURL);\n if (imageURL) {\n this.imageElement.src = imageURL;\n }\n }\n\n setMask(maskRectangle: Protocol.DOM.Rect|null): void {\n this.maskRectangle = maskRectangle;\n this.maskElement.classList.toggle('hidden', !maskRectangle);\n }\n override wasShown(): void {\n super.wasShown();\n this.registerCSSFiles([timelinePaintProfilerStyles]);\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"TimelinePaintProfilerView.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelinePaintProfilerView.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2014 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as SDK from '../../core/sdk/sdk.js';\nimport type * as Protocol from '../../generated/protocol.js';\nimport * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as LayerViewer from '../layer_viewer/layer_viewer.js';\n\nimport timelinePaintProfilerStyles from './timelinePaintProfiler.css.js';\n\nexport class TimelinePaintProfilerView extends UI.SplitWidget.SplitWidget {\n private readonly logAndImageSplitWidget: UI.SplitWidget.SplitWidget;\n private readonly imageView: TimelinePaintImageView;\n private readonly paintProfilerView: LayerViewer.PaintProfilerView.PaintProfilerView;\n private readonly logTreeView: LayerViewer.PaintProfilerView.PaintProfilerCommandLogView;\n private needsUpdateWhenVisible: boolean;\n private pendingSnapshot: SDK.PaintProfiler.PaintProfilerSnapshot|null;\n private event: Trace.Types.Events.Event|null;\n private paintProfilerModel: SDK.PaintProfiler.PaintProfilerModel|null;\n private lastLoadedSnapshot: SDK.PaintProfiler.PaintProfilerSnapshot|null;\n #parsedTrace: Trace.Handlers.Types.ParsedTrace;\n\n constructor(parsedTrace: Trace.Handlers.Types.ParsedTrace) {\n super(false, false);\n this.element.classList.add('timeline-paint-profiler-view');\n this.setSidebarSize(60);\n this.setResizable(false);\n\n this.#parsedTrace = parsedTrace;\n\n this.logAndImageSplitWidget = new UI.SplitWidget.SplitWidget(true, false);\n this.logAndImageSplitWidget.element.classList.add('timeline-paint-profiler-log-split');\n this.setMainWidget(this.logAndImageSplitWidget);\n this.imageView = new TimelinePaintImageView();\n this.logAndImageSplitWidget.setMainWidget(this.imageView);\n\n this.paintProfilerView =\n new LayerViewer.PaintProfilerView.PaintProfilerView(this.imageView.showImage.bind(this.imageView));\n this.paintProfilerView.addEventListener(\n LayerViewer.PaintProfilerView.Events.WINDOW_CHANGED, this.onWindowChanged, this);\n this.setSidebarWidget(this.paintProfilerView);\n\n this.logTreeView = new LayerViewer.PaintProfilerView.PaintProfilerCommandLogView();\n this.logAndImageSplitWidget.setSidebarWidget(this.logTreeView);\n\n this.needsUpdateWhenVisible = false;\n this.pendingSnapshot = null;\n this.event = null;\n this.paintProfilerModel = null;\n this.lastLoadedSnapshot = null;\n }\n\n override wasShown(): void {\n super.wasShown();\n if (this.needsUpdateWhenVisible) {\n this.needsUpdateWhenVisible = false;\n this.update();\n }\n }\n\n setSnapshot(snapshot: SDK.PaintProfiler.PaintProfilerSnapshot): void {\n this.releaseSnapshot();\n this.pendingSnapshot = snapshot;\n this.event = null;\n this.updateWhenVisible();\n }\n\n #rasterEventHasTile(event: Trace.Types.Events.RasterTask): boolean {\n const data = event.args.tileData;\n if (!data) {\n return false;\n }\n\n const frame = this.#parsedTrace.Frames.framesById[data.sourceFrameNumber];\n if (!frame || !frame.layerTree) {\n return false;\n }\n return true;\n }\n\n setEvent(paintProfilerModel: SDK.PaintProfiler.PaintProfilerModel, event: Trace.Types.Events.Event): boolean {\n this.releaseSnapshot();\n this.paintProfilerModel = paintProfilerModel;\n this.pendingSnapshot = null;\n this.event = event;\n\n this.updateWhenVisible();\n if (Trace.Types.Events.isPaint(event)) {\n const snapshot = this.#parsedTrace.LayerTree.paintsToSnapshots.get(event);\n return Boolean(snapshot);\n }\n if (Trace.Types.Events.isRasterTask(event)) {\n return this.#rasterEventHasTile(event);\n }\n return false;\n }\n\n private updateWhenVisible(): void {\n if (this.isShowing()) {\n this.update();\n } else {\n this.needsUpdateWhenVisible = true;\n }\n }\n\n async #rasterTilePromise(rasterEvent: Trace.Types.Events.RasterTask): Promise<{\n rect: Protocol.DOM.Rect,\n snapshot: SDK.PaintProfiler.PaintProfilerSnapshot,\n }|null> {\n const data = rasterEvent.args.tileData;\n if (!data) {\n return null;\n }\n\n if (!data.tileId.id_ref) {\n return null;\n }\n\n const target = SDK.TargetManager.TargetManager.instance().rootTarget();\n if (!target) {\n return null;\n }\n\n const frame = this.#parsedTrace.Frames.framesById[data.sourceFrameNumber];\n if (!frame || !frame.layerTree) {\n return null;\n }\n\n const layerTree = new TimelineModel.TracingLayerTree.TracingFrameLayerTree(\n target,\n frame.layerTree,\n );\n const tracingLayerTree = await layerTree.layerTreePromise();\n return tracingLayerTree ? tracingLayerTree.pictureForRasterTile(data.tileId.id_ref) : null;\n }\n\n private update(): void {\n this.logTreeView.setCommandLog([]);\n void this.paintProfilerView.setSnapshotAndLog(null, [], null);\n\n let snapshotPromise: Promise<{\n rect: Protocol.DOM.Rect | null,\n snapshot: SDK.PaintProfiler.PaintProfilerSnapshot,\n }|null>;\n if (this.pendingSnapshot) {\n snapshotPromise = Promise.resolve({rect: null, snapshot: this.pendingSnapshot});\n } else if (this.event && this.paintProfilerModel && Trace.Types.Events.isPaint(this.event)) {\n // When we process events (TimelineModel#processEvent) and find a\n // snapshot event, we look for the last paint that occurred and link the\n // snapshot to that paint event. That is why here if the event is a Paint\n // event, we look to see if it has had a matching picture event set for\n // it.\n const snapshotEvent = this.#parsedTrace.LayerTree.paintsToSnapshots.get(this.event);\n if (snapshotEvent) {\n const encodedData = snapshotEvent.args.snapshot.skp64;\n snapshotPromise = this.paintProfilerModel.loadSnapshot(encodedData).then(snapshot => {\n return snapshot && {rect: null, snapshot};\n });\n } else {\n snapshotPromise = Promise.resolve(null);\n }\n\n } else if (this.event && Trace.Types.Events.isRasterTask(this.event)) {\n snapshotPromise = this.#rasterTilePromise(this.event);\n } else {\n console.assert(false, 'Unexpected event type or no snapshot');\n return;\n }\n void snapshotPromise.then(snapshotWithRect => {\n this.releaseSnapshot();\n if (!snapshotWithRect) {\n this.imageView.showImage();\n return;\n }\n const snapshot = snapshotWithRect.snapshot;\n this.lastLoadedSnapshot = snapshot;\n this.imageView.setMask(snapshotWithRect.rect);\n void snapshot.commandLog().then(log => onCommandLogDone.call(this, snapshot, snapshotWithRect.rect, log || []));\n });\n\n function onCommandLogDone(\n this: TimelinePaintProfilerView, snapshot: SDK.PaintProfiler.PaintProfilerSnapshot,\n clipRect: Protocol.DOM.Rect|null, log?: SDK.PaintProfiler.PaintProfilerLogItem[]): void {\n this.logTreeView.setCommandLog(log || []);\n void this.paintProfilerView.setSnapshotAndLog(snapshot, log || [], clipRect);\n }\n }\n\n private releaseSnapshot(): void {\n if (!this.lastLoadedSnapshot) {\n return;\n }\n this.lastLoadedSnapshot.release();\n this.lastLoadedSnapshot = null;\n }\n\n private onWindowChanged(): void {\n this.logTreeView.updateWindow(this.paintProfilerView.selectionWindow());\n }\n}\n\nexport class TimelinePaintImageView extends UI.Widget.Widget {\n private imageContainer: HTMLElement;\n private imageElement: HTMLImageElement;\n private readonly maskElement: HTMLElement;\n private transformController: LayerViewer.TransformController.TransformController;\n private maskRectangle?: Protocol.DOM.Rect|null;\n constructor() {\n super(true);\n\n this.contentElement.classList.add('fill', 'paint-profiler-image-view');\n this.imageContainer = this.contentElement.createChild('div', 'paint-profiler-image-container');\n this.imageElement = (this.imageContainer.createChild('img') as HTMLImageElement);\n this.maskElement = this.imageContainer.createChild('div');\n this.imageElement.addEventListener('load', this.updateImagePosition.bind(this), false);\n this.transformController =\n new LayerViewer.TransformController.TransformController((this.contentElement as HTMLElement), true);\n this.transformController.addEventListener(\n LayerViewer.TransformController.Events.TRANSFORM_CHANGED, this.updateImagePosition, this);\n }\n\n override onResize(): void {\n if (this.imageElement.src) {\n this.updateImagePosition();\n }\n }\n\n private updateImagePosition(): void {\n const width = this.imageElement.naturalWidth;\n const height = this.imageElement.naturalHeight;\n const clientWidth = this.contentElement.clientWidth;\n const clientHeight = this.contentElement.clientHeight;\n\n const paddingFraction = 0.1;\n const paddingX = clientWidth * paddingFraction;\n const paddingY = clientHeight * paddingFraction;\n const scaleX = (clientWidth - paddingX) / width;\n const scaleY = (clientHeight - paddingY) / height;\n const scale = Math.min(scaleX, scaleY);\n\n if (this.maskRectangle) {\n const style = this.maskElement.style;\n style.width = width + 'px';\n style.height = height + 'px';\n style.borderLeftWidth = this.maskRectangle.x + 'px';\n style.borderTopWidth = this.maskRectangle.y + 'px';\n style.borderRightWidth = (width - this.maskRectangle.x - this.maskRectangle.width) + 'px';\n style.borderBottomWidth = (height - this.maskRectangle.y - this.maskRectangle.height) + 'px';\n }\n this.transformController.setScaleConstraints(0.5, 10 / scale);\n let matrix = new WebKitCSSMatrix()\n .scale(this.transformController.scale(), this.transformController.scale())\n .translate(clientWidth / 2, clientHeight / 2)\n .scale(scale, scale)\n .translate(-width / 2, -height / 2);\n const bounds = UI.Geometry.boundsForTransformedPoints(matrix, [0, 0, 0, width, height, 0]);\n this.transformController.clampOffsets(\n paddingX - bounds.maxX, clientWidth - paddingX - bounds.minX, paddingY - bounds.maxY,\n clientHeight - paddingY - bounds.minY);\n matrix = new WebKitCSSMatrix()\n .translate(this.transformController.offsetX(), this.transformController.offsetY())\n .multiply(matrix);\n this.imageContainer.style.webkitTransform = matrix.toString();\n }\n\n showImage(imageURL?: string): void {\n this.imageContainer.classList.toggle('hidden', !imageURL);\n if (imageURL) {\n this.imageElement.src = imageURL;\n }\n }\n\n setMask(maskRectangle: Protocol.DOM.Rect|null): void {\n this.maskRectangle = maskRectangle;\n this.maskElement.classList.toggle('hidden', !maskRectangle);\n }\n override wasShown(): void {\n super.wasShown();\n this.registerCSSFiles([timelinePaintProfilerStyles]);\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelinePanel.d.ts b/public/panels/timeline/TimelinePanel.d.ts index 0203423c4..fb01ba0bd 100644 --- a/public/panels/timeline/TimelinePanel.d.ts +++ b/public/panels/timeline/TimelinePanel.d.ts @@ -2,7 +2,7 @@ import * as Common from '../../core/common/common.js'; import * as Platform from '../../core/platform/platform.js'; import * as SDK from '../../core/sdk/sdk.js'; import type * as TimelineModel from '../../models/timeline_model/timeline_model.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as UI from '../../ui/legacy/legacy.js'; import { type Client } from './TimelineController.js'; import { TimelineFlameChartView } from './TimelineFlameChartView.js'; @@ -59,7 +59,7 @@ export declare class TimelinePanel extends UI.Panel.Panel implements Client, Tim searchableView(): UI.SearchableView.SearchableView | null; wasShown(): void; willHide(): void; - loadFromEvents(events: TraceEngine.Types.TraceEvents.TraceEventData[]): void; + loadFromEvents(events: Trace.Types.Events.Event[]): void; getFlameChart(): TimelineFlameChartView; getMinimap(): TimelineMiniMap; /** @@ -68,14 +68,14 @@ export declare class TimelinePanel extends UI.Panel.Panel implements Client, Tim * within DevTools you are warned when using the method. * @deprecated **/ - getTraceEngineDataForLayoutTests(): TraceEngine.Handlers.Types.TraceParseData; + getParsedTraceForLayoutTests(): Trace.Handlers.Types.ParsedTrace; /** * NOTE: this method only exists to enable some layout tests to be migrated to the new engine. * DO NOT use this method within DevTools. It is marked as deprecated so * within DevTools you are warned when using the method. * @deprecated **/ - getTraceEngineRawTraceEventsForLayoutTests(): readonly TraceEngine.Types.TraceEvents.TraceEventData[]; + getTraceEngineRawTraceEventsForLayoutTests(): readonly Trace.Types.Events.Event[]; private loadFromCpuProfile; private setState; private createSettingCheckbox; @@ -122,7 +122,7 @@ export declare class TimelinePanel extends UI.Panel.Panel implements Client, Tim * user switches to an existing trace, please {@see setModel} and put your * code in there. **/ - loadingComplete(collectedEvents: TraceEngine.Types.TraceEvents.TraceEventData[], exclusiveFilter: (TimelineModel.TimelineModelFilter.TimelineModelFilter | null) | undefined, isCpuProfile: boolean, recordingStartTime: number | null, metadata: TraceEngine.Types.File.MetaData | null): Promise; + loadingComplete(collectedEvents: Trace.Types.Events.Event[], exclusiveFilter: (TimelineModel.TimelineModelFilter.TimelineModelFilter | null) | undefined, isCpuProfile: boolean, recordingStartTime: number | null, metadata: Trace.Types.File.MetaData | null): Promise; recordTraceLoadMetric(): void; loadingCompleteForTest(): void; private showRecordingStarted; @@ -131,8 +131,8 @@ export declare class TimelinePanel extends UI.Panel.Panel implements Client, Tim private frameForSelection; jumpToFrame(offset: number): true | undefined; select(selection: TimelineSelection | null): void; - selectEntryAtTime(events: TraceEngine.Types.TraceEvents.TraceEventData[] | null, time: number): void; - highlightEvent(event: TraceEngine.Types.TraceEvents.TraceEventData | null): void; + selectEntryAtTime(events: Trace.Types.Events.Event[] | null, time: number): void; + highlightEvent(event: Trace.Types.Events.Event | null): void; private handleDrop; } export declare const enum State { @@ -148,8 +148,8 @@ export declare const headerHeight = 20; export interface TimelineModeViewDelegate { select(selection: TimelineSelection | null): void; element: Element; - selectEntryAtTime(events: TraceEngine.Types.TraceEvents.TraceEventData[] | null, time: number): void; - highlightEvent(event: TraceEngine.Types.TraceEvents.TraceEventData | null): void; + selectEntryAtTime(events: Trace.Types.Events.Event[] | null, time: number): void; + highlightEvent(event: Trace.Types.Events.Event | null): void; } export declare class StatusPane extends UI.Widget.VBox { #private; @@ -170,7 +170,7 @@ export declare class StatusPane extends UI.Widget.VBox { buttonDisabled?: boolean; }, buttonCallback: () => (Promise | void)); finish(): void; - enableDownloadOfEvents(rawEvents: TraceEngine.Types.TraceEvents.TraceEventData[]): void; + enableDownloadOfEvents(rawEvents: Trace.Types.Events.Event[]): void; remove(): void; showPane(parent: Element): void; enableAndFocusButton(): void; diff --git a/public/panels/timeline/TimelinePanel.js b/public/panels/timeline/TimelinePanel.js index 329aee749..70d15d57c 100644 --- a/public/panels/timeline/TimelinePanel.js +++ b/public/panels/timeline/TimelinePanel.js @@ -37,7 +37,7 @@ import * as i18n from '../../core/i18n/i18n.js'; import * as Platform from '../../core/platform/platform.js'; import * as Root from '../../core/root/root.js'; import * as SDK from '../../core/sdk/sdk.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as Workspace from '../../models/workspace/workspace.js'; import * as TraceBounds from '../../services/trace_bounds/trace_bounds.js'; import * as Adorners from '../../ui/components/adorners/adorners.js'; @@ -392,11 +392,11 @@ export class TimelinePanel extends UI.Panel.Panel { }; this.brickBreakerToolbarButton = new UI.Toolbar.ToolbarButton(i18nString(UIStrings.fixMe), adorner); this.brickBreakerToolbarButton.addEventListener("Click" /* UI.Toolbar.ToolbarButton.Events.CLICK */, () => this.#onBrickBreakerEasterEggClick()); - const config = TraceEngine.Types.Configuration.defaults(); + const config = Trace.Types.Configuration.defaults(); config.showAllEvents = Root.Runtime.experiments.isEnabled('timeline-show-all-events'); config.includeRuntimeCallStats = Root.Runtime.experiments.isEnabled('timeline-v8-runtime-call-stats'); config.debugMode = Root.Runtime.experiments.isEnabled("timeline-debug-mode" /* Root.Runtime.ExperimentName.TIMELINE_DEBUG_MODE */); - this.#traceEngineModel = TraceEngine.TraceModel.Model.createWithAllHandlers(config); + this.#traceEngineModel = Trace.TraceModel.Model.createWithAllHandlers(config); this.#listenForProcessingProgress(); this.element.addEventListener('contextmenu', this.contextMenu.bind(this), false); this.dropTarget = new UI.DropTarget.DropTarget(this.element, [UI.DropTarget.Type.File, UI.DropTarget.Type.URI], i18nString(UIStrings.dropTimelineFileOrUrlHere), this.handleDrop.bind(this)); @@ -462,6 +462,10 @@ export class TimelinePanel extends UI.Panel.Panel { const { name, navigationId, createOverlayFn } = event; this.#setActiveInsight({ name, navigationId, createOverlayFn }); }); + this.#sideBar.element.addEventListener(TimelineInsights.SidebarInsight.InsightOverlayOverride.eventName, event => { + const { overlays } = event; + this.flameChart.setOverlaysOverride(overlays); + }); this.#sideBar.contentElement.addEventListener(TimelineComponents.Sidebar.EventReferenceClick.eventName, event => { const { metricEvent } = event; this.flameChart.setSelectionAndReveal(TimelineSelection.fromTraceEvent(metricEvent)); @@ -470,6 +474,17 @@ export class TimelinePanel extends UI.Panel.Panel { const { removedAnnotation } = event; ModificationsManager.activeManager()?.removeAnnotation(removedAnnotation); }); + this.#sideBar.element.addEventListener(TimelineComponents.Sidebar.RevealAnnotation.eventName, event => { + this.flameChart.revealAnnotation(event.annotation); + }); + this.#sideBar.element.addEventListener(TimelineInsights.SidebarInsight.NavigationBoundsHovered.eventName, event => { + if (event.bounds) { + this.#minimapComponent.highlightBounds(event.bounds); + } + else { + this.#minimapComponent.clearBoundsHighlight(); + } + }); this.onModeChanged(); this.populateToolbar(); // The viewMode is set by default to the landing page, so we don't call @@ -659,12 +674,12 @@ export class TimelinePanel extends UI.Panel.Panel { * within DevTools you are warned when using the method. * @deprecated **/ - getTraceEngineDataForLayoutTests() { + getParsedTraceForLayoutTests() { const traceIndex = this.#activeTraceIndex(); if (traceIndex === null) { throw new Error('No trace index active.'); } - const data = this.#traceEngineModel.traceParsedData(traceIndex); + const data = this.#traceEngineModel.parsedTrace(traceIndex); if (data === null) { throw new Error('No trace engine data found.'); } @@ -926,14 +941,14 @@ export class TimelinePanel extends UI.Panel.Panel { delete metadata.modifications; } if (metadata && isEnhancedTraces) { - metadata.enhancedTraceVersion = TraceEngine.Handlers.ModelHandlers.EnhancedTraces.EnhancedTracesVersion; + metadata.enhancedTraceVersion = SDK.EnhancedTracesParser.EnhancedTracesParser.enhancedTraceVersion; } if (!traceEvents) { return; } const traceStart = Platform.DateUtilities.toISO8601Compact(new Date()); let fileName; - if (metadata?.dataOrigin === "CPUProfile" /* TraceEngine.Types.File.DataOrigin.CPU_PROFILE */) { + if (metadata?.dataOrigin === "CPUProfile" /* Trace.Types.File.DataOrigin.CPU_PROFILE */) { fileName = `CPU-${traceStart}.cpuprofile`; } else if (metadata && metadata.enhancedTraceVersion) { @@ -945,7 +960,7 @@ export class TimelinePanel extends UI.Panel.Panel { try { // TODO(crbug.com/1456818): Extract this logic and add more tests. let traceAsString; - if (metadata?.dataOrigin === "CPUProfile" /* TraceEngine.Types.File.DataOrigin.CPU_PROFILE */) { + if (metadata?.dataOrigin === "CPUProfile" /* Trace.Types.File.DataOrigin.CPU_PROFILE */) { const profileEvent = traceEvents.find(e => e.name === 'CpuProfile'); if (!profileEvent || !profileEvent.args?.data) { return; @@ -990,7 +1005,7 @@ export class TimelinePanel extends UI.Panel.Panel { else { this.#changeView({ mode: 'VIEWING_TRACE', - traceIndex: recordingData.traceParseDataIndex, + traceIndex: recordingData.parsedTraceIndex, }); } } @@ -1002,7 +1017,7 @@ export class TimelinePanel extends UI.Panel.Panel { if (recordingData && recordingData.type === 'TRACE_INDEX') { this.#changeView({ mode: 'VIEWING_TRACE', - traceIndex: recordingData.traceParseDataIndex, + traceIndex: recordingData.parsedTraceIndex, }); } return true; @@ -1040,14 +1055,14 @@ export class TimelinePanel extends UI.Panel.Panel { if (this.#viewMode.mode !== 'VIEWING_TRACE') { return; } - const traceParsedData = this.#traceEngineModel.traceParsedData(this.#viewMode.traceIndex); + const parsedTrace = this.#traceEngineModel.parsedTrace(this.#viewMode.traceIndex); const isCpuProfile = this.#traceEngineModel.metadata(this.#viewMode.traceIndex)?.dataOrigin === - "CPUProfile" /* TraceEngine.Types.File.DataOrigin.CPU_PROFILE */; - if (!traceParsedData) { + "CPUProfile" /* Trace.Types.File.DataOrigin.CPU_PROFILE */; + if (!parsedTrace) { return; } this.#minimapComponent.setData({ - traceParsedData, + parsedTrace, isCpuProfile, settings: { showScreenshots: this.showScreenshotsSetting.get(), @@ -1393,23 +1408,23 @@ export class TimelinePanel extends UI.Panel.Panel { return; } const { traceIndex } = this.#viewMode; - const traceParsedData = this.#traceEngineModel.traceParsedData(traceIndex); + const parsedTrace = this.#traceEngineModel.parsedTrace(traceIndex); const syntheticEventsManager = this.#traceEngineModel.syntheticTraceEventsManager(traceIndex); - if (!traceParsedData || !syntheticEventsManager) { + if (!parsedTrace || !syntheticEventsManager) { // This should not happen, because you can only get into the // VIEWING_TRACE viewMode if you have a valid trace index from the - // TraceEngine. If it does, let's bail back to the landing page. + // Trace Engine. If it does, let's bail back to the landing page. console.error(`setModelForActiveTrace was called with an invalid trace index: ${traceIndex}`); this.#changeView({ mode: 'LANDING_PAGE' }); return; } - TraceEngine.Helpers.SyntheticEvents.SyntheticEventsManager.activate(syntheticEventsManager); + Trace.Helpers.SyntheticEvents.SyntheticEventsManager.activate(syntheticEventsManager); // Clear the line level profile that could exist from the previous trace. PerfUI.LineLevelProfile.Performance.instance().reset(); this.#minimapComponent.reset(); // Order is important: the bounds must be set before we initiate any UI // rendering. - TraceBounds.TraceBounds.BoundsManager.instance().resetWithNewBounds(traceParsedData.Meta.traceBounds); + TraceBounds.TraceBounds.BoundsManager.instance().resetWithNewBounds(parsedTrace.Meta.traceBounds); // Set up the modifications manager for the newly active trace. // The order is important: this needs to happen before we trigger a flame chart redraw by setting the model. // (it could happen after, but then we would need to trigger a fresh redraw so let's not do that) @@ -1418,15 +1433,15 @@ export class TimelinePanel extends UI.Panel.Panel { console.error('ModificationsManager could not be created or activated.'); } this.statusPane?.updateProgressBar(i18nString(UIStrings.processed), 70); - const isCpuProfile = this.#traceEngineModel.metadata(traceIndex)?.dataOrigin === "CPUProfile" /* TraceEngine.Types.File.DataOrigin.CPU_PROFILE */; - this.flameChart.setModel(traceParsedData, isCpuProfile); + const isCpuProfile = this.#traceEngineModel.metadata(traceIndex)?.dataOrigin === "CPUProfile" /* Trace.Types.File.DataOrigin.CPU_PROFILE */; + this.flameChart.setModel(parsedTrace, isCpuProfile); this.flameChart.resizeToPreferredHeights(); // Reset the visual selection as we've just swapped to a new trace. this.flameChart.setSelectionAndReveal(null); - this.#sideBar.setTraceParsedData(traceParsedData); + this.#sideBar.setParsedTrace(parsedTrace); this.searchableViewInternal.showWidget(); const exclusiveFilter = this.#exclusiveFilterPerTrace.get(traceIndex) ?? null; - this.#applyActiveFilters(traceParsedData.Meta.traceIsGeneric, exclusiveFilter); + this.#applyActiveFilters(parsedTrace.Meta.traceIsGeneric, exclusiveFilter); // Add ModificationsManager listeners for annotations change to update the Annotation Overlays. currentManager?.addEventListener(AnnotationModifiedEvent.eventName, event => { const { overlay, action } = event; @@ -1446,6 +1461,9 @@ export class TimelinePanel extends UI.Panel.Panel { entryTo: overlay.entryTo, }); } + else if (action === 'EnterLabelEditState' && Overlays.Overlays.isEntryLabel(overlay)) { + this.flameChart.enterLabelEditMode(overlay); + } const annotations = currentManager.getAnnotations(); const annotationEntryToColorMap = this.buildColorsAnnotationsMap(annotations); this.#sideBar.setAnnotations(annotations, annotationEntryToColorMap); @@ -1453,25 +1471,23 @@ export class TimelinePanel extends UI.Panel.Panel { // To calculate the activity we might want to zoom in, we use the top-most main-thread track const topMostMainThreadAppender = this.flameChart.getMainDataProvider().compatibilityTracksAppenderInstance().threadAppenders().at(0); if (topMostMainThreadAppender) { - const zoomedInBounds = TraceEngine.Extras.MainThreadActivity.calculateWindow(traceParsedData.Meta.traceBounds, topMostMainThreadAppender.getEntries()); + const zoomedInBounds = Trace.Extras.MainThreadActivity.calculateWindow(parsedTrace.Meta.traceBounds, topMostMainThreadAppender.getEntries()); TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(zoomedInBounds); } // Add overlays for annotations loaded from the trace file const currModificationManager = ModificationsManager.activeManager(); if (currModificationManager) { - currModificationManager.getOverlays().forEach(overlay => { - this.flameChart.addOverlay(overlay); - }); const annotations = currModificationManager.getAnnotations(); const annotationEntryToColorMap = this.buildColorsAnnotationsMap(annotations); this.#sideBar.setAnnotations(annotations, annotationEntryToColorMap); + this.flameChart.bulkAddOverlays(currModificationManager.getOverlays()); } // Set up line level profiling with CPU profiles, if we found any. PerfUI.LineLevelProfile.Performance.instance().reset(); - if (traceParsedData && traceParsedData.Samples.profilesInProcess.size) { + if (parsedTrace && parsedTrace.Samples.profilesInProcess.size) { const primaryPageTarget = SDK.TargetManager.TargetManager.instance().primaryPageTarget(); // Gather up all CPU Profiles we found when parsing this trace. - const cpuProfiles = Array.from(traceParsedData.Samples.profilesInProcess).flatMap(([_processId, threadsInProcess]) => { + const cpuProfiles = Array.from(parsedTrace.Samples.profilesInProcess).flatMap(([_processId, threadsInProcess]) => { const profiles = Array.from(threadsInProcess.values()).map(profileData => profileData.parsedProfile); return profiles; }); @@ -1481,7 +1497,7 @@ export class TimelinePanel extends UI.Panel.Panel { } // Set up SourceMapsResolver to ensure we resolve any function names in // profile calls. - this.#sourceMapsResolver = new SourceMapsResolver(traceParsedData); + this.#sourceMapsResolver = new SourceMapsResolver(parsedTrace); this.#sourceMapsResolver.addEventListener(NodeNamesUpdated.eventName, this.#onSourceMapsNodeNamesResolvedBound); void this.#sourceMapsResolver.install(); this.statusPane?.updateProgressBar(i18nString(UIStrings.processed), 80); @@ -1489,10 +1505,10 @@ export class TimelinePanel extends UI.Panel.Panel { this.statusPane?.updateProgressBar(i18nString(UIStrings.processed), 90); this.updateTimelineControls(); this.#setActiveInsight(null); - const traceInsightsData = this.#traceEngineModel.traceInsights(traceIndex); - if (traceInsightsData) { - this.flameChart.setInsights(traceInsightsData); - this.#sideBar.setInsights(traceInsightsData); + const traceInsightsSets = this.#traceEngineModel.traceInsights(traceIndex); + if (traceInsightsSets) { + this.flameChart.setInsights(traceInsightsSets); + this.#sideBar.setInsights(traceInsightsSets); } this.#showSidebarIfRequired(); } @@ -1516,10 +1532,10 @@ export class TimelinePanel extends UI.Panel.Panel { buildColorsAnnotationsMap(annotations) { const annotationEntryToColorMap = new Map(); for (const annotation of annotations) { - if (TraceEngine.Types.File.isEntryLabelAnnotation(annotation)) { + if (Trace.Types.File.isEntryLabelAnnotation(annotation)) { annotationEntryToColorMap.set(annotation.entry, this.getEntryColorByEntry(annotation.entry)); } - else if (TraceEngine.Types.File.isEntriesLinkAnnotation(annotation)) { + else if (Trace.Types.File.isEntriesLinkAnnotation(annotation)) { annotationEntryToColorMap.set(annotation.entryFrom, this.getEntryColorByEntry(annotation.entryFrom)); if (annotation.entryTo) { annotationEntryToColorMap.set(annotation.entryTo, this.getEntryColorByEntry(annotation.entryTo)); @@ -1617,7 +1633,7 @@ export class TimelinePanel extends UI.Panel.Panel { if (!this.loader) { this.statusPane.finish(); } - this.traceLoadStart = TraceEngine.Types.Timing.MilliSeconds(performance.now()); + this.traceLoadStart = Trace.Types.Timing.MilliSeconds(performance.now()); await this.loadingProgress(0); } async loadingProgress(progress) { @@ -1629,15 +1645,15 @@ export class TimelinePanel extends UI.Panel.Panel { this.statusPane?.updateStatus(i18nString(UIStrings.processingProfile)); } #listenForProcessingProgress() { - this.#traceEngineModel.addEventListener(TraceEngine.TraceModel.ModelUpdateEvent.eventName, e => { + this.#traceEngineModel.addEventListener(Trace.TraceModel.ModelUpdateEvent.eventName, e => { const updateEvent = e; const str = i18nString(UIStrings.processed); - // TraceEngine will report progress from [0...1] but we still have more work to do. So, scale them down a bit. + // Trace Engine will report progress from [0...1] but we still have more work to do. So, scale them down a bit. const traceParseMaxProgress = 0.7; - if (updateEvent.data.type === "COMPLETE" /* TraceEngine.TraceModel.ModelUpdateType.COMPLETE */) { + if (updateEvent.data.type === "COMPLETE" /* Trace.TraceModel.ModelUpdateType.COMPLETE */) { this.statusPane?.updateProgressBar(str, 100 * traceParseMaxProgress); } - else if (updateEvent.data.type === "PROGRESS_UPDATE" /* TraceEngine.TraceModel.ModelUpdateType.PROGRESS_UPDATE */) { + else if (updateEvent.data.type === "PROGRESS_UPDATE" /* Trace.TraceModel.ModelUpdateType.PROGRESS_UPDATE */) { const data = updateEvent.data.data; this.statusPane?.updateProgressBar(str, data.percent * 100 * traceParseMaxProgress); } @@ -1680,11 +1696,10 @@ export class TimelinePanel extends UI.Panel.Panel { } return; } - metadata = metadata ? - metadata : - await TraceEngine.Extras.Metadata.forNewRecording(isCpuProfile, recordingStartTime ?? undefined); + metadata = metadata ? metadata : + await Trace.Extras.Metadata.forNewRecording(isCpuProfile, recordingStartTime ?? undefined); try { - await this.#executeNewTraceEngine(collectedEvents, recordingIsFresh, metadata); + await this.#executeNewTrace(collectedEvents, recordingIsFresh, metadata); const traceIndex = this.#traceEngineModel.lastTraceIndex(); if (exclusiveFilter) { this.#exclusiveFilterPerTrace.set(traceIndex, exclusiveFilter); @@ -1693,12 +1708,12 @@ export class TimelinePanel extends UI.Panel.Panel { mode: 'VIEWING_TRACE', traceIndex, }); - const traceData = this.#traceEngineModel.traceParsedData(traceIndex); - if (!traceData) { + const parsedTrace = this.#traceEngineModel.parsedTrace(traceIndex); + if (!parsedTrace) { throw new Error(`Could not get trace data at index ${traceIndex}`); } if (recordingIsFresh) { - Tracker.instance().registerFreshRecording(traceData); + Tracker.instance().registerFreshRecording(parsedTrace); } // We store the index of the active trace so we can load it back easily // if the user goes to a different trace then comes back. @@ -1706,11 +1721,11 @@ export class TimelinePanel extends UI.Panel.Panel { // the preview overview thumbnail of the trace that gets shown in the UI. this.#historyManager.addRecording({ data: { - traceParseDataIndex: traceIndex, + parsedTraceIndex: traceIndex, type: 'TRACE_INDEX', }, - filmStripForPreview: TraceEngine.Extras.FilmStrip.fromTraceData(traceData), - traceParsedData: traceData, + filmStripForPreview: Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace), + parsedTrace, startTime: recordingStartTime ?? null, }); } @@ -1735,15 +1750,15 @@ export class TimelinePanel extends UI.Panel.Panel { // for the first paint of the flamechart requestAnimationFrame(() => { setTimeout(() => { - const end = TraceEngine.Types.Timing.MilliSeconds(performance.now()); + const end = Trace.Types.Timing.MilliSeconds(performance.now()); const measure = performance.measure('TraceLoad', { start, end }); - const duration = TraceEngine.Types.Timing.MilliSeconds(measure.duration); + const duration = Trace.Types.Timing.MilliSeconds(measure.duration); this.element.dispatchEvent(new TraceLoadEvent(duration)); Host.userMetrics.performanceTraceLoad(measure); }, 0); }); } - async #executeNewTraceEngine(collectedEvents, isFreshRecording, metadata) { + async #executeNewTrace(collectedEvents, isFreshRecording, metadata) { return this.#traceEngineModel.parse(collectedEvents, { metadata, isFreshRecording, @@ -1791,24 +1806,24 @@ export class TimelinePanel extends UI.Panel.Panel { return null; } if (TimelineSelection.isLegacyTimelineFrame(selection.object) && - selection.object instanceof TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame) { + selection.object instanceof Trace.Handlers.ModelHandlers.Frames.TimelineFrame) { return selection.object; } if (TimelineSelection.isRangeSelection(selection.object) || TimelineSelection.isSyntheticNetworkRequestDetailsEventSelection(selection.object)) { return null; } - if (TimelineSelection.isTraceEventSelection(selection.object)) { - const traceData = this.#traceEngineModel.traceParsedData(this.#viewMode.traceIndex); - if (!traceData) { + if (TimelineSelection.isSelection(selection.object)) { + const parsedTrace = this.#traceEngineModel.parsedTrace(this.#viewMode.traceIndex); + if (!parsedTrace) { return null; } // If the user has selected a time range, the frame we want is the last // frame in that time window, hence why the window we look for is the // endTime to the endTime. - const endTimeMicro = TraceEngine.Helpers.Timing.millisecondsToMicroseconds(selection.endTime); - const lastFrameInSelection = TraceEngine.Handlers.ModelHandlers.Frames - .framesWithinWindow(traceData.Frames.frames, endTimeMicro, endTimeMicro) + const endTimeMicro = Trace.Helpers.Timing.millisecondsToMicroseconds(selection.endTime); + const lastFrameInSelection = Trace.Handlers.ModelHandlers.Frames + .framesWithinWindow(parsedTrace.Frames.frames, endTimeMicro, endTimeMicro) .at(0); return lastFrameInSelection || null; } @@ -1823,15 +1838,15 @@ export class TimelinePanel extends UI.Panel.Panel { if (!currentFrame) { return; } - const traceData = this.#traceEngineModel.traceParsedData(this.#viewMode.traceIndex); - if (!traceData) { + const parsedTrace = this.#traceEngineModel.parsedTrace(this.#viewMode.traceIndex); + if (!parsedTrace) { return; } - let index = traceData.Frames.frames.indexOf(currentFrame); + let index = parsedTrace.Frames.frames.indexOf(currentFrame); console.assert(index >= 0, 'Can\'t find current frame in the frame list'); - index = Platform.NumberUtilities.clamp(index + offset, 0, traceData.Frames.frames.length - 1); - const frame = traceData.Frames.frames[index]; - this.#revealTimeRange(TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.startTime), TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.endTime)); + index = Platform.NumberUtilities.clamp(index + offset, 0, parsedTrace.Frames.frames.length - 1); + const frame = parsedTrace.Frames.frames[index]; + this.#revealTimeRange(Trace.Helpers.Timing.microSecondsToMilliseconds(frame.startTime), Trace.Helpers.Timing.microSecondsToMilliseconds(frame.endTime)); this.select(TimelineSelection.fromFrame(frame)); return true; } @@ -1850,8 +1865,8 @@ export class TimelinePanel extends UI.Panel.Panel { // Find best match, then backtrack to the first visible entry. for (let index = Platform.ArrayUtilities.upperBound(events, time, (time, event) => time - event.ts) - 1; index >= 0; --index) { const event = events[index]; - const { endTime } = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event); - if (TraceEngine.Helpers.Trace.isTopLevelEvent(event) && endTime < time) { + const { endTime } = Trace.Helpers.Timing.eventTimingsMilliSeconds(event); + if (Trace.Helpers.Trace.isTopLevelEvent(event) && endTime < time) { break; } if (ActiveFilters.instance().isVisible(event) && endTime >= time) { @@ -1877,7 +1892,7 @@ export class TimelinePanel extends UI.Panel.Panel { else if (traceWindow.min > startTime) { offset = startTime - traceWindow.min; } - TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(TraceEngine.Helpers.Timing.traceWindowFromMilliSeconds(TraceEngine.Types.Timing.MilliSeconds(traceWindow.min + offset), TraceEngine.Types.Timing.MilliSeconds(traceWindow.max + offset)), { + TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(Trace.Helpers.Timing.traceWindowFromMilliSeconds(Trace.Types.Timing.MilliSeconds(traceWindow.min + offset), Trace.Types.Timing.MilliSeconds(traceWindow.max + offset)), { shouldAnimate: true, }); } diff --git a/public/panels/timeline/TimelinePanel.js.map b/public/panels/timeline/TimelinePanel.js.map index 0c3ea60b9..f7bfc0b82 100644 --- a/public/panels/timeline/TimelinePanel.js.map +++ b/public/panels/timeline/TimelinePanel.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelinePanel.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelinePanel.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2021 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/*\n * Copyright (C) 2012 Google Inc. All rights reserved.\n * Copyright (C) 2012 Intel Inc. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * * Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above\n * copyright notice, this list of conditions and the following disclaimer\n * in the documentation and/or other materials provided with the\n * distribution.\n * * Neither the name of Google Inc. nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport * as Common from '../../core/common/common.js';\nimport * as Host from '../../core/host/host.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as Root from '../../core/root/root.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport type * as Protocol from '../../generated/protocol.js';\nimport type * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as Workspace from '../../models/workspace/workspace.js';\nimport * as TraceBounds from '../../services/trace_bounds/trace_bounds.js';\nimport * as Adorners from '../../ui/components/adorners/adorners.js';\nimport type * as Buttons from '../../ui/components/buttons/buttons.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\nimport * as MobileThrottling from '../mobile_throttling/mobile_throttling.js';\n\nimport {ActiveFilters} from './ActiveFilters.js';\nimport {TraceLoadEvent} from './BenchmarkEvents.js';\nimport * as TimelineComponents from './components/components.js';\nimport * as TimelineInsights from './components/insights/insights.js';\nimport {SHOULD_SHOW_EASTER_EGG} from './EasterEgg.js';\nimport {Tracker} from './FreshRecording.js';\nimport historyToolbarButtonStyles from './historyToolbarButton.css.js';\nimport {IsolateSelector} from './IsolateSelector.js';\nimport {AnnotationModifiedEvent, ModificationsManager} from './ModificationsManager.js';\nimport * as Overlays from './overlays/overlays.js';\nimport {cpuprofileJsonGenerator, traceJsonGenerator} from './SaveFileFormatter.js';\nimport {NodeNamesUpdated, SourceMapsResolver} from './SourceMapsResolver.js';\nimport {type Client, TimelineController} from './TimelineController.js';\nimport {TimelineFlameChartView} from './TimelineFlameChartView.js';\nimport {TimelineHistoryManager} from './TimelineHistoryManager.js';\nimport {TimelineLandingPage} from './TimelineLandingPage.js';\nimport {TimelineLoader} from './TimelineLoader.js';\nimport {TimelineMiniMap} from './TimelineMiniMap.js';\nimport timelinePanelStyles from './timelinePanel.css.js';\nimport {TimelineSelection} from './TimelineSelection.js';\nimport timelineStatusDialogStyles from './timelineStatusDialog.css.js';\nimport {TimelineUIUtils} from './TimelineUIUtils.js';\nimport {UIDevtoolsController} from './UIDevtoolsController.js';\nimport {UIDevtoolsUtils} from './UIDevtoolsUtils.js';\n\nconst UIStrings = {\n /**\n *@description Text that appears when user drag and drop something (for example, a file) in Timeline Panel of the Performance panel\n */\n dropTimelineFileOrUrlHere: 'Drop timeline file or URL here',\n /**\n *@description Title of disable capture jsprofile setting in timeline panel of the performance panel\n */\n disableJavascriptSamples: 'Disable JavaScript samples',\n /**\n *@description Title of capture layers and pictures setting in timeline panel of the performance panel\n */\n enableAdvancedPaint: 'Enable advanced paint instrumentation (slow)',\n /**\n *@description Title of CSS selector stats setting in timeline panel of the performance panel\n */\n enableSelectorStats: 'Enable CSS selector stats (slow)',\n /**\n *@description Title of show screenshots setting in timeline panel of the performance panel\n */\n screenshots: 'Screenshots',\n /**\n *@description Text for the memory of the page\n */\n memory: 'Memory',\n /**\n *@description Text to clear content\n */\n clear: 'Clear',\n /**\n *@description A label for a button that fixes something.\n */\n fixMe: 'Fix me',\n /**\n *@description Tooltip text that appears when hovering over the largeicon load button\n */\n loadProfile: 'Load profile…',\n /**\n *@description Tooltip text that appears when hovering over the largeicon download button\n */\n saveProfile: 'Save profile…',\n /**\n *@description An option to save trace with annotations that appears in the menu of the toolbar download button. This is the expected default option, therefore it does not mention annotations.\n */\n saveTraceWithAnnotationsMenuOption: 'Save trace',\n /**\n *@description An option to save trace without annotations that appears in the menu of the toolbar download button\n */\n saveTraceWithoutAnnotationsMenuOption: 'Save trace without annotations',\n /**\n *@description Text to take screenshots\n */\n captureScreenshots: 'Capture screenshots',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n showMemoryTimeline: 'Show memory timeline',\n /**\n *@description Tooltip text that appears when hovering over the largeicon settings gear in show settings pane setting in timeline panel of the performance panel\n */\n captureSettings: 'Capture settings',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n disablesJavascriptSampling: 'Disables JavaScript sampling, reduces overhead when running against mobile devices',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n capturesAdvancedPaint: 'Captures advanced paint instrumentation, introduces significant performance overhead',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n capturesSelectorStats: 'Captures CSS selector statistics',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n network: 'Network:',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n cpu: 'CPU:',\n /**\n *@description Title of the 'Network conditions' tool in the bottom drawer\n */\n networkConditions: 'Network conditions',\n /**\n *@description Text in Timeline Panel of the Performance panel\n *@example {wrong format} PH1\n *@example {ERROR_FILE_NOT_FOUND} PH2\n */\n failedToSaveTimelineSS: 'Failed to save timeline: {PH1} ({PH2})',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n CpuThrottlingIsEnabled: '- CPU throttling is enabled',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n NetworkThrottlingIsEnabled: '- Network throttling is enabled',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n HardwareConcurrencyIsEnabled: '- Hardware concurrency override is enabled',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n SignificantOverheadDueToPaint: '- Significant overhead due to paint instrumentation',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n SelectorStatsEnabled: '- Selector stats is enabled',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n JavascriptSamplingIsDisabled: '- JavaScript sampling is disabled',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n stoppingTimeline: 'Stopping timeline…',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n received: 'Received',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n processed: 'Processed',\n /**\n *@description Text to close something\n */\n close: 'Close',\n /**\n *@description Text to download the raw trace files after an error\n */\n downloadAfterError: 'Download raw trace events',\n /**\n *@description Status text to indicate the recording has failed in the Performance panel\n */\n recordingFailed: 'Recording failed',\n /**\n * @description Text to indicate the progress of a profile. Informs the user that we are currently\n * creating a peformance profile.\n */\n profiling: 'Profiling…',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n bufferUsage: 'Buffer usage',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n loadingProfile: 'Loading profile…',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n processingProfile: 'Processing profile…',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n initializingProfiler: 'Initializing profiler…',\n /**\n *@description Text for the status of something\n */\n status: 'Status',\n /**\n *@description Text that refers to the time\n */\n time: 'Time',\n /**\n *@description Text for the description of something\n */\n description: 'Description',\n /**\n *@description Text of an item that stops the running task\n */\n stop: 'Stop',\n /**\n *@description Time text content in Timeline Panel of the Performance panel\n *@example {2.12} PH1\n */\n ssec: '{PH1} sec',\n /**\n *\n * @description Text for exporting basic traces\n */\n exportNormalTraces: 'Basic performance traces',\n /**\n *\n * @description Text for exporting enhanced traces\n */\n exportEnhancedTraces: 'Enhanced performance traces',\n /**\n *@description Tooltip description for a checkbox that toggles the visibility of data added by extensions of this panel (Performance).\n */\n showDataAddedByExtensions: 'Show data added by extensions of the Performance panel',\n /**\n Label for a checkbox that toggles the visibility of data added by extensions of this panel (Performance).\n */\n performanceExtension: 'Extension data',\n\n /**\n * @description Tooltip for the the sidebar toggle in the Performance panel. Command to open/show the sidebar.\n */\n showSidebar: 'Show sidebar',\n /**\n * @description Tooltip for the the sole sidebar toggle in the Performance panel. Command to close the sidebar.\n */\n hideSidebar: 'Hide sole sidebar',\n /**\n * @description Screen reader announcement when the sidebar is shown in the Performance panel.\n */\n sidebarShown: 'Performance sidebar shown',\n /**\n * @description Screen reader announcement when the sidebar is hidden in the Performance panel.\n */\n sidebarHidden: 'Performance sidebar hidden',\n\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelinePanel.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nlet timelinePanelInstance: TimelinePanel;\nlet isNode: boolean;\n\n/**\n * Represents the states that the timeline panel can be in.\n * If you need to change the panel's view, use the {@see #changeView} method.\n * Note that we do not represent the \"Loading/Processing\" view here. The\n * StatusPane is managed in the code that handles file import/recording, and\n * when it is visible it is rendered on top of the UI so obscures what is behind\n * it. When it completes, we will set the view mode to the trace that has been\n * loaded.\n */\ntype ViewMode = {\n mode: 'LANDING_PAGE',\n}|{\n mode: 'VIEWING_TRACE',\n traceIndex: number,\n}|{\n mode: 'STATUS_PANE_OVERLAY',\n};\n\nexport class TimelinePanel extends UI.Panel.Panel implements Client, TimelineModeViewDelegate {\n private readonly dropTarget: UI.DropTarget.DropTarget;\n private readonly recordingOptionUIControls: UI.Toolbar.ToolbarItem[];\n private state: State;\n private recordingPageReload: boolean;\n private readonly millisecondsToRecordAfterLoadEvent: number;\n private readonly toggleRecordAction: UI.ActionRegistration.Action;\n private readonly recordReloadAction: UI.ActionRegistration.Action;\n readonly #historyManager: TimelineHistoryManager;\n private disableCaptureJSProfileSetting: Common.Settings.Setting;\n private readonly captureLayersAndPicturesSetting: Common.Settings.Setting;\n private readonly captureSelectorStatsSetting: Common.Settings.Setting;\n readonly #thirdPartyTracksSetting: Common.Settings.Setting;\n private showScreenshotsSetting: Common.Settings.Setting;\n private showMemorySetting: Common.Settings.Setting;\n private readonly panelToolbar: UI.Toolbar.Toolbar;\n private readonly panelRightToolbar: UI.Toolbar.Toolbar;\n private readonly timelinePane: UI.Widget.VBox;\n readonly #minimapComponent = new TimelineMiniMap();\n #viewMode: ViewMode = {mode: 'LANDING_PAGE'};\n\n /**\n * We get given any filters for a new trace when it is recorded/imported.\n * Because the user can then use the dropdown to navigate to another trace,\n * we store the filters by the trace index, so if the user then navigates back\n * to a previous trace we can reinstate the filters from this map.\n */\n #exclusiveFilterPerTrace: Map = new Map();\n /**\n * This widget holds the timeline sidebar which shows Insights & Annotations,\n * and the main UI which shows the timeline\n */\n readonly #splitWidget = new UI.SplitWidget.SplitWidget(\n true, // isVertical\n false, // secondIsSidebar\n 'timeline-panel-sidebar-state', // settingName (to persist the open/closed state for the user)\n TimelineComponents.Sidebar.DEFAULT_SIDEBAR_WIDTH_PX,\n );\n private readonly statusPaneContainer: HTMLElement;\n private readonly flameChart: TimelineFlameChartView;\n private readonly searchableViewInternal: UI.SearchableView.SearchableView;\n private showSettingsPaneButton!: UI.Toolbar.ToolbarSettingToggle;\n private showSettingsPaneSetting!: Common.Settings.Setting;\n private settingsPane!: UI.Widget.Widget;\n private controller!: TimelineController|null;\n private cpuProfiler!: SDK.CPUProfilerModel.CPUProfilerModel|null;\n private clearButton!: UI.Toolbar.ToolbarButton;\n private brickBreakerToolbarButton: UI.Toolbar.ToolbarButton;\n private brickBreakerToolbarButtonAdded = false;\n private loadButton!: UI.Toolbar.ToolbarButton;\n private saveButton!: UI.Toolbar.ToolbarButton|UI.Toolbar.ToolbarMenuButton;\n private statusPane!: StatusPane|null;\n private landingPage!: UI.Widget.Widget;\n private loader?: TimelineLoader;\n private showScreenshotsToolbarCheckbox?: UI.Toolbar.ToolbarItem;\n private showMemoryToolbarCheckbox?: UI.Toolbar.ToolbarItem;\n private networkThrottlingSelect?: UI.Toolbar.ToolbarComboBox;\n private cpuThrottlingSelect?: UI.Toolbar.ToolbarComboBox;\n private fileSelectorElement?: HTMLInputElement;\n private selection?: TimelineSelection|null;\n private traceLoadStart!: TraceEngine.Types.Timing.MilliSeconds|null;\n private primaryPageTargetPromiseCallback = (_target: SDK.Target.Target): void => {};\n // Note: this is technically unused, but we need it to define the promiseCallback function above.\n private primaryPageTargetPromise = new Promise(res => {\n this.primaryPageTargetPromiseCallback = res;\n });\n\n #traceEngineModel: TraceEngine.TraceModel.Model;\n #sourceMapsResolver: SourceMapsResolver|null = null;\n #onSourceMapsNodeNamesResolvedBound = this.#onSourceMapsNodeNamesResolved.bind(this);\n readonly #onChartPlayableStateChangeBound: (event: Common.EventTarget.EventTargetEvent) => void;\n #sidebarToggleButton = this.#splitWidget.createShowHideSidebarButton(\n i18nString(UIStrings.showSidebar),\n i18nString(UIStrings.hideSidebar),\n // These are used to announce to screen-readers and not shown visibly.\n i18nString(UIStrings.sidebarShown),\n i18nString(UIStrings.sidebarHidden),\n 'timeline.sidebar', // jslog context\n );\n\n #sideBar = new TimelineComponents.Sidebar.SidebarWidget();\n /**\n * Rather than auto-pop the sidebar every time the user records a trace,\n * which could get annoying, we instead persist the state of the sidebar\n * visibility to a setting so it's restored across sessions.\n * However, sometimes we have to automatically hide the sidebar, like when a\n * trace recording is happening, or the user is on the landing page. In those\n * times, we toggle this flag to true. Then, when we enter the VIEWING_TRACE\n * mode, we check this flag and pop the sidebar open if it's set to true.\n * Longer term a better fix here would be to divide the 3 UI screens\n * (status pane, landing page, trace view) into distinct components /\n * widgets, to avoid this complexity.\n */\n #restoreSidebarVisibilityOnTraceLoad: boolean = false;\n\n constructor() {\n super('timeline');\n const adornerContent = document.createElement('span');\n adornerContent.innerHTML = `
💫
`;\n const adorner = new Adorners.Adorner.Adorner();\n adorner.classList.add('fix-perf-icon');\n adorner.data = {\n name: i18nString(UIStrings.fixMe),\n content: adornerContent,\n };\n this.brickBreakerToolbarButton = new UI.Toolbar.ToolbarButton(i18nString(UIStrings.fixMe), adorner);\n this.brickBreakerToolbarButton.addEventListener(\n UI.Toolbar.ToolbarButton.Events.CLICK, () => this.#onBrickBreakerEasterEggClick());\n const config = TraceEngine.Types.Configuration.defaults();\n config.showAllEvents = Root.Runtime.experiments.isEnabled('timeline-show-all-events');\n config.includeRuntimeCallStats = Root.Runtime.experiments.isEnabled('timeline-v8-runtime-call-stats');\n config.debugMode = Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_DEBUG_MODE);\n\n this.#traceEngineModel = TraceEngine.TraceModel.Model.createWithAllHandlers(config);\n this.#listenForProcessingProgress();\n\n this.element.addEventListener('contextmenu', this.contextMenu.bind(this), false);\n this.dropTarget = new UI.DropTarget.DropTarget(\n this.element, [UI.DropTarget.Type.File, UI.DropTarget.Type.URI],\n i18nString(UIStrings.dropTimelineFileOrUrlHere), this.handleDrop.bind(this));\n\n this.recordingOptionUIControls = [];\n this.state = State.IDLE;\n this.recordingPageReload = false;\n this.millisecondsToRecordAfterLoadEvent = 5000;\n this.toggleRecordAction = UI.ActionRegistry.ActionRegistry.instance().getAction('timeline.toggle-recording');\n this.recordReloadAction = UI.ActionRegistry.ActionRegistry.instance().getAction('timeline.record-reload');\n\n this.#historyManager = new TimelineHistoryManager(this.#minimapComponent);\n\n this.traceLoadStart = null;\n\n this.disableCaptureJSProfileSetting =\n Common.Settings.Settings.instance().createSetting('timeline-disable-js-sampling', false);\n this.disableCaptureJSProfileSetting.setTitle(i18nString(UIStrings.disableJavascriptSamples));\n this.captureLayersAndPicturesSetting = Common.Settings.Settings.instance().createSetting(\n 'timeline-capture-layers-and-pictures', false, Common.Settings.SettingStorageType.SESSION);\n this.captureLayersAndPicturesSetting.setTitle(i18nString(UIStrings.enableAdvancedPaint));\n this.captureSelectorStatsSetting = Common.Settings.Settings.instance().createSetting(\n 'timeline-capture-selector-stats', false, Common.Settings.SettingStorageType.SESSION);\n this.captureSelectorStatsSetting.setTitle(i18nString(UIStrings.enableSelectorStats));\n\n this.showScreenshotsSetting =\n Common.Settings.Settings.instance().createSetting('timeline-show-screenshots', isNode ? false : true);\n this.showScreenshotsSetting.setTitle(i18nString(UIStrings.screenshots));\n this.showScreenshotsSetting.addChangeListener(this.updateMiniMap, this);\n\n this.showMemorySetting = Common.Settings.Settings.instance().createSetting('timeline-show-memory', false);\n this.showMemorySetting.setTitle(i18nString(UIStrings.memory));\n this.showMemorySetting.addChangeListener(this.onModeChanged, this);\n\n this.#thirdPartyTracksSetting = TimelinePanel.extensionDataVisibilitySetting();\n this.#thirdPartyTracksSetting.addChangeListener(this.#extensionDataVisibilityChanged, this);\n this.#thirdPartyTracksSetting.setTitle(i18nString(UIStrings.performanceExtension));\n\n const timelineToolbarContainer = this.element.createChild('div', 'timeline-toolbar-container');\n timelineToolbarContainer.setAttribute('jslog', `${VisualLogging.toolbar()}`);\n this.panelToolbar = new UI.Toolbar.Toolbar('timeline-main-toolbar', timelineToolbarContainer);\n this.panelToolbar.makeWrappable(true);\n this.panelRightToolbar = new UI.Toolbar.Toolbar('', timelineToolbarContainer);\n if (!isNode) {\n this.createSettingsPane();\n this.updateShowSettingsToolbarButton();\n }\n this.timelinePane = new UI.Widget.VBox();\n const topPaneElement = this.timelinePane.element.createChild('div', 'hbox');\n topPaneElement.id = 'timeline-overview-panel';\n\n this.#minimapComponent.show(topPaneElement);\n\n this.statusPaneContainer = this.timelinePane.element.createChild('div', 'status-pane-container fill');\n\n this.createFileSelector();\n\n SDK.TargetManager.TargetManager.instance().addModelListener(\n SDK.ResourceTreeModel.ResourceTreeModel, SDK.ResourceTreeModel.Events.Load, this.loadEventFired, this);\n\n this.flameChart = new TimelineFlameChartView(this);\n this.#onChartPlayableStateChangeBound = this.#onChartPlayableStateChange.bind(this);\n\n this.flameChart.getMainFlameChart().addEventListener(\n PerfUI.FlameChart.Events.CHART_PLAYABLE_STATE_CHANGED, this.#onChartPlayableStateChangeBound, this);\n\n this.searchableViewInternal = new UI.SearchableView.SearchableView(this.flameChart, null);\n this.searchableViewInternal.setMinimumSize(0, 100);\n this.searchableViewInternal.element.classList.add('searchable-view');\n this.searchableViewInternal.show(this.timelinePane.element);\n this.flameChart.show(this.searchableViewInternal.element);\n this.flameChart.setSearchableView(this.searchableViewInternal);\n this.searchableViewInternal.hideWidget();\n\n this.#splitWidget.setMainWidget(this.timelinePane);\n this.#splitWidget.setSidebarWidget(this.#sideBar);\n this.#splitWidget.enableShowModeSaving();\n this.#splitWidget.show(this.element);\n\n this.#sideBar.element.addEventListener(TimelineInsights.SidebarInsight.InsightDeactivated.eventName, () => {\n this.#setActiveInsight(null);\n });\n\n this.#sideBar.element.addEventListener(TimelineInsights.SidebarInsight.InsightActivated.eventName, event => {\n const {name, navigationId, createOverlayFn} = event;\n this.#setActiveInsight({name, navigationId, createOverlayFn});\n });\n\n this.#sideBar.contentElement.addEventListener(TimelineComponents.Sidebar.EventReferenceClick.eventName, event => {\n const {metricEvent} = event;\n this.flameChart.setSelectionAndReveal(TimelineSelection.fromTraceEvent(metricEvent));\n });\n\n this.#sideBar.element.addEventListener(TimelineComponents.Sidebar.RemoveAnnotation.eventName, event => {\n const {removedAnnotation} = (event as TimelineComponents.Sidebar.RemoveAnnotation);\n ModificationsManager.activeManager()?.removeAnnotation(removedAnnotation);\n });\n\n this.onModeChanged();\n this.populateToolbar();\n // The viewMode is set by default to the landing page, so we don't call\n // `#changeView` here and can instead directly call showLandingPage();\n this.#showLandingPage();\n this.updateTimelineControls();\n\n SDK.TargetManager.TargetManager.instance().addEventListener(\n SDK.TargetManager.Events.SUSPEND_STATE_CHANGED, this.onSuspendStateChanged, this);\n const profilerModels = SDK.TargetManager.TargetManager.instance().models(SDK.CPUProfilerModel.CPUProfilerModel);\n for (const model of profilerModels) {\n for (const message of model.registeredConsoleProfileMessages) {\n this.consoleProfileFinished(message);\n }\n }\n SDK.TargetManager.TargetManager.instance().observeModels(\n SDK.CPUProfilerModel.CPUProfilerModel,\n {\n modelAdded: (model: SDK.CPUProfilerModel.CPUProfilerModel) => {\n model.addEventListener(\n SDK.CPUProfilerModel.Events.CONSOLE_PROFILE_FINISHED, event => this.consoleProfileFinished(event.data));\n },\n modelRemoved: (_model: SDK.CPUProfilerModel.CPUProfilerModel) => {\n\n },\n },\n );\n SDK.TargetManager.TargetManager.instance().observeTargets({\n targetAdded: (target: SDK.Target.Target) => {\n if (target !== SDK.TargetManager.TargetManager.instance().primaryPageTarget()) {\n return;\n }\n this.primaryPageTargetPromiseCallback(target);\n },\n targetRemoved: (_: SDK.Target.Target) => {},\n });\n }\n\n #setActiveInsight(insight: TimelineComponents.Sidebar.ActiveInsight|null): void {\n this.#sideBar.setActiveInsight(insight);\n this.flameChart.setActiveInsight(insight);\n }\n\n static instance(opts: {\n forceNew: boolean|null,\n isNode: boolean,\n }|undefined = {forceNew: null, isNode: false}): TimelinePanel {\n const {forceNew, isNode: isNodeMode} = opts;\n isNode = isNodeMode;\n\n if (!timelinePanelInstance || forceNew) {\n timelinePanelInstance = new TimelinePanel();\n }\n\n return timelinePanelInstance;\n }\n\n static extensionDataVisibilitySetting(): Common.Settings.Setting {\n // Calling this multiple times doesn't recreate the setting.\n // Instead, after the second call, the cached setting is returned.\n return Common.Settings.Settings.instance().createSetting('timeline-show-extension-data', true);\n }\n override searchableView(): UI.SearchableView.SearchableView|null {\n return this.searchableViewInternal;\n }\n\n override wasShown(): void {\n super.wasShown();\n UI.Context.Context.instance().setFlavor(TimelinePanel, this);\n this.registerCSSFiles([timelinePanelStyles]);\n // Record the performance tool load time.\n Host.userMetrics.panelLoaded('timeline', 'DevTools.Launch.Timeline');\n }\n\n override willHide(): void {\n UI.Context.Context.instance().setFlavor(TimelinePanel, null);\n this.#historyManager.cancelIfShowing();\n }\n\n loadFromEvents(events: TraceEngine.Types.TraceEvents.TraceEventData[]): void {\n if (this.state !== State.IDLE) {\n return;\n }\n this.prepareToLoadTimeline();\n this.loader = TimelineLoader.loadFromEvents(events, this);\n }\n\n getFlameChart(): TimelineFlameChartView {\n return this.flameChart;\n }\n\n getMinimap(): TimelineMiniMap {\n return this.#minimapComponent;\n }\n\n /**\n * Determine if two view modes are equivalent. Useful because if {@see\n * #changeView} gets called and the new mode is identical to the current,\n * we can bail without doing any UI updates.\n */\n #viewModesEquivalent(m1: ViewMode, m2: ViewMode): boolean {\n if (m1.mode === 'LANDING_PAGE' && m2.mode === 'LANDING_PAGE') {\n return true;\n }\n\n if (m1.mode === 'STATUS_PANE_OVERLAY' && m2.mode === 'STATUS_PANE_OVERLAY') {\n return true;\n }\n\n // VIEWING_TRACE views are only equivalent if their traceIndex is the same.\n if (m1.mode === 'VIEWING_TRACE' && m2.mode === 'VIEWING_TRACE' && m1.traceIndex === m2.traceIndex) {\n return true;\n }\n return false;\n }\n\n #uninstallSourceMapsResolver(): void {\n if (this.#sourceMapsResolver) {\n // this set of NodeNames is cached by PIDs, so we clear it so we don't\n // use incorrect names from another trace that might happen to share\n // PID/TIDs.\n SourceMapsResolver.clearResolvedNodeNames();\n\n this.#sourceMapsResolver.removeEventListener(\n NodeNamesUpdated.eventName, this.#onSourceMapsNodeNamesResolvedBound);\n this.#sourceMapsResolver.uninstall();\n this.#sourceMapsResolver = null;\n }\n }\n\n #removeStatusPane(): void {\n if (this.statusPane) {\n this.statusPane.remove();\n }\n this.statusPane = null;\n }\n\n #changeView(newMode: ViewMode): void {\n if (this.#viewModesEquivalent(this.#viewMode, newMode)) {\n return;\n }\n\n if (this.#viewMode.mode === 'VIEWING_TRACE') {\n // If the current / about to be \"old\" view was viewing a trace\n // we also uninstall any source maps resolver for the trace that was active.\n // If the user swaps back to this trace via the history dropdown, this will be reinstated.\n this.#uninstallSourceMapsResolver();\n\n // Store any modifications (e.g. annotations) that the user has created\n // on the current trace before we move away to a new view.\n this.#saveModificationsForActiveTrace();\n }\n\n this.#viewMode = newMode;\n\n /**\n * Note that the TimelinePanel UI is really rendered in two distinct layers.\n * 1. status-pane-container: this is what renders both the StatusPane\n * loading modal AND the landing page.\n * What is important to note is that this renders ON TOP of the\n * SearchableView widget, which is what holds the FlameChartView.\n *\n * 2. SearchableView: this is the container that renders\n * TimelineFlameChartView and the rest of the flame chart code.\n *\n * What this layering means is that when we swap to the LANDING_PAGE or\n * STATUS_PANE_OVERLAY view, we don't actually need to reset the\n * SearchableView that is rendered behind it, because it won't be visible\n * and will be hidden behind the StatusPane/Landing Page.\n *\n * So the only time we update this SearchableView is when the user goes to\n * view a trace. That is why in the switch() statement below you won't see\n * any code that resets the SearchableView because we don't need to. We do\n * mark it as hidden, but mainly so the user can't accidentally use Cmd-F\n * to search a hidden view.\n */\n switch (newMode.mode) {\n case 'LANDING_PAGE': {\n this.#removeStatusPane();\n this.#showLandingPage();\n\n // Whilst we don't reset this, we hide it, mainly so the user cannot\n // hit Ctrl/Cmd-F and try to search when it isn't visible.\n this.searchableViewInternal.hideWidget();\n\n // Hide the brick-breaker easter egg\n this.brickBreakerToolbarButtonAdded = false;\n this.panelToolbar.removeToolbarItem(this.brickBreakerToolbarButton);\n return;\n }\n\n case 'VIEWING_TRACE': {\n this.#hideLandingPage();\n this.#setModelForActiveTrace();\n this.#removeStatusPane();\n this.#showSidebarIfRequired();\n return;\n }\n\n case 'STATUS_PANE_OVERLAY': {\n // We don't manage the StatusPane UI here; it is done in the\n // recordingStarted/recordingProgress callbacks, but we do make sure we\n // hide the landing page.\n this.#hideLandingPage();\n\n // We also hide the sidebar - else if the user is viewing a trace and\n // then load/record another, the sidebar remains visible.\n this.#hideSidebar();\n return;\n }\n default:\n Platform.assertNever(newMode, 'Unsupported TimelinePanel viewMode');\n }\n }\n\n #activeTraceIndex(): number|null {\n if (this.#viewMode.mode === 'VIEWING_TRACE') {\n return this.#viewMode.traceIndex;\n }\n return null;\n }\n\n /**\n * NOTE: this method only exists to enable some layout tests to be migrated to the new engine.\n * DO NOT use this method within DevTools. It is marked as deprecated so\n * within DevTools you are warned when using the method.\n * @deprecated\n **/\n getTraceEngineDataForLayoutTests(): TraceEngine.Handlers.Types.TraceParseData {\n const traceIndex = this.#activeTraceIndex();\n if (traceIndex === null) {\n throw new Error('No trace index active.');\n }\n const data = this.#traceEngineModel.traceParsedData(traceIndex);\n if (data === null) {\n throw new Error('No trace engine data found.');\n }\n return data;\n }\n\n /**\n * NOTE: this method only exists to enable some layout tests to be migrated to the new engine.\n * DO NOT use this method within DevTools. It is marked as deprecated so\n * within DevTools you are warned when using the method.\n * @deprecated\n **/\n getTraceEngineRawTraceEventsForLayoutTests(): readonly TraceEngine.Types.TraceEvents.TraceEventData[] {\n const traceIndex = this.#activeTraceIndex();\n if (traceIndex === null) {\n throw new Error('No trace index active.');\n }\n const data = this.#traceEngineModel.rawTraceEvents(traceIndex);\n if (data === null) {\n throw new Error('No trace engine data found.');\n }\n return data;\n }\n\n #onChartPlayableStateChange(event: Common.EventTarget.EventTargetEvent): void {\n if (event.data) {\n const dateObj = new Date();\n const month = dateObj.getUTCMonth() + 1;\n const day = dateObj.getUTCDate();\n const isAprilFools = (month === 4 && (day === 1 || day === 2)); // Show only on April fools and the next day\n if (isAprilFools && !this.brickBreakerToolbarButtonAdded && SHOULD_SHOW_EASTER_EGG) {\n this.brickBreakerToolbarButtonAdded = true;\n this.panelToolbar.appendToolbarItem(this.brickBreakerToolbarButton);\n }\n } else {\n this.brickBreakerToolbarButtonAdded = false;\n this.panelToolbar.removeToolbarItem(this.brickBreakerToolbarButton);\n }\n }\n\n private loadFromCpuProfile(profile: Protocol.Profiler.Profile|null): void {\n if (this.state !== State.IDLE || profile === null) {\n return;\n }\n this.prepareToLoadTimeline();\n this.loader = TimelineLoader.loadFromCpuProfile(profile, this);\n }\n\n private setState(state: State): void {\n this.state = state;\n this.updateTimelineControls();\n }\n\n private createSettingCheckbox(setting: Common.Settings.Setting, tooltip: string): UI.Toolbar.ToolbarItem {\n const checkboxItem = new UI.Toolbar.ToolbarSettingCheckbox(setting, tooltip);\n this.recordingOptionUIControls.push(checkboxItem);\n return checkboxItem;\n }\n\n /**\n * Users don't explicitly opt in to the sidebar, but if they opt into either\n * Insights or Annotations, we will show the sidebar.\n */\n #panelSidebarEnabled(): boolean {\n const sidebarEnabled = Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_INSIGHTS) ||\n Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_ANNOTATIONS);\n return sidebarEnabled;\n }\n #addSidebarIconToToolbar(): void {\n if (!this.#panelSidebarEnabled()) {\n return;\n }\n\n if (this.panelToolbar.hasItem(this.#sidebarToggleButton)) {\n return;\n }\n\n this.panelToolbar.prependToolbarItem(this.#sidebarToggleButton);\n }\n\n /**\n * Used when the user deletes their last trace and is taken back to the\n * landing page - we don't add this icon until there is a trace loaded.\n */\n #removeSidebarIconFromToolbar(): void {\n this.panelToolbar.removeToolbarItem(this.#sidebarToggleButton);\n }\n\n private populateDownloadMenu(contextMenu: UI.ContextMenu.ContextMenu): void {\n contextMenu.viewSection().appendItem(i18nString(UIStrings.saveTraceWithAnnotationsMenuOption), () => {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.PerfPanelTraceExported);\n void this.saveToFile(/* isEnhancedTraces */ false, /* addModifications */ true);\n });\n contextMenu.viewSection().appendItem(i18nString(UIStrings.saveTraceWithoutAnnotationsMenuOption), () => {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.PerfPanelTraceExported);\n void this.saveToFile();\n });\n }\n\n private populateToolbar(): void {\n // Record\n this.panelToolbar.appendToolbarItem(UI.Toolbar.Toolbar.createActionButton(this.toggleRecordAction));\n this.panelToolbar.appendToolbarItem(UI.Toolbar.Toolbar.createActionButton(this.recordReloadAction));\n this.clearButton = new UI.Toolbar.ToolbarButton(i18nString(UIStrings.clear), 'clear', undefined, 'timeline.clear');\n this.clearButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, () => this.onClearButton());\n this.panelToolbar.appendToolbarItem(this.clearButton);\n\n // Load / SaveCLICK\n this.loadButton =\n new UI.Toolbar.ToolbarButton(i18nString(UIStrings.loadProfile), 'import', undefined, 'timeline.load-from-file');\n this.loadButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, () => {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.PerfPanelTraceImported);\n this.selectFileToLoad();\n });\n\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_ANNOTATIONS)) {\n this.saveButton = new UI.Toolbar.ToolbarMenuButton(\n this.populateDownloadMenu.bind(this), true, true, 'more-options', 'download');\n this.saveButton.setTitle(i18nString(UIStrings.saveProfile));\n } else {\n this.saveButton = new UI.Toolbar.ToolbarButton(\n i18nString(UIStrings.saveProfile), 'download', undefined, 'timeline.save-to-file');\n this.saveButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, _event => {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.PerfPanelTraceExported);\n void this.saveToFile();\n });\n }\n\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_ENHANCED_TRACES)) {\n this.saveButton.element.addEventListener('contextmenu', event => {\n event.preventDefault();\n event.stopPropagation();\n\n if (event.ctrlKey || event.button === 2) {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n contextMenu.saveSection().appendItem(i18nString(UIStrings.exportNormalTraces), () => {\n void this.saveToFile();\n });\n contextMenu.saveSection().appendItem(i18nString(UIStrings.exportEnhancedTraces), () => {\n void this.saveToFile(/* isEnhancedTraces */ true);\n });\n\n void contextMenu.show();\n } else {\n void this.saveToFile();\n }\n });\n }\n\n this.panelToolbar.appendSeparator();\n this.panelToolbar.appendToolbarItem(this.loadButton);\n this.panelToolbar.appendToolbarItem(this.saveButton);\n\n // History\n this.panelToolbar.appendSeparator();\n this.panelToolbar.appendToolbarItem(this.#historyManager.button());\n this.panelToolbar.registerCSSFiles([historyToolbarButtonStyles]);\n this.panelToolbar.appendSeparator();\n\n // View\n this.panelToolbar.appendSeparator();\n if (!isNode) {\n this.showScreenshotsToolbarCheckbox =\n this.createSettingCheckbox(this.showScreenshotsSetting, i18nString(UIStrings.captureScreenshots));\n this.panelToolbar.appendToolbarItem(this.showScreenshotsToolbarCheckbox);\n }\n\n this.showMemoryToolbarCheckbox =\n this.createSettingCheckbox(this.showMemorySetting, i18nString(UIStrings.showMemoryTimeline));\n this.panelToolbar.appendToolbarItem(this.showMemoryToolbarCheckbox);\n\n // GC\n this.panelToolbar.appendToolbarItem(UI.Toolbar.Toolbar.createActionButtonForId('components.collect-garbage'));\n\n // Isolate selector\n const isolateSelector = new IsolateSelector();\n if (isNode) {\n this.panelToolbar.appendSeparator();\n this.panelToolbar.appendToolbarItem(isolateSelector);\n }\n\n // Settings\n if (!isNode) {\n this.panelRightToolbar.appendSeparator();\n this.panelRightToolbar.appendToolbarItem(this.showSettingsPaneButton);\n }\n }\n\n private createSettingsPane(): void {\n this.showSettingsPaneSetting =\n Common.Settings.Settings.instance().createSetting('timeline-show-settings-toolbar', false);\n this.showSettingsPaneButton = new UI.Toolbar.ToolbarSettingToggle(\n this.showSettingsPaneSetting, 'gear', i18nString(UIStrings.captureSettings), 'gear-filled',\n 'timeline-settings-toggle');\n SDK.NetworkManager.MultitargetNetworkManager.instance().addEventListener(\n SDK.NetworkManager.MultitargetNetworkManager.Events.CONDITIONS_CHANGED, this.updateShowSettingsToolbarButton,\n this);\n SDK.CPUThrottlingManager.CPUThrottlingManager.instance().addEventListener(\n SDK.CPUThrottlingManager.Events.RATE_CHANGED, this.updateShowSettingsToolbarButton, this);\n SDK.CPUThrottlingManager.CPUThrottlingManager.instance().addEventListener(\n SDK.CPUThrottlingManager.Events.HARDWARE_CONCURRENCY_CHANGED, this.updateShowSettingsToolbarButton, this);\n this.disableCaptureJSProfileSetting.addChangeListener(this.updateShowSettingsToolbarButton, this);\n this.captureLayersAndPicturesSetting.addChangeListener(this.updateShowSettingsToolbarButton, this);\n this.captureSelectorStatsSetting.addChangeListener(this.updateShowSettingsToolbarButton, this);\n\n this.settingsPane = new UI.Widget.HBox();\n this.settingsPane.element.classList.add('timeline-settings-pane');\n this.settingsPane.element.setAttribute(\n 'jslog', `${VisualLogging.pane('timeline-settings-pane').track({resize: true})}`);\n this.settingsPane.show(this.element);\n\n const captureToolbar = new UI.Toolbar.Toolbar('', this.settingsPane.element);\n captureToolbar.element.classList.add('flex-auto');\n captureToolbar.makeVertical();\n captureToolbar.appendToolbarItem(this.createSettingCheckbox(\n this.disableCaptureJSProfileSetting, i18nString(UIStrings.disablesJavascriptSampling)));\n captureToolbar.appendToolbarItem(\n this.createSettingCheckbox(this.captureLayersAndPicturesSetting, i18nString(UIStrings.capturesAdvancedPaint)));\n captureToolbar.appendToolbarItem(\n this.createSettingCheckbox(this.captureSelectorStatsSetting, i18nString(UIStrings.capturesSelectorStats)));\n\n const throttlingPane = new UI.Widget.VBox();\n throttlingPane.element.classList.add('flex-auto');\n throttlingPane.show(this.settingsPane.element);\n\n const cpuThrottlingToolbar = new UI.Toolbar.Toolbar('', throttlingPane.element);\n cpuThrottlingToolbar.appendText(i18nString(UIStrings.cpu));\n this.cpuThrottlingSelect = MobileThrottling.ThrottlingManager.throttlingManager().createCPUThrottlingSelector();\n cpuThrottlingToolbar.appendToolbarItem(this.cpuThrottlingSelect);\n\n const networkThrottlingToolbar = new UI.Toolbar.Toolbar('', throttlingPane.element);\n networkThrottlingToolbar.appendText(i18nString(UIStrings.network));\n this.networkThrottlingSelect = this.createNetworkConditionsSelect();\n networkThrottlingToolbar.appendToolbarItem(this.networkThrottlingSelect);\n\n const hardwareConcurrencyPane = new UI.Widget.VBox();\n hardwareConcurrencyPane.element.classList.add('flex-auto');\n hardwareConcurrencyPane.show(this.settingsPane.element);\n\n const thirdPartyToolbar = new UI.Toolbar.Toolbar('', this.settingsPane.element);\n thirdPartyToolbar.element.classList.add('flex-auto');\n thirdPartyToolbar.makeVertical();\n thirdPartyToolbar.appendToolbarItem(\n this.createSettingCheckbox(this.#thirdPartyTracksSetting, i18nString(UIStrings.showDataAddedByExtensions)));\n\n const {toggle, input, reset, warning} =\n MobileThrottling.ThrottlingManager.throttlingManager().createHardwareConcurrencySelector();\n const concurrencyThrottlingToolbar = new UI.Toolbar.Toolbar('', hardwareConcurrencyPane.element);\n concurrencyThrottlingToolbar.registerCSSFiles([timelinePanelStyles]);\n input.element.classList.add('timeline-concurrency-input');\n concurrencyThrottlingToolbar.appendToolbarItem(toggle);\n concurrencyThrottlingToolbar.appendToolbarItem(input);\n concurrencyThrottlingToolbar.appendToolbarItem(reset);\n concurrencyThrottlingToolbar.appendToolbarItem(warning);\n\n this.showSettingsPaneSetting.addChangeListener(this.updateSettingsPaneVisibility.bind(this));\n this.updateSettingsPaneVisibility();\n }\n\n private createNetworkConditionsSelect(): UI.Toolbar.ToolbarComboBox {\n const toolbarItem = new UI.Toolbar.ToolbarComboBox(null, i18nString(UIStrings.networkConditions));\n toolbarItem.setMaxWidth(140);\n MobileThrottling.ThrottlingManager.throttlingManager().decorateSelectWithNetworkThrottling(\n toolbarItem.selectElement());\n return toolbarItem;\n }\n\n private prepareToLoadTimeline(): void {\n console.assert(this.state === State.IDLE);\n this.setState(State.LOADING);\n }\n\n private createFileSelector(): void {\n if (this.fileSelectorElement) {\n this.fileSelectorElement.remove();\n }\n // .gz is far more popular than .gzip, but both are valid.\n this.fileSelectorElement =\n UI.UIUtils.createFileSelectorElement(this.loadFromFile.bind(this), '.json,.gz,.gzip,.cpuprofile');\n this.timelinePane.element.appendChild(this.fileSelectorElement);\n }\n\n private contextMenu(event: Event): void {\n // Do not show this Context menu on FlameChart entries because we have a different context menu for FlameChart entries\n const mouseEvent = (event as MouseEvent);\n if (this.flameChart.getMainFlameChart().coordinatesToEntryIndex(mouseEvent.offsetX, mouseEvent.offsetY) !== -1) {\n return;\n }\n const contextMenu = new UI.ContextMenu.ContextMenu(event, {useSoftMenu: true});\n contextMenu.appendItemsAtLocation('timelineMenu');\n void contextMenu.show();\n }\n\n async saveToFile(isEnhancedTraces: boolean = false, addModifications: boolean = false): Promise {\n if (this.state !== State.IDLE) {\n return;\n }\n if (this.#viewMode.mode !== 'VIEWING_TRACE') {\n return;\n }\n const traceEvents = this.#traceEngineModel.rawTraceEvents(this.#viewMode.traceIndex);\n const metadata = this.#traceEngineModel.metadata(this.#viewMode.traceIndex);\n // Save modifications into the metadata if modifications experiment is on\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_ANNOTATIONS) && metadata &&\n addModifications) {\n metadata.modifications = ModificationsManager.activeManager()?.toJSON();\n } else if (metadata) {\n delete metadata.modifications;\n }\n if (metadata && isEnhancedTraces) {\n metadata.enhancedTraceVersion = TraceEngine.Handlers.ModelHandlers.EnhancedTraces.EnhancedTracesVersion;\n }\n if (!traceEvents) {\n return;\n }\n\n const traceStart = Platform.DateUtilities.toISO8601Compact(new Date());\n let fileName: Platform.DevToolsPath.RawPathString;\n if (metadata?.dataOrigin === TraceEngine.Types.File.DataOrigin.CPU_PROFILE) {\n fileName = `CPU-${traceStart}.cpuprofile` as Platform.DevToolsPath.RawPathString;\n } else if (metadata && metadata.enhancedTraceVersion) {\n fileName = `EnhancedTraces-${traceStart}.json` as Platform.DevToolsPath.RawPathString;\n } else {\n fileName = `Trace-${traceStart}.json` as Platform.DevToolsPath.RawPathString;\n }\n\n try {\n // TODO(crbug.com/1456818): Extract this logic and add more tests.\n let traceAsString;\n if (metadata?.dataOrigin === TraceEngine.Types.File.DataOrigin.CPU_PROFILE) {\n const profileEvent = traceEvents.find(e => e.name === 'CpuProfile');\n if (!profileEvent || !profileEvent.args?.data) {\n return;\n }\n const profileEventData = profileEvent.args?.data;\n if (profileEventData.hasOwnProperty('cpuProfile')) {\n // TODO(crbug.com/1456799): Currently use a hack way because we can't differentiate\n // cpuprofile from trace events when loading a file.\n // The loader will directly add the fake trace created from CpuProfile to the tracingModel.\n // And there is where the old saving logic saves the cpuprofile.\n // This will be solved when the CPUProfileHandler is done. Then we can directly get it\n // from the new traceEngine\n const profile = (profileEventData as {cpuProfile: Protocol.Profiler.Profile}).cpuProfile;\n traceAsString = cpuprofileJsonGenerator(profile as Protocol.Profiler.Profile);\n }\n } else {\n const formattedTraceIter = traceJsonGenerator(traceEvents, metadata);\n traceAsString = Array.from(formattedTraceIter).join('');\n }\n if (!traceAsString) {\n throw new Error('Trace content empty');\n }\n await Workspace.FileManager.FileManager.instance().save(\n fileName, traceAsString, true /* forceSaveAs */, false /* isBase64 */);\n Workspace.FileManager.FileManager.instance().close(fileName);\n } catch (error) {\n console.error(error.stack);\n if (error.name === 'AbortError') {\n // The user cancelled the action, so this is not an error we need to report.\n return;\n }\n Common.Console.Console.instance().error(\n i18nString(UIStrings.failedToSaveTimelineSS, {PH1: error.message, PH2: error.name}));\n }\n }\n\n async showHistoryDropdown(): Promise {\n const recordingData = await this.#historyManager.showHistoryDropDown();\n if (recordingData) {\n if (recordingData.type === 'LANDING_PAGE') {\n this.#changeView({mode: 'LANDING_PAGE'});\n } else {\n this.#changeView({\n mode: 'VIEWING_TRACE',\n traceIndex: recordingData.traceParseDataIndex,\n });\n }\n }\n }\n\n navigateHistory(direction: number): boolean {\n const recordingData = this.#historyManager.navigate(direction);\n // When navigating programatically, you cannot navigate to the landing page\n // view, so we can discount that possibility here.\n if (recordingData && recordingData.type === 'TRACE_INDEX') {\n this.#changeView({\n mode: 'VIEWING_TRACE',\n traceIndex: recordingData.traceParseDataIndex,\n });\n }\n return true;\n }\n\n #saveModificationsForActiveTrace(): void {\n if (this.#viewMode.mode !== 'VIEWING_TRACE') {\n return;\n }\n const newModifications = ModificationsManager.activeManager()?.toJSON();\n if (newModifications) {\n this.#traceEngineModel.overrideModifications(this.#viewMode.traceIndex, newModifications);\n }\n }\n\n selectFileToLoad(): void {\n if (this.fileSelectorElement) {\n this.fileSelectorElement.click();\n }\n }\n\n async loadFromFile(file: File): Promise {\n if (this.state !== State.IDLE) {\n return;\n }\n this.prepareToLoadTimeline();\n this.loader = await TimelineLoader.loadFromFile(file, this);\n this.createFileSelector();\n }\n\n async loadFromURL(url: Platform.DevToolsPath.UrlString): Promise {\n if (this.state !== State.IDLE) {\n return;\n }\n this.prepareToLoadTimeline();\n this.loader = await TimelineLoader.loadFromURL(url, this);\n }\n\n private updateMiniMap(): void {\n if (this.#viewMode.mode !== 'VIEWING_TRACE') {\n return;\n }\n\n const traceParsedData = this.#traceEngineModel.traceParsedData(this.#viewMode.traceIndex);\n const isCpuProfile = this.#traceEngineModel.metadata(this.#viewMode.traceIndex)?.dataOrigin ===\n TraceEngine.Types.File.DataOrigin.CPU_PROFILE;\n if (!traceParsedData) {\n return;\n }\n\n this.#minimapComponent.setData({\n traceParsedData,\n isCpuProfile,\n settings: {\n showScreenshots: this.showScreenshotsSetting.get(),\n showMemory: this.showMemorySetting.get(),\n },\n });\n }\n\n private onModeChanged(): void {\n this.flameChart.updateCountersGraphToggle(this.showMemorySetting.get());\n this.updateMiniMap();\n this.doResize();\n this.select(null);\n }\n\n #extensionDataVisibilityChanged(): void {\n this.flameChart.extensionDataVisibilityChanged();\n }\n\n private updateSettingsPaneVisibility(): void {\n if (isNode) {\n return;\n }\n if (this.showSettingsPaneSetting.get()) {\n this.showSettingsPaneButton.setToggled(true);\n this.settingsPane.showWidget();\n } else {\n this.showSettingsPaneButton.setToggled(false);\n this.settingsPane.hideWidget();\n }\n }\n\n private updateShowSettingsToolbarButton(): void {\n const messages: string[] = [];\n if (SDK.CPUThrottlingManager.CPUThrottlingManager.instance().cpuThrottlingRate() !== 1) {\n messages.push(i18nString(UIStrings.CpuThrottlingIsEnabled));\n }\n if (MobileThrottling.ThrottlingManager.throttlingManager().hardwareConcurrencyOverrideEnabled) {\n messages.push(i18nString(UIStrings.HardwareConcurrencyIsEnabled));\n }\n if (SDK.NetworkManager.MultitargetNetworkManager.instance().isThrottling()) {\n messages.push(i18nString(UIStrings.NetworkThrottlingIsEnabled));\n }\n if (this.captureLayersAndPicturesSetting.get()) {\n messages.push(i18nString(UIStrings.SignificantOverheadDueToPaint));\n }\n if (this.captureSelectorStatsSetting.get()) {\n messages.push(i18nString(UIStrings.SelectorStatsEnabled));\n }\n if (this.disableCaptureJSProfileSetting.get()) {\n messages.push(i18nString(UIStrings.JavascriptSamplingIsDisabled));\n }\n\n this.showSettingsPaneButton.setChecked(messages.length > 0);\n this.showSettingsPaneButton.element.style.setProperty('--dot-toggle-top', '16px');\n this.showSettingsPaneButton.element.style.setProperty('--dot-toggle-left', '15px');\n\n if (messages.length) {\n const tooltipElement = document.createElement('div');\n messages.forEach(message => {\n tooltipElement.createChild('div').textContent = message;\n });\n this.showSettingsPaneButton.setTitle(tooltipElement.textContent || '');\n } else {\n this.showSettingsPaneButton.setTitle(i18nString(UIStrings.captureSettings));\n }\n }\n\n private setUIControlsEnabled(enabled: boolean): void {\n this.recordingOptionUIControls.forEach(control => control.setEnabled(enabled));\n }\n\n async #evaluateInspectedURL(): Promise {\n if (!this.controller) {\n return Platform.DevToolsPath.EmptyUrlString;\n }\n\n // target.inspectedURL is reliably populated, however it lacks any url #hash\n const inspectedURL = this.controller.primaryPageTarget.inspectedURL();\n\n // We'll use the navigationHistory to acquire the current URL including hash\n const resourceTreeModel = this.controller.primaryPageTarget.model(SDK.ResourceTreeModel.ResourceTreeModel);\n const navHistory = resourceTreeModel && await resourceTreeModel.navigationHistory();\n if (!resourceTreeModel || !navHistory) {\n return inspectedURL;\n }\n\n const {currentIndex, entries} = navHistory;\n const navigationEntry = entries[currentIndex];\n return navigationEntry.url as Platform.DevToolsPath.UrlString;\n }\n\n async #navigateToAboutBlank(): Promise {\n const aboutBlankNavigationComplete = new Promise(async (resolve, reject) => {\n if (!this.controller) {\n reject('Could not find TimelineController');\n return;\n }\n const target = this.controller.primaryPageTarget;\n const resourceModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel);\n if (!resourceModel) {\n reject('Could not load resourceModel');\n return;\n }\n\n // To clear out the page and any state from prior test runs, we\n // navigate to about:blank before initiating the trace recording.\n // Once we have navigated to about:blank, we start recording and\n // then navigate to the original page URL, to ensure we profile the\n // page load.\n function waitForAboutBlank(event: Common.EventTarget.EventTargetEvent):\n void {\n if (event.data.url === 'about:blank') {\n resolve();\n } else {\n reject(`Unexpected navigation to ${event.data.url}`);\n }\n resourceModel?.removeEventListener(SDK.ResourceTreeModel.Events.FrameNavigated, waitForAboutBlank);\n }\n resourceModel.addEventListener(SDK.ResourceTreeModel.Events.FrameNavigated, waitForAboutBlank);\n await resourceModel.navigate('about:blank' as Platform.DevToolsPath.UrlString);\n });\n await aboutBlankNavigationComplete;\n }\n\n async #startCPUProfilingRecording(): Promise {\n try {\n this.cpuProfiler = UI.Context.Context.instance().flavor(SDK.CPUProfilerModel.CPUProfilerModel);\n if (!this.cpuProfiler) {\n // If there is no isolate selected, we will profile the first isolate that devtools connects to.\n // If we profile all target, but this will cause some bugs like time for the function is calculated wrong,\n // because the profiles will be concated and sorted together, so the total time will be amplified.\n // Multiple targets problem might happen when you inspect multiple node servers on different port at same time,\n // or when you let DevTools listen to both locolhost:9229 & 127.0.0.1:9229.\n const firstNodeTarget =\n SDK.TargetManager.TargetManager.instance().targets().find(target => target.type() === SDK.Target.Type.NODE);\n if (!firstNodeTarget) {\n throw new Error('Could not load any Node target.');\n }\n if (firstNodeTarget) {\n this.cpuProfiler = firstNodeTarget.model(SDK.CPUProfilerModel.CPUProfilerModel);\n }\n }\n\n this.setUIControlsEnabled(false);\n this.#changeView({mode: 'STATUS_PANE_OVERLAY'});\n if (!this.cpuProfiler) {\n throw new Error('No Node target is found.');\n }\n await SDK.TargetManager.TargetManager.instance().suspendAllTargets('performance-timeline');\n await this.cpuProfiler.startRecording();\n\n this.recordingStarted();\n } catch (e) {\n await this.recordingFailed(e.message);\n }\n }\n\n async #startTraceRecording(): Promise {\n try {\n // We record against the root target, but also need to use the\n // primaryPageTarget to inspect the current URL. For more info, see the\n // JSDoc comment on the TimelineController constructor.\n const rootTarget = SDK.TargetManager.TargetManager.instance().rootTarget();\n const primaryPageTarget = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n\n if (!primaryPageTarget) {\n throw new Error('Could not load primary page target.');\n }\n if (!rootTarget) {\n throw new Error('Could not load root target.');\n }\n\n if (UIDevtoolsUtils.isUiDevTools()) {\n this.controller = new UIDevtoolsController(rootTarget, primaryPageTarget, this);\n } else {\n this.controller = new TimelineController(rootTarget, primaryPageTarget, this);\n }\n this.setUIControlsEnabled(false);\n this.#changeView({mode: 'STATUS_PANE_OVERLAY'});\n if (!this.controller) {\n throw new Error('Could not create Timeline controller');\n }\n\n const urlToTrace = await this.#evaluateInspectedURL();\n // If we are doing \"Reload & record\", we first navigate the page to\n // about:blank. This is to ensure any data on the timeline from any\n // previous performance recording is lost, avoiding the problem where a\n // timeline will show data & screenshots from a previous page load that\n // was not relevant.\n if (this.recordingPageReload) {\n await this.#navigateToAboutBlank();\n }\n const recordingOptions = {\n enableJSSampling: !this.disableCaptureJSProfileSetting.get(),\n capturePictures: this.captureLayersAndPicturesSetting.get(),\n captureFilmStrip: this.showScreenshotsSetting.get(),\n captureSelectorStats: this.captureSelectorStatsSetting.get(),\n };\n // Order is important here: we tell the controller to start recording, which enables tracing.\n const response = await this.controller.startRecording(recordingOptions);\n if (response.getError()) {\n throw new Error(response.getError());\n }\n // Once we get here, we know tracing is active.\n // This is when, if the user has hit \"Reload & Record\" that we now need to navigate to the original URL.\n // If the user has just hit \"record\", we don't do any navigating.\n const recordingConfig = this.recordingPageReload ? {navigateToUrl: urlToTrace} : undefined;\n this.recordingStarted(recordingConfig);\n } catch (e) {\n await this.recordingFailed(e.message);\n }\n }\n\n private async startRecording(): Promise {\n console.assert(!this.statusPane, 'Status pane is already opened.');\n this.setState(State.START_PENDING);\n this.showRecordingStarted();\n\n if (isNode) {\n await this.#startCPUProfilingRecording();\n } else {\n await this.#startTraceRecording();\n }\n }\n\n private async stopRecording(): Promise {\n if (this.statusPane) {\n this.statusPane.finish();\n this.statusPane.updateStatus(i18nString(UIStrings.stoppingTimeline));\n this.statusPane.updateProgressBar(i18nString(UIStrings.received), 0);\n }\n this.setState(State.STOP_PENDING);\n if (this.controller) {\n await this.controller.stopRecording();\n this.setUIControlsEnabled(true);\n await this.controller.dispose();\n this.controller = null;\n return;\n }\n if (this.cpuProfiler) {\n const profile = await this.cpuProfiler.stopRecording();\n this.setState(State.IDLE);\n this.loadFromCpuProfile(profile);\n\n this.setUIControlsEnabled(true);\n this.cpuProfiler = null;\n\n await SDK.TargetManager.TargetManager.instance().resumeAllTargets();\n }\n }\n\n private async recordingFailed(error: string, rawEvents?: TraceEngine.Types.TraceEvents.TraceEventData[]):\n Promise {\n if (this.statusPane) {\n this.statusPane.remove();\n }\n this.statusPane = new StatusPane(\n {\n description: error,\n buttonText: i18nString(UIStrings.close),\n buttonDisabled: false,\n showProgress: undefined,\n showTimer: undefined,\n },\n // When recording failed, we should load null to go back to the landing page.\n async () => {\n this.statusPane?.remove();\n await this.loadingComplete(\n /* no collectedEvents */[],\n /* exclusiveFilter= */ null,\n /* isCpuProfile= */ false,\n /* recordingStartTime= */ null,\n /* metadata= */ null);\n });\n this.statusPane.showPane(this.statusPaneContainer);\n this.statusPane.updateStatus(i18nString(UIStrings.recordingFailed));\n\n if (rawEvents) {\n this.statusPane.enableDownloadOfEvents(rawEvents);\n }\n\n this.setState(State.RECORDING_FAILED);\n this.traceLoadStart = null;\n this.setUIControlsEnabled(true);\n if (this.controller) {\n await this.controller.dispose();\n this.controller = null;\n }\n // Ensure we resume all targets, otherwise DevTools remains unresponsive in the event of an error.\n void SDK.TargetManager.TargetManager.instance().resumeAllTargets();\n }\n\n private onSuspendStateChanged(): void {\n this.updateTimelineControls();\n }\n\n private consoleProfileFinished(data: SDK.CPUProfilerModel.ProfileFinishedData): void {\n this.loadFromCpuProfile(data.cpuProfile);\n void UI.InspectorView.InspectorView.instance().showPanel('timeline');\n }\n\n private updateTimelineControls(): void {\n this.toggleRecordAction.setToggled(this.state === State.RECORDING);\n this.toggleRecordAction.setEnabled(this.state === State.RECORDING || this.state === State.IDLE);\n this.recordReloadAction.setEnabled(isNode ? false : this.state === State.IDLE);\n this.#historyManager.setEnabled(this.state === State.IDLE);\n this.clearButton.setEnabled(this.state === State.IDLE);\n this.panelToolbar.setEnabled(this.state !== State.LOADING);\n this.panelRightToolbar.setEnabled(this.state !== State.LOADING);\n this.dropTarget.setEnabled(this.state === State.IDLE);\n this.loadButton.setEnabled(this.state === State.IDLE);\n this.saveButton.setEnabled(this.state === State.IDLE && this.#hasActiveTrace());\n if (this.#viewMode.mode === 'VIEWING_TRACE') {\n this.#addSidebarIconToToolbar();\n }\n }\n\n async toggleRecording(): Promise {\n if (this.state === State.IDLE) {\n this.recordingPageReload = false;\n await this.startRecording();\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.TimelineStarted);\n } else if (this.state === State.RECORDING) {\n await this.stopRecording();\n }\n }\n\n recordReload(): void {\n if (this.state !== State.IDLE) {\n return;\n }\n this.recordingPageReload = true;\n void this.startRecording();\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.TimelinePageReloadStarted);\n }\n\n private onClearButton(): void {\n this.#historyManager.clear();\n this.#changeView({mode: 'LANDING_PAGE'});\n }\n\n #hasActiveTrace(): boolean {\n return this.#viewMode.mode === 'VIEWING_TRACE';\n }\n\n #onBrickBreakerEasterEggClick(): void {\n if (!this.#hasActiveTrace()) {\n return;\n }\n this.flameChart.runBrickBreakerGame();\n }\n\n #applyActiveFilters(\n traceIsGeneric: boolean,\n exclusiveFilter: TimelineModel.TimelineModelFilter.TimelineModelFilter|null = null): void {\n if (traceIsGeneric || Root.Runtime.experiments.isEnabled('timeline-show-all-events')) {\n return;\n }\n\n const newActiveFilters = exclusiveFilter ? [exclusiveFilter] : [\n TimelineUIUtils.visibleEventsFilter(),\n ];\n\n ActiveFilters.instance().setFilters(newActiveFilters);\n }\n\n /**\n * Called when we update the active trace that is being shown to the user.\n * This is called from {@see changeView} when we change the UI to show a\n * trace - either one the user has just recorded/imported, or one they have\n * navigated to via the dropdown.\n *\n * If you need code to execute whenever the active trace changes, this is the method to use.\n * If you need code to execute ONLY ON NEW TRACES, then use {@see loadingComplete}\n * You should not call this method directly if you want the UI to update; use\n * {@see changeView} to control what is shown to the user.\n */\n #setModelForActiveTrace(): void {\n if (this.#viewMode.mode !== 'VIEWING_TRACE') {\n return;\n }\n const {traceIndex} = this.#viewMode;\n const traceParsedData = this.#traceEngineModel.traceParsedData(traceIndex);\n const syntheticEventsManager = this.#traceEngineModel.syntheticTraceEventsManager(traceIndex);\n\n if (!traceParsedData || !syntheticEventsManager) {\n // This should not happen, because you can only get into the\n // VIEWING_TRACE viewMode if you have a valid trace index from the\n // TraceEngine. If it does, let's bail back to the landing page.\n console.error(`setModelForActiveTrace was called with an invalid trace index: ${traceIndex}`);\n this.#changeView({mode: 'LANDING_PAGE'});\n return;\n }\n\n TraceEngine.Helpers.SyntheticEvents.SyntheticEventsManager.activate(syntheticEventsManager);\n // Clear the line level profile that could exist from the previous trace.\n PerfUI.LineLevelProfile.Performance.instance().reset();\n\n this.#minimapComponent.reset();\n\n // Order is important: the bounds must be set before we initiate any UI\n // rendering.\n TraceBounds.TraceBounds.BoundsManager.instance().resetWithNewBounds(\n traceParsedData.Meta.traceBounds,\n );\n\n // Set up the modifications manager for the newly active trace.\n // The order is important: this needs to happen before we trigger a flame chart redraw by setting the model.\n // (it could happen after, but then we would need to trigger a fresh redraw so let's not do that)\n const currentManager = ModificationsManager.initAndActivateModificationsManager(this.#traceEngineModel, traceIndex);\n\n if (!currentManager) {\n console.error('ModificationsManager could not be created or activated.');\n }\n this.statusPane?.updateProgressBar(i18nString(UIStrings.processed), 70);\n\n const isCpuProfile =\n this.#traceEngineModel.metadata(traceIndex)?.dataOrigin === TraceEngine.Types.File.DataOrigin.CPU_PROFILE;\n this.flameChart.setModel(traceParsedData, isCpuProfile);\n this.flameChart.resizeToPreferredHeights();\n // Reset the visual selection as we've just swapped to a new trace.\n this.flameChart.setSelectionAndReveal(null);\n this.#sideBar.setTraceParsedData(traceParsedData);\n\n this.searchableViewInternal.showWidget();\n\n const exclusiveFilter = this.#exclusiveFilterPerTrace.get(traceIndex) ?? null;\n this.#applyActiveFilters(traceParsedData.Meta.traceIsGeneric, exclusiveFilter);\n\n // Add ModificationsManager listeners for annotations change to update the Annotation Overlays.\n currentManager?.addEventListener(AnnotationModifiedEvent.eventName, event => {\n const {overlay, action} = (event as AnnotationModifiedEvent);\n if (action === 'Add') {\n this.flameChart.addOverlay(overlay);\n } else if (action === 'Remove') {\n this.flameChart.removeOverlay(overlay);\n } else if (action === 'UpdateTimeRange' && Overlays.Overlays.isTimeRangeLabel(overlay)) {\n this.flameChart.updateExistingOverlay(overlay, {\n bounds: overlay.bounds,\n });\n } else if (action === 'UpdateLinkToEntry' && Overlays.Overlays.isEntriesLink(overlay)) {\n this.flameChart.updateExistingOverlay(overlay, {\n entryTo: overlay.entryTo,\n });\n }\n\n const annotations = currentManager.getAnnotations();\n const annotationEntryToColorMap = this.buildColorsAnnotationsMap(annotations);\n this.#sideBar.setAnnotations(annotations, annotationEntryToColorMap);\n });\n\n // To calculate the activity we might want to zoom in, we use the top-most main-thread track\n const topMostMainThreadAppender =\n this.flameChart.getMainDataProvider().compatibilityTracksAppenderInstance().threadAppenders().at(0);\n if (topMostMainThreadAppender) {\n const zoomedInBounds = TraceEngine.Extras.MainThreadActivity.calculateWindow(\n traceParsedData.Meta.traceBounds, topMostMainThreadAppender.getEntries());\n\n TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(zoomedInBounds);\n }\n\n // Add overlays for annotations loaded from the trace file\n const currModificationManager = ModificationsManager.activeManager();\n if (currModificationManager) {\n currModificationManager.getOverlays().forEach(overlay => {\n this.flameChart.addOverlay(overlay);\n });\n const annotations = currModificationManager.getAnnotations();\n const annotationEntryToColorMap = this.buildColorsAnnotationsMap(annotations);\n this.#sideBar.setAnnotations(annotations, annotationEntryToColorMap);\n }\n\n // Set up line level profiling with CPU profiles, if we found any.\n PerfUI.LineLevelProfile.Performance.instance().reset();\n if (traceParsedData && traceParsedData.Samples.profilesInProcess.size) {\n const primaryPageTarget = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n // Gather up all CPU Profiles we found when parsing this trace.\n const cpuProfiles =\n Array.from(traceParsedData.Samples.profilesInProcess).flatMap(([_processId, threadsInProcess]) => {\n const profiles = Array.from(threadsInProcess.values()).map(profileData => profileData.parsedProfile);\n return profiles;\n });\n for (const profile of cpuProfiles) {\n PerfUI.LineLevelProfile.Performance.instance().appendCPUProfile(profile, primaryPageTarget);\n }\n }\n\n // Set up SourceMapsResolver to ensure we resolve any function names in\n // profile calls.\n this.#sourceMapsResolver = new SourceMapsResolver(traceParsedData);\n this.#sourceMapsResolver.addEventListener(NodeNamesUpdated.eventName, this.#onSourceMapsNodeNamesResolvedBound);\n void this.#sourceMapsResolver.install();\n\n this.statusPane?.updateProgressBar(i18nString(UIStrings.processed), 80);\n this.updateMiniMap();\n this.statusPane?.updateProgressBar(i18nString(UIStrings.processed), 90);\n this.updateTimelineControls();\n\n this.#setActiveInsight(null);\n\n const traceInsightsData = this.#traceEngineModel.traceInsights(traceIndex);\n if (traceInsightsData) {\n this.flameChart.setInsights(traceInsightsData);\n this.#sideBar.setInsights(traceInsightsData);\n }\n\n this.#showSidebarIfRequired();\n }\n\n /**\n * We automatically show the sidebar in only 2 scenarios:\n * 1. The user has never seen it before, so we show it once to aid discovery\n * 2. The user had it open, and we hid it (for example, during recording), so now we need to bring it back.\n * We also check that the experiments are enabled, else we reveal an entirely empty sidebar.\n */\n #showSidebarIfRequired(): void {\n const needToRestore = this.#restoreSidebarVisibilityOnTraceLoad;\n const userHasSeenSidebar = this.#sideBar.userHasOpenedSidebarOnce();\n const experimentsEnabled = this.#panelSidebarEnabled();\n\n if (experimentsEnabled && (!userHasSeenSidebar || needToRestore)) {\n this.#splitWidget.showBoth();\n }\n this.#restoreSidebarVisibilityOnTraceLoad = false;\n }\n\n // Build a map mapping annotated entries to the colours that are used to display them in the FlameChart.\n // We need this map to display the entries in the sidebar with the same colours.\n private buildColorsAnnotationsMap(annotations: TraceEngine.Types.File.Annotation[]):\n Map {\n const annotationEntryToColorMap = new Map();\n\n for (const annotation of annotations) {\n if (TraceEngine.Types.File.isEntryLabelAnnotation(annotation)) {\n annotationEntryToColorMap.set(annotation.entry, this.getEntryColorByEntry(annotation.entry));\n } else if (TraceEngine.Types.File.isEntriesLinkAnnotation(annotation)) {\n annotationEntryToColorMap.set(annotation.entryFrom, this.getEntryColorByEntry(annotation.entryFrom));\n if (annotation.entryTo) {\n annotationEntryToColorMap.set(annotation.entryTo, this.getEntryColorByEntry(annotation.entryTo));\n }\n }\n }\n\n return annotationEntryToColorMap;\n }\n\n private getEntryColorByEntry(entry: TraceEngine.Types.TraceEvents.TraceEventData): string {\n const mainIndex = this.flameChart.getMainDataProvider().indexForEvent(entry);\n const networkIndex = this.flameChart.getNetworkDataProvider().indexForEvent(entry);\n if (mainIndex) {\n const color = this.flameChart.getMainDataProvider().entryColor(mainIndex);\n return color;\n }\n if (networkIndex) {\n const color = this.flameChart.getNetworkDataProvider().entryColor(networkIndex);\n return color;\n }\n\n console.warn('Could not get entry color for ', entry);\n return ThemeSupport.ThemeSupport.instance().getComputedValue('--app-color-system');\n }\n\n private recordingStarted(config?: {navigateToUrl: Platform.DevToolsPath.UrlString}): void {\n if (config && this.recordingPageReload && this.controller) {\n // If the user hit \"Reload & record\", by this point we have:\n // 1. Navigated to about:blank\n // 2. Initiated tracing.\n // We therefore now should navigate back to the original URL that the user wants to profile.\n const resourceModel = this.controller?.primaryPageTarget.model(SDK.ResourceTreeModel.ResourceTreeModel);\n if (!resourceModel) {\n void this.recordingFailed('Could not navigate to original URL');\n return;\n }\n // We don't need to await this because we are purposefully showing UI\n // progress as the page loads & tracing is underway.\n void resourceModel.navigate(config.navigateToUrl);\n }\n\n this.#changeView({mode: 'STATUS_PANE_OVERLAY'});\n this.setState(State.RECORDING);\n this.showRecordingStarted();\n if (this.statusPane) {\n this.statusPane.enableAndFocusButton();\n this.statusPane.updateStatus(i18nString(UIStrings.profiling));\n this.statusPane.updateProgressBar(i18nString(UIStrings.bufferUsage), 0);\n this.statusPane.startTimer();\n }\n }\n\n recordingProgress(usage: number): void {\n if (this.statusPane) {\n this.statusPane.updateProgressBar(i18nString(UIStrings.bufferUsage), usage * 100);\n }\n }\n\n /**\n * Hide the sidebar, but persist the user's state, because when they import a\n * trace we want to revert the sidebar back to what it was.\n */\n #hideSidebar(): void {\n if (this.#splitWidget.sidebarIsShowing()) {\n this.#restoreSidebarVisibilityOnTraceLoad = true;\n this.#splitWidget.hideSidebar();\n }\n }\n\n #showLandingPage(): void {\n this.updateSettingsPaneVisibility();\n this.#removeSidebarIconFromToolbar();\n this.#hideSidebar();\n\n if (this.landingPage) {\n this.landingPage.show(this.statusPaneContainer);\n return;\n }\n\n this.landingPage = new TimelineLandingPage(this.toggleRecordAction, {isNode});\n this.landingPage.show(this.statusPaneContainer);\n }\n\n #hideLandingPage(): void {\n this.landingPage.detach();\n\n // Hide pane settings in trace view to conserve UI space, but preserve underlying setting.\n this.showSettingsPaneButton?.setToggled(false);\n this.settingsPane?.hideWidget();\n }\n\n async loadingStarted(): Promise {\n this.#changeView({mode: 'STATUS_PANE_OVERLAY'});\n\n if (this.statusPane) {\n this.statusPane.remove();\n }\n this.statusPane = new StatusPane(\n {\n showProgress: true,\n showTimer: undefined,\n buttonDisabled: undefined,\n buttonText: undefined,\n description: undefined,\n },\n () => this.cancelLoading());\n this.statusPane.showPane(this.statusPaneContainer);\n this.statusPane.updateStatus(i18nString(UIStrings.loadingProfile));\n // FIXME: make loading from backend cancelable as well.\n if (!this.loader) {\n this.statusPane.finish();\n }\n this.traceLoadStart = TraceEngine.Types.Timing.MilliSeconds(performance.now());\n await this.loadingProgress(0);\n }\n\n async loadingProgress(progress?: number): Promise {\n if (typeof progress === 'number' && this.statusPane) {\n this.statusPane.updateProgressBar(i18nString(UIStrings.received), progress * 100);\n }\n }\n\n async processingStarted(): Promise {\n this.statusPane?.updateStatus(i18nString(UIStrings.processingProfile));\n }\n\n #listenForProcessingProgress(): void {\n this.#traceEngineModel.addEventListener(TraceEngine.TraceModel.ModelUpdateEvent.eventName, e => {\n const updateEvent = e as TraceEngine.TraceModel.ModelUpdateEvent;\n const str = i18nString(UIStrings.processed);\n\n // TraceEngine will report progress from [0...1] but we still have more work to do. So, scale them down a bit.\n const traceParseMaxProgress = 0.7;\n\n if (updateEvent.data.type === TraceEngine.TraceModel.ModelUpdateType.COMPLETE) {\n this.statusPane?.updateProgressBar(str, 100 * traceParseMaxProgress);\n } else if (updateEvent.data.type === TraceEngine.TraceModel.ModelUpdateType.PROGRESS_UPDATE) {\n const data = updateEvent.data.data;\n this.statusPane?.updateProgressBar(str, data.percent * 100 * traceParseMaxProgress);\n }\n });\n }\n\n #onSourceMapsNodeNamesResolved(): void {\n this.flameChart.refreshMainFlameChart();\n }\n\n /**\n * This is called with we are done loading a trace from a file, or after we\n * have recorded a fresh trace.\n *\n * IMPORTANT: All the code in here should be code that is only required when we have\n * recorded or loaded a brand new trace. If you need the code to run when the\n * user switches to an existing trace, please {@see setModel} and put your\n * code in there.\n **/\n async loadingComplete(\n collectedEvents: TraceEngine.Types.TraceEvents.TraceEventData[],\n exclusiveFilter: TimelineModel.TimelineModelFilter.TimelineModelFilter|null = null, isCpuProfile: boolean,\n recordingStartTime: number|null, metadata: TraceEngine.Types.File.MetaData|null): Promise {\n this.#traceEngineModel.resetProcessor();\n\n delete this.loader;\n\n // If the user just recorded this trace via the record UI, the state will\n // be StopPending. Whereas if it was an existing trace they loaded via a\n // file, it will be State.Loading. This means we can tell the recording is\n // fresh by checking the state value.\n const recordingIsFresh = this.state === State.STOP_PENDING;\n\n this.setState(State.IDLE);\n\n if (collectedEvents.length === 0) {\n // 0 collected events indicates probably an invalid file was imported.\n // If the user does not have any already-loaded traces, then we should\n // just reset the panel back to the landing page. However if they had a\n // previous trace imported, we should go to that instead.\n if (this.#traceEngineModel.size()) {\n this.#changeView({\n mode: 'VIEWING_TRACE',\n traceIndex: this.#traceEngineModel.lastTraceIndex(),\n });\n } else {\n this.#changeView({mode: 'LANDING_PAGE'});\n }\n return;\n }\n\n metadata = metadata ?\n metadata :\n await TraceEngine.Extras.Metadata.forNewRecording(isCpuProfile, recordingStartTime ?? undefined);\n\n try {\n await this.#executeNewTraceEngine(collectedEvents, recordingIsFresh, metadata);\n const traceIndex = this.#traceEngineModel.lastTraceIndex();\n if (exclusiveFilter) {\n this.#exclusiveFilterPerTrace.set(traceIndex, exclusiveFilter);\n }\n this.#changeView({\n mode: 'VIEWING_TRACE',\n traceIndex,\n });\n\n const traceData = this.#traceEngineModel.traceParsedData(traceIndex);\n if (!traceData) {\n throw new Error(`Could not get trace data at index ${traceIndex}`);\n }\n\n if (recordingIsFresh) {\n Tracker.instance().registerFreshRecording(traceData);\n }\n\n // We store the index of the active trace so we can load it back easily\n // if the user goes to a different trace then comes back.\n // However we also pass in the full trace data because we use it to build\n // the preview overview thumbnail of the trace that gets shown in the UI.\n this.#historyManager.addRecording({\n data: {\n traceParseDataIndex: traceIndex,\n type: 'TRACE_INDEX',\n },\n filmStripForPreview: TraceEngine.Extras.FilmStrip.fromTraceData(traceData),\n traceParsedData: traceData,\n startTime: recordingStartTime ?? null,\n });\n } catch (error) {\n // If we errored during the parsing stage, it\n // is useful to get access to the raw events to download the trace. This\n // allows us to debug crashes!\n void this.recordingFailed(error.message, collectedEvents);\n console.error(error);\n } finally {\n this.recordTraceLoadMetric();\n }\n }\n\n recordTraceLoadMetric(): void {\n if (!this.traceLoadStart) {\n return;\n }\n const start = this.traceLoadStart;\n // Right *now* is the end of trace parsing and model building, but the flamechart rendering\n // isn't complete yet. To capture that we'll do a rAF+setTimeout to give the most accurate timestamp\n // for the first paint of the flamechart\n requestAnimationFrame(() => {\n setTimeout(() => {\n const end = TraceEngine.Types.Timing.MilliSeconds(performance.now());\n const measure = performance.measure('TraceLoad', {start, end});\n const duration = TraceEngine.Types.Timing.MilliSeconds(measure.duration);\n this.element.dispatchEvent(new TraceLoadEvent(duration));\n Host.userMetrics.performanceTraceLoad(measure);\n }, 0);\n });\n }\n\n async #executeNewTraceEngine(\n collectedEvents: TraceEngine.Types.TraceEvents.TraceEventData[], isFreshRecording: boolean,\n metadata: TraceEngine.Types.File.MetaData): Promise {\n return this.#traceEngineModel.parse(\n collectedEvents,\n {\n metadata,\n isFreshRecording,\n },\n );\n }\n\n loadingCompleteForTest(): void {\n // Not implemented, added only for allowing the TimelineTestRunner\n // to be in sync when a trace load is finished.\n }\n\n private showRecordingStarted(): void {\n this.#changeView({mode: 'STATUS_PANE_OVERLAY'});\n if (this.statusPane) {\n this.statusPane.remove();\n }\n this.statusPane = new StatusPane(\n {\n showTimer: true,\n showProgress: true,\n buttonDisabled: true,\n description: undefined,\n buttonText: undefined,\n },\n () => this.stopRecording());\n this.statusPane.showPane(this.statusPaneContainer);\n this.statusPane.updateStatus(i18nString(UIStrings.initializingProfiler));\n }\n\n private cancelLoading(): void {\n if (this.loader) {\n void this.loader.cancel();\n }\n }\n\n private async loadEventFired(\n event: Common.EventTarget\n .EventTargetEvent<{resourceTreeModel: SDK.ResourceTreeModel.ResourceTreeModel, loadTime: number}>):\n Promise {\n if (this.state !== State.RECORDING || !this.recordingPageReload || !this.controller ||\n this.controller.primaryPageTarget !== event.data.resourceTreeModel.target()) {\n return;\n }\n const controller = this.controller;\n await new Promise(r => window.setTimeout(r, this.millisecondsToRecordAfterLoadEvent));\n\n // Check if we're still in the same recording session.\n if (controller !== this.controller || this.state !== State.RECORDING) {\n return;\n }\n void this.stopRecording();\n }\n\n private frameForSelection(selection: TimelineSelection): TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame\n |null {\n if (this.#viewMode.mode !== 'VIEWING_TRACE') {\n return null;\n }\n if (TimelineSelection.isLegacyTimelineFrame(selection.object) &&\n selection.object instanceof TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame) {\n return selection.object;\n }\n if (TimelineSelection.isRangeSelection(selection.object) ||\n TimelineSelection.isSyntheticNetworkRequestDetailsEventSelection(selection.object)) {\n return null;\n }\n if (TimelineSelection.isTraceEventSelection(selection.object)) {\n const traceData = this.#traceEngineModel.traceParsedData(this.#viewMode.traceIndex);\n if (!traceData) {\n return null;\n }\n // If the user has selected a time range, the frame we want is the last\n // frame in that time window, hence why the window we look for is the\n // endTime to the endTime.\n const endTimeMicro = TraceEngine.Helpers.Timing.millisecondsToMicroseconds(selection.endTime);\n const lastFrameInSelection = TraceEngine.Handlers.ModelHandlers.Frames\n .framesWithinWindow(\n traceData.Frames.frames,\n endTimeMicro,\n endTimeMicro,\n )\n .at(0);\n return lastFrameInSelection || null;\n }\n console.assert(false, 'Should never be reached');\n return null;\n }\n\n jumpToFrame(offset: number): true|undefined {\n if (this.#viewMode.mode !== 'VIEWING_TRACE') {\n return;\n }\n const currentFrame = this.selection && this.frameForSelection(this.selection);\n if (!currentFrame) {\n return;\n }\n const traceData = this.#traceEngineModel.traceParsedData(this.#viewMode.traceIndex);\n if (!traceData) {\n return;\n }\n let index = traceData.Frames.frames.indexOf(currentFrame);\n console.assert(index >= 0, 'Can\\'t find current frame in the frame list');\n index = Platform.NumberUtilities.clamp(index + offset, 0, traceData.Frames.frames.length - 1);\n const frame = traceData.Frames.frames[index];\n this.#revealTimeRange(\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.startTime),\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.endTime));\n this.select(TimelineSelection.fromFrame(frame));\n return true;\n }\n\n select(selection: TimelineSelection|null): void {\n this.selection = selection;\n this.flameChart.setSelectionAndReveal(selection);\n }\n\n selectEntryAtTime(events: TraceEngine.Types.TraceEvents.TraceEventData[]|null, time: number): void {\n if (!events) {\n return;\n }\n\n if (events.length === 0) {\n this.select(null);\n return;\n }\n\n // Find best match, then backtrack to the first visible entry.\n for (let index = Platform.ArrayUtilities.upperBound(events, time, (time, event) => time - event.ts) - 1; index >= 0;\n --index) {\n const event = events[index];\n const {endTime} = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event);\n if (TraceEngine.Helpers.Trace.isTopLevelEvent(event) && endTime < time) {\n break;\n }\n if (ActiveFilters.instance().isVisible(event) && endTime >= time) {\n this.select(TimelineSelection.fromTraceEvent(event));\n return;\n }\n }\n this.select(null);\n }\n\n highlightEvent(event: TraceEngine.Types.TraceEvents.TraceEventData|null): void {\n this.flameChart.highlightEvent(event);\n }\n\n #revealTimeRange(startTime: TraceEngine.Types.Timing.MilliSeconds, endTime: TraceEngine.Types.Timing.MilliSeconds):\n void {\n const traceBoundsState = TraceBounds.TraceBounds.BoundsManager.instance().state();\n if (!traceBoundsState) {\n return;\n }\n const traceWindow = traceBoundsState.milli.timelineTraceWindow;\n\n let offset = 0;\n if (traceWindow.max < endTime) {\n offset = endTime - traceWindow.max;\n } else if (traceWindow.min > startTime) {\n offset = startTime - traceWindow.min;\n }\n TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(\n TraceEngine.Helpers.Timing.traceWindowFromMilliSeconds(\n TraceEngine.Types.Timing.MilliSeconds(traceWindow.min + offset),\n TraceEngine.Types.Timing.MilliSeconds(traceWindow.max + offset),\n ),\n {\n shouldAnimate: true,\n },\n );\n }\n\n private handleDrop(dataTransfer: DataTransfer): void {\n const items = dataTransfer.items;\n if (!items.length) {\n return;\n }\n const item = items[0];\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.PerfPanelTraceImported);\n if (item.kind === 'string') {\n const url = dataTransfer.getData('text/uri-list') as Platform.DevToolsPath.UrlString;\n if (new Common.ParsedURL.ParsedURL(url).isValid) {\n void this.loadFromURL(url);\n }\n } else if (item.kind === 'file') {\n const file = items[0].getAsFile();\n if (!file) {\n return;\n }\n void this.loadFromFile(file);\n }\n }\n}\n\nexport const enum State {\n IDLE = 'Idle',\n START_PENDING = 'StartPending',\n RECORDING = 'Recording',\n STOP_PENDING = 'StopPending',\n LOADING = 'Loading',\n RECORDING_FAILED = 'RecordingFailed',\n}\n\n// Define row and header height, should be in sync with styles for timeline graphs.\nexport const rowHeight = 18;\n\nexport const headerHeight = 20;\nexport interface TimelineModeViewDelegate {\n select(selection: TimelineSelection|null): void;\n element: Element;\n selectEntryAtTime(events: TraceEngine.Types.TraceEvents.TraceEventData[]|null, time: number): void;\n highlightEvent(event: TraceEngine.Types.TraceEvents.TraceEventData|null): void;\n}\n\nexport class StatusPane extends UI.Widget.VBox {\n private status: HTMLElement;\n private time: Element|undefined;\n private progressLabel!: Element;\n private progressBar!: Element;\n private readonly description: HTMLElement|undefined;\n private button: Buttons.Button.Button;\n private downloadTraceButton: Buttons.Button.Button;\n private startTime!: number;\n private timeUpdateTimer?: number;\n #rawEvents?: TraceEngine.Types.TraceEvents.TraceEventData[];\n\n constructor(\n options: {\n showTimer?: boolean,\n showProgress?: boolean,\n description?: string,\n buttonText?: string,\n buttonDisabled?: boolean,\n },\n buttonCallback: () => (Promise| void)) {\n super(true);\n\n this.contentElement.classList.add('timeline-status-dialog');\n this.contentElement.setAttribute('jslog', `${VisualLogging.dialog('timeline-status').track({resize: true})}`);\n\n const statusLine = this.contentElement.createChild('div', 'status-dialog-line status');\n statusLine.createChild('div', 'label').textContent = i18nString(UIStrings.status);\n this.status = statusLine.createChild('div', 'content');\n UI.ARIAUtils.markAsStatus(this.status);\n\n if (options.showTimer) {\n const timeLine = this.contentElement.createChild('div', 'status-dialog-line time');\n timeLine.createChild('div', 'label').textContent = i18nString(UIStrings.time);\n this.time = timeLine.createChild('div', 'content');\n }\n\n if (options.showProgress) {\n const progressLine = this.contentElement.createChild('div', 'status-dialog-line progress');\n this.progressLabel = progressLine.createChild('div', 'label');\n this.progressBar = progressLine.createChild('div', 'indicator-container').createChild('div', 'indicator');\n UI.ARIAUtils.markAsProgressBar(this.progressBar);\n }\n\n if (typeof options.description === 'string') {\n const descriptionLine = this.contentElement.createChild('div', 'status-dialog-line description');\n descriptionLine.createChild('div', 'label').textContent = i18nString(UIStrings.description);\n this.description = descriptionLine.createChild('div', 'content');\n this.description.innerText = options.description;\n }\n\n const buttonContainer = this.contentElement.createChild('div', 'stop-button');\n this.downloadTraceButton = UI.UIUtils.createTextButton(i18nString(UIStrings.downloadAfterError), () => {\n void this.#downloadRawTraceAfterError();\n }, {jslogContext: 'timeline.download-after-error'});\n\n this.downloadTraceButton.disabled = true;\n this.downloadTraceButton.style.visibility = 'hidden';\n\n const buttonText = options.buttonText || i18nString(UIStrings.stop);\n this.button = UI.UIUtils.createTextButton(buttonText, buttonCallback, {\n jslogContext: 'timeline.stop-recording',\n });\n // Profiling can't be stopped during initialization.\n this.button.disabled = !options.buttonDisabled === false;\n\n buttonContainer.append(this.downloadTraceButton);\n buttonContainer.append(this.button);\n }\n\n finish(): void {\n this.stopTimer();\n this.button.disabled = true;\n }\n\n async #downloadRawTraceAfterError(): Promise {\n if (!this.#rawEvents || this.#rawEvents.length === 0) {\n return;\n }\n const traceStart = Platform.DateUtilities.toISO8601Compact(new Date());\n const fileName = `Trace-Load-Error-${traceStart}.json` as Platform.DevToolsPath.RawPathString;\n const formattedTraceIter = traceJsonGenerator(this.#rawEvents, {});\n const traceAsString = Array.from(formattedTraceIter).join('');\n await Workspace.FileManager.FileManager.instance().save(\n fileName, traceAsString, true /* forceSaveAs */, false /* isBase64 */);\n Workspace.FileManager.FileManager.instance().close(fileName);\n }\n\n enableDownloadOfEvents(rawEvents: TraceEngine.Types.TraceEvents.TraceEventData[]): void {\n this.#rawEvents = rawEvents;\n this.downloadTraceButton.disabled = false;\n this.downloadTraceButton.style.visibility = 'visible';\n }\n\n remove(): void {\n if (this.element.parentNode) {\n (this.element.parentNode as HTMLElement).classList.remove('tinted');\n this.arrangeDialog((this.element.parentNode as HTMLElement));\n }\n this.stopTimer();\n this.element.remove();\n }\n\n showPane(parent: Element): void {\n this.arrangeDialog(parent);\n this.show(parent);\n parent.classList.add('tinted');\n }\n\n enableAndFocusButton(): void {\n this.button.disabled = false;\n this.button.focus();\n }\n\n updateStatus(text: string): void {\n this.status.textContent = text;\n }\n\n updateProgressBar(activity: string, percent: number): void {\n this.progressLabel.textContent = activity;\n (this.progressBar as HTMLElement).style.width = percent.toFixed(1) + '%';\n UI.ARIAUtils.setValueNow(this.progressBar, percent);\n this.updateTimer();\n }\n\n startTimer(): void {\n this.startTime = Date.now();\n this.timeUpdateTimer = window.setInterval(this.updateTimer.bind(this), 1000);\n this.updateTimer();\n }\n\n private stopTimer(): void {\n if (!this.timeUpdateTimer) {\n return;\n }\n clearInterval(this.timeUpdateTimer);\n this.updateTimer();\n delete this.timeUpdateTimer;\n }\n\n private updateTimer(): void {\n this.arrangeDialog((this.element.parentNode as HTMLElement));\n if (!this.timeUpdateTimer || !this.time) {\n return;\n }\n const elapsed = (Date.now() - this.startTime) / 1000;\n this.time.textContent = i18nString(UIStrings.ssec, {PH1: Math.round(elapsed)});\n }\n\n private arrangeDialog(parent: Element): void {\n const isSmallDialog = parent.clientWidth < 325;\n this.element.classList.toggle('small-dialog', isSmallDialog);\n this.contentElement.classList.toggle('small-dialog', isSmallDialog);\n }\n override wasShown(): void {\n super.wasShown();\n this.registerCSSFiles([timelineStatusDialogStyles]);\n }\n}\n\nlet loadTimelineHandlerInstance: LoadTimelineHandler;\n\nexport class LoadTimelineHandler implements Common.QueryParamHandler.QueryParamHandler {\n static instance(opts: {\n forceNew: boolean|null,\n } = {forceNew: null}): LoadTimelineHandler {\n const {forceNew} = opts;\n if (!loadTimelineHandlerInstance || forceNew) {\n loadTimelineHandlerInstance = new LoadTimelineHandler();\n }\n\n return loadTimelineHandlerInstance;\n }\n\n handleQueryParam(value: string): void {\n void UI.ViewManager.ViewManager.instance().showView('timeline').then(async () => {\n await TimelinePanel.instance().loadFromURL(window.decodeURIComponent(value) as Platform.DevToolsPath.UrlString);\n });\n }\n}\n\nexport class TraceRevealer implements Common.Revealer.Revealer {\n async reveal(trace: SDK.TraceObject.TraceObject): Promise {\n await UI.ViewManager.ViewManager.instance().showView('timeline');\n TimelinePanel.instance().loadFromEvents(trace.traceEvents);\n }\n}\n\nexport class ActionDelegate implements UI.ActionRegistration.ActionDelegate {\n handleAction(context: UI.Context.Context, actionId: string): boolean {\n const panel = context.flavor(TimelinePanel);\n if (panel === null) {\n return false;\n }\n switch (actionId) {\n case 'timeline.toggle-recording':\n void panel.toggleRecording();\n return true;\n case 'timeline.record-reload':\n panel.recordReload();\n return true;\n case 'timeline.save-to-file':\n void panel.saveToFile();\n return true;\n case 'timeline.load-from-file':\n panel.selectFileToLoad();\n return true;\n case 'timeline.jump-to-previous-frame':\n panel.jumpToFrame(-1);\n return true;\n case 'timeline.jump-to-next-frame':\n panel.jumpToFrame(1);\n return true;\n case 'timeline.show-history':\n void panel.showHistoryDropdown();\n return true;\n case 'timeline.previous-recording':\n panel.navigateHistory(1);\n return true;\n case 'timeline.next-recording':\n panel.navigateHistory(-1);\n return true;\n }\n return false;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"TimelinePanel.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelinePanel.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2021 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/*\n * Copyright (C) 2012 Google Inc. All rights reserved.\n * Copyright (C) 2012 Intel Inc. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * * Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above\n * copyright notice, this list of conditions and the following disclaimer\n * in the documentation and/or other materials provided with the\n * distribution.\n * * Neither the name of Google Inc. nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport * as Common from '../../core/common/common.js';\nimport * as Host from '../../core/host/host.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as Root from '../../core/root/root.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport type * as Protocol from '../../generated/protocol.js';\nimport type * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as Workspace from '../../models/workspace/workspace.js';\nimport * as TraceBounds from '../../services/trace_bounds/trace_bounds.js';\nimport * as Adorners from '../../ui/components/adorners/adorners.js';\nimport type * as Buttons from '../../ui/components/buttons/buttons.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\nimport * as MobileThrottling from '../mobile_throttling/mobile_throttling.js';\n\nimport {ActiveFilters} from './ActiveFilters.js';\nimport {TraceLoadEvent} from './BenchmarkEvents.js';\nimport * as TimelineComponents from './components/components.js';\nimport * as TimelineInsights from './components/insights/insights.js';\nimport {SHOULD_SHOW_EASTER_EGG} from './EasterEgg.js';\nimport {Tracker} from './FreshRecording.js';\nimport historyToolbarButtonStyles from './historyToolbarButton.css.js';\nimport {IsolateSelector} from './IsolateSelector.js';\nimport {AnnotationModifiedEvent, ModificationsManager} from './ModificationsManager.js';\nimport * as Overlays from './overlays/overlays.js';\nimport {cpuprofileJsonGenerator, traceJsonGenerator} from './SaveFileFormatter.js';\nimport {NodeNamesUpdated, SourceMapsResolver} from './SourceMapsResolver.js';\nimport {type Client, TimelineController} from './TimelineController.js';\nimport {TimelineFlameChartView} from './TimelineFlameChartView.js';\nimport {TimelineHistoryManager} from './TimelineHistoryManager.js';\nimport {TimelineLandingPage} from './TimelineLandingPage.js';\nimport {TimelineLoader} from './TimelineLoader.js';\nimport {TimelineMiniMap} from './TimelineMiniMap.js';\nimport timelinePanelStyles from './timelinePanel.css.js';\nimport {TimelineSelection} from './TimelineSelection.js';\nimport timelineStatusDialogStyles from './timelineStatusDialog.css.js';\nimport {TimelineUIUtils} from './TimelineUIUtils.js';\nimport {UIDevtoolsController} from './UIDevtoolsController.js';\nimport {UIDevtoolsUtils} from './UIDevtoolsUtils.js';\n\nconst UIStrings = {\n /**\n *@description Text that appears when user drag and drop something (for example, a file) in Timeline Panel of the Performance panel\n */\n dropTimelineFileOrUrlHere: 'Drop timeline file or URL here',\n /**\n *@description Title of disable capture jsprofile setting in timeline panel of the performance panel\n */\n disableJavascriptSamples: 'Disable JavaScript samples',\n /**\n *@description Title of capture layers and pictures setting in timeline panel of the performance panel\n */\n enableAdvancedPaint: 'Enable advanced paint instrumentation (slow)',\n /**\n *@description Title of CSS selector stats setting in timeline panel of the performance panel\n */\n enableSelectorStats: 'Enable CSS selector stats (slow)',\n /**\n *@description Title of show screenshots setting in timeline panel of the performance panel\n */\n screenshots: 'Screenshots',\n /**\n *@description Text for the memory of the page\n */\n memory: 'Memory',\n /**\n *@description Text to clear content\n */\n clear: 'Clear',\n /**\n *@description A label for a button that fixes something.\n */\n fixMe: 'Fix me',\n /**\n *@description Tooltip text that appears when hovering over the largeicon load button\n */\n loadProfile: 'Load profile…',\n /**\n *@description Tooltip text that appears when hovering over the largeicon download button\n */\n saveProfile: 'Save profile…',\n /**\n *@description An option to save trace with annotations that appears in the menu of the toolbar download button. This is the expected default option, therefore it does not mention annotations.\n */\n saveTraceWithAnnotationsMenuOption: 'Save trace',\n /**\n *@description An option to save trace without annotations that appears in the menu of the toolbar download button\n */\n saveTraceWithoutAnnotationsMenuOption: 'Save trace without annotations',\n /**\n *@description Text to take screenshots\n */\n captureScreenshots: 'Capture screenshots',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n showMemoryTimeline: 'Show memory timeline',\n /**\n *@description Tooltip text that appears when hovering over the largeicon settings gear in show settings pane setting in timeline panel of the performance panel\n */\n captureSettings: 'Capture settings',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n disablesJavascriptSampling: 'Disables JavaScript sampling, reduces overhead when running against mobile devices',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n capturesAdvancedPaint: 'Captures advanced paint instrumentation, introduces significant performance overhead',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n capturesSelectorStats: 'Captures CSS selector statistics',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n network: 'Network:',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n cpu: 'CPU:',\n /**\n *@description Title of the 'Network conditions' tool in the bottom drawer\n */\n networkConditions: 'Network conditions',\n /**\n *@description Text in Timeline Panel of the Performance panel\n *@example {wrong format} PH1\n *@example {ERROR_FILE_NOT_FOUND} PH2\n */\n failedToSaveTimelineSS: 'Failed to save timeline: {PH1} ({PH2})',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n CpuThrottlingIsEnabled: '- CPU throttling is enabled',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n NetworkThrottlingIsEnabled: '- Network throttling is enabled',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n HardwareConcurrencyIsEnabled: '- Hardware concurrency override is enabled',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n SignificantOverheadDueToPaint: '- Significant overhead due to paint instrumentation',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n SelectorStatsEnabled: '- Selector stats is enabled',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n JavascriptSamplingIsDisabled: '- JavaScript sampling is disabled',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n stoppingTimeline: 'Stopping timeline…',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n received: 'Received',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n processed: 'Processed',\n /**\n *@description Text to close something\n */\n close: 'Close',\n /**\n *@description Text to download the raw trace files after an error\n */\n downloadAfterError: 'Download raw trace events',\n /**\n *@description Status text to indicate the recording has failed in the Performance panel\n */\n recordingFailed: 'Recording failed',\n /**\n * @description Text to indicate the progress of a profile. Informs the user that we are currently\n * creating a peformance profile.\n */\n profiling: 'Profiling…',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n bufferUsage: 'Buffer usage',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n loadingProfile: 'Loading profile…',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n processingProfile: 'Processing profile…',\n /**\n *@description Text in Timeline Panel of the Performance panel\n */\n initializingProfiler: 'Initializing profiler…',\n /**\n *@description Text for the status of something\n */\n status: 'Status',\n /**\n *@description Text that refers to the time\n */\n time: 'Time',\n /**\n *@description Text for the description of something\n */\n description: 'Description',\n /**\n *@description Text of an item that stops the running task\n */\n stop: 'Stop',\n /**\n *@description Time text content in Timeline Panel of the Performance panel\n *@example {2.12} PH1\n */\n ssec: '{PH1} sec',\n /**\n *\n * @description Text for exporting basic traces\n */\n exportNormalTraces: 'Basic performance traces',\n /**\n *\n * @description Text for exporting enhanced traces\n */\n exportEnhancedTraces: 'Enhanced performance traces',\n /**\n *@description Tooltip description for a checkbox that toggles the visibility of data added by extensions of this panel (Performance).\n */\n showDataAddedByExtensions: 'Show data added by extensions of the Performance panel',\n /**\n Label for a checkbox that toggles the visibility of data added by extensions of this panel (Performance).\n */\n performanceExtension: 'Extension data',\n\n /**\n * @description Tooltip for the the sidebar toggle in the Performance panel. Command to open/show the sidebar.\n */\n showSidebar: 'Show sidebar',\n /**\n * @description Tooltip for the the sole sidebar toggle in the Performance panel. Command to close the sidebar.\n */\n hideSidebar: 'Hide sole sidebar',\n /**\n * @description Screen reader announcement when the sidebar is shown in the Performance panel.\n */\n sidebarShown: 'Performance sidebar shown',\n /**\n * @description Screen reader announcement when the sidebar is hidden in the Performance panel.\n */\n sidebarHidden: 'Performance sidebar hidden',\n\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelinePanel.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nlet timelinePanelInstance: TimelinePanel;\nlet isNode: boolean;\n\n/**\n * Represents the states that the timeline panel can be in.\n * If you need to change the panel's view, use the {@see #changeView} method.\n * Note that we do not represent the \"Loading/Processing\" view here. The\n * StatusPane is managed in the code that handles file import/recording, and\n * when it is visible it is rendered on top of the UI so obscures what is behind\n * it. When it completes, we will set the view mode to the trace that has been\n * loaded.\n */\ntype ViewMode = {\n mode: 'LANDING_PAGE',\n}|{\n mode: 'VIEWING_TRACE',\n traceIndex: number,\n}|{\n mode: 'STATUS_PANE_OVERLAY',\n};\n\nexport class TimelinePanel extends UI.Panel.Panel implements Client, TimelineModeViewDelegate {\n private readonly dropTarget: UI.DropTarget.DropTarget;\n private readonly recordingOptionUIControls: UI.Toolbar.ToolbarItem[];\n private state: State;\n private recordingPageReload: boolean;\n private readonly millisecondsToRecordAfterLoadEvent: number;\n private readonly toggleRecordAction: UI.ActionRegistration.Action;\n private readonly recordReloadAction: UI.ActionRegistration.Action;\n readonly #historyManager: TimelineHistoryManager;\n private disableCaptureJSProfileSetting: Common.Settings.Setting;\n private readonly captureLayersAndPicturesSetting: Common.Settings.Setting;\n private readonly captureSelectorStatsSetting: Common.Settings.Setting;\n readonly #thirdPartyTracksSetting: Common.Settings.Setting;\n private showScreenshotsSetting: Common.Settings.Setting;\n private showMemorySetting: Common.Settings.Setting;\n private readonly panelToolbar: UI.Toolbar.Toolbar;\n private readonly panelRightToolbar: UI.Toolbar.Toolbar;\n private readonly timelinePane: UI.Widget.VBox;\n readonly #minimapComponent = new TimelineMiniMap();\n #viewMode: ViewMode = {mode: 'LANDING_PAGE'};\n\n /**\n * We get given any filters for a new trace when it is recorded/imported.\n * Because the user can then use the dropdown to navigate to another trace,\n * we store the filters by the trace index, so if the user then navigates back\n * to a previous trace we can reinstate the filters from this map.\n */\n #exclusiveFilterPerTrace: Map = new Map();\n /**\n * This widget holds the timeline sidebar which shows Insights & Annotations,\n * and the main UI which shows the timeline\n */\n readonly #splitWidget = new UI.SplitWidget.SplitWidget(\n true, // isVertical\n false, // secondIsSidebar\n 'timeline-panel-sidebar-state', // settingName (to persist the open/closed state for the user)\n TimelineComponents.Sidebar.DEFAULT_SIDEBAR_WIDTH_PX,\n );\n private readonly statusPaneContainer: HTMLElement;\n private readonly flameChart: TimelineFlameChartView;\n private readonly searchableViewInternal: UI.SearchableView.SearchableView;\n private showSettingsPaneButton!: UI.Toolbar.ToolbarSettingToggle;\n private showSettingsPaneSetting!: Common.Settings.Setting;\n private settingsPane!: UI.Widget.Widget;\n private controller!: TimelineController|null;\n private cpuProfiler!: SDK.CPUProfilerModel.CPUProfilerModel|null;\n private clearButton!: UI.Toolbar.ToolbarButton;\n private brickBreakerToolbarButton: UI.Toolbar.ToolbarButton;\n private brickBreakerToolbarButtonAdded = false;\n private loadButton!: UI.Toolbar.ToolbarButton;\n private saveButton!: UI.Toolbar.ToolbarButton|UI.Toolbar.ToolbarMenuButton;\n private statusPane!: StatusPane|null;\n private landingPage!: UI.Widget.Widget;\n private loader?: TimelineLoader;\n private showScreenshotsToolbarCheckbox?: UI.Toolbar.ToolbarItem;\n private showMemoryToolbarCheckbox?: UI.Toolbar.ToolbarItem;\n private networkThrottlingSelect?: UI.Toolbar.ToolbarComboBox;\n private cpuThrottlingSelect?: UI.Toolbar.ToolbarComboBox;\n private fileSelectorElement?: HTMLInputElement;\n private selection?: TimelineSelection|null;\n private traceLoadStart!: Trace.Types.Timing.MilliSeconds|null;\n private primaryPageTargetPromiseCallback = (_target: SDK.Target.Target): void => {};\n // Note: this is technically unused, but we need it to define the promiseCallback function above.\n private primaryPageTargetPromise = new Promise(res => {\n this.primaryPageTargetPromiseCallback = res;\n });\n\n #traceEngineModel: Trace.TraceModel.Model;\n #sourceMapsResolver: SourceMapsResolver|null = null;\n #onSourceMapsNodeNamesResolvedBound = this.#onSourceMapsNodeNamesResolved.bind(this);\n readonly #onChartPlayableStateChangeBound: (event: Common.EventTarget.EventTargetEvent) => void;\n #sidebarToggleButton = this.#splitWidget.createShowHideSidebarButton(\n i18nString(UIStrings.showSidebar),\n i18nString(UIStrings.hideSidebar),\n // These are used to announce to screen-readers and not shown visibly.\n i18nString(UIStrings.sidebarShown),\n i18nString(UIStrings.sidebarHidden),\n 'timeline.sidebar', // jslog context\n );\n\n #sideBar = new TimelineComponents.Sidebar.SidebarWidget();\n /**\n * Rather than auto-pop the sidebar every time the user records a trace,\n * which could get annoying, we instead persist the state of the sidebar\n * visibility to a setting so it's restored across sessions.\n * However, sometimes we have to automatically hide the sidebar, like when a\n * trace recording is happening, or the user is on the landing page. In those\n * times, we toggle this flag to true. Then, when we enter the VIEWING_TRACE\n * mode, we check this flag and pop the sidebar open if it's set to true.\n * Longer term a better fix here would be to divide the 3 UI screens\n * (status pane, landing page, trace view) into distinct components /\n * widgets, to avoid this complexity.\n */\n #restoreSidebarVisibilityOnTraceLoad: boolean = false;\n\n constructor() {\n super('timeline');\n const adornerContent = document.createElement('span');\n adornerContent.innerHTML = `
💫
`;\n const adorner = new Adorners.Adorner.Adorner();\n adorner.classList.add('fix-perf-icon');\n adorner.data = {\n name: i18nString(UIStrings.fixMe),\n content: adornerContent,\n };\n this.brickBreakerToolbarButton = new UI.Toolbar.ToolbarButton(i18nString(UIStrings.fixMe), adorner);\n this.brickBreakerToolbarButton.addEventListener(\n UI.Toolbar.ToolbarButton.Events.CLICK, () => this.#onBrickBreakerEasterEggClick());\n const config = Trace.Types.Configuration.defaults();\n config.showAllEvents = Root.Runtime.experiments.isEnabled('timeline-show-all-events');\n config.includeRuntimeCallStats = Root.Runtime.experiments.isEnabled('timeline-v8-runtime-call-stats');\n config.debugMode = Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_DEBUG_MODE);\n\n this.#traceEngineModel = Trace.TraceModel.Model.createWithAllHandlers(config);\n this.#listenForProcessingProgress();\n\n this.element.addEventListener('contextmenu', this.contextMenu.bind(this), false);\n this.dropTarget = new UI.DropTarget.DropTarget(\n this.element, [UI.DropTarget.Type.File, UI.DropTarget.Type.URI],\n i18nString(UIStrings.dropTimelineFileOrUrlHere), this.handleDrop.bind(this));\n\n this.recordingOptionUIControls = [];\n this.state = State.IDLE;\n this.recordingPageReload = false;\n this.millisecondsToRecordAfterLoadEvent = 5000;\n this.toggleRecordAction = UI.ActionRegistry.ActionRegistry.instance().getAction('timeline.toggle-recording');\n this.recordReloadAction = UI.ActionRegistry.ActionRegistry.instance().getAction('timeline.record-reload');\n\n this.#historyManager = new TimelineHistoryManager(this.#minimapComponent);\n\n this.traceLoadStart = null;\n\n this.disableCaptureJSProfileSetting =\n Common.Settings.Settings.instance().createSetting('timeline-disable-js-sampling', false);\n this.disableCaptureJSProfileSetting.setTitle(i18nString(UIStrings.disableJavascriptSamples));\n this.captureLayersAndPicturesSetting = Common.Settings.Settings.instance().createSetting(\n 'timeline-capture-layers-and-pictures', false, Common.Settings.SettingStorageType.SESSION);\n this.captureLayersAndPicturesSetting.setTitle(i18nString(UIStrings.enableAdvancedPaint));\n this.captureSelectorStatsSetting = Common.Settings.Settings.instance().createSetting(\n 'timeline-capture-selector-stats', false, Common.Settings.SettingStorageType.SESSION);\n this.captureSelectorStatsSetting.setTitle(i18nString(UIStrings.enableSelectorStats));\n\n this.showScreenshotsSetting =\n Common.Settings.Settings.instance().createSetting('timeline-show-screenshots', isNode ? false : true);\n this.showScreenshotsSetting.setTitle(i18nString(UIStrings.screenshots));\n this.showScreenshotsSetting.addChangeListener(this.updateMiniMap, this);\n\n this.showMemorySetting = Common.Settings.Settings.instance().createSetting('timeline-show-memory', false);\n this.showMemorySetting.setTitle(i18nString(UIStrings.memory));\n this.showMemorySetting.addChangeListener(this.onModeChanged, this);\n\n this.#thirdPartyTracksSetting = TimelinePanel.extensionDataVisibilitySetting();\n this.#thirdPartyTracksSetting.addChangeListener(this.#extensionDataVisibilityChanged, this);\n this.#thirdPartyTracksSetting.setTitle(i18nString(UIStrings.performanceExtension));\n\n const timelineToolbarContainer = this.element.createChild('div', 'timeline-toolbar-container');\n timelineToolbarContainer.setAttribute('jslog', `${VisualLogging.toolbar()}`);\n this.panelToolbar = new UI.Toolbar.Toolbar('timeline-main-toolbar', timelineToolbarContainer);\n this.panelToolbar.makeWrappable(true);\n this.panelRightToolbar = new UI.Toolbar.Toolbar('', timelineToolbarContainer);\n if (!isNode) {\n this.createSettingsPane();\n this.updateShowSettingsToolbarButton();\n }\n this.timelinePane = new UI.Widget.VBox();\n const topPaneElement = this.timelinePane.element.createChild('div', 'hbox');\n topPaneElement.id = 'timeline-overview-panel';\n\n this.#minimapComponent.show(topPaneElement);\n\n this.statusPaneContainer = this.timelinePane.element.createChild('div', 'status-pane-container fill');\n\n this.createFileSelector();\n\n SDK.TargetManager.TargetManager.instance().addModelListener(\n SDK.ResourceTreeModel.ResourceTreeModel, SDK.ResourceTreeModel.Events.Load, this.loadEventFired, this);\n\n this.flameChart = new TimelineFlameChartView(this);\n this.#onChartPlayableStateChangeBound = this.#onChartPlayableStateChange.bind(this);\n\n this.flameChart.getMainFlameChart().addEventListener(\n PerfUI.FlameChart.Events.CHART_PLAYABLE_STATE_CHANGED, this.#onChartPlayableStateChangeBound, this);\n\n this.searchableViewInternal = new UI.SearchableView.SearchableView(this.flameChart, null);\n this.searchableViewInternal.setMinimumSize(0, 100);\n this.searchableViewInternal.element.classList.add('searchable-view');\n this.searchableViewInternal.show(this.timelinePane.element);\n this.flameChart.show(this.searchableViewInternal.element);\n this.flameChart.setSearchableView(this.searchableViewInternal);\n this.searchableViewInternal.hideWidget();\n\n this.#splitWidget.setMainWidget(this.timelinePane);\n this.#splitWidget.setSidebarWidget(this.#sideBar);\n this.#splitWidget.enableShowModeSaving();\n this.#splitWidget.show(this.element);\n\n this.#sideBar.element.addEventListener(TimelineInsights.SidebarInsight.InsightDeactivated.eventName, () => {\n this.#setActiveInsight(null);\n });\n\n this.#sideBar.element.addEventListener(TimelineInsights.SidebarInsight.InsightActivated.eventName, event => {\n const {name, navigationId, createOverlayFn} = event;\n this.#setActiveInsight({name, navigationId, createOverlayFn});\n });\n\n this.#sideBar.element.addEventListener(TimelineInsights.SidebarInsight.InsightOverlayOverride.eventName, event => {\n const {overlays} = event;\n this.flameChart.setOverlaysOverride(overlays);\n });\n\n this.#sideBar.contentElement.addEventListener(TimelineComponents.Sidebar.EventReferenceClick.eventName, event => {\n const {metricEvent} = event;\n this.flameChart.setSelectionAndReveal(TimelineSelection.fromTraceEvent(metricEvent));\n });\n\n this.#sideBar.element.addEventListener(TimelineComponents.Sidebar.RemoveAnnotation.eventName, event => {\n const {removedAnnotation} = (event as TimelineComponents.Sidebar.RemoveAnnotation);\n ModificationsManager.activeManager()?.removeAnnotation(removedAnnotation);\n });\n\n this.#sideBar.element.addEventListener(TimelineComponents.Sidebar.RevealAnnotation.eventName, event => {\n this.flameChart.revealAnnotation(event.annotation);\n });\n\n this.#sideBar.element.addEventListener(TimelineInsights.SidebarInsight.NavigationBoundsHovered.eventName, event => {\n if (event.bounds) {\n this.#minimapComponent.highlightBounds(event.bounds);\n } else {\n this.#minimapComponent.clearBoundsHighlight();\n }\n });\n\n this.onModeChanged();\n this.populateToolbar();\n // The viewMode is set by default to the landing page, so we don't call\n // `#changeView` here and can instead directly call showLandingPage();\n this.#showLandingPage();\n this.updateTimelineControls();\n\n SDK.TargetManager.TargetManager.instance().addEventListener(\n SDK.TargetManager.Events.SUSPEND_STATE_CHANGED, this.onSuspendStateChanged, this);\n const profilerModels = SDK.TargetManager.TargetManager.instance().models(SDK.CPUProfilerModel.CPUProfilerModel);\n for (const model of profilerModels) {\n for (const message of model.registeredConsoleProfileMessages) {\n this.consoleProfileFinished(message);\n }\n }\n SDK.TargetManager.TargetManager.instance().observeModels(\n SDK.CPUProfilerModel.CPUProfilerModel,\n {\n modelAdded: (model: SDK.CPUProfilerModel.CPUProfilerModel) => {\n model.addEventListener(\n SDK.CPUProfilerModel.Events.CONSOLE_PROFILE_FINISHED, event => this.consoleProfileFinished(event.data));\n },\n modelRemoved: (_model: SDK.CPUProfilerModel.CPUProfilerModel) => {\n\n },\n },\n );\n SDK.TargetManager.TargetManager.instance().observeTargets({\n targetAdded: (target: SDK.Target.Target) => {\n if (target !== SDK.TargetManager.TargetManager.instance().primaryPageTarget()) {\n return;\n }\n this.primaryPageTargetPromiseCallback(target);\n },\n targetRemoved: (_: SDK.Target.Target) => {},\n });\n }\n\n #setActiveInsight(insight: TimelineComponents.Sidebar.ActiveInsight|null): void {\n this.#sideBar.setActiveInsight(insight);\n this.flameChart.setActiveInsight(insight);\n }\n\n static instance(opts: {\n forceNew: boolean|null,\n isNode: boolean,\n }|undefined = {forceNew: null, isNode: false}): TimelinePanel {\n const {forceNew, isNode: isNodeMode} = opts;\n isNode = isNodeMode;\n\n if (!timelinePanelInstance || forceNew) {\n timelinePanelInstance = new TimelinePanel();\n }\n\n return timelinePanelInstance;\n }\n\n static extensionDataVisibilitySetting(): Common.Settings.Setting {\n // Calling this multiple times doesn't recreate the setting.\n // Instead, after the second call, the cached setting is returned.\n return Common.Settings.Settings.instance().createSetting('timeline-show-extension-data', true);\n }\n override searchableView(): UI.SearchableView.SearchableView|null {\n return this.searchableViewInternal;\n }\n\n override wasShown(): void {\n super.wasShown();\n UI.Context.Context.instance().setFlavor(TimelinePanel, this);\n this.registerCSSFiles([timelinePanelStyles]);\n // Record the performance tool load time.\n Host.userMetrics.panelLoaded('timeline', 'DevTools.Launch.Timeline');\n }\n\n override willHide(): void {\n UI.Context.Context.instance().setFlavor(TimelinePanel, null);\n this.#historyManager.cancelIfShowing();\n }\n\n loadFromEvents(events: Trace.Types.Events.Event[]): void {\n if (this.state !== State.IDLE) {\n return;\n }\n this.prepareToLoadTimeline();\n this.loader = TimelineLoader.loadFromEvents(events, this);\n }\n\n getFlameChart(): TimelineFlameChartView {\n return this.flameChart;\n }\n\n getMinimap(): TimelineMiniMap {\n return this.#minimapComponent;\n }\n\n /**\n * Determine if two view modes are equivalent. Useful because if {@see\n * #changeView} gets called and the new mode is identical to the current,\n * we can bail without doing any UI updates.\n */\n #viewModesEquivalent(m1: ViewMode, m2: ViewMode): boolean {\n if (m1.mode === 'LANDING_PAGE' && m2.mode === 'LANDING_PAGE') {\n return true;\n }\n\n if (m1.mode === 'STATUS_PANE_OVERLAY' && m2.mode === 'STATUS_PANE_OVERLAY') {\n return true;\n }\n\n // VIEWING_TRACE views are only equivalent if their traceIndex is the same.\n if (m1.mode === 'VIEWING_TRACE' && m2.mode === 'VIEWING_TRACE' && m1.traceIndex === m2.traceIndex) {\n return true;\n }\n return false;\n }\n\n #uninstallSourceMapsResolver(): void {\n if (this.#sourceMapsResolver) {\n // this set of NodeNames is cached by PIDs, so we clear it so we don't\n // use incorrect names from another trace that might happen to share\n // PID/TIDs.\n SourceMapsResolver.clearResolvedNodeNames();\n\n this.#sourceMapsResolver.removeEventListener(\n NodeNamesUpdated.eventName, this.#onSourceMapsNodeNamesResolvedBound);\n this.#sourceMapsResolver.uninstall();\n this.#sourceMapsResolver = null;\n }\n }\n\n #removeStatusPane(): void {\n if (this.statusPane) {\n this.statusPane.remove();\n }\n this.statusPane = null;\n }\n\n #changeView(newMode: ViewMode): void {\n if (this.#viewModesEquivalent(this.#viewMode, newMode)) {\n return;\n }\n\n if (this.#viewMode.mode === 'VIEWING_TRACE') {\n // If the current / about to be \"old\" view was viewing a trace\n // we also uninstall any source maps resolver for the trace that was active.\n // If the user swaps back to this trace via the history dropdown, this will be reinstated.\n this.#uninstallSourceMapsResolver();\n\n // Store any modifications (e.g. annotations) that the user has created\n // on the current trace before we move away to a new view.\n this.#saveModificationsForActiveTrace();\n }\n\n this.#viewMode = newMode;\n\n /**\n * Note that the TimelinePanel UI is really rendered in two distinct layers.\n * 1. status-pane-container: this is what renders both the StatusPane\n * loading modal AND the landing page.\n * What is important to note is that this renders ON TOP of the\n * SearchableView widget, which is what holds the FlameChartView.\n *\n * 2. SearchableView: this is the container that renders\n * TimelineFlameChartView and the rest of the flame chart code.\n *\n * What this layering means is that when we swap to the LANDING_PAGE or\n * STATUS_PANE_OVERLAY view, we don't actually need to reset the\n * SearchableView that is rendered behind it, because it won't be visible\n * and will be hidden behind the StatusPane/Landing Page.\n *\n * So the only time we update this SearchableView is when the user goes to\n * view a trace. That is why in the switch() statement below you won't see\n * any code that resets the SearchableView because we don't need to. We do\n * mark it as hidden, but mainly so the user can't accidentally use Cmd-F\n * to search a hidden view.\n */\n switch (newMode.mode) {\n case 'LANDING_PAGE': {\n this.#removeStatusPane();\n this.#showLandingPage();\n\n // Whilst we don't reset this, we hide it, mainly so the user cannot\n // hit Ctrl/Cmd-F and try to search when it isn't visible.\n this.searchableViewInternal.hideWidget();\n\n // Hide the brick-breaker easter egg\n this.brickBreakerToolbarButtonAdded = false;\n this.panelToolbar.removeToolbarItem(this.brickBreakerToolbarButton);\n return;\n }\n\n case 'VIEWING_TRACE': {\n this.#hideLandingPage();\n this.#setModelForActiveTrace();\n this.#removeStatusPane();\n this.#showSidebarIfRequired();\n return;\n }\n\n case 'STATUS_PANE_OVERLAY': {\n // We don't manage the StatusPane UI here; it is done in the\n // recordingStarted/recordingProgress callbacks, but we do make sure we\n // hide the landing page.\n this.#hideLandingPage();\n\n // We also hide the sidebar - else if the user is viewing a trace and\n // then load/record another, the sidebar remains visible.\n this.#hideSidebar();\n return;\n }\n default:\n Platform.assertNever(newMode, 'Unsupported TimelinePanel viewMode');\n }\n }\n\n #activeTraceIndex(): number|null {\n if (this.#viewMode.mode === 'VIEWING_TRACE') {\n return this.#viewMode.traceIndex;\n }\n return null;\n }\n\n /**\n * NOTE: this method only exists to enable some layout tests to be migrated to the new engine.\n * DO NOT use this method within DevTools. It is marked as deprecated so\n * within DevTools you are warned when using the method.\n * @deprecated\n **/\n getParsedTraceForLayoutTests(): Trace.Handlers.Types.ParsedTrace {\n const traceIndex = this.#activeTraceIndex();\n if (traceIndex === null) {\n throw new Error('No trace index active.');\n }\n const data = this.#traceEngineModel.parsedTrace(traceIndex);\n if (data === null) {\n throw new Error('No trace engine data found.');\n }\n return data;\n }\n\n /**\n * NOTE: this method only exists to enable some layout tests to be migrated to the new engine.\n * DO NOT use this method within DevTools. It is marked as deprecated so\n * within DevTools you are warned when using the method.\n * @deprecated\n **/\n getTraceEngineRawTraceEventsForLayoutTests(): readonly Trace.Types.Events.Event[] {\n const traceIndex = this.#activeTraceIndex();\n if (traceIndex === null) {\n throw new Error('No trace index active.');\n }\n const data = this.#traceEngineModel.rawTraceEvents(traceIndex);\n if (data === null) {\n throw new Error('No trace engine data found.');\n }\n return data;\n }\n\n #onChartPlayableStateChange(event: Common.EventTarget.EventTargetEvent): void {\n if (event.data) {\n const dateObj = new Date();\n const month = dateObj.getUTCMonth() + 1;\n const day = dateObj.getUTCDate();\n const isAprilFools = (month === 4 && (day === 1 || day === 2)); // Show only on April fools and the next day\n if (isAprilFools && !this.brickBreakerToolbarButtonAdded && SHOULD_SHOW_EASTER_EGG) {\n this.brickBreakerToolbarButtonAdded = true;\n this.panelToolbar.appendToolbarItem(this.brickBreakerToolbarButton);\n }\n } else {\n this.brickBreakerToolbarButtonAdded = false;\n this.panelToolbar.removeToolbarItem(this.brickBreakerToolbarButton);\n }\n }\n\n private loadFromCpuProfile(profile: Protocol.Profiler.Profile|null): void {\n if (this.state !== State.IDLE || profile === null) {\n return;\n }\n this.prepareToLoadTimeline();\n this.loader = TimelineLoader.loadFromCpuProfile(profile, this);\n }\n\n private setState(state: State): void {\n this.state = state;\n this.updateTimelineControls();\n }\n\n private createSettingCheckbox(setting: Common.Settings.Setting, tooltip: string): UI.Toolbar.ToolbarItem {\n const checkboxItem = new UI.Toolbar.ToolbarSettingCheckbox(setting, tooltip);\n this.recordingOptionUIControls.push(checkboxItem);\n return checkboxItem;\n }\n\n /**\n * Users don't explicitly opt in to the sidebar, but if they opt into either\n * Insights or Annotations, we will show the sidebar.\n */\n #panelSidebarEnabled(): boolean {\n const sidebarEnabled = Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_INSIGHTS) ||\n Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_ANNOTATIONS);\n return sidebarEnabled;\n }\n #addSidebarIconToToolbar(): void {\n if (!this.#panelSidebarEnabled()) {\n return;\n }\n\n if (this.panelToolbar.hasItem(this.#sidebarToggleButton)) {\n return;\n }\n\n this.panelToolbar.prependToolbarItem(this.#sidebarToggleButton);\n }\n\n /**\n * Used when the user deletes their last trace and is taken back to the\n * landing page - we don't add this icon until there is a trace loaded.\n */\n #removeSidebarIconFromToolbar(): void {\n this.panelToolbar.removeToolbarItem(this.#sidebarToggleButton);\n }\n\n private populateDownloadMenu(contextMenu: UI.ContextMenu.ContextMenu): void {\n contextMenu.viewSection().appendItem(i18nString(UIStrings.saveTraceWithAnnotationsMenuOption), () => {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.PerfPanelTraceExported);\n void this.saveToFile(/* isEnhancedTraces */ false, /* addModifications */ true);\n });\n contextMenu.viewSection().appendItem(i18nString(UIStrings.saveTraceWithoutAnnotationsMenuOption), () => {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.PerfPanelTraceExported);\n void this.saveToFile();\n });\n }\n\n private populateToolbar(): void {\n // Record\n this.panelToolbar.appendToolbarItem(UI.Toolbar.Toolbar.createActionButton(this.toggleRecordAction));\n this.panelToolbar.appendToolbarItem(UI.Toolbar.Toolbar.createActionButton(this.recordReloadAction));\n this.clearButton = new UI.Toolbar.ToolbarButton(i18nString(UIStrings.clear), 'clear', undefined, 'timeline.clear');\n this.clearButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, () => this.onClearButton());\n this.panelToolbar.appendToolbarItem(this.clearButton);\n\n // Load / SaveCLICK\n this.loadButton =\n new UI.Toolbar.ToolbarButton(i18nString(UIStrings.loadProfile), 'import', undefined, 'timeline.load-from-file');\n this.loadButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, () => {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.PerfPanelTraceImported);\n this.selectFileToLoad();\n });\n\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_ANNOTATIONS)) {\n this.saveButton = new UI.Toolbar.ToolbarMenuButton(\n this.populateDownloadMenu.bind(this), true, true, 'more-options', 'download');\n this.saveButton.setTitle(i18nString(UIStrings.saveProfile));\n } else {\n this.saveButton = new UI.Toolbar.ToolbarButton(\n i18nString(UIStrings.saveProfile), 'download', undefined, 'timeline.save-to-file');\n this.saveButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, _event => {\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.PerfPanelTraceExported);\n void this.saveToFile();\n });\n }\n\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_ENHANCED_TRACES)) {\n this.saveButton.element.addEventListener('contextmenu', event => {\n event.preventDefault();\n event.stopPropagation();\n\n if (event.ctrlKey || event.button === 2) {\n const contextMenu = new UI.ContextMenu.ContextMenu(event);\n contextMenu.saveSection().appendItem(i18nString(UIStrings.exportNormalTraces), () => {\n void this.saveToFile();\n });\n contextMenu.saveSection().appendItem(i18nString(UIStrings.exportEnhancedTraces), () => {\n void this.saveToFile(/* isEnhancedTraces */ true);\n });\n\n void contextMenu.show();\n } else {\n void this.saveToFile();\n }\n });\n }\n\n this.panelToolbar.appendSeparator();\n this.panelToolbar.appendToolbarItem(this.loadButton);\n this.panelToolbar.appendToolbarItem(this.saveButton);\n\n // History\n this.panelToolbar.appendSeparator();\n this.panelToolbar.appendToolbarItem(this.#historyManager.button());\n this.panelToolbar.registerCSSFiles([historyToolbarButtonStyles]);\n this.panelToolbar.appendSeparator();\n\n // View\n this.panelToolbar.appendSeparator();\n if (!isNode) {\n this.showScreenshotsToolbarCheckbox =\n this.createSettingCheckbox(this.showScreenshotsSetting, i18nString(UIStrings.captureScreenshots));\n this.panelToolbar.appendToolbarItem(this.showScreenshotsToolbarCheckbox);\n }\n\n this.showMemoryToolbarCheckbox =\n this.createSettingCheckbox(this.showMemorySetting, i18nString(UIStrings.showMemoryTimeline));\n this.panelToolbar.appendToolbarItem(this.showMemoryToolbarCheckbox);\n\n // GC\n this.panelToolbar.appendToolbarItem(UI.Toolbar.Toolbar.createActionButtonForId('components.collect-garbage'));\n\n // Isolate selector\n const isolateSelector = new IsolateSelector();\n if (isNode) {\n this.panelToolbar.appendSeparator();\n this.panelToolbar.appendToolbarItem(isolateSelector);\n }\n\n // Settings\n if (!isNode) {\n this.panelRightToolbar.appendSeparator();\n this.panelRightToolbar.appendToolbarItem(this.showSettingsPaneButton);\n }\n }\n\n private createSettingsPane(): void {\n this.showSettingsPaneSetting =\n Common.Settings.Settings.instance().createSetting('timeline-show-settings-toolbar', false);\n this.showSettingsPaneButton = new UI.Toolbar.ToolbarSettingToggle(\n this.showSettingsPaneSetting, 'gear', i18nString(UIStrings.captureSettings), 'gear-filled',\n 'timeline-settings-toggle');\n SDK.NetworkManager.MultitargetNetworkManager.instance().addEventListener(\n SDK.NetworkManager.MultitargetNetworkManager.Events.CONDITIONS_CHANGED, this.updateShowSettingsToolbarButton,\n this);\n SDK.CPUThrottlingManager.CPUThrottlingManager.instance().addEventListener(\n SDK.CPUThrottlingManager.Events.RATE_CHANGED, this.updateShowSettingsToolbarButton, this);\n SDK.CPUThrottlingManager.CPUThrottlingManager.instance().addEventListener(\n SDK.CPUThrottlingManager.Events.HARDWARE_CONCURRENCY_CHANGED, this.updateShowSettingsToolbarButton, this);\n this.disableCaptureJSProfileSetting.addChangeListener(this.updateShowSettingsToolbarButton, this);\n this.captureLayersAndPicturesSetting.addChangeListener(this.updateShowSettingsToolbarButton, this);\n this.captureSelectorStatsSetting.addChangeListener(this.updateShowSettingsToolbarButton, this);\n\n this.settingsPane = new UI.Widget.HBox();\n this.settingsPane.element.classList.add('timeline-settings-pane');\n this.settingsPane.element.setAttribute(\n 'jslog', `${VisualLogging.pane('timeline-settings-pane').track({resize: true})}`);\n this.settingsPane.show(this.element);\n\n const captureToolbar = new UI.Toolbar.Toolbar('', this.settingsPane.element);\n captureToolbar.element.classList.add('flex-auto');\n captureToolbar.makeVertical();\n captureToolbar.appendToolbarItem(this.createSettingCheckbox(\n this.disableCaptureJSProfileSetting, i18nString(UIStrings.disablesJavascriptSampling)));\n captureToolbar.appendToolbarItem(\n this.createSettingCheckbox(this.captureLayersAndPicturesSetting, i18nString(UIStrings.capturesAdvancedPaint)));\n captureToolbar.appendToolbarItem(\n this.createSettingCheckbox(this.captureSelectorStatsSetting, i18nString(UIStrings.capturesSelectorStats)));\n\n const throttlingPane = new UI.Widget.VBox();\n throttlingPane.element.classList.add('flex-auto');\n throttlingPane.show(this.settingsPane.element);\n\n const cpuThrottlingToolbar = new UI.Toolbar.Toolbar('', throttlingPane.element);\n cpuThrottlingToolbar.appendText(i18nString(UIStrings.cpu));\n this.cpuThrottlingSelect = MobileThrottling.ThrottlingManager.throttlingManager().createCPUThrottlingSelector();\n cpuThrottlingToolbar.appendToolbarItem(this.cpuThrottlingSelect);\n\n const networkThrottlingToolbar = new UI.Toolbar.Toolbar('', throttlingPane.element);\n networkThrottlingToolbar.appendText(i18nString(UIStrings.network));\n this.networkThrottlingSelect = this.createNetworkConditionsSelect();\n networkThrottlingToolbar.appendToolbarItem(this.networkThrottlingSelect);\n\n const hardwareConcurrencyPane = new UI.Widget.VBox();\n hardwareConcurrencyPane.element.classList.add('flex-auto');\n hardwareConcurrencyPane.show(this.settingsPane.element);\n\n const thirdPartyToolbar = new UI.Toolbar.Toolbar('', this.settingsPane.element);\n thirdPartyToolbar.element.classList.add('flex-auto');\n thirdPartyToolbar.makeVertical();\n thirdPartyToolbar.appendToolbarItem(\n this.createSettingCheckbox(this.#thirdPartyTracksSetting, i18nString(UIStrings.showDataAddedByExtensions)));\n\n const {toggle, input, reset, warning} =\n MobileThrottling.ThrottlingManager.throttlingManager().createHardwareConcurrencySelector();\n const concurrencyThrottlingToolbar = new UI.Toolbar.Toolbar('', hardwareConcurrencyPane.element);\n concurrencyThrottlingToolbar.registerCSSFiles([timelinePanelStyles]);\n input.element.classList.add('timeline-concurrency-input');\n concurrencyThrottlingToolbar.appendToolbarItem(toggle);\n concurrencyThrottlingToolbar.appendToolbarItem(input);\n concurrencyThrottlingToolbar.appendToolbarItem(reset);\n concurrencyThrottlingToolbar.appendToolbarItem(warning);\n\n this.showSettingsPaneSetting.addChangeListener(this.updateSettingsPaneVisibility.bind(this));\n this.updateSettingsPaneVisibility();\n }\n\n private createNetworkConditionsSelect(): UI.Toolbar.ToolbarComboBox {\n const toolbarItem = new UI.Toolbar.ToolbarComboBox(null, i18nString(UIStrings.networkConditions));\n toolbarItem.setMaxWidth(140);\n MobileThrottling.ThrottlingManager.throttlingManager().decorateSelectWithNetworkThrottling(\n toolbarItem.selectElement());\n return toolbarItem;\n }\n\n private prepareToLoadTimeline(): void {\n console.assert(this.state === State.IDLE);\n this.setState(State.LOADING);\n }\n\n private createFileSelector(): void {\n if (this.fileSelectorElement) {\n this.fileSelectorElement.remove();\n }\n // .gz is far more popular than .gzip, but both are valid.\n this.fileSelectorElement =\n UI.UIUtils.createFileSelectorElement(this.loadFromFile.bind(this), '.json,.gz,.gzip,.cpuprofile');\n this.timelinePane.element.appendChild(this.fileSelectorElement);\n }\n\n private contextMenu(event: Event): void {\n // Do not show this Context menu on FlameChart entries because we have a different context menu for FlameChart entries\n const mouseEvent = (event as MouseEvent);\n if (this.flameChart.getMainFlameChart().coordinatesToEntryIndex(mouseEvent.offsetX, mouseEvent.offsetY) !== -1) {\n return;\n }\n const contextMenu = new UI.ContextMenu.ContextMenu(event, {useSoftMenu: true});\n contextMenu.appendItemsAtLocation('timelineMenu');\n void contextMenu.show();\n }\n\n async saveToFile(isEnhancedTraces: boolean = false, addModifications: boolean = false): Promise {\n if (this.state !== State.IDLE) {\n return;\n }\n if (this.#viewMode.mode !== 'VIEWING_TRACE') {\n return;\n }\n const traceEvents = this.#traceEngineModel.rawTraceEvents(this.#viewMode.traceIndex);\n const metadata = this.#traceEngineModel.metadata(this.#viewMode.traceIndex);\n // Save modifications into the metadata if modifications experiment is on\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_ANNOTATIONS) && metadata &&\n addModifications) {\n metadata.modifications = ModificationsManager.activeManager()?.toJSON();\n } else if (metadata) {\n delete metadata.modifications;\n }\n if (metadata && isEnhancedTraces) {\n metadata.enhancedTraceVersion = SDK.EnhancedTracesParser.EnhancedTracesParser.enhancedTraceVersion;\n }\n if (!traceEvents) {\n return;\n }\n\n const traceStart = Platform.DateUtilities.toISO8601Compact(new Date());\n let fileName: Platform.DevToolsPath.RawPathString;\n if (metadata?.dataOrigin === Trace.Types.File.DataOrigin.CPU_PROFILE) {\n fileName = `CPU-${traceStart}.cpuprofile` as Platform.DevToolsPath.RawPathString;\n } else if (metadata && metadata.enhancedTraceVersion) {\n fileName = `EnhancedTraces-${traceStart}.json` as Platform.DevToolsPath.RawPathString;\n } else {\n fileName = `Trace-${traceStart}.json` as Platform.DevToolsPath.RawPathString;\n }\n\n try {\n // TODO(crbug.com/1456818): Extract this logic and add more tests.\n let traceAsString;\n if (metadata?.dataOrigin === Trace.Types.File.DataOrigin.CPU_PROFILE) {\n const profileEvent = traceEvents.find(e => e.name === 'CpuProfile');\n if (!profileEvent || !profileEvent.args?.data) {\n return;\n }\n const profileEventData = profileEvent.args?.data;\n if (profileEventData.hasOwnProperty('cpuProfile')) {\n // TODO(crbug.com/1456799): Currently use a hack way because we can't differentiate\n // cpuprofile from trace events when loading a file.\n // The loader will directly add the fake trace created from CpuProfile to the tracingModel.\n // And there is where the old saving logic saves the cpuprofile.\n // This will be solved when the CPUProfileHandler is done. Then we can directly get it\n // from the new traceEngine\n const profile = (profileEventData as {cpuProfile: Protocol.Profiler.Profile}).cpuProfile;\n traceAsString = cpuprofileJsonGenerator(profile as Protocol.Profiler.Profile);\n }\n } else {\n const formattedTraceIter = traceJsonGenerator(traceEvents, metadata);\n traceAsString = Array.from(formattedTraceIter).join('');\n }\n if (!traceAsString) {\n throw new Error('Trace content empty');\n }\n await Workspace.FileManager.FileManager.instance().save(\n fileName, traceAsString, true /* forceSaveAs */, false /* isBase64 */);\n Workspace.FileManager.FileManager.instance().close(fileName);\n } catch (error) {\n console.error(error.stack);\n if (error.name === 'AbortError') {\n // The user cancelled the action, so this is not an error we need to report.\n return;\n }\n Common.Console.Console.instance().error(\n i18nString(UIStrings.failedToSaveTimelineSS, {PH1: error.message, PH2: error.name}));\n }\n }\n\n async showHistoryDropdown(): Promise {\n const recordingData = await this.#historyManager.showHistoryDropDown();\n if (recordingData) {\n if (recordingData.type === 'LANDING_PAGE') {\n this.#changeView({mode: 'LANDING_PAGE'});\n } else {\n this.#changeView({\n mode: 'VIEWING_TRACE',\n traceIndex: recordingData.parsedTraceIndex,\n });\n }\n }\n }\n\n navigateHistory(direction: number): boolean {\n const recordingData = this.#historyManager.navigate(direction);\n // When navigating programatically, you cannot navigate to the landing page\n // view, so we can discount that possibility here.\n if (recordingData && recordingData.type === 'TRACE_INDEX') {\n this.#changeView({\n mode: 'VIEWING_TRACE',\n traceIndex: recordingData.parsedTraceIndex,\n });\n }\n return true;\n }\n\n #saveModificationsForActiveTrace(): void {\n if (this.#viewMode.mode !== 'VIEWING_TRACE') {\n return;\n }\n const newModifications = ModificationsManager.activeManager()?.toJSON();\n if (newModifications) {\n this.#traceEngineModel.overrideModifications(this.#viewMode.traceIndex, newModifications);\n }\n }\n\n selectFileToLoad(): void {\n if (this.fileSelectorElement) {\n this.fileSelectorElement.click();\n }\n }\n\n async loadFromFile(file: File): Promise {\n if (this.state !== State.IDLE) {\n return;\n }\n this.prepareToLoadTimeline();\n this.loader = await TimelineLoader.loadFromFile(file, this);\n this.createFileSelector();\n }\n\n async loadFromURL(url: Platform.DevToolsPath.UrlString): Promise {\n if (this.state !== State.IDLE) {\n return;\n }\n this.prepareToLoadTimeline();\n this.loader = await TimelineLoader.loadFromURL(url, this);\n }\n\n private updateMiniMap(): void {\n if (this.#viewMode.mode !== 'VIEWING_TRACE') {\n return;\n }\n\n const parsedTrace = this.#traceEngineModel.parsedTrace(this.#viewMode.traceIndex);\n const isCpuProfile = this.#traceEngineModel.metadata(this.#viewMode.traceIndex)?.dataOrigin ===\n Trace.Types.File.DataOrigin.CPU_PROFILE;\n if (!parsedTrace) {\n return;\n }\n\n this.#minimapComponent.setData({\n parsedTrace,\n isCpuProfile,\n settings: {\n showScreenshots: this.showScreenshotsSetting.get(),\n showMemory: this.showMemorySetting.get(),\n },\n });\n }\n\n private onModeChanged(): void {\n this.flameChart.updateCountersGraphToggle(this.showMemorySetting.get());\n this.updateMiniMap();\n this.doResize();\n this.select(null);\n }\n\n #extensionDataVisibilityChanged(): void {\n this.flameChart.extensionDataVisibilityChanged();\n }\n\n private updateSettingsPaneVisibility(): void {\n if (isNode) {\n return;\n }\n if (this.showSettingsPaneSetting.get()) {\n this.showSettingsPaneButton.setToggled(true);\n this.settingsPane.showWidget();\n } else {\n this.showSettingsPaneButton.setToggled(false);\n this.settingsPane.hideWidget();\n }\n }\n\n private updateShowSettingsToolbarButton(): void {\n const messages: string[] = [];\n if (SDK.CPUThrottlingManager.CPUThrottlingManager.instance().cpuThrottlingRate() !== 1) {\n messages.push(i18nString(UIStrings.CpuThrottlingIsEnabled));\n }\n if (MobileThrottling.ThrottlingManager.throttlingManager().hardwareConcurrencyOverrideEnabled) {\n messages.push(i18nString(UIStrings.HardwareConcurrencyIsEnabled));\n }\n if (SDK.NetworkManager.MultitargetNetworkManager.instance().isThrottling()) {\n messages.push(i18nString(UIStrings.NetworkThrottlingIsEnabled));\n }\n if (this.captureLayersAndPicturesSetting.get()) {\n messages.push(i18nString(UIStrings.SignificantOverheadDueToPaint));\n }\n if (this.captureSelectorStatsSetting.get()) {\n messages.push(i18nString(UIStrings.SelectorStatsEnabled));\n }\n if (this.disableCaptureJSProfileSetting.get()) {\n messages.push(i18nString(UIStrings.JavascriptSamplingIsDisabled));\n }\n\n this.showSettingsPaneButton.setChecked(messages.length > 0);\n this.showSettingsPaneButton.element.style.setProperty('--dot-toggle-top', '16px');\n this.showSettingsPaneButton.element.style.setProperty('--dot-toggle-left', '15px');\n\n if (messages.length) {\n const tooltipElement = document.createElement('div');\n messages.forEach(message => {\n tooltipElement.createChild('div').textContent = message;\n });\n this.showSettingsPaneButton.setTitle(tooltipElement.textContent || '');\n } else {\n this.showSettingsPaneButton.setTitle(i18nString(UIStrings.captureSettings));\n }\n }\n\n private setUIControlsEnabled(enabled: boolean): void {\n this.recordingOptionUIControls.forEach(control => control.setEnabled(enabled));\n }\n\n async #evaluateInspectedURL(): Promise {\n if (!this.controller) {\n return Platform.DevToolsPath.EmptyUrlString;\n }\n\n // target.inspectedURL is reliably populated, however it lacks any url #hash\n const inspectedURL = this.controller.primaryPageTarget.inspectedURL();\n\n // We'll use the navigationHistory to acquire the current URL including hash\n const resourceTreeModel = this.controller.primaryPageTarget.model(SDK.ResourceTreeModel.ResourceTreeModel);\n const navHistory = resourceTreeModel && await resourceTreeModel.navigationHistory();\n if (!resourceTreeModel || !navHistory) {\n return inspectedURL;\n }\n\n const {currentIndex, entries} = navHistory;\n const navigationEntry = entries[currentIndex];\n return navigationEntry.url as Platform.DevToolsPath.UrlString;\n }\n\n async #navigateToAboutBlank(): Promise {\n const aboutBlankNavigationComplete = new Promise(async (resolve, reject) => {\n if (!this.controller) {\n reject('Could not find TimelineController');\n return;\n }\n const target = this.controller.primaryPageTarget;\n const resourceModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel);\n if (!resourceModel) {\n reject('Could not load resourceModel');\n return;\n }\n\n // To clear out the page and any state from prior test runs, we\n // navigate to about:blank before initiating the trace recording.\n // Once we have navigated to about:blank, we start recording and\n // then navigate to the original page URL, to ensure we profile the\n // page load.\n function waitForAboutBlank(event: Common.EventTarget.EventTargetEvent):\n void {\n if (event.data.url === 'about:blank') {\n resolve();\n } else {\n reject(`Unexpected navigation to ${event.data.url}`);\n }\n resourceModel?.removeEventListener(SDK.ResourceTreeModel.Events.FrameNavigated, waitForAboutBlank);\n }\n resourceModel.addEventListener(SDK.ResourceTreeModel.Events.FrameNavigated, waitForAboutBlank);\n await resourceModel.navigate('about:blank' as Platform.DevToolsPath.UrlString);\n });\n await aboutBlankNavigationComplete;\n }\n\n async #startCPUProfilingRecording(): Promise {\n try {\n this.cpuProfiler = UI.Context.Context.instance().flavor(SDK.CPUProfilerModel.CPUProfilerModel);\n if (!this.cpuProfiler) {\n // If there is no isolate selected, we will profile the first isolate that devtools connects to.\n // If we profile all target, but this will cause some bugs like time for the function is calculated wrong,\n // because the profiles will be concated and sorted together, so the total time will be amplified.\n // Multiple targets problem might happen when you inspect multiple node servers on different port at same time,\n // or when you let DevTools listen to both locolhost:9229 & 127.0.0.1:9229.\n const firstNodeTarget =\n SDK.TargetManager.TargetManager.instance().targets().find(target => target.type() === SDK.Target.Type.NODE);\n if (!firstNodeTarget) {\n throw new Error('Could not load any Node target.');\n }\n if (firstNodeTarget) {\n this.cpuProfiler = firstNodeTarget.model(SDK.CPUProfilerModel.CPUProfilerModel);\n }\n }\n\n this.setUIControlsEnabled(false);\n this.#changeView({mode: 'STATUS_PANE_OVERLAY'});\n if (!this.cpuProfiler) {\n throw new Error('No Node target is found.');\n }\n await SDK.TargetManager.TargetManager.instance().suspendAllTargets('performance-timeline');\n await this.cpuProfiler.startRecording();\n\n this.recordingStarted();\n } catch (e) {\n await this.recordingFailed(e.message);\n }\n }\n\n async #startTraceRecording(): Promise {\n try {\n // We record against the root target, but also need to use the\n // primaryPageTarget to inspect the current URL. For more info, see the\n // JSDoc comment on the TimelineController constructor.\n const rootTarget = SDK.TargetManager.TargetManager.instance().rootTarget();\n const primaryPageTarget = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n\n if (!primaryPageTarget) {\n throw new Error('Could not load primary page target.');\n }\n if (!rootTarget) {\n throw new Error('Could not load root target.');\n }\n\n if (UIDevtoolsUtils.isUiDevTools()) {\n this.controller = new UIDevtoolsController(rootTarget, primaryPageTarget, this);\n } else {\n this.controller = new TimelineController(rootTarget, primaryPageTarget, this);\n }\n this.setUIControlsEnabled(false);\n this.#changeView({mode: 'STATUS_PANE_OVERLAY'});\n if (!this.controller) {\n throw new Error('Could not create Timeline controller');\n }\n\n const urlToTrace = await this.#evaluateInspectedURL();\n // If we are doing \"Reload & record\", we first navigate the page to\n // about:blank. This is to ensure any data on the timeline from any\n // previous performance recording is lost, avoiding the problem where a\n // timeline will show data & screenshots from a previous page load that\n // was not relevant.\n if (this.recordingPageReload) {\n await this.#navigateToAboutBlank();\n }\n const recordingOptions = {\n enableJSSampling: !this.disableCaptureJSProfileSetting.get(),\n capturePictures: this.captureLayersAndPicturesSetting.get(),\n captureFilmStrip: this.showScreenshotsSetting.get(),\n captureSelectorStats: this.captureSelectorStatsSetting.get(),\n };\n // Order is important here: we tell the controller to start recording, which enables tracing.\n const response = await this.controller.startRecording(recordingOptions);\n if (response.getError()) {\n throw new Error(response.getError());\n }\n // Once we get here, we know tracing is active.\n // This is when, if the user has hit \"Reload & Record\" that we now need to navigate to the original URL.\n // If the user has just hit \"record\", we don't do any navigating.\n const recordingConfig = this.recordingPageReload ? {navigateToUrl: urlToTrace} : undefined;\n this.recordingStarted(recordingConfig);\n } catch (e) {\n await this.recordingFailed(e.message);\n }\n }\n\n private async startRecording(): Promise {\n console.assert(!this.statusPane, 'Status pane is already opened.');\n this.setState(State.START_PENDING);\n this.showRecordingStarted();\n\n if (isNode) {\n await this.#startCPUProfilingRecording();\n } else {\n await this.#startTraceRecording();\n }\n }\n\n private async stopRecording(): Promise {\n if (this.statusPane) {\n this.statusPane.finish();\n this.statusPane.updateStatus(i18nString(UIStrings.stoppingTimeline));\n this.statusPane.updateProgressBar(i18nString(UIStrings.received), 0);\n }\n this.setState(State.STOP_PENDING);\n if (this.controller) {\n await this.controller.stopRecording();\n this.setUIControlsEnabled(true);\n await this.controller.dispose();\n this.controller = null;\n return;\n }\n if (this.cpuProfiler) {\n const profile = await this.cpuProfiler.stopRecording();\n this.setState(State.IDLE);\n this.loadFromCpuProfile(profile);\n\n this.setUIControlsEnabled(true);\n this.cpuProfiler = null;\n\n await SDK.TargetManager.TargetManager.instance().resumeAllTargets();\n }\n }\n\n private async recordingFailed(error: string, rawEvents?: Trace.Types.Events.Event[]): Promise {\n if (this.statusPane) {\n this.statusPane.remove();\n }\n this.statusPane = new StatusPane(\n {\n description: error,\n buttonText: i18nString(UIStrings.close),\n buttonDisabled: false,\n showProgress: undefined,\n showTimer: undefined,\n },\n // When recording failed, we should load null to go back to the landing page.\n async () => {\n this.statusPane?.remove();\n await this.loadingComplete(\n /* no collectedEvents */[],\n /* exclusiveFilter= */ null,\n /* isCpuProfile= */ false,\n /* recordingStartTime= */ null,\n /* metadata= */ null);\n });\n this.statusPane.showPane(this.statusPaneContainer);\n this.statusPane.updateStatus(i18nString(UIStrings.recordingFailed));\n\n if (rawEvents) {\n this.statusPane.enableDownloadOfEvents(rawEvents);\n }\n\n this.setState(State.RECORDING_FAILED);\n this.traceLoadStart = null;\n this.setUIControlsEnabled(true);\n if (this.controller) {\n await this.controller.dispose();\n this.controller = null;\n }\n // Ensure we resume all targets, otherwise DevTools remains unresponsive in the event of an error.\n void SDK.TargetManager.TargetManager.instance().resumeAllTargets();\n }\n\n private onSuspendStateChanged(): void {\n this.updateTimelineControls();\n }\n\n private consoleProfileFinished(data: SDK.CPUProfilerModel.ProfileFinishedData): void {\n this.loadFromCpuProfile(data.cpuProfile);\n void UI.InspectorView.InspectorView.instance().showPanel('timeline');\n }\n\n private updateTimelineControls(): void {\n this.toggleRecordAction.setToggled(this.state === State.RECORDING);\n this.toggleRecordAction.setEnabled(this.state === State.RECORDING || this.state === State.IDLE);\n this.recordReloadAction.setEnabled(isNode ? false : this.state === State.IDLE);\n this.#historyManager.setEnabled(this.state === State.IDLE);\n this.clearButton.setEnabled(this.state === State.IDLE);\n this.panelToolbar.setEnabled(this.state !== State.LOADING);\n this.panelRightToolbar.setEnabled(this.state !== State.LOADING);\n this.dropTarget.setEnabled(this.state === State.IDLE);\n this.loadButton.setEnabled(this.state === State.IDLE);\n this.saveButton.setEnabled(this.state === State.IDLE && this.#hasActiveTrace());\n if (this.#viewMode.mode === 'VIEWING_TRACE') {\n this.#addSidebarIconToToolbar();\n }\n }\n\n async toggleRecording(): Promise {\n if (this.state === State.IDLE) {\n this.recordingPageReload = false;\n await this.startRecording();\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.TimelineStarted);\n } else if (this.state === State.RECORDING) {\n await this.stopRecording();\n }\n }\n\n recordReload(): void {\n if (this.state !== State.IDLE) {\n return;\n }\n this.recordingPageReload = true;\n void this.startRecording();\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.TimelinePageReloadStarted);\n }\n\n private onClearButton(): void {\n this.#historyManager.clear();\n this.#changeView({mode: 'LANDING_PAGE'});\n }\n\n #hasActiveTrace(): boolean {\n return this.#viewMode.mode === 'VIEWING_TRACE';\n }\n\n #onBrickBreakerEasterEggClick(): void {\n if (!this.#hasActiveTrace()) {\n return;\n }\n this.flameChart.runBrickBreakerGame();\n }\n\n #applyActiveFilters(\n traceIsGeneric: boolean,\n exclusiveFilter: TimelineModel.TimelineModelFilter.TimelineModelFilter|null = null): void {\n if (traceIsGeneric || Root.Runtime.experiments.isEnabled('timeline-show-all-events')) {\n return;\n }\n\n const newActiveFilters = exclusiveFilter ? [exclusiveFilter] : [\n TimelineUIUtils.visibleEventsFilter(),\n ];\n\n ActiveFilters.instance().setFilters(newActiveFilters);\n }\n\n /**\n * Called when we update the active trace that is being shown to the user.\n * This is called from {@see changeView} when we change the UI to show a\n * trace - either one the user has just recorded/imported, or one they have\n * navigated to via the dropdown.\n *\n * If you need code to execute whenever the active trace changes, this is the method to use.\n * If you need code to execute ONLY ON NEW TRACES, then use {@see loadingComplete}\n * You should not call this method directly if you want the UI to update; use\n * {@see changeView} to control what is shown to the user.\n */\n #setModelForActiveTrace(): void {\n if (this.#viewMode.mode !== 'VIEWING_TRACE') {\n return;\n }\n const {traceIndex} = this.#viewMode;\n const parsedTrace = this.#traceEngineModel.parsedTrace(traceIndex);\n const syntheticEventsManager = this.#traceEngineModel.syntheticTraceEventsManager(traceIndex);\n\n if (!parsedTrace || !syntheticEventsManager) {\n // This should not happen, because you can only get into the\n // VIEWING_TRACE viewMode if you have a valid trace index from the\n // Trace Engine. If it does, let's bail back to the landing page.\n console.error(`setModelForActiveTrace was called with an invalid trace index: ${traceIndex}`);\n this.#changeView({mode: 'LANDING_PAGE'});\n return;\n }\n\n Trace.Helpers.SyntheticEvents.SyntheticEventsManager.activate(syntheticEventsManager);\n // Clear the line level profile that could exist from the previous trace.\n PerfUI.LineLevelProfile.Performance.instance().reset();\n\n this.#minimapComponent.reset();\n\n // Order is important: the bounds must be set before we initiate any UI\n // rendering.\n TraceBounds.TraceBounds.BoundsManager.instance().resetWithNewBounds(\n parsedTrace.Meta.traceBounds,\n );\n\n // Set up the modifications manager for the newly active trace.\n // The order is important: this needs to happen before we trigger a flame chart redraw by setting the model.\n // (it could happen after, but then we would need to trigger a fresh redraw so let's not do that)\n const currentManager = ModificationsManager.initAndActivateModificationsManager(this.#traceEngineModel, traceIndex);\n\n if (!currentManager) {\n console.error('ModificationsManager could not be created or activated.');\n }\n this.statusPane?.updateProgressBar(i18nString(UIStrings.processed), 70);\n\n const isCpuProfile =\n this.#traceEngineModel.metadata(traceIndex)?.dataOrigin === Trace.Types.File.DataOrigin.CPU_PROFILE;\n this.flameChart.setModel(parsedTrace, isCpuProfile);\n this.flameChart.resizeToPreferredHeights();\n // Reset the visual selection as we've just swapped to a new trace.\n this.flameChart.setSelectionAndReveal(null);\n this.#sideBar.setParsedTrace(parsedTrace);\n\n this.searchableViewInternal.showWidget();\n\n const exclusiveFilter = this.#exclusiveFilterPerTrace.get(traceIndex) ?? null;\n this.#applyActiveFilters(parsedTrace.Meta.traceIsGeneric, exclusiveFilter);\n\n // Add ModificationsManager listeners for annotations change to update the Annotation Overlays.\n currentManager?.addEventListener(AnnotationModifiedEvent.eventName, event => {\n const {overlay, action} = (event as AnnotationModifiedEvent);\n if (action === 'Add') {\n this.flameChart.addOverlay(overlay);\n } else if (action === 'Remove') {\n this.flameChart.removeOverlay(overlay);\n } else if (action === 'UpdateTimeRange' && Overlays.Overlays.isTimeRangeLabel(overlay)) {\n this.flameChart.updateExistingOverlay(overlay, {\n bounds: overlay.bounds,\n });\n } else if (action === 'UpdateLinkToEntry' && Overlays.Overlays.isEntriesLink(overlay)) {\n this.flameChart.updateExistingOverlay(overlay, {\n entryTo: overlay.entryTo,\n });\n } else if (action === 'EnterLabelEditState' && Overlays.Overlays.isEntryLabel(overlay)) {\n this.flameChart.enterLabelEditMode(overlay);\n }\n\n const annotations = currentManager.getAnnotations();\n const annotationEntryToColorMap = this.buildColorsAnnotationsMap(annotations);\n this.#sideBar.setAnnotations(annotations, annotationEntryToColorMap);\n });\n\n // To calculate the activity we might want to zoom in, we use the top-most main-thread track\n const topMostMainThreadAppender =\n this.flameChart.getMainDataProvider().compatibilityTracksAppenderInstance().threadAppenders().at(0);\n if (topMostMainThreadAppender) {\n const zoomedInBounds = Trace.Extras.MainThreadActivity.calculateWindow(\n parsedTrace.Meta.traceBounds, topMostMainThreadAppender.getEntries());\n\n TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(zoomedInBounds);\n }\n\n // Add overlays for annotations loaded from the trace file\n const currModificationManager = ModificationsManager.activeManager();\n if (currModificationManager) {\n const annotations = currModificationManager.getAnnotations();\n const annotationEntryToColorMap = this.buildColorsAnnotationsMap(annotations);\n this.#sideBar.setAnnotations(annotations, annotationEntryToColorMap);\n this.flameChart.bulkAddOverlays(currModificationManager.getOverlays());\n }\n\n // Set up line level profiling with CPU profiles, if we found any.\n PerfUI.LineLevelProfile.Performance.instance().reset();\n if (parsedTrace && parsedTrace.Samples.profilesInProcess.size) {\n const primaryPageTarget = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n // Gather up all CPU Profiles we found when parsing this trace.\n const cpuProfiles =\n Array.from(parsedTrace.Samples.profilesInProcess).flatMap(([_processId, threadsInProcess]) => {\n const profiles = Array.from(threadsInProcess.values()).map(profileData => profileData.parsedProfile);\n return profiles;\n });\n for (const profile of cpuProfiles) {\n PerfUI.LineLevelProfile.Performance.instance().appendCPUProfile(profile, primaryPageTarget);\n }\n }\n\n // Set up SourceMapsResolver to ensure we resolve any function names in\n // profile calls.\n this.#sourceMapsResolver = new SourceMapsResolver(parsedTrace);\n this.#sourceMapsResolver.addEventListener(NodeNamesUpdated.eventName, this.#onSourceMapsNodeNamesResolvedBound);\n void this.#sourceMapsResolver.install();\n\n this.statusPane?.updateProgressBar(i18nString(UIStrings.processed), 80);\n this.updateMiniMap();\n this.statusPane?.updateProgressBar(i18nString(UIStrings.processed), 90);\n this.updateTimelineControls();\n\n this.#setActiveInsight(null);\n\n const traceInsightsSets = this.#traceEngineModel.traceInsights(traceIndex);\n if (traceInsightsSets) {\n this.flameChart.setInsights(traceInsightsSets);\n this.#sideBar.setInsights(traceInsightsSets);\n }\n\n this.#showSidebarIfRequired();\n }\n\n /**\n * We automatically show the sidebar in only 2 scenarios:\n * 1. The user has never seen it before, so we show it once to aid discovery\n * 2. The user had it open, and we hid it (for example, during recording), so now we need to bring it back.\n * We also check that the experiments are enabled, else we reveal an entirely empty sidebar.\n */\n #showSidebarIfRequired(): void {\n const needToRestore = this.#restoreSidebarVisibilityOnTraceLoad;\n const userHasSeenSidebar = this.#sideBar.userHasOpenedSidebarOnce();\n const experimentsEnabled = this.#panelSidebarEnabled();\n\n if (experimentsEnabled && (!userHasSeenSidebar || needToRestore)) {\n this.#splitWidget.showBoth();\n }\n this.#restoreSidebarVisibilityOnTraceLoad = false;\n }\n\n // Build a map mapping annotated entries to the colours that are used to display them in the FlameChart.\n // We need this map to display the entries in the sidebar with the same colours.\n private buildColorsAnnotationsMap(annotations: Trace.Types.File.Annotation[]): Map {\n const annotationEntryToColorMap = new Map();\n\n for (const annotation of annotations) {\n if (Trace.Types.File.isEntryLabelAnnotation(annotation)) {\n annotationEntryToColorMap.set(annotation.entry, this.getEntryColorByEntry(annotation.entry));\n } else if (Trace.Types.File.isEntriesLinkAnnotation(annotation)) {\n annotationEntryToColorMap.set(annotation.entryFrom, this.getEntryColorByEntry(annotation.entryFrom));\n if (annotation.entryTo) {\n annotationEntryToColorMap.set(annotation.entryTo, this.getEntryColorByEntry(annotation.entryTo));\n }\n }\n }\n\n return annotationEntryToColorMap;\n }\n\n private getEntryColorByEntry(entry: Trace.Types.Events.Event): string {\n const mainIndex = this.flameChart.getMainDataProvider().indexForEvent(entry);\n const networkIndex = this.flameChart.getNetworkDataProvider().indexForEvent(entry);\n if (mainIndex) {\n const color = this.flameChart.getMainDataProvider().entryColor(mainIndex);\n return color;\n }\n if (networkIndex) {\n const color = this.flameChart.getNetworkDataProvider().entryColor(networkIndex);\n return color;\n }\n\n console.warn('Could not get entry color for ', entry);\n return ThemeSupport.ThemeSupport.instance().getComputedValue('--app-color-system');\n }\n\n private recordingStarted(config?: {navigateToUrl: Platform.DevToolsPath.UrlString}): void {\n if (config && this.recordingPageReload && this.controller) {\n // If the user hit \"Reload & record\", by this point we have:\n // 1. Navigated to about:blank\n // 2. Initiated tracing.\n // We therefore now should navigate back to the original URL that the user wants to profile.\n const resourceModel = this.controller?.primaryPageTarget.model(SDK.ResourceTreeModel.ResourceTreeModel);\n if (!resourceModel) {\n void this.recordingFailed('Could not navigate to original URL');\n return;\n }\n // We don't need to await this because we are purposefully showing UI\n // progress as the page loads & tracing is underway.\n void resourceModel.navigate(config.navigateToUrl);\n }\n\n this.#changeView({mode: 'STATUS_PANE_OVERLAY'});\n this.setState(State.RECORDING);\n this.showRecordingStarted();\n if (this.statusPane) {\n this.statusPane.enableAndFocusButton();\n this.statusPane.updateStatus(i18nString(UIStrings.profiling));\n this.statusPane.updateProgressBar(i18nString(UIStrings.bufferUsage), 0);\n this.statusPane.startTimer();\n }\n }\n\n recordingProgress(usage: number): void {\n if (this.statusPane) {\n this.statusPane.updateProgressBar(i18nString(UIStrings.bufferUsage), usage * 100);\n }\n }\n\n /**\n * Hide the sidebar, but persist the user's state, because when they import a\n * trace we want to revert the sidebar back to what it was.\n */\n #hideSidebar(): void {\n if (this.#splitWidget.sidebarIsShowing()) {\n this.#restoreSidebarVisibilityOnTraceLoad = true;\n this.#splitWidget.hideSidebar();\n }\n }\n\n #showLandingPage(): void {\n this.updateSettingsPaneVisibility();\n this.#removeSidebarIconFromToolbar();\n this.#hideSidebar();\n\n if (this.landingPage) {\n this.landingPage.show(this.statusPaneContainer);\n return;\n }\n\n this.landingPage = new TimelineLandingPage(this.toggleRecordAction, {isNode});\n this.landingPage.show(this.statusPaneContainer);\n }\n\n #hideLandingPage(): void {\n this.landingPage.detach();\n\n // Hide pane settings in trace view to conserve UI space, but preserve underlying setting.\n this.showSettingsPaneButton?.setToggled(false);\n this.settingsPane?.hideWidget();\n }\n\n async loadingStarted(): Promise {\n this.#changeView({mode: 'STATUS_PANE_OVERLAY'});\n\n if (this.statusPane) {\n this.statusPane.remove();\n }\n this.statusPane = new StatusPane(\n {\n showProgress: true,\n showTimer: undefined,\n buttonDisabled: undefined,\n buttonText: undefined,\n description: undefined,\n },\n () => this.cancelLoading());\n this.statusPane.showPane(this.statusPaneContainer);\n this.statusPane.updateStatus(i18nString(UIStrings.loadingProfile));\n // FIXME: make loading from backend cancelable as well.\n if (!this.loader) {\n this.statusPane.finish();\n }\n this.traceLoadStart = Trace.Types.Timing.MilliSeconds(performance.now());\n await this.loadingProgress(0);\n }\n\n async loadingProgress(progress?: number): Promise {\n if (typeof progress === 'number' && this.statusPane) {\n this.statusPane.updateProgressBar(i18nString(UIStrings.received), progress * 100);\n }\n }\n\n async processingStarted(): Promise {\n this.statusPane?.updateStatus(i18nString(UIStrings.processingProfile));\n }\n\n #listenForProcessingProgress(): void {\n this.#traceEngineModel.addEventListener(Trace.TraceModel.ModelUpdateEvent.eventName, e => {\n const updateEvent = e as Trace.TraceModel.ModelUpdateEvent;\n const str = i18nString(UIStrings.processed);\n\n // Trace Engine will report progress from [0...1] but we still have more work to do. So, scale them down a bit.\n const traceParseMaxProgress = 0.7;\n\n if (updateEvent.data.type === Trace.TraceModel.ModelUpdateType.COMPLETE) {\n this.statusPane?.updateProgressBar(str, 100 * traceParseMaxProgress);\n } else if (updateEvent.data.type === Trace.TraceModel.ModelUpdateType.PROGRESS_UPDATE) {\n const data = updateEvent.data.data;\n this.statusPane?.updateProgressBar(str, data.percent * 100 * traceParseMaxProgress);\n }\n });\n }\n\n #onSourceMapsNodeNamesResolved(): void {\n this.flameChart.refreshMainFlameChart();\n }\n\n /**\n * This is called with we are done loading a trace from a file, or after we\n * have recorded a fresh trace.\n *\n * IMPORTANT: All the code in here should be code that is only required when we have\n * recorded or loaded a brand new trace. If you need the code to run when the\n * user switches to an existing trace, please {@see setModel} and put your\n * code in there.\n **/\n async loadingComplete(\n collectedEvents: Trace.Types.Events.Event[],\n exclusiveFilter: TimelineModel.TimelineModelFilter.TimelineModelFilter|null = null, isCpuProfile: boolean,\n recordingStartTime: number|null, metadata: Trace.Types.File.MetaData|null): Promise {\n this.#traceEngineModel.resetProcessor();\n\n delete this.loader;\n\n // If the user just recorded this trace via the record UI, the state will\n // be StopPending. Whereas if it was an existing trace they loaded via a\n // file, it will be State.Loading. This means we can tell the recording is\n // fresh by checking the state value.\n const recordingIsFresh = this.state === State.STOP_PENDING;\n\n this.setState(State.IDLE);\n\n if (collectedEvents.length === 0) {\n // 0 collected events indicates probably an invalid file was imported.\n // If the user does not have any already-loaded traces, then we should\n // just reset the panel back to the landing page. However if they had a\n // previous trace imported, we should go to that instead.\n if (this.#traceEngineModel.size()) {\n this.#changeView({\n mode: 'VIEWING_TRACE',\n traceIndex: this.#traceEngineModel.lastTraceIndex(),\n });\n } else {\n this.#changeView({mode: 'LANDING_PAGE'});\n }\n return;\n }\n\n metadata = metadata ? metadata :\n await Trace.Extras.Metadata.forNewRecording(isCpuProfile, recordingStartTime ?? undefined);\n\n try {\n await this.#executeNewTrace(collectedEvents, recordingIsFresh, metadata);\n const traceIndex = this.#traceEngineModel.lastTraceIndex();\n if (exclusiveFilter) {\n this.#exclusiveFilterPerTrace.set(traceIndex, exclusiveFilter);\n }\n this.#changeView({\n mode: 'VIEWING_TRACE',\n traceIndex,\n });\n\n const parsedTrace = this.#traceEngineModel.parsedTrace(traceIndex);\n if (!parsedTrace) {\n throw new Error(`Could not get trace data at index ${traceIndex}`);\n }\n\n if (recordingIsFresh) {\n Tracker.instance().registerFreshRecording(parsedTrace);\n }\n\n // We store the index of the active trace so we can load it back easily\n // if the user goes to a different trace then comes back.\n // However we also pass in the full trace data because we use it to build\n // the preview overview thumbnail of the trace that gets shown in the UI.\n this.#historyManager.addRecording({\n data: {\n parsedTraceIndex: traceIndex,\n type: 'TRACE_INDEX',\n },\n filmStripForPreview: Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace),\n parsedTrace,\n startTime: recordingStartTime ?? null,\n });\n } catch (error) {\n // If we errored during the parsing stage, it\n // is useful to get access to the raw events to download the trace. This\n // allows us to debug crashes!\n void this.recordingFailed(error.message, collectedEvents);\n console.error(error);\n } finally {\n this.recordTraceLoadMetric();\n }\n }\n\n recordTraceLoadMetric(): void {\n if (!this.traceLoadStart) {\n return;\n }\n const start = this.traceLoadStart;\n // Right *now* is the end of trace parsing and model building, but the flamechart rendering\n // isn't complete yet. To capture that we'll do a rAF+setTimeout to give the most accurate timestamp\n // for the first paint of the flamechart\n requestAnimationFrame(() => {\n setTimeout(() => {\n const end = Trace.Types.Timing.MilliSeconds(performance.now());\n const measure = performance.measure('TraceLoad', {start, end});\n const duration = Trace.Types.Timing.MilliSeconds(measure.duration);\n this.element.dispatchEvent(new TraceLoadEvent(duration));\n Host.userMetrics.performanceTraceLoad(measure);\n }, 0);\n });\n }\n\n async #executeNewTrace(\n collectedEvents: Trace.Types.Events.Event[], isFreshRecording: boolean,\n metadata: Trace.Types.File.MetaData): Promise {\n return this.#traceEngineModel.parse(\n collectedEvents,\n {\n metadata,\n isFreshRecording,\n },\n );\n }\n\n loadingCompleteForTest(): void {\n // Not implemented, added only for allowing the TimelineTestRunner\n // to be in sync when a trace load is finished.\n }\n\n private showRecordingStarted(): void {\n this.#changeView({mode: 'STATUS_PANE_OVERLAY'});\n if (this.statusPane) {\n this.statusPane.remove();\n }\n this.statusPane = new StatusPane(\n {\n showTimer: true,\n showProgress: true,\n buttonDisabled: true,\n description: undefined,\n buttonText: undefined,\n },\n () => this.stopRecording());\n this.statusPane.showPane(this.statusPaneContainer);\n this.statusPane.updateStatus(i18nString(UIStrings.initializingProfiler));\n }\n\n private cancelLoading(): void {\n if (this.loader) {\n void this.loader.cancel();\n }\n }\n\n private async loadEventFired(\n event: Common.EventTarget\n .EventTargetEvent<{resourceTreeModel: SDK.ResourceTreeModel.ResourceTreeModel, loadTime: number}>):\n Promise {\n if (this.state !== State.RECORDING || !this.recordingPageReload || !this.controller ||\n this.controller.primaryPageTarget !== event.data.resourceTreeModel.target()) {\n return;\n }\n const controller = this.controller;\n await new Promise(r => window.setTimeout(r, this.millisecondsToRecordAfterLoadEvent));\n\n // Check if we're still in the same recording session.\n if (controller !== this.controller || this.state !== State.RECORDING) {\n return;\n }\n void this.stopRecording();\n }\n\n private frameForSelection(selection: TimelineSelection): Trace.Handlers.ModelHandlers.Frames.TimelineFrame|null {\n if (this.#viewMode.mode !== 'VIEWING_TRACE') {\n return null;\n }\n if (TimelineSelection.isLegacyTimelineFrame(selection.object) &&\n selection.object instanceof Trace.Handlers.ModelHandlers.Frames.TimelineFrame) {\n return selection.object;\n }\n if (TimelineSelection.isRangeSelection(selection.object) ||\n TimelineSelection.isSyntheticNetworkRequestDetailsEventSelection(selection.object)) {\n return null;\n }\n if (TimelineSelection.isSelection(selection.object)) {\n const parsedTrace = this.#traceEngineModel.parsedTrace(this.#viewMode.traceIndex);\n if (!parsedTrace) {\n return null;\n }\n // If the user has selected a time range, the frame we want is the last\n // frame in that time window, hence why the window we look for is the\n // endTime to the endTime.\n const endTimeMicro = Trace.Helpers.Timing.millisecondsToMicroseconds(selection.endTime);\n const lastFrameInSelection = Trace.Handlers.ModelHandlers.Frames\n .framesWithinWindow(\n parsedTrace.Frames.frames,\n endTimeMicro,\n endTimeMicro,\n )\n .at(0);\n return lastFrameInSelection || null;\n }\n console.assert(false, 'Should never be reached');\n return null;\n }\n\n jumpToFrame(offset: number): true|undefined {\n if (this.#viewMode.mode !== 'VIEWING_TRACE') {\n return;\n }\n const currentFrame = this.selection && this.frameForSelection(this.selection);\n if (!currentFrame) {\n return;\n }\n const parsedTrace = this.#traceEngineModel.parsedTrace(this.#viewMode.traceIndex);\n if (!parsedTrace) {\n return;\n }\n let index = parsedTrace.Frames.frames.indexOf(currentFrame);\n console.assert(index >= 0, 'Can\\'t find current frame in the frame list');\n index = Platform.NumberUtilities.clamp(index + offset, 0, parsedTrace.Frames.frames.length - 1);\n const frame = parsedTrace.Frames.frames[index];\n this.#revealTimeRange(\n Trace.Helpers.Timing.microSecondsToMilliseconds(frame.startTime),\n Trace.Helpers.Timing.microSecondsToMilliseconds(frame.endTime));\n this.select(TimelineSelection.fromFrame(frame));\n return true;\n }\n\n select(selection: TimelineSelection|null): void {\n this.selection = selection;\n this.flameChart.setSelectionAndReveal(selection);\n }\n\n selectEntryAtTime(events: Trace.Types.Events.Event[]|null, time: number): void {\n if (!events) {\n return;\n }\n\n if (events.length === 0) {\n this.select(null);\n return;\n }\n\n // Find best match, then backtrack to the first visible entry.\n for (let index = Platform.ArrayUtilities.upperBound(events, time, (time, event) => time - event.ts) - 1; index >= 0;\n --index) {\n const event = events[index];\n const {endTime} = Trace.Helpers.Timing.eventTimingsMilliSeconds(event);\n if (Trace.Helpers.Trace.isTopLevelEvent(event) && endTime < time) {\n break;\n }\n if (ActiveFilters.instance().isVisible(event) && endTime >= time) {\n this.select(TimelineSelection.fromTraceEvent(event));\n return;\n }\n }\n this.select(null);\n }\n\n highlightEvent(event: Trace.Types.Events.Event|null): void {\n this.flameChart.highlightEvent(event);\n }\n\n #revealTimeRange(startTime: Trace.Types.Timing.MilliSeconds, endTime: Trace.Types.Timing.MilliSeconds): void {\n const traceBoundsState = TraceBounds.TraceBounds.BoundsManager.instance().state();\n if (!traceBoundsState) {\n return;\n }\n const traceWindow = traceBoundsState.milli.timelineTraceWindow;\n\n let offset = 0;\n if (traceWindow.max < endTime) {\n offset = endTime - traceWindow.max;\n } else if (traceWindow.min > startTime) {\n offset = startTime - traceWindow.min;\n }\n TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(\n Trace.Helpers.Timing.traceWindowFromMilliSeconds(\n Trace.Types.Timing.MilliSeconds(traceWindow.min + offset),\n Trace.Types.Timing.MilliSeconds(traceWindow.max + offset),\n ),\n {\n shouldAnimate: true,\n },\n );\n }\n\n private handleDrop(dataTransfer: DataTransfer): void {\n const items = dataTransfer.items;\n if (!items.length) {\n return;\n }\n const item = items[0];\n Host.userMetrics.actionTaken(Host.UserMetrics.Action.PerfPanelTraceImported);\n if (item.kind === 'string') {\n const url = dataTransfer.getData('text/uri-list') as Platform.DevToolsPath.UrlString;\n if (new Common.ParsedURL.ParsedURL(url).isValid) {\n void this.loadFromURL(url);\n }\n } else if (item.kind === 'file') {\n const file = items[0].getAsFile();\n if (!file) {\n return;\n }\n void this.loadFromFile(file);\n }\n }\n}\n\nexport const enum State {\n IDLE = 'Idle',\n START_PENDING = 'StartPending',\n RECORDING = 'Recording',\n STOP_PENDING = 'StopPending',\n LOADING = 'Loading',\n RECORDING_FAILED = 'RecordingFailed',\n}\n\n// Define row and header height, should be in sync with styles for timeline graphs.\nexport const rowHeight = 18;\n\nexport const headerHeight = 20;\nexport interface TimelineModeViewDelegate {\n select(selection: TimelineSelection|null): void;\n element: Element;\n selectEntryAtTime(events: Trace.Types.Events.Event[]|null, time: number): void;\n highlightEvent(event: Trace.Types.Events.Event|null): void;\n}\n\nexport class StatusPane extends UI.Widget.VBox {\n private status: HTMLElement;\n private time: Element|undefined;\n private progressLabel!: Element;\n private progressBar!: Element;\n private readonly description: HTMLElement|undefined;\n private button: Buttons.Button.Button;\n private downloadTraceButton: Buttons.Button.Button;\n private startTime!: number;\n private timeUpdateTimer?: number;\n #rawEvents?: Trace.Types.Events.Event[];\n\n constructor(\n options: {\n showTimer?: boolean,\n showProgress?: boolean,\n description?: string,\n buttonText?: string,\n buttonDisabled?: boolean,\n },\n buttonCallback: () => (Promise| void)) {\n super(true);\n\n this.contentElement.classList.add('timeline-status-dialog');\n this.contentElement.setAttribute('jslog', `${VisualLogging.dialog('timeline-status').track({resize: true})}`);\n\n const statusLine = this.contentElement.createChild('div', 'status-dialog-line status');\n statusLine.createChild('div', 'label').textContent = i18nString(UIStrings.status);\n this.status = statusLine.createChild('div', 'content');\n UI.ARIAUtils.markAsStatus(this.status);\n\n if (options.showTimer) {\n const timeLine = this.contentElement.createChild('div', 'status-dialog-line time');\n timeLine.createChild('div', 'label').textContent = i18nString(UIStrings.time);\n this.time = timeLine.createChild('div', 'content');\n }\n\n if (options.showProgress) {\n const progressLine = this.contentElement.createChild('div', 'status-dialog-line progress');\n this.progressLabel = progressLine.createChild('div', 'label');\n this.progressBar = progressLine.createChild('div', 'indicator-container').createChild('div', 'indicator');\n UI.ARIAUtils.markAsProgressBar(this.progressBar);\n }\n\n if (typeof options.description === 'string') {\n const descriptionLine = this.contentElement.createChild('div', 'status-dialog-line description');\n descriptionLine.createChild('div', 'label').textContent = i18nString(UIStrings.description);\n this.description = descriptionLine.createChild('div', 'content');\n this.description.innerText = options.description;\n }\n\n const buttonContainer = this.contentElement.createChild('div', 'stop-button');\n this.downloadTraceButton = UI.UIUtils.createTextButton(i18nString(UIStrings.downloadAfterError), () => {\n void this.#downloadRawTraceAfterError();\n }, {jslogContext: 'timeline.download-after-error'});\n\n this.downloadTraceButton.disabled = true;\n this.downloadTraceButton.style.visibility = 'hidden';\n\n const buttonText = options.buttonText || i18nString(UIStrings.stop);\n this.button = UI.UIUtils.createTextButton(buttonText, buttonCallback, {\n jslogContext: 'timeline.stop-recording',\n });\n // Profiling can't be stopped during initialization.\n this.button.disabled = !options.buttonDisabled === false;\n\n buttonContainer.append(this.downloadTraceButton);\n buttonContainer.append(this.button);\n }\n\n finish(): void {\n this.stopTimer();\n this.button.disabled = true;\n }\n\n async #downloadRawTraceAfterError(): Promise {\n if (!this.#rawEvents || this.#rawEvents.length === 0) {\n return;\n }\n const traceStart = Platform.DateUtilities.toISO8601Compact(new Date());\n const fileName = `Trace-Load-Error-${traceStart}.json` as Platform.DevToolsPath.RawPathString;\n const formattedTraceIter = traceJsonGenerator(this.#rawEvents, {});\n const traceAsString = Array.from(formattedTraceIter).join('');\n await Workspace.FileManager.FileManager.instance().save(\n fileName, traceAsString, true /* forceSaveAs */, false /* isBase64 */);\n Workspace.FileManager.FileManager.instance().close(fileName);\n }\n\n enableDownloadOfEvents(rawEvents: Trace.Types.Events.Event[]): void {\n this.#rawEvents = rawEvents;\n this.downloadTraceButton.disabled = false;\n this.downloadTraceButton.style.visibility = 'visible';\n }\n\n remove(): void {\n if (this.element.parentNode) {\n (this.element.parentNode as HTMLElement).classList.remove('tinted');\n this.arrangeDialog((this.element.parentNode as HTMLElement));\n }\n this.stopTimer();\n this.element.remove();\n }\n\n showPane(parent: Element): void {\n this.arrangeDialog(parent);\n this.show(parent);\n parent.classList.add('tinted');\n }\n\n enableAndFocusButton(): void {\n this.button.disabled = false;\n this.button.focus();\n }\n\n updateStatus(text: string): void {\n this.status.textContent = text;\n }\n\n updateProgressBar(activity: string, percent: number): void {\n this.progressLabel.textContent = activity;\n (this.progressBar as HTMLElement).style.width = percent.toFixed(1) + '%';\n UI.ARIAUtils.setValueNow(this.progressBar, percent);\n this.updateTimer();\n }\n\n startTimer(): void {\n this.startTime = Date.now();\n this.timeUpdateTimer = window.setInterval(this.updateTimer.bind(this), 1000);\n this.updateTimer();\n }\n\n private stopTimer(): void {\n if (!this.timeUpdateTimer) {\n return;\n }\n clearInterval(this.timeUpdateTimer);\n this.updateTimer();\n delete this.timeUpdateTimer;\n }\n\n private updateTimer(): void {\n this.arrangeDialog((this.element.parentNode as HTMLElement));\n if (!this.timeUpdateTimer || !this.time) {\n return;\n }\n const elapsed = (Date.now() - this.startTime) / 1000;\n this.time.textContent = i18nString(UIStrings.ssec, {PH1: Math.round(elapsed)});\n }\n\n private arrangeDialog(parent: Element): void {\n const isSmallDialog = parent.clientWidth < 325;\n this.element.classList.toggle('small-dialog', isSmallDialog);\n this.contentElement.classList.toggle('small-dialog', isSmallDialog);\n }\n override wasShown(): void {\n super.wasShown();\n this.registerCSSFiles([timelineStatusDialogStyles]);\n }\n}\n\nlet loadTimelineHandlerInstance: LoadTimelineHandler;\n\nexport class LoadTimelineHandler implements Common.QueryParamHandler.QueryParamHandler {\n static instance(opts: {\n forceNew: boolean|null,\n } = {forceNew: null}): LoadTimelineHandler {\n const {forceNew} = opts;\n if (!loadTimelineHandlerInstance || forceNew) {\n loadTimelineHandlerInstance = new LoadTimelineHandler();\n }\n\n return loadTimelineHandlerInstance;\n }\n\n handleQueryParam(value: string): void {\n void UI.ViewManager.ViewManager.instance().showView('timeline').then(async () => {\n await TimelinePanel.instance().loadFromURL(window.decodeURIComponent(value) as Platform.DevToolsPath.UrlString);\n });\n }\n}\n\nexport class TraceRevealer implements Common.Revealer.Revealer {\n async reveal(trace: SDK.TraceObject.TraceObject): Promise {\n await UI.ViewManager.ViewManager.instance().showView('timeline');\n TimelinePanel.instance().loadFromEvents(trace.traceEvents);\n }\n}\n\nexport class ActionDelegate implements UI.ActionRegistration.ActionDelegate {\n handleAction(context: UI.Context.Context, actionId: string): boolean {\n const panel = context.flavor(TimelinePanel);\n if (panel === null) {\n return false;\n }\n switch (actionId) {\n case 'timeline.toggle-recording':\n void panel.toggleRecording();\n return true;\n case 'timeline.record-reload':\n panel.recordReload();\n return true;\n case 'timeline.save-to-file':\n void panel.saveToFile();\n return true;\n case 'timeline.load-from-file':\n panel.selectFileToLoad();\n return true;\n case 'timeline.jump-to-previous-frame':\n panel.jumpToFrame(-1);\n return true;\n case 'timeline.jump-to-next-frame':\n panel.jumpToFrame(1);\n return true;\n case 'timeline.show-history':\n void panel.showHistoryDropdown();\n return true;\n case 'timeline.previous-recording':\n panel.navigateHistory(1);\n return true;\n case 'timeline.next-recording':\n panel.navigateHistory(-1);\n return true;\n }\n return false;\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineSelection.d.ts b/public/panels/timeline/TimelineSelection.d.ts index e6770a4aa..60c37ecf8 100644 --- a/public/panels/timeline/TimelineSelection.d.ts +++ b/public/panels/timeline/TimelineSelection.d.ts @@ -1,18 +1,18 @@ -import * as TraceEngine from '../../models/trace/trace.js'; -type PermittedObjectTypes = TraceEngine.Types.TraceEvents.LegacyTimelineFrame | TraceEngine.Types.TraceEvents.TraceEventData | SelectionRange; +import * as Trace from '../../models/trace/trace.js'; +type PermittedObjectTypes = Trace.Types.Events.LegacyTimelineFrame | Trace.Types.Events.Event | SelectionRange; declare const SelectionRangeSymbol: unique symbol; export type SelectionRange = typeof SelectionRangeSymbol; export declare class TimelineSelection { - readonly startTime: TraceEngine.Types.Timing.MilliSeconds; - readonly endTime: TraceEngine.Types.Timing.MilliSeconds; + readonly startTime: Trace.Types.Timing.MilliSeconds; + readonly endTime: Trace.Types.Timing.MilliSeconds; readonly object: PermittedObjectTypes; - constructor(startTime: TraceEngine.Types.Timing.MilliSeconds, endTime: TraceEngine.Types.Timing.MilliSeconds, object: PermittedObjectTypes); - static isLegacyTimelineFrame(object: PermittedObjectTypes): object is TraceEngine.Types.TraceEvents.LegacyTimelineFrame; - static fromFrame(frame: TraceEngine.Types.TraceEvents.LegacyTimelineFrame): TimelineSelection; - static isSyntheticNetworkRequestDetailsEventSelection(object: PermittedObjectTypes): object is TraceEngine.Types.TraceEvents.SyntheticNetworkRequest; - static isNetworkEventSelection(object: PermittedObjectTypes): object is TraceEngine.Types.TraceEvents.SyntheticNetworkRequest | TraceEngine.Types.TraceEvents.WebSocketEvent; - static isTraceEventSelection(object: PermittedObjectTypes): object is TraceEngine.Types.TraceEvents.TraceEventData; - static fromTraceEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): TimelineSelection; + constructor(startTime: Trace.Types.Timing.MilliSeconds, endTime: Trace.Types.Timing.MilliSeconds, object: PermittedObjectTypes); + static isLegacyTimelineFrame(object: PermittedObjectTypes): object is Trace.Types.Events.LegacyTimelineFrame; + static fromFrame(frame: Trace.Types.Events.LegacyTimelineFrame): TimelineSelection; + static isSyntheticNetworkRequestDetailsEventSelection(object: PermittedObjectTypes): object is Trace.Types.Events.SyntheticNetworkRequest; + static isNetworkEventSelection(object: PermittedObjectTypes): object is Trace.Types.Events.SyntheticNetworkRequest | Trace.Types.Events.WebSocketEvent; + static isSelection(object: PermittedObjectTypes): object is Trace.Types.Events.Event; + static fromTraceEvent(event: Trace.Types.Events.Event): TimelineSelection; static isRangeSelection(object: PermittedObjectTypes): object is SelectionRange; static fromRange(startTime: number, endTime: number): TimelineSelection; } diff --git a/public/panels/timeline/TimelineSelection.js b/public/panels/timeline/TimelineSelection.js index 995a42c6b..7fbd5634d 100644 --- a/public/panels/timeline/TimelineSelection.js +++ b/public/panels/timeline/TimelineSelection.js @@ -1,7 +1,7 @@ // 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 * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; const SelectionRangeSymbol = Symbol('SelectionRange'); export class TimelineSelection { startTime; @@ -13,10 +13,10 @@ export class TimelineSelection { this.object = object; } static isLegacyTimelineFrame(object) { - return typeof object !== 'symbol' && TraceEngine.Types.TraceEvents.isLegacyTimelineFrame(object); + return typeof object !== 'symbol' && Trace.Types.Events.isLegacyTimelineFrame(object); } static fromFrame(frame) { - return new TimelineSelection(TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.startTime), TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.endTime), frame); + return new TimelineSelection(Trace.Helpers.Timing.microSecondsToMilliseconds(frame.startTime), Trace.Helpers.Timing.microSecondsToMilliseconds(frame.endTime), frame); } static isSyntheticNetworkRequestDetailsEventSelection(object) { if (TimelineSelection.isLegacyTimelineFrame(object) || TimelineSelection.isRangeSelection(object)) { @@ -24,7 +24,7 @@ export class TimelineSelection { } // At this point we know the selection is a raw trace event, so we just // need to check it's the right type of raw event. - return TraceEngine.Types.TraceEvents.isSyntheticNetworkRequestEvent(object); + return Trace.Types.Events.isSyntheticNetworkRequest(object); } static isNetworkEventSelection(object) { if (TimelineSelection.isLegacyTimelineFrame(object) || TimelineSelection.isRangeSelection(object)) { @@ -32,29 +32,29 @@ export class TimelineSelection { } // At this point we know the selection is a raw trace event, so we just // need to check it's the right type of raw event. - return TraceEngine.Types.TraceEvents.isNetworkTrackEntry(object); + return Trace.Types.Events.isNetworkTrackEntry(object); } - static isTraceEventSelection(object) { + static isSelection(object) { // Trace events are just raw objects, so now we have to confirm it is a trace event by ruling everything else out. if (TimelineSelection.isLegacyTimelineFrame(object) || TimelineSelection.isRangeSelection(object)) { return false; } // Although Network Requests are trace events, in TimelineSelection we // treat Network requests distinctly - if (TraceEngine.Types.TraceEvents.isSyntheticNetworkRequestEvent(object)) { + if (Trace.Types.Events.isSyntheticNetworkRequest(object)) { return false; } return true; } static fromTraceEvent(event) { - const { startTime, endTime } = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event); - return new TimelineSelection(startTime, TraceEngine.Types.Timing.MilliSeconds(endTime || (startTime + 1)), event); + const { startTime, endTime } = Trace.Helpers.Timing.eventTimingsMilliSeconds(event); + return new TimelineSelection(startTime, Trace.Types.Timing.MilliSeconds(endTime || (startTime + 1)), event); } static isRangeSelection(object) { return object === SelectionRangeSymbol; } static fromRange(startTime, endTime) { - return new TimelineSelection(TraceEngine.Types.Timing.MilliSeconds(startTime), TraceEngine.Types.Timing.MilliSeconds(endTime), SelectionRangeSymbol); + return new TimelineSelection(Trace.Types.Timing.MilliSeconds(startTime), Trace.Types.Timing.MilliSeconds(endTime), SelectionRangeSymbol); } } //# sourceMappingURL=TimelineSelection.js.map \ No newline at end of file diff --git a/public/panels/timeline/TimelineSelection.js.map b/public/panels/timeline/TimelineSelection.js.map index a41f9557d..907aea90b 100644 --- a/public/panels/timeline/TimelineSelection.js.map +++ b/public/panels/timeline/TimelineSelection.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineSelection.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineSelection.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceEngine from '../../models/trace/trace.js';\n\ntype PermittedObjectTypes =\n TraceEngine.Types.TraceEvents.LegacyTimelineFrame|TraceEngine.Types.TraceEvents.TraceEventData|SelectionRange;\n\nconst SelectionRangeSymbol = Symbol('SelectionRange');\nexport type SelectionRange = typeof SelectionRangeSymbol;\n\nexport class TimelineSelection {\n readonly startTime: TraceEngine.Types.Timing.MilliSeconds;\n readonly endTime: TraceEngine.Types.Timing.MilliSeconds;\n readonly object: PermittedObjectTypes;\n\n constructor(\n startTime: TraceEngine.Types.Timing.MilliSeconds, endTime: TraceEngine.Types.Timing.MilliSeconds,\n object: PermittedObjectTypes) {\n this.startTime = startTime;\n this.endTime = endTime;\n this.object = object;\n }\n\n static isLegacyTimelineFrame(object: PermittedObjectTypes):\n object is TraceEngine.Types.TraceEvents.LegacyTimelineFrame {\n return typeof object !== 'symbol' && TraceEngine.Types.TraceEvents.isLegacyTimelineFrame(object);\n }\n\n static fromFrame(frame: TraceEngine.Types.TraceEvents.LegacyTimelineFrame): TimelineSelection {\n return new TimelineSelection(\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.startTime),\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.endTime), frame);\n }\n\n static isSyntheticNetworkRequestDetailsEventSelection(object: PermittedObjectTypes):\n object is TraceEngine.Types.TraceEvents.SyntheticNetworkRequest {\n if (TimelineSelection.isLegacyTimelineFrame(object) || TimelineSelection.isRangeSelection(object)) {\n return false;\n }\n // At this point we know the selection is a raw trace event, so we just\n // need to check it's the right type of raw event.\n return TraceEngine.Types.TraceEvents.isSyntheticNetworkRequestEvent(object);\n }\n\n static isNetworkEventSelection(object: PermittedObjectTypes):\n object is TraceEngine.Types.TraceEvents.SyntheticNetworkRequest|TraceEngine.Types.TraceEvents.WebSocketEvent {\n if (TimelineSelection.isLegacyTimelineFrame(object) || TimelineSelection.isRangeSelection(object)) {\n return false;\n }\n // At this point we know the selection is a raw trace event, so we just\n // need to check it's the right type of raw event.\n return TraceEngine.Types.TraceEvents.isNetworkTrackEntry(object);\n }\n\n static isTraceEventSelection(object: PermittedObjectTypes): object is TraceEngine.Types.TraceEvents.TraceEventData {\n // Trace events are just raw objects, so now we have to confirm it is a trace event by ruling everything else out.\n if (TimelineSelection.isLegacyTimelineFrame(object) || TimelineSelection.isRangeSelection(object)) {\n return false;\n }\n\n // Although Network Requests are trace events, in TimelineSelection we\n // treat Network requests distinctly\n if (TraceEngine.Types.TraceEvents.isSyntheticNetworkRequestEvent(object)) {\n return false;\n }\n return true;\n }\n\n static fromTraceEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): TimelineSelection {\n const {startTime, endTime} = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event);\n return new TimelineSelection(startTime, TraceEngine.Types.Timing.MilliSeconds(endTime || (startTime + 1)), event);\n }\n\n static isRangeSelection(object: PermittedObjectTypes): object is SelectionRange {\n return object === SelectionRangeSymbol;\n }\n\n static fromRange(startTime: number, endTime: number): TimelineSelection {\n return new TimelineSelection(\n TraceEngine.Types.Timing.MilliSeconds(startTime), TraceEngine.Types.Timing.MilliSeconds(endTime),\n SelectionRangeSymbol);\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"TimelineSelection.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineSelection.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../models/trace/trace.js';\n\ntype PermittedObjectTypes = Trace.Types.Events.LegacyTimelineFrame|Trace.Types.Events.Event|SelectionRange;\n\nconst SelectionRangeSymbol = Symbol('SelectionRange');\nexport type SelectionRange = typeof SelectionRangeSymbol;\n\nexport class TimelineSelection {\n readonly startTime: Trace.Types.Timing.MilliSeconds;\n readonly endTime: Trace.Types.Timing.MilliSeconds;\n readonly object: PermittedObjectTypes;\n\n constructor(\n startTime: Trace.Types.Timing.MilliSeconds, endTime: Trace.Types.Timing.MilliSeconds,\n object: PermittedObjectTypes) {\n this.startTime = startTime;\n this.endTime = endTime;\n this.object = object;\n }\n\n static isLegacyTimelineFrame(object: PermittedObjectTypes): object is Trace.Types.Events.LegacyTimelineFrame {\n return typeof object !== 'symbol' && Trace.Types.Events.isLegacyTimelineFrame(object);\n }\n\n static fromFrame(frame: Trace.Types.Events.LegacyTimelineFrame): TimelineSelection {\n return new TimelineSelection(\n Trace.Helpers.Timing.microSecondsToMilliseconds(frame.startTime),\n Trace.Helpers.Timing.microSecondsToMilliseconds(frame.endTime), frame);\n }\n\n static isSyntheticNetworkRequestDetailsEventSelection(object: PermittedObjectTypes):\n object is Trace.Types.Events.SyntheticNetworkRequest {\n if (TimelineSelection.isLegacyTimelineFrame(object) || TimelineSelection.isRangeSelection(object)) {\n return false;\n }\n // At this point we know the selection is a raw trace event, so we just\n // need to check it's the right type of raw event.\n return Trace.Types.Events.isSyntheticNetworkRequest(object);\n }\n\n static isNetworkEventSelection(object: PermittedObjectTypes):\n object is Trace.Types.Events.SyntheticNetworkRequest|Trace.Types.Events.WebSocketEvent {\n if (TimelineSelection.isLegacyTimelineFrame(object) || TimelineSelection.isRangeSelection(object)) {\n return false;\n }\n // At this point we know the selection is a raw trace event, so we just\n // need to check it's the right type of raw event.\n return Trace.Types.Events.isNetworkTrackEntry(object);\n }\n\n static isSelection(object: PermittedObjectTypes): object is Trace.Types.Events.Event {\n // Trace events are just raw objects, so now we have to confirm it is a trace event by ruling everything else out.\n if (TimelineSelection.isLegacyTimelineFrame(object) || TimelineSelection.isRangeSelection(object)) {\n return false;\n }\n\n // Although Network Requests are trace events, in TimelineSelection we\n // treat Network requests distinctly\n if (Trace.Types.Events.isSyntheticNetworkRequest(object)) {\n return false;\n }\n return true;\n }\n\n static fromTraceEvent(event: Trace.Types.Events.Event): TimelineSelection {\n const {startTime, endTime} = Trace.Helpers.Timing.eventTimingsMilliSeconds(event);\n return new TimelineSelection(startTime, Trace.Types.Timing.MilliSeconds(endTime || (startTime + 1)), event);\n }\n\n static isRangeSelection(object: PermittedObjectTypes): object is SelectionRange {\n return object === SelectionRangeSymbol;\n }\n\n static fromRange(startTime: number, endTime: number): TimelineSelection {\n return new TimelineSelection(\n Trace.Types.Timing.MilliSeconds(startTime), Trace.Types.Timing.MilliSeconds(endTime), SelectionRangeSymbol);\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineSelection.test.js b/public/panels/timeline/TimelineSelection.test.js index 019d5e5b3..34f3b2b03 100644 --- a/public/panels/timeline/TimelineSelection.test.js +++ b/public/panels/timeline/TimelineSelection.test.js @@ -1,33 +1,33 @@ // 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 * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import { describeWithEnvironment } from '../../testing/EnvironmentHelpers.js'; import { TraceLoader } from '../../testing/TraceLoader.js'; import * as Timeline from './timeline.js'; describeWithEnvironment('TimelineSelection', function () { it('can be created with a frame', function () { - const frame = new TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame( - /* seqId */ 1, /* startTime */ TraceEngine.Types.Timing.MicroSeconds(1000), - /* start offset */ TraceEngine.Types.Timing.MicroSeconds(0)); + const frame = new Trace.Handlers.ModelHandlers.Frames.TimelineFrame( + /* seqId */ 1, /* startTime */ Trace.Types.Timing.MicroSeconds(1000), + /* start offset */ Trace.Types.Timing.MicroSeconds(0)); const selection = Timeline.TimelineSelection.TimelineSelection.fromFrame(frame); assert.strictEqual(selection.object, frame); - assert.strictEqual(selection.startTime, TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.startTime)); - assert.strictEqual(selection.endTime, TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.endTime)); + assert.strictEqual(selection.startTime, Trace.Helpers.Timing.microSecondsToMilliseconds(frame.startTime)); + assert.strictEqual(selection.endTime, Trace.Helpers.Timing.microSecondsToMilliseconds(frame.endTime)); assert.isTrue(Timeline.TimelineSelection.TimelineSelection.isLegacyTimelineFrame(selection.object)); }); it('can be created with a network request', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const request = traceData.NetworkRequests.byTime[0]; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const request = parsedTrace.NetworkRequests.byTime[0]; const selection = Timeline.TimelineSelection.TimelineSelection.fromTraceEvent(request); assert.strictEqual(selection.object, request); - assert.strictEqual(selection.startTime, TraceEngine.Helpers.Timing.microSecondsToMilliseconds(request.ts)); - assert.strictEqual(selection.endTime, TraceEngine.Helpers.Timing.microSecondsToMilliseconds((request.ts + request.dur))); + assert.strictEqual(selection.startTime, Trace.Helpers.Timing.microSecondsToMilliseconds(request.ts)); + assert.strictEqual(selection.endTime, Trace.Helpers.Timing.microSecondsToMilliseconds((request.ts + request.dur))); assert.isTrue(Timeline.TimelineSelection.TimelineSelection.isSyntheticNetworkRequestDetailsEventSelection(selection.object)); }); - it('can be created with a TraceEngine event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const firstLCPEvent = traceData.PageLoadMetrics.allMarkerEvents.find(event => { + it('can be created with a Trace event', async function () { + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const firstLCPEvent = parsedTrace.PageLoadMetrics.allMarkerEvents.find(event => { return event.name === 'largestContentfulPaint::Candidate'; }); if (!firstLCPEvent) { @@ -35,9 +35,9 @@ describeWithEnvironment('TimelineSelection', function () { } const selection = Timeline.TimelineSelection.TimelineSelection.fromTraceEvent(firstLCPEvent); assert.strictEqual(selection.object, firstLCPEvent); - assert.strictEqual(selection.startTime, TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(firstLCPEvent).startTime); - assert.strictEqual(selection.endTime, TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(firstLCPEvent).endTime); - assert.isTrue(Timeline.TimelineSelection.TimelineSelection.isTraceEventSelection(selection.object)); + assert.strictEqual(selection.startTime, Trace.Helpers.Timing.eventTimingsMilliSeconds(firstLCPEvent).startTime); + assert.strictEqual(selection.endTime, Trace.Helpers.Timing.eventTimingsMilliSeconds(firstLCPEvent).endTime); + assert.isTrue(Timeline.TimelineSelection.TimelineSelection.isSelection(selection.object)); }); it('can be created with a range', async function () { const selection = Timeline.TimelineSelection.TimelineSelection.fromRange(0, 10); diff --git a/public/panels/timeline/TimelineSelection.test.js.map b/public/panels/timeline/TimelineSelection.test.js.map index c26e5de86..1962429d0 100644 --- a/public/panels/timeline/TimelineSelection.test.js.map +++ b/public/panels/timeline/TimelineSelection.test.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineSelection.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineSelection.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\n\nimport * as Timeline from './timeline.js';\n\ndescribeWithEnvironment('TimelineSelection', function() {\n it('can be created with a frame', function() {\n const frame = new TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame(\n /* seqId */ 1, /* startTime */ TraceEngine.Types.Timing.MicroSeconds(1000),\n /* start offset */ TraceEngine.Types.Timing.MicroSeconds(0));\n const selection = Timeline.TimelineSelection.TimelineSelection.fromFrame(frame);\n assert.strictEqual(selection.object, frame);\n assert.strictEqual(selection.startTime, TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.startTime));\n assert.strictEqual(selection.endTime, TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.endTime));\n assert.isTrue(Timeline.TimelineSelection.TimelineSelection.isLegacyTimelineFrame(selection.object));\n });\n\n it('can be created with a network request', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const request = traceData.NetworkRequests.byTime[0];\n const selection = Timeline.TimelineSelection.TimelineSelection.fromTraceEvent(request);\n assert.strictEqual(selection.object, request);\n assert.strictEqual(selection.startTime, TraceEngine.Helpers.Timing.microSecondsToMilliseconds(request.ts));\n assert.strictEqual(\n selection.endTime,\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds(\n (request.ts + request.dur) as TraceEngine.Types.Timing.MicroSeconds));\n assert.isTrue(\n Timeline.TimelineSelection.TimelineSelection.isSyntheticNetworkRequestDetailsEventSelection(selection.object));\n });\n\n it('can be created with a TraceEngine event', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const firstLCPEvent = traceData.PageLoadMetrics.allMarkerEvents.find(event => {\n return event.name === 'largestContentfulPaint::Candidate';\n });\n if (!firstLCPEvent) {\n throw new Error('Could not find LCP event');\n }\n const selection = Timeline.TimelineSelection.TimelineSelection.fromTraceEvent(firstLCPEvent);\n assert.strictEqual(selection.object, firstLCPEvent);\n assert.strictEqual(\n selection.startTime, TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(firstLCPEvent).startTime);\n assert.strictEqual(selection.endTime, TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(firstLCPEvent).endTime);\n assert.isTrue(Timeline.TimelineSelection.TimelineSelection.isTraceEventSelection(selection.object));\n });\n\n it('can be created with a range', async function() {\n const selection = Timeline.TimelineSelection.TimelineSelection.fromRange(0, 10);\n assert.strictEqual(selection.startTime, 0);\n assert.strictEqual(selection.endTime, 10);\n assert.isTrue(Timeline.TimelineSelection.TimelineSelection.isRangeSelection(selection.object));\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"TimelineSelection.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineSelection.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\n\nimport * as Timeline from './timeline.js';\n\ndescribeWithEnvironment('TimelineSelection', function() {\n it('can be created with a frame', function() {\n const frame = new Trace.Handlers.ModelHandlers.Frames.TimelineFrame(\n /* seqId */ 1, /* startTime */ Trace.Types.Timing.MicroSeconds(1000),\n /* start offset */ Trace.Types.Timing.MicroSeconds(0));\n const selection = Timeline.TimelineSelection.TimelineSelection.fromFrame(frame);\n assert.strictEqual(selection.object, frame);\n assert.strictEqual(selection.startTime, Trace.Helpers.Timing.microSecondsToMilliseconds(frame.startTime));\n assert.strictEqual(selection.endTime, Trace.Helpers.Timing.microSecondsToMilliseconds(frame.endTime));\n assert.isTrue(Timeline.TimelineSelection.TimelineSelection.isLegacyTimelineFrame(selection.object));\n });\n\n it('can be created with a network request', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const request = parsedTrace.NetworkRequests.byTime[0];\n const selection = Timeline.TimelineSelection.TimelineSelection.fromTraceEvent(request);\n assert.strictEqual(selection.object, request);\n assert.strictEqual(selection.startTime, Trace.Helpers.Timing.microSecondsToMilliseconds(request.ts));\n assert.strictEqual(\n selection.endTime,\n Trace.Helpers.Timing.microSecondsToMilliseconds((request.ts + request.dur) as Trace.Types.Timing.MicroSeconds));\n assert.isTrue(\n Timeline.TimelineSelection.TimelineSelection.isSyntheticNetworkRequestDetailsEventSelection(selection.object));\n });\n\n it('can be created with a Trace event', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const firstLCPEvent = parsedTrace.PageLoadMetrics.allMarkerEvents.find(event => {\n return event.name === 'largestContentfulPaint::Candidate';\n });\n if (!firstLCPEvent) {\n throw new Error('Could not find LCP event');\n }\n const selection = Timeline.TimelineSelection.TimelineSelection.fromTraceEvent(firstLCPEvent);\n assert.strictEqual(selection.object, firstLCPEvent);\n assert.strictEqual(selection.startTime, Trace.Helpers.Timing.eventTimingsMilliSeconds(firstLCPEvent).startTime);\n assert.strictEqual(selection.endTime, Trace.Helpers.Timing.eventTimingsMilliSeconds(firstLCPEvent).endTime);\n assert.isTrue(Timeline.TimelineSelection.TimelineSelection.isSelection(selection.object));\n });\n\n it('can be created with a range', async function() {\n const selection = Timeline.TimelineSelection.TimelineSelection.fromRange(0, 10);\n assert.strictEqual(selection.startTime, 0);\n assert.strictEqual(selection.endTime, 10);\n assert.isTrue(Timeline.TimelineSelection.TimelineSelection.isRangeSelection(selection.object));\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineSelectorStatsView.d.ts b/public/panels/timeline/TimelineSelectorStatsView.d.ts index 3bbeb0520..3ee245db9 100644 --- a/public/panels/timeline/TimelineSelectorStatsView.d.ts +++ b/public/panels/timeline/TimelineSelectorStatsView.d.ts @@ -1,9 +1,9 @@ -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as UI from '../../ui/legacy/legacy.js'; export declare class TimelineSelectorStatsView extends UI.Widget.VBox { #private; - constructor(traceParsedData: TraceEngine.Handlers.Types.TraceParseData | null); - setEvent(event: TraceEngine.Types.TraceEvents.TraceEventUpdateLayoutTree): boolean; - setAggregatedEvents(events: TraceEngine.Types.TraceEvents.TraceEventUpdateLayoutTree[]): void; + constructor(parsedTrace: Trace.Handlers.Types.ParsedTrace | null); + setEvent(event: Trace.Types.Events.UpdateLayoutTree): boolean; + setAggregatedEvents(events: Trace.Types.Events.UpdateLayoutTree[]): void; private createRowsForTable; } diff --git a/public/panels/timeline/TimelineSelectorStatsView.js b/public/panels/timeline/TimelineSelectorStatsView.js index a43f12198..68b0aab1a 100644 --- a/public/panels/timeline/TimelineSelectorStatsView.js +++ b/public/panels/timeline/TimelineSelectorStatsView.js @@ -3,7 +3,7 @@ // found in the LICENSE file. import * as i18n from '../../core/i18n/i18n.js'; import * as SDK from '../../core/sdk/sdk.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as DataGrid from '../../ui/components/data_grid/data_grid.js'; import * as Linkifier from '../../ui/components/linkifier/linkifier.js'; import * as UI from '../../ui/legacy/legacy.js'; @@ -72,11 +72,11 @@ const UIStrings = { }; const str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelineSelectorStatsView.ts', UIStrings); const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); -const SelectorTimingsKey = TraceEngine.Types.TraceEvents.SelectorTimingsKey; +const SelectorTimingsKey = Trace.Types.Events.SelectorTimingsKey; export class TimelineSelectorStatsView extends UI.Widget.VBox { #datagrid; #selectorLocations; - #traceParsedData = null; + #parsedTrace = null; /** * We store the last event (or array of events) that we renderered. We do * this because as the user zooms around the panel this view is updated, @@ -86,12 +86,12 @@ export class TimelineSelectorStatsView extends UI.Widget.VBox { * If it's null, that means we have not rendered yet. */ #lastStatsSourceEventOrEvents = null; - constructor(traceParsedData) { + constructor(parsedTrace) { super(); this.#datagrid = new DataGrid.DataGridController.DataGridController(); this.element.setAttribute('jslog', `${VisualLogging.pane('selector-stats').track({ resize: true })}`); this.#selectorLocations = new Map(); - this.#traceParsedData = traceParsedData; + this.#parsedTrace = parsedTrace; this.#datagrid.data = { label: i18nString(UIStrings.selectorStats), showScrollbar: true, @@ -201,7 +201,7 @@ export class TimelineSelectorStatsView extends UI.Widget.VBox { this.contentElement.appendChild(this.#datagrid); } setEvent(event) { - if (!this.#traceParsedData) { + if (!this.#parsedTrace) { return false; } if (this.#lastStatsSourceEventOrEvents === event) { @@ -210,7 +210,7 @@ export class TimelineSelectorStatsView extends UI.Widget.VBox { return false; } this.#lastStatsSourceEventOrEvents = event; - const selectorStats = this.#traceParsedData.SelectorStats.dataForUpdateLayoutEvent.get(event); + const selectorStats = this.#parsedTrace.SelectorStats.dataForUpdateLayoutEvent.get(event); if (!selectorStats) { this.#datagrid.data = { ...this.#datagrid.data, rows: [] }; return false; @@ -224,7 +224,7 @@ export class TimelineSelectorStatsView extends UI.Widget.VBox { setAggregatedEvents(events) { const timings = []; const selectorMap = new Map(); - if (!this.#traceParsedData) { + if (!this.#parsedTrace) { return; } const sums = { @@ -252,7 +252,7 @@ export class TimelineSelectorStatsView extends UI.Widget.VBox { this.#lastStatsSourceEventOrEvents = events; for (let i = 0; i < events.length; i++) { const event = events[i]; - const selectorStats = event ? this.#traceParsedData.SelectorStats.dataForUpdateLayoutEvent.get(event) : undefined; + const selectorStats = event ? this.#parsedTrace.SelectorStats.dataForUpdateLayoutEvent.get(event) : undefined; if (!selectorStats) { continue; } diff --git a/public/panels/timeline/TimelineSelectorStatsView.js.map b/public/panels/timeline/TimelineSelectorStatsView.js.map index fb434c83a..74bf5c162 100644 --- a/public/panels/timeline/TimelineSelectorStatsView.js.map +++ b/public/panels/timeline/TimelineSelectorStatsView.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineSelectorStatsView.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineSelectorStatsView.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../core/i18n/i18n.js';\nimport type * as Platform from '../../core/platform/platform.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport type * as Protocol from '../../generated/protocol.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as DataGrid from '../../ui/components/data_grid/data_grid.js';\nimport * as Linkifier from '../../ui/components/linkifier/linkifier.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as LitHtml from '../../ui/lit-html/lit-html.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nconst UIStrings = {\n /**\n *@description Label for selector stats data table\n */\n selectorStats: 'Selector stats',\n /**\n *@description Column name and time unit for elapsed time spent computing a style rule\n */\n elapsed: 'Elapsed (ms)',\n /**\n *@description Column name and percentage of slow mach non-matches computing a style rule\n */\n rejectPercentage: '% of slow-path non-matches',\n /**\n *@description Tooltip description '% of slow-path non-matches'\n */\n rejectPercentageExplanation:\n 'The percentage of non-matching nodes (Match Attempts - Match Count) that couldn\\'t be quickly ruled out by the bloom filter. Lower is better.',\n /**\n *@description Column name for count of elements that the engine attempted to match against a style rule\n */\n matchAttempts: 'Match attempts',\n /**\n *@description Column name for count of elements that matched a style rule\n */\n matchCount: 'Match count',\n /**\n *@description Column name for a style rule's CSS selector text\n */\n selector: 'Selector',\n /**\n *@description Column name for a style rule's CSS selector text\n */\n styleSheetId: 'Style Sheet',\n /**\n *@description A context menu item in data grids to copy entire table to clipboard\n */\n copyTable: 'Copy table',\n /**\n *@description A cell value displayed in table when no source file can be traced via css style\n */\n unableToLink: 'Unable to link',\n /**\n *@description Tooltip for the cell that no source file can be traced via style sheet id\n *@example {style-sheet-4} PH1\n */\n unableToLinkViaStyleSheetId: 'Unable to link via {PH1}',\n /**\n *@description Text for announcing that the entire table was copied to clipboard\n */\n tableCopiedToClipboard: 'Table copied to clipboard',\n /**\n *@description Text shown as the \"Selectelector\" cell value for one row of the Selector Stats table, however this particular row is the totals. While normally the Selector cell is values like \"div.container\", the parenthesis can denote this description is not an actual selector, but a general row description.\n */\n totalForAllSelectors: '(Totals for all selectors)',\n\n /**\n *@description Text for showing the location of a selector in the style sheet\n *@example {256} PH1\n *@example {14} PH2\n */\n lineNumber: 'Line {PH1}:{PH2}',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelineSelectorStatsView.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nconst SelectorTimingsKey = TraceEngine.Types.TraceEvents.SelectorTimingsKey;\n\nexport class TimelineSelectorStatsView extends UI.Widget.VBox {\n #datagrid: DataGrid.DataGridController.DataGridController;\n #selectorLocations: Map;\n #traceParsedData: TraceEngine.Handlers.Types.TraceParseData|null = null;\n /**\n * We store the last event (or array of events) that we renderered. We do\n * this because as the user zooms around the panel this view is updated,\n * however if the set of events that are populating the view is the same as it\n * was the last time, we can bail without doing any re-rendering work.\n * If the user views a single event, this will be set to that single event, but if they are viewing a range of events, this will be set to an array.\n * If it's null, that means we have not rendered yet.\n */\n #lastStatsSourceEventOrEvents: TraceEngine.Types.TraceEvents.TraceEventUpdateLayoutTree|\n TraceEngine.Types.TraceEvents.TraceEventUpdateLayoutTree[]|null = null;\n\n constructor(traceParsedData: TraceEngine.Handlers.Types.TraceParseData|null) {\n super();\n\n this.#datagrid = new DataGrid.DataGridController.DataGridController();\n this.element.setAttribute('jslog', `${VisualLogging.pane('selector-stats').track({resize: true})}`);\n this.#selectorLocations = new Map();\n this.#traceParsedData = traceParsedData;\n\n this.#datagrid.data = {\n label: i18nString(UIStrings.selectorStats),\n showScrollbar: true,\n autoScrollToBottom: false,\n initialSort: {\n columnId: SelectorTimingsKey.Elapsed as Lowercase,\n direction: DataGrid.DataGridUtils.SortDirection.DESC,\n },\n columns: [\n {\n id: SelectorTimingsKey.Elapsed as Lowercase,\n title: i18nString(UIStrings.elapsed),\n sortable: true,\n widthWeighting: 1,\n visible: true,\n hideable: true,\n styles: {\n 'text-align': 'right',\n },\n },\n {\n id: SelectorTimingsKey.MatchAttempts as Lowercase,\n title: i18nString(UIStrings.matchAttempts),\n sortable: true,\n widthWeighting: 1,\n visible: true,\n hideable: true,\n styles: {\n 'text-align': 'right',\n },\n },\n {\n id: SelectorTimingsKey.MatchCount as Lowercase,\n title: i18nString(UIStrings.matchCount),\n sortable: true,\n widthWeighting: 1,\n visible: true,\n hideable: true,\n styles: {\n 'text-align': 'right',\n },\n },\n {\n id: SelectorTimingsKey.RejectPercentage as Lowercase,\n title: i18nString(UIStrings.rejectPercentage),\n titleElement: LitHtml.html`${\n i18nString(UIStrings.rejectPercentage)}`,\n sortable: true,\n widthWeighting: 1,\n visible: true,\n hideable: true,\n styles: {\n 'text-align': 'right',\n },\n },\n {\n id: SelectorTimingsKey.Selector as Lowercase,\n title: i18nString(UIStrings.selector),\n sortable: true,\n widthWeighting: 3,\n visible: true,\n hideable: true,\n },\n {\n id: SelectorTimingsKey.StyleSheetId as Lowercase,\n title: i18nString(UIStrings.styleSheetId),\n sortable: true,\n widthWeighting: 1.5,\n visible: true,\n hideable: true,\n },\n ],\n rows: [],\n contextMenus: {\n bodyRow: (\n menu: UI.ContextMenu.ContextMenu, columns: readonly DataGrid.DataGridUtils.Column[],\n row: Readonly, rows: readonly DataGrid.DataGridUtils.Row[]): void => {\n menu.defaultSection().appendItem(i18nString(UIStrings.copyTable), () => {\n const tableData = [];\n const columnName = columns.map(col => col.title);\n tableData.push(columnName.join('\\t'));\n for (const rowData of rows) {\n const cellsValue = rowData.cells;\n const rowValue = cellsValue.map(cell => {\n if (cell.columnId === SelectorTimingsKey.StyleSheetId) {\n // Export link via raw StyleSheetId data\n const defaultLinkValue = i18nString(UIStrings.unableToLink);\n let linkData = '';\n const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n const cssModel = target?.model(SDK.CSSModel.CSSModel);\n if (cssModel) {\n const styleSheetHeader = cssModel.styleSheetHeaderForId(cell.value as Protocol.CSS.StyleSheetId);\n if (styleSheetHeader) {\n linkData = styleSheetHeader.resourceURL().toString();\n }\n }\n return linkData ? linkData.toString() : defaultLinkValue;\n }\n return String(cell.value);\n });\n tableData.push(rowValue.join('\\t'));\n }\n const data = tableData.join('\\n');\n void navigator.clipboard.writeText(data);\n UI.ARIAUtils.alert(i18nString(UIStrings.tableCopiedToClipboard));\n });\n },\n },\n };\n\n this.contentElement.appendChild(this.#datagrid);\n }\n\n setEvent(event: TraceEngine.Types.TraceEvents.TraceEventUpdateLayoutTree): boolean {\n if (!this.#traceParsedData) {\n return false;\n }\n\n if (this.#lastStatsSourceEventOrEvents === event) {\n // The event that is populating the selector stats table has not changed,\n // so no need to do any work because the data will be the same.\n return false;\n }\n\n this.#lastStatsSourceEventOrEvents = event;\n\n const selectorStats = this.#traceParsedData.SelectorStats.dataForUpdateLayoutEvent.get(event);\n if (!selectorStats) {\n this.#datagrid.data = {...this.#datagrid.data, rows: []};\n return false;\n }\n\n const timings: TraceEngine.Types.TraceEvents.SelectorTiming[] = selectorStats.timings;\n void this.createRowsForTable(timings).then(rows => {\n this.#datagrid.data = {...this.#datagrid.data, rows};\n });\n\n return true;\n }\n\n setAggregatedEvents(events: TraceEngine.Types.TraceEvents.TraceEventUpdateLayoutTree[]): void {\n const timings: TraceEngine.Types.TraceEvents.SelectorTiming[] = [];\n const selectorMap = new Map();\n\n if (!this.#traceParsedData) {\n return;\n }\n\n const sums = {\n [SelectorTimingsKey.Elapsed]: 0,\n [SelectorTimingsKey.MatchAttempts]: 0,\n [SelectorTimingsKey.MatchCount]: 0,\n [SelectorTimingsKey.FastRejectCount]: 0,\n };\n\n // Now we want to check if the set of events we have been given matches the\n // set of events we last rendered. We can't just compare the arrays because\n // they will be different events, so instead for each event in the new\n // array we see if it has a match in the old set of events at the same\n // index.\n\n if (Array.isArray(this.#lastStatsSourceEventOrEvents)) {\n if (this.#lastStatsSourceEventOrEvents.length === events.length && events.every((event, index) => {\n // This is true due to the isArray check, but without this cast TS\n // would want us to repeat the isArray() check inside this callback,\n // but we want to avoid that extra work.\n const previousEvents =\n this.#lastStatsSourceEventOrEvents as TraceEngine.Types.TraceEvents.TraceEventUpdateLayoutTree[];\n return event === previousEvents[index];\n })) {\n return;\n }\n }\n\n this.#lastStatsSourceEventOrEvents = events;\n\n for (let i = 0; i < events.length; i++) {\n const event = events[i];\n const selectorStats = event ? this.#traceParsedData.SelectorStats.dataForUpdateLayoutEvent.get(event) : undefined;\n if (!selectorStats) {\n continue;\n } else {\n const data: TraceEngine.Types.TraceEvents.SelectorTiming[] = selectorStats.timings;\n for (const timing of data) {\n const key = timing[SelectorTimingsKey.Selector] + '_' + timing[SelectorTimingsKey.StyleSheetId];\n const findTiming = selectorMap.get(key);\n if (findTiming !== undefined) {\n findTiming[SelectorTimingsKey.Elapsed] += timing[SelectorTimingsKey.Elapsed];\n findTiming[SelectorTimingsKey.FastRejectCount] += timing[SelectorTimingsKey.FastRejectCount];\n findTiming[SelectorTimingsKey.MatchAttempts] += timing[SelectorTimingsKey.MatchAttempts];\n findTiming[SelectorTimingsKey.MatchCount] += timing[SelectorTimingsKey.MatchCount];\n } else {\n selectorMap.set(key, structuredClone(timing));\n }\n // Keep track of the total times for a sum row.\n sums[SelectorTimingsKey.Elapsed] += timing[SelectorTimingsKey.Elapsed];\n sums[SelectorTimingsKey.MatchAttempts] += timing[SelectorTimingsKey.MatchAttempts];\n sums[SelectorTimingsKey.MatchCount] += timing[SelectorTimingsKey.MatchCount];\n sums[SelectorTimingsKey.FastRejectCount] += timing[SelectorTimingsKey.FastRejectCount];\n }\n }\n }\n if (selectorMap.size > 0) {\n selectorMap.forEach(timing => {\n timings.push(timing);\n });\n selectorMap.clear();\n } else {\n this.#datagrid.data = {...this.#datagrid.data, rows: []};\n return;\n }\n\n // Add the sum row.\n timings.unshift({\n [SelectorTimingsKey.Elapsed]: sums[SelectorTimingsKey.Elapsed],\n [SelectorTimingsKey.FastRejectCount]: sums[SelectorTimingsKey.FastRejectCount],\n [SelectorTimingsKey.MatchAttempts]: sums[SelectorTimingsKey.MatchAttempts],\n [SelectorTimingsKey.MatchCount]: sums[SelectorTimingsKey.MatchCount],\n [SelectorTimingsKey.Selector]: i18nString(UIStrings.totalForAllSelectors),\n [SelectorTimingsKey.StyleSheetId]: 'n/a',\n });\n\n void this.createRowsForTable(timings).then(rows => {\n this.#datagrid.data = {...this.#datagrid.data, rows};\n });\n }\n\n private async createRowsForTable(timings: TraceEngine.Types.TraceEvents.SelectorTiming[]):\n Promise {\n async function toSourceFileLocation(\n cssModel: SDK.CSSModel.CSSModel, styleSheetId: Protocol.CSS.StyleSheetId, selectorText: string,\n selectorLocations: Map):\n Promise {\n if (!cssModel) {\n return undefined;\n }\n const styleSheetHeader = cssModel.styleSheetHeaderForId(styleSheetId);\n if (!styleSheetHeader || !styleSheetHeader.resourceURL()) {\n return undefined;\n }\n\n // get the locations from cache if available\n const key: string = JSON.stringify({selectorText, styleSheetId});\n let ranges = selectorLocations.get(key);\n if (!ranges) {\n const result = await cssModel.agent.invoke_getLocationForSelector({styleSheetId, selectorText});\n if (result.getError() || !result.ranges) {\n return undefined;\n }\n ranges = result.ranges;\n selectorLocations.set(key, ranges);\n }\n\n const linkData = ranges.map(range => {\n return {\n url: styleSheetHeader.resourceURL() as Platform.DevToolsPath.UrlString,\n lineNumber: range.startLine,\n columnNumber: range.startColumn,\n linkText: i18nString(UIStrings.lineNumber, {PH1: range.startLine + 1, PH2: range.startColumn + 1}),\n } as Linkifier.Linkifier.LinkifierData;\n });\n return linkData;\n }\n\n const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n const cssModel = target?.model(SDK.CSSModel.CSSModel);\n if (!cssModel) {\n return [];\n }\n\n const rows = await Promise.all(timings.map(async x => {\n const styleSheetId = x[SelectorTimingsKey.StyleSheetId] as Protocol.CSS.StyleSheetId;\n const selectorText = x[SelectorTimingsKey.Selector].trim();\n const elapsedTimeInMs = x[SelectorTimingsKey.Elapsed] / 1000.0;\n const nonMatches = x[SelectorTimingsKey.MatchAttempts] - x[SelectorTimingsKey.MatchCount];\n const rejectPercentage = (nonMatches ? x[SelectorTimingsKey.FastRejectCount] / nonMatches : 1) * 100;\n const locations = styleSheetId === 'n/a' ?\n null :\n await toSourceFileLocation(cssModel, styleSheetId, selectorText, this.#selectorLocations);\n\n return {\n cells: [\n {\n columnId: SelectorTimingsKey.Elapsed,\n value: elapsedTimeInMs,\n renderer(): LitHtml.TemplateResult {\n return LitHtml.html`${elapsedTimeInMs.toFixed(3)}`;\n },\n },\n {columnId: SelectorTimingsKey.MatchAttempts, value: x[SelectorTimingsKey.MatchAttempts]},\n {columnId: SelectorTimingsKey.MatchCount, value: x[SelectorTimingsKey.MatchCount]},\n {\n columnId: SelectorTimingsKey.RejectPercentage,\n value: rejectPercentage,\n renderer(): LitHtml.TemplateResult {\n return LitHtml.html`${rejectPercentage.toFixed(1)}`;\n },\n },\n {\n columnId: SelectorTimingsKey.Selector,\n title: x[SelectorTimingsKey.Selector],\n value: x[SelectorTimingsKey.Selector],\n },\n {\n columnId: SelectorTimingsKey.StyleSheetId,\n value: x[SelectorTimingsKey.StyleSheetId],\n renderer(): LitHtml.TemplateResult {\n if (locations === null) {\n return LitHtml.html``;\n }\n if (locations === undefined) {\n return LitHtml.html`${i18nString(UIStrings.unableToLink)}`;\n }\n return LitHtml.html`\n ${locations.map((location, itemIndex) => {\n if (itemIndex !== locations.length - 1) {\n // eslint-disable-next-line rulesdir/ban_a_tags_in_lit_html\n return LitHtml.html`<${Linkifier.Linkifier.Linkifier.litTagName} .data=${\n location as Linkifier.Linkifier.LinkifierData}>\n , `;\n }\n return LitHtml.html`<${Linkifier.Linkifier.Linkifier.litTagName} .data=${\n location as Linkifier.Linkifier.LinkifierData}>`;\n })}\n `;\n },\n },\n ],\n };\n }));\n\n return rows;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"TimelineSelectorStatsView.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineSelectorStatsView.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../core/i18n/i18n.js';\nimport type * as Platform from '../../core/platform/platform.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport type * as Protocol from '../../generated/protocol.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as DataGrid from '../../ui/components/data_grid/data_grid.js';\nimport * as Linkifier from '../../ui/components/linkifier/linkifier.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as LitHtml from '../../ui/lit-html/lit-html.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nconst UIStrings = {\n /**\n *@description Label for selector stats data table\n */\n selectorStats: 'Selector stats',\n /**\n *@description Column name and time unit for elapsed time spent computing a style rule\n */\n elapsed: 'Elapsed (ms)',\n /**\n *@description Column name and percentage of slow mach non-matches computing a style rule\n */\n rejectPercentage: '% of slow-path non-matches',\n /**\n *@description Tooltip description '% of slow-path non-matches'\n */\n rejectPercentageExplanation:\n 'The percentage of non-matching nodes (Match Attempts - Match Count) that couldn\\'t be quickly ruled out by the bloom filter. Lower is better.',\n /**\n *@description Column name for count of elements that the engine attempted to match against a style rule\n */\n matchAttempts: 'Match attempts',\n /**\n *@description Column name for count of elements that matched a style rule\n */\n matchCount: 'Match count',\n /**\n *@description Column name for a style rule's CSS selector text\n */\n selector: 'Selector',\n /**\n *@description Column name for a style rule's CSS selector text\n */\n styleSheetId: 'Style Sheet',\n /**\n *@description A context menu item in data grids to copy entire table to clipboard\n */\n copyTable: 'Copy table',\n /**\n *@description A cell value displayed in table when no source file can be traced via css style\n */\n unableToLink: 'Unable to link',\n /**\n *@description Tooltip for the cell that no source file can be traced via style sheet id\n *@example {style-sheet-4} PH1\n */\n unableToLinkViaStyleSheetId: 'Unable to link via {PH1}',\n /**\n *@description Text for announcing that the entire table was copied to clipboard\n */\n tableCopiedToClipboard: 'Table copied to clipboard',\n /**\n *@description Text shown as the \"Selectelector\" cell value for one row of the Selector Stats table, however this particular row is the totals. While normally the Selector cell is values like \"div.container\", the parenthesis can denote this description is not an actual selector, but a general row description.\n */\n totalForAllSelectors: '(Totals for all selectors)',\n\n /**\n *@description Text for showing the location of a selector in the style sheet\n *@example {256} PH1\n *@example {14} PH2\n */\n lineNumber: 'Line {PH1}:{PH2}',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelineSelectorStatsView.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nconst SelectorTimingsKey = Trace.Types.Events.SelectorTimingsKey;\n\nexport class TimelineSelectorStatsView extends UI.Widget.VBox {\n #datagrid: DataGrid.DataGridController.DataGridController;\n #selectorLocations: Map;\n #parsedTrace: Trace.Handlers.Types.ParsedTrace|null = null;\n /**\n * We store the last event (or array of events) that we renderered. We do\n * this because as the user zooms around the panel this view is updated,\n * however if the set of events that are populating the view is the same as it\n * was the last time, we can bail without doing any re-rendering work.\n * If the user views a single event, this will be set to that single event, but if they are viewing a range of events, this will be set to an array.\n * If it's null, that means we have not rendered yet.\n */\n #lastStatsSourceEventOrEvents: Trace.Types.Events.UpdateLayoutTree|Trace.Types.Events.UpdateLayoutTree[]|null = null;\n\n constructor(parsedTrace: Trace.Handlers.Types.ParsedTrace|null) {\n super();\n\n this.#datagrid = new DataGrid.DataGridController.DataGridController();\n this.element.setAttribute('jslog', `${VisualLogging.pane('selector-stats').track({resize: true})}`);\n this.#selectorLocations = new Map();\n this.#parsedTrace = parsedTrace;\n\n this.#datagrid.data = {\n label: i18nString(UIStrings.selectorStats),\n showScrollbar: true,\n autoScrollToBottom: false,\n initialSort: {\n columnId: SelectorTimingsKey.Elapsed as Lowercase,\n direction: DataGrid.DataGridUtils.SortDirection.DESC,\n },\n columns: [\n {\n id: SelectorTimingsKey.Elapsed as Lowercase,\n title: i18nString(UIStrings.elapsed),\n sortable: true,\n widthWeighting: 1,\n visible: true,\n hideable: true,\n styles: {\n 'text-align': 'right',\n },\n },\n {\n id: SelectorTimingsKey.MatchAttempts as Lowercase,\n title: i18nString(UIStrings.matchAttempts),\n sortable: true,\n widthWeighting: 1,\n visible: true,\n hideable: true,\n styles: {\n 'text-align': 'right',\n },\n },\n {\n id: SelectorTimingsKey.MatchCount as Lowercase,\n title: i18nString(UIStrings.matchCount),\n sortable: true,\n widthWeighting: 1,\n visible: true,\n hideable: true,\n styles: {\n 'text-align': 'right',\n },\n },\n {\n id: SelectorTimingsKey.RejectPercentage as Lowercase,\n title: i18nString(UIStrings.rejectPercentage),\n titleElement: LitHtml.html`${\n i18nString(UIStrings.rejectPercentage)}`,\n sortable: true,\n widthWeighting: 1,\n visible: true,\n hideable: true,\n styles: {\n 'text-align': 'right',\n },\n },\n {\n id: SelectorTimingsKey.Selector as Lowercase,\n title: i18nString(UIStrings.selector),\n sortable: true,\n widthWeighting: 3,\n visible: true,\n hideable: true,\n },\n {\n id: SelectorTimingsKey.StyleSheetId as Lowercase,\n title: i18nString(UIStrings.styleSheetId),\n sortable: true,\n widthWeighting: 1.5,\n visible: true,\n hideable: true,\n },\n ],\n rows: [],\n contextMenus: {\n bodyRow: (\n menu: UI.ContextMenu.ContextMenu, columns: readonly DataGrid.DataGridUtils.Column[],\n row: Readonly, rows: readonly DataGrid.DataGridUtils.Row[]): void => {\n menu.defaultSection().appendItem(i18nString(UIStrings.copyTable), () => {\n const tableData = [];\n const columnName = columns.map(col => col.title);\n tableData.push(columnName.join('\\t'));\n for (const rowData of rows) {\n const cellsValue = rowData.cells;\n const rowValue = cellsValue.map(cell => {\n if (cell.columnId === SelectorTimingsKey.StyleSheetId) {\n // Export link via raw StyleSheetId data\n const defaultLinkValue = i18nString(UIStrings.unableToLink);\n let linkData = '';\n const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n const cssModel = target?.model(SDK.CSSModel.CSSModel);\n if (cssModel) {\n const styleSheetHeader = cssModel.styleSheetHeaderForId(cell.value as Protocol.CSS.StyleSheetId);\n if (styleSheetHeader) {\n linkData = styleSheetHeader.resourceURL().toString();\n }\n }\n return linkData ? linkData.toString() : defaultLinkValue;\n }\n return String(cell.value);\n });\n tableData.push(rowValue.join('\\t'));\n }\n const data = tableData.join('\\n');\n void navigator.clipboard.writeText(data);\n UI.ARIAUtils.alert(i18nString(UIStrings.tableCopiedToClipboard));\n });\n },\n },\n };\n\n this.contentElement.appendChild(this.#datagrid);\n }\n\n setEvent(event: Trace.Types.Events.UpdateLayoutTree): boolean {\n if (!this.#parsedTrace) {\n return false;\n }\n\n if (this.#lastStatsSourceEventOrEvents === event) {\n // The event that is populating the selector stats table has not changed,\n // so no need to do any work because the data will be the same.\n return false;\n }\n\n this.#lastStatsSourceEventOrEvents = event;\n\n const selectorStats = this.#parsedTrace.SelectorStats.dataForUpdateLayoutEvent.get(event);\n if (!selectorStats) {\n this.#datagrid.data = {...this.#datagrid.data, rows: []};\n return false;\n }\n\n const timings: Trace.Types.Events.SelectorTiming[] = selectorStats.timings;\n void this.createRowsForTable(timings).then(rows => {\n this.#datagrid.data = {...this.#datagrid.data, rows};\n });\n\n return true;\n }\n\n setAggregatedEvents(events: Trace.Types.Events.UpdateLayoutTree[]): void {\n const timings: Trace.Types.Events.SelectorTiming[] = [];\n const selectorMap = new Map();\n\n if (!this.#parsedTrace) {\n return;\n }\n\n const sums = {\n [SelectorTimingsKey.Elapsed]: 0,\n [SelectorTimingsKey.MatchAttempts]: 0,\n [SelectorTimingsKey.MatchCount]: 0,\n [SelectorTimingsKey.FastRejectCount]: 0,\n };\n\n // Now we want to check if the set of events we have been given matches the\n // set of events we last rendered. We can't just compare the arrays because\n // they will be different events, so instead for each event in the new\n // array we see if it has a match in the old set of events at the same\n // index.\n\n if (Array.isArray(this.#lastStatsSourceEventOrEvents)) {\n if (this.#lastStatsSourceEventOrEvents.length === events.length && events.every((event, index) => {\n // This is true due to the isArray check, but without this cast TS\n // would want us to repeat the isArray() check inside this callback,\n // but we want to avoid that extra work.\n const previousEvents = this.#lastStatsSourceEventOrEvents as Trace.Types.Events.UpdateLayoutTree[];\n return event === previousEvents[index];\n })) {\n return;\n }\n }\n\n this.#lastStatsSourceEventOrEvents = events;\n\n for (let i = 0; i < events.length; i++) {\n const event = events[i];\n const selectorStats = event ? this.#parsedTrace.SelectorStats.dataForUpdateLayoutEvent.get(event) : undefined;\n if (!selectorStats) {\n continue;\n } else {\n const data: Trace.Types.Events.SelectorTiming[] = selectorStats.timings;\n for (const timing of data) {\n const key = timing[SelectorTimingsKey.Selector] + '_' + timing[SelectorTimingsKey.StyleSheetId];\n const findTiming = selectorMap.get(key);\n if (findTiming !== undefined) {\n findTiming[SelectorTimingsKey.Elapsed] += timing[SelectorTimingsKey.Elapsed];\n findTiming[SelectorTimingsKey.FastRejectCount] += timing[SelectorTimingsKey.FastRejectCount];\n findTiming[SelectorTimingsKey.MatchAttempts] += timing[SelectorTimingsKey.MatchAttempts];\n findTiming[SelectorTimingsKey.MatchCount] += timing[SelectorTimingsKey.MatchCount];\n } else {\n selectorMap.set(key, structuredClone(timing));\n }\n // Keep track of the total times for a sum row.\n sums[SelectorTimingsKey.Elapsed] += timing[SelectorTimingsKey.Elapsed];\n sums[SelectorTimingsKey.MatchAttempts] += timing[SelectorTimingsKey.MatchAttempts];\n sums[SelectorTimingsKey.MatchCount] += timing[SelectorTimingsKey.MatchCount];\n sums[SelectorTimingsKey.FastRejectCount] += timing[SelectorTimingsKey.FastRejectCount];\n }\n }\n }\n if (selectorMap.size > 0) {\n selectorMap.forEach(timing => {\n timings.push(timing);\n });\n selectorMap.clear();\n } else {\n this.#datagrid.data = {...this.#datagrid.data, rows: []};\n return;\n }\n\n // Add the sum row.\n timings.unshift({\n [SelectorTimingsKey.Elapsed]: sums[SelectorTimingsKey.Elapsed],\n [SelectorTimingsKey.FastRejectCount]: sums[SelectorTimingsKey.FastRejectCount],\n [SelectorTimingsKey.MatchAttempts]: sums[SelectorTimingsKey.MatchAttempts],\n [SelectorTimingsKey.MatchCount]: sums[SelectorTimingsKey.MatchCount],\n [SelectorTimingsKey.Selector]: i18nString(UIStrings.totalForAllSelectors),\n [SelectorTimingsKey.StyleSheetId]: 'n/a',\n });\n\n void this.createRowsForTable(timings).then(rows => {\n this.#datagrid.data = {...this.#datagrid.data, rows};\n });\n }\n\n private async createRowsForTable(timings: Trace.Types.Events.SelectorTiming[]):\n Promise {\n async function toSourceFileLocation(\n cssModel: SDK.CSSModel.CSSModel, styleSheetId: Protocol.CSS.StyleSheetId, selectorText: string,\n selectorLocations: Map):\n Promise {\n if (!cssModel) {\n return undefined;\n }\n const styleSheetHeader = cssModel.styleSheetHeaderForId(styleSheetId);\n if (!styleSheetHeader || !styleSheetHeader.resourceURL()) {\n return undefined;\n }\n\n // get the locations from cache if available\n const key: string = JSON.stringify({selectorText, styleSheetId});\n let ranges = selectorLocations.get(key);\n if (!ranges) {\n const result = await cssModel.agent.invoke_getLocationForSelector({styleSheetId, selectorText});\n if (result.getError() || !result.ranges) {\n return undefined;\n }\n ranges = result.ranges;\n selectorLocations.set(key, ranges);\n }\n\n const linkData = ranges.map(range => {\n return {\n url: styleSheetHeader.resourceURL() as Platform.DevToolsPath.UrlString,\n lineNumber: range.startLine,\n columnNumber: range.startColumn,\n linkText: i18nString(UIStrings.lineNumber, {PH1: range.startLine + 1, PH2: range.startColumn + 1}),\n } as Linkifier.Linkifier.LinkifierData;\n });\n return linkData;\n }\n\n const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n const cssModel = target?.model(SDK.CSSModel.CSSModel);\n if (!cssModel) {\n return [];\n }\n\n const rows = await Promise.all(timings.map(async x => {\n const styleSheetId = x[SelectorTimingsKey.StyleSheetId] as Protocol.CSS.StyleSheetId;\n const selectorText = x[SelectorTimingsKey.Selector].trim();\n const elapsedTimeInMs = x[SelectorTimingsKey.Elapsed] / 1000.0;\n const nonMatches = x[SelectorTimingsKey.MatchAttempts] - x[SelectorTimingsKey.MatchCount];\n const rejectPercentage = (nonMatches ? x[SelectorTimingsKey.FastRejectCount] / nonMatches : 1) * 100;\n const locations = styleSheetId === 'n/a' ?\n null :\n await toSourceFileLocation(cssModel, styleSheetId, selectorText, this.#selectorLocations);\n\n return {\n cells: [\n {\n columnId: SelectorTimingsKey.Elapsed,\n value: elapsedTimeInMs,\n renderer(): LitHtml.TemplateResult {\n return LitHtml.html`${elapsedTimeInMs.toFixed(3)}`;\n },\n },\n {columnId: SelectorTimingsKey.MatchAttempts, value: x[SelectorTimingsKey.MatchAttempts]},\n {columnId: SelectorTimingsKey.MatchCount, value: x[SelectorTimingsKey.MatchCount]},\n {\n columnId: SelectorTimingsKey.RejectPercentage,\n value: rejectPercentage,\n renderer(): LitHtml.TemplateResult {\n return LitHtml.html`${rejectPercentage.toFixed(1)}`;\n },\n },\n {\n columnId: SelectorTimingsKey.Selector,\n title: x[SelectorTimingsKey.Selector],\n value: x[SelectorTimingsKey.Selector],\n },\n {\n columnId: SelectorTimingsKey.StyleSheetId,\n value: x[SelectorTimingsKey.StyleSheetId],\n renderer(): LitHtml.TemplateResult {\n if (locations === null) {\n return LitHtml.html``;\n }\n if (locations === undefined) {\n return LitHtml.html`${i18nString(UIStrings.unableToLink)}`;\n }\n return LitHtml.html`\n ${locations.map((location, itemIndex) => {\n if (itemIndex !== locations.length - 1) {\n // eslint-disable-next-line rulesdir/ban_a_tags_in_lit_html\n return LitHtml.html`<${Linkifier.Linkifier.Linkifier.litTagName} .data=${\n location as Linkifier.Linkifier.LinkifierData}>\n , `;\n }\n return LitHtml.html`<${Linkifier.Linkifier.Linkifier.litTagName} .data=${\n location as Linkifier.Linkifier.LinkifierData}>`;\n })}\n `;\n },\n },\n ],\n };\n }));\n\n return rows;\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineTreeView.d.ts b/public/panels/timeline/TimelineTreeView.d.ts index 33e2d61e5..3b25eb550 100644 --- a/public/panels/timeline/TimelineTreeView.d.ts +++ b/public/panels/timeline/TimelineTreeView.d.ts @@ -1,7 +1,7 @@ import * as Common from '../../core/common/common.js'; import * as Platform from '../../core/platform/platform.js'; import * as TimelineModel from '../../models/timeline_model/timeline_model.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as DataGrid from '../../ui/legacy/components/data_grid/data_grid.js'; import * as Components from '../../ui/legacy/components/utils/utils.js'; import * as UI from '../../ui/legacy/legacy.js'; @@ -15,8 +15,8 @@ export declare class TimelineTreeView extends UI.Widget.VBox implements UI.Searc private lastHoveredProfileNode; private textFilterInternal; private taskFilter; - protected startTime: TraceEngine.Types.Timing.MilliSeconds; - protected endTime: TraceEngine.Types.Timing.MilliSeconds; + protected startTime: Trace.Types.Timing.MilliSeconds; + protected endTime: Trace.Types.Timing.MilliSeconds; splitWidget: UI.SplitWidget.SplitWidget; detailsView: UI.Widget.Widget; private searchableView; @@ -30,24 +30,24 @@ export declare class TimelineTreeView extends UI.Widget.VBox implements UI.Searc private matchWholeWord; constructor(); setSearchableView(searchableView: UI.SearchableView.SearchableView): void; - setModelWithEvents(selectedEvents: TraceEngine.Types.TraceEvents.TraceEventData[] | null, traceParseData?: TraceEngine.Handlers.Types.TraceParseData | null): void; - traceParseData(): TraceEngine.Handlers.Types.TraceParseData | null; + setModelWithEvents(selectedEvents: Trace.Types.Events.Event[] | null, parsedTrace?: Trace.Handlers.Types.ParsedTrace | null): void; + parsedTrace(): Trace.Handlers.Types.ParsedTrace | null; init(): void; lastSelectedNode(): TimelineModel.TimelineProfileTree.Node | null | undefined; updateContents(selection: TimelineSelection): void; - setRange(startTime: TraceEngine.Types.Timing.MilliSeconds, endTime: TraceEngine.Types.Timing.MilliSeconds): void; + setRange(startTime: Trace.Types.Timing.MilliSeconds, endTime: Trace.Types.Timing.MilliSeconds): void; filters(): TimelineModel.TimelineModelFilter.TimelineModelFilter[]; filtersWithoutTextFilter(): TimelineModel.TimelineModelFilter.TimelineModelFilter[]; textFilter(): TimelineRegExp; exposePercentages(): boolean; populateToolbar(toolbar: UI.Toolbar.Toolbar): void; - selectedEvents(): TraceEngine.Types.TraceEvents.TraceEventData[]; + selectedEvents(): Trace.Types.Events.Event[]; onHover(_node: TimelineModel.TimelineProfileTree.Node | null): void; appendContextMenuItems(_contextMenu: UI.ContextMenu.ContextMenu, _node: TimelineModel.TimelineProfileTree.Node): void; selectProfileNode(treeNode: TimelineModel.TimelineProfileTree.Node, suppressSelectedEvent: boolean): void; refreshTree(): void; buildTree(): TimelineModel.TimelineProfileTree.Node; - buildTopDownTree(doNotAggregate: boolean, groupIdCallback: ((arg0: TraceEngine.Types.TraceEvents.TraceEventData) => string) | null): TimelineModel.TimelineProfileTree.Node; + buildTopDownTree(doNotAggregate: boolean, groupIdCallback: ((arg0: Trace.Types.Events.Event) => string) | null): TimelineModel.TimelineProfileTree.Node; populateColumns(columns: DataGrid.DataGrid.ColumnDescriptor[]): void; private sortingChanged; private onShowModeChanged; @@ -99,7 +99,7 @@ export declare class AggregatedTimelineTreeView extends TimelineTreeView { exposePercentages(): boolean; private onStackViewSelectionChanged; showDetailsForNode(node: TimelineModel.TimelineProfileTree.Node): boolean; - protected groupingFunction(groupBy: AggregatedTimelineTreeView.GroupBy): ((arg0: TraceEngine.Types.TraceEvents.TraceEventData) => string) | null; + protected groupingFunction(groupBy: AggregatedTimelineTreeView.GroupBy): ((arg0: Trace.Types.Events.Event) => string) | null; private domainByEvent; private static isExtensionInternalURL; private static isV8NativeURL; diff --git a/public/panels/timeline/TimelineTreeView.js b/public/panels/timeline/TimelineTreeView.js index a69e1b3a1..72481cc6f 100644 --- a/public/panels/timeline/TimelineTreeView.js +++ b/public/panels/timeline/TimelineTreeView.js @@ -6,7 +6,7 @@ import * as i18n from '../../core/i18n/i18n.js'; import * as Platform from '../../core/platform/platform.js'; import * as SDK from '../../core/sdk/sdk.js'; import * as TimelineModel from '../../models/timeline_model/timeline_model.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as ThirdPartyWeb from '../../third_party/third-party-web/third-party-web.js'; import * as DataGrid from '../../ui/legacy/components/data_grid/data_grid.js'; import * as Components from '../../ui/legacy/components/utils/utils.js'; @@ -169,7 +169,7 @@ export class TimelineTreeView extends UI.Widget.VBox { caseSensitiveButton; regexButton; matchWholeWord; - #traceParseData = null; + #parsedTrace = null; constructor() { super(); this.#selectedEvents = null; @@ -178,25 +178,25 @@ export class TimelineTreeView extends UI.Widget.VBox { } #eventNameForSorting(event) { const name = TimelineUIUtils.eventTitle(event) || event.name; - if (!this.#traceParseData) { + if (!this.#parsedTrace) { return name; } - return name + ':@' + TraceEngine.Extras.URLForEntry.get(this.#traceParseData, event); + return name + ':@' + Trace.Extras.URLForEntry.get(this.#parsedTrace, event); } setSearchableView(searchableView) { this.searchableView = searchableView; } - setModelWithEvents(selectedEvents, traceParseData = null) { - this.#traceParseData = traceParseData; + setModelWithEvents(selectedEvents, parsedTrace = null) { + this.#parsedTrace = parsedTrace; this.#selectedEvents = selectedEvents; } - traceParseData() { - return this.#traceParseData; + parsedTrace() { + return this.#parsedTrace; } init() { this.linkifier = new Components.Linkifier.Linkifier(); this.taskFilter = new TimelineModel.TimelineModelFilter.ExclusiveNameFilter([ - "RunTask" /* TraceEngine.Types.TraceEvents.KnownEventName.RUN_TASK */, + "RunTask" /* Trace.Types.Events.Name.RUN_TASK */, ]); this.textFilterInternal = new TimelineRegExp(); this.currentThreadSetting = Common.Settings.Settings.instance().createSetting('timeline-tree-current-thread', 0); @@ -313,7 +313,7 @@ export class TimelineTreeView extends UI.Widget.VBox { } this.linkifier.reset(); this.dataGrid.rootNode().removeChildren(); - if (!this.#traceParseData) { + if (!this.#parsedTrace) { this.updateDetailsForSelection(); return; } @@ -367,7 +367,7 @@ export class TimelineTreeView extends UI.Widget.VBox { if (!eventA || !eventB) { return 0; } - if (!this.#traceParseData) { + if (!this.#parsedTrace) { return 0; } const nameA = this.#eventNameForSorting(eventA); @@ -488,7 +488,7 @@ export class TimelineTreeView extends UI.Widget.VBox { return; } const searchRegex = searchConfig.toSearchRegex(); - this.searchResults = this.root.searchTree(event => TimelineUIUtils.testContentMatching(event, searchRegex.regex, this.#traceParseData || undefined)); + this.searchResults = this.root.searchTree(event => TimelineUIUtils.testContentMatching(event, searchRegex.regex, this.#parsedTrace || undefined)); this.searchableView.updateSearchMatchesCount(this.searchResults.length); } jumpToNextSearchResult() { @@ -554,10 +554,10 @@ export class GridNode extends DataGrid.SortableDataGrid.SortableDataGridNode { } else if (event) { name.textContent = TimelineUIUtils.eventTitle(event); - const traceData = this.treeView.traceParseData(); - const target = traceData ? targetForEvent(traceData, event) : null; + const parsedTrace = this.treeView.parsedTrace(); + const target = parsedTrace ? targetForEvent(parsedTrace, event) : null; const linkifier = this.treeView.linkifier; - const isFreshRecording = Boolean(traceData && Tracker.instance().recordingIsFresh(traceData)); + const isFreshRecording = Boolean(parsedTrace && Tracker.instance().recordingIsFresh(parsedTrace)); this.linkElement = TimelineUIUtils.linkifyTopCallFrame(event, target, linkifier, isFreshRecording); if (this.linkElement) { container.createChild('div', 'activity-link').appendChild(this.linkElement); @@ -566,7 +566,7 @@ export class GridNode extends DataGrid.SortableDataGrid.SortableDataGridNode { const eventCategory = eventStyle.category; UI.ARIAUtils.setLabel(icon, eventCategory.title); icon.style.backgroundColor = eventCategory.getComputedColorValue(); - if (TraceEngine.Types.Extensions.isSyntheticExtensionEntry(event)) { + if (Trace.Types.Extensions.isSyntheticExtensionEntry(event)) { icon.style.backgroundColor = Extensions.ExtensionUI.extensionEntryColor(event); } } @@ -584,13 +584,13 @@ export class GridNode extends DataGrid.SortableDataGrid.SortableDataGridNode { case 'start-time': { event = this.profileNode.event; - const traceParseData = this.treeView.traceParseData(); - if (!traceParseData) { + const parsedTrace = this.treeView.parsedTrace(); + if (!parsedTrace) { throw new Error('Unable to load trace data for tree view'); } - const timings = event && TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event); + const timings = event && Trace.Helpers.Timing.eventTimingsMilliSeconds(event); const startTime = timings?.startTime ?? 0; - value = startTime - TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceParseData.Meta.traceBounds.min); + value = startTime - Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min); } break; case 'self': @@ -718,7 +718,7 @@ export class AggregatedTimelineTreeView extends TimelineTreeView { case AggregatedTimelineTreeView.GroupBy.URL: break; case AggregatedTimelineTreeView.GroupBy.Frame: { - const frame = id ? this.traceParseData()?.PageFrames.frames.get(id) : undefined; + const frame = id ? this.parsedTrace()?.PageFrames.frames.get(id) : undefined; const frameName = frame ? TimelineUIUtils.displayNameForFrame(frame) : i18nString(UIStrings.page); return { name: frameName, color, icon: undefined }; } @@ -789,13 +789,13 @@ export class AggregatedTimelineTreeView extends TimelineTreeView { return this.domainByEvent.bind(this, groupBy); case GroupBy.URL: return (event) => { - const traceParsedData = this.traceParseData(); - return traceParsedData ? TraceEngine.Extras.URLForEntry.get(traceParsedData, event) ?? '' : ''; + const parsedTrace = this.parsedTrace(); + return parsedTrace ? Trace.Extras.URLForEntry.get(parsedTrace, event) ?? '' : ''; }; case GroupBy.Frame: return (event) => { - const frameId = TraceEngine.Helpers.Trace.frameIDForEvent(event); - return frameId || this.traceParseData()?.Meta.mainFrameId || ''; + const frameId = Trace.Helpers.Trace.frameIDForEvent(event); + return frameId || this.parsedTrace()?.Meta.mainFrameId || ''; }; default: console.assert(false, `Unexpected aggregation setting: ${groupBy}`); @@ -803,11 +803,11 @@ export class AggregatedTimelineTreeView extends TimelineTreeView { } } domainByEvent(groupBy, event) { - const traceParsedData = this.traceParseData(); - if (!traceParsedData) { + const parsedTrace = this.parsedTrace(); + if (!parsedTrace) { return ''; } - const url = TraceEngine.Extras.URLForEntry.get(traceParsedData, event); + const url = Trace.Extras.URLForEntry.get(parsedTrace, event); if (!url) { return ''; } diff --git a/public/panels/timeline/TimelineTreeView.js.map b/public/panels/timeline/TimelineTreeView.js.map index 3e8ba80bf..8dbb1a49d 100644 --- a/public/panels/timeline/TimelineTreeView.js.map +++ b/public/panels/timeline/TimelineTreeView.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineTreeView.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineTreeView.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2015 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as ThirdPartyWeb from '../../third_party/third-party-web/third-party-web.js';\nimport * as DataGrid from '../../ui/legacy/components/data_grid/data_grid.js';\nimport * as Components from '../../ui/legacy/components/utils/utils.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport {ActiveFilters} from './ActiveFilters.js';\nimport * as TimelineComponents from './components/components.js';\nimport * as Extensions from './extensions/extensions.js';\nimport {Tracker} from './FreshRecording.js';\nimport {targetForEvent} from './TargetForEvent.js';\nimport {TimelineRegExp} from './TimelineFilters.js';\nimport {type TimelineSelection} from './TimelineSelection.js';\nimport {TimelineUIUtils} from './TimelineUIUtils.js';\n\nconst UIStrings = {\n /**\n *@description Text for the performance of something\n */\n performance: 'Performance',\n /**\n *@description Time of a single activity, as opposed to the total time\n */\n selfTime: 'Self time',\n /**\n *@description Text for the total time of something\n */\n totalTime: 'Total time',\n /**\n *@description Text in Timeline Tree View of the Performance panel\n */\n activity: 'Activity',\n /**\n *@description Text of a DOM element in Timeline Tree View of the Performance panel\n */\n selectItemForDetails: 'Select item for details.',\n /**\n *@description Time in miliseconds\n *@example {30.1} PH1\n */\n fms: '{PH1} ms',\n /**\n *@description Number followed by percent sign\n *@example {20} PH1\n */\n percentPlaceholder: '{PH1} %',\n /**\n *@description Text in Timeline Tree View of the Performance panel\n */\n chromeExtensionsOverhead: '[`Chrome` extensions overhead]',\n /**\n * @description Text in Timeline Tree View of the Performance panel. The text is presented\n * when developers investigate the performance of a page. 'V8 Runtime' labels the time\n * spent in (i.e. runtime) the V8 JavaScript engine.\n */\n vRuntime: '[`V8` Runtime]',\n /**\n *@description Text in Timeline Tree View of the Performance panel\n */\n unattributed: '[unattributed]',\n /**\n *@description Text that refers to one or a group of webpages\n */\n page: 'Page',\n /**\n *@description Text in Timeline Tree View of the Performance panel\n */\n noGrouping: 'No grouping',\n /**\n *@description Text in Timeline Tree View of the Performance panel\n */\n groupByActivity: 'Group by activity',\n /**\n *@description Text in Timeline Tree View of the Performance panel\n */\n groupByCategory: 'Group by category',\n /**\n *@description Text in Timeline Tree View of the Performance panel\n */\n groupByDomain: 'Group by domain',\n /**\n *@description Text in Timeline Tree View of the Performance panel\n */\n groupByFrame: 'Group by frame',\n /**\n *@description Text in Timeline Tree View of the Performance panel\n */\n groupBySubdomain: 'Group by subdomain',\n /**\n *@description Text in Timeline Tree View of the Performance panel\n */\n groupByUrl: 'Group by URL',\n /**\n *@description Text in Timeline Tree View of the Performance panel\n */\n groupByThirdParties: 'Group by Third Parties',\n /**\n *@description Aria-label for grouping combo box in Timeline Details View\n */\n groupBy: 'Group by',\n /**\n * @description Title of the sidebar pane in the Performance panel which shows the stack (call\n * stack) where the program spent the most time (out of all the call stacks) while executing.\n */\n heaviestStack: 'Heaviest stack',\n /**\n * @description Tooltip for the the Heaviest stack sidebar toggle in the Timeline Tree View of the\n * Performance panel. Command to open/show the sidebar.\n */\n showHeaviestStack: 'Show heaviest stack',\n /**\n * @description Tooltip for the the Heaviest stack sidebar toggle in the Timeline Tree View of the\n * Performance panel. Command to close/hide the sidebar.\n */\n hideHeaviestStack: 'Hide heaviest stack',\n /**\n * @description Screen reader announcement when the heaviest stack sidebar is shown in the Performance panel.\n */\n heaviestStackShown: 'Heaviest stack sidebar shown',\n /**\n * @description Screen reader announcement when the heaviest stack sidebar is hidden in the Performance panel.\n */\n heaviestStackHidden: 'Heaviest stack sidebar hidden',\n /**\n *@description Data grid name for Timeline Stack data grids\n */\n timelineStack: 'Timeline stack',\n /**\n /*@description Text to search by matching case of the input button\n */\n matchCase: 'Match case',\n /**\n *@description Text for searching with regular expression button\n */\n useRegularExpression: 'Use regular expression',\n /**\n * @description Text for Match whole word button\n */\n matchWholeWord: 'Match whole word',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelineTreeView.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nexport class TimelineTreeView extends UI.Widget.VBox implements UI.SearchableView.Searchable {\n #selectedEvents: TraceEngine.Types.TraceEvents.TraceEventData[]|null;\n private searchResults: TimelineModel.TimelineProfileTree.Node[];\n linkifier!: Components.Linkifier.Linkifier;\n dataGrid!: DataGrid.SortableDataGrid.SortableDataGrid;\n private lastHoveredProfileNode!: TimelineModel.TimelineProfileTree.Node|null;\n private textFilterInternal!: TimelineRegExp;\n private taskFilter!: TimelineModel.TimelineModelFilter.ExclusiveNameFilter;\n protected startTime!: TraceEngine.Types.Timing.MilliSeconds;\n protected endTime!: TraceEngine.Types.Timing.MilliSeconds;\n splitWidget!: UI.SplitWidget.SplitWidget;\n detailsView!: UI.Widget.Widget;\n private searchableView!: UI.SearchableView.SearchableView;\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private currentThreadSetting?: Common.Settings.Setting;\n private lastSelectedNodeInternal?: TimelineModel.TimelineProfileTree.Node|null;\n private root?: TimelineModel.TimelineProfileTree.Node;\n private currentResult?: number;\n textFilterUI?: UI.Toolbar.ToolbarInput;\n private caseSensitiveButton: UI.Toolbar.ToolbarToggle|undefined;\n private regexButton: UI.Toolbar.ToolbarToggle|undefined;\n private matchWholeWord: UI.Toolbar.ToolbarToggle|undefined;\n\n #traceParseData: TraceEngine.Handlers.Types.TraceParseData|null = null;\n\n constructor() {\n super();\n this.#selectedEvents = null;\n this.element.classList.add('timeline-tree-view');\n\n this.searchResults = [];\n }\n\n #eventNameForSorting(event: TraceEngine.Types.TraceEvents.TraceEventData): string {\n const name = TimelineUIUtils.eventTitle(event) || event.name;\n if (!this.#traceParseData) {\n return name;\n }\n return name + ':@' + TraceEngine.Extras.URLForEntry.get(this.#traceParseData, event);\n }\n\n setSearchableView(searchableView: UI.SearchableView.SearchableView): void {\n this.searchableView = searchableView;\n }\n\n setModelWithEvents(\n selectedEvents: TraceEngine.Types.TraceEvents.TraceEventData[]|null,\n traceParseData: TraceEngine.Handlers.Types.TraceParseData|null = null,\n ): void {\n this.#traceParseData = traceParseData;\n this.#selectedEvents = selectedEvents;\n }\n\n traceParseData(): TraceEngine.Handlers.Types.TraceParseData|null {\n return this.#traceParseData;\n }\n\n init(): void {\n this.linkifier = new Components.Linkifier.Linkifier();\n\n this.taskFilter = new TimelineModel.TimelineModelFilter.ExclusiveNameFilter([\n TraceEngine.Types.TraceEvents.KnownEventName.RUN_TASK,\n ]);\n this.textFilterInternal = new TimelineRegExp();\n\n this.currentThreadSetting = Common.Settings.Settings.instance().createSetting('timeline-tree-current-thread', 0);\n this.currentThreadSetting.addChangeListener(this.refreshTree, this);\n\n const columns = ([] as DataGrid.DataGrid.ColumnDescriptor[]);\n this.populateColumns(columns);\n\n this.splitWidget = new UI.SplitWidget.SplitWidget(true, true, 'timeline-tree-view-details-split-widget');\n const mainView = new UI.Widget.VBox();\n const toolbar = new UI.Toolbar.Toolbar('', mainView.element);\n toolbar.element.setAttribute('jslog', `${VisualLogging.toolbar()}`);\n toolbar.makeWrappable(true);\n this.populateToolbar(toolbar);\n\n this.dataGrid = new DataGrid.SortableDataGrid.SortableDataGrid({\n displayName: i18nString(UIStrings.performance),\n columns,\n refreshCallback: undefined,\n editCallback: undefined,\n deleteCallback: undefined,\n });\n this.dataGrid.addEventListener(DataGrid.DataGrid.Events.SORTING_CHANGED, this.sortingChanged, this);\n this.dataGrid.element.addEventListener('mousemove', this.onMouseMove.bind(this), true);\n this.dataGrid.setResizeMethod(DataGrid.DataGrid.ResizeMethod.LAST);\n this.dataGrid.setRowContextMenuCallback(this.onContextMenu.bind(this));\n this.dataGrid.asWidget().show(mainView.element);\n this.dataGrid.addEventListener(DataGrid.DataGrid.Events.SELECTED_NODE, this.updateDetailsForSelection, this);\n\n this.detailsView = new UI.Widget.VBox();\n this.detailsView.element.classList.add('timeline-details-view', 'timeline-details-view-body');\n this.splitWidget.setMainWidget(mainView);\n this.splitWidget.setSidebarWidget(this.detailsView);\n this.splitWidget.hideSidebar();\n this.splitWidget.show(this.element);\n this.splitWidget.addEventListener(UI.SplitWidget.Events.SHOW_MODE_CHANGED, this.onShowModeChanged, this);\n\n this.lastSelectedNodeInternal;\n }\n\n lastSelectedNode(): TimelineModel.TimelineProfileTree.Node|null|undefined {\n return this.lastSelectedNodeInternal;\n }\n\n updateContents(selection: TimelineSelection): void {\n this.setRange(selection.startTime, selection.endTime);\n }\n\n setRange(startTime: TraceEngine.Types.Timing.MilliSeconds, endTime: TraceEngine.Types.Timing.MilliSeconds): void {\n this.startTime = startTime;\n this.endTime = endTime;\n this.refreshTree();\n }\n\n filters(): TimelineModel.TimelineModelFilter.TimelineModelFilter[] {\n return [this.taskFilter, this.textFilterInternal, ...(ActiveFilters.instance().activeFilters())];\n }\n\n filtersWithoutTextFilter(): TimelineModel.TimelineModelFilter.TimelineModelFilter[] {\n return [this.taskFilter, ...(ActiveFilters.instance().activeFilters())];\n }\n\n textFilter(): TimelineRegExp {\n return this.textFilterInternal;\n }\n\n exposePercentages(): boolean {\n return false;\n }\n\n populateToolbar(toolbar: UI.Toolbar.Toolbar): void {\n this.caseSensitiveButton =\n new UI.Toolbar.ToolbarToggle(i18nString(UIStrings.matchCase), 'match-case', undefined, 'match-case');\n this.caseSensitiveButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, () => {\n this.#filterChanged();\n }, this);\n toolbar.appendToolbarItem(this.caseSensitiveButton);\n\n this.regexButton = new UI.Toolbar.ToolbarToggle(\n i18nString(UIStrings.useRegularExpression), 'regular-expression', undefined, 'regular-expression');\n this.regexButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, () => {\n this.#filterChanged();\n }, this);\n toolbar.appendToolbarItem(this.regexButton);\n\n this.matchWholeWord = new UI.Toolbar.ToolbarToggle(\n i18nString(UIStrings.matchWholeWord), 'match-whole-word', undefined, 'match-whole-word');\n this.matchWholeWord.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, () => {\n this.#filterChanged();\n }, this);\n toolbar.appendToolbarItem(this.matchWholeWord);\n\n const textFilterUI = new UI.Toolbar.ToolbarFilter();\n this.textFilterUI = textFilterUI;\n textFilterUI.addEventListener(UI.Toolbar.ToolbarInput.Event.TEXT_CHANGED, this.#filterChanged, this);\n toolbar.appendToolbarItem(textFilterUI);\n }\n\n selectedEvents(): TraceEngine.Types.TraceEvents.TraceEventData[] {\n // TODO: can we make this type readonly?\n return this.#selectedEvents || [];\n }\n\n onHover(_node: TimelineModel.TimelineProfileTree.Node|null): void {\n }\n\n appendContextMenuItems(_contextMenu: UI.ContextMenu.ContextMenu, _node: TimelineModel.TimelineProfileTree.Node):\n void {\n }\n\n selectProfileNode(treeNode: TimelineModel.TimelineProfileTree.Node, suppressSelectedEvent: boolean): void {\n const pathToRoot = [];\n let node: (TimelineModel.TimelineProfileTree.Node|null)|TimelineModel.TimelineProfileTree.Node = treeNode;\n for (; node; node = node.parent) {\n pathToRoot.push(node);\n }\n for (let i = pathToRoot.length - 1; i > 0; --i) {\n const gridNode = this.dataGridNodeForTreeNode(pathToRoot[i]);\n if (gridNode && gridNode.dataGrid) {\n gridNode.expand();\n }\n }\n const gridNode = this.dataGridNodeForTreeNode(treeNode);\n if (gridNode && gridNode.dataGrid) {\n gridNode.reveal();\n gridNode.select(suppressSelectedEvent);\n }\n }\n\n refreshTree(): void {\n if (!this.element.parentElement) {\n // This function can be called in different views (Bottom-Up and\n // Call Tree) by the same single event whenever the group-by\n // dropdown changes value. Thus, we bail out whenever the view is\n // not visible, which we know if the related element is detached\n // from the document.\n return;\n }\n this.linkifier.reset();\n this.dataGrid.rootNode().removeChildren();\n if (!this.#traceParseData) {\n this.updateDetailsForSelection();\n return;\n }\n this.root = this.buildTree();\n const children = this.root.children();\n let maxSelfTime = 0;\n let maxTotalTime = 0;\n const totalUsedTime = this.root.totalTime - this.root.selfTime;\n for (const child of children.values()) {\n maxSelfTime = Math.max(maxSelfTime, child.selfTime);\n maxTotalTime = Math.max(maxTotalTime, child.totalTime);\n }\n for (const child of children.values()) {\n // Exclude the idle time off the total calculation.\n const gridNode = new TreeGridNode(child, totalUsedTime, maxSelfTime, maxTotalTime, this);\n this.dataGrid.insertChild(gridNode);\n }\n this.sortingChanged();\n this.updateDetailsForSelection();\n if (this.searchableView) {\n this.searchableView.refreshSearch();\n }\n const rootNode = this.dataGrid.rootNode();\n if (rootNode.children.length > 0) {\n rootNode.children[0].select(/* supressSelectedEvent */ true);\n }\n }\n\n buildTree(): TimelineModel.TimelineProfileTree.Node {\n throw new Error('Not Implemented');\n }\n\n buildTopDownTree(\n doNotAggregate: boolean, groupIdCallback: ((arg0: TraceEngine.Types.TraceEvents.TraceEventData) => string)|null):\n TimelineModel.TimelineProfileTree.Node {\n return new TimelineModel.TimelineProfileTree.TopDownRootNode(\n this.selectedEvents(), this.filters(), this.startTime, this.endTime, doNotAggregate, groupIdCallback);\n }\n\n populateColumns(columns: DataGrid.DataGrid.ColumnDescriptor[]): void {\n columns.push(\n ({id: 'self', title: i18nString(UIStrings.selfTime), width: '120px', fixedWidth: true, sortable: true} as\n DataGrid.DataGrid.ColumnDescriptor));\n columns.push(\n ({id: 'total', title: i18nString(UIStrings.totalTime), width: '120px', fixedWidth: true, sortable: true} as\n DataGrid.DataGrid.ColumnDescriptor));\n columns.push(\n ({id: 'activity', title: i18nString(UIStrings.activity), disclosure: true, sortable: true} as\n DataGrid.DataGrid.ColumnDescriptor));\n }\n\n private sortingChanged(): void {\n const columnId = this.dataGrid.sortColumnId();\n if (!columnId) {\n return;\n }\n let sortFunction;\n\n const compareNameSortFn =\n (a: DataGrid.SortableDataGrid.SortableDataGridNode,\n b: DataGrid.SortableDataGrid.SortableDataGridNode): number => {\n const nodeA = (a as TreeGridNode);\n const nodeB = (b as TreeGridNode);\n const eventA = nodeA.profileNode.event;\n const eventB = nodeB.profileNode.event;\n // Should not happen, but guard against the nodes not having events.\n if (!eventA || !eventB) {\n return 0;\n }\n if (!this.#traceParseData) {\n return 0;\n }\n const nameA = this.#eventNameForSorting(eventA);\n const nameB = this.#eventNameForSorting(eventB);\n return nameA.localeCompare(nameB);\n };\n\n switch (columnId) {\n case 'start-time':\n sortFunction = compareStartTime;\n break;\n case 'self':\n sortFunction = compareSelfTime;\n break;\n case 'total':\n sortFunction = compareTotalTime;\n break;\n case 'activity':\n sortFunction = compareNameSortFn;\n break;\n default:\n console.assert(false, 'Unknown sort field: ' + columnId);\n return;\n }\n this.dataGrid.sortNodes(sortFunction, !this.dataGrid.isSortOrderAscending());\n\n function compareSelfTime(\n a: DataGrid.SortableDataGrid.SortableDataGridNode,\n b: DataGrid.SortableDataGrid.SortableDataGridNode): number {\n const nodeA = a as TreeGridNode;\n const nodeB = b as TreeGridNode;\n return nodeA.profileNode.selfTime - nodeB.profileNode.selfTime;\n }\n\n function compareStartTime(\n a: DataGrid.SortableDataGrid.SortableDataGridNode,\n b: DataGrid.SortableDataGrid.SortableDataGridNode): number {\n const nodeA = (a as TreeGridNode);\n const nodeB = (b as TreeGridNode);\n const eventA = nodeA.profileNode.event;\n const eventB = nodeB.profileNode.event;\n // Should not happen, but guard against the nodes not having events.\n if (!eventA || !eventB) {\n return 0;\n }\n return eventA.ts - eventB.ts;\n }\n\n function compareTotalTime(\n a: DataGrid.SortableDataGrid.SortableDataGridNode,\n b: DataGrid.SortableDataGrid.SortableDataGridNode): number {\n const nodeA = a as TreeGridNode;\n const nodeB = b as TreeGridNode;\n return nodeA.profileNode.totalTime - nodeB.profileNode.totalTime;\n }\n }\n\n #filterChanged(): void {\n const searchQuery = this.textFilterUI && this.textFilterUI.value();\n const caseSensitive = this.caseSensitiveButton !== undefined && this.caseSensitiveButton.isToggled();\n const isRegex = this.regexButton !== undefined && this.regexButton.isToggled();\n const matchWholeWord = this.matchWholeWord !== undefined && this.matchWholeWord.isToggled();\n\n this.textFilterInternal.setRegExp(\n searchQuery ? Platform.StringUtilities.createSearchRegex(searchQuery, caseSensitive, isRegex, matchWholeWord) :\n null);\n this.refreshTree();\n }\n\n private onShowModeChanged(): void {\n if (this.splitWidget.showMode() === UI.SplitWidget.ShowMode.ONLY_MAIN) {\n return;\n }\n this.lastSelectedNodeInternal = undefined;\n this.updateDetailsForSelection();\n }\n\n private updateDetailsForSelection(): void {\n const selectedNode = this.dataGrid.selectedNode ? (this.dataGrid.selectedNode as TreeGridNode).profileNode : null;\n if (selectedNode === this.lastSelectedNodeInternal) {\n return;\n }\n this.lastSelectedNodeInternal = selectedNode;\n if (this.splitWidget.showMode() === UI.SplitWidget.ShowMode.ONLY_MAIN) {\n return;\n }\n this.detailsView.detachChildWidgets();\n this.detailsView.element.removeChildren();\n if (selectedNode && this.showDetailsForNode(selectedNode)) {\n return;\n }\n const banner = this.detailsView.element.createChild('div', 'full-widget-dimmed-banner');\n UI.UIUtils.createTextChild(banner, i18nString(UIStrings.selectItemForDetails));\n }\n\n showDetailsForNode(_node: TimelineModel.TimelineProfileTree.Node): boolean {\n return false;\n }\n\n private onMouseMove(event: Event): void {\n const gridNode = event.target && (event.target instanceof Node) ?\n (this.dataGrid.dataGridNodeFromNode((event.target as Node))) :\n null;\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // @ts-expect-error\n const profileNode = gridNode && gridNode._profileNode;\n if (profileNode === this.lastHoveredProfileNode) {\n return;\n }\n this.lastHoveredProfileNode = profileNode;\n this.onHover(profileNode);\n }\n\n private onContextMenu(\n contextMenu: UI.ContextMenu.ContextMenu, eventGridNode: DataGrid.DataGrid.DataGridNode): void {\n const gridNode = (eventGridNode as GridNode);\n if (gridNode.linkElement) {\n contextMenu.appendApplicableItems(gridNode.linkElement);\n }\n const profileNode = gridNode.profileNode;\n if (profileNode) {\n this.appendContextMenuItems(contextMenu, profileNode);\n }\n }\n\n dataGridNodeForTreeNode(treeNode: TimelineModel.TimelineProfileTree.Node): GridNode|null {\n return profileNodeToTreeGridNode.get(treeNode) || null;\n }\n\n // UI.SearchableView.Searchable implementation\n\n onSearchCanceled(): void {\n this.searchResults = [];\n this.currentResult = 0;\n }\n\n performSearch(searchConfig: UI.SearchableView.SearchConfig, _shouldJump: boolean, _jumpBackwards?: boolean): void {\n this.searchResults = [];\n this.currentResult = 0;\n if (!this.root) {\n return;\n }\n const searchRegex = searchConfig.toSearchRegex();\n this.searchResults = this.root.searchTree(\n event => TimelineUIUtils.testContentMatching(event, searchRegex.regex, this.#traceParseData || undefined));\n this.searchableView.updateSearchMatchesCount(this.searchResults.length);\n }\n\n jumpToNextSearchResult(): void {\n if (!this.searchResults.length || this.currentResult === undefined) {\n return;\n }\n this.selectProfileNode(this.searchResults[this.currentResult], false);\n this.currentResult = Platform.NumberUtilities.mod(this.currentResult + 1, this.searchResults.length);\n }\n\n jumpToPreviousSearchResult(): void {\n if (!this.searchResults.length || this.currentResult === undefined) {\n return;\n }\n this.selectProfileNode(this.searchResults[this.currentResult], false);\n this.currentResult = Platform.NumberUtilities.mod(this.currentResult - 1, this.searchResults.length);\n }\n\n supportsCaseSensitiveSearch(): boolean {\n return true;\n }\n\n supportsRegexSearch(): boolean {\n return true;\n }\n}\n\nexport class GridNode extends DataGrid.SortableDataGrid.SortableDataGridNode {\n protected populated: boolean;\n profileNode: TimelineModel.TimelineProfileTree.Node;\n protected treeView: TimelineTreeView;\n protected grandTotalTime: number;\n protected maxSelfTime: number;\n protected maxTotalTime: number;\n linkElement: Element|null;\n\n constructor(\n profileNode: TimelineModel.TimelineProfileTree.Node, grandTotalTime: number, maxSelfTime: number,\n maxTotalTime: number, treeView: TimelineTreeView) {\n super(null, false);\n this.populated = false;\n this.profileNode = profileNode;\n this.treeView = treeView;\n this.grandTotalTime = grandTotalTime;\n this.maxSelfTime = maxSelfTime;\n this.maxTotalTime = maxTotalTime;\n this.linkElement = null;\n }\n\n override createCell(columnId: string): HTMLElement {\n if (columnId === 'activity') {\n return this.createNameCell(columnId);\n }\n return this.createValueCell(columnId) || super.createCell(columnId);\n }\n\n private createNameCell(columnId: string): HTMLElement {\n const cell = this.createTD(columnId);\n const container = cell.createChild('div', 'name-container');\n const iconContainer = container.createChild('div', 'activity-icon-container');\n const icon = iconContainer.createChild('div', 'activity-icon');\n const name = container.createChild('div', 'activity-name');\n const event = this.profileNode.event;\n if (this.profileNode.isGroupNode()) {\n const treeView = (this.treeView as AggregatedTimelineTreeView);\n const info = treeView.displayInfoForGroupNode(this.profileNode);\n name.textContent = info.name;\n icon.style.backgroundColor = info.color;\n if (info.icon) {\n iconContainer.insertBefore(info.icon, icon);\n }\n } else if (event) {\n name.textContent = TimelineUIUtils.eventTitle(event);\n const traceData = this.treeView.traceParseData();\n const target = traceData ? targetForEvent(traceData, event) : null;\n const linkifier = this.treeView.linkifier;\n const isFreshRecording = Boolean(traceData && Tracker.instance().recordingIsFresh(traceData));\n this.linkElement = TimelineUIUtils.linkifyTopCallFrame(event, target, linkifier, isFreshRecording);\n if (this.linkElement) {\n container.createChild('div', 'activity-link').appendChild(this.linkElement);\n }\n const eventStyle = TimelineUIUtils.eventStyle(event);\n const eventCategory = eventStyle.category;\n UI.ARIAUtils.setLabel(icon, eventCategory.title);\n icon.style.backgroundColor = eventCategory.getComputedColorValue();\n if (TraceEngine.Types.Extensions.isSyntheticExtensionEntry(event)) {\n icon.style.backgroundColor = Extensions.ExtensionUI.extensionEntryColor(event);\n }\n }\n return cell;\n }\n\n private createValueCell(columnId: string): HTMLElement|null {\n if (columnId !== 'self' && columnId !== 'total' && columnId !== 'start-time') {\n return null;\n }\n\n let showPercents = false;\n let value: number;\n let maxTime: number|undefined;\n let event: TraceEngine.Types.TraceEvents.TraceEventData|null;\n switch (columnId) {\n case 'start-time': {\n event = this.profileNode.event;\n const traceParseData = this.treeView.traceParseData();\n if (!traceParseData) {\n throw new Error('Unable to load trace data for tree view');\n }\n const timings = event && TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event);\n const startTime = timings?.startTime ?? 0;\n value = startTime - TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceParseData.Meta.traceBounds.min);\n } break;\n case 'self':\n value = this.profileNode.selfTime;\n maxTime = this.maxSelfTime;\n showPercents = true;\n break;\n case 'total':\n value = this.profileNode.totalTime;\n maxTime = this.maxTotalTime;\n showPercents = true;\n break;\n default:\n return null;\n }\n const cell = this.createTD(columnId);\n cell.className = 'numeric-column';\n cell.setAttribute('title', i18nString(UIStrings.fms, {PH1: value.toFixed(4)}));\n const textDiv = cell.createChild('div');\n textDiv.createChild('span').textContent = i18nString(UIStrings.fms, {PH1: value.toFixed(1)});\n\n if (showPercents && this.treeView.exposePercentages()) {\n textDiv.createChild('span', 'percent-column').textContent =\n i18nString(UIStrings.percentPlaceholder, {PH1: (value / this.grandTotalTime * 100).toFixed(1)});\n }\n if (maxTime) {\n textDiv.classList.add('background-percent-bar');\n cell.createChild('div', 'background-bar-container').createChild('div', 'background-bar').style.width =\n (value * 100 / maxTime).toFixed(1) + '%';\n }\n return cell;\n }\n}\n\nexport class TreeGridNode extends GridNode {\n constructor(\n profileNode: TimelineModel.TimelineProfileTree.Node, grandTotalTime: number, maxSelfTime: number,\n maxTotalTime: number, treeView: TimelineTreeView) {\n super(profileNode, grandTotalTime, maxSelfTime, maxTotalTime, treeView);\n this.setHasChildren(this.profileNode.hasChildren());\n profileNodeToTreeGridNode.set(profileNode, this);\n }\n\n override populate(): void {\n if (this.populated) {\n return;\n }\n this.populated = true;\n if (!this.profileNode.children) {\n return;\n }\n for (const node of this.profileNode.children().values()) {\n const gridNode = new TreeGridNode(node, this.grandTotalTime, this.maxSelfTime, this.maxTotalTime, this.treeView);\n this.insertChildOrdered(gridNode);\n }\n }\n}\n\nconst profileNodeToTreeGridNode = new WeakMap();\n\nexport class AggregatedTimelineTreeView extends TimelineTreeView {\n protected readonly groupBySetting: Common.Settings.Setting;\n private readonly stackView: TimelineStackView;\n private executionContextNamesByOrigin = new Map();\n\n constructor() {\n super();\n this.groupBySetting = Common.Settings.Settings.instance().createSetting(\n 'timeline-tree-group-by', AggregatedTimelineTreeView.GroupBy.None);\n this.groupBySetting.addChangeListener(this.refreshTree.bind(this));\n this.init();\n this.stackView = new TimelineStackView(this);\n this.stackView.addEventListener(TimelineStackView.Events.SELECTION_CHANGED, this.onStackViewSelectionChanged, this);\n }\n\n setGroupBySettingForTests(groupBy: AggregatedTimelineTreeView.GroupBy): void {\n this.groupBySetting.set(groupBy);\n }\n\n override updateContents(selection: TimelineSelection): void {\n this.updateExtensionResolver();\n super.updateContents(selection);\n const rootNode = this.dataGrid.rootNode();\n if (rootNode.children.length) {\n rootNode.children[0].select(/* suppressSelectedEvent */ true);\n }\n }\n\n private updateExtensionResolver(): void {\n this.executionContextNamesByOrigin = new Map();\n for (const runtimeModel of SDK.TargetManager.TargetManager.instance().models(SDK.RuntimeModel.RuntimeModel)) {\n for (const context of runtimeModel.executionContexts()) {\n this.executionContextNamesByOrigin.set(context.origin, context.name);\n }\n }\n }\n\n private beautifyDomainName(this: AggregatedTimelineTreeView, name: string): string {\n if (AggregatedTimelineTreeView.isExtensionInternalURL(name as Platform.DevToolsPath.UrlString)) {\n name = i18nString(UIStrings.chromeExtensionsOverhead);\n } else if (AggregatedTimelineTreeView.isV8NativeURL(name as Platform.DevToolsPath.UrlString)) {\n name = i18nString(UIStrings.vRuntime);\n } else if (name.startsWith('chrome-extension')) {\n name = this.executionContextNamesByOrigin.get(name as Platform.DevToolsPath.UrlString) || name;\n }\n return name;\n }\n\n displayInfoForGroupNode(node: TimelineModel.TimelineProfileTree.Node): {\n name: string,\n color: string,\n icon: (Element|undefined),\n } {\n const categories = TimelineComponents.EntryStyles.getCategoryStyles();\n const color = node.id && node.event ? TimelineUIUtils.eventColor(node.event) : categories['other'].color;\n const unattributed = i18nString(UIStrings.unattributed);\n\n const id = typeof node.id === 'symbol' ? undefined : node.id;\n\n switch (this.groupBySetting.get()) {\n case AggregatedTimelineTreeView.GroupBy.Category: {\n const idIsValid = id && TimelineComponents.EntryStyles.stringIsEventCategory(id);\n const category = idIsValid ? categories[id] || categories['other'] : {title: unattributed, color: unattributed};\n return {name: category.title, color: category.color, icon: undefined};\n }\n\n case AggregatedTimelineTreeView.GroupBy.Domain:\n case AggregatedTimelineTreeView.GroupBy.Subdomain:\n case AggregatedTimelineTreeView.GroupBy.ThirdParties: {\n const domainName = id ? this.beautifyDomainName(id) : undefined;\n return {name: domainName || unattributed, color, icon: undefined};\n }\n\n case AggregatedTimelineTreeView.GroupBy.EventName: {\n if (!node.event) {\n throw new Error('Unable to find event for group by operation');\n }\n const name = TimelineUIUtils.eventTitle(node.event);\n return {\n name,\n color,\n icon: undefined,\n };\n }\n\n case AggregatedTimelineTreeView.GroupBy.URL:\n break;\n\n case AggregatedTimelineTreeView.GroupBy.Frame: {\n const frame = id ? this.traceParseData()?.PageFrames.frames.get(id) : undefined;\n const frameName = frame ? TimelineUIUtils.displayNameForFrame(frame) : i18nString(UIStrings.page);\n return {name: frameName, color, icon: undefined};\n }\n\n default:\n console.assert(false, 'Unexpected grouping type');\n }\n return {name: id || unattributed, color, icon: undefined};\n }\n\n override populateToolbar(toolbar: UI.Toolbar.Toolbar): void {\n super.populateToolbar(toolbar);\n const groupBy = AggregatedTimelineTreeView.GroupBy;\n const options = [\n {label: i18nString(UIStrings.noGrouping), value: groupBy.None},\n {label: i18nString(UIStrings.groupByActivity), value: groupBy.EventName},\n {label: i18nString(UIStrings.groupByCategory), value: groupBy.Category},\n {label: i18nString(UIStrings.groupByDomain), value: groupBy.Domain},\n {label: i18nString(UIStrings.groupByFrame), value: groupBy.Frame},\n {label: i18nString(UIStrings.groupBySubdomain), value: groupBy.Subdomain},\n {label: i18nString(UIStrings.groupByUrl), value: groupBy.URL},\n {label: i18nString(UIStrings.groupByThirdParties), value: groupBy.ThirdParties},\n ];\n toolbar.appendToolbarItem(\n new UI.Toolbar.ToolbarSettingComboBox(options, this.groupBySetting, i18nString(UIStrings.groupBy)));\n toolbar.appendSpacer();\n toolbar.appendToolbarItem(this.splitWidget.createShowHideSidebarButton(\n i18nString(UIStrings.showHeaviestStack), i18nString(UIStrings.hideHeaviestStack),\n i18nString(UIStrings.heaviestStackShown), i18nString(UIStrings.heaviestStackHidden)));\n }\n\n private buildHeaviestStack(treeNode: TimelineModel.TimelineProfileTree.Node):\n TimelineModel.TimelineProfileTree.Node[] {\n console.assert(Boolean(treeNode.parent), 'Attempt to build stack for tree root');\n let result: TimelineModel.TimelineProfileTree.Node[] = [];\n // Do not add root to the stack, as it's the tree itself.\n for (let node: TimelineModel.TimelineProfileTree.Node = treeNode; node && node.parent; node = node.parent) {\n result.push(node);\n }\n result = result.reverse();\n for (let node: TimelineModel.TimelineProfileTree.Node = treeNode;\n node && node.children() && node.children().size;) {\n const children = Array.from(node.children().values());\n node = children.reduce((a, b) => a.totalTime > b.totalTime ? a : b);\n result.push(node);\n }\n return result;\n }\n\n override exposePercentages(): boolean {\n return true;\n }\n\n private onStackViewSelectionChanged(): void {\n const treeNode = this.stackView.selectedTreeNode();\n if (treeNode) {\n this.selectProfileNode(treeNode, true);\n }\n }\n\n override showDetailsForNode(node: TimelineModel.TimelineProfileTree.Node): boolean {\n const stack = this.buildHeaviestStack(node);\n this.stackView.setStack(stack, node);\n this.stackView.show(this.detailsView.element);\n return true;\n }\n\n protected groupingFunction(groupBy: AggregatedTimelineTreeView.GroupBy):\n ((arg0: TraceEngine.Types.TraceEvents.TraceEventData) => string)|null {\n const GroupBy = AggregatedTimelineTreeView.GroupBy;\n switch (groupBy) {\n case GroupBy.None:\n return null;\n case GroupBy.EventName:\n return (event: TraceEngine.Types.TraceEvents.TraceEventData) => TimelineUIUtils.eventStyle(event).title;\n case GroupBy.Category:\n return (event: TraceEngine.Types.TraceEvents.TraceEventData) => TimelineUIUtils.eventStyle(event).category.name;\n case GroupBy.Subdomain:\n case GroupBy.Domain:\n case GroupBy.ThirdParties:\n return this.domainByEvent.bind(this, groupBy);\n case GroupBy.URL:\n return (event: TraceEngine.Types.TraceEvents.TraceEventData) => {\n const traceParsedData = this.traceParseData();\n return traceParsedData ? TraceEngine.Extras.URLForEntry.get(traceParsedData, event) ?? '' : '';\n };\n case GroupBy.Frame:\n return (event: TraceEngine.Types.TraceEvents.TraceEventData) => {\n const frameId = TraceEngine.Helpers.Trace.frameIDForEvent(event);\n return frameId || this.traceParseData()?.Meta.mainFrameId || '';\n };\n default:\n console.assert(false, `Unexpected aggregation setting: ${groupBy}`);\n return null;\n }\n }\n\n private domainByEvent(\n groupBy: AggregatedTimelineTreeView.GroupBy, event: TraceEngine.Types.TraceEvents.TraceEventData): string {\n const traceParsedData = this.traceParseData();\n if (!traceParsedData) {\n return '';\n }\n const url = TraceEngine.Extras.URLForEntry.get(traceParsedData, event);\n if (!url) {\n return '';\n }\n if (AggregatedTimelineTreeView.isExtensionInternalURL(url)) {\n return AggregatedTimelineTreeView.extensionInternalPrefix;\n }\n if (AggregatedTimelineTreeView.isV8NativeURL(url)) {\n return AggregatedTimelineTreeView.v8NativePrefix;\n }\n const parsedURL = Common.ParsedURL.ParsedURL.fromString(url);\n if (!parsedURL) {\n return '';\n }\n if (parsedURL.scheme === 'chrome-extension') {\n return parsedURL.scheme + '://' + parsedURL.host;\n }\n if (groupBy === AggregatedTimelineTreeView.GroupBy.ThirdParties) {\n const entity = ThirdPartyWeb.ThirdPartyWeb.getEntity(url);\n if (!entity) {\n return parsedURL.host;\n }\n return entity.name;\n }\n if (groupBy === AggregatedTimelineTreeView.GroupBy.Subdomain) {\n return parsedURL.host;\n }\n if (/^[.0-9]+$/.test(parsedURL.host)) {\n return parsedURL.host;\n }\n const domainMatch = /([^.]*\\.)?[^.]*$/.exec(parsedURL.host);\n return domainMatch && domainMatch[0] || '';\n }\n\n private static isExtensionInternalURL(url: Platform.DevToolsPath.UrlString): boolean {\n return url.startsWith(AggregatedTimelineTreeView.extensionInternalPrefix);\n }\n\n private static isV8NativeURL(url: Platform.DevToolsPath.UrlString): boolean {\n return url.startsWith(AggregatedTimelineTreeView.v8NativePrefix);\n }\n\n private static readonly extensionInternalPrefix = 'extensions::';\n private static readonly v8NativePrefix = 'native ';\n}\nexport namespace AggregatedTimelineTreeView {\n export enum GroupBy {\n /* eslint-disable @typescript-eslint/naming-convention -- Used by web_tests. */\n None = 'None',\n EventName = 'EventName',\n Category = 'Category',\n Domain = 'Domain',\n Subdomain = 'Subdomain',\n URL = 'URL',\n Frame = 'Frame',\n ThirdParties = 'ThirdParties',\n /* eslint-enable @typescript-eslint/naming-convention */\n }\n}\n\nexport class CallTreeTimelineTreeView extends AggregatedTimelineTreeView {\n constructor() {\n super();\n this.element.setAttribute('jslog', `${VisualLogging.pane('call-tree').track({resize: true})}`);\n this.dataGrid.markColumnAsSortedBy('total', DataGrid.DataGrid.Order.Descending);\n }\n\n override buildTree(): TimelineModel.TimelineProfileTree.Node {\n const grouping = this.groupBySetting.get();\n return this.buildTopDownTree(false, this.groupingFunction(grouping));\n }\n}\n\nexport class BottomUpTimelineTreeView extends AggregatedTimelineTreeView {\n constructor() {\n super();\n this.element.setAttribute('jslog', `${VisualLogging.pane('bottom-up').track({resize: true})}`);\n this.dataGrid.markColumnAsSortedBy('self', DataGrid.DataGrid.Order.Descending);\n }\n\n override buildTree(): TimelineModel.TimelineProfileTree.Node {\n return new TimelineModel.TimelineProfileTree.BottomUpRootNode(\n this.selectedEvents(), this.textFilter(), this.filtersWithoutTextFilter(), this.startTime, this.endTime,\n this.groupingFunction(this.groupBySetting.get()));\n }\n}\n\nexport class TimelineStackView extends\n Common.ObjectWrapper.eventMixin(UI.Widget.VBox) {\n private readonly treeView: TimelineTreeView;\n private readonly dataGrid: DataGrid.ViewportDataGrid.ViewportDataGrid;\n\n constructor(treeView: TimelineTreeView) {\n super();\n const header = this.element.createChild('div', 'timeline-stack-view-header');\n header.textContent = i18nString(UIStrings.heaviestStack);\n this.treeView = treeView;\n const columns = ([\n {id: 'total', title: i18nString(UIStrings.totalTime), fixedWidth: true, width: '110px'},\n {id: 'activity', title: i18nString(UIStrings.activity)},\n ] as DataGrid.DataGrid.ColumnDescriptor[]);\n this.dataGrid = new DataGrid.ViewportDataGrid.ViewportDataGrid({\n displayName: i18nString(UIStrings.timelineStack),\n columns,\n deleteCallback: undefined,\n editCallback: undefined,\n refreshCallback: undefined,\n });\n this.dataGrid.setResizeMethod(DataGrid.DataGrid.ResizeMethod.LAST);\n this.dataGrid.addEventListener(DataGrid.DataGrid.Events.SELECTED_NODE, this.onSelectionChanged, this);\n this.dataGrid.asWidget().show(this.element);\n }\n\n setStack(stack: TimelineModel.TimelineProfileTree.Node[], selectedNode: TimelineModel.TimelineProfileTree.Node):\n void {\n const rootNode = this.dataGrid.rootNode();\n rootNode.removeChildren();\n let nodeToReveal: GridNode|null = null;\n const totalTime = Math.max.apply(Math, stack.map(node => node.totalTime));\n for (const node of stack) {\n const gridNode = new GridNode(node, totalTime, totalTime, totalTime, this.treeView);\n rootNode.appendChild(gridNode);\n if (node === selectedNode) {\n nodeToReveal = gridNode;\n }\n }\n if (nodeToReveal) {\n nodeToReveal.revealAndSelect();\n }\n }\n\n selectedTreeNode(): TimelineModel.TimelineProfileTree.Node|null {\n const selectedNode = this.dataGrid.selectedNode;\n return selectedNode && (selectedNode as GridNode).profileNode;\n }\n\n private onSelectionChanged(): void {\n this.dispatchEventToListeners(TimelineStackView.Events.SELECTION_CHANGED);\n }\n}\n\nexport namespace TimelineStackView {\n export const enum Events {\n SELECTION_CHANGED = 'SelectionChanged',\n }\n\n export type EventTypes = {\n [Events.SELECTION_CHANGED]: void,\n };\n}\n"]} \ No newline at end of file +{"version":3,"file":"TimelineTreeView.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineTreeView.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2015 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as ThirdPartyWeb from '../../third_party/third-party-web/third-party-web.js';\nimport * as DataGrid from '../../ui/legacy/components/data_grid/data_grid.js';\nimport * as Components from '../../ui/legacy/components/utils/utils.js';\nimport * as UI from '../../ui/legacy/legacy.js';\nimport * as VisualLogging from '../../ui/visual_logging/visual_logging.js';\n\nimport {ActiveFilters} from './ActiveFilters.js';\nimport * as TimelineComponents from './components/components.js';\nimport * as Extensions from './extensions/extensions.js';\nimport {Tracker} from './FreshRecording.js';\nimport {targetForEvent} from './TargetForEvent.js';\nimport {TimelineRegExp} from './TimelineFilters.js';\nimport {type TimelineSelection} from './TimelineSelection.js';\nimport {TimelineUIUtils} from './TimelineUIUtils.js';\n\nconst UIStrings = {\n /**\n *@description Text for the performance of something\n */\n performance: 'Performance',\n /**\n *@description Time of a single activity, as opposed to the total time\n */\n selfTime: 'Self time',\n /**\n *@description Text for the total time of something\n */\n totalTime: 'Total time',\n /**\n *@description Text in Timeline Tree View of the Performance panel\n */\n activity: 'Activity',\n /**\n *@description Text of a DOM element in Timeline Tree View of the Performance panel\n */\n selectItemForDetails: 'Select item for details.',\n /**\n *@description Time in miliseconds\n *@example {30.1} PH1\n */\n fms: '{PH1} ms',\n /**\n *@description Number followed by percent sign\n *@example {20} PH1\n */\n percentPlaceholder: '{PH1} %',\n /**\n *@description Text in Timeline Tree View of the Performance panel\n */\n chromeExtensionsOverhead: '[`Chrome` extensions overhead]',\n /**\n * @description Text in Timeline Tree View of the Performance panel. The text is presented\n * when developers investigate the performance of a page. 'V8 Runtime' labels the time\n * spent in (i.e. runtime) the V8 JavaScript engine.\n */\n vRuntime: '[`V8` Runtime]',\n /**\n *@description Text in Timeline Tree View of the Performance panel\n */\n unattributed: '[unattributed]',\n /**\n *@description Text that refers to one or a group of webpages\n */\n page: 'Page',\n /**\n *@description Text in Timeline Tree View of the Performance panel\n */\n noGrouping: 'No grouping',\n /**\n *@description Text in Timeline Tree View of the Performance panel\n */\n groupByActivity: 'Group by activity',\n /**\n *@description Text in Timeline Tree View of the Performance panel\n */\n groupByCategory: 'Group by category',\n /**\n *@description Text in Timeline Tree View of the Performance panel\n */\n groupByDomain: 'Group by domain',\n /**\n *@description Text in Timeline Tree View of the Performance panel\n */\n groupByFrame: 'Group by frame',\n /**\n *@description Text in Timeline Tree View of the Performance panel\n */\n groupBySubdomain: 'Group by subdomain',\n /**\n *@description Text in Timeline Tree View of the Performance panel\n */\n groupByUrl: 'Group by URL',\n /**\n *@description Text in Timeline Tree View of the Performance panel\n */\n groupByThirdParties: 'Group by Third Parties',\n /**\n *@description Aria-label for grouping combo box in Timeline Details View\n */\n groupBy: 'Group by',\n /**\n * @description Title of the sidebar pane in the Performance panel which shows the stack (call\n * stack) where the program spent the most time (out of all the call stacks) while executing.\n */\n heaviestStack: 'Heaviest stack',\n /**\n * @description Tooltip for the the Heaviest stack sidebar toggle in the Timeline Tree View of the\n * Performance panel. Command to open/show the sidebar.\n */\n showHeaviestStack: 'Show heaviest stack',\n /**\n * @description Tooltip for the the Heaviest stack sidebar toggle in the Timeline Tree View of the\n * Performance panel. Command to close/hide the sidebar.\n */\n hideHeaviestStack: 'Hide heaviest stack',\n /**\n * @description Screen reader announcement when the heaviest stack sidebar is shown in the Performance panel.\n */\n heaviestStackShown: 'Heaviest stack sidebar shown',\n /**\n * @description Screen reader announcement when the heaviest stack sidebar is hidden in the Performance panel.\n */\n heaviestStackHidden: 'Heaviest stack sidebar hidden',\n /**\n *@description Data grid name for Timeline Stack data grids\n */\n timelineStack: 'Timeline stack',\n /**\n /*@description Text to search by matching case of the input button\n */\n matchCase: 'Match case',\n /**\n *@description Text for searching with regular expression button\n */\n useRegularExpression: 'Use regular expression',\n /**\n * @description Text for Match whole word button\n */\n matchWholeWord: 'Match whole word',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelineTreeView.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nexport class TimelineTreeView extends UI.Widget.VBox implements UI.SearchableView.Searchable {\n #selectedEvents: Trace.Types.Events.Event[]|null;\n private searchResults: TimelineModel.TimelineProfileTree.Node[];\n linkifier!: Components.Linkifier.Linkifier;\n dataGrid!: DataGrid.SortableDataGrid.SortableDataGrid;\n private lastHoveredProfileNode!: TimelineModel.TimelineProfileTree.Node|null;\n private textFilterInternal!: TimelineRegExp;\n private taskFilter!: TimelineModel.TimelineModelFilter.ExclusiveNameFilter;\n protected startTime!: Trace.Types.Timing.MilliSeconds;\n protected endTime!: Trace.Types.Timing.MilliSeconds;\n splitWidget!: UI.SplitWidget.SplitWidget;\n detailsView!: UI.Widget.Widget;\n private searchableView!: UI.SearchableView.SearchableView;\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private currentThreadSetting?: Common.Settings.Setting;\n private lastSelectedNodeInternal?: TimelineModel.TimelineProfileTree.Node|null;\n private root?: TimelineModel.TimelineProfileTree.Node;\n private currentResult?: number;\n textFilterUI?: UI.Toolbar.ToolbarInput;\n private caseSensitiveButton: UI.Toolbar.ToolbarToggle|undefined;\n private regexButton: UI.Toolbar.ToolbarToggle|undefined;\n private matchWholeWord: UI.Toolbar.ToolbarToggle|undefined;\n\n #parsedTrace: Trace.Handlers.Types.ParsedTrace|null = null;\n\n constructor() {\n super();\n this.#selectedEvents = null;\n this.element.classList.add('timeline-tree-view');\n\n this.searchResults = [];\n }\n\n #eventNameForSorting(event: Trace.Types.Events.Event): string {\n const name = TimelineUIUtils.eventTitle(event) || event.name;\n if (!this.#parsedTrace) {\n return name;\n }\n return name + ':@' + Trace.Extras.URLForEntry.get(this.#parsedTrace, event);\n }\n\n setSearchableView(searchableView: UI.SearchableView.SearchableView): void {\n this.searchableView = searchableView;\n }\n\n setModelWithEvents(\n selectedEvents: Trace.Types.Events.Event[]|null,\n parsedTrace: Trace.Handlers.Types.ParsedTrace|null = null,\n ): void {\n this.#parsedTrace = parsedTrace;\n this.#selectedEvents = selectedEvents;\n }\n\n parsedTrace(): Trace.Handlers.Types.ParsedTrace|null {\n return this.#parsedTrace;\n }\n\n init(): void {\n this.linkifier = new Components.Linkifier.Linkifier();\n\n this.taskFilter = new TimelineModel.TimelineModelFilter.ExclusiveNameFilter([\n Trace.Types.Events.Name.RUN_TASK,\n ]);\n this.textFilterInternal = new TimelineRegExp();\n\n this.currentThreadSetting = Common.Settings.Settings.instance().createSetting('timeline-tree-current-thread', 0);\n this.currentThreadSetting.addChangeListener(this.refreshTree, this);\n\n const columns = ([] as DataGrid.DataGrid.ColumnDescriptor[]);\n this.populateColumns(columns);\n\n this.splitWidget = new UI.SplitWidget.SplitWidget(true, true, 'timeline-tree-view-details-split-widget');\n const mainView = new UI.Widget.VBox();\n const toolbar = new UI.Toolbar.Toolbar('', mainView.element);\n toolbar.element.setAttribute('jslog', `${VisualLogging.toolbar()}`);\n toolbar.makeWrappable(true);\n this.populateToolbar(toolbar);\n\n this.dataGrid = new DataGrid.SortableDataGrid.SortableDataGrid({\n displayName: i18nString(UIStrings.performance),\n columns,\n refreshCallback: undefined,\n editCallback: undefined,\n deleteCallback: undefined,\n });\n this.dataGrid.addEventListener(DataGrid.DataGrid.Events.SORTING_CHANGED, this.sortingChanged, this);\n this.dataGrid.element.addEventListener('mousemove', this.onMouseMove.bind(this), true);\n this.dataGrid.setResizeMethod(DataGrid.DataGrid.ResizeMethod.LAST);\n this.dataGrid.setRowContextMenuCallback(this.onContextMenu.bind(this));\n this.dataGrid.asWidget().show(mainView.element);\n this.dataGrid.addEventListener(DataGrid.DataGrid.Events.SELECTED_NODE, this.updateDetailsForSelection, this);\n\n this.detailsView = new UI.Widget.VBox();\n this.detailsView.element.classList.add('timeline-details-view', 'timeline-details-view-body');\n this.splitWidget.setMainWidget(mainView);\n this.splitWidget.setSidebarWidget(this.detailsView);\n this.splitWidget.hideSidebar();\n this.splitWidget.show(this.element);\n this.splitWidget.addEventListener(UI.SplitWidget.Events.SHOW_MODE_CHANGED, this.onShowModeChanged, this);\n\n this.lastSelectedNodeInternal;\n }\n\n lastSelectedNode(): TimelineModel.TimelineProfileTree.Node|null|undefined {\n return this.lastSelectedNodeInternal;\n }\n\n updateContents(selection: TimelineSelection): void {\n this.setRange(selection.startTime, selection.endTime);\n }\n\n setRange(startTime: Trace.Types.Timing.MilliSeconds, endTime: Trace.Types.Timing.MilliSeconds): void {\n this.startTime = startTime;\n this.endTime = endTime;\n this.refreshTree();\n }\n\n filters(): TimelineModel.TimelineModelFilter.TimelineModelFilter[] {\n return [this.taskFilter, this.textFilterInternal, ...(ActiveFilters.instance().activeFilters())];\n }\n\n filtersWithoutTextFilter(): TimelineModel.TimelineModelFilter.TimelineModelFilter[] {\n return [this.taskFilter, ...(ActiveFilters.instance().activeFilters())];\n }\n\n textFilter(): TimelineRegExp {\n return this.textFilterInternal;\n }\n\n exposePercentages(): boolean {\n return false;\n }\n\n populateToolbar(toolbar: UI.Toolbar.Toolbar): void {\n this.caseSensitiveButton =\n new UI.Toolbar.ToolbarToggle(i18nString(UIStrings.matchCase), 'match-case', undefined, 'match-case');\n this.caseSensitiveButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, () => {\n this.#filterChanged();\n }, this);\n toolbar.appendToolbarItem(this.caseSensitiveButton);\n\n this.regexButton = new UI.Toolbar.ToolbarToggle(\n i18nString(UIStrings.useRegularExpression), 'regular-expression', undefined, 'regular-expression');\n this.regexButton.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, () => {\n this.#filterChanged();\n }, this);\n toolbar.appendToolbarItem(this.regexButton);\n\n this.matchWholeWord = new UI.Toolbar.ToolbarToggle(\n i18nString(UIStrings.matchWholeWord), 'match-whole-word', undefined, 'match-whole-word');\n this.matchWholeWord.addEventListener(UI.Toolbar.ToolbarButton.Events.CLICK, () => {\n this.#filterChanged();\n }, this);\n toolbar.appendToolbarItem(this.matchWholeWord);\n\n const textFilterUI = new UI.Toolbar.ToolbarFilter();\n this.textFilterUI = textFilterUI;\n textFilterUI.addEventListener(UI.Toolbar.ToolbarInput.Event.TEXT_CHANGED, this.#filterChanged, this);\n toolbar.appendToolbarItem(textFilterUI);\n }\n\n selectedEvents(): Trace.Types.Events.Event[] {\n // TODO: can we make this type readonly?\n return this.#selectedEvents || [];\n }\n\n onHover(_node: TimelineModel.TimelineProfileTree.Node|null): void {\n }\n\n appendContextMenuItems(_contextMenu: UI.ContextMenu.ContextMenu, _node: TimelineModel.TimelineProfileTree.Node):\n void {\n }\n\n selectProfileNode(treeNode: TimelineModel.TimelineProfileTree.Node, suppressSelectedEvent: boolean): void {\n const pathToRoot = [];\n let node: (TimelineModel.TimelineProfileTree.Node|null)|TimelineModel.TimelineProfileTree.Node = treeNode;\n for (; node; node = node.parent) {\n pathToRoot.push(node);\n }\n for (let i = pathToRoot.length - 1; i > 0; --i) {\n const gridNode = this.dataGridNodeForTreeNode(pathToRoot[i]);\n if (gridNode && gridNode.dataGrid) {\n gridNode.expand();\n }\n }\n const gridNode = this.dataGridNodeForTreeNode(treeNode);\n if (gridNode && gridNode.dataGrid) {\n gridNode.reveal();\n gridNode.select(suppressSelectedEvent);\n }\n }\n\n refreshTree(): void {\n if (!this.element.parentElement) {\n // This function can be called in different views (Bottom-Up and\n // Call Tree) by the same single event whenever the group-by\n // dropdown changes value. Thus, we bail out whenever the view is\n // not visible, which we know if the related element is detached\n // from the document.\n return;\n }\n this.linkifier.reset();\n this.dataGrid.rootNode().removeChildren();\n if (!this.#parsedTrace) {\n this.updateDetailsForSelection();\n return;\n }\n this.root = this.buildTree();\n const children = this.root.children();\n let maxSelfTime = 0;\n let maxTotalTime = 0;\n const totalUsedTime = this.root.totalTime - this.root.selfTime;\n for (const child of children.values()) {\n maxSelfTime = Math.max(maxSelfTime, child.selfTime);\n maxTotalTime = Math.max(maxTotalTime, child.totalTime);\n }\n for (const child of children.values()) {\n // Exclude the idle time off the total calculation.\n const gridNode = new TreeGridNode(child, totalUsedTime, maxSelfTime, maxTotalTime, this);\n this.dataGrid.insertChild(gridNode);\n }\n this.sortingChanged();\n this.updateDetailsForSelection();\n if (this.searchableView) {\n this.searchableView.refreshSearch();\n }\n const rootNode = this.dataGrid.rootNode();\n if (rootNode.children.length > 0) {\n rootNode.children[0].select(/* supressSelectedEvent */ true);\n }\n }\n\n buildTree(): TimelineModel.TimelineProfileTree.Node {\n throw new Error('Not Implemented');\n }\n\n buildTopDownTree(doNotAggregate: boolean, groupIdCallback: ((arg0: Trace.Types.Events.Event) => string)|null):\n TimelineModel.TimelineProfileTree.Node {\n return new TimelineModel.TimelineProfileTree.TopDownRootNode(\n this.selectedEvents(), this.filters(), this.startTime, this.endTime, doNotAggregate, groupIdCallback);\n }\n\n populateColumns(columns: DataGrid.DataGrid.ColumnDescriptor[]): void {\n columns.push(\n ({id: 'self', title: i18nString(UIStrings.selfTime), width: '120px', fixedWidth: true, sortable: true} as\n DataGrid.DataGrid.ColumnDescriptor));\n columns.push(\n ({id: 'total', title: i18nString(UIStrings.totalTime), width: '120px', fixedWidth: true, sortable: true} as\n DataGrid.DataGrid.ColumnDescriptor));\n columns.push(\n ({id: 'activity', title: i18nString(UIStrings.activity), disclosure: true, sortable: true} as\n DataGrid.DataGrid.ColumnDescriptor));\n }\n\n private sortingChanged(): void {\n const columnId = this.dataGrid.sortColumnId();\n if (!columnId) {\n return;\n }\n let sortFunction;\n\n const compareNameSortFn =\n (a: DataGrid.SortableDataGrid.SortableDataGridNode,\n b: DataGrid.SortableDataGrid.SortableDataGridNode): number => {\n const nodeA = (a as TreeGridNode);\n const nodeB = (b as TreeGridNode);\n const eventA = nodeA.profileNode.event;\n const eventB = nodeB.profileNode.event;\n // Should not happen, but guard against the nodes not having events.\n if (!eventA || !eventB) {\n return 0;\n }\n if (!this.#parsedTrace) {\n return 0;\n }\n const nameA = this.#eventNameForSorting(eventA);\n const nameB = this.#eventNameForSorting(eventB);\n return nameA.localeCompare(nameB);\n };\n\n switch (columnId) {\n case 'start-time':\n sortFunction = compareStartTime;\n break;\n case 'self':\n sortFunction = compareSelfTime;\n break;\n case 'total':\n sortFunction = compareTotalTime;\n break;\n case 'activity':\n sortFunction = compareNameSortFn;\n break;\n default:\n console.assert(false, 'Unknown sort field: ' + columnId);\n return;\n }\n this.dataGrid.sortNodes(sortFunction, !this.dataGrid.isSortOrderAscending());\n\n function compareSelfTime(\n a: DataGrid.SortableDataGrid.SortableDataGridNode,\n b: DataGrid.SortableDataGrid.SortableDataGridNode): number {\n const nodeA = a as TreeGridNode;\n const nodeB = b as TreeGridNode;\n return nodeA.profileNode.selfTime - nodeB.profileNode.selfTime;\n }\n\n function compareStartTime(\n a: DataGrid.SortableDataGrid.SortableDataGridNode,\n b: DataGrid.SortableDataGrid.SortableDataGridNode): number {\n const nodeA = (a as TreeGridNode);\n const nodeB = (b as TreeGridNode);\n const eventA = nodeA.profileNode.event;\n const eventB = nodeB.profileNode.event;\n // Should not happen, but guard against the nodes not having events.\n if (!eventA || !eventB) {\n return 0;\n }\n return eventA.ts - eventB.ts;\n }\n\n function compareTotalTime(\n a: DataGrid.SortableDataGrid.SortableDataGridNode,\n b: DataGrid.SortableDataGrid.SortableDataGridNode): number {\n const nodeA = a as TreeGridNode;\n const nodeB = b as TreeGridNode;\n return nodeA.profileNode.totalTime - nodeB.profileNode.totalTime;\n }\n }\n\n #filterChanged(): void {\n const searchQuery = this.textFilterUI && this.textFilterUI.value();\n const caseSensitive = this.caseSensitiveButton !== undefined && this.caseSensitiveButton.isToggled();\n const isRegex = this.regexButton !== undefined && this.regexButton.isToggled();\n const matchWholeWord = this.matchWholeWord !== undefined && this.matchWholeWord.isToggled();\n\n this.textFilterInternal.setRegExp(\n searchQuery ? Platform.StringUtilities.createSearchRegex(searchQuery, caseSensitive, isRegex, matchWholeWord) :\n null);\n this.refreshTree();\n }\n\n private onShowModeChanged(): void {\n if (this.splitWidget.showMode() === UI.SplitWidget.ShowMode.ONLY_MAIN) {\n return;\n }\n this.lastSelectedNodeInternal = undefined;\n this.updateDetailsForSelection();\n }\n\n private updateDetailsForSelection(): void {\n const selectedNode = this.dataGrid.selectedNode ? (this.dataGrid.selectedNode as TreeGridNode).profileNode : null;\n if (selectedNode === this.lastSelectedNodeInternal) {\n return;\n }\n this.lastSelectedNodeInternal = selectedNode;\n if (this.splitWidget.showMode() === UI.SplitWidget.ShowMode.ONLY_MAIN) {\n return;\n }\n this.detailsView.detachChildWidgets();\n this.detailsView.element.removeChildren();\n if (selectedNode && this.showDetailsForNode(selectedNode)) {\n return;\n }\n const banner = this.detailsView.element.createChild('div', 'full-widget-dimmed-banner');\n UI.UIUtils.createTextChild(banner, i18nString(UIStrings.selectItemForDetails));\n }\n\n showDetailsForNode(_node: TimelineModel.TimelineProfileTree.Node): boolean {\n return false;\n }\n\n private onMouseMove(event: Event): void {\n const gridNode = event.target && (event.target instanceof Node) ?\n (this.dataGrid.dataGridNodeFromNode((event.target as Node))) :\n null;\n // TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration\n // @ts-expect-error\n const profileNode = gridNode && gridNode._profileNode;\n if (profileNode === this.lastHoveredProfileNode) {\n return;\n }\n this.lastHoveredProfileNode = profileNode;\n this.onHover(profileNode);\n }\n\n private onContextMenu(\n contextMenu: UI.ContextMenu.ContextMenu, eventGridNode: DataGrid.DataGrid.DataGridNode): void {\n const gridNode = (eventGridNode as GridNode);\n if (gridNode.linkElement) {\n contextMenu.appendApplicableItems(gridNode.linkElement);\n }\n const profileNode = gridNode.profileNode;\n if (profileNode) {\n this.appendContextMenuItems(contextMenu, profileNode);\n }\n }\n\n dataGridNodeForTreeNode(treeNode: TimelineModel.TimelineProfileTree.Node): GridNode|null {\n return profileNodeToTreeGridNode.get(treeNode) || null;\n }\n\n // UI.SearchableView.Searchable implementation\n\n onSearchCanceled(): void {\n this.searchResults = [];\n this.currentResult = 0;\n }\n\n performSearch(searchConfig: UI.SearchableView.SearchConfig, _shouldJump: boolean, _jumpBackwards?: boolean): void {\n this.searchResults = [];\n this.currentResult = 0;\n if (!this.root) {\n return;\n }\n const searchRegex = searchConfig.toSearchRegex();\n this.searchResults = this.root.searchTree(\n event => TimelineUIUtils.testContentMatching(event, searchRegex.regex, this.#parsedTrace || undefined));\n this.searchableView.updateSearchMatchesCount(this.searchResults.length);\n }\n\n jumpToNextSearchResult(): void {\n if (!this.searchResults.length || this.currentResult === undefined) {\n return;\n }\n this.selectProfileNode(this.searchResults[this.currentResult], false);\n this.currentResult = Platform.NumberUtilities.mod(this.currentResult + 1, this.searchResults.length);\n }\n\n jumpToPreviousSearchResult(): void {\n if (!this.searchResults.length || this.currentResult === undefined) {\n return;\n }\n this.selectProfileNode(this.searchResults[this.currentResult], false);\n this.currentResult = Platform.NumberUtilities.mod(this.currentResult - 1, this.searchResults.length);\n }\n\n supportsCaseSensitiveSearch(): boolean {\n return true;\n }\n\n supportsRegexSearch(): boolean {\n return true;\n }\n}\n\nexport class GridNode extends DataGrid.SortableDataGrid.SortableDataGridNode {\n protected populated: boolean;\n profileNode: TimelineModel.TimelineProfileTree.Node;\n protected treeView: TimelineTreeView;\n protected grandTotalTime: number;\n protected maxSelfTime: number;\n protected maxTotalTime: number;\n linkElement: Element|null;\n\n constructor(\n profileNode: TimelineModel.TimelineProfileTree.Node, grandTotalTime: number, maxSelfTime: number,\n maxTotalTime: number, treeView: TimelineTreeView) {\n super(null, false);\n this.populated = false;\n this.profileNode = profileNode;\n this.treeView = treeView;\n this.grandTotalTime = grandTotalTime;\n this.maxSelfTime = maxSelfTime;\n this.maxTotalTime = maxTotalTime;\n this.linkElement = null;\n }\n\n override createCell(columnId: string): HTMLElement {\n if (columnId === 'activity') {\n return this.createNameCell(columnId);\n }\n return this.createValueCell(columnId) || super.createCell(columnId);\n }\n\n private createNameCell(columnId: string): HTMLElement {\n const cell = this.createTD(columnId);\n const container = cell.createChild('div', 'name-container');\n const iconContainer = container.createChild('div', 'activity-icon-container');\n const icon = iconContainer.createChild('div', 'activity-icon');\n const name = container.createChild('div', 'activity-name');\n const event = this.profileNode.event;\n if (this.profileNode.isGroupNode()) {\n const treeView = (this.treeView as AggregatedTimelineTreeView);\n const info = treeView.displayInfoForGroupNode(this.profileNode);\n name.textContent = info.name;\n icon.style.backgroundColor = info.color;\n if (info.icon) {\n iconContainer.insertBefore(info.icon, icon);\n }\n } else if (event) {\n name.textContent = TimelineUIUtils.eventTitle(event);\n const parsedTrace = this.treeView.parsedTrace();\n const target = parsedTrace ? targetForEvent(parsedTrace, event) : null;\n const linkifier = this.treeView.linkifier;\n const isFreshRecording = Boolean(parsedTrace && Tracker.instance().recordingIsFresh(parsedTrace));\n this.linkElement = TimelineUIUtils.linkifyTopCallFrame(event, target, linkifier, isFreshRecording);\n if (this.linkElement) {\n container.createChild('div', 'activity-link').appendChild(this.linkElement);\n }\n const eventStyle = TimelineUIUtils.eventStyle(event);\n const eventCategory = eventStyle.category;\n UI.ARIAUtils.setLabel(icon, eventCategory.title);\n icon.style.backgroundColor = eventCategory.getComputedColorValue();\n if (Trace.Types.Extensions.isSyntheticExtensionEntry(event)) {\n icon.style.backgroundColor = Extensions.ExtensionUI.extensionEntryColor(event);\n }\n }\n return cell;\n }\n\n private createValueCell(columnId: string): HTMLElement|null {\n if (columnId !== 'self' && columnId !== 'total' && columnId !== 'start-time') {\n return null;\n }\n\n let showPercents = false;\n let value: number;\n let maxTime: number|undefined;\n let event: Trace.Types.Events.Event|null;\n switch (columnId) {\n case 'start-time': {\n event = this.profileNode.event;\n const parsedTrace = this.treeView.parsedTrace();\n if (!parsedTrace) {\n throw new Error('Unable to load trace data for tree view');\n }\n const timings = event && Trace.Helpers.Timing.eventTimingsMilliSeconds(event);\n const startTime = timings?.startTime ?? 0;\n value = startTime - Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min);\n } break;\n case 'self':\n value = this.profileNode.selfTime;\n maxTime = this.maxSelfTime;\n showPercents = true;\n break;\n case 'total':\n value = this.profileNode.totalTime;\n maxTime = this.maxTotalTime;\n showPercents = true;\n break;\n default:\n return null;\n }\n const cell = this.createTD(columnId);\n cell.className = 'numeric-column';\n cell.setAttribute('title', i18nString(UIStrings.fms, {PH1: value.toFixed(4)}));\n const textDiv = cell.createChild('div');\n textDiv.createChild('span').textContent = i18nString(UIStrings.fms, {PH1: value.toFixed(1)});\n\n if (showPercents && this.treeView.exposePercentages()) {\n textDiv.createChild('span', 'percent-column').textContent =\n i18nString(UIStrings.percentPlaceholder, {PH1: (value / this.grandTotalTime * 100).toFixed(1)});\n }\n if (maxTime) {\n textDiv.classList.add('background-percent-bar');\n cell.createChild('div', 'background-bar-container').createChild('div', 'background-bar').style.width =\n (value * 100 / maxTime).toFixed(1) + '%';\n }\n return cell;\n }\n}\n\nexport class TreeGridNode extends GridNode {\n constructor(\n profileNode: TimelineModel.TimelineProfileTree.Node, grandTotalTime: number, maxSelfTime: number,\n maxTotalTime: number, treeView: TimelineTreeView) {\n super(profileNode, grandTotalTime, maxSelfTime, maxTotalTime, treeView);\n this.setHasChildren(this.profileNode.hasChildren());\n profileNodeToTreeGridNode.set(profileNode, this);\n }\n\n override populate(): void {\n if (this.populated) {\n return;\n }\n this.populated = true;\n if (!this.profileNode.children) {\n return;\n }\n for (const node of this.profileNode.children().values()) {\n const gridNode = new TreeGridNode(node, this.grandTotalTime, this.maxSelfTime, this.maxTotalTime, this.treeView);\n this.insertChildOrdered(gridNode);\n }\n }\n}\n\nconst profileNodeToTreeGridNode = new WeakMap();\n\nexport class AggregatedTimelineTreeView extends TimelineTreeView {\n protected readonly groupBySetting: Common.Settings.Setting;\n private readonly stackView: TimelineStackView;\n private executionContextNamesByOrigin = new Map();\n\n constructor() {\n super();\n this.groupBySetting = Common.Settings.Settings.instance().createSetting(\n 'timeline-tree-group-by', AggregatedTimelineTreeView.GroupBy.None);\n this.groupBySetting.addChangeListener(this.refreshTree.bind(this));\n this.init();\n this.stackView = new TimelineStackView(this);\n this.stackView.addEventListener(TimelineStackView.Events.SELECTION_CHANGED, this.onStackViewSelectionChanged, this);\n }\n\n setGroupBySettingForTests(groupBy: AggregatedTimelineTreeView.GroupBy): void {\n this.groupBySetting.set(groupBy);\n }\n\n override updateContents(selection: TimelineSelection): void {\n this.updateExtensionResolver();\n super.updateContents(selection);\n const rootNode = this.dataGrid.rootNode();\n if (rootNode.children.length) {\n rootNode.children[0].select(/* suppressSelectedEvent */ true);\n }\n }\n\n private updateExtensionResolver(): void {\n this.executionContextNamesByOrigin = new Map();\n for (const runtimeModel of SDK.TargetManager.TargetManager.instance().models(SDK.RuntimeModel.RuntimeModel)) {\n for (const context of runtimeModel.executionContexts()) {\n this.executionContextNamesByOrigin.set(context.origin, context.name);\n }\n }\n }\n\n private beautifyDomainName(this: AggregatedTimelineTreeView, name: string): string {\n if (AggregatedTimelineTreeView.isExtensionInternalURL(name as Platform.DevToolsPath.UrlString)) {\n name = i18nString(UIStrings.chromeExtensionsOverhead);\n } else if (AggregatedTimelineTreeView.isV8NativeURL(name as Platform.DevToolsPath.UrlString)) {\n name = i18nString(UIStrings.vRuntime);\n } else if (name.startsWith('chrome-extension')) {\n name = this.executionContextNamesByOrigin.get(name as Platform.DevToolsPath.UrlString) || name;\n }\n return name;\n }\n\n displayInfoForGroupNode(node: TimelineModel.TimelineProfileTree.Node): {\n name: string,\n color: string,\n icon: (Element|undefined),\n } {\n const categories = TimelineComponents.EntryStyles.getCategoryStyles();\n const color = node.id && node.event ? TimelineUIUtils.eventColor(node.event) : categories['other'].color;\n const unattributed = i18nString(UIStrings.unattributed);\n\n const id = typeof node.id === 'symbol' ? undefined : node.id;\n\n switch (this.groupBySetting.get()) {\n case AggregatedTimelineTreeView.GroupBy.Category: {\n const idIsValid = id && TimelineComponents.EntryStyles.stringIsEventCategory(id);\n const category = idIsValid ? categories[id] || categories['other'] : {title: unattributed, color: unattributed};\n return {name: category.title, color: category.color, icon: undefined};\n }\n\n case AggregatedTimelineTreeView.GroupBy.Domain:\n case AggregatedTimelineTreeView.GroupBy.Subdomain:\n case AggregatedTimelineTreeView.GroupBy.ThirdParties: {\n const domainName = id ? this.beautifyDomainName(id) : undefined;\n return {name: domainName || unattributed, color, icon: undefined};\n }\n\n case AggregatedTimelineTreeView.GroupBy.EventName: {\n if (!node.event) {\n throw new Error('Unable to find event for group by operation');\n }\n const name = TimelineUIUtils.eventTitle(node.event);\n return {\n name,\n color,\n icon: undefined,\n };\n }\n\n case AggregatedTimelineTreeView.GroupBy.URL:\n break;\n\n case AggregatedTimelineTreeView.GroupBy.Frame: {\n const frame = id ? this.parsedTrace()?.PageFrames.frames.get(id) : undefined;\n const frameName = frame ? TimelineUIUtils.displayNameForFrame(frame) : i18nString(UIStrings.page);\n return {name: frameName, color, icon: undefined};\n }\n\n default:\n console.assert(false, 'Unexpected grouping type');\n }\n return {name: id || unattributed, color, icon: undefined};\n }\n\n override populateToolbar(toolbar: UI.Toolbar.Toolbar): void {\n super.populateToolbar(toolbar);\n const groupBy = AggregatedTimelineTreeView.GroupBy;\n const options = [\n {label: i18nString(UIStrings.noGrouping), value: groupBy.None},\n {label: i18nString(UIStrings.groupByActivity), value: groupBy.EventName},\n {label: i18nString(UIStrings.groupByCategory), value: groupBy.Category},\n {label: i18nString(UIStrings.groupByDomain), value: groupBy.Domain},\n {label: i18nString(UIStrings.groupByFrame), value: groupBy.Frame},\n {label: i18nString(UIStrings.groupBySubdomain), value: groupBy.Subdomain},\n {label: i18nString(UIStrings.groupByUrl), value: groupBy.URL},\n {label: i18nString(UIStrings.groupByThirdParties), value: groupBy.ThirdParties},\n ];\n toolbar.appendToolbarItem(\n new UI.Toolbar.ToolbarSettingComboBox(options, this.groupBySetting, i18nString(UIStrings.groupBy)));\n toolbar.appendSpacer();\n toolbar.appendToolbarItem(this.splitWidget.createShowHideSidebarButton(\n i18nString(UIStrings.showHeaviestStack), i18nString(UIStrings.hideHeaviestStack),\n i18nString(UIStrings.heaviestStackShown), i18nString(UIStrings.heaviestStackHidden)));\n }\n\n private buildHeaviestStack(treeNode: TimelineModel.TimelineProfileTree.Node):\n TimelineModel.TimelineProfileTree.Node[] {\n console.assert(Boolean(treeNode.parent), 'Attempt to build stack for tree root');\n let result: TimelineModel.TimelineProfileTree.Node[] = [];\n // Do not add root to the stack, as it's the tree itself.\n for (let node: TimelineModel.TimelineProfileTree.Node = treeNode; node && node.parent; node = node.parent) {\n result.push(node);\n }\n result = result.reverse();\n for (let node: TimelineModel.TimelineProfileTree.Node = treeNode;\n node && node.children() && node.children().size;) {\n const children = Array.from(node.children().values());\n node = children.reduce((a, b) => a.totalTime > b.totalTime ? a : b);\n result.push(node);\n }\n return result;\n }\n\n override exposePercentages(): boolean {\n return true;\n }\n\n private onStackViewSelectionChanged(): void {\n const treeNode = this.stackView.selectedTreeNode();\n if (treeNode) {\n this.selectProfileNode(treeNode, true);\n }\n }\n\n override showDetailsForNode(node: TimelineModel.TimelineProfileTree.Node): boolean {\n const stack = this.buildHeaviestStack(node);\n this.stackView.setStack(stack, node);\n this.stackView.show(this.detailsView.element);\n return true;\n }\n\n protected groupingFunction(groupBy: AggregatedTimelineTreeView.GroupBy):\n ((arg0: Trace.Types.Events.Event) => string)|null {\n const GroupBy = AggregatedTimelineTreeView.GroupBy;\n switch (groupBy) {\n case GroupBy.None:\n return null;\n case GroupBy.EventName:\n return (event: Trace.Types.Events.Event) => TimelineUIUtils.eventStyle(event).title;\n case GroupBy.Category:\n return (event: Trace.Types.Events.Event) => TimelineUIUtils.eventStyle(event).category.name;\n case GroupBy.Subdomain:\n case GroupBy.Domain:\n case GroupBy.ThirdParties:\n return this.domainByEvent.bind(this, groupBy);\n case GroupBy.URL:\n return (event: Trace.Types.Events.Event) => {\n const parsedTrace = this.parsedTrace();\n return parsedTrace ? Trace.Extras.URLForEntry.get(parsedTrace, event) ?? '' : '';\n };\n case GroupBy.Frame:\n return (event: Trace.Types.Events.Event) => {\n const frameId = Trace.Helpers.Trace.frameIDForEvent(event);\n return frameId || this.parsedTrace()?.Meta.mainFrameId || '';\n };\n default:\n console.assert(false, `Unexpected aggregation setting: ${groupBy}`);\n return null;\n }\n }\n\n private domainByEvent(groupBy: AggregatedTimelineTreeView.GroupBy, event: Trace.Types.Events.Event): string {\n const parsedTrace = this.parsedTrace();\n if (!parsedTrace) {\n return '';\n }\n const url = Trace.Extras.URLForEntry.get(parsedTrace, event);\n if (!url) {\n return '';\n }\n if (AggregatedTimelineTreeView.isExtensionInternalURL(url)) {\n return AggregatedTimelineTreeView.extensionInternalPrefix;\n }\n if (AggregatedTimelineTreeView.isV8NativeURL(url)) {\n return AggregatedTimelineTreeView.v8NativePrefix;\n }\n const parsedURL = Common.ParsedURL.ParsedURL.fromString(url);\n if (!parsedURL) {\n return '';\n }\n if (parsedURL.scheme === 'chrome-extension') {\n return parsedURL.scheme + '://' + parsedURL.host;\n }\n if (groupBy === AggregatedTimelineTreeView.GroupBy.ThirdParties) {\n const entity = ThirdPartyWeb.ThirdPartyWeb.getEntity(url);\n if (!entity) {\n return parsedURL.host;\n }\n return entity.name;\n }\n if (groupBy === AggregatedTimelineTreeView.GroupBy.Subdomain) {\n return parsedURL.host;\n }\n if (/^[.0-9]+$/.test(parsedURL.host)) {\n return parsedURL.host;\n }\n const domainMatch = /([^.]*\\.)?[^.]*$/.exec(parsedURL.host);\n return domainMatch && domainMatch[0] || '';\n }\n\n private static isExtensionInternalURL(url: Platform.DevToolsPath.UrlString): boolean {\n return url.startsWith(AggregatedTimelineTreeView.extensionInternalPrefix);\n }\n\n private static isV8NativeURL(url: Platform.DevToolsPath.UrlString): boolean {\n return url.startsWith(AggregatedTimelineTreeView.v8NativePrefix);\n }\n\n private static readonly extensionInternalPrefix = 'extensions::';\n private static readonly v8NativePrefix = 'native ';\n}\nexport namespace AggregatedTimelineTreeView {\n export enum GroupBy {\n /* eslint-disable @typescript-eslint/naming-convention -- Used by web_tests. */\n None = 'None',\n EventName = 'EventName',\n Category = 'Category',\n Domain = 'Domain',\n Subdomain = 'Subdomain',\n URL = 'URL',\n Frame = 'Frame',\n ThirdParties = 'ThirdParties',\n /* eslint-enable @typescript-eslint/naming-convention */\n }\n}\n\nexport class CallTreeTimelineTreeView extends AggregatedTimelineTreeView {\n constructor() {\n super();\n this.element.setAttribute('jslog', `${VisualLogging.pane('call-tree').track({resize: true})}`);\n this.dataGrid.markColumnAsSortedBy('total', DataGrid.DataGrid.Order.Descending);\n }\n\n override buildTree(): TimelineModel.TimelineProfileTree.Node {\n const grouping = this.groupBySetting.get();\n return this.buildTopDownTree(false, this.groupingFunction(grouping));\n }\n}\n\nexport class BottomUpTimelineTreeView extends AggregatedTimelineTreeView {\n constructor() {\n super();\n this.element.setAttribute('jslog', `${VisualLogging.pane('bottom-up').track({resize: true})}`);\n this.dataGrid.markColumnAsSortedBy('self', DataGrid.DataGrid.Order.Descending);\n }\n\n override buildTree(): TimelineModel.TimelineProfileTree.Node {\n return new TimelineModel.TimelineProfileTree.BottomUpRootNode(\n this.selectedEvents(), this.textFilter(), this.filtersWithoutTextFilter(), this.startTime, this.endTime,\n this.groupingFunction(this.groupBySetting.get()));\n }\n}\n\nexport class TimelineStackView extends\n Common.ObjectWrapper.eventMixin(UI.Widget.VBox) {\n private readonly treeView: TimelineTreeView;\n private readonly dataGrid: DataGrid.ViewportDataGrid.ViewportDataGrid;\n\n constructor(treeView: TimelineTreeView) {\n super();\n const header = this.element.createChild('div', 'timeline-stack-view-header');\n header.textContent = i18nString(UIStrings.heaviestStack);\n this.treeView = treeView;\n const columns = ([\n {id: 'total', title: i18nString(UIStrings.totalTime), fixedWidth: true, width: '110px'},\n {id: 'activity', title: i18nString(UIStrings.activity)},\n ] as DataGrid.DataGrid.ColumnDescriptor[]);\n this.dataGrid = new DataGrid.ViewportDataGrid.ViewportDataGrid({\n displayName: i18nString(UIStrings.timelineStack),\n columns,\n deleteCallback: undefined,\n editCallback: undefined,\n refreshCallback: undefined,\n });\n this.dataGrid.setResizeMethod(DataGrid.DataGrid.ResizeMethod.LAST);\n this.dataGrid.addEventListener(DataGrid.DataGrid.Events.SELECTED_NODE, this.onSelectionChanged, this);\n this.dataGrid.asWidget().show(this.element);\n }\n\n setStack(stack: TimelineModel.TimelineProfileTree.Node[], selectedNode: TimelineModel.TimelineProfileTree.Node):\n void {\n const rootNode = this.dataGrid.rootNode();\n rootNode.removeChildren();\n let nodeToReveal: GridNode|null = null;\n const totalTime = Math.max.apply(Math, stack.map(node => node.totalTime));\n for (const node of stack) {\n const gridNode = new GridNode(node, totalTime, totalTime, totalTime, this.treeView);\n rootNode.appendChild(gridNode);\n if (node === selectedNode) {\n nodeToReveal = gridNode;\n }\n }\n if (nodeToReveal) {\n nodeToReveal.revealAndSelect();\n }\n }\n\n selectedTreeNode(): TimelineModel.TimelineProfileTree.Node|null {\n const selectedNode = this.dataGrid.selectedNode;\n return selectedNode && (selectedNode as GridNode).profileNode;\n }\n\n private onSelectionChanged(): void {\n this.dispatchEventToListeners(TimelineStackView.Events.SELECTION_CHANGED);\n }\n}\n\nexport namespace TimelineStackView {\n export const enum Events {\n SELECTION_CHANGED = 'SelectionChanged',\n }\n\n export type EventTypes = {\n [Events.SELECTION_CHANGED]: void,\n };\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineTreeView.test.js b/public/panels/timeline/TimelineTreeView.test.js index c536ae1b6..f085d8efd 100644 --- a/public/panels/timeline/TimelineTreeView.test.js +++ b/public/panels/timeline/TimelineTreeView.test.js @@ -1,7 +1,7 @@ // Copyright 2021 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 * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import { describeWithEnvironment } from '../../testing/EnvironmentHelpers.js'; import { TraceLoader } from '../../testing/TraceLoader.js'; import * as Timeline from './timeline.js'; @@ -22,10 +22,10 @@ describeWithEnvironment('TimelineTreeView', function () { Timeline.TimelineUIUtils.TimelineUIUtils.categories().scripting.hidden = false; }); it('Creates a tree from nestable async events', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'sync-like-timings.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'sync-like-timings.json.gz'); const eventTreeView = new Timeline.EventsTimelineTreeView.EventsTimelineTreeView(mockViewDelegate); - const consoleTimings = [...traceData.UserTimings.consoleTimings]; - eventTreeView.setModelWithEvents(consoleTimings, traceData); + const consoleTimings = [...parsedTrace.UserTimings.consoleTimings]; + eventTreeView.setModelWithEvents(consoleTimings, parsedTrace); const tree = eventTreeView.buildTree(); const topNodesIterator = tree.children().values(); const firstNode = topNodesIterator.next().value; @@ -36,10 +36,10 @@ describeWithEnvironment('TimelineTreeView', function () { assert.strictEqual(bottomNode.event?.name, 'second console time'); }); it('shows instant events as nodes', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'user-timings.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'user-timings.json.gz'); const eventTreeView = new Timeline.EventsTimelineTreeView.EventsTimelineTreeView(mockViewDelegate); - const consoleTimings = [...traceData.UserTimings.performanceMarks]; - eventTreeView.setModelWithEvents(consoleTimings, traceData); + const consoleTimings = [...parsedTrace.UserTimings.performanceMarks]; + eventTreeView.setModelWithEvents(consoleTimings, parsedTrace); const tree = eventTreeView.buildTree(); const topNodesIterator = tree.children().values(); const firstNode = topNodesIterator.next().value; @@ -48,10 +48,10 @@ describeWithEnvironment('TimelineTreeView', function () { assert.strictEqual(secondNode.event?.name, 'mark3'); }); it('can filter events by text', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'user-timings.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'user-timings.json.gz'); const eventTreeView = new Timeline.EventsTimelineTreeView.EventsTimelineTreeView(mockViewDelegate); - const consoleTimings = [...traceData.UserTimings.performanceMarks]; - eventTreeView.setModelWithEvents(consoleTimings, traceData); + const consoleTimings = [...parsedTrace.UserTimings.performanceMarks]; + eventTreeView.setModelWithEvents(consoleTimings, parsedTrace); let tree = eventTreeView.buildTree(); const topLevelChildren = Array.from(tree.children().values(), childNode => { return childNode.event?.name || 'NO_EVENT_FOR_NODE'; @@ -65,10 +65,10 @@ describeWithEnvironment('TimelineTreeView', function () { assert.deepEqual(newTopLevelChildren, ['mark1']); }); it('can filter and hide entire categories', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'user-timings.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'user-timings.json.gz'); const eventTreeView = new Timeline.EventsTimelineTreeView.EventsTimelineTreeView(mockViewDelegate); - const performanceTimingEvents = [...traceData.UserTimings.performanceMeasures]; - eventTreeView.setModelWithEvents(performanceTimingEvents, traceData); + const performanceTimingEvents = [...parsedTrace.UserTimings.performanceMeasures]; + eventTreeView.setModelWithEvents(performanceTimingEvents, parsedTrace); let tree = eventTreeView.buildTree(); const topLevelChildren = Array.from(tree.children().values(), childNode => { return childNode.event?.name || 'NO_EVENT_FOR_NODE'; @@ -86,13 +86,13 @@ describeWithEnvironment('TimelineTreeView', function () { }); describe('BottomUpTimelineTreeView', function () { it('Creates a bottom up tree from nestable events', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'sync-like-timings.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'sync-like-timings.json.gz'); const bottomUpTreeView = new Timeline.TimelineTreeView.BottomUpTimelineTreeView(); - const consoleTimings = [...traceData.UserTimings.consoleTimings]; - const startTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min); - const endTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max); + const consoleTimings = [...parsedTrace.UserTimings.consoleTimings]; + const startTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min); + const endTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max); bottomUpTreeView.setRange(startTime, endTime); - bottomUpTreeView.setModelWithEvents(consoleTimings, traceData); + bottomUpTreeView.setModelWithEvents(consoleTimings, parsedTrace); const tree = bottomUpTreeView.buildTree(); const topNodesIterator = tree.children().values(); const firstNode = topNodesIterator.next().value; @@ -107,13 +107,13 @@ describeWithEnvironment('TimelineTreeView', function () { }); describe('CallTreeTimelineTreeView', function () { it('Creates a call tree from nestable events', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'sync-like-timings.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'sync-like-timings.json.gz'); const callTreeView = new Timeline.TimelineTreeView.CallTreeTimelineTreeView(); - const consoleTimings = [...traceData.UserTimings.consoleTimings]; - const startTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min); - const endTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max); + const consoleTimings = [...parsedTrace.UserTimings.consoleTimings]; + const startTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min); + const endTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max); callTreeView.setRange(startTime, endTime); - callTreeView.setModelWithEvents(consoleTimings, traceData); + callTreeView.setModelWithEvents(consoleTimings, parsedTrace); const tree = callTreeView.buildTree(); const topNodesIterator = tree.children().values(); const firstNode = topNodesIterator.next().value; @@ -126,14 +126,14 @@ describeWithEnvironment('TimelineTreeView', function () { }); describe('event grouping', function () { it('groups events by category in the Call Tree view', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'sync-like-timings.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'sync-like-timings.json.gz'); const callTreeView = new Timeline.TimelineTreeView.CallTreeTimelineTreeView(); - const consoleTimings = [...traceData.UserTimings.consoleTimings]; - const startTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min); - const endTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max); + const consoleTimings = [...parsedTrace.UserTimings.consoleTimings]; + const startTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min); + const endTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max); callTreeView.setRange(startTime, endTime); callTreeView.setGroupBySettingForTests(Timeline.TimelineTreeView.AggregatedTimelineTreeView.GroupBy.Category); - callTreeView.setModelWithEvents(consoleTimings, traceData); + callTreeView.setModelWithEvents(consoleTimings, parsedTrace); const tree = callTreeView.buildTree(); const treeEntries = tree.children().entries(); const groupEntry = treeEntries.next(); @@ -147,14 +147,14 @@ describeWithEnvironment('TimelineTreeView', function () { assert.strictEqual(children.next().value.event.name, 'third console time'); }); it('groups events by category in the Bottom up Tree view', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'sync-like-timings.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'sync-like-timings.json.gz'); const callTreeView = new Timeline.TimelineTreeView.BottomUpTimelineTreeView(); - const consoleTimings = [...traceData.UserTimings.consoleTimings]; - const startTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min); - const endTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max); + const consoleTimings = [...parsedTrace.UserTimings.consoleTimings]; + const startTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min); + const endTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max); callTreeView.setRange(startTime, endTime); callTreeView.setGroupBySettingForTests(Timeline.TimelineTreeView.AggregatedTimelineTreeView.GroupBy.Category); - callTreeView.setModelWithEvents(consoleTimings, traceData); + callTreeView.setModelWithEvents(consoleTimings, parsedTrace); const tree = callTreeView.buildTree(); const treeEntries = tree.children().entries(); const groupEntry = treeEntries.next(); @@ -169,13 +169,13 @@ describeWithEnvironment('TimelineTreeView', function () { assert.strictEqual(children.next().value.event.name, 'third console time'); }); it('can group entries by domain', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); const callTreeView = new Timeline.TimelineTreeView.BottomUpTimelineTreeView(); - const startTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min); - const endTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max); + const startTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min); + const endTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max); callTreeView.setRange(startTime, endTime); callTreeView.setGroupBySettingForTests(Timeline.TimelineTreeView.AggregatedTimelineTreeView.GroupBy.Domain); - callTreeView.setModelWithEvents(traceData.Renderer.allTraceEntries, traceData); + callTreeView.setModelWithEvents(parsedTrace.Renderer.allTraceEntries, parsedTrace); const tree = callTreeView.buildTree(); const topLevelGroupNodes = Array.from(tree.children().entries()); assert.deepEqual(topLevelGroupNodes.map(node => node[0]), [ @@ -190,13 +190,13 @@ describeWithEnvironment('TimelineTreeView', function () { ]); }); it('can group entries by third parties', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); const callTreeView = new Timeline.TimelineTreeView.BottomUpTimelineTreeView(); - const startTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min); - const endTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max); + const startTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min); + const endTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max); callTreeView.setRange(startTime, endTime); callTreeView.setGroupBySettingForTests(Timeline.TimelineTreeView.AggregatedTimelineTreeView.GroupBy.ThirdParties); - callTreeView.setModelWithEvents(traceData.Renderer.allTraceEntries, traceData); + callTreeView.setModelWithEvents(parsedTrace.Renderer.allTraceEntries, parsedTrace); const tree = callTreeView.buildTree(); const topLevelGroupNodes = Array.from(tree.children().entries()); assert.deepEqual(topLevelGroupNodes.map(node => node[0]), [ @@ -211,13 +211,13 @@ describeWithEnvironment('TimelineTreeView', function () { ]); }); it('can group entries by frame', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); const callTreeView = new Timeline.TimelineTreeView.BottomUpTimelineTreeView(); - const startTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min); - const endTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max); + const startTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min); + const endTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max); callTreeView.setRange(startTime, endTime); callTreeView.setGroupBySettingForTests(Timeline.TimelineTreeView.AggregatedTimelineTreeView.GroupBy.Frame); - callTreeView.setModelWithEvents(traceData.Renderer.allTraceEntries, traceData); + callTreeView.setModelWithEvents(parsedTrace.Renderer.allTraceEntries, parsedTrace); const tree = callTreeView.buildTree(); const topLevelGroupNodes = Array.from(tree.children().entries()); assert.deepEqual(topLevelGroupNodes.map(node => node[0]), [ @@ -226,13 +226,13 @@ describeWithEnvironment('TimelineTreeView', function () { ]); }); it('can group entries by URL', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); const callTreeView = new Timeline.TimelineTreeView.BottomUpTimelineTreeView(); - const startTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min); - const endTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max); + const startTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min); + const endTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max); callTreeView.setRange(startTime, endTime); callTreeView.setGroupBySettingForTests(Timeline.TimelineTreeView.AggregatedTimelineTreeView.GroupBy.URL); - callTreeView.setModelWithEvents(traceData.Renderer.allTraceEntries, traceData); + callTreeView.setModelWithEvents(parsedTrace.Renderer.allTraceEntries, parsedTrace); const tree = callTreeView.buildTree(); const topLevelGroupNodes = Array.from(tree.children().entries()); assert.deepEqual(topLevelGroupNodes.map(node => node[0]), [ diff --git a/public/panels/timeline/TimelineTreeView.test.js.map b/public/panels/timeline/TimelineTreeView.test.js.map index eb6c9aab3..c21e22859 100644 --- a/public/panels/timeline/TimelineTreeView.test.js.map +++ b/public/panels/timeline/TimelineTreeView.test.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineTreeView.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineTreeView.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2021 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\n\nimport * as Timeline from './timeline.js';\n\nclass MockViewDelegate implements Timeline.TimelinePanel.TimelineModeViewDelegate {\n select(_selection: Timeline.TimelineSelection.TimelineSelection|null): void {\n }\n selectEntryAtTime(_events: TraceEngine.Types.TraceEvents.TraceEventData[]|null, _time: number): void {\n }\n highlightEvent(_event: TraceEngine.Types.TraceEvents.TraceEventData|null): void {\n }\n element = document.createElement('div');\n}\n\ndescribeWithEnvironment('TimelineTreeView', function() {\n const mockViewDelegate = new MockViewDelegate();\n\n describe('EventsTimelineTreeView', function() {\n afterEach(() => {\n // One of the unit tests changes this, so ensure it gets set back after the test.\n Timeline.TimelineUIUtils.TimelineUIUtils.categories().scripting.hidden = false;\n });\n\n it('Creates a tree from nestable async events', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'sync-like-timings.json.gz');\n const eventTreeView = new Timeline.EventsTimelineTreeView.EventsTimelineTreeView(mockViewDelegate);\n const consoleTimings = [...traceData.UserTimings.consoleTimings];\n eventTreeView.setModelWithEvents(consoleTimings, traceData);\n const tree = eventTreeView.buildTree();\n const topNodesIterator = tree.children().values();\n const firstNode = topNodesIterator.next().value as TimelineModel.TimelineProfileTree.Node;\n assert.strictEqual(firstNode.event?.name, 'first console time');\n\n const secondNode = topNodesIterator.next().value as TimelineModel.TimelineProfileTree.Node;\n assert.strictEqual(secondNode.event?.name, 'third console time');\n\n const bottomNode = firstNode.children().values().next().value as TimelineModel.TimelineProfileTree.Node;\n assert.strictEqual(bottomNode.event?.name, 'second console time');\n });\n\n it('shows instant events as nodes', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'user-timings.json.gz');\n const eventTreeView = new Timeline.EventsTimelineTreeView.EventsTimelineTreeView(mockViewDelegate);\n const consoleTimings = [...traceData.UserTimings.performanceMarks];\n eventTreeView.setModelWithEvents(consoleTimings, traceData);\n const tree = eventTreeView.buildTree();\n const topNodesIterator = tree.children().values();\n const firstNode = topNodesIterator.next().value as TimelineModel.TimelineProfileTree.Node;\n assert.strictEqual(firstNode.event?.name, 'mark1');\n\n const secondNode = topNodesIterator.next().value as TimelineModel.TimelineProfileTree.Node;\n assert.strictEqual(secondNode.event?.name, 'mark3');\n });\n\n it('can filter events by text', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'user-timings.json.gz');\n const eventTreeView = new Timeline.EventsTimelineTreeView.EventsTimelineTreeView(mockViewDelegate);\n const consoleTimings = [...traceData.UserTimings.performanceMarks];\n eventTreeView.setModelWithEvents(consoleTimings, traceData);\n let tree = eventTreeView.buildTree();\n const topLevelChildren = Array.from(tree.children().values(), childNode => {\n return childNode.event?.name || 'NO_EVENT_FOR_NODE';\n });\n assert.deepEqual(topLevelChildren, ['mark1', 'mark3']);\n eventTreeView.textFilterUI?.setValue('mark1', true);\n tree = eventTreeView.buildTree();\n const newTopLevelChildren = Array.from(tree.children().values(), childNode => {\n return childNode.event?.name || 'NO_EVENT_FOR_NODE';\n });\n assert.deepEqual(newTopLevelChildren, ['mark1']);\n });\n\n it('can filter and hide entire categories', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'user-timings.json.gz');\n const eventTreeView = new Timeline.EventsTimelineTreeView.EventsTimelineTreeView(mockViewDelegate);\n const performanceTimingEvents = [...traceData.UserTimings.performanceMeasures];\n eventTreeView.setModelWithEvents(performanceTimingEvents, traceData);\n let tree = eventTreeView.buildTree();\n const topLevelChildren = Array.from(tree.children().values(), childNode => {\n return childNode.event?.name || 'NO_EVENT_FOR_NODE';\n });\n assert.deepEqual(topLevelChildren, ['first measure', 'third measure']);\n // Now make the scripting category hidden and tell the treeview to re-render.\n Timeline.TimelineUIUtils.TimelineUIUtils.categories().scripting.hidden = true;\n eventTreeView.refreshTree();\n tree = eventTreeView.buildTree();\n const newTopLevelChildren = Array.from(tree.children().values(), childNode => {\n return childNode.event?.name || 'NO_EVENT_FOR_NODE';\n });\n assert.deepEqual(newTopLevelChildren, []);\n });\n });\n\n describe('BottomUpTimelineTreeView', function() {\n it('Creates a bottom up tree from nestable events', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'sync-like-timings.json.gz');\n const bottomUpTreeView = new Timeline.TimelineTreeView.BottomUpTimelineTreeView();\n const consoleTimings = [...traceData.UserTimings.consoleTimings];\n const startTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min);\n const endTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max);\n bottomUpTreeView.setRange(startTime, endTime);\n bottomUpTreeView.setModelWithEvents(consoleTimings, traceData);\n\n const tree = bottomUpTreeView.buildTree();\n const topNodesIterator = tree.children().values();\n const firstNode = topNodesIterator.next().value as TimelineModel.TimelineProfileTree.Node;\n assert.strictEqual(firstNode.event?.name, 'second console time');\n\n const secondNode = topNodesIterator.next().value as TimelineModel.TimelineProfileTree.Node;\n assert.strictEqual(secondNode.event?.name, 'first console time');\n\n const thirdNode = topNodesIterator.next().value as TimelineModel.TimelineProfileTree.Node;\n assert.strictEqual(thirdNode.event?.name, 'third console time');\n\n const childNode = firstNode.children().values().next().value as TimelineModel.TimelineProfileTree.Node;\n assert.strictEqual(childNode.event?.name, 'first console time');\n });\n });\n\n describe('CallTreeTimelineTreeView', function() {\n it('Creates a call tree from nestable events', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'sync-like-timings.json.gz');\n const callTreeView = new Timeline.TimelineTreeView.CallTreeTimelineTreeView();\n const consoleTimings = [...traceData.UserTimings.consoleTimings];\n const startTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min);\n const endTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max);\n callTreeView.setRange(startTime, endTime);\n callTreeView.setModelWithEvents(consoleTimings, traceData);\n\n const tree = callTreeView.buildTree();\n const topNodesIterator = tree.children().values();\n const firstNode = topNodesIterator.next().value as TimelineModel.TimelineProfileTree.Node;\n assert.strictEqual(firstNode.event?.name, 'first console time');\n\n const secondNode = topNodesIterator.next().value as TimelineModel.TimelineProfileTree.Node;\n assert.strictEqual(secondNode.event?.name, 'third console time');\n\n const childNode = firstNode.children().values().next().value as TimelineModel.TimelineProfileTree.Node;\n assert.strictEqual(childNode.event?.name, 'second console time');\n });\n });\n\n describe('event grouping', function() {\n it('groups events by category in the Call Tree view', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'sync-like-timings.json.gz');\n const callTreeView = new Timeline.TimelineTreeView.CallTreeTimelineTreeView();\n const consoleTimings = [...traceData.UserTimings.consoleTimings];\n const startTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min);\n const endTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max);\n callTreeView.setRange(startTime, endTime);\n callTreeView.setGroupBySettingForTests(Timeline.TimelineTreeView.AggregatedTimelineTreeView.GroupBy.Category);\n callTreeView.setModelWithEvents(consoleTimings, traceData);\n const tree = callTreeView.buildTree();\n const treeEntries = tree.children().entries();\n const groupEntry = treeEntries.next();\n const nodeName = groupEntry.value[0];\n const node = groupEntry.value[1];\n assert.strictEqual(nodeName, 'scripting');\n assert.strictEqual(callTreeView.displayInfoForGroupNode(node).color, 'rgb(250 204 21 / 100%)');\n\n assert.isTrue(node.isGroupNode());\n const children = node.children().values();\n assert.strictEqual(children.next().value.event.name, 'first console time');\n assert.strictEqual(children.next().value.event.name, 'third console time');\n });\n it('groups events by category in the Bottom up Tree view', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'sync-like-timings.json.gz');\n const callTreeView = new Timeline.TimelineTreeView.BottomUpTimelineTreeView();\n const consoleTimings = [...traceData.UserTimings.consoleTimings];\n const startTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min);\n const endTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max);\n callTreeView.setRange(startTime, endTime);\n callTreeView.setGroupBySettingForTests(Timeline.TimelineTreeView.AggregatedTimelineTreeView.GroupBy.Category);\n callTreeView.setModelWithEvents(consoleTimings, traceData);\n const tree = callTreeView.buildTree();\n const treeEntries = tree.children().entries();\n const groupEntry = treeEntries.next();\n const nodeName = groupEntry.value[0];\n const node = groupEntry.value[1];\n assert.strictEqual(nodeName, 'scripting');\n assert.strictEqual(callTreeView.displayInfoForGroupNode(node).color, 'rgb(250 204 21 / 100%)');\n\n assert.isTrue(node.isGroupNode());\n const children = node.children().values();\n assert.strictEqual(children.next().value.event.name, 'second console time');\n assert.strictEqual(children.next().value.event.name, 'first console time');\n assert.strictEqual(children.next().value.event.name, 'third console time');\n });\n\n it('can group entries by domain', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n const callTreeView = new Timeline.TimelineTreeView.BottomUpTimelineTreeView();\n const startTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min);\n const endTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max);\n\n callTreeView.setRange(startTime, endTime);\n callTreeView.setGroupBySettingForTests(Timeline.TimelineTreeView.AggregatedTimelineTreeView.GroupBy.Domain);\n callTreeView.setModelWithEvents(traceData.Renderer.allTraceEntries, traceData);\n\n const tree = callTreeView.buildTree();\n const topLevelGroupNodes = Array.from(tree.children().entries());\n\n assert.deepEqual(topLevelGroupNodes.map(node => node[0]), [\n '',\n 'web.dev',\n 'extensions::',\n 'chrome-extension://noondiphcddnnabmjcihcjfbhfklnnep',\n 'imgix.net',\n 'googletagmanager.com',\n 'google-analytics.com',\n 'web.app',\n ]);\n });\n\n it('can group entries by third parties', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n const callTreeView = new Timeline.TimelineTreeView.BottomUpTimelineTreeView();\n const startTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min);\n const endTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max);\n\n callTreeView.setRange(startTime, endTime);\n callTreeView.setGroupBySettingForTests(Timeline.TimelineTreeView.AggregatedTimelineTreeView.GroupBy.ThirdParties);\n callTreeView.setModelWithEvents(traceData.Renderer.allTraceEntries, traceData);\n\n const tree = callTreeView.buildTree();\n const topLevelGroupNodes = Array.from(tree.children().entries());\n\n assert.deepEqual(topLevelGroupNodes.map(node => node[0]), [\n '',\n 'web.dev',\n 'extensions::',\n 'chrome-extension://noondiphcddnnabmjcihcjfbhfklnnep',\n 'imgix',\n 'Google Tag Manager',\n 'Google Analytics',\n 'shared-storage-demo-content-producer.web.app',\n ]);\n });\n\n it('can group entries by frame', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n const callTreeView = new Timeline.TimelineTreeView.BottomUpTimelineTreeView();\n const startTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min);\n const endTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max);\n\n callTreeView.setRange(startTime, endTime);\n callTreeView.setGroupBySettingForTests(Timeline.TimelineTreeView.AggregatedTimelineTreeView.GroupBy.Frame);\n callTreeView.setModelWithEvents(traceData.Renderer.allTraceEntries, traceData);\n\n const tree = callTreeView.buildTree();\n const topLevelGroupNodes = Array.from(tree.children().entries());\n\n assert.deepEqual(topLevelGroupNodes.map(node => node[0]), [\n '25D2F12F1818C70B5BD4325CC9ACD8FF',\n '1094B71EC09B8BD3DD48B77D091D6024',\n ]);\n });\n\n it('can group entries by URL', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n const callTreeView = new Timeline.TimelineTreeView.BottomUpTimelineTreeView();\n const startTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min);\n const endTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max);\n\n callTreeView.setRange(startTime, endTime);\n callTreeView.setGroupBySettingForTests(Timeline.TimelineTreeView.AggregatedTimelineTreeView.GroupBy.URL);\n callTreeView.setModelWithEvents(traceData.Renderer.allTraceEntries, traceData);\n\n const tree = callTreeView.buildTree();\n const topLevelGroupNodes = Array.from(tree.children().entries());\n\n assert.deepEqual(topLevelGroupNodes.map(node => node[0]), [\n '', // Represents \"Unattributed\" in the UI\n 'https://web.dev/',\n 'extensions::SafeBuiltins',\n 'chrome-extension://noondiphcddnnabmjcihcjfbhfklnnep/content_script_compiled.js',\n 'https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/4i7JstVZvgTFk9dxCe4a.svg',\n 'https://web.dev/js/home.js?v=73b0d143',\n 'https://web.dev/js/actions-f0eb5c8e.js',\n 'https://web.dev/js/app.js?v=fedf5fbe',\n 'https://web.dev/js/index-f45448ab.js',\n 'https://web.dev/js/index-7e29abb6.js',\n 'https://www.googletagmanager.com/gtm.js?id=GTM-MZWCJPP',\n 'https://www.google-analytics.com/analytics.js',\n 'https://www.googletagmanager.com/gtag/js?id=G-18JR3Q8PJ8&l=dataLayer&cx=c',\n 'https://www.google-analytics.com/j/collect?v=1&_v=j101&a=68725886&t=event&ni=1&_s=1&dl=https%3A%2F%2Fweb.dev%2F&ul=en-gb&de=UTF-8&dt=web.dev&sd=24-bit&sr=3360x1890&vp=1665x846&je=0&ec=Web%20Vitals&ea=FCP&el=v3-1696581005645-6472407333688&ev=129&_u=QACAAEABAAAAACAAIg~&jid=&gjid=&cid=1874137241.1685438100&tid=UA-126406676-2&_gid=656288571.1696581004&_slc=1>m=45He3a40n81MZWCJPP&cd5=15&cd6=navigate&cd7=light&cd8=dom-content-loaded&cd9=8&z=54974500',\n 'https://shared-storage-demo-content-producer.web.app/paa/scripts/private-aggregation-test.js',\n 'https://shared-storage-demo-content-producer.web.app/paa/scripts/private-aggregation-test.html',\n 'https://web-dev.imgix.net/image/SZHNhsfjU9RbCestTGZU6N7JEWs1/VwL892KEz6bakZMlq10D.png?auto=format&w=740',\n ]);\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"TimelineTreeView.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineTreeView.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2021 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\n\nimport * as Timeline from './timeline.js';\n\nclass MockViewDelegate implements Timeline.TimelinePanel.TimelineModeViewDelegate {\n select(_selection: Timeline.TimelineSelection.TimelineSelection|null): void {\n }\n selectEntryAtTime(_events: Trace.Types.Events.Event[]|null, _time: number): void {\n }\n highlightEvent(_event: Trace.Types.Events.Event|null): void {\n }\n element = document.createElement('div');\n}\n\ndescribeWithEnvironment('TimelineTreeView', function() {\n const mockViewDelegate = new MockViewDelegate();\n\n describe('EventsTimelineTreeView', function() {\n afterEach(() => {\n // One of the unit tests changes this, so ensure it gets set back after the test.\n Timeline.TimelineUIUtils.TimelineUIUtils.categories().scripting.hidden = false;\n });\n\n it('Creates a tree from nestable async events', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'sync-like-timings.json.gz');\n const eventTreeView = new Timeline.EventsTimelineTreeView.EventsTimelineTreeView(mockViewDelegate);\n const consoleTimings = [...parsedTrace.UserTimings.consoleTimings];\n eventTreeView.setModelWithEvents(consoleTimings, parsedTrace);\n const tree = eventTreeView.buildTree();\n const topNodesIterator = tree.children().values();\n const firstNode = topNodesIterator.next().value as TimelineModel.TimelineProfileTree.Node;\n assert.strictEqual(firstNode.event?.name, 'first console time');\n\n const secondNode = topNodesIterator.next().value as TimelineModel.TimelineProfileTree.Node;\n assert.strictEqual(secondNode.event?.name, 'third console time');\n\n const bottomNode = firstNode.children().values().next().value as TimelineModel.TimelineProfileTree.Node;\n assert.strictEqual(bottomNode.event?.name, 'second console time');\n });\n\n it('shows instant events as nodes', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'user-timings.json.gz');\n const eventTreeView = new Timeline.EventsTimelineTreeView.EventsTimelineTreeView(mockViewDelegate);\n const consoleTimings = [...parsedTrace.UserTimings.performanceMarks];\n eventTreeView.setModelWithEvents(consoleTimings, parsedTrace);\n const tree = eventTreeView.buildTree();\n const topNodesIterator = tree.children().values();\n const firstNode = topNodesIterator.next().value as TimelineModel.TimelineProfileTree.Node;\n assert.strictEqual(firstNode.event?.name, 'mark1');\n\n const secondNode = topNodesIterator.next().value as TimelineModel.TimelineProfileTree.Node;\n assert.strictEqual(secondNode.event?.name, 'mark3');\n });\n\n it('can filter events by text', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'user-timings.json.gz');\n const eventTreeView = new Timeline.EventsTimelineTreeView.EventsTimelineTreeView(mockViewDelegate);\n const consoleTimings = [...parsedTrace.UserTimings.performanceMarks];\n eventTreeView.setModelWithEvents(consoleTimings, parsedTrace);\n let tree = eventTreeView.buildTree();\n const topLevelChildren = Array.from(tree.children().values(), childNode => {\n return childNode.event?.name || 'NO_EVENT_FOR_NODE';\n });\n assert.deepEqual(topLevelChildren, ['mark1', 'mark3']);\n eventTreeView.textFilterUI?.setValue('mark1', true);\n tree = eventTreeView.buildTree();\n const newTopLevelChildren = Array.from(tree.children().values(), childNode => {\n return childNode.event?.name || 'NO_EVENT_FOR_NODE';\n });\n assert.deepEqual(newTopLevelChildren, ['mark1']);\n });\n\n it('can filter and hide entire categories', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'user-timings.json.gz');\n const eventTreeView = new Timeline.EventsTimelineTreeView.EventsTimelineTreeView(mockViewDelegate);\n const performanceTimingEvents = [...parsedTrace.UserTimings.performanceMeasures];\n eventTreeView.setModelWithEvents(performanceTimingEvents, parsedTrace);\n let tree = eventTreeView.buildTree();\n const topLevelChildren = Array.from(tree.children().values(), childNode => {\n return childNode.event?.name || 'NO_EVENT_FOR_NODE';\n });\n assert.deepEqual(topLevelChildren, ['first measure', 'third measure']);\n // Now make the scripting category hidden and tell the treeview to re-render.\n Timeline.TimelineUIUtils.TimelineUIUtils.categories().scripting.hidden = true;\n eventTreeView.refreshTree();\n tree = eventTreeView.buildTree();\n const newTopLevelChildren = Array.from(tree.children().values(), childNode => {\n return childNode.event?.name || 'NO_EVENT_FOR_NODE';\n });\n assert.deepEqual(newTopLevelChildren, []);\n });\n });\n\n describe('BottomUpTimelineTreeView', function() {\n it('Creates a bottom up tree from nestable events', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'sync-like-timings.json.gz');\n const bottomUpTreeView = new Timeline.TimelineTreeView.BottomUpTimelineTreeView();\n const consoleTimings = [...parsedTrace.UserTimings.consoleTimings];\n const startTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min);\n const endTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max);\n bottomUpTreeView.setRange(startTime, endTime);\n bottomUpTreeView.setModelWithEvents(consoleTimings, parsedTrace);\n\n const tree = bottomUpTreeView.buildTree();\n const topNodesIterator = tree.children().values();\n const firstNode = topNodesIterator.next().value as TimelineModel.TimelineProfileTree.Node;\n assert.strictEqual(firstNode.event?.name, 'second console time');\n\n const secondNode = topNodesIterator.next().value as TimelineModel.TimelineProfileTree.Node;\n assert.strictEqual(secondNode.event?.name, 'first console time');\n\n const thirdNode = topNodesIterator.next().value as TimelineModel.TimelineProfileTree.Node;\n assert.strictEqual(thirdNode.event?.name, 'third console time');\n\n const childNode = firstNode.children().values().next().value as TimelineModel.TimelineProfileTree.Node;\n assert.strictEqual(childNode.event?.name, 'first console time');\n });\n });\n\n describe('CallTreeTimelineTreeView', function() {\n it('Creates a call tree from nestable events', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'sync-like-timings.json.gz');\n const callTreeView = new Timeline.TimelineTreeView.CallTreeTimelineTreeView();\n const consoleTimings = [...parsedTrace.UserTimings.consoleTimings];\n const startTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min);\n const endTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max);\n callTreeView.setRange(startTime, endTime);\n callTreeView.setModelWithEvents(consoleTimings, parsedTrace);\n\n const tree = callTreeView.buildTree();\n const topNodesIterator = tree.children().values();\n const firstNode = topNodesIterator.next().value as TimelineModel.TimelineProfileTree.Node;\n assert.strictEqual(firstNode.event?.name, 'first console time');\n\n const secondNode = topNodesIterator.next().value as TimelineModel.TimelineProfileTree.Node;\n assert.strictEqual(secondNode.event?.name, 'third console time');\n\n const childNode = firstNode.children().values().next().value as TimelineModel.TimelineProfileTree.Node;\n assert.strictEqual(childNode.event?.name, 'second console time');\n });\n });\n\n describe('event grouping', function() {\n it('groups events by category in the Call Tree view', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'sync-like-timings.json.gz');\n const callTreeView = new Timeline.TimelineTreeView.CallTreeTimelineTreeView();\n const consoleTimings = [...parsedTrace.UserTimings.consoleTimings];\n const startTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min);\n const endTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max);\n callTreeView.setRange(startTime, endTime);\n callTreeView.setGroupBySettingForTests(Timeline.TimelineTreeView.AggregatedTimelineTreeView.GroupBy.Category);\n callTreeView.setModelWithEvents(consoleTimings, parsedTrace);\n const tree = callTreeView.buildTree();\n const treeEntries = tree.children().entries();\n const groupEntry = treeEntries.next();\n const nodeName = groupEntry.value[0];\n const node = groupEntry.value[1];\n assert.strictEqual(nodeName, 'scripting');\n assert.strictEqual(callTreeView.displayInfoForGroupNode(node).color, 'rgb(250 204 21 / 100%)');\n\n assert.isTrue(node.isGroupNode());\n const children = node.children().values();\n assert.strictEqual(children.next().value.event.name, 'first console time');\n assert.strictEqual(children.next().value.event.name, 'third console time');\n });\n it('groups events by category in the Bottom up Tree view', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'sync-like-timings.json.gz');\n const callTreeView = new Timeline.TimelineTreeView.BottomUpTimelineTreeView();\n const consoleTimings = [...parsedTrace.UserTimings.consoleTimings];\n const startTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min);\n const endTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max);\n callTreeView.setRange(startTime, endTime);\n callTreeView.setGroupBySettingForTests(Timeline.TimelineTreeView.AggregatedTimelineTreeView.GroupBy.Category);\n callTreeView.setModelWithEvents(consoleTimings, parsedTrace);\n const tree = callTreeView.buildTree();\n const treeEntries = tree.children().entries();\n const groupEntry = treeEntries.next();\n const nodeName = groupEntry.value[0];\n const node = groupEntry.value[1];\n assert.strictEqual(nodeName, 'scripting');\n assert.strictEqual(callTreeView.displayInfoForGroupNode(node).color, 'rgb(250 204 21 / 100%)');\n\n assert.isTrue(node.isGroupNode());\n const children = node.children().values();\n assert.strictEqual(children.next().value.event.name, 'second console time');\n assert.strictEqual(children.next().value.event.name, 'first console time');\n assert.strictEqual(children.next().value.event.name, 'third console time');\n });\n\n it('can group entries by domain', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n const callTreeView = new Timeline.TimelineTreeView.BottomUpTimelineTreeView();\n const startTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min);\n const endTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max);\n\n callTreeView.setRange(startTime, endTime);\n callTreeView.setGroupBySettingForTests(Timeline.TimelineTreeView.AggregatedTimelineTreeView.GroupBy.Domain);\n callTreeView.setModelWithEvents(parsedTrace.Renderer.allTraceEntries, parsedTrace);\n\n const tree = callTreeView.buildTree();\n const topLevelGroupNodes = Array.from(tree.children().entries());\n\n assert.deepEqual(topLevelGroupNodes.map(node => node[0]), [\n '',\n 'web.dev',\n 'extensions::',\n 'chrome-extension://noondiphcddnnabmjcihcjfbhfklnnep',\n 'imgix.net',\n 'googletagmanager.com',\n 'google-analytics.com',\n 'web.app',\n ]);\n });\n\n it('can group entries by third parties', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n const callTreeView = new Timeline.TimelineTreeView.BottomUpTimelineTreeView();\n const startTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min);\n const endTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max);\n\n callTreeView.setRange(startTime, endTime);\n callTreeView.setGroupBySettingForTests(Timeline.TimelineTreeView.AggregatedTimelineTreeView.GroupBy.ThirdParties);\n callTreeView.setModelWithEvents(parsedTrace.Renderer.allTraceEntries, parsedTrace);\n\n const tree = callTreeView.buildTree();\n const topLevelGroupNodes = Array.from(tree.children().entries());\n\n assert.deepEqual(topLevelGroupNodes.map(node => node[0]), [\n '',\n 'web.dev',\n 'extensions::',\n 'chrome-extension://noondiphcddnnabmjcihcjfbhfklnnep',\n 'imgix',\n 'Google Tag Manager',\n 'Google Analytics',\n 'shared-storage-demo-content-producer.web.app',\n ]);\n });\n\n it('can group entries by frame', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n const callTreeView = new Timeline.TimelineTreeView.BottomUpTimelineTreeView();\n const startTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min);\n const endTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max);\n\n callTreeView.setRange(startTime, endTime);\n callTreeView.setGroupBySettingForTests(Timeline.TimelineTreeView.AggregatedTimelineTreeView.GroupBy.Frame);\n callTreeView.setModelWithEvents(parsedTrace.Renderer.allTraceEntries, parsedTrace);\n\n const tree = callTreeView.buildTree();\n const topLevelGroupNodes = Array.from(tree.children().entries());\n\n assert.deepEqual(topLevelGroupNodes.map(node => node[0]), [\n '25D2F12F1818C70B5BD4325CC9ACD8FF',\n '1094B71EC09B8BD3DD48B77D091D6024',\n ]);\n });\n\n it('can group entries by URL', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n const callTreeView = new Timeline.TimelineTreeView.BottomUpTimelineTreeView();\n const startTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min);\n const endTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max);\n\n callTreeView.setRange(startTime, endTime);\n callTreeView.setGroupBySettingForTests(Timeline.TimelineTreeView.AggregatedTimelineTreeView.GroupBy.URL);\n callTreeView.setModelWithEvents(parsedTrace.Renderer.allTraceEntries, parsedTrace);\n\n const tree = callTreeView.buildTree();\n const topLevelGroupNodes = Array.from(tree.children().entries());\n\n assert.deepEqual(topLevelGroupNodes.map(node => node[0]), [\n '', // Represents \"Unattributed\" in the UI\n 'https://web.dev/',\n 'extensions::SafeBuiltins',\n 'chrome-extension://noondiphcddnnabmjcihcjfbhfklnnep/content_script_compiled.js',\n 'https://web-dev.imgix.net/image/kheDArv5csY6rvQUJDbWRscckLr1/4i7JstVZvgTFk9dxCe4a.svg',\n 'https://web.dev/js/home.js?v=73b0d143',\n 'https://web.dev/js/actions-f0eb5c8e.js',\n 'https://web.dev/js/app.js?v=fedf5fbe',\n 'https://web.dev/js/index-f45448ab.js',\n 'https://web.dev/js/index-7e29abb6.js',\n 'https://www.googletagmanager.com/gtm.js?id=GTM-MZWCJPP',\n 'https://www.google-analytics.com/analytics.js',\n 'https://www.googletagmanager.com/gtag/js?id=G-18JR3Q8PJ8&l=dataLayer&cx=c',\n 'https://www.google-analytics.com/j/collect?v=1&_v=j101&a=68725886&t=event&ni=1&_s=1&dl=https%3A%2F%2Fweb.dev%2F&ul=en-gb&de=UTF-8&dt=web.dev&sd=24-bit&sr=3360x1890&vp=1665x846&je=0&ec=Web%20Vitals&ea=FCP&el=v3-1696581005645-6472407333688&ev=129&_u=QACAAEABAAAAACAAIg~&jid=&gjid=&cid=1874137241.1685438100&tid=UA-126406676-2&_gid=656288571.1696581004&_slc=1>m=45He3a40n81MZWCJPP&cd5=15&cd6=navigate&cd7=light&cd8=dom-content-loaded&cd9=8&z=54974500',\n 'https://shared-storage-demo-content-producer.web.app/paa/scripts/private-aggregation-test.js',\n 'https://shared-storage-demo-content-producer.web.app/paa/scripts/private-aggregation-test.html',\n 'https://web-dev.imgix.net/image/SZHNhsfjU9RbCestTGZU6N7JEWs1/VwL892KEz6bakZMlq10D.png?auto=format&w=740',\n ]);\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineUIUtils.d.ts b/public/panels/timeline/TimelineUIUtils.d.ts index 6d699aa32..1a3192ea0 100644 --- a/public/panels/timeline/TimelineUIUtils.d.ts +++ b/public/panels/timeline/TimelineUIUtils.d.ts @@ -2,7 +2,7 @@ import * as Platform from '../../core/platform/platform.js'; import * as SDK from '../../core/sdk/sdk.js'; import type * as Protocol from '../../generated/protocol.js'; import * as TimelineModel from '../../models/timeline_model/timeline_model.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as LegacyComponents from '../../ui/legacy/components/utils/utils.js'; import * as TimelineComponents from './components/components.js'; type LinkifyLocationOptions = { @@ -16,48 +16,48 @@ type LinkifyLocationOptions = { }; export declare class TimelineUIUtils { static frameDisplayName(frame: Protocol.Runtime.CallFrame): string; - static testContentMatching(traceEvent: TraceEngine.Types.TraceEvents.TraceEventData, regExp: RegExp, traceParsedData?: TraceEngine.Handlers.Types.TraceParseData): boolean; - static eventStyle(event: TraceEngine.Types.TraceEvents.TraceEventData): TimelineComponents.EntryStyles.TimelineRecordStyle; - static eventColor(event: TraceEngine.Types.TraceEvents.TraceEventData): string; - static eventTitle(event: TraceEngine.Types.TraceEvents.TraceEventData): string; + static testContentMatching(traceEvent: Trace.Types.Events.Event, regExp: RegExp, parsedTrace?: Trace.Handlers.Types.ParsedTrace): boolean; + static eventStyle(event: Trace.Types.Events.Event): TimelineComponents.EntryStyles.TimelineRecordStyle; + static eventColor(event: Trace.Types.Events.Event): string; + static eventTitle(event: Trace.Types.Events.Event): string; static isUserFrame(frame: Protocol.Runtime.CallFrame): boolean; - static buildDetailsTextForTraceEvent(event: TraceEngine.Types.TraceEvents.TraceEventData, traceParsedData: TraceEngine.Handlers.Types.TraceParseData): Promise; - static buildDetailsNodeForTraceEvent(event: TraceEngine.Types.TraceEvents.TraceEventData, target: SDK.Target.Target | null, linkifier: LegacyComponents.Linkifier.Linkifier, isFreshRecording: boolean | undefined, traceParsedData: TraceEngine.Handlers.Types.TraceParseData): Promise; + static buildDetailsTextForTraceEvent(event: Trace.Types.Events.Event, parsedTrace: Trace.Handlers.Types.ParsedTrace): Promise; + static buildDetailsNodeForTraceEvent(event: Trace.Types.Events.Event, target: SDK.Target.Target | null, linkifier: LegacyComponents.Linkifier.Linkifier, isFreshRecording: boolean | undefined, parsedTrace: Trace.Handlers.Types.ParsedTrace): Promise; static linkifyLocation(linkifyOptions: LinkifyLocationOptions): Element | null; - static linkifyTopCallFrame(event: TraceEngine.Types.TraceEvents.TraceEventData, target: SDK.Target.Target | null, linkifier: LegacyComponents.Linkifier.Linkifier, isFreshRecording?: boolean): Element | null; - static buildDetailsNodeForMarkerEvents(event: TraceEngine.Types.TraceEvents.MarkerEvent): HTMLElement; + static linkifyTopCallFrame(event: Trace.Types.Events.Event, target: SDK.Target.Target | null, linkifier: LegacyComponents.Linkifier.Linkifier, isFreshRecording?: boolean): Element | null; + static buildDetailsNodeForMarkerEvents(event: Trace.Types.Events.MarkerEvent): HTMLElement; static buildConsumeCacheDetails(eventData: { consumedCacheSize?: number; cacheRejected?: boolean; cacheKind?: string; }, contentHelper: TimelineDetailsContentHelper): void; - static buildTraceEventDetails(traceParseData: TraceEngine.Handlers.Types.TraceParseData, event: TraceEngine.Types.TraceEvents.TraceEventData, linkifier: LegacyComponents.Linkifier.Linkifier, detailed: boolean): Promise; - static statsForTimeRange(events: TraceEngine.Types.TraceEvents.TraceEventData[], startTime: TraceEngine.Types.Timing.MilliSeconds, endTime: TraceEngine.Types.Timing.MilliSeconds): { + static buildTraceEventDetails(parsedTrace: Trace.Handlers.Types.ParsedTrace, event: Trace.Types.Events.Event, linkifier: LegacyComponents.Linkifier.Linkifier, detailed: boolean): Promise; + static statsForTimeRange(events: Trace.Types.Events.Event[], startTime: Trace.Types.Timing.MilliSeconds, endTime: Trace.Types.Timing.MilliSeconds): { [x: string]: number; }; private static renderEventJson; private static renderObjectJson; - static stackTraceFromCallFrames(callFrames: Protocol.Runtime.CallFrame[] | TraceEngine.Types.TraceEvents.TraceEventCallFrame[]): Protocol.Runtime.StackTrace; + static stackTraceFromCallFrames(callFrames: Protocol.Runtime.CallFrame[] | Trace.Types.Events.CallFrame[]): Protocol.Runtime.StackTrace; private static generateCauses; private static createEntryLink; private static generateInvalidationsList; private static generateInvalidationsForReason; private static aggregatedStatsForTraceEvent; - static buildPicturePreviewContent(traceData: TraceEngine.Handlers.Types.TraceParseData, event: TraceEngine.Types.TraceEvents.TraceEventPaint, target: SDK.Target.Target): Promise; - static createEventDivider(event: TraceEngine.Types.TraceEvents.TraceEventData, zeroTime: number): Element; + static buildPicturePreviewContent(parsedTrace: Trace.Handlers.Types.ParsedTrace, event: Trace.Types.Events.Paint, target: SDK.Target.Target): Promise; + static createEventDivider(event: Trace.Types.Events.Event, zeroTime: number): Element; static visibleEventsFilter(): TimelineModel.TimelineModelFilter.TimelineModelFilter; static categories(): TimelineComponents.EntryStyles.CategoryPalette; static generatePieChart(aggregatedStats: { [x: string]: number; }, selfCategory?: TimelineComponents.EntryStyles.TimelineCategory, selfTime?: number): Element; - static generateDetailsContentForFrame(frame: TraceEngine.Types.TraceEvents.LegacyTimelineFrame, filmStrip: TraceEngine.Extras.FilmStrip.Data | null, filmStripFrame: TraceEngine.Extras.FilmStrip.Frame | null): DocumentFragment; - static frameDuration(frame: TraceEngine.Types.TraceEvents.LegacyTimelineFrame): Element; + static generateDetailsContentForFrame(frame: Trace.Types.Events.LegacyTimelineFrame, filmStrip: Trace.Extras.FilmStrip.Data | null, filmStripFrame: Trace.Extras.FilmStrip.Frame | null): DocumentFragment; + static frameDuration(frame: Trace.Types.Events.LegacyTimelineFrame): Element; static quadWidth(quad: number[]): number; static quadHeight(quad: number[]): number; static eventDispatchDesciptors(): EventDispatchTypeDescriptor[]; - static markerStyleForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): TimelineMarkerStyle; + static markerStyleForEvent(event: Trace.Types.Events.Event): TimelineMarkerStyle; static colorForId(id: string): string; - static displayNameForFrame(frame: TraceEngine.Types.TraceEvents.TraceFrame, trimAt?: number): string; + static displayNameForFrame(frame: Trace.Types.Events.TraceFrame, trimAt?: number): string; } export declare const aggregatedStatsKey: unique symbol; export declare const previewElementSymbol: unique symbol; @@ -97,12 +97,12 @@ export interface TimelineMarkerStyle { * where the user has navigated multiple times in the trace, so that we can show * the LCP (for example) relative to the last navigation. **/ -export declare function timeStampForEventAdjustedForClosestNavigationIfPossible(event: TraceEngine.Types.TraceEvents.TraceEventData, traceParsedData: TraceEngine.Handlers.Types.TraceParseData | null): TraceEngine.Types.Timing.MilliSeconds; +export declare function timeStampForEventAdjustedForClosestNavigationIfPossible(event: Trace.Types.Events.Event, parsedTrace: Trace.Handlers.Types.ParsedTrace | null): Trace.Types.Timing.MilliSeconds; /** * Determines if an event is potentially a marker event. A marker event here * is a single moment in time that we want to highlight on the timeline, such as * the LCP time. This method does not filter out events: for example, it treats * every LCP Candidate event as a potential marker event. **/ -export declare function isMarkerEvent(traceParseData: TraceEngine.Handlers.Types.TraceParseData, event: TraceEngine.Types.TraceEvents.TraceEventData): boolean; +export declare function isMarkerEvent(parsedTrace: Trace.Handlers.Types.ParsedTrace, event: Trace.Types.Events.Event): boolean; export {}; diff --git a/public/panels/timeline/TimelineUIUtils.js b/public/panels/timeline/TimelineUIUtils.js index 1b5a4e2c1..af5f9cffe 100644 --- a/public/panels/timeline/TimelineUIUtils.js +++ b/public/panels/timeline/TimelineUIUtils.js @@ -38,7 +38,7 @@ import * as Root from '../../core/root/root.js'; import * as SDK from '../../core/sdk/sdk.js'; import * as Bindings from '../../models/bindings/bindings.js'; import * as TimelineModel from '../../models/timeline_model/timeline_model.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as TraceBounds from '../../services/trace_bounds/trace_bounds.js'; import * as CodeHighlighter from '../../ui/components/code_highlighter/code_highlighter.js'; // eslint-disable-next-line rulesdir/es_modules_import @@ -47,8 +47,6 @@ import * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js'; // eslint-disable-next-line rulesdir/es_modules_import import imagePreviewStyles from '../../ui/legacy/components/utils/imagePreview.css.js'; import * as LegacyComponents from '../../ui/legacy/components/utils/utils.js'; -// eslint-disable-next-line rulesdir/es_modules_import -import inspectorCommonStyles from '../../ui/legacy/inspectorCommon.css.js'; import * as UI from '../../ui/legacy/legacy.js'; import { CLSRect } from './CLSLinkifier.js'; import * as TimelineComponents from './components/components.js'; @@ -274,10 +272,6 @@ const UIStrings = { *@description Text used to tell the user they are viewing an event that has a function embedded in it, which is referred to as the "callback function". */ callbackFunction: 'Callback function', - /** - *@description The current state of an item - */ - state: 'State', /** *@description Text used to show the relevant range of a file - e.g. "lines 2-10". */ @@ -412,6 +406,32 @@ const UIStrings = { *@description Stack label in Timeline UIUtils of the Performance panel */ layoutForced: 'Layout forced', + /** + *@description Label in front of CSS property (eg `opacity`) being animated or a CSS animation name (eg `layer-4-fade-in-out`) + */ + animating: 'Animating', + /** + *@description Label in front of reasons why a CSS animation wasn't composited (aka hardware accelerated) + */ + compositingFailed: 'Compositing failed', + /** + * @description [ICU Syntax] Descriptive reason for why a user-provided animation failed to be optimized by the browser due to the animated CSS property not being supported on the compositor. Shown in a table with a list of other potential failure reasons. + * @example {height, width} properties + */ + unsupportedCSSProperty: `{propertyCount, plural, + =1 {Unsupported CSS property: {properties}} + other {Unsupported CSS properties: {properties}} + }`, + /** Descriptive reason for why a user-provided animation failed to be optimized by the browser due to a `transform` property being dependent on the size of the element itself. Shown in a table with a list of other potential failure reasons. */ + transformDependsBoxSize: 'Transform-related property depends on box size', + /** Descriptive reason for why a user-provided animation failed to be optimized by the browser due to a `filter` property possibly moving pixels. Shown in a table with a list of other potential failure reasons. */ + filterMayMovePixels: 'Filter-related property may move pixels', + /** Descriptive reason for why a user-provided animation failed to be optimized by the browser due to an effect having a composite mode which is not `replace`. Shown in a table with a list of other potential failure reasons. */ + nonReplaceCompositeMode: 'Effect has composite mode other than "replace"', + /** Descriptive reason for why a user-provided animation failed to be optimized by the browser due to another animation on the same target being incompatible. Shown in a table with a list of other potential failure reasons. */ + incompatibleAnimations: 'Target has another animation which is incompatible', + /** Descriptive reason for why a user-provided animation failed to be optimized by the browser due to an effect having unsupported timing parameters. Shown in a table with a list of other potential failure reasons. */ + unsupportedTimingParameters: 'Effect has unsupported timing parameters', /** *@description Text for the execution stack trace */ @@ -515,25 +535,25 @@ export class TimelineUIUtils { } return frame.functionName; } - static testContentMatching(traceEvent, regExp, traceParsedData) { + static testContentMatching(traceEvent, regExp, parsedTrace) { const title = TimelineUIUtils.eventStyle(traceEvent).title; const tokens = [title]; - if (TraceEngine.Types.TraceEvents.isProfileCall(traceEvent)) { + if (Trace.Types.Events.isProfileCall(traceEvent)) { // In the future this case will not be possible - wherever we call this // function we will be able to pass in the data from the new engine. But // currently this is called in a variety of places including from the // legacy model which does not have a reference to the new engine's data. // So if we are missing the data, we just fallback to the name from the // callFrame. - if (!traceParsedData || !traceParsedData.Samples) { + if (!parsedTrace || !parsedTrace.Samples) { tokens.push(traceEvent.callFrame.functionName); } else { - tokens.push(TraceEngine.Handlers.ModelHandlers.Samples.getProfileCallFunctionName(traceParsedData.Samples, traceEvent)); + tokens.push(Trace.Handlers.ModelHandlers.Samples.getProfileCallFunctionName(parsedTrace.Samples, traceEvent)); } } - if (traceParsedData) { - const url = TraceEngine.Extras.URLForEntry.get(traceParsedData, traceEvent); + if (parsedTrace) { + const url = Trace.Extras.URLForEntry.get(parsedTrace, traceEvent); if (url) { tokens.push(url); } @@ -561,30 +581,29 @@ export class TimelineUIUtils { } } static eventStyle(event) { - if (TraceEngine.Types.TraceEvents.isProfileCall(event) && event.callFrame.functionName === '(idle)') { + if (Trace.Types.Events.isProfileCall(event) && event.callFrame.functionName === '(idle)') { return new TimelineComponents.EntryStyles.TimelineRecordStyle(event.name, TimelineComponents.EntryStyles.getCategoryStyles().idle); } - if (event.cat === TraceEngine.Types.TraceEvents.Categories.Console || - event.cat === TraceEngine.Types.TraceEvents.Categories.UserTiming) { + if (event.cat === Trace.Types.Events.Categories.Console || event.cat === Trace.Types.Events.Categories.UserTiming) { return new TimelineComponents.EntryStyles.TimelineRecordStyle(event.name, TimelineComponents.EntryStyles.getCategoryStyles()['scripting']); } return TimelineComponents.EntryStyles.getEventStyle(event.name) ?? new TimelineComponents.EntryStyles.TimelineRecordStyle(event.name, TimelineComponents.EntryStyles.getCategoryStyles().other); } static eventColor(event) { - if (TraceEngine.Types.TraceEvents.isProfileCall(event)) { + if (Trace.Types.Events.isProfileCall(event)) { const frame = event.callFrame; if (TimelineUIUtils.isUserFrame(frame)) { return TimelineUIUtils.colorForId(frame.url); } } - if (TraceEngine.Types.Extensions.isSyntheticExtensionEntry(event)) { + if (Trace.Types.Extensions.isSyntheticExtensionEntry(event)) { return Extensions.ExtensionUI.extensionEntryColor(event); } let parsedColor = TimelineUIUtils.eventStyle(event).category.getComputedColorValue(); // This event is considered idle time but still rendered as a scripting event here // to connect the StreamingCompileScriptParsing events it belongs to. - if (event.name === "v8.parseOnBackgroundWaiting" /* TraceEngine.Types.TraceEvents.KnownEventName.STREAMING_COMPILE_SCRIPT_WAITING */) { + if (event.name === "v8.parseOnBackgroundWaiting" /* Trace.Types.Events.Name.STREAMING_COMPILE_SCRIPT_WAITING */) { parsedColor = TimelineComponents.EntryStyles.getCategoryStyles().scripting.getComputedColorValue(); if (!parsedColor) { throw new Error('Unable to parse color from getCategoryStyles().scripting.color'); @@ -596,26 +615,26 @@ export class TimelineUIUtils { // Profile call events do not have a args.data property, thus, we // need to check for profile calls in the beginning of this // function. - if (TraceEngine.Types.TraceEvents.isProfileCall(event)) { + if (Trace.Types.Events.isProfileCall(event)) { const maybeResolvedName = SourceMapsResolver.resolvedNodeNameForEntry(event); const displayName = maybeResolvedName || TimelineUIUtils.frameDisplayName(event.callFrame); return displayName; } - if (event.name === 'EventTiming' && TraceEngine.Types.TraceEvents.isSyntheticInteractionEvent(event)) { + if (event.name === 'EventTiming' && Trace.Types.Events.isSyntheticInteraction(event)) { // TODO(crbug.com/365047728): replace this entire method with this call. return TimelineComponents.EntryName.nameForEntry(event); } const title = TimelineUIUtils.eventStyle(event).title; - if (TraceEngine.Helpers.Trace.eventHasCategory(event, TraceEngine.Types.TraceEvents.Categories.Console)) { + if (Trace.Helpers.Trace.eventHasCategory(event, Trace.Types.Events.Categories.Console)) { return title; } - if (TraceEngine.Types.TraceEvents.isTraceEventTimeStamp(event)) { + if (Trace.Types.Events.isTimeStamp(event)) { return i18nString(UIStrings.sS, { PH1: title, PH2: event.args.data.message }); } - if (TraceEngine.Types.TraceEvents.isTraceEventAnimation(event) && event.args.data.name) { + if (Trace.Types.Events.isAnimation(event) && event.args.data.name) { return i18nString(UIStrings.sS, { PH1: title, PH2: event.args.data.name }); } - if (TraceEngine.Types.TraceEvents.isTraceEventDispatch(event)) { + if (Trace.Types.Events.isDispatch(event)) { return i18nString(UIStrings.sS, { PH1: title, PH2: event.args.data.type }); } return title; @@ -623,7 +642,7 @@ export class TimelineUIUtils { static isUserFrame(frame) { return frame.scriptId !== '0' && !(frame.url && frame.url.startsWith('native ')); } - static async buildDetailsTextForTraceEvent(event, traceParsedData) { + static async buildDetailsTextForTraceEvent(event, parsedTrace) { let detailsText; // TODO(40287735): update this code with type-safe data checks. // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -631,24 +650,24 @@ export class TimelineUIUtils { // eslint-disable-next-line @typescript-eslint/no-explicit-any const unsafeEventData = event.args?.data; switch (event.name) { - case "GCEvent" /* TraceEngine.Types.TraceEvents.KnownEventName.GC */: - case "MajorGC" /* TraceEngine.Types.TraceEvents.KnownEventName.MAJOR_GC */: - case "MinorGC" /* TraceEngine.Types.TraceEvents.KnownEventName.MINOR_GC */: { + case "GCEvent" /* Trace.Types.Events.Name.GC */: + case "MajorGC" /* Trace.Types.Events.Name.MAJOR_GC */: + case "MinorGC" /* Trace.Types.Events.Name.MINOR_GC */: { const delta = unsafeEventArgs['usedHeapSizeBefore'] - unsafeEventArgs['usedHeapSizeAfter']; detailsText = i18nString(UIStrings.sCollected, { PH1: Platform.NumberUtilities.bytesToString(delta) }); break; } - case "FunctionCall" /* TraceEngine.Types.TraceEvents.KnownEventName.FUNCTION_CALL */: { - const { lineNumber, columnNumber } = TraceEngine.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event); + case "FunctionCall" /* Trace.Types.Events.Name.FUNCTION_CALL */: { + const { lineNumber, columnNumber } = Trace.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event); if (lineNumber !== undefined && columnNumber !== undefined) { detailsText = unsafeEventData.url + ':' + (lineNumber + 1) + ':' + (columnNumber + 1); } break; } - case "EventDispatch" /* TraceEngine.Types.TraceEvents.KnownEventName.EVENT_DISPATCH */: + case "EventDispatch" /* Trace.Types.Events.Name.EVENT_DISPATCH */: detailsText = unsafeEventData ? unsafeEventData['type'] : null; break; - case "Paint" /* TraceEngine.Types.TraceEvents.KnownEventName.PAINT */: { + case "Paint" /* Trace.Types.Events.Name.PAINT */: { const width = TimelineUIUtils.quadWidth(unsafeEventData.clip); const height = TimelineUIUtils.quadHeight(unsafeEventData.clip); if (width && height) { @@ -656,7 +675,7 @@ export class TimelineUIUtils { } break; } - case "ParseHTML" /* TraceEngine.Types.TraceEvents.KnownEventName.PARSE_HTML */: { + case "ParseHTML" /* Trace.Types.Events.Name.PARSE_HTML */: { const startLine = unsafeEventArgs['beginData']['startLine']; const endLine = unsafeEventArgs['endData'] && unsafeEventArgs['endData']['endLine']; const url = Bindings.ResourceUtils.displayNameForURL(unsafeEventArgs['beginData']['url']); @@ -668,72 +687,69 @@ export class TimelineUIUtils { } break; } - case "V8.CompileModule" /* TraceEngine.Types.TraceEvents.KnownEventName.COMPILE_MODULE */: - case "v8.produceModuleCache" /* TraceEngine.Types.TraceEvents.KnownEventName.CACHE_MODULE */: + case "V8.CompileModule" /* Trace.Types.Events.Name.COMPILE_MODULE */: + case "v8.produceModuleCache" /* Trace.Types.Events.Name.CACHE_MODULE */: detailsText = Bindings.ResourceUtils.displayNameForURL(unsafeEventArgs['fileName']); break; - case "V8.CompileScript" /* TraceEngine.Types.TraceEvents.KnownEventName.COMPILE_SCRIPT */: - case "v8.produceCache" /* TraceEngine.Types.TraceEvents.KnownEventName.CACHE_SCRIPT */: - case "EvaluateScript" /* TraceEngine.Types.TraceEvents.KnownEventName.EVALUATE_SCRIPT */: { - const { lineNumber } = TraceEngine.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event); + case "V8.CompileScript" /* Trace.Types.Events.Name.COMPILE_SCRIPT */: + case "v8.produceCache" /* Trace.Types.Events.Name.CACHE_SCRIPT */: + case "EvaluateScript" /* Trace.Types.Events.Name.EVALUATE_SCRIPT */: { + const { lineNumber } = Trace.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event); const url = unsafeEventData && unsafeEventData['url']; if (url) { detailsText = Bindings.ResourceUtils.displayNameForURL(url) + ':' + ((lineNumber || 0) + 1); } break; } - case "v8.wasm.compiledModule" /* TraceEngine.Types.TraceEvents.KnownEventName.WASM_COMPILED_MODULE */: - case "v8.wasm.moduleCacheHit" /* TraceEngine.Types.TraceEvents.KnownEventName.WASM_MODULE_CACHE_HIT */: { + case "v8.wasm.compiledModule" /* Trace.Types.Events.Name.WASM_COMPILED_MODULE */: + case "v8.wasm.moduleCacheHit" /* Trace.Types.Events.Name.WASM_MODULE_CACHE_HIT */: { const url = unsafeEventArgs['url']; if (url) { detailsText = Bindings.ResourceUtils.displayNameForURL(url); } break; } - case "v8.parseOnBackground" /* TraceEngine.Types.TraceEvents.KnownEventName.STREAMING_COMPILE_SCRIPT */: - case "v8.deserializeOnBackground" /* TraceEngine.Types.TraceEvents.KnownEventName.BACKGROUND_DESERIALIZE */: - case "XHRReadyStateChange" /* TraceEngine.Types.TraceEvents.KnownEventName.XHR_READY_STATE_CHANGED */: - case "XHRLoad" /* TraceEngine.Types.TraceEvents.KnownEventName.XHR_LOAD */: { + case "v8.parseOnBackground" /* Trace.Types.Events.Name.STREAMING_COMPILE_SCRIPT */: + case "v8.deserializeOnBackground" /* Trace.Types.Events.Name.BACKGROUND_DESERIALIZE */: + case "XHRReadyStateChange" /* Trace.Types.Events.Name.XHR_READY_STATE_CHANGED */: + case "XHRLoad" /* Trace.Types.Events.Name.XHR_LOAD */: { const url = unsafeEventData['url']; if (url) { detailsText = Bindings.ResourceUtils.displayNameForURL(url); } break; } - case "TimeStamp" /* TraceEngine.Types.TraceEvents.KnownEventName.TIME_STAMP */: + case "TimeStamp" /* Trace.Types.Events.Name.TIME_STAMP */: detailsText = unsafeEventData['message']; break; - case "WebSocketCreate" /* TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_CREATE */: - case "WebSocketSendHandshakeRequest" /* TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_SEND_HANDSHAKE_REQUEST */: - case "WebSocketReceiveHandshakeResponse" /* TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST */: - case "WebSocketSend" /* TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_SEND */: - case "WebSocketReceive" /* TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_RECEIVE */: - case "WebSocketDestroy" /* TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_DESTROY */: - case "ResourceWillSendRequest" /* TraceEngine.Types.TraceEvents.KnownEventName.RESOURCE_WILL_SEND_REQUEST */: - case "ResourceSendRequest" /* TraceEngine.Types.TraceEvents.KnownEventName.RESOURCE_SEND_REQUEST */: - case "ResourceReceivedData" /* TraceEngine.Types.TraceEvents.KnownEventName.RESOURCE_RECEIVE_DATA */: - case "ResourceReceiveResponse" /* TraceEngine.Types.TraceEvents.KnownEventName.RESOURCE_RECEIVE_RESPONSE */: - case "ResourceFinish" /* TraceEngine.Types.TraceEvents.KnownEventName.RESOURCE_FINISH */: - case "PaintImage" /* TraceEngine.Types.TraceEvents.KnownEventName.PAINT_IMAGE */: - case "Decode Image" /* TraceEngine.Types.TraceEvents.KnownEventName.DECODE_IMAGE */: - case "Decode LazyPixelRef" /* TraceEngine.Types.TraceEvents.KnownEventName.DECODE_LAZY_PIXEL_REF */: { - const url = TraceEngine.Extras.URLForEntry.get(traceParsedData, event); + case "WebSocketCreate" /* Trace.Types.Events.Name.WEB_SOCKET_CREATE */: + case "WebSocketSendHandshakeRequest" /* Trace.Types.Events.Name.WEB_SOCKET_SEND_HANDSHAKE_REQUEST */: + case "WebSocketReceiveHandshakeResponse" /* Trace.Types.Events.Name.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST */: + case "WebSocketSend" /* Trace.Types.Events.Name.WEB_SOCKET_SEND */: + case "WebSocketReceive" /* Trace.Types.Events.Name.WEB_SOCKET_RECEIVE */: + case "WebSocketDestroy" /* Trace.Types.Events.Name.WEB_SOCKET_DESTROY */: + case "ResourceWillSendRequest" /* Trace.Types.Events.Name.RESOURCE_WILL_SEND_REQUEST */: + case "ResourceSendRequest" /* Trace.Types.Events.Name.RESOURCE_SEND_REQUEST */: + case "ResourceReceivedData" /* Trace.Types.Events.Name.RESOURCE_RECEIVE_DATA */: + case "ResourceReceiveResponse" /* Trace.Types.Events.Name.RESOURCE_RECEIVE_RESPONSE */: + case "ResourceFinish" /* Trace.Types.Events.Name.RESOURCE_FINISH */: + case "PaintImage" /* Trace.Types.Events.Name.PAINT_IMAGE */: + case "Decode Image" /* Trace.Types.Events.Name.DECODE_IMAGE */: + case "Decode LazyPixelRef" /* Trace.Types.Events.Name.DECODE_LAZY_PIXEL_REF */: { + const url = Trace.Extras.URLForEntry.get(parsedTrace, event); if (url) { detailsText = Bindings.ResourceUtils.displayNameForURL(url); } break; } - case "EmbedderCallback" /* TraceEngine.Types.TraceEvents.KnownEventName.EMBEDDER_CALLBACK */: + case "EmbedderCallback" /* Trace.Types.Events.Name.EMBEDDER_CALLBACK */: detailsText = unsafeEventData['callbackName']; break; - case "Animation" /* TraceEngine.Types.TraceEvents.KnownEventName.ANIMATION */: - detailsText = unsafeEventData && unsafeEventData['name']; - break; - case "AsyncTask" /* TraceEngine.Types.TraceEvents.KnownEventName.ASYNC_TASK */: + case "AsyncTask" /* Trace.Types.Events.Name.ASYNC_TASK */: detailsText = unsafeEventData ? unsafeEventData['name'] : null; break; default: - if (TraceEngine.Helpers.Trace.eventHasCategory(event, TraceEngine.Types.TraceEvents.Categories.Console)) { + if (Trace.Helpers.Trace.eventHasCategory(event, Trace.Types.Events.Categories.Console)) { detailsText = null; } else { @@ -743,14 +759,14 @@ export class TimelineUIUtils { } return detailsText; function linkifyTopCallFrameAsText() { - const frame = TraceEngine.Helpers.Trace.getZeroIndexedStackTraceForEvent(event)?.at(0) ?? null; + const frame = Trace.Helpers.Trace.getZeroIndexedStackTraceForEvent(event)?.at(0) ?? null; if (!frame) { return null; } return frame.url + ':' + (frame.lineNumber + 1) + ':' + (frame.columnNumber + 1); } } - static async buildDetailsNodeForTraceEvent(event, target, linkifier, isFreshRecording = false, traceParsedData) { + static async buildDetailsNodeForTraceEvent(event, target, linkifier, isFreshRecording = false, parsedTrace) { let details = null; let detailsText; // TODO(40287735): update this code with type-safe data checks. @@ -760,39 +776,39 @@ export class TimelineUIUtils { // eslint-disable-next-line @typescript-eslint/no-explicit-any const unsafeEventData = event.args?.data; switch (event.name) { - case "GCEvent" /* TraceEngine.Types.TraceEvents.KnownEventName.GC */: - case "MajorGC" /* TraceEngine.Types.TraceEvents.KnownEventName.MAJOR_GC */: - case "MinorGC" /* TraceEngine.Types.TraceEvents.KnownEventName.MINOR_GC */: - case "EventDispatch" /* TraceEngine.Types.TraceEvents.KnownEventName.EVENT_DISPATCH */: - case "Paint" /* TraceEngine.Types.TraceEvents.KnownEventName.PAINT */: - case "Animation" /* TraceEngine.Types.TraceEvents.KnownEventName.ANIMATION */: - case "EmbedderCallback" /* TraceEngine.Types.TraceEvents.KnownEventName.EMBEDDER_CALLBACK */: - case "ParseHTML" /* TraceEngine.Types.TraceEvents.KnownEventName.PARSE_HTML */: - case "v8.wasm.streamFromResponseCallback" /* TraceEngine.Types.TraceEvents.KnownEventName.WASM_STREAM_FROM_RESPONSE_CALLBACK */: - case "v8.wasm.compiledModule" /* TraceEngine.Types.TraceEvents.KnownEventName.WASM_COMPILED_MODULE */: - case "v8.wasm.moduleCacheHit" /* TraceEngine.Types.TraceEvents.KnownEventName.WASM_MODULE_CACHE_HIT */: - case "v8.wasm.cachedModule" /* TraceEngine.Types.TraceEvents.KnownEventName.WASM_CACHED_MODULE */: - case "v8.wasm.moduleCacheInvalid" /* TraceEngine.Types.TraceEvents.KnownEventName.WASM_MODULE_CACHE_INVALID */: - case "WebSocketCreate" /* TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_CREATE */: - case "WebSocketSendHandshakeRequest" /* TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_SEND_HANDSHAKE_REQUEST */: - case "WebSocketReceiveHandshakeResponse" /* TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST */: - case "WebSocketSend" /* TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_SEND */: - case "WebSocketReceive" /* TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_RECEIVE */: - case "WebSocketDestroy" /* TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_DESTROY */: { - detailsText = await TimelineUIUtils.buildDetailsTextForTraceEvent(event, traceParsedData); - break; - } - case "PaintImage" /* TraceEngine.Types.TraceEvents.KnownEventName.PAINT_IMAGE */: - case "Decode Image" /* TraceEngine.Types.TraceEvents.KnownEventName.DECODE_IMAGE */: - case "Decode LazyPixelRef" /* TraceEngine.Types.TraceEvents.KnownEventName.DECODE_LAZY_PIXEL_REF */: - case "XHRReadyStateChange" /* TraceEngine.Types.TraceEvents.KnownEventName.XHR_READY_STATE_CHANGED */: - case "XHRLoad" /* TraceEngine.Types.TraceEvents.KnownEventName.XHR_LOAD */: - case "ResourceWillSendRequest" /* TraceEngine.Types.TraceEvents.KnownEventName.RESOURCE_WILL_SEND_REQUEST */: - case "ResourceSendRequest" /* TraceEngine.Types.TraceEvents.KnownEventName.RESOURCE_SEND_REQUEST */: - case "ResourceReceivedData" /* TraceEngine.Types.TraceEvents.KnownEventName.RESOURCE_RECEIVE_DATA */: - case "ResourceReceiveResponse" /* TraceEngine.Types.TraceEvents.KnownEventName.RESOURCE_RECEIVE_RESPONSE */: - case "ResourceFinish" /* TraceEngine.Types.TraceEvents.KnownEventName.RESOURCE_FINISH */: { - const url = TraceEngine.Extras.URLForEntry.get(traceParsedData, event); + case "GCEvent" /* Trace.Types.Events.Name.GC */: + case "MajorGC" /* Trace.Types.Events.Name.MAJOR_GC */: + case "MinorGC" /* Trace.Types.Events.Name.MINOR_GC */: + case "EventDispatch" /* Trace.Types.Events.Name.EVENT_DISPATCH */: + case "Paint" /* Trace.Types.Events.Name.PAINT */: + case "Animation" /* Trace.Types.Events.Name.ANIMATION */: + case "EmbedderCallback" /* Trace.Types.Events.Name.EMBEDDER_CALLBACK */: + case "ParseHTML" /* Trace.Types.Events.Name.PARSE_HTML */: + case "v8.wasm.streamFromResponseCallback" /* Trace.Types.Events.Name.WASM_STREAM_FROM_RESPONSE_CALLBACK */: + case "v8.wasm.compiledModule" /* Trace.Types.Events.Name.WASM_COMPILED_MODULE */: + case "v8.wasm.moduleCacheHit" /* Trace.Types.Events.Name.WASM_MODULE_CACHE_HIT */: + case "v8.wasm.cachedModule" /* Trace.Types.Events.Name.WASM_CACHED_MODULE */: + case "v8.wasm.moduleCacheInvalid" /* Trace.Types.Events.Name.WASM_MODULE_CACHE_INVALID */: + case "WebSocketCreate" /* Trace.Types.Events.Name.WEB_SOCKET_CREATE */: + case "WebSocketSendHandshakeRequest" /* Trace.Types.Events.Name.WEB_SOCKET_SEND_HANDSHAKE_REQUEST */: + case "WebSocketReceiveHandshakeResponse" /* Trace.Types.Events.Name.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST */: + case "WebSocketSend" /* Trace.Types.Events.Name.WEB_SOCKET_SEND */: + case "WebSocketReceive" /* Trace.Types.Events.Name.WEB_SOCKET_RECEIVE */: + case "WebSocketDestroy" /* Trace.Types.Events.Name.WEB_SOCKET_DESTROY */: { + detailsText = await TimelineUIUtils.buildDetailsTextForTraceEvent(event, parsedTrace); + break; + } + case "PaintImage" /* Trace.Types.Events.Name.PAINT_IMAGE */: + case "Decode Image" /* Trace.Types.Events.Name.DECODE_IMAGE */: + case "Decode LazyPixelRef" /* Trace.Types.Events.Name.DECODE_LAZY_PIXEL_REF */: + case "XHRReadyStateChange" /* Trace.Types.Events.Name.XHR_READY_STATE_CHANGED */: + case "XHRLoad" /* Trace.Types.Events.Name.XHR_LOAD */: + case "ResourceWillSendRequest" /* Trace.Types.Events.Name.RESOURCE_WILL_SEND_REQUEST */: + case "ResourceSendRequest" /* Trace.Types.Events.Name.RESOURCE_SEND_REQUEST */: + case "ResourceReceivedData" /* Trace.Types.Events.Name.RESOURCE_RECEIVE_DATA */: + case "ResourceReceiveResponse" /* Trace.Types.Events.Name.RESOURCE_RECEIVE_RESPONSE */: + case "ResourceFinish" /* Trace.Types.Events.Name.RESOURCE_FINISH */: { + const url = Trace.Extras.URLForEntry.get(parsedTrace, event); if (url) { const options = { tabStop: true, @@ -803,14 +819,14 @@ export class TimelineUIUtils { } break; } - case "FunctionCall" /* TraceEngine.Types.TraceEvents.KnownEventName.FUNCTION_CALL */: { + case "FunctionCall" /* Trace.Types.Events.Name.FUNCTION_CALL */: { details = document.createElement('span'); // FunctionCall events have an args.data that could be a CallFrame, if all the details are present, so we check for that. - if (TraceEngine.Types.TraceEvents.isTraceEventFunctionCall(event) && event.args.data && - TraceEngine.Types.TraceEvents.objectIsTraceEventCallFrame(event.args.data)) { + if (Trace.Types.Events.isFunctionCall(event) && event.args.data && + Trace.Types.Events.objectIsCallFrame(event.args.data)) { UI.UIUtils.createTextChild(details, TimelineUIUtils.frameDisplayName({ ...event.args.data, scriptId: String(event.args.data.scriptId) })); } - const { lineNumber, columnNumber } = TraceEngine.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event); + const { lineNumber, columnNumber } = Trace.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event); const location = this.linkifyLocation({ scriptId: unsafeEventData['scriptId'], url: unsafeEventData['url'], @@ -826,8 +842,8 @@ export class TimelineUIUtils { } break; } - case "V8.CompileModule" /* TraceEngine.Types.TraceEvents.KnownEventName.COMPILE_MODULE */: - case "v8.produceModuleCache" /* TraceEngine.Types.TraceEvents.KnownEventName.CACHE_MODULE */: { + case "V8.CompileModule" /* Trace.Types.Events.Name.COMPILE_MODULE */: + case "v8.produceModuleCache" /* Trace.Types.Events.Name.CACHE_MODULE */: { details = this.linkifyLocation({ scriptId: null, url: unsafeEventArgs['fileName'], @@ -839,12 +855,12 @@ export class TimelineUIUtils { }); break; } - case "V8.CompileScript" /* TraceEngine.Types.TraceEvents.KnownEventName.COMPILE_SCRIPT */: - case "v8.produceCache" /* TraceEngine.Types.TraceEvents.KnownEventName.CACHE_SCRIPT */: - case "EvaluateScript" /* TraceEngine.Types.TraceEvents.KnownEventName.EVALUATE_SCRIPT */: { + case "V8.CompileScript" /* Trace.Types.Events.Name.COMPILE_SCRIPT */: + case "v8.produceCache" /* Trace.Types.Events.Name.CACHE_SCRIPT */: + case "EvaluateScript" /* Trace.Types.Events.Name.EVALUATE_SCRIPT */: { const url = unsafeEventData['url']; if (url) { - const { lineNumber } = TraceEngine.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event); + const { lineNumber } = Trace.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event); details = this.linkifyLocation({ scriptId: null, url, @@ -857,18 +873,18 @@ export class TimelineUIUtils { } break; } - case "v8.deserializeOnBackground" /* TraceEngine.Types.TraceEvents.KnownEventName.BACKGROUND_DESERIALIZE */: - case "v8.parseOnBackground" /* TraceEngine.Types.TraceEvents.KnownEventName.STREAMING_COMPILE_SCRIPT */: { + case "v8.deserializeOnBackground" /* Trace.Types.Events.Name.BACKGROUND_DESERIALIZE */: + case "v8.parseOnBackground" /* Trace.Types.Events.Name.STREAMING_COMPILE_SCRIPT */: { const url = unsafeEventData['url']; if (url) { details = this.linkifyLocation({ scriptId: null, url, lineNumber: 0, columnNumber: 0, target, isFreshRecording, linkifier }); } break; } - case "ProfileCall" /* TraceEngine.Types.TraceEvents.KnownEventName.PROFILE_CALL */: { + case "ProfileCall" /* Trace.Types.Events.Name.PROFILE_CALL */: { details = document.createElement('span'); // This check is only added for convenience with the type checker. - if (!TraceEngine.Types.TraceEvents.isProfileCall(event)) { + if (!Trace.Types.Events.isProfileCall(event)) { break; } const maybeResolvedName = SourceMapsResolver.resolvedNodeNameForEntry(event); @@ -894,9 +910,8 @@ export class TimelineUIUtils { * Some events have a stack trace which is extracted by default at @see TimelineUIUtils.generateCauses * thus, we prevent extracting the stack trace again here. */ - if (TraceEngine.Helpers.Trace.eventHasCategory(event, TraceEngine.Types.TraceEvents.Categories.Console) || - TraceEngine.Types.TraceEvents.isTraceEventUserTiming(event) || - TraceEngine.Types.Extensions.isSyntheticExtensionEntry(event)) { + if (Trace.Helpers.Trace.eventHasCategory(event, Trace.Types.Events.Categories.Console) || + Trace.Types.Events.isUserTiming(event) || Trace.Types.Extensions.isSyntheticExtensionEntry(event)) { detailsText = null; } else { @@ -926,8 +941,8 @@ export class TimelineUIUtils { return LegacyComponents.Linkifier.Linkifier.linkifyURL(url, options); } static linkifyTopCallFrame(event, target, linkifier, isFreshRecording = false) { - let frame = TraceEngine.Helpers.Trace.getZeroIndexedStackTraceForEvent(event)?.[0]; - if (TraceEngine.Types.TraceEvents.isProfileCall(event)) { + let frame = Trace.Helpers.Trace.getZeroIndexedStackTraceForEvent(event)?.[0]; + if (Trace.Types.Events.isProfileCall(event)) { frame = event.callFrame; } if (!frame) { @@ -950,11 +965,11 @@ export class TimelineUIUtils { let link = 'https://web.dev/user-centric-performance-metrics/'; let name = 'page performance metrics'; switch (event.name) { - case "largestContentfulPaint::Candidate" /* TraceEngine.Types.TraceEvents.KnownEventName.MARK_LCP_CANDIDATE */: + case "largestContentfulPaint::Candidate" /* Trace.Types.Events.Name.MARK_LCP_CANDIDATE */: link = 'https://web.dev/lcp/'; name = 'largest contentful paint'; break; - case "firstContentfulPaint" /* TraceEngine.Types.TraceEvents.KnownEventName.MARK_FCP */: + case "firstContentfulPaint" /* Trace.Types.Events.Name.MARK_FCP */: link = 'https://web.dev/first-contentful-paint/'; name = 'first contentful paint'; break; @@ -981,16 +996,16 @@ export class TimelineUIUtils { contentHelper.appendTextRow(i18nString(UIStrings.compilationCacheStatus), i18nString(UIStrings.scriptNotEligibleToBeLoadedFromCache)); } } - static async buildTraceEventDetails(traceParseData, event, linkifier, detailed) { - const maybeTarget = targetForEvent(traceParseData, event); - const { duration } = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event); - const selfTime = getEventSelfTime(event, traceParseData); - const relatedNodesMap = await TraceEngine.Extras.FetchNodes.extractRelatedDOMNodesFromEvent(traceParseData, event); + static async buildTraceEventDetails(parsedTrace, event, linkifier, detailed) { + const maybeTarget = targetForEvent(parsedTrace, event); + const { duration } = Trace.Helpers.Timing.eventTimingsMilliSeconds(event); + const selfTime = getEventSelfTime(event, parsedTrace); + const relatedNodesMap = await Trace.Extras.FetchNodes.extractRelatedDOMNodesFromEvent(parsedTrace, event); if (maybeTarget) { // @ts-ignore TODO(crbug.com/1011811): Remove symbol usage. if (typeof event[previewElementSymbol] === 'undefined') { let previewElement = null; - const url = TraceEngine.Extras.URLForEntry.get(traceParseData, event); + const url = Trace.Extras.URLForEntry.get(parsedTrace, event); if (url) { previewElement = await LegacyComponents.ImagePreview.ImagePreview.build(maybeTarget, url, false, { imageAltText: LegacyComponents.ImagePreview.ImagePreview.defaultAltTextForImageURL(url), @@ -998,22 +1013,22 @@ export class TimelineUIUtils { align: "start" /* LegacyComponents.ImagePreview.Align.START */, }); } - else if (TraceEngine.Types.TraceEvents.isTraceEventPaint(event)) { - previewElement = await TimelineUIUtils.buildPicturePreviewContent(traceParseData, event, maybeTarget); + else if (Trace.Types.Events.isPaint(event)) { + previewElement = await TimelineUIUtils.buildPicturePreviewContent(parsedTrace, event, maybeTarget); } // @ts-ignore TODO(crbug.com/1011811): Remove symbol usage. event[previewElementSymbol] = previewElement; } } - if (TraceEngine.Types.TraceEvents.isSyntheticLayoutShift(event)) { + if (Trace.Types.Events.isSyntheticLayoutShift(event)) { // Ensure that there are no pie charts or extended info for layout shifts. detailed = false; } // This message may vary per event.name; let relatedNodeLabel; - const contentHelper = new TimelineDetailsContentHelper(targetForEvent(traceParseData, event), linkifier); + const contentHelper = new TimelineDetailsContentHelper(targetForEvent(parsedTrace, event), linkifier); const defaultColorForEvent = this.eventColor(event); - const isMarker = traceParseData && isMarkerEvent(traceParseData, event); + const isMarker = parsedTrace && isMarkerEvent(parsedTrace, event); const color = isMarker ? TimelineUIUtils.markerStyleForEvent(event).color : defaultColorForEvent; contentHelper.addSection(TimelineUIUtils.eventTitle(event), color); // TODO: as part of the removal of the old engine, produce a typesafe way @@ -1022,18 +1037,18 @@ export class TimelineUIUtils { const unsafeEventArgs = event.args; // eslint-disable-next-line @typescript-eslint/no-explicit-any const unsafeEventData = event.args?.data; - const initiator = traceParseData.Initiators.eventToInitiator.get(event) ?? null; - const initiatorFor = traceParseData.Initiators.initiatorToEvents.get(event) ?? null; + const initiator = parsedTrace.Initiators.eventToInitiator.get(event) ?? null; + const initiatorFor = parsedTrace.Initiators.initiatorToEvents.get(event) ?? null; let url = null; - if (traceParseData) { - const warnings = TimelineComponents.DetailsView.buildWarningElementsForEvent(event, traceParseData); + if (parsedTrace) { + const warnings = TimelineComponents.DetailsView.buildWarningElementsForEvent(event, parsedTrace); for (const warning of warnings) { contentHelper.appendElementRow(i18nString(UIStrings.warning), warning, true); } } // Add timestamp to user timings. - if (TraceEngine.Helpers.Trace.eventHasCategory(event, TraceEngine.Types.TraceEvents.Categories.UserTiming)) { - const adjustedEventTimeStamp = timeStampForEventAdjustedForClosestNavigationIfPossible(event, traceParseData); + if (Trace.Helpers.Trace.eventHasCategory(event, Trace.Types.Events.Categories.UserTiming)) { + const adjustedEventTimeStamp = timeStampForEventAdjustedForClosestNavigationIfPossible(event, parsedTrace); contentHelper.appendTextRow(i18nString(UIStrings.timestamp), i18n.TimeUtilities.preciseMillisToString(adjustedEventTimeStamp, 1)); } // Only show total time and self time for events with non-zero durations. @@ -1041,22 +1056,22 @@ export class TimelineUIUtils { contentHelper.appendTextRow(i18nString(UIStrings.totalTime), i18n.TimeUtilities.millisToString(duration || 0, true)); contentHelper.appendTextRow(i18nString(UIStrings.selfTime), i18n.TimeUtilities.millisToString(selfTime, true)); } - if (TraceEngine.Types.TraceEvents.isTraceEventPerformanceMark(event) && event.args.data?.detail) { + if (Trace.Types.Events.isPerformanceMark(event) && event.args.data?.detail) { const detailContainer = TimelineUIUtils.renderObjectJson(JSON.parse(event.args.data?.detail)); contentHelper.appendElementRow(i18nString(UIStrings.details), detailContainer); } - if (TraceEngine.Types.TraceEvents.isSyntheticUserTiming(event) && event.args?.data?.beginEvent.args.detail) { + if (Trace.Types.Events.isSyntheticUserTiming(event) && event.args?.data?.beginEvent.args.detail) { const detailContainer = TimelineUIUtils.renderObjectJson(JSON.parse(event.args?.data?.beginEvent.args.detail)); contentHelper.appendElementRow(i18nString(UIStrings.details), detailContainer); } - if (traceParseData.Meta.traceIsGeneric) { + if (parsedTrace.Meta.traceIsGeneric) { TimelineUIUtils.renderEventJson(event, contentHelper); return contentHelper.fragment; } - if (TraceEngine.Types.TraceEvents.isTraceEventV8Compile(event)) { + if (Trace.Types.Events.isV8Compile(event)) { url = event.args.data?.url; if (url) { - const { lineNumber, columnNumber } = TraceEngine.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event); + const { lineNumber, columnNumber } = Trace.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event); contentHelper.appendLocationRow(i18nString(UIStrings.script), url, lineNumber || 0, columnNumber); } const isEager = Boolean(event.args.data?.eager); @@ -1069,80 +1084,80 @@ export class TimelineUIUtils { TimelineUIUtils.buildConsumeCacheDetails(event.args.data, contentHelper); } } - if (TraceEngine.Types.Extensions.isSyntheticExtensionEntry(event)) { + if (Trace.Types.Extensions.isSyntheticExtensionEntry(event)) { for (const [key, value] of event.args.properties || []) { contentHelper.appendTextRow(key, value); } } - if (TraceEngine.Types.TraceEvents.isSyntheticServerTiming(event) && event.args.data.desc) { + if (Trace.Types.Events.isSyntheticServerTiming(event) && event.args.data.desc) { contentHelper.appendTextRow(i18nString(UIStrings.description), event.args.data.desc); } - const isFreshRecording = Boolean(traceParseData && Tracker.instance().recordingIsFresh(traceParseData)); + const isFreshRecording = Boolean(parsedTrace && Tracker.instance().recordingIsFresh(parsedTrace)); switch (event.name) { - case "GCEvent" /* TraceEngine.Types.TraceEvents.KnownEventName.GC */: - case "MajorGC" /* TraceEngine.Types.TraceEvents.KnownEventName.MAJOR_GC */: - case "MinorGC" /* TraceEngine.Types.TraceEvents.KnownEventName.MINOR_GC */: { + case "GCEvent" /* Trace.Types.Events.Name.GC */: + case "MajorGC" /* Trace.Types.Events.Name.MAJOR_GC */: + case "MinorGC" /* Trace.Types.Events.Name.MINOR_GC */: { const delta = unsafeEventArgs['usedHeapSizeBefore'] - unsafeEventArgs['usedHeapSizeAfter']; contentHelper.appendTextRow(i18nString(UIStrings.collected), Platform.NumberUtilities.bytesToString(delta)); break; } - case "ProfileCall" /* TraceEngine.Types.TraceEvents.KnownEventName.PROFILE_CALL */: - case "FunctionCall" /* TraceEngine.Types.TraceEvents.KnownEventName.FUNCTION_CALL */: { - const detailsNode = await TimelineUIUtils.buildDetailsNodeForTraceEvent(event, targetForEvent(traceParseData, event), linkifier, isFreshRecording, traceParseData); + case "ProfileCall" /* Trace.Types.Events.Name.PROFILE_CALL */: + case "FunctionCall" /* Trace.Types.Events.Name.FUNCTION_CALL */: { + const detailsNode = await TimelineUIUtils.buildDetailsNodeForTraceEvent(event, targetForEvent(parsedTrace, event), linkifier, isFreshRecording, parsedTrace); if (detailsNode) { contentHelper.appendElementRow(i18nString(UIStrings.function), detailsNode); } break; } - case "TimerFire" /* TraceEngine.Types.TraceEvents.KnownEventName.TIMER_FIRE */: - case "TimerInstall" /* TraceEngine.Types.TraceEvents.KnownEventName.TIMER_INSTALL */: - case "TimerRemove" /* TraceEngine.Types.TraceEvents.KnownEventName.TIMER_REMOVE */: { + case "TimerFire" /* Trace.Types.Events.Name.TIMER_FIRE */: + case "TimerInstall" /* Trace.Types.Events.Name.TIMER_INSTALL */: + case "TimerRemove" /* Trace.Types.Events.Name.TIMER_REMOVE */: { contentHelper.appendTextRow(i18nString(UIStrings.timerId), unsafeEventData.timerId); - if (event.name === "TimerInstall" /* TraceEngine.Types.TraceEvents.KnownEventName.TIMER_INSTALL */) { + if (event.name === "TimerInstall" /* Trace.Types.Events.Name.TIMER_INSTALL */) { contentHelper.appendTextRow(i18nString(UIStrings.timeout), i18n.TimeUtilities.millisToString(unsafeEventData['timeout'])); contentHelper.appendTextRow(i18nString(UIStrings.repeats), !unsafeEventData['singleShot']); } break; } - case "FireAnimationFrame" /* TraceEngine.Types.TraceEvents.KnownEventName.FIRE_ANIMATION_FRAME */: { + case "FireAnimationFrame" /* Trace.Types.Events.Name.FIRE_ANIMATION_FRAME */: { contentHelper.appendTextRow(i18nString(UIStrings.callbackId), unsafeEventData['id']); break; } - case "V8.CompileModule" /* TraceEngine.Types.TraceEvents.KnownEventName.COMPILE_MODULE */: { + case "V8.CompileModule" /* Trace.Types.Events.Name.COMPILE_MODULE */: { contentHelper.appendLocationRow(i18nString(UIStrings.module), unsafeEventArgs['fileName'], 0); break; } - case "V8.CompileScript" /* TraceEngine.Types.TraceEvents.KnownEventName.COMPILE_SCRIPT */: { + case "V8.CompileScript" /* Trace.Types.Events.Name.COMPILE_SCRIPT */: { // This case is handled above break; } - case "v8.produceModuleCache" /* TraceEngine.Types.TraceEvents.KnownEventName.CACHE_MODULE */: { + case "v8.produceModuleCache" /* Trace.Types.Events.Name.CACHE_MODULE */: { url = unsafeEventData && unsafeEventData['url']; contentHelper.appendTextRow(i18nString(UIStrings.compilationCacheSize), Platform.NumberUtilities.bytesToString(unsafeEventData['producedCacheSize'])); break; } - case "v8.produceCache" /* TraceEngine.Types.TraceEvents.KnownEventName.CACHE_SCRIPT */: { + case "v8.produceCache" /* Trace.Types.Events.Name.CACHE_SCRIPT */: { url = unsafeEventData && unsafeEventData['url']; if (url) { - const { lineNumber, columnNumber } = TraceEngine.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event); + const { lineNumber, columnNumber } = Trace.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event); contentHelper.appendLocationRow(i18nString(UIStrings.script), url, lineNumber || 0, columnNumber); } contentHelper.appendTextRow(i18nString(UIStrings.compilationCacheSize), Platform.NumberUtilities.bytesToString(unsafeEventData['producedCacheSize'])); break; } - case "EvaluateScript" /* TraceEngine.Types.TraceEvents.KnownEventName.EVALUATE_SCRIPT */: { + case "EvaluateScript" /* Trace.Types.Events.Name.EVALUATE_SCRIPT */: { url = unsafeEventData && unsafeEventData['url']; if (url) { - const { lineNumber, columnNumber } = TraceEngine.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event); + const { lineNumber, columnNumber } = Trace.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event); contentHelper.appendLocationRow(i18nString(UIStrings.script), url, lineNumber || 0, columnNumber); } break; } - case "v8.wasm.streamFromResponseCallback" /* TraceEngine.Types.TraceEvents.KnownEventName.WASM_STREAM_FROM_RESPONSE_CALLBACK */: - case "v8.wasm.compiledModule" /* TraceEngine.Types.TraceEvents.KnownEventName.WASM_COMPILED_MODULE */: - case "v8.wasm.cachedModule" /* TraceEngine.Types.TraceEvents.KnownEventName.WASM_CACHED_MODULE */: - case "v8.wasm.moduleCacheHit" /* TraceEngine.Types.TraceEvents.KnownEventName.WASM_MODULE_CACHE_HIT */: - case "v8.wasm.moduleCacheInvalid" /* TraceEngine.Types.TraceEvents.KnownEventName.WASM_MODULE_CACHE_INVALID */: { + case "v8.wasm.streamFromResponseCallback" /* Trace.Types.Events.Name.WASM_STREAM_FROM_RESPONSE_CALLBACK */: + case "v8.wasm.compiledModule" /* Trace.Types.Events.Name.WASM_COMPILED_MODULE */: + case "v8.wasm.cachedModule" /* Trace.Types.Events.Name.WASM_CACHED_MODULE */: + case "v8.wasm.moduleCacheHit" /* Trace.Types.Events.Name.WASM_MODULE_CACHE_HIT */: + case "v8.wasm.moduleCacheInvalid" /* Trace.Types.Events.Name.WASM_MODULE_CACHE_INVALID */: { if (unsafeEventData) { url = unsafeEventArgs['url']; if (url) { @@ -1160,25 +1175,25 @@ export class TimelineUIUtils { break; } // @ts-ignore Fall-through intended. - case "Paint" /* TraceEngine.Types.TraceEvents.KnownEventName.PAINT */: { + case "Paint" /* Trace.Types.Events.Name.PAINT */: { const clip = unsafeEventData['clip']; contentHelper.appendTextRow(i18nString(UIStrings.location), i18nString(UIStrings.sSCurlyBrackets, { PH1: clip[0], PH2: clip[1] })); const clipWidth = TimelineUIUtils.quadWidth(clip); const clipHeight = TimelineUIUtils.quadHeight(clip); contentHelper.appendTextRow(i18nString(UIStrings.dimensions), i18nString(UIStrings.sSDimensions, { PH1: clipWidth, PH2: clipHeight })); } - case "PaintSetup" /* TraceEngine.Types.TraceEvents.KnownEventName.PAINT_SETUP */: - case "Rasterize" /* TraceEngine.Types.TraceEvents.KnownEventName.RASTERIZE */: - case "ScrollLayer" /* TraceEngine.Types.TraceEvents.KnownEventName.SCROLL_LAYER */: { + case "PaintSetup" /* Trace.Types.Events.Name.PAINT_SETUP */: + case "Rasterize" /* Trace.Types.Events.Name.RASTERIZE */: + case "ScrollLayer" /* Trace.Types.Events.Name.SCROLL_LAYER */: { relatedNodeLabel = i18nString(UIStrings.layerRoot); break; } - case "PaintImage" /* TraceEngine.Types.TraceEvents.KnownEventName.PAINT_IMAGE */: - case "Decode LazyPixelRef" /* TraceEngine.Types.TraceEvents.KnownEventName.DECODE_LAZY_PIXEL_REF */: - case "Decode Image" /* TraceEngine.Types.TraceEvents.KnownEventName.DECODE_IMAGE */: - case "Draw LazyPixelRef" /* TraceEngine.Types.TraceEvents.KnownEventName.DRAW_LAZY_PIXEL_REF */: { + case "PaintImage" /* Trace.Types.Events.Name.PAINT_IMAGE */: + case "Decode LazyPixelRef" /* Trace.Types.Events.Name.DECODE_LAZY_PIXEL_REF */: + case "Decode Image" /* Trace.Types.Events.Name.DECODE_IMAGE */: + case "Draw LazyPixelRef" /* Trace.Types.Events.Name.DRAW_LAZY_PIXEL_REF */: { relatedNodeLabel = i18nString(UIStrings.ownerElement); - url = TraceEngine.Extras.URLForEntry.get(traceParseData, event); + url = Trace.Extras.URLForEntry.get(parsedTrace, event); if (url) { const options = { tabStop: true, @@ -1189,7 +1204,7 @@ export class TimelineUIUtils { } break; } - case "ParseAuthorStyleSheet" /* TraceEngine.Types.TraceEvents.KnownEventName.PARSE_AUTHOR_STYLE_SHEET */: { + case "ParseAuthorStyleSheet" /* Trace.Types.Events.Name.PARSE_AUTHOR_STYLE_SHEET */: { url = unsafeEventData['styleSheetUrl']; if (url) { const options = { @@ -1201,7 +1216,7 @@ export class TimelineUIUtils { } break; } - case "UpdateLayoutTree" /* TraceEngine.Types.TraceEvents.KnownEventName.UPDATE_LAYOUT_TREE */: { + case "UpdateLayoutTree" /* Trace.Types.Events.Name.UPDATE_LAYOUT_TREE */: { contentHelper.appendTextRow(i18nString(UIStrings.elementsAffected), unsafeEventArgs['elementCount']); const selectorStatsSetting = Common.Settings.Settings.instance().createSetting('timeline-capture-selector-stats', false); if (!selectorStatsSetting.get()) { @@ -1211,41 +1226,83 @@ export class TimelineUIUtils { } break; } - case "Layout" /* TraceEngine.Types.TraceEvents.KnownEventName.LAYOUT */: { + case "Layout" /* Trace.Types.Events.Name.LAYOUT */: { const beginData = unsafeEventArgs['beginData']; contentHelper.appendTextRow(i18nString(UIStrings.nodesThatNeedLayout), i18nString(UIStrings.sOfS, { PH1: beginData['dirtyObjects'], PH2: beginData['totalObjects'] })); relatedNodeLabel = i18nString(UIStrings.layoutRoot); break; } - case "ConsoleTime" /* TraceEngine.Types.TraceEvents.KnownEventName.CONSOLE_TIME */: { + case "ConsoleTime" /* Trace.Types.Events.Name.CONSOLE_TIME */: { contentHelper.appendTextRow(i18nString(UIStrings.message), event.name); break; } - case "WebSocketCreate" /* TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_CREATE */: - case "WebSocketSendHandshakeRequest" /* TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_SEND_HANDSHAKE_REQUEST */: - case "WebSocketReceiveHandshakeResponse" /* TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST */: - case "WebSocketSend" /* TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_SEND */: - case "WebSocketReceive" /* TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_RECEIVE */: - case "WebSocketDestroy" /* TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_DESTROY */: { - if (TraceEngine.Types.TraceEvents.isWebSocketTraceEvent(event)) { - const rows = TimelineComponents.DetailsView.buildRowsForWebSocketEvent(event, traceParseData); + case "WebSocketCreate" /* Trace.Types.Events.Name.WEB_SOCKET_CREATE */: + case "WebSocketSendHandshakeRequest" /* Trace.Types.Events.Name.WEB_SOCKET_SEND_HANDSHAKE_REQUEST */: + case "WebSocketReceiveHandshakeResponse" /* Trace.Types.Events.Name.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST */: + case "WebSocketSend" /* Trace.Types.Events.Name.WEB_SOCKET_SEND */: + case "WebSocketReceive" /* Trace.Types.Events.Name.WEB_SOCKET_RECEIVE */: + case "WebSocketDestroy" /* Trace.Types.Events.Name.WEB_SOCKET_DESTROY */: { + if (Trace.Types.Events.isWebSocketTraceEvent(event)) { + const rows = TimelineComponents.DetailsView.buildRowsForWebSocketEvent(event, parsedTrace); for (const { key, value } of rows) { contentHelper.appendTextRow(key, value); } } break; } - case "EmbedderCallback" /* TraceEngine.Types.TraceEvents.KnownEventName.EMBEDDER_CALLBACK */: { + case "EmbedderCallback" /* Trace.Types.Events.Name.EMBEDDER_CALLBACK */: { contentHelper.appendTextRow(i18nString(UIStrings.callbackFunction), unsafeEventData['callbackName']); break; } - case "Animation" /* TraceEngine.Types.TraceEvents.KnownEventName.ANIMATION */: { - if (event.ph === "n" /* TraceEngine.Types.TraceEvents.Phase.ASYNC_NESTABLE_INSTANT */) { - contentHelper.appendTextRow(i18nString(UIStrings.state), unsafeEventData['state']); + case "Animation" /* Trace.Types.Events.Name.ANIMATION */: { + if (!Trace.Types.Events.isSyntheticAnimation(event)) { + break; + } + const { displayName, nodeName } = event.args.data.beginEvent.args.data; + displayName && contentHelper.appendTextRow(i18nString(UIStrings.animating), displayName); + // If relatedNodes is empty (maybe saved trace), then print the text description of the DOM node. + if (!relatedNodesMap?.size && nodeName) { + contentHelper.appendTextRow(i18nString(UIStrings.relatedNode), nodeName); + } + const CLSInsight = Trace.Insights.InsightRunners.CumulativeLayoutShift; + const failures = CLSInsight.getNonCompositedFailure(event); + if (!failures.length) { + break; + } + const failureReasons = new Set(failures.map(f => f.failureReasons).flat().filter(Boolean)); + const unsupportedProperties = new Set(failures.map(f => f.unsupportedProperties).flat().filter(Boolean)); + for (const reason of failureReasons) { + let str; + switch (reason) { + case "UNSUPPORTED_CSS_PROPERTY" /* CLSInsight.AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY */: + str = i18nString(UIStrings.unsupportedCSSProperty, { + propertyCount: unsupportedProperties.size, + properties: new Intl.ListFormat(undefined, { style: 'short', type: 'conjunction' }).format(unsupportedProperties), + }); + break; + case "TRANSFROM_BOX_SIZE_DEPENDENT" /* CLSInsight.AnimationFailureReasons.TRANSFROM_BOX_SIZE_DEPENDENT */: + str = i18nString(UIStrings.transformDependsBoxSize); + break; + case "FILTER_MAY_MOVE_PIXELS" /* CLSInsight.AnimationFailureReasons.FILTER_MAY_MOVE_PIXELS */: + str = i18nString(UIStrings.filterMayMovePixels); + break; + case "NON_REPLACE_COMPOSITE_MODE" /* CLSInsight.AnimationFailureReasons.NON_REPLACE_COMPOSITE_MODE */: + str = i18nString(UIStrings.nonReplaceCompositeMode); + break; + case "INCOMPATIBLE_ANIMATIONS" /* CLSInsight.AnimationFailureReasons.INCOMPATIBLE_ANIMATIONS */: + str = i18nString(UIStrings.incompatibleAnimations); + break; + case "UNSUPPORTED_TIMING_PARAMS" /* CLSInsight.AnimationFailureReasons.UNSUPPORTED_TIMING_PARAMS */: + str = i18nString(UIStrings.unsupportedTimingParameters); + break; + default: + break; + } + str && contentHelper.appendElementRow(i18nString(UIStrings.compositingFailed), str, true); } break; } - case "ParseHTML" /* TraceEngine.Types.TraceEvents.KnownEventName.PARSE_HTML */: { + case "ParseHTML" /* Trace.Types.Events.Name.PARSE_HTML */: { const beginData = unsafeEventArgs['beginData']; const startLine = beginData['startLine'] - 1; const endLine = unsafeEventArgs['endData'] ? unsafeEventArgs['endData']['endLine'] - 1 : undefined; @@ -1256,41 +1313,41 @@ export class TimelineUIUtils { break; } // @ts-ignore Fall-through intended. - case "FireIdleCallback" /* TraceEngine.Types.TraceEvents.KnownEventName.FIRE_IDLE_CALLBACK */: { + case "FireIdleCallback" /* Trace.Types.Events.Name.FIRE_IDLE_CALLBACK */: { contentHelper.appendTextRow(i18nString(UIStrings.allottedTime), i18n.TimeUtilities.millisToString(unsafeEventData['allottedMilliseconds'])); contentHelper.appendTextRow(i18nString(UIStrings.invokedByTimeout), unsafeEventData['timedOut']); } - case "RequestIdleCallback" /* TraceEngine.Types.TraceEvents.KnownEventName.REQUEST_IDLE_CALLBACK */: - case "CancelIdleCallback" /* TraceEngine.Types.TraceEvents.KnownEventName.CANCEL_IDLE_CALLBACK */: { + case "RequestIdleCallback" /* Trace.Types.Events.Name.REQUEST_IDLE_CALLBACK */: + case "CancelIdleCallback" /* Trace.Types.Events.Name.CANCEL_IDLE_CALLBACK */: { contentHelper.appendTextRow(i18nString(UIStrings.callbackId), unsafeEventData['id']); break; } - case "EventDispatch" /* TraceEngine.Types.TraceEvents.KnownEventName.EVENT_DISPATCH */: { + case "EventDispatch" /* Trace.Types.Events.Name.EVENT_DISPATCH */: { contentHelper.appendTextRow(i18nString(UIStrings.type), unsafeEventData['type']); break; } // @ts-ignore Fall-through intended. - case "largestContentfulPaint::Candidate" /* TraceEngine.Types.TraceEvents.KnownEventName.MARK_LCP_CANDIDATE */: { + case "largestContentfulPaint::Candidate" /* Trace.Types.Events.Name.MARK_LCP_CANDIDATE */: { contentHelper.appendTextRow(i18nString(UIStrings.type), String(unsafeEventData['type'])); contentHelper.appendTextRow(i18nString(UIStrings.size), String(unsafeEventData['size'])); } - case "firstPaint" /* TraceEngine.Types.TraceEvents.KnownEventName.MARK_FIRST_PAINT */: - case "firstContentfulPaint" /* TraceEngine.Types.TraceEvents.KnownEventName.MARK_FCP */: - case "MarkLoad" /* TraceEngine.Types.TraceEvents.KnownEventName.MARK_LOAD */: - case "MarkDOMContent" /* TraceEngine.Types.TraceEvents.KnownEventName.MARK_DOM_CONTENT */: { - const adjustedEventTimeStamp = timeStampForEventAdjustedForClosestNavigationIfPossible(event, traceParseData); + case "firstPaint" /* Trace.Types.Events.Name.MARK_FIRST_PAINT */: + case "firstContentfulPaint" /* Trace.Types.Events.Name.MARK_FCP */: + case "MarkLoad" /* Trace.Types.Events.Name.MARK_LOAD */: + case "MarkDOMContent" /* Trace.Types.Events.Name.MARK_DOM_CONTENT */: { + const adjustedEventTimeStamp = timeStampForEventAdjustedForClosestNavigationIfPossible(event, parsedTrace); contentHelper.appendTextRow(i18nString(UIStrings.timestamp), i18n.TimeUtilities.preciseMillisToString(adjustedEventTimeStamp, 1)); - if (TraceEngine.Types.TraceEvents.isTraceEventMarkerEvent(event)) { + if (Trace.Types.Events.isMarkerEvent(event)) { contentHelper.appendElementRow(i18nString(UIStrings.details), TimelineUIUtils.buildDetailsNodeForMarkerEvents(event)); } break; } - case "EventTiming" /* TraceEngine.Types.TraceEvents.KnownEventName.EVENT_TIMING */: { - const detailsNode = await TimelineUIUtils.buildDetailsNodeForTraceEvent(event, targetForEvent(traceParseData, event), linkifier, isFreshRecording, traceParseData); + case "EventTiming" /* Trace.Types.Events.Name.EVENT_TIMING */: { + const detailsNode = await TimelineUIUtils.buildDetailsNodeForTraceEvent(event, targetForEvent(parsedTrace, event), linkifier, isFreshRecording, parsedTrace); if (detailsNode) { contentHelper.appendElementRow(i18nString(UIStrings.details), detailsNode); } - if (TraceEngine.Types.TraceEvents.isSyntheticInteractionEvent(event)) { + if (Trace.Types.Events.isSyntheticInteraction(event)) { const inputDelay = i18n.TimeUtilities.formatMicroSecondsAsMillisFixed(event.inputDelay); const mainThreadTime = i18n.TimeUtilities.formatMicroSecondsAsMillisFixed(event.mainThreadHandling); const presentationDelay = i18n.TimeUtilities.formatMicroSecondsAsMillisFixed(event.presentationDelay); @@ -1301,8 +1358,8 @@ export class TimelineUIUtils { } break; } - case "LayoutShift" /* TraceEngine.Types.TraceEvents.KnownEventName.LAYOUT_SHIFT */: { - if (!TraceEngine.Types.TraceEvents.isSyntheticLayoutShift(event)) { + case "LayoutShift" /* Trace.Types.Events.Name.LAYOUT_SHIFT */: { + if (!Trace.Types.Events.isSyntheticLayoutShift(event)) { console.error('Unexpected type for LayoutShift event'); break; } @@ -1332,7 +1389,7 @@ export class TimelineUIUtils { break; } default: { - const detailsNode = await TimelineUIUtils.buildDetailsNodeForTraceEvent(event, targetForEvent(traceParseData, event), linkifier, isFreshRecording, traceParseData); + const detailsNode = await TimelineUIUtils.buildDetailsNodeForTraceEvent(event, targetForEvent(parsedTrace, event), linkifier, isFreshRecording, parsedTrace); if (detailsNode) { contentHelper.appendElementRow(i18nString(UIStrings.details), detailsNode); } @@ -1352,15 +1409,15 @@ export class TimelineUIUtils { // @ts-ignore TODO(crbug.com/1011811): Remove symbol usage. contentHelper.appendElementRow('', event[previewElementSymbol]); } - const stackTrace = TraceEngine.Helpers.Trace.getZeroIndexedStackTraceForEvent(event); - if (initiator || initiatorFor || stackTrace || traceParseData?.Invalidations.invalidationsForEvent.get(event)) { - await TimelineUIUtils.generateCauses(event, contentHelper, traceParseData); + const stackTrace = Trace.Helpers.Trace.getZeroIndexedStackTraceForEvent(event); + if (initiator || initiatorFor || stackTrace || parsedTrace?.Invalidations.invalidationsForEvent.get(event)) { + await TimelineUIUtils.generateCauses(event, contentHelper, parsedTrace); } if (Root.Runtime.experiments.isEnabled("timeline-debug-mode" /* Root.Runtime.ExperimentName.TIMELINE_DEBUG_MODE */)) { TimelineUIUtils.renderEventJson(event, contentHelper); } const stats = {}; - const showPieChart = detailed && traceParseData && TimelineUIUtils.aggregatedStatsForTraceEvent(stats, traceParseData, event); + const showPieChart = detailed && parsedTrace && TimelineUIUtils.aggregatedStatsForTraceEvent(stats, parsedTrace, event); if (showPieChart) { contentHelper.addSection(i18nString(UIStrings.aggregatedTime)); const pieChart = TimelineUIUtils.generatePieChart(stats, TimelineUIUtils.eventStyle(event).category, selfTime); @@ -1419,7 +1476,7 @@ export class TimelineUIUtils { const aggregatedStats = {}; const categoryStack = []; let lastTime = 0; - TraceEngine.Helpers.Trace.forEachEvent(events, { + Trace.Helpers.Trace.forEachEvent(events, { onStartEvent, onEndEvent, }); @@ -1446,9 +1503,8 @@ export class TimelineUIUtils { } } function onStartEvent(e) { - const { startTime } = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(e); - const category = TimelineComponents.EntryStyles.getEventStyle(e.name) - ?.category.name || + const { startTime } = Trace.Helpers.Timing.eventTimingsMilliSeconds(e); + const category = TimelineComponents.EntryStyles.getEventStyle(e.name)?.category.name || TimelineComponents.EntryStyles.getCategoryStyles().other.name; const parentCategory = categoryStack.length ? categoryStack[categoryStack.length - 1] : null; if (category !== parentCategory) { @@ -1457,7 +1513,7 @@ export class TimelineUIUtils { categoryStack.push(category); } function onEndEvent(e) { - const { endTime } = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(e); + const { endTime } = Trace.Helpers.Timing.eventTimingsMilliSeconds(e); const category = categoryStack.pop(); const parentCategory = categoryStack.length ? categoryStack[categoryStack.length - 1] : null; if (category !== parentCategory) { @@ -1484,8 +1540,7 @@ export class TimelineUIUtils { const eventStr = JSON.stringify(obj, null, indentLength).slice(0, 10_000).replace(/{\n /, '{ '); // Use CodeHighlighter for syntax highlighting. const highlightContainer = document.createElement('div'); - const shadowRoot = highlightContainer.attachShadow({ mode: 'open' }); - shadowRoot.adoptedStyleSheets = [inspectorCommonStyles, codeHighlighterStyles]; + const shadowRoot = UI.UIUtils.createShadowRootWithCoreStyles(highlightContainer, { cssFile: [codeHighlighterStyles] }); const elem = shadowRoot.createChild('div'); elem.classList.add('monospace', 'source-code'); elem.textContent = eventStr; @@ -1495,41 +1550,41 @@ export class TimelineUIUtils { static stackTraceFromCallFrames(callFrames) { return { callFrames }; } - static async generateCauses(event, contentHelper, traceParseData) { - const { startTime } = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event); + static async generateCauses(event, contentHelper, parsedTrace) { + const { startTime } = Trace.Helpers.Timing.eventTimingsMilliSeconds(event); let initiatorStackLabel = i18nString(UIStrings.initiatorStackTrace); let stackLabel = i18nString(UIStrings.stackTrace); switch (event.name) { - case "TimerFire" /* TraceEngine.Types.TraceEvents.KnownEventName.TIMER_FIRE */: + case "TimerFire" /* Trace.Types.Events.Name.TIMER_FIRE */: initiatorStackLabel = i18nString(UIStrings.timerInstalled); break; - case "FireAnimationFrame" /* TraceEngine.Types.TraceEvents.KnownEventName.FIRE_ANIMATION_FRAME */: + case "FireAnimationFrame" /* Trace.Types.Events.Name.FIRE_ANIMATION_FRAME */: initiatorStackLabel = i18nString(UIStrings.animationFrameRequested); break; - case "FireIdleCallback" /* TraceEngine.Types.TraceEvents.KnownEventName.FIRE_IDLE_CALLBACK */: + case "FireIdleCallback" /* Trace.Types.Events.Name.FIRE_IDLE_CALLBACK */: initiatorStackLabel = i18nString(UIStrings.idleCallbackRequested); break; - case "UpdateLayoutTree" /* TraceEngine.Types.TraceEvents.KnownEventName.UPDATE_LAYOUT_TREE */: + case "UpdateLayoutTree" /* Trace.Types.Events.Name.UPDATE_LAYOUT_TREE */: initiatorStackLabel = i18nString(UIStrings.firstInvalidated); stackLabel = i18nString(UIStrings.recalculationForced); break; - case "Layout" /* TraceEngine.Types.TraceEvents.KnownEventName.LAYOUT */: + case "Layout" /* Trace.Types.Events.Name.LAYOUT */: initiatorStackLabel = i18nString(UIStrings.firstLayoutInvalidation); stackLabel = i18nString(UIStrings.layoutForced); break; } - const stackTrace = TraceEngine.Helpers.Trace.getZeroIndexedStackTraceForEvent(event); + const stackTrace = Trace.Helpers.Trace.getZeroIndexedStackTraceForEvent(event); if (stackTrace && stackTrace.length) { contentHelper.addSection(stackLabel); contentHelper.createChildStackTraceElement(TimelineUIUtils.stackTraceFromCallFrames(stackTrace)); } - const initiator = traceParseData.Initiators.eventToInitiator.get(event); - const initiatorFor = traceParseData.Initiators.initiatorToEvents.get(event); - const invalidations = traceParseData.Invalidations.invalidationsForEvent.get(event); + const initiator = parsedTrace.Initiators.eventToInitiator.get(event); + const initiatorFor = parsedTrace.Initiators.initiatorToEvents.get(event); + const invalidations = parsedTrace.Invalidations.invalidationsForEvent.get(event); if (initiator) { // If we have an initiator for the event, we can show its stack trace, a link to reveal the initiator, // and the time since the initiator (Pending For). - const stackTrace = TraceEngine.Helpers.Trace.getZeroIndexedStackTraceForEvent(initiator); + const stackTrace = Trace.Helpers.Trace.getZeroIndexedStackTraceForEvent(initiator); if (stackTrace) { contentHelper.addSection(initiatorStackLabel); contentHelper.createChildStackTraceElement(TimelineUIUtils.stackTraceFromCallFrames(stackTrace.map(frame => { @@ -1541,7 +1596,7 @@ export class TimelineUIUtils { } const link = this.createEntryLink(initiator); contentHelper.appendElementRow(i18nString(UIStrings.initiatedBy), link); - const { startTime: initiatorStartTime } = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(initiator); + const { startTime: initiatorStartTime } = Trace.Helpers.Timing.eventTimingsMilliSeconds(initiator); const delay = startTime - initiatorStartTime; contentHelper.appendTextRow(i18nString(UIStrings.pendingFor), i18n.TimeUtilities.preciseMillisToString(delay, 1)); } @@ -1558,7 +1613,7 @@ export class TimelineUIUtils { contentHelper.appendElementRow(UIStrings.initiatorFor, links); } if (invalidations && invalidations.length) { - const totalInvalidations = traceParseData.Invalidations.invalidationCountForEvent.get(event) ?? + const totalInvalidations = parsedTrace.Invalidations.invalidationCountForEvent.get(event) ?? 0; // Won't be 0, but saves us dealing with undefined. contentHelper.addSection(i18nString(UIStrings.invalidations, { PH1: totalInvalidations })); await TimelineUIUtils.generateInvalidationsList(invalidations, contentHelper); @@ -1635,7 +1690,7 @@ export class TimelineUIUtils { } const generatedItems = new Set(); for (const invalidation of invalidations) { - const stackTrace = TraceEngine.Helpers.Trace.getZeroIndexedStackTraceForEvent(invalidation); + const stackTrace = Trace.Helpers.Trace.getZeroIndexedStackTraceForEvent(invalidation); let scriptLink = null; const callFrame = stackTrace?.at(0); if (callFrame) { @@ -1659,11 +1714,11 @@ export class TimelineUIUtils { contentHelper.appendElementRow(reason, text); } } - static aggregatedStatsForTraceEvent(total, traceParseData, event) { - const events = traceParseData.Renderer?.allTraceEntries || []; - const { startTime, endTime } = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event); + static aggregatedStatsForTraceEvent(total, parsedTrace, event) { + const events = parsedTrace.Renderer?.allTraceEntries || []; + const { startTime, endTime } = Trace.Helpers.Timing.eventTimingsMilliSeconds(event); function eventComparator(startTime, e) { - const { startTime: eventStartTime } = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(e); + const { startTime: eventStartTime } = Trace.Helpers.Timing.eventTimingsMilliSeconds(e); return startTime - eventStartTime; } const index = Platform.ArrayUtilities.binaryIndexOf(events, startTime, eventComparator); @@ -1675,11 +1730,11 @@ export class TimelineUIUtils { if (endTime) { for (let i = index; i < events.length; i++) { const nextEvent = events[i]; - const { startTime: nextEventStartTime } = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(nextEvent); + const { startTime: nextEventStartTime } = Trace.Helpers.Timing.eventTimingsMilliSeconds(nextEvent); if (nextEventStartTime >= endTime) { break; } - const nextEventSelfTime = getEventSelfTime(nextEvent, traceParseData); + const nextEventSelfTime = getEventSelfTime(nextEvent, parsedTrace); if (!nextEventSelfTime) { continue; } @@ -1693,7 +1748,7 @@ export class TimelineUIUtils { total[categoryName] = (total[categoryName] || 0) + nextEventSelfTime; } } - if (TraceEngine.Types.TraceEvents.isAsyncPhase(event.ph)) { + if (Trace.Types.Events.isPhaseAsync(event.ph)) { if (endTime) { let aggregatedTotal = 0; for (const categoryName in total) { @@ -1705,8 +1760,8 @@ export class TimelineUIUtils { } return hasChildren; } - static async buildPicturePreviewContent(traceData, event, target) { - const snapshotEvent = traceData.LayerTree.paintsToSnapshots.get(event); + static async buildPicturePreviewContent(parsedTrace, event, target) { + const snapshotEvent = parsedTrace.LayerTree.paintsToSnapshots.get(event); if (!snapshotEvent) { return null; } @@ -1755,7 +1810,7 @@ export class TimelineUIUtils { static createEventDivider(event, zeroTime) { const eventDivider = document.createElement('div'); eventDivider.classList.add('resources-event-divider'); - const { startTime: eventStartTime } = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event); + const { startTime: eventStartTime } = Trace.Helpers.Timing.eventTimingsMilliSeconds(event); const startTime = i18n.TimeUtilities.millisToString(eventStartTime - zeroTime); UI.Tooltip.Tooltip.install(eventDivider, i18nString(UIStrings.sAtS, { PH1: TimelineUIUtils.eventTitle(event), PH2: startTime })); const style = TimelineUIUtils.markerStyleForEvent(event); @@ -1843,8 +1898,8 @@ export class TimelineUIUtils { return contentHelper.fragment; } static frameDuration(frame) { - const offsetMilli = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.startTimeOffset); - const durationMilli = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(TraceEngine.Types.Timing.MicroSeconds(frame.endTime - frame.startTime)); + const offsetMilli = Trace.Helpers.Timing.microSecondsToMilliseconds(frame.startTimeOffset); + const durationMilli = Trace.Helpers.Timing.microSecondsToMilliseconds(Trace.Types.Timing.MicroSeconds(frame.endTime - frame.startTime)); const durationText = i18nString(UIStrings.sAtSParentheses, { PH1: i18n.TimeUtilities.millisToString(durationMilli, true), PH2: i18n.TimeUtilities.millisToString(offsetMilli, true), @@ -1879,16 +1934,14 @@ export class TimelineUIUtils { static markerStyleForEvent(event) { const tallMarkerDashStyle = [6, 4]; const title = TimelineUIUtils.eventTitle(event); - if (event.name !== "navigationStart" /* TraceEngine.Types.TraceEvents.KnownEventName.NAVIGATION_START */ && - TraceEngine.Helpers.Trace.eventHasCategory(event, TraceEngine.Types.TraceEvents.Categories.Console) || - TraceEngine.Helpers.Trace.eventHasCategory(event, TraceEngine.Types.TraceEvents.Categories.UserTiming)) { + if (event.name !== "navigationStart" /* Trace.Types.Events.Name.NAVIGATION_START */ && + Trace.Helpers.Trace.eventHasCategory(event, Trace.Types.Events.Categories.Console) || + Trace.Helpers.Trace.eventHasCategory(event, Trace.Types.Events.Categories.UserTiming)) { return { title, dashStyle: tallMarkerDashStyle, lineWidth: 0.5, - color: TraceEngine.Helpers.Trace.eventHasCategory(event, TraceEngine.Types.TraceEvents.Categories.Console) ? - 'purple' : - 'orange', + color: Trace.Helpers.Trace.eventHasCategory(event, Trace.Types.Events.Categories.Console) ? 'purple' : 'orange', tall: false, lowPriority: false, }; @@ -1896,35 +1949,35 @@ export class TimelineUIUtils { let tall = false; let color = 'grey'; switch (event.name) { - case "navigationStart" /* TraceEngine.Types.TraceEvents.KnownEventName.NAVIGATION_START */: + case "navigationStart" /* Trace.Types.Events.Name.NAVIGATION_START */: color = '#FF9800'; tall = true; break; - case "FrameStartedLoading" /* TraceEngine.Types.TraceEvents.KnownEventName.FRAME_STARTED_LOADING */: + case "FrameStartedLoading" /* Trace.Types.Events.Name.FRAME_STARTED_LOADING */: color = 'green'; tall = true; break; - case "MarkDOMContent" /* TraceEngine.Types.TraceEvents.KnownEventName.MARK_DOM_CONTENT */: + case "MarkDOMContent" /* Trace.Types.Events.Name.MARK_DOM_CONTENT */: color = '#0867CB'; tall = true; break; - case "MarkLoad" /* TraceEngine.Types.TraceEvents.KnownEventName.MARK_LOAD */: + case "MarkLoad" /* Trace.Types.Events.Name.MARK_LOAD */: color = '#B31412'; tall = true; break; - case "firstPaint" /* TraceEngine.Types.TraceEvents.KnownEventName.MARK_FIRST_PAINT */: + case "firstPaint" /* Trace.Types.Events.Name.MARK_FIRST_PAINT */: color = '#228847'; tall = true; break; - case "firstContentfulPaint" /* TraceEngine.Types.TraceEvents.KnownEventName.MARK_FCP */: + case "firstContentfulPaint" /* Trace.Types.Events.Name.MARK_FCP */: color = '#1A6937'; tall = true; break; - case "largestContentfulPaint::Candidate" /* TraceEngine.Types.TraceEvents.KnownEventName.MARK_LCP_CANDIDATE */: + case "largestContentfulPaint::Candidate" /* Trace.Types.Events.Name.MARK_LCP_CANDIDATE */: color = '#1A3422'; tall = true; break; - case "TimeStamp" /* TraceEngine.Types.TraceEvents.KnownEventName.TIME_STAMP */: + case "TimeStamp" /* Trace.Types.Events.Name.TIME_STAMP */: color = 'orange'; break; } @@ -2069,13 +2122,13 @@ export const categoryBreakdownCacheSymbol = Symbol('categoryBreakdownCache'); * where the user has navigated multiple times in the trace, so that we can show * the LCP (for example) relative to the last navigation. **/ -export function timeStampForEventAdjustedForClosestNavigationIfPossible(event, traceParsedData) { - if (!traceParsedData) { - const { startTime } = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event); +export function timeStampForEventAdjustedForClosestNavigationIfPossible(event, parsedTrace) { + if (!parsedTrace) { + const { startTime } = Trace.Helpers.Timing.eventTimingsMilliSeconds(event); return startTime; } - const time = TraceEngine.Helpers.Timing.timeStampForEventAdjustedByClosestNavigation(event, traceParsedData.Meta.traceBounds, traceParsedData.Meta.navigationsByNavigationId, traceParsedData.Meta.navigationsByFrameId); - return TraceEngine.Helpers.Timing.microSecondsToMilliseconds(time); + const time = Trace.Helpers.Timing.timeStampForEventAdjustedByClosestNavigation(event, parsedTrace.Meta.traceBounds, parsedTrace.Meta.navigationsByNavigationId, parsedTrace.Meta.navigationsByFrameId); + return Trace.Helpers.Timing.microSecondsToMilliseconds(time); } /** * Determines if an event is potentially a marker event. A marker event here @@ -2083,18 +2136,16 @@ export function timeStampForEventAdjustedForClosestNavigationIfPossible(event, t * the LCP time. This method does not filter out events: for example, it treats * every LCP Candidate event as a potential marker event. **/ -export function isMarkerEvent(traceParseData, event) { - const { KnownEventName } = TraceEngine.Types.TraceEvents; - if (event.name === "TimeStamp" /* KnownEventName.TIME_STAMP */) { +export function isMarkerEvent(parsedTrace, event) { + const { Name } = Trace.Types.Events; + if (event.name === "TimeStamp" /* Name.TIME_STAMP */) { return true; } - if (TraceEngine.Types.TraceEvents.isTraceEventFirstContentfulPaint(event) || - TraceEngine.Types.TraceEvents.isTraceEventFirstPaint(event)) { - return event.args.frame === traceParseData.Meta.mainFrameId; + if (Trace.Types.Events.isFirstContentfulPaint(event) || Trace.Types.Events.isFirstPaint(event)) { + return event.args.frame === parsedTrace.Meta.mainFrameId; } - if (TraceEngine.Types.TraceEvents.isTraceEventMarkDOMContent(event) || - TraceEngine.Types.TraceEvents.isTraceEventMarkLoad(event) || - TraceEngine.Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate(event)) { + if (Trace.Types.Events.isMarkDOMContent(event) || Trace.Types.Events.isMarkLoad(event) || + Trace.Types.Events.isLargestContentfulPaintCandidate(event)) { // isOutermostMainFrame was added in 2022, so we fallback to isMainFrame // for older traces. if (!event.args.data) { @@ -2111,12 +2162,11 @@ export function isMarkerEvent(traceParseData, event) { } return false; } -function getEventSelfTime(event, traceParseData) { - const mapToUse = TraceEngine.Types.Extensions.isSyntheticExtensionEntry(event) ? - traceParseData.ExtensionTraceData.entryToNode : - traceParseData.Renderer.entryToNode; +function getEventSelfTime(event, parsedTrace) { + const mapToUse = Trace.Types.Extensions.isSyntheticExtensionEntry(event) ? + parsedTrace.ExtensionTraceData.entryToNode : + parsedTrace.Renderer.entryToNode; const selfTime = mapToUse.get(event)?.selfTime; - return selfTime ? TraceEngine.Helpers.Timing.microSecondsToMilliseconds(selfTime) : - TraceEngine.Types.Timing.MilliSeconds(0); + return selfTime ? Trace.Helpers.Timing.microSecondsToMilliseconds(selfTime) : Trace.Types.Timing.MilliSeconds(0); } //# sourceMappingURL=TimelineUIUtils.js.map \ No newline at end of file diff --git a/public/panels/timeline/TimelineUIUtils.js.map b/public/panels/timeline/TimelineUIUtils.js.map index fac7b7115..d69cda742 100644 --- a/public/panels/timeline/TimelineUIUtils.js.map +++ b/public/panels/timeline/TimelineUIUtils.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineUIUtils.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineUIUtils.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2021 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/*\n * Copyright (C) 2013 Google Inc. All rights reserved.\n * Copyright (C) 2012 Intel Inc. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * * Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above\n * copyright notice, this list of conditions and the following disclaimer\n * in the documentation and/or other materials provided with the\n * distribution.\n * * Neither the name of Google Inc. nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as Root from '../../core/root/root.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport type * as Protocol from '../../generated/protocol.js';\nimport * as Bindings from '../../models/bindings/bindings.js';\nimport * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as TraceBounds from '../../services/trace_bounds/trace_bounds.js';\nimport * as CodeHighlighter from '../../ui/components/code_highlighter/code_highlighter.js';\n// eslint-disable-next-line rulesdir/es_modules_import\nimport codeHighlighterStyles from '../../ui/components/code_highlighter/codeHighlighter.css.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\n// eslint-disable-next-line rulesdir/es_modules_import\nimport imagePreviewStyles from '../../ui/legacy/components/utils/imagePreview.css.js';\nimport * as LegacyComponents from '../../ui/legacy/components/utils/utils.js';\n// eslint-disable-next-line rulesdir/es_modules_import\nimport inspectorCommonStyles from '../../ui/legacy/inspectorCommon.css.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport {CLSRect} from './CLSLinkifier.js';\nimport * as TimelineComponents from './components/components.js';\nimport * as Extensions from './extensions/extensions.js';\nimport {Tracker} from './FreshRecording.js';\nimport {ModificationsManager} from './ModificationsManager.js';\nimport {SourceMapsResolver} from './SourceMapsResolver.js';\nimport {targetForEvent} from './TargetForEvent.js';\nimport {TimelinePanel} from './TimelinePanel.js';\nimport {TimelineSelection} from './TimelineSelection.js';\n\nconst UIStrings = {\n /**\n *@description Text that only contain a placeholder\n *@example {100ms (at 200ms)} PH1\n */\n emptyPlaceholder: '{PH1}', // eslint-disable-line rulesdir/l10n_no_locked_or_placeholder_only_phrase\n /**\n *@description Text for timestamps of items\n */\n timestamp: 'Timestamp',\n /**\n *@description Text shown next to the interaction event's ID in the detail view.\n */\n interactionID: 'ID',\n /**\n *@description Text shown next to the interaction event's input delay time in the detail view.\n */\n inputDelay: 'Input delay',\n /**\n *@description Text shown next to the interaction event's thread processing duration in the detail view.\n */\n processingDuration: 'Processing duration',\n /**\n *@description Text shown next to the interaction event's presentation delay time in the detail view.\n */\n presentationDelay: 'Presentation delay',\n /**\n *@description Text shown when the user has selected an event that represents script compiliation.\n */\n compile: 'Compile',\n /**\n *@description Text shown when the user selects an event that represents script parsing.\n */\n parse: 'Parse',\n /**\n *@description Text with two placeholders separated by a colon\n *@example {Node removed} PH1\n *@example {div#id1} PH2\n */\n sS: '{PH1}: {PH2}',\n /**\n *@description Details text used to show the amount of data collected.\n *@example {30 MB} PH1\n */\n sCollected: '{PH1} collected',\n /**\n *@description Text used to show a URL to a script and the relevant line numbers.\n *@example {https://example.com/foo.js} PH1\n *@example {2} PH2\n *@example {4} PH3\n */\n sSs: '{PH1} [{PH2}…{PH3}]',\n /**\n *@description Text used to show a URL to a script and the starting line\n * number - used when there is no end line number available.\n *@example {https://example.com/foo.js} PH1\n *@example {2} PH2\n */\n sSSquareBrackets: '{PH1} [{PH2}…]',\n /**\n *@description Text that is usually a hyperlink to more documentation\n */\n learnMore: 'Learn more',\n /**\n *@description Text referring to the status of the browser's compilation cache.\n */\n compilationCacheStatus: 'Compilation cache status',\n /**\n *@description Text referring to the size of the browser's compiliation cache.\n */\n compilationCacheSize: 'Compilation cache size',\n /**\n *@description Text in Timeline UIUtils of the Performance panel. \"Compilation\n * cache\" refers to the code cache described at\n * https://v8.dev/blog/code-caching-for-devs . This label is followed by the\n * type of code cache data used, either \"normal\" or \"full\" as described in the\n * linked article.\n */\n compilationCacheKind: 'Compilation cache kind',\n /**\n *@description Text used to inform the user that the script they are looking\n * at was loaded from the browser's cache.\n */\n scriptLoadedFromCache: 'script loaded from cache',\n /**\n *@description Text to inform the user that the script they are looking at\n * was unable to be loaded from the browser's cache.\n */\n failedToLoadScriptFromCache: 'failed to load script from cache',\n /**\n *@description Text to inform the user that the script they are looking at was not eligible to be loaded from the browser's cache.\n */\n scriptNotEligibleToBeLoadedFromCache: 'script not eligible',\n /**\n *@description Text for the total time of something\n */\n totalTime: 'Total time',\n /**\n *@description Time of a single activity, as opposed to the total time\n */\n selfTime: 'Self time',\n /**\n *@description Label in the summary view in the Performance panel for a number which indicates how much managed memory has been reclaimed by performing Garbage Collection\n */\n collected: 'Collected',\n /**\n *@description Text for a programming function\n */\n function: 'Function',\n /**\n *@description Text for referring to the ID of a timer.\n */\n timerId: 'Timer ID',\n /**\n *@description Text for referring to a timer that has timed-out and therefore is being removed.\n */\n timeout: 'Timeout',\n /**\n *@description Text used to indicate that a timer is repeating (e.g. every X seconds) rather than a one off.\n */\n repeats: 'Repeats',\n /**\n *@description Text for referring to the ID of a callback function installed by an event.\n */\n callbackId: 'Callback ID',\n /**\n *@description Text for a module, the programming concept\n */\n module: 'Module',\n /**\n *@description Label for a group of JavaScript files\n */\n script: 'Script',\n /**\n *@description Text used to tell a user that a compilation trace event was streamed.\n */\n streamed: 'Streamed',\n /**\n *@description Text to indicate if a compilation event was eager.\n */\n eagerCompile: 'Compiling all functions eagerly',\n /**\n *@description Text to refer to the URL associated with a given event.\n */\n url: 'Url',\n /**\n *@description Text to indicate to the user the size of the cache (as a filesize - e.g. 5mb).\n */\n producedCacheSize: 'Produced cache size',\n /**\n *@description Text to indicate to the user the amount of the cache (as a filesize - e.g. 5mb) that has been used.\n */\n consumedCacheSize: 'Consumed cache size',\n /**\n *@description Title for a group of cities\n */\n location: 'Location',\n /**\n *@description Text used to show a coordinate pair (e.g. (3, 2)).\n *@example {2} PH1\n *@example {2} PH2\n */\n sSCurlyBrackets: '({PH1}, {PH2})',\n /**\n *@description Text used to indicate to the user they are looking at the physical dimensions of a shape that was drawn by the browser.\n */\n dimensions: 'Dimensions',\n /**\n *@description Text used to show the user the dimensions of a shape and indicate its area (e.g. 3x2).\n *@example {2} PH1\n *@example {2} PH2\n */\n sSDimensions: '{PH1} × {PH2}',\n /**\n *@description Related node label in Timeline UIUtils of the Performance panel\n */\n layerRoot: 'Layer root',\n /**\n *@description Related node label in Timeline UIUtils of the Performance panel\n */\n ownerElement: 'Owner element',\n /**\n *@description Text used to show the user the URL of the image they are viewing.\n */\n imageUrl: 'Image URL',\n /**\n *@description Text used to show the user that the URL they are viewing is loading a CSS stylesheet.\n */\n stylesheetUrl: 'Stylesheet URL',\n /**\n *@description Text used next to a number to show the user how many elements were affected.\n */\n elementsAffected: 'Elements affected',\n /**\n *@description Text used next to a number to show the user how many nodes required the browser to update and re-layout the page.\n */\n nodesThatNeedLayout: 'Nodes that need layout',\n /**\n *@description Text used to show the amount in a subset - e.g. \"2 of 10\".\n *@example {2} PH1\n *@example {10} PH2\n */\n sOfS: '{PH1} of {PH2}',\n /**\n *@description Related node label in Timeline UIUtils of the Performance panel\n */\n layoutRoot: 'Layout root',\n /**\n *@description Text used when viewing an event that can have a custom message attached.\n */\n message: 'Message',\n /**\n *@description Text used to tell the user they are viewing an event that has a function embedded in it, which is referred to as the \"callback function\".\n */\n callbackFunction: 'Callback function',\n /**\n *@description The current state of an item\n */\n state: 'State',\n /**\n *@description Text used to show the relevant range of a file - e.g. \"lines 2-10\".\n */\n range: 'Range',\n /**\n *@description Text used to refer to the amount of time some event or code was given to complete within.\n */\n allottedTime: 'Allotted time',\n /**\n *@description Text used to tell a user that a particular event or function was automatically run by a timeout.\n */\n invokedByTimeout: 'Invoked by timeout',\n /**\n *@description Text that refers to some types\n */\n type: 'Type',\n /**\n *@description Text for the size of something\n */\n size: 'Size',\n /**\n *@description Text for the details of something\n */\n details: 'Details',\n /**\n *@description Title in Timeline for Cumulative Layout Shifts\n */\n cumulativeLayoutShifts: 'Cumulative Layout Shifts',\n /**\n *@description Text for the link to the evolved CLS website\n */\n evolvedClsLink: 'evolved',\n /**\n *@description Warning in Timeline that CLS can cause a poor user experience. It contains a link to inform developers about the recent changes to how CLS is measured. The new CLS metric is said to have evolved from the previous version.\n *@example {Link to web.dev/metrics} PH1\n *@example {Link to web.dev/evolving-cls which will always have the text 'evolved'} PH2\n */\n sCLSInformation: '{PH1} can result in poor user experiences. It has recently {PH2}.',\n /**\n *@description Text to indicate an item is a warning\n */\n warning: 'Warning',\n /**\n *@description Title for the Timeline CLS Score\n */\n score: 'Score',\n /**\n *@description Text in Timeline for the cumulative CLS score\n */\n cumulativeScore: 'Cumulative score',\n /**\n *@description Text in Timeline for the current CLS score\n */\n currentClusterScore: 'Current cluster score',\n /**\n *@description Text in Timeline for the current CLS cluster\n */\n currentClusterId: 'Current cluster ID',\n /**\n *@description Text in Timeline for whether input happened recently\n */\n hadRecentInput: 'Had recent input',\n /**\n *@description Text in Timeline indicating that input has happened recently\n */\n yes: 'Yes',\n /**\n *@description Text in Timeline indicating that input has not happened recently\n */\n no: 'No',\n /**\n *@description Label for Cumulative Layout records, indicating where they moved from\n */\n movedFrom: 'Moved from',\n /**\n *@description Label for Cumulative Layout records, indicating where they moved to\n */\n movedTo: 'Moved to',\n /**\n *@description Text that indicates a particular HTML element or node is related to what the user is viewing.\n */\n relatedNode: 'Related node',\n /**\n *@description Text for previewing items\n */\n preview: 'Preview',\n /**\n *@description Text used to refer to the total time summed up across multiple events.\n */\n aggregatedTime: 'Aggregated time',\n /**\n *@description Text for the duration of something\n */\n duration: 'Duration',\n /**\n *@description Text for the stack trace of the initiator of something. The Initiator is the event or factor that directly triggered or precipitated a subsequent action.\n */\n initiatorStackTrace: 'Initiator stack trace',\n /**\n *@description Text for the event initiated by another one\n */\n initiatedBy: 'Initiated by',\n /**\n *@description Text for the event that is an initiator for another one\n */\n initiatorFor: 'Initiator for',\n /**\n *@description Text for the underlying data behing a specific flamechart selection. Trace events are the browser instrumentation that are emitted as JSON objects.\n */\n traceEvent: 'Trace event',\n /**\n *@description Call site stack label in Timeline UIUtils of the Performance panel\n */\n timerInstalled: 'Timer installed',\n /**\n *@description Call site stack label in Timeline UIUtils of the Performance panel\n */\n animationFrameRequested: 'Animation frame requested',\n /**\n *@description Call site stack label in Timeline UIUtils of the Performance panel\n */\n idleCallbackRequested: 'Idle callback requested',\n /**\n *@description Stack label in Timeline UIUtils of the Performance panel\n */\n recalculationForced: 'Recalculation forced',\n /**\n *@description Call site stack label in Timeline UIUtils of the Performance panel\n */\n firstLayoutInvalidation: 'First layout invalidation',\n /**\n *@description Stack label in Timeline UIUtils of the Performance panel\n */\n layoutForced: 'Layout forced',\n /**\n *@description Text for the execution stack trace\n */\n stackTrace: 'Stack trace',\n /**\n *@description Text used to show any invalidations for a particular event that caused the browser to have to do more work to update the page.\n * @example {2} PH1\n */\n invalidations: 'Invalidations ({PH1} total)',\n /**\n * @description Text in Timeline UIUtils of the Performance panel. Phrase is followed by a number of milliseconds.\n * Some events or tasks might have been only started, but have not ended yet. Such events or tasks are considered\n * \"pending\".\n */\n pendingFor: 'Pending for',\n /**\n *@description Noun label for a stack trace which indicates the first time some condition was invalidated.\n */\n firstInvalidated: 'First invalidated',\n /**\n *@description Title of the paint profiler, old name of the performance pane\n */\n paintProfiler: 'Paint profiler',\n /**\n *@description Text in Timeline Flame Chart View of the Performance panel\n *@example {Frame} PH1\n *@example {10ms} PH2\n */\n sAtS: '{PH1} at {PH2}',\n /**\n *@description Text used next to a time to indicate that the particular event took that much time itself. In context this might look like \"3ms blink.console (self)\"\n *@example {blink.console} PH1\n */\n sSelf: '{PH1} (self)',\n /**\n *@description Text used next to a time to indicate that the event's children took that much time. In context this might look like \"3ms blink.console (children)\"\n *@example {blink.console} PH1\n */\n sChildren: '{PH1} (children)',\n /**\n *@description Text used to show the user how much time the browser spent on rendering (drawing the page onto the screen).\n */\n timeSpentInRendering: 'Time spent in rendering',\n /**\n *@description Text for a rendering frame\n */\n frame: 'Frame',\n /**\n *@description Text used to refer to the duration of an event at a given offset - e.g. \"2ms at 10ms\" which can be read as \"2ms starting after 10ms\".\n *@example {10ms} PH1\n *@example {10ms} PH2\n */\n sAtSParentheses: '{PH1} (at {PH2})',\n /**\n *@description Text of a DOM element in Timeline UIUtils of the Performance panel\n */\n UnknownNode: '[ unknown node ]',\n /**\n *@description Text used to refer to a particular element and the file it was referred to in.\n *@example {node} PH1\n *@example {app.js} PH2\n */\n invalidationWithCallFrame: '{PH1} at {PH2}',\n /**\n *@description Text indicating that something is outside of the Performace Panel Timeline Minimap range\n */\n outsideBreadcrumbRange: '(outside of the breadcrumb range)',\n /**\n *@description Text indicating that something is hidden from the Performace Panel Timeline\n */\n entryIsHidden: '(entry is hidden)',\n /**\n * @description Title of a row in the details view for a `Recalculate Styles` event that contains more info about selector stats tracing.\n */\n selectorStatsTitle: 'Selector stats',\n /**\n * @description Info text that explains to the user how to enable selector stats tracing.\n * @example {Setting Name} PH1\n */\n sSelectorStatsInfo: 'Select \"{PH1}\" to collect detailed CSS selector matching statistics.',\n /**\n * @description Label for a description text of a metric.\n */\n description: 'Description',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelineUIUtils.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nlet eventDispatchDesciptors: EventDispatchTypeDescriptor[];\n\nlet colorGenerator: Common.Color.Generator;\n\ntype LinkifyLocationOptions = {\n scriptId: Protocol.Runtime.ScriptId|null,\n url: string,\n lineNumber: number,\n target: SDK.Target.Target|null,\n linkifier: LegacyComponents.Linkifier.Linkifier,\n isFreshRecording?: boolean,\n columnNumber?: number,\n};\n\nexport class TimelineUIUtils {\n static frameDisplayName(frame: Protocol.Runtime.CallFrame): string {\n if (!TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.isNativeRuntimeFrame(frame)) {\n return UI.UIUtils.beautifyFunctionName(frame.functionName);\n }\n const nativeGroup = TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.nativeGroup(frame.functionName);\n switch (nativeGroup) {\n case TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.NativeGroups.COMPILE:\n return i18nString(UIStrings.compile);\n case TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.NativeGroups.PARSE:\n return i18nString(UIStrings.parse);\n }\n return frame.functionName;\n }\n\n static testContentMatching(\n traceEvent: TraceEngine.Types.TraceEvents.TraceEventData, regExp: RegExp,\n traceParsedData?: TraceEngine.Handlers.Types.TraceParseData): boolean {\n const title = TimelineUIUtils.eventStyle(traceEvent).title;\n const tokens = [title];\n\n if (TraceEngine.Types.TraceEvents.isProfileCall(traceEvent)) {\n // In the future this case will not be possible - wherever we call this\n // function we will be able to pass in the data from the new engine. But\n // currently this is called in a variety of places including from the\n // legacy model which does not have a reference to the new engine's data.\n // So if we are missing the data, we just fallback to the name from the\n // callFrame.\n if (!traceParsedData || !traceParsedData.Samples) {\n tokens.push(traceEvent.callFrame.functionName);\n } else {\n tokens.push(\n TraceEngine.Handlers.ModelHandlers.Samples.getProfileCallFunctionName(traceParsedData.Samples, traceEvent));\n }\n }\n if (traceParsedData) {\n const url = TraceEngine.Extras.URLForEntry.get(traceParsedData, traceEvent);\n if (url) {\n tokens.push(url);\n }\n }\n // This works for both legacy and new engine events.\n appendObjectProperties(traceEvent.args as ContentObject, 2);\n const result = tokens.join('|').match(regExp);\n return result ? result.length > 0 : false;\n\n interface ContentObject {\n [x: string]: number|string|ContentObject;\n }\n function appendObjectProperties(object: ContentObject, depth: number): void {\n if (!depth) {\n return;\n }\n for (const key in object) {\n const value = object[key];\n if (typeof value === 'string') {\n tokens.push(value);\n } else if (typeof value === 'number') {\n tokens.push(String(value));\n } else if (typeof value === 'object' && value !== null) {\n appendObjectProperties(value, depth - 1);\n }\n }\n }\n }\n\n static eventStyle(event: TraceEngine.Types.TraceEvents.TraceEventData):\n TimelineComponents.EntryStyles.TimelineRecordStyle {\n if (TraceEngine.Types.TraceEvents.isProfileCall(event) && event.callFrame.functionName === '(idle)') {\n return new TimelineComponents.EntryStyles.TimelineRecordStyle(\n event.name, TimelineComponents.EntryStyles.getCategoryStyles().idle);\n }\n\n if (event.cat === TraceEngine.Types.TraceEvents.Categories.Console ||\n event.cat === TraceEngine.Types.TraceEvents.Categories.UserTiming) {\n return new TimelineComponents.EntryStyles.TimelineRecordStyle(\n event.name, TimelineComponents.EntryStyles.getCategoryStyles()['scripting']);\n }\n\n return TimelineComponents.EntryStyles.getEventStyle(event.name as TraceEngine.Types.TraceEvents.KnownEventName) ??\n new TimelineComponents.EntryStyles.TimelineRecordStyle(\n event.name, TimelineComponents.EntryStyles.getCategoryStyles().other);\n }\n\n static eventColor(event: TraceEngine.Types.TraceEvents.TraceEventData): string {\n if (TraceEngine.Types.TraceEvents.isProfileCall(event)) {\n const frame = event.callFrame;\n if (TimelineUIUtils.isUserFrame(frame)) {\n return TimelineUIUtils.colorForId(frame.url);\n }\n }\n if (TraceEngine.Types.Extensions.isSyntheticExtensionEntry(event)) {\n return Extensions.ExtensionUI.extensionEntryColor(event);\n }\n let parsedColor = TimelineUIUtils.eventStyle(event).category.getComputedColorValue();\n // This event is considered idle time but still rendered as a scripting event here\n // to connect the StreamingCompileScriptParsing events it belongs to.\n if (event.name === TraceEngine.Types.TraceEvents.KnownEventName.STREAMING_COMPILE_SCRIPT_WAITING) {\n parsedColor = TimelineComponents.EntryStyles.getCategoryStyles().scripting.getComputedColorValue();\n if (!parsedColor) {\n throw new Error('Unable to parse color from getCategoryStyles().scripting.color');\n }\n }\n return parsedColor;\n }\n\n static eventTitle(event: TraceEngine.Types.TraceEvents.TraceEventData): string {\n // Profile call events do not have a args.data property, thus, we\n // need to check for profile calls in the beginning of this\n // function.\n if (TraceEngine.Types.TraceEvents.isProfileCall(event)) {\n const maybeResolvedName = SourceMapsResolver.resolvedNodeNameForEntry(event);\n const displayName = maybeResolvedName || TimelineUIUtils.frameDisplayName(event.callFrame);\n return displayName;\n }\n if (event.name === 'EventTiming' && TraceEngine.Types.TraceEvents.isSyntheticInteractionEvent(event)) {\n // TODO(crbug.com/365047728): replace this entire method with this call.\n return TimelineComponents.EntryName.nameForEntry(event);\n }\n const title = TimelineUIUtils.eventStyle(event).title;\n if (TraceEngine.Helpers.Trace.eventHasCategory(event, TraceEngine.Types.TraceEvents.Categories.Console)) {\n return title;\n }\n if (TraceEngine.Types.TraceEvents.isTraceEventTimeStamp(event)) {\n return i18nString(UIStrings.sS, {PH1: title, PH2: event.args.data.message});\n }\n if (TraceEngine.Types.TraceEvents.isTraceEventAnimation(event) && event.args.data.name) {\n return i18nString(UIStrings.sS, {PH1: title, PH2: event.args.data.name});\n }\n if (TraceEngine.Types.TraceEvents.isTraceEventDispatch(event)) {\n return i18nString(UIStrings.sS, {PH1: title, PH2: event.args.data.type});\n }\n return title;\n }\n\n static isUserFrame(frame: Protocol.Runtime.CallFrame): boolean {\n return frame.scriptId !== '0' && !(frame.url && frame.url.startsWith('native '));\n }\n\n static async buildDetailsTextForTraceEvent(\n event: TraceEngine.Types.TraceEvents.TraceEventData,\n traceParsedData: TraceEngine.Handlers.Types.TraceParseData): Promise {\n let detailsText;\n\n // TODO(40287735): update this code with type-safe data checks.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const unsafeEventArgs = event.args as Record;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const unsafeEventData = event.args?.data as Record;\n\n switch (event.name) {\n case TraceEngine.Types.TraceEvents.KnownEventName.GC:\n case TraceEngine.Types.TraceEvents.KnownEventName.MAJOR_GC:\n case TraceEngine.Types.TraceEvents.KnownEventName.MINOR_GC: {\n const delta = unsafeEventArgs['usedHeapSizeBefore'] - unsafeEventArgs['usedHeapSizeAfter'];\n detailsText = i18nString(UIStrings.sCollected, {PH1: Platform.NumberUtilities.bytesToString(delta)});\n break;\n }\n case TraceEngine.Types.TraceEvents.KnownEventName.FUNCTION_CALL: {\n const {lineNumber, columnNumber} = TraceEngine.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event);\n if (lineNumber !== undefined && columnNumber !== undefined) {\n detailsText = unsafeEventData.url + ':' + (lineNumber + 1) + ':' + (columnNumber + 1);\n }\n break;\n }\n case TraceEngine.Types.TraceEvents.KnownEventName.EVENT_DISPATCH:\n detailsText = unsafeEventData ? unsafeEventData['type'] : null;\n break;\n case TraceEngine.Types.TraceEvents.KnownEventName.PAINT: {\n const width = TimelineUIUtils.quadWidth(unsafeEventData.clip);\n const height = TimelineUIUtils.quadHeight(unsafeEventData.clip);\n if (width && height) {\n detailsText = i18nString(UIStrings.sSDimensions, {PH1: width, PH2: height});\n }\n break;\n }\n case TraceEngine.Types.TraceEvents.KnownEventName.PARSE_HTML: {\n const startLine = unsafeEventArgs['beginData']['startLine'];\n const endLine = unsafeEventArgs['endData'] && unsafeEventArgs['endData']['endLine'];\n const url = Bindings.ResourceUtils.displayNameForURL(unsafeEventArgs['beginData']['url']);\n if (endLine >= 0) {\n detailsText = i18nString(UIStrings.sSs, {PH1: url, PH2: startLine + 1, PH3: endLine + 1});\n } else {\n detailsText = i18nString(UIStrings.sSSquareBrackets, {PH1: url, PH2: startLine + 1});\n }\n break;\n }\n case TraceEngine.Types.TraceEvents.KnownEventName.COMPILE_MODULE:\n case TraceEngine.Types.TraceEvents.KnownEventName.CACHE_MODULE:\n detailsText = Bindings.ResourceUtils.displayNameForURL(unsafeEventArgs['fileName']);\n break;\n case TraceEngine.Types.TraceEvents.KnownEventName.COMPILE_SCRIPT:\n case TraceEngine.Types.TraceEvents.KnownEventName.CACHE_SCRIPT:\n case TraceEngine.Types.TraceEvents.KnownEventName.EVALUATE_SCRIPT: {\n const {lineNumber} = TraceEngine.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event);\n const url = unsafeEventData && unsafeEventData['url'];\n if (url) {\n detailsText = Bindings.ResourceUtils.displayNameForURL(url) + ':' + ((lineNumber || 0) + 1);\n }\n break;\n }\n case TraceEngine.Types.TraceEvents.KnownEventName.WASM_COMPILED_MODULE:\n case TraceEngine.Types.TraceEvents.KnownEventName.WASM_MODULE_CACHE_HIT: {\n const url = unsafeEventArgs['url'];\n if (url) {\n detailsText = Bindings.ResourceUtils.displayNameForURL(url);\n }\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.STREAMING_COMPILE_SCRIPT:\n case TraceEngine.Types.TraceEvents.KnownEventName.BACKGROUND_DESERIALIZE:\n case TraceEngine.Types.TraceEvents.KnownEventName.XHR_READY_STATE_CHANGED:\n case TraceEngine.Types.TraceEvents.KnownEventName.XHR_LOAD: {\n const url = unsafeEventData['url'];\n if (url) {\n detailsText = Bindings.ResourceUtils.displayNameForURL(url);\n }\n break;\n }\n case TraceEngine.Types.TraceEvents.KnownEventName.TIME_STAMP:\n detailsText = unsafeEventData['message'];\n break;\n\n case TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_CREATE:\n case TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_SEND_HANDSHAKE_REQUEST:\n case TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST:\n case TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_SEND:\n case TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_RECEIVE:\n case TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_DESTROY:\n case TraceEngine.Types.TraceEvents.KnownEventName.RESOURCE_WILL_SEND_REQUEST:\n case TraceEngine.Types.TraceEvents.KnownEventName.RESOURCE_SEND_REQUEST:\n case TraceEngine.Types.TraceEvents.KnownEventName.RESOURCE_RECEIVE_DATA:\n case TraceEngine.Types.TraceEvents.KnownEventName.RESOURCE_RECEIVE_RESPONSE:\n case TraceEngine.Types.TraceEvents.KnownEventName.RESOURCE_FINISH:\n case TraceEngine.Types.TraceEvents.KnownEventName.PAINT_IMAGE:\n case TraceEngine.Types.TraceEvents.KnownEventName.DECODE_IMAGE:\n case TraceEngine.Types.TraceEvents.KnownEventName.DECODE_LAZY_PIXEL_REF: {\n const url = TraceEngine.Extras.URLForEntry.get(traceParsedData, event);\n if (url) {\n detailsText = Bindings.ResourceUtils.displayNameForURL(url);\n }\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.EMBEDDER_CALLBACK:\n detailsText = unsafeEventData['callbackName'];\n break;\n\n case TraceEngine.Types.TraceEvents.KnownEventName.ANIMATION:\n detailsText = unsafeEventData && unsafeEventData['name'];\n break;\n\n case TraceEngine.Types.TraceEvents.KnownEventName.ASYNC_TASK:\n detailsText = unsafeEventData ? unsafeEventData['name'] : null;\n break;\n\n default:\n if (TraceEngine.Helpers.Trace.eventHasCategory(event, TraceEngine.Types.TraceEvents.Categories.Console)) {\n detailsText = null;\n } else {\n detailsText = linkifyTopCallFrameAsText();\n }\n break;\n }\n\n return detailsText;\n\n function linkifyTopCallFrameAsText(): string|null {\n const frame = TraceEngine.Helpers.Trace.getZeroIndexedStackTraceForEvent(event)?.at(0) ?? null;\n if (!frame) {\n return null;\n }\n\n return frame.url + ':' + (frame.lineNumber + 1) + ':' + (frame.columnNumber + 1);\n }\n }\n\n static async buildDetailsNodeForTraceEvent(\n event: TraceEngine.Types.TraceEvents.TraceEventData, target: SDK.Target.Target|null,\n linkifier: LegacyComponents.Linkifier.Linkifier, isFreshRecording = false,\n traceParsedData: TraceEngine.Handlers.Types.TraceParseData): Promise {\n let details: HTMLElement|HTMLSpanElement|(Element | null)|Text|null = null;\n let detailsText;\n // TODO(40287735): update this code with type-safe data checks.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const unsafeEventArgs = event.args as Record;\n // TODO(40287735): update this code with type-safe data checks.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const unsafeEventData = event.args?.data as Record;\n\n switch (event.name) {\n case TraceEngine.Types.TraceEvents.KnownEventName.GC:\n case TraceEngine.Types.TraceEvents.KnownEventName.MAJOR_GC:\n case TraceEngine.Types.TraceEvents.KnownEventName.MINOR_GC:\n case TraceEngine.Types.TraceEvents.KnownEventName.EVENT_DISPATCH:\n case TraceEngine.Types.TraceEvents.KnownEventName.PAINT:\n case TraceEngine.Types.TraceEvents.KnownEventName.ANIMATION:\n case TraceEngine.Types.TraceEvents.KnownEventName.EMBEDDER_CALLBACK:\n case TraceEngine.Types.TraceEvents.KnownEventName.PARSE_HTML:\n case TraceEngine.Types.TraceEvents.KnownEventName.WASM_STREAM_FROM_RESPONSE_CALLBACK:\n case TraceEngine.Types.TraceEvents.KnownEventName.WASM_COMPILED_MODULE:\n case TraceEngine.Types.TraceEvents.KnownEventName.WASM_MODULE_CACHE_HIT:\n case TraceEngine.Types.TraceEvents.KnownEventName.WASM_CACHED_MODULE:\n case TraceEngine.Types.TraceEvents.KnownEventName.WASM_MODULE_CACHE_INVALID:\n case TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_CREATE:\n case TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_SEND_HANDSHAKE_REQUEST:\n case TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST:\n case TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_SEND:\n case TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_RECEIVE:\n case TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_DESTROY: {\n detailsText = await TimelineUIUtils.buildDetailsTextForTraceEvent(event, traceParsedData);\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.PAINT_IMAGE:\n case TraceEngine.Types.TraceEvents.KnownEventName.DECODE_IMAGE:\n case TraceEngine.Types.TraceEvents.KnownEventName.DECODE_LAZY_PIXEL_REF:\n case TraceEngine.Types.TraceEvents.KnownEventName.XHR_READY_STATE_CHANGED:\n case TraceEngine.Types.TraceEvents.KnownEventName.XHR_LOAD:\n case TraceEngine.Types.TraceEvents.KnownEventName.RESOURCE_WILL_SEND_REQUEST:\n case TraceEngine.Types.TraceEvents.KnownEventName.RESOURCE_SEND_REQUEST:\n case TraceEngine.Types.TraceEvents.KnownEventName.RESOURCE_RECEIVE_DATA:\n case TraceEngine.Types.TraceEvents.KnownEventName.RESOURCE_RECEIVE_RESPONSE:\n case TraceEngine.Types.TraceEvents.KnownEventName.RESOURCE_FINISH: {\n const url = TraceEngine.Extras.URLForEntry.get(traceParsedData, event);\n if (url) {\n const options = {\n tabStop: true,\n showColumnNumber: false,\n inlineFrameIndex: 0,\n };\n details = LegacyComponents.Linkifier.Linkifier.linkifyURL(url, options);\n }\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.FUNCTION_CALL: {\n details = document.createElement('span');\n\n // FunctionCall events have an args.data that could be a CallFrame, if all the details are present, so we check for that.\n if (TraceEngine.Types.TraceEvents.isTraceEventFunctionCall(event) && event.args.data &&\n TraceEngine.Types.TraceEvents.objectIsTraceEventCallFrame(event.args.data)) {\n UI.UIUtils.createTextChild(\n details,\n TimelineUIUtils.frameDisplayName(\n {...event.args.data, scriptId: String(event.args.data.scriptId) as Protocol.Runtime.ScriptId}));\n }\n const {lineNumber, columnNumber} = TraceEngine.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event);\n const location = this.linkifyLocation({\n scriptId: unsafeEventData['scriptId'],\n url: unsafeEventData['url'],\n lineNumber: lineNumber || 0,\n columnNumber,\n target,\n isFreshRecording,\n linkifier,\n });\n if (location) {\n UI.UIUtils.createTextChild(details, ' @ ');\n details.appendChild(location);\n }\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.COMPILE_MODULE:\n case TraceEngine.Types.TraceEvents.KnownEventName.CACHE_MODULE: {\n details = this.linkifyLocation({\n scriptId: null,\n url: unsafeEventArgs['fileName'],\n lineNumber: 0,\n columnNumber: 0,\n target,\n isFreshRecording,\n linkifier,\n });\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.COMPILE_SCRIPT:\n case TraceEngine.Types.TraceEvents.KnownEventName.CACHE_SCRIPT:\n case TraceEngine.Types.TraceEvents.KnownEventName.EVALUATE_SCRIPT: {\n const url = unsafeEventData['url'];\n if (url) {\n const {lineNumber} = TraceEngine.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event);\n details = this.linkifyLocation({\n scriptId: null,\n url,\n lineNumber: lineNumber || 0,\n columnNumber: 0,\n target,\n isFreshRecording,\n linkifier,\n });\n }\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.BACKGROUND_DESERIALIZE:\n case TraceEngine.Types.TraceEvents.KnownEventName.STREAMING_COMPILE_SCRIPT: {\n const url = unsafeEventData['url'];\n if (url) {\n details = this.linkifyLocation(\n {scriptId: null, url, lineNumber: 0, columnNumber: 0, target, isFreshRecording, linkifier});\n }\n break;\n }\n case TraceEngine.Types.TraceEvents.KnownEventName.PROFILE_CALL: {\n details = document.createElement('span');\n // This check is only added for convenience with the type checker.\n if (!TraceEngine.Types.TraceEvents.isProfileCall(event)) {\n break;\n }\n const maybeResolvedName = SourceMapsResolver.resolvedNodeNameForEntry(event);\n const functionName = maybeResolvedName || TimelineUIUtils.frameDisplayName(event.callFrame);\n UI.UIUtils.createTextChild(details, functionName);\n const location = this.linkifyLocation({\n scriptId: event.callFrame['scriptId'],\n url: event.callFrame['url'],\n lineNumber: event.callFrame['lineNumber'],\n columnNumber: event.callFrame['columnNumber'],\n target,\n isFreshRecording,\n linkifier,\n });\n if (location) {\n UI.UIUtils.createTextChild(details, ' @ ');\n details.appendChild(location);\n }\n break;\n }\n\n default: {\n /**\n * Some events have a stack trace which is extracted by default at @see TimelineUIUtils.generateCauses\n * thus, we prevent extracting the stack trace again here.\n */\n if (TraceEngine.Helpers.Trace.eventHasCategory(event, TraceEngine.Types.TraceEvents.Categories.Console) ||\n TraceEngine.Types.TraceEvents.isTraceEventUserTiming(event) ||\n TraceEngine.Types.Extensions.isSyntheticExtensionEntry(event)) {\n detailsText = null;\n } else {\n details = this.linkifyTopCallFrame(event, target, linkifier, isFreshRecording) ?? null;\n }\n break;\n }\n }\n\n if (!details && detailsText) {\n details = document.createTextNode(detailsText);\n }\n return details;\n }\n\n static linkifyLocation(linkifyOptions: LinkifyLocationOptions): Element|null {\n const {scriptId, url, lineNumber, columnNumber, isFreshRecording, linkifier, target} = linkifyOptions;\n const options = {\n lineNumber,\n columnNumber,\n showColumnNumber: true,\n inlineFrameIndex: 0,\n className: 'timeline-details',\n tabStop: true,\n };\n if (isFreshRecording) {\n return linkifier.linkifyScriptLocation(\n target, scriptId, url as Platform.DevToolsPath.UrlString, lineNumber, options);\n }\n return LegacyComponents.Linkifier.Linkifier.linkifyURL(url as Platform.DevToolsPath.UrlString, options);\n }\n\n static linkifyTopCallFrame(\n event: TraceEngine.Types.TraceEvents.TraceEventData, target: SDK.Target.Target|null,\n linkifier: LegacyComponents.Linkifier.Linkifier, isFreshRecording = false): Element|null {\n let frame = TraceEngine.Helpers.Trace.getZeroIndexedStackTraceForEvent(event)?.[0];\n if (TraceEngine.Types.TraceEvents.isProfileCall(event)) {\n frame = event.callFrame;\n }\n if (!frame) {\n return null;\n }\n const options = {\n className: 'timeline-details',\n tabStop: true,\n inlineFrameIndex: 0,\n showColumnNumber: true,\n columnNumber: frame.columnNumber,\n lineNumber: frame.lineNumber,\n };\n if (isFreshRecording) {\n return linkifier.maybeLinkifyConsoleCallFrame(target, frame, {showColumnNumber: true, inlineFrameIndex: 0});\n }\n return LegacyComponents.Linkifier.Linkifier.linkifyURL(frame.url as Platform.DevToolsPath.UrlString, options);\n }\n\n static buildDetailsNodeForMarkerEvents(event: TraceEngine.Types.TraceEvents.MarkerEvent): HTMLElement {\n let link = 'https://web.dev/user-centric-performance-metrics/';\n let name = 'page performance metrics';\n switch (event.name) {\n case TraceEngine.Types.TraceEvents.KnownEventName.MARK_LCP_CANDIDATE:\n link = 'https://web.dev/lcp/';\n name = 'largest contentful paint';\n break;\n case TraceEngine.Types.TraceEvents.KnownEventName.MARK_FCP:\n link = 'https://web.dev/first-contentful-paint/';\n name = 'first contentful paint';\n break;\n default:\n break;\n }\n\n const html = UI.Fragment.html`
${\n UI.XLink.XLink.create(\n link, i18nString(UIStrings.learnMore), undefined, undefined, 'learn-more')} about ${name}.
`;\n return html as HTMLElement;\n }\n\n static buildConsumeCacheDetails(\n eventData: {\n consumedCacheSize?: number,\n cacheRejected?: boolean,\n cacheKind?: string,\n },\n contentHelper: TimelineDetailsContentHelper): void {\n if (typeof eventData.consumedCacheSize === 'number') {\n contentHelper.appendTextRow(\n i18nString(UIStrings.compilationCacheStatus), i18nString(UIStrings.scriptLoadedFromCache));\n contentHelper.appendTextRow(\n i18nString(UIStrings.compilationCacheSize),\n Platform.NumberUtilities.bytesToString(eventData.consumedCacheSize));\n const cacheKind = eventData.cacheKind;\n if (cacheKind) {\n contentHelper.appendTextRow(i18nString(UIStrings.compilationCacheKind), cacheKind);\n }\n } else if ('cacheRejected' in eventData && eventData['cacheRejected']) {\n // Version mismatch or similar.\n contentHelper.appendTextRow(\n i18nString(UIStrings.compilationCacheStatus), i18nString(UIStrings.failedToLoadScriptFromCache));\n } else {\n contentHelper.appendTextRow(\n i18nString(UIStrings.compilationCacheStatus), i18nString(UIStrings.scriptNotEligibleToBeLoadedFromCache));\n }\n }\n\n static async buildTraceEventDetails(\n traceParseData: TraceEngine.Handlers.Types.TraceParseData,\n event: TraceEngine.Types.TraceEvents.TraceEventData,\n linkifier: LegacyComponents.Linkifier.Linkifier,\n detailed: boolean,\n ): Promise {\n const maybeTarget = targetForEvent(traceParseData, event);\n const {duration} = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event);\n const selfTime = getEventSelfTime(event, traceParseData);\n const relatedNodesMap = await TraceEngine.Extras.FetchNodes.extractRelatedDOMNodesFromEvent(\n traceParseData,\n event,\n );\n\n if (maybeTarget) {\n // @ts-ignore TODO(crbug.com/1011811): Remove symbol usage.\n if (typeof event[previewElementSymbol] === 'undefined') {\n let previewElement: (Element|null)|null = null;\n const url = TraceEngine.Extras.URLForEntry.get(traceParseData, event);\n if (url) {\n previewElement = await LegacyComponents.ImagePreview.ImagePreview.build(maybeTarget, url, false, {\n imageAltText: LegacyComponents.ImagePreview.ImagePreview.defaultAltTextForImageURL(url),\n precomputedFeatures: undefined,\n align: LegacyComponents.ImagePreview.Align.START,\n });\n } else if (TraceEngine.Types.TraceEvents.isTraceEventPaint(event)) {\n previewElement = await TimelineUIUtils.buildPicturePreviewContent(traceParseData, event, maybeTarget);\n }\n // @ts-ignore TODO(crbug.com/1011811): Remove symbol usage.\n event[previewElementSymbol] = previewElement;\n }\n }\n\n if (TraceEngine.Types.TraceEvents.isSyntheticLayoutShift(event)) {\n // Ensure that there are no pie charts or extended info for layout shifts.\n detailed = false;\n }\n\n // This message may vary per event.name;\n let relatedNodeLabel;\n\n const contentHelper = new TimelineDetailsContentHelper(targetForEvent(traceParseData, event), linkifier);\n\n const defaultColorForEvent = this.eventColor(event);\n const isMarker = traceParseData && isMarkerEvent(traceParseData, event);\n const color = isMarker ? TimelineUIUtils.markerStyleForEvent(event).color : defaultColorForEvent;\n\n contentHelper.addSection(TimelineUIUtils.eventTitle(event), color);\n\n // TODO: as part of the removal of the old engine, produce a typesafe way\n // to look up args and data for events.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const unsafeEventArgs = event.args as Record;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const unsafeEventData = event.args?.data as Record;\n const initiator = traceParseData.Initiators.eventToInitiator.get(event) ?? null;\n const initiatorFor = traceParseData.Initiators.initiatorToEvents.get(event) ?? null;\n\n let url: Platform.DevToolsPath.UrlString|null = null;\n\n if (traceParseData) {\n const warnings = TimelineComponents.DetailsView.buildWarningElementsForEvent(event, traceParseData);\n for (const warning of warnings) {\n contentHelper.appendElementRow(i18nString(UIStrings.warning), warning, true);\n }\n }\n\n // Add timestamp to user timings.\n if (TraceEngine.Helpers.Trace.eventHasCategory(event, TraceEngine.Types.TraceEvents.Categories.UserTiming)) {\n const adjustedEventTimeStamp = timeStampForEventAdjustedForClosestNavigationIfPossible(\n event,\n traceParseData,\n );\n contentHelper.appendTextRow(\n i18nString(UIStrings.timestamp), i18n.TimeUtilities.preciseMillisToString(adjustedEventTimeStamp, 1));\n }\n\n // Only show total time and self time for events with non-zero durations.\n if (detailed && !Number.isNaN(duration || 0) && duration !== 0) {\n contentHelper.appendTextRow(\n i18nString(UIStrings.totalTime), i18n.TimeUtilities.millisToString(duration || 0, true));\n contentHelper.appendTextRow(i18nString(UIStrings.selfTime), i18n.TimeUtilities.millisToString(selfTime, true));\n }\n\n if (TraceEngine.Types.TraceEvents.isTraceEventPerformanceMark(event) && event.args.data?.detail) {\n const detailContainer = TimelineUIUtils.renderObjectJson(JSON.parse(event.args.data?.detail));\n contentHelper.appendElementRow(i18nString(UIStrings.details), detailContainer);\n }\n if (TraceEngine.Types.TraceEvents.isSyntheticUserTiming(event) && event.args?.data?.beginEvent.args.detail) {\n const detailContainer = TimelineUIUtils.renderObjectJson(JSON.parse(event.args?.data?.beginEvent.args.detail));\n contentHelper.appendElementRow(i18nString(UIStrings.details), detailContainer);\n }\n\n if (traceParseData.Meta.traceIsGeneric) {\n TimelineUIUtils.renderEventJson(event, contentHelper);\n return contentHelper.fragment;\n }\n\n if (TraceEngine.Types.TraceEvents.isTraceEventV8Compile(event)) {\n url = event.args.data?.url as Platform.DevToolsPath.UrlString;\n if (url) {\n const {lineNumber, columnNumber} = TraceEngine.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event);\n contentHelper.appendLocationRow(i18nString(UIStrings.script), url, lineNumber || 0, columnNumber);\n }\n const isEager = Boolean(event.args.data?.eager);\n if (isEager) {\n contentHelper.appendTextRow(i18nString(UIStrings.eagerCompile), true);\n }\n\n const isStreamed = Boolean(event.args.data?.streamed);\n contentHelper.appendTextRow(\n i18nString(UIStrings.streamed),\n isStreamed + (isStreamed ? '' : `: ${event.args.data?.notStreamedReason || ''}`));\n if (event.args.data) {\n TimelineUIUtils.buildConsumeCacheDetails(event.args.data, contentHelper);\n }\n }\n\n if (TraceEngine.Types.Extensions.isSyntheticExtensionEntry(event)) {\n for (const [key, value] of event.args.properties || []) {\n contentHelper.appendTextRow(key, value);\n }\n }\n\n if (TraceEngine.Types.TraceEvents.isSyntheticServerTiming(event) && event.args.data.desc) {\n contentHelper.appendTextRow(i18nString(UIStrings.description), event.args.data.desc);\n }\n\n const isFreshRecording = Boolean(traceParseData && Tracker.instance().recordingIsFresh(traceParseData));\n\n switch (event.name) {\n case TraceEngine.Types.TraceEvents.KnownEventName.GC:\n case TraceEngine.Types.TraceEvents.KnownEventName.MAJOR_GC:\n case TraceEngine.Types.TraceEvents.KnownEventName.MINOR_GC: {\n const delta = unsafeEventArgs['usedHeapSizeBefore'] - unsafeEventArgs['usedHeapSizeAfter'];\n contentHelper.appendTextRow(i18nString(UIStrings.collected), Platform.NumberUtilities.bytesToString(delta));\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.PROFILE_CALL:\n case TraceEngine.Types.TraceEvents.KnownEventName.FUNCTION_CALL: {\n const detailsNode = await TimelineUIUtils.buildDetailsNodeForTraceEvent(\n event, targetForEvent(traceParseData, event), linkifier, isFreshRecording, traceParseData);\n if (detailsNode) {\n contentHelper.appendElementRow(i18nString(UIStrings.function), detailsNode);\n }\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.TIMER_FIRE:\n case TraceEngine.Types.TraceEvents.KnownEventName.TIMER_INSTALL:\n case TraceEngine.Types.TraceEvents.KnownEventName.TIMER_REMOVE: {\n contentHelper.appendTextRow(i18nString(UIStrings.timerId), unsafeEventData.timerId);\n\n if (event.name === TraceEngine.Types.TraceEvents.KnownEventName.TIMER_INSTALL) {\n contentHelper.appendTextRow(\n i18nString(UIStrings.timeout), i18n.TimeUtilities.millisToString(unsafeEventData['timeout']));\n contentHelper.appendTextRow(i18nString(UIStrings.repeats), !unsafeEventData['singleShot']);\n }\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.FIRE_ANIMATION_FRAME: {\n contentHelper.appendTextRow(i18nString(UIStrings.callbackId), unsafeEventData['id']);\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.COMPILE_MODULE: {\n contentHelper.appendLocationRow(i18nString(UIStrings.module), unsafeEventArgs['fileName'], 0);\n break;\n }\n case TraceEngine.Types.TraceEvents.KnownEventName.COMPILE_SCRIPT: {\n // This case is handled above\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.CACHE_MODULE: {\n url = unsafeEventData && unsafeEventData['url'] as Platform.DevToolsPath.UrlString;\n contentHelper.appendTextRow(\n i18nString(UIStrings.compilationCacheSize),\n Platform.NumberUtilities.bytesToString(unsafeEventData['producedCacheSize']));\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.CACHE_SCRIPT: {\n url = unsafeEventData && unsafeEventData['url'] as Platform.DevToolsPath.UrlString;\n if (url) {\n const {lineNumber, columnNumber} = TraceEngine.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event);\n contentHelper.appendLocationRow(i18nString(UIStrings.script), url, lineNumber || 0, columnNumber);\n }\n contentHelper.appendTextRow(\n i18nString(UIStrings.compilationCacheSize),\n Platform.NumberUtilities.bytesToString(unsafeEventData['producedCacheSize']));\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.EVALUATE_SCRIPT: {\n url = unsafeEventData && unsafeEventData['url'] as Platform.DevToolsPath.UrlString;\n if (url) {\n const {lineNumber, columnNumber} = TraceEngine.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event);\n contentHelper.appendLocationRow(i18nString(UIStrings.script), url, lineNumber || 0, columnNumber);\n }\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.WASM_STREAM_FROM_RESPONSE_CALLBACK:\n case TraceEngine.Types.TraceEvents.KnownEventName.WASM_COMPILED_MODULE:\n case TraceEngine.Types.TraceEvents.KnownEventName.WASM_CACHED_MODULE:\n case TraceEngine.Types.TraceEvents.KnownEventName.WASM_MODULE_CACHE_HIT:\n case TraceEngine.Types.TraceEvents.KnownEventName.WASM_MODULE_CACHE_INVALID: {\n if (unsafeEventData) {\n url = unsafeEventArgs['url'] as Platform.DevToolsPath.UrlString;\n if (url) {\n contentHelper.appendTextRow(i18nString(UIStrings.url), url);\n }\n const producedCachedSize = unsafeEventArgs['producedCachedSize'];\n if (producedCachedSize) {\n contentHelper.appendTextRow(i18nString(UIStrings.producedCacheSize), producedCachedSize);\n }\n const consumedCachedSize = unsafeEventArgs['consumedCachedSize'];\n if (consumedCachedSize) {\n contentHelper.appendTextRow(i18nString(UIStrings.consumedCacheSize), consumedCachedSize);\n }\n }\n break;\n }\n\n // @ts-ignore Fall-through intended.\n case TraceEngine.Types.TraceEvents.KnownEventName.PAINT: {\n const clip = unsafeEventData['clip'];\n contentHelper.appendTextRow(\n i18nString(UIStrings.location), i18nString(UIStrings.sSCurlyBrackets, {PH1: clip[0], PH2: clip[1]}));\n const clipWidth = TimelineUIUtils.quadWidth(clip);\n const clipHeight = TimelineUIUtils.quadHeight(clip);\n contentHelper.appendTextRow(\n i18nString(UIStrings.dimensions), i18nString(UIStrings.sSDimensions, {PH1: clipWidth, PH2: clipHeight}));\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.PAINT_SETUP:\n case TraceEngine.Types.TraceEvents.KnownEventName.RASTERIZE:\n case TraceEngine.Types.TraceEvents.KnownEventName.SCROLL_LAYER: {\n relatedNodeLabel = i18nString(UIStrings.layerRoot);\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.PAINT_IMAGE:\n case TraceEngine.Types.TraceEvents.KnownEventName.DECODE_LAZY_PIXEL_REF:\n case TraceEngine.Types.TraceEvents.KnownEventName.DECODE_IMAGE:\n case TraceEngine.Types.TraceEvents.KnownEventName.DRAW_LAZY_PIXEL_REF: {\n relatedNodeLabel = i18nString(UIStrings.ownerElement);\n url = TraceEngine.Extras.URLForEntry.get(traceParseData, event);\n if (url) {\n const options = {\n tabStop: true,\n showColumnNumber: false,\n inlineFrameIndex: 0,\n };\n contentHelper.appendElementRow(\n i18nString(UIStrings.imageUrl), LegacyComponents.Linkifier.Linkifier.linkifyURL(url, options));\n }\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.PARSE_AUTHOR_STYLE_SHEET: {\n url = unsafeEventData['styleSheetUrl'] as Platform.DevToolsPath.UrlString;\n if (url) {\n const options = {\n tabStop: true,\n showColumnNumber: false,\n inlineFrameIndex: 0,\n };\n contentHelper.appendElementRow(\n i18nString(UIStrings.stylesheetUrl), LegacyComponents.Linkifier.Linkifier.linkifyURL(url, options));\n }\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.UPDATE_LAYOUT_TREE: {\n contentHelper.appendTextRow(i18nString(UIStrings.elementsAffected), unsafeEventArgs['elementCount']);\n\n const selectorStatsSetting =\n Common.Settings.Settings.instance().createSetting('timeline-capture-selector-stats', false);\n if (!selectorStatsSetting.get()) {\n const note = document.createElement('span');\n note.textContent = i18nString(UIStrings.sSelectorStatsInfo, {PH1: selectorStatsSetting.title()});\n contentHelper.appendElementRow(i18nString(UIStrings.selectorStatsTitle), note);\n }\n\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.LAYOUT: {\n const beginData = unsafeEventArgs['beginData'];\n contentHelper.appendTextRow(\n i18nString(UIStrings.nodesThatNeedLayout),\n i18nString(UIStrings.sOfS, {PH1: beginData['dirtyObjects'], PH2: beginData['totalObjects']}));\n relatedNodeLabel = i18nString(UIStrings.layoutRoot);\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.CONSOLE_TIME: {\n contentHelper.appendTextRow(i18nString(UIStrings.message), event.name);\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_CREATE:\n case TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_SEND_HANDSHAKE_REQUEST:\n case TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST:\n case TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_SEND:\n case TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_RECEIVE:\n case TraceEngine.Types.TraceEvents.KnownEventName.WEB_SOCKET_DESTROY: {\n if (TraceEngine.Types.TraceEvents.isWebSocketTraceEvent(event)) {\n const rows = TimelineComponents.DetailsView.buildRowsForWebSocketEvent(event, traceParseData);\n for (const {key, value} of rows) {\n contentHelper.appendTextRow(key, value);\n }\n }\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.EMBEDDER_CALLBACK: {\n contentHelper.appendTextRow(i18nString(UIStrings.callbackFunction), unsafeEventData['callbackName']);\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.ANIMATION: {\n if (event.ph === TraceEngine.Types.TraceEvents.Phase.ASYNC_NESTABLE_INSTANT) {\n contentHelper.appendTextRow(i18nString(UIStrings.state), unsafeEventData['state']);\n }\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.PARSE_HTML: {\n const beginData = unsafeEventArgs['beginData'];\n const startLine = beginData['startLine'] - 1;\n const endLine = unsafeEventArgs['endData'] ? unsafeEventArgs['endData']['endLine'] - 1 : undefined;\n url = beginData['url'];\n if (url) {\n contentHelper.appendLocationRange(i18nString(UIStrings.range), url, startLine, endLine);\n }\n break;\n }\n\n // @ts-ignore Fall-through intended.\n case TraceEngine.Types.TraceEvents.KnownEventName.FIRE_IDLE_CALLBACK: {\n contentHelper.appendTextRow(\n i18nString(UIStrings.allottedTime),\n i18n.TimeUtilities.millisToString(unsafeEventData['allottedMilliseconds']));\n contentHelper.appendTextRow(i18nString(UIStrings.invokedByTimeout), unsafeEventData['timedOut']);\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.REQUEST_IDLE_CALLBACK:\n case TraceEngine.Types.TraceEvents.KnownEventName.CANCEL_IDLE_CALLBACK: {\n contentHelper.appendTextRow(i18nString(UIStrings.callbackId), unsafeEventData['id']);\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.EVENT_DISPATCH: {\n contentHelper.appendTextRow(i18nString(UIStrings.type), unsafeEventData['type']);\n break;\n }\n\n // @ts-ignore Fall-through intended.\n case TraceEngine.Types.TraceEvents.KnownEventName.MARK_LCP_CANDIDATE: {\n contentHelper.appendTextRow(i18nString(UIStrings.type), String(unsafeEventData['type']));\n contentHelper.appendTextRow(i18nString(UIStrings.size), String(unsafeEventData['size']));\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.MARK_FIRST_PAINT:\n case TraceEngine.Types.TraceEvents.KnownEventName.MARK_FCP:\n case TraceEngine.Types.TraceEvents.KnownEventName.MARK_LOAD:\n case TraceEngine.Types.TraceEvents.KnownEventName.MARK_DOM_CONTENT: {\n const adjustedEventTimeStamp = timeStampForEventAdjustedForClosestNavigationIfPossible(\n event,\n traceParseData,\n );\n\n contentHelper.appendTextRow(\n i18nString(UIStrings.timestamp), i18n.TimeUtilities.preciseMillisToString(adjustedEventTimeStamp, 1));\n\n if (TraceEngine.Types.TraceEvents.isTraceEventMarkerEvent(event)) {\n contentHelper.appendElementRow(\n i18nString(UIStrings.details), TimelineUIUtils.buildDetailsNodeForMarkerEvents(event));\n }\n\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.EVENT_TIMING: {\n const detailsNode = await TimelineUIUtils.buildDetailsNodeForTraceEvent(\n event, targetForEvent(traceParseData, event), linkifier, isFreshRecording, traceParseData);\n if (detailsNode) {\n contentHelper.appendElementRow(i18nString(UIStrings.details), detailsNode);\n }\n if (TraceEngine.Types.TraceEvents.isSyntheticInteractionEvent(event)) {\n const inputDelay = i18n.TimeUtilities.formatMicroSecondsAsMillisFixed(event.inputDelay);\n const mainThreadTime = i18n.TimeUtilities.formatMicroSecondsAsMillisFixed(event.mainThreadHandling);\n const presentationDelay = i18n.TimeUtilities.formatMicroSecondsAsMillisFixed(event.presentationDelay);\n contentHelper.appendTextRow(i18nString(UIStrings.interactionID), event.interactionId);\n contentHelper.appendTextRow(i18nString(UIStrings.inputDelay), inputDelay);\n contentHelper.appendTextRow(i18nString(UIStrings.processingDuration), mainThreadTime);\n contentHelper.appendTextRow(i18nString(UIStrings.presentationDelay), presentationDelay);\n }\n break;\n }\n\n case TraceEngine.Types.TraceEvents.KnownEventName.LAYOUT_SHIFT: {\n if (!TraceEngine.Types.TraceEvents.isSyntheticLayoutShift(event)) {\n console.error('Unexpected type for LayoutShift event');\n break;\n }\n const layoutShift = event as TraceEngine.Types.TraceEvents.SyntheticLayoutShift;\n const layoutShiftEventData = layoutShift.args.data;\n const warning = document.createElement('span');\n const clsLink = UI.XLink.XLink.create(\n 'https://web.dev/cls/', i18nString(UIStrings.cumulativeLayoutShifts), undefined, undefined,\n 'cumulative-layout-shifts');\n const evolvedClsLink = UI.XLink.XLink.create(\n 'https://web.dev/evolving-cls/', i18nString(UIStrings.evolvedClsLink), undefined, undefined, 'evolved-cls');\n\n warning.appendChild(\n i18n.i18n.getFormatLocalizedString(str_, UIStrings.sCLSInformation, {PH1: clsLink, PH2: evolvedClsLink}));\n contentHelper.appendElementRow(i18nString(UIStrings.warning), warning, true);\n if (!layoutShiftEventData) {\n break;\n }\n contentHelper.appendTextRow(i18nString(UIStrings.score), layoutShiftEventData['score'].toPrecision(4));\n contentHelper.appendTextRow(\n i18nString(UIStrings.cumulativeScore), layoutShiftEventData['cumulative_score'].toPrecision(4));\n contentHelper.appendTextRow(\n i18nString(UIStrings.currentClusterId), layoutShift.parsedData.sessionWindowData.id);\n contentHelper.appendTextRow(\n i18nString(UIStrings.currentClusterScore),\n layoutShift.parsedData.sessionWindowData.cumulativeWindowScore.toPrecision(4));\n contentHelper.appendTextRow(\n i18nString(UIStrings.hadRecentInput),\n unsafeEventData['had_recent_input'] ? i18nString(UIStrings.yes) : i18nString(UIStrings.no));\n\n for (const impactedNode of unsafeEventData['impacted_nodes']) {\n const oldRect = new CLSRect(impactedNode['old_rect']);\n const newRect = new CLSRect(impactedNode['new_rect']);\n\n const linkedOldRect = await Common.Linkifier.Linkifier.linkify(oldRect);\n const linkedNewRect = await Common.Linkifier.Linkifier.linkify(newRect);\n\n contentHelper.appendElementRow(i18nString(UIStrings.movedFrom), linkedOldRect);\n contentHelper.appendElementRow(i18nString(UIStrings.movedTo), linkedNewRect);\n }\n\n break;\n }\n\n default: {\n const detailsNode = await TimelineUIUtils.buildDetailsNodeForTraceEvent(\n event, targetForEvent(traceParseData, event), linkifier, isFreshRecording, traceParseData);\n if (detailsNode) {\n contentHelper.appendElementRow(i18nString(UIStrings.details), detailsNode);\n }\n break;\n }\n }\n const relatedNodes = relatedNodesMap?.values() || [];\n for (const relatedNode of relatedNodes) {\n if (relatedNode) {\n const nodeSpan = await Common.Linkifier.Linkifier.linkify(relatedNode);\n contentHelper.appendElementRow(relatedNodeLabel || i18nString(UIStrings.relatedNode), nodeSpan);\n }\n }\n\n // @ts-ignore TODO(crbug.com/1011811): Remove symbol usage.\n if (event[previewElementSymbol]) {\n contentHelper.addSection(i18nString(UIStrings.preview));\n // @ts-ignore TODO(crbug.com/1011811): Remove symbol usage.\n contentHelper.appendElementRow('', event[previewElementSymbol]);\n }\n\n const stackTrace = TraceEngine.Helpers.Trace.getZeroIndexedStackTraceForEvent(event);\n if (initiator || initiatorFor || stackTrace || traceParseData?.Invalidations.invalidationsForEvent.get(event)) {\n await TimelineUIUtils.generateCauses(event, contentHelper, traceParseData);\n }\n\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_DEBUG_MODE)) {\n TimelineUIUtils.renderEventJson(event, contentHelper);\n }\n\n const stats: {\n [x: string]: number,\n } = {};\n const showPieChart =\n detailed && traceParseData && TimelineUIUtils.aggregatedStatsForTraceEvent(stats, traceParseData, event);\n if (showPieChart) {\n contentHelper.addSection(i18nString(UIStrings.aggregatedTime));\n const pieChart = TimelineUIUtils.generatePieChart(stats, TimelineUIUtils.eventStyle(event).category, selfTime);\n contentHelper.appendElementRow('', pieChart);\n }\n\n return contentHelper.fragment;\n }\n\n static statsForTimeRange(\n events: TraceEngine.Types.TraceEvents.TraceEventData[], startTime: TraceEngine.Types.Timing.MilliSeconds,\n endTime: TraceEngine.Types.Timing.MilliSeconds): {\n [x: string]: number,\n } {\n if (!events.length) {\n return {idle: endTime - startTime};\n }\n\n buildRangeStatsCacheIfNeeded(events);\n const aggregatedStats = subtractStats(aggregatedStatsAtTime(endTime), aggregatedStatsAtTime(startTime));\n const aggregatedTotal = Object.values(aggregatedStats).reduce((a, b) => a + b, 0);\n aggregatedStats['idle'] = Math.max(0, endTime - startTime - aggregatedTotal);\n return aggregatedStats;\n\n function aggregatedStatsAtTime(time: number): {\n [x: string]: number,\n } {\n const stats: {\n [x: string]: number,\n } = {};\n // @ts-ignore TODO(crbug.com/1011811): Remove symbol usage.\n const cache = events[categoryBreakdownCacheSymbol];\n for (const category in cache) {\n const categoryCache = cache[category];\n const index =\n Platform.ArrayUtilities.upperBound(categoryCache.time, time, Platform.ArrayUtilities.DEFAULT_COMPARATOR);\n let value;\n if (index === 0) {\n value = 0;\n } else if (index === categoryCache.time.length) {\n value = categoryCache.value[categoryCache.value.length - 1];\n } else {\n const t0 = categoryCache.time[index - 1];\n const t1 = categoryCache.time[index];\n const v0 = categoryCache.value[index - 1];\n const v1 = categoryCache.value[index];\n value = v0 + (v1 - v0) * (time - t0) / (t1 - t0);\n }\n stats[category] = value;\n }\n return stats;\n }\n\n function subtractStats(\n a: {\n [x: string]: number,\n },\n b: {\n [x: string]: number,\n }): {\n [x: string]: number,\n } {\n const result = Object.assign({}, a);\n for (const key in b) {\n result[key] -= b[key];\n }\n return result;\n }\n\n function buildRangeStatsCacheIfNeeded(events: TraceEngine.Types.TraceEvents.TraceEventData[]): void {\n // @ts-ignore TODO(crbug.com/1011811): Remove symbol usage.\n if (events[categoryBreakdownCacheSymbol]) {\n return;\n }\n\n // aggeregatedStats is a map by categories. For each category there's an array\n // containing sorted time points which records accumulated value of the category.\n const aggregatedStats: {\n [x: string]: {\n time: number[],\n value: number[],\n },\n } = {};\n const categoryStack: string[] = [];\n let lastTime = 0;\n TraceEngine.Helpers.Trace.forEachEvent(events, {\n onStartEvent,\n onEndEvent,\n });\n\n function updateCategory(category: string, time: number): void {\n let statsArrays: {\n time: number[],\n value: number[],\n } = aggregatedStats[category];\n if (!statsArrays) {\n statsArrays = {time: [], value: []};\n aggregatedStats[category] = statsArrays;\n }\n if (statsArrays.time.length && statsArrays.time[statsArrays.time.length - 1] === time || lastTime > time) {\n return;\n }\n const lastValue = statsArrays.value.length > 0 ? statsArrays.value[statsArrays.value.length - 1] : 0;\n statsArrays.value.push(lastValue + time - lastTime);\n statsArrays.time.push(time);\n }\n\n function categoryChange(from: string|null, to: string|null, time: number): void {\n if (from) {\n updateCategory(from, time);\n }\n lastTime = time;\n if (to) {\n updateCategory(to, time);\n }\n }\n\n function onStartEvent(e: TraceEngine.Types.TraceEvents.TraceEventData): void {\n const {startTime} = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(e);\n const category =\n TimelineComponents.EntryStyles.getEventStyle(e.name as TraceEngine.Types.TraceEvents.KnownEventName)\n ?.category.name ||\n TimelineComponents.EntryStyles.getCategoryStyles().other.name;\n const parentCategory = categoryStack.length ? categoryStack[categoryStack.length - 1] : null;\n if (category !== parentCategory) {\n categoryChange(parentCategory || null, category, startTime);\n }\n categoryStack.push(category);\n }\n\n function onEndEvent(e: TraceEngine.Types.TraceEvents.TraceEventData): void {\n const {endTime} = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(e);\n const category = categoryStack.pop();\n const parentCategory = categoryStack.length ? categoryStack[categoryStack.length - 1] : null;\n if (category !== parentCategory) {\n categoryChange(category || null, parentCategory || null, endTime || 0);\n }\n }\n\n const obj = (events as Object);\n // @ts-ignore TODO(crbug.com/1011811): Remove symbol usage.\n obj[categoryBreakdownCacheSymbol] = aggregatedStats;\n }\n }\n\n private static renderEventJson(\n event: TraceEngine.Types.TraceEvents.TraceEventData, contentHelper: TimelineDetailsContentHelper): void {\n contentHelper.addSection(i18nString(UIStrings.traceEvent));\n\n const eventWithArgsFirst = {\n ...{args: event.args},\n ...event,\n };\n const highlightContainer = TimelineUIUtils.renderObjectJson(eventWithArgsFirst);\n contentHelper.appendElementRow('', highlightContainer);\n }\n\n private static renderObjectJson(obj: Object): HTMLDivElement {\n const indentLength = Common.Settings.Settings.instance().moduleSetting('text-editor-indent').get().length;\n // Elide if the data is huge. Then remove the initial new-line for a denser UI\n const eventStr = JSON.stringify(obj, null, indentLength).slice(0, 10_000).replace(/{\\n /, '{ ');\n\n // Use CodeHighlighter for syntax highlighting.\n const highlightContainer = document.createElement('div');\n const shadowRoot = highlightContainer.attachShadow({mode: 'open'});\n shadowRoot.adoptedStyleSheets = [inspectorCommonStyles, codeHighlighterStyles];\n const elem = shadowRoot.createChild('div');\n elem.classList.add('monospace', 'source-code');\n elem.textContent = eventStr;\n void CodeHighlighter.CodeHighlighter.highlightNode(elem, 'text/javascript');\n return highlightContainer;\n }\n\n static stackTraceFromCallFrames(callFrames: Protocol.Runtime.CallFrame[]|\n TraceEngine.Types.TraceEvents.TraceEventCallFrame[]): Protocol.Runtime.StackTrace {\n return {callFrames} as Protocol.Runtime.StackTrace;\n }\n\n private static async generateCauses(\n event: TraceEngine.Types.TraceEvents.TraceEventData, contentHelper: TimelineDetailsContentHelper,\n traceParseData: TraceEngine.Handlers.Types.TraceParseData): Promise {\n const {startTime} = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event);\n let initiatorStackLabel = i18nString(UIStrings.initiatorStackTrace);\n let stackLabel = i18nString(UIStrings.stackTrace);\n\n switch (event.name) {\n case TraceEngine.Types.TraceEvents.KnownEventName.TIMER_FIRE:\n initiatorStackLabel = i18nString(UIStrings.timerInstalled);\n break;\n case TraceEngine.Types.TraceEvents.KnownEventName.FIRE_ANIMATION_FRAME:\n initiatorStackLabel = i18nString(UIStrings.animationFrameRequested);\n break;\n case TraceEngine.Types.TraceEvents.KnownEventName.FIRE_IDLE_CALLBACK:\n initiatorStackLabel = i18nString(UIStrings.idleCallbackRequested);\n break;\n case TraceEngine.Types.TraceEvents.KnownEventName.UPDATE_LAYOUT_TREE:\n initiatorStackLabel = i18nString(UIStrings.firstInvalidated);\n stackLabel = i18nString(UIStrings.recalculationForced);\n break;\n case TraceEngine.Types.TraceEvents.KnownEventName.LAYOUT:\n initiatorStackLabel = i18nString(UIStrings.firstLayoutInvalidation);\n stackLabel = i18nString(UIStrings.layoutForced);\n break;\n }\n\n const stackTrace = TraceEngine.Helpers.Trace.getZeroIndexedStackTraceForEvent(event);\n if (stackTrace && stackTrace.length) {\n contentHelper.addSection(stackLabel);\n contentHelper.createChildStackTraceElement(TimelineUIUtils.stackTraceFromCallFrames(stackTrace));\n }\n\n const initiator = traceParseData.Initiators.eventToInitiator.get(event);\n const initiatorFor = traceParseData.Initiators.initiatorToEvents.get(event);\n const invalidations = traceParseData.Invalidations.invalidationsForEvent.get(event);\n\n if (initiator) {\n // If we have an initiator for the event, we can show its stack trace, a link to reveal the initiator,\n // and the time since the initiator (Pending For).\n const stackTrace = TraceEngine.Helpers.Trace.getZeroIndexedStackTraceForEvent(initiator);\n if (stackTrace) {\n contentHelper.addSection(initiatorStackLabel);\n contentHelper.createChildStackTraceElement(TimelineUIUtils.stackTraceFromCallFrames(stackTrace.map(frame => {\n return {\n ...frame,\n scriptId: String(frame.scriptId) as Protocol.Runtime.ScriptId,\n };\n })));\n }\n\n const link = this.createEntryLink(initiator);\n contentHelper.appendElementRow(i18nString(UIStrings.initiatedBy), link);\n\n const {startTime: initiatorStartTime} = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(initiator);\n const delay = startTime - initiatorStartTime;\n contentHelper.appendTextRow(i18nString(UIStrings.pendingFor), i18n.TimeUtilities.preciseMillisToString(delay, 1));\n }\n\n if (initiatorFor) {\n // If the event is an initiator for some entries, add links to reveal them.\n const links = document.createElement('div');\n initiatorFor.map((initiator, i) => {\n links.appendChild(this.createEntryLink(initiator));\n // Add space between each link if it's not last\n if (i < initiatorFor.length - 1) {\n links.append(' ');\n }\n });\n contentHelper.appendElementRow(UIStrings.initiatorFor, links);\n }\n\n if (invalidations && invalidations.length) {\n const totalInvalidations = traceParseData.Invalidations.invalidationCountForEvent.get(event) ??\n 0; // Won't be 0, but saves us dealing with undefined.\n contentHelper.addSection(i18nString(UIStrings.invalidations, {PH1: totalInvalidations}));\n await TimelineUIUtils.generateInvalidationsList(invalidations, contentHelper);\n }\n }\n\n private static createEntryLink(entry: TraceEngine.Types.TraceEvents.TraceEventData): HTMLElement {\n const link = document.createElement('span');\n\n const traceBoundsState = TraceBounds.TraceBounds.BoundsManager.instance().state();\n\n if (!traceBoundsState) {\n console.error('Tried to link to an entry without any traceBoundsState. This should never happen.');\n return link;\n }\n\n // Check is the entry is outside of the current breadcrumb. If it is, don't create a link to navigate to it because there is no way to navigate outside breadcrumb without removing it. Instead, just display the name and \"outside breadcrumb\" text\n // Consider entry outside breadcrumb only if it is fully outside. If a part of it is visible, we can still select it.\n const isEntryOutsideBreadcrumb = traceBoundsState.micro.minimapTraceBounds.min > entry.ts + (entry.dur || 0) ||\n traceBoundsState.micro.minimapTraceBounds.max < entry.ts;\n\n // Check if it is in the hidden array\n const isEntryHidden = ModificationsManager.activeManager()?.getEntriesFilter().entryIsInvisible(entry);\n\n if (!isEntryOutsideBreadcrumb) {\n link.classList.add('devtools-link');\n UI.ARIAUtils.markAsLink(link);\n link.tabIndex = 0;\n link.addEventListener('click', () => {\n TimelinePanel.instance().select(TimelineSelection.fromTraceEvent((entry)));\n });\n\n link.addEventListener('keydown', event => {\n if (event.key === 'Enter') {\n TimelinePanel.instance().select(TimelineSelection.fromTraceEvent((entry)));\n event.consume(true);\n }\n });\n }\n\n if (isEntryHidden) {\n link.textContent = this.eventTitle(entry) + ' ' + i18nString(UIStrings.entryIsHidden);\n } else if (isEntryOutsideBreadcrumb) {\n link.textContent = this.eventTitle(entry) + ' ' + i18nString(UIStrings.outsideBreadcrumbRange);\n } else {\n link.textContent = this.eventTitle(entry);\n }\n\n return link;\n }\n\n private static async generateInvalidationsList(\n invalidations: TraceEngine.Types.TraceEvents.InvalidationTrackingEvent[],\n contentHelper: TimelineDetailsContentHelper): Promise {\n const {groupedByReason, backendNodeIds} = TimelineComponents.DetailsView.generateInvalidationsList(invalidations);\n\n let relatedNodesMap: Map|null = null;\n const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n const domModel = target?.model(SDK.DOMModel.DOMModel);\n if (domModel) {\n relatedNodesMap = await domModel.pushNodesByBackendIdsToFrontend(backendNodeIds);\n }\n\n Object.keys(groupedByReason).forEach(reason => {\n TimelineUIUtils.generateInvalidationsForReason(reason, groupedByReason[reason], relatedNodesMap, contentHelper);\n });\n }\n\n private static generateInvalidationsForReason(\n reason: string, invalidations: TraceEngine.Types.TraceEvents.InvalidationTrackingEvent[],\n relatedNodesMap: Map|null, contentHelper: TimelineDetailsContentHelper): void {\n function createLinkForInvalidationNode(invalidation: TraceEngine.Types.TraceEvents.InvalidationTrackingEvent):\n HTMLSpanElement {\n const node = (invalidation.args.data.nodeId && relatedNodesMap) ?\n relatedNodesMap.get(invalidation.args.data.nodeId) :\n null;\n if (node) {\n const nodeSpan = document.createElement('span');\n void Common.Linkifier.Linkifier.linkify(node).then(link => nodeSpan.appendChild(link));\n return nodeSpan;\n }\n if (invalidation.args.data.nodeName) {\n const nodeSpan = document.createElement('span');\n nodeSpan.textContent = invalidation.args.data.nodeName;\n return nodeSpan;\n }\n const nodeSpan = document.createElement('span');\n UI.UIUtils.createTextChild(nodeSpan, i18nString(UIStrings.UnknownNode));\n return nodeSpan;\n }\n\n const generatedItems = new Set();\n\n for (const invalidation of invalidations) {\n const stackTrace = TraceEngine.Helpers.Trace.getZeroIndexedStackTraceForEvent(invalidation);\n let scriptLink: HTMLElement|null = null;\n const callFrame = stackTrace?.at(0);\n if (callFrame) {\n scriptLink = contentHelper.linkifier()?.maybeLinkifyScriptLocation(\n SDK.TargetManager.TargetManager.instance().rootTarget(),\n callFrame.scriptId as Protocol.Runtime.ScriptId,\n callFrame.url as Platform.DevToolsPath.UrlString,\n callFrame.lineNumber,\n ) ||\n null;\n }\n\n const niceNodeLink = createLinkForInvalidationNode(invalidation);\n\n const text = scriptLink ?\n i18n.i18n.getFormatLocalizedString(\n str_, UIStrings.invalidationWithCallFrame, {PH1: niceNodeLink, PH2: scriptLink}) as HTMLElement :\n niceNodeLink;\n\n // Sometimes we can get different Invalidation events which cause\n // the same text for the same element for the same reason to be\n // generated. Rather than show the user duplicates, if we have\n // generated text that looks identical to this before, we will\n // bail.\n const generatedText: string = (typeof text === 'string' ? text : text.innerText);\n if (generatedItems.has(generatedText)) {\n continue;\n }\n\n generatedItems.add(generatedText);\n contentHelper.appendElementRow(reason, text);\n }\n }\n\n private static aggregatedStatsForTraceEvent(\n total: {\n [x: string]: number,\n },\n traceParseData: TraceEngine.Handlers.Types.TraceParseData,\n event: TraceEngine.Types.TraceEvents.TraceEventData): boolean {\n const events = traceParseData.Renderer?.allTraceEntries || [];\n const {startTime, endTime} = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event);\n function eventComparator(startTime: number, e: TraceEngine.Types.TraceEvents.TraceEventData): number {\n const {startTime: eventStartTime} = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(e);\n return startTime - eventStartTime;\n }\n\n const index = Platform.ArrayUtilities.binaryIndexOf(events, startTime, eventComparator);\n // Not a main thread event?\n if (index < 0) {\n return false;\n }\n let hasChildren = false;\n if (endTime) {\n for (let i = index; i < events.length; i++) {\n const nextEvent = events[i];\n const {startTime: nextEventStartTime} = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(nextEvent);\n if (nextEventStartTime >= endTime) {\n break;\n }\n const nextEventSelfTime = getEventSelfTime(nextEvent, traceParseData);\n if (!nextEventSelfTime) {\n continue;\n }\n if (nextEvent.tid !== event.tid) {\n continue;\n }\n if (i > index) {\n hasChildren = true;\n }\n const categoryName = TimelineUIUtils.eventStyle(nextEvent).category.name;\n total[categoryName] = (total[categoryName] || 0) + nextEventSelfTime;\n }\n }\n if (TraceEngine.Types.TraceEvents.isAsyncPhase(event.ph)) {\n if (endTime) {\n let aggregatedTotal = 0;\n for (const categoryName in total) {\n aggregatedTotal += total[categoryName];\n }\n total['idle'] = Math.max(0, endTime - startTime - aggregatedTotal);\n }\n return false;\n }\n return hasChildren;\n }\n\n static async buildPicturePreviewContent(\n traceData: TraceEngine.Handlers.Types.TraceParseData, event: TraceEngine.Types.TraceEvents.TraceEventPaint,\n target: SDK.Target.Target): Promise {\n const snapshotEvent = traceData.LayerTree.paintsToSnapshots.get(event);\n if (!snapshotEvent) {\n return null;\n }\n\n const paintProfilerModel = target.model(SDK.PaintProfiler.PaintProfilerModel);\n if (!paintProfilerModel) {\n return null;\n }\n const snapshot = await paintProfilerModel.loadSnapshot(snapshotEvent.args.snapshot.skp64);\n if (!snapshot) {\n return null;\n }\n\n const snapshotWithRect = {\n snapshot,\n rect: snapshotEvent.args.snapshot.params?.layer_rect,\n };\n\n if (!snapshotWithRect) {\n return null;\n }\n const imageURLPromise = snapshotWithRect.snapshot.replay();\n snapshotWithRect.snapshot.release();\n const imageURL = await imageURLPromise as Platform.DevToolsPath.UrlString;\n if (!imageURL) {\n return null;\n }\n const stylesContainer = document.createElement('div');\n const shadowRoot = stylesContainer.attachShadow({mode: 'open'});\n shadowRoot.adoptedStyleSheets = [imagePreviewStyles];\n const container = shadowRoot.createChild('div') as HTMLDivElement;\n container.classList.add('image-preview-container', 'vbox', 'link');\n const img = (container.createChild('img') as HTMLImageElement);\n img.src = imageURL;\n img.alt = LegacyComponents.ImagePreview.ImagePreview.defaultAltTextForImageURL(imageURL);\n const paintProfilerButton = container.createChild('a');\n paintProfilerButton.textContent = i18nString(UIStrings.paintProfiler);\n UI.ARIAUtils.markAsLink(container);\n container.tabIndex = 0;\n container.addEventListener(\n 'click', () => TimelinePanel.instance().select(TimelineSelection.fromTraceEvent(event)), false);\n container.addEventListener('keydown', keyEvent => {\n if (keyEvent.key === 'Enter') {\n TimelinePanel.instance().select(TimelineSelection.fromTraceEvent(event));\n keyEvent.consume(true);\n }\n });\n return stylesContainer;\n }\n\n static createEventDivider(event: TraceEngine.Types.TraceEvents.TraceEventData, zeroTime: number): Element {\n const eventDivider = document.createElement('div');\n eventDivider.classList.add('resources-event-divider');\n const {startTime: eventStartTime} = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event);\n\n const startTime = i18n.TimeUtilities.millisToString(eventStartTime - zeroTime);\n UI.Tooltip.Tooltip.install(\n eventDivider, i18nString(UIStrings.sAtS, {PH1: TimelineUIUtils.eventTitle(event), PH2: startTime}));\n const style = TimelineUIUtils.markerStyleForEvent(event);\n if (style.tall) {\n eventDivider.style.backgroundColor = style.color;\n }\n return eventDivider;\n }\n\n static visibleEventsFilter(): TimelineModel.TimelineModelFilter.TimelineModelFilter {\n return new TimelineModel.TimelineModelFilter.TimelineVisibleEventsFilter(\n TimelineComponents.EntryStyles.visibleTypes());\n }\n\n // Included only for layout tests.\n // TODO(crbug.com/1386091): Fix/port layout tests and remove.\n static categories(): TimelineComponents.EntryStyles.CategoryPalette {\n return TimelineComponents.EntryStyles.getCategoryStyles();\n }\n\n static generatePieChart(\n aggregatedStats: {\n [x: string]: number,\n },\n selfCategory?: TimelineComponents.EntryStyles.TimelineCategory, selfTime?: number): Element {\n let total = 0;\n for (const categoryName in aggregatedStats) {\n total += aggregatedStats[categoryName];\n }\n\n const element = document.createElement('div');\n element.classList.add('timeline-details-view-pie-chart-wrapper');\n element.classList.add('hbox');\n\n const pieChart = new PerfUI.PieChart.PieChart();\n const slices: {\n value: number,\n color: string,\n title: string,\n }[] = [];\n\n function appendLegendRow(name: string, title: string, value: number, color: string): void {\n if (!value) {\n return;\n }\n slices.push({value, color, title});\n }\n\n // In case of self time, first add self, then children of the same category.\n if (selfCategory) {\n if (selfTime) {\n appendLegendRow(\n selfCategory.name, i18nString(UIStrings.sSelf, {PH1: selfCategory.title}), selfTime,\n selfCategory.getCSSValue());\n }\n // Children of the same category.\n const categoryTime = aggregatedStats[selfCategory.name];\n const value = categoryTime - (selfTime || 0);\n if (value > 0) {\n appendLegendRow(\n selfCategory.name, i18nString(UIStrings.sChildren, {PH1: selfCategory.title}), value,\n selfCategory.getCSSValue());\n }\n }\n\n // Add other categories.\n for (const categoryName in TimelineComponents.EntryStyles.getCategoryStyles()) {\n const category = TimelineComponents.EntryStyles\n .getCategoryStyles()[categoryName as keyof TimelineComponents.EntryStyles.CategoryPalette];\n if (categoryName === selfCategory?.name) {\n // Do not add an entry for this event's self category because 2\n // entries for it where added just before this for loop (for\n // self and children times).\n continue;\n }\n appendLegendRow(category.name, category.title, aggregatedStats[category.name], category.getCSSValue());\n }\n\n pieChart.data = {\n chartName: i18nString(UIStrings.timeSpentInRendering),\n size: 110,\n formatter: (value: number) => i18n.TimeUtilities.preciseMillisToString(value),\n showLegend: true,\n total,\n slices,\n };\n const pieChartContainer = element.createChild('div', 'vbox');\n pieChartContainer.appendChild(pieChart);\n\n return element;\n }\n\n static generateDetailsContentForFrame(\n frame: TraceEngine.Types.TraceEvents.LegacyTimelineFrame, filmStrip: TraceEngine.Extras.FilmStrip.Data|null,\n filmStripFrame: TraceEngine.Extras.FilmStrip.Frame|null): DocumentFragment {\n const contentHelper = new TimelineDetailsContentHelper(null, null);\n contentHelper.addSection(i18nString(UIStrings.frame));\n\n const duration = TimelineUIUtils.frameDuration(frame);\n contentHelper.appendElementRow(i18nString(UIStrings.duration), duration);\n if (filmStrip && filmStripFrame) {\n const filmStripPreview = document.createElement('div');\n filmStripPreview.classList.add('timeline-filmstrip-preview');\n void UI.UIUtils.loadImage(filmStripFrame.screenshotEvent.args.dataUri)\n .then(image => image && filmStripPreview.appendChild(image));\n contentHelper.appendElementRow('', filmStripPreview);\n filmStripPreview.addEventListener('click', frameClicked.bind(null, filmStrip, filmStripFrame), false);\n }\n\n function frameClicked(\n filmStrip: TraceEngine.Extras.FilmStrip.Data, filmStripFrame: TraceEngine.Extras.FilmStrip.Frame): void {\n PerfUI.FilmStripView.Dialog.fromFilmStrip(filmStrip, filmStripFrame.index);\n }\n\n return contentHelper.fragment;\n }\n\n static frameDuration(frame: TraceEngine.Types.TraceEvents.LegacyTimelineFrame): Element {\n const offsetMilli = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.startTimeOffset);\n const durationMilli = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(\n TraceEngine.Types.Timing.MicroSeconds(frame.endTime - frame.startTime));\n\n const durationText = i18nString(UIStrings.sAtSParentheses, {\n PH1: i18n.TimeUtilities.millisToString(durationMilli, true),\n PH2: i18n.TimeUtilities.millisToString(offsetMilli, true),\n });\n return i18n.i18n.getFormatLocalizedString(str_, UIStrings.emptyPlaceholder, {PH1: durationText});\n }\n\n static quadWidth(quad: number[]): number {\n return Math.round(Math.sqrt(Math.pow(quad[0] - quad[2], 2) + Math.pow(quad[1] - quad[3], 2)));\n }\n\n static quadHeight(quad: number[]): number {\n return Math.round(Math.sqrt(Math.pow(quad[0] - quad[6], 2) + Math.pow(quad[1] - quad[7], 2)));\n }\n\n static eventDispatchDesciptors(): EventDispatchTypeDescriptor[] {\n if (eventDispatchDesciptors) {\n return eventDispatchDesciptors;\n }\n const lightOrange = 'hsl(40,100%,80%)';\n const orange = 'hsl(40,100%,50%)';\n const green = 'hsl(90,100%,40%)';\n const purple = 'hsl(256,100%,75%)';\n eventDispatchDesciptors = [\n new EventDispatchTypeDescriptor(\n 1, lightOrange, ['mousemove', 'mouseenter', 'mouseleave', 'mouseout', 'mouseover']),\n new EventDispatchTypeDescriptor(\n 1, lightOrange, ['pointerover', 'pointerout', 'pointerenter', 'pointerleave', 'pointermove']),\n new EventDispatchTypeDescriptor(2, green, ['wheel']),\n new EventDispatchTypeDescriptor(3, orange, ['click', 'mousedown', 'mouseup']),\n new EventDispatchTypeDescriptor(3, orange, ['touchstart', 'touchend', 'touchmove', 'touchcancel']),\n new EventDispatchTypeDescriptor(\n 3, orange, ['pointerdown', 'pointerup', 'pointercancel', 'gotpointercapture', 'lostpointercapture']),\n new EventDispatchTypeDescriptor(3, purple, ['keydown', 'keyup', 'keypress']),\n ];\n return eventDispatchDesciptors;\n }\n\n static markerStyleForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): TimelineMarkerStyle {\n const tallMarkerDashStyle = [6, 4];\n const title = TimelineUIUtils.eventTitle(event);\n\n if (event.name !== TraceEngine.Types.TraceEvents.KnownEventName.NAVIGATION_START &&\n TraceEngine.Helpers.Trace.eventHasCategory(event, TraceEngine.Types.TraceEvents.Categories.Console) ||\n TraceEngine.Helpers.Trace.eventHasCategory(event, TraceEngine.Types.TraceEvents.Categories.UserTiming)) {\n return {\n title,\n dashStyle: tallMarkerDashStyle,\n lineWidth: 0.5,\n color: TraceEngine.Helpers.Trace.eventHasCategory(event, TraceEngine.Types.TraceEvents.Categories.Console) ?\n 'purple' :\n 'orange',\n tall: false,\n lowPriority: false,\n };\n }\n let tall = false;\n let color = 'grey';\n switch (event.name) {\n case TraceEngine.Types.TraceEvents.KnownEventName.NAVIGATION_START:\n color = '#FF9800';\n tall = true;\n break;\n case TraceEngine.Types.TraceEvents.KnownEventName.FRAME_STARTED_LOADING:\n color = 'green';\n tall = true;\n break;\n case TraceEngine.Types.TraceEvents.KnownEventName.MARK_DOM_CONTENT:\n color = '#0867CB';\n tall = true;\n break;\n case TraceEngine.Types.TraceEvents.KnownEventName.MARK_LOAD:\n color = '#B31412';\n tall = true;\n break;\n case TraceEngine.Types.TraceEvents.KnownEventName.MARK_FIRST_PAINT:\n color = '#228847';\n tall = true;\n break;\n case TraceEngine.Types.TraceEvents.KnownEventName.MARK_FCP:\n color = '#1A6937';\n tall = true;\n break;\n case TraceEngine.Types.TraceEvents.KnownEventName.MARK_LCP_CANDIDATE:\n color = '#1A3422';\n tall = true;\n break;\n case TraceEngine.Types.TraceEvents.KnownEventName.TIME_STAMP:\n color = 'orange';\n break;\n }\n return {\n title,\n dashStyle: tallMarkerDashStyle,\n lineWidth: 0.5,\n color,\n tall,\n lowPriority: false,\n };\n }\n\n static colorForId(id: string): string {\n if (!colorGenerator) {\n colorGenerator =\n new Common.Color.Generator({min: 30, max: 330, count: undefined}, {min: 50, max: 80, count: 3}, 85);\n colorGenerator.setColorForID('', '#f2ecdc');\n }\n return colorGenerator.colorForID(id);\n }\n\n static displayNameForFrame(frame: TraceEngine.Types.TraceEvents.TraceFrame, trimAt: number = 80): string {\n const url = frame.url as Platform.DevToolsPath.UrlString;\n return Common.ParsedURL.schemeIs(url, 'about:') ? `\"${Platform.StringUtilities.trimMiddle(frame.name, trimAt)}\"` :\n frame.url.slice(0, trimAt);\n }\n}\n\nexport const aggregatedStatsKey = Symbol('aggregatedStats');\n\nexport const previewElementSymbol = Symbol('previewElement');\n\nexport class EventDispatchTypeDescriptor {\n priority: number;\n color: string;\n eventTypes: string[];\n\n constructor(priority: number, color: string, eventTypes: string[]) {\n this.priority = priority;\n this.color = color;\n this.eventTypes = eventTypes;\n }\n}\n\nexport class TimelineDetailsContentHelper {\n fragment: DocumentFragment;\n private linkifierInternal: LegacyComponents.Linkifier.Linkifier|null;\n private target: SDK.Target.Target|null;\n element: HTMLDivElement;\n private tableElement: HTMLElement;\n\n constructor(target: SDK.Target.Target|null, linkifier: LegacyComponents.Linkifier.Linkifier|null) {\n this.fragment = document.createDocumentFragment();\n\n this.linkifierInternal = linkifier;\n this.target = target;\n\n this.element = document.createElement('div');\n this.element.classList.add('timeline-details-view-block');\n this.tableElement = this.element.createChild('div', 'vbox timeline-details-chip-body');\n this.fragment.appendChild(this.element);\n }\n\n addSection(title: string, swatchColor?: string): void {\n if (!this.tableElement.hasChildNodes()) {\n this.element.removeChildren();\n } else {\n this.element = document.createElement('div');\n this.element.classList.add('timeline-details-view-block');\n this.fragment.appendChild(this.element);\n }\n\n if (title) {\n const titleElement = this.element.createChild('div', 'timeline-details-chip-title');\n if (swatchColor) {\n titleElement.createChild('div').style.backgroundColor = swatchColor;\n }\n UI.UIUtils.createTextChild(titleElement, title);\n }\n\n this.tableElement = this.element.createChild('div', 'vbox timeline-details-chip-body');\n this.fragment.appendChild(this.element);\n }\n\n linkifier(): LegacyComponents.Linkifier.Linkifier|null {\n return this.linkifierInternal;\n }\n\n appendTextRow(title: string, value: string|number|boolean): void {\n const rowElement = this.tableElement.createChild('div', 'timeline-details-view-row');\n rowElement.createChild('div', 'timeline-details-view-row-title').textContent = title;\n rowElement.createChild('div', 'timeline-details-view-row-value').textContent = value.toString();\n }\n\n appendElementRow(title: string, content: string|Node, isWarning?: boolean, isStacked?: boolean): void {\n const rowElement = this.tableElement.createChild('div', 'timeline-details-view-row');\n rowElement.setAttribute('data-row-title', title);\n if (isWarning) {\n rowElement.classList.add('timeline-details-warning');\n }\n if (isStacked) {\n rowElement.classList.add('timeline-details-stack-values');\n }\n const titleElement = rowElement.createChild('div', 'timeline-details-view-row-title');\n titleElement.textContent = title;\n const valueElement = rowElement.createChild('div', 'timeline-details-view-row-value');\n if (content instanceof Node) {\n valueElement.appendChild(content);\n } else {\n UI.UIUtils.createTextChild(valueElement, content || '');\n }\n }\n\n appendLocationRow(title: string, url: string, startLine: number, startColumn?: number): void {\n if (!this.linkifierInternal) {\n return;\n }\n\n const options = {\n tabStop: true,\n columnNumber: startColumn,\n showColumnNumber: true,\n inlineFrameIndex: 0,\n };\n const link = this.linkifierInternal.maybeLinkifyScriptLocation(\n this.target, null, url as Platform.DevToolsPath.UrlString, startLine, options);\n if (!link) {\n return;\n }\n this.appendElementRow(title, link);\n }\n\n appendLocationRange(title: string, url: Platform.DevToolsPath.UrlString, startLine: number, endLine?: number): void {\n if (!this.linkifierInternal || !this.target) {\n return;\n }\n const locationContent = document.createElement('span');\n const link = this.linkifierInternal.maybeLinkifyScriptLocation(\n this.target, null, url, startLine, {tabStop: true, inlineFrameIndex: 0});\n if (!link) {\n return;\n }\n locationContent.appendChild(link);\n UI.UIUtils.createTextChild(\n locationContent, Platform.StringUtilities.sprintf(' [%s…%s]', startLine + 1, (endLine || 0) + 1 || ''));\n this.appendElementRow(title, locationContent);\n }\n\n createChildStackTraceElement(stackTrace: Protocol.Runtime.StackTrace): void {\n if (!this.linkifierInternal) {\n return;\n }\n\n const stackTraceElement =\n this.tableElement.createChild('div', 'timeline-details-view-row timeline-details-stack-values');\n const callFrameContents = LegacyComponents.JSPresentationUtils.buildStackTracePreviewContents(\n this.target, this.linkifierInternal, {stackTrace, tabStops: true, showColumnNumber: true});\n stackTraceElement.appendChild(callFrameContents.element);\n }\n}\n\nexport const categoryBreakdownCacheSymbol = Symbol('categoryBreakdownCache');\nexport interface TimelineMarkerStyle {\n title: string;\n color: string;\n lineWidth: number;\n dashStyle: number[];\n tall: boolean;\n lowPriority: boolean;\n}\n\n/**\n * Given a particular event, this method can adjust its timestamp by\n * substracting the timestamp of the previous navigation. This helps in cases\n * where the user has navigated multiple times in the trace, so that we can show\n * the LCP (for example) relative to the last navigation.\n **/\nexport function timeStampForEventAdjustedForClosestNavigationIfPossible(\n event: TraceEngine.Types.TraceEvents.TraceEventData,\n traceParsedData: TraceEngine.Handlers.Types.TraceParseData|null): TraceEngine.Types.Timing.MilliSeconds {\n if (!traceParsedData) {\n const {startTime} = TraceEngine.Helpers.Timing.eventTimingsMilliSeconds(event);\n return startTime;\n }\n\n const time = TraceEngine.Helpers.Timing.timeStampForEventAdjustedByClosestNavigation(\n event,\n traceParsedData.Meta.traceBounds,\n traceParsedData.Meta.navigationsByNavigationId,\n traceParsedData.Meta.navigationsByFrameId,\n );\n return TraceEngine.Helpers.Timing.microSecondsToMilliseconds(time);\n}\n\n/**\n * Determines if an event is potentially a marker event. A marker event here\n * is a single moment in time that we want to highlight on the timeline, such as\n * the LCP time. This method does not filter out events: for example, it treats\n * every LCP Candidate event as a potential marker event.\n **/\nexport function isMarkerEvent(\n traceParseData: TraceEngine.Handlers.Types.TraceParseData,\n event: TraceEngine.Types.TraceEvents.TraceEventData): boolean {\n const {KnownEventName} = TraceEngine.Types.TraceEvents;\n\n if (event.name === KnownEventName.TIME_STAMP) {\n return true;\n }\n\n if (TraceEngine.Types.TraceEvents.isTraceEventFirstContentfulPaint(event) ||\n TraceEngine.Types.TraceEvents.isTraceEventFirstPaint(event)) {\n return event.args.frame === traceParseData.Meta.mainFrameId;\n }\n\n if (TraceEngine.Types.TraceEvents.isTraceEventMarkDOMContent(event) ||\n TraceEngine.Types.TraceEvents.isTraceEventMarkLoad(event) ||\n TraceEngine.Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate(event)) {\n // isOutermostMainFrame was added in 2022, so we fallback to isMainFrame\n // for older traces.\n if (!event.args.data) {\n return false;\n }\n const {isOutermostMainFrame, isMainFrame} = event.args.data;\n if (typeof isOutermostMainFrame !== 'undefined') {\n // If isOutermostMainFrame is defined we want to use that and not\n // fallback to isMainFrame, even if isOutermostMainFrame is false. Hence\n // this check.\n return isOutermostMainFrame;\n }\n return Boolean(isMainFrame);\n }\n\n return false;\n}\n\nfunction getEventSelfTime(\n event: TraceEngine.Types.TraceEvents.TraceEventData,\n traceParseData: TraceEngine.Handlers.Types.TraceParseData): TraceEngine.Types.Timing.MilliSeconds {\n const mapToUse = TraceEngine.Types.Extensions.isSyntheticExtensionEntry(event) ?\n traceParseData.ExtensionTraceData.entryToNode :\n traceParseData.Renderer.entryToNode;\n const selfTime = mapToUse.get(event)?.selfTime;\n return selfTime ? TraceEngine.Helpers.Timing.microSecondsToMilliseconds(selfTime) :\n TraceEngine.Types.Timing.MilliSeconds(0);\n}\n"]} \ No newline at end of file +{"version":3,"file":"TimelineUIUtils.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineUIUtils.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2021 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/*\n * Copyright (C) 2013 Google Inc. All rights reserved.\n * Copyright (C) 2012 Intel Inc. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * * Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above\n * copyright notice, this list of conditions and the following disclaimer\n * in the documentation and/or other materials provided with the\n * distribution.\n * * Neither the name of Google Inc. nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Platform from '../../core/platform/platform.js';\nimport * as Root from '../../core/root/root.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport type * as Protocol from '../../generated/protocol.js';\nimport * as Bindings from '../../models/bindings/bindings.js';\nimport * as TimelineModel from '../../models/timeline_model/timeline_model.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as TraceBounds from '../../services/trace_bounds/trace_bounds.js';\nimport * as CodeHighlighter from '../../ui/components/code_highlighter/code_highlighter.js';\n// eslint-disable-next-line rulesdir/es_modules_import\nimport codeHighlighterStyles from '../../ui/components/code_highlighter/codeHighlighter.css.js';\nimport * as PerfUI from '../../ui/legacy/components/perf_ui/perf_ui.js';\n// eslint-disable-next-line rulesdir/es_modules_import\nimport imagePreviewStyles from '../../ui/legacy/components/utils/imagePreview.css.js';\nimport * as LegacyComponents from '../../ui/legacy/components/utils/utils.js';\nimport * as UI from '../../ui/legacy/legacy.js';\n\nimport {CLSRect} from './CLSLinkifier.js';\nimport * as TimelineComponents from './components/components.js';\nimport * as Extensions from './extensions/extensions.js';\nimport {Tracker} from './FreshRecording.js';\nimport {ModificationsManager} from './ModificationsManager.js';\nimport {SourceMapsResolver} from './SourceMapsResolver.js';\nimport {targetForEvent} from './TargetForEvent.js';\nimport {TimelinePanel} from './TimelinePanel.js';\nimport {TimelineSelection} from './TimelineSelection.js';\n\nconst UIStrings = {\n /**\n *@description Text that only contain a placeholder\n *@example {100ms (at 200ms)} PH1\n */\n emptyPlaceholder: '{PH1}', // eslint-disable-line rulesdir/l10n_no_locked_or_placeholder_only_phrase\n /**\n *@description Text for timestamps of items\n */\n timestamp: 'Timestamp',\n /**\n *@description Text shown next to the interaction event's ID in the detail view.\n */\n interactionID: 'ID',\n /**\n *@description Text shown next to the interaction event's input delay time in the detail view.\n */\n inputDelay: 'Input delay',\n /**\n *@description Text shown next to the interaction event's thread processing duration in the detail view.\n */\n processingDuration: 'Processing duration',\n /**\n *@description Text shown next to the interaction event's presentation delay time in the detail view.\n */\n presentationDelay: 'Presentation delay',\n /**\n *@description Text shown when the user has selected an event that represents script compiliation.\n */\n compile: 'Compile',\n /**\n *@description Text shown when the user selects an event that represents script parsing.\n */\n parse: 'Parse',\n /**\n *@description Text with two placeholders separated by a colon\n *@example {Node removed} PH1\n *@example {div#id1} PH2\n */\n sS: '{PH1}: {PH2}',\n /**\n *@description Details text used to show the amount of data collected.\n *@example {30 MB} PH1\n */\n sCollected: '{PH1} collected',\n /**\n *@description Text used to show a URL to a script and the relevant line numbers.\n *@example {https://example.com/foo.js} PH1\n *@example {2} PH2\n *@example {4} PH3\n */\n sSs: '{PH1} [{PH2}…{PH3}]',\n /**\n *@description Text used to show a URL to a script and the starting line\n * number - used when there is no end line number available.\n *@example {https://example.com/foo.js} PH1\n *@example {2} PH2\n */\n sSSquareBrackets: '{PH1} [{PH2}…]',\n /**\n *@description Text that is usually a hyperlink to more documentation\n */\n learnMore: 'Learn more',\n /**\n *@description Text referring to the status of the browser's compilation cache.\n */\n compilationCacheStatus: 'Compilation cache status',\n /**\n *@description Text referring to the size of the browser's compiliation cache.\n */\n compilationCacheSize: 'Compilation cache size',\n /**\n *@description Text in Timeline UIUtils of the Performance panel. \"Compilation\n * cache\" refers to the code cache described at\n * https://v8.dev/blog/code-caching-for-devs . This label is followed by the\n * type of code cache data used, either \"normal\" or \"full\" as described in the\n * linked article.\n */\n compilationCacheKind: 'Compilation cache kind',\n /**\n *@description Text used to inform the user that the script they are looking\n * at was loaded from the browser's cache.\n */\n scriptLoadedFromCache: 'script loaded from cache',\n /**\n *@description Text to inform the user that the script they are looking at\n * was unable to be loaded from the browser's cache.\n */\n failedToLoadScriptFromCache: 'failed to load script from cache',\n /**\n *@description Text to inform the user that the script they are looking at was not eligible to be loaded from the browser's cache.\n */\n scriptNotEligibleToBeLoadedFromCache: 'script not eligible',\n /**\n *@description Text for the total time of something\n */\n totalTime: 'Total time',\n /**\n *@description Time of a single activity, as opposed to the total time\n */\n selfTime: 'Self time',\n /**\n *@description Label in the summary view in the Performance panel for a number which indicates how much managed memory has been reclaimed by performing Garbage Collection\n */\n collected: 'Collected',\n /**\n *@description Text for a programming function\n */\n function: 'Function',\n /**\n *@description Text for referring to the ID of a timer.\n */\n timerId: 'Timer ID',\n /**\n *@description Text for referring to a timer that has timed-out and therefore is being removed.\n */\n timeout: 'Timeout',\n /**\n *@description Text used to indicate that a timer is repeating (e.g. every X seconds) rather than a one off.\n */\n repeats: 'Repeats',\n /**\n *@description Text for referring to the ID of a callback function installed by an event.\n */\n callbackId: 'Callback ID',\n /**\n *@description Text for a module, the programming concept\n */\n module: 'Module',\n /**\n *@description Label for a group of JavaScript files\n */\n script: 'Script',\n /**\n *@description Text used to tell a user that a compilation trace event was streamed.\n */\n streamed: 'Streamed',\n /**\n *@description Text to indicate if a compilation event was eager.\n */\n eagerCompile: 'Compiling all functions eagerly',\n /**\n *@description Text to refer to the URL associated with a given event.\n */\n url: 'Url',\n /**\n *@description Text to indicate to the user the size of the cache (as a filesize - e.g. 5mb).\n */\n producedCacheSize: 'Produced cache size',\n /**\n *@description Text to indicate to the user the amount of the cache (as a filesize - e.g. 5mb) that has been used.\n */\n consumedCacheSize: 'Consumed cache size',\n /**\n *@description Title for a group of cities\n */\n location: 'Location',\n /**\n *@description Text used to show a coordinate pair (e.g. (3, 2)).\n *@example {2} PH1\n *@example {2} PH2\n */\n sSCurlyBrackets: '({PH1}, {PH2})',\n /**\n *@description Text used to indicate to the user they are looking at the physical dimensions of a shape that was drawn by the browser.\n */\n dimensions: 'Dimensions',\n /**\n *@description Text used to show the user the dimensions of a shape and indicate its area (e.g. 3x2).\n *@example {2} PH1\n *@example {2} PH2\n */\n sSDimensions: '{PH1} × {PH2}',\n /**\n *@description Related node label in Timeline UIUtils of the Performance panel\n */\n layerRoot: 'Layer root',\n /**\n *@description Related node label in Timeline UIUtils of the Performance panel\n */\n ownerElement: 'Owner element',\n /**\n *@description Text used to show the user the URL of the image they are viewing.\n */\n imageUrl: 'Image URL',\n /**\n *@description Text used to show the user that the URL they are viewing is loading a CSS stylesheet.\n */\n stylesheetUrl: 'Stylesheet URL',\n /**\n *@description Text used next to a number to show the user how many elements were affected.\n */\n elementsAffected: 'Elements affected',\n /**\n *@description Text used next to a number to show the user how many nodes required the browser to update and re-layout the page.\n */\n nodesThatNeedLayout: 'Nodes that need layout',\n /**\n *@description Text used to show the amount in a subset - e.g. \"2 of 10\".\n *@example {2} PH1\n *@example {10} PH2\n */\n sOfS: '{PH1} of {PH2}',\n /**\n *@description Related node label in Timeline UIUtils of the Performance panel\n */\n layoutRoot: 'Layout root',\n /**\n *@description Text used when viewing an event that can have a custom message attached.\n */\n message: 'Message',\n /**\n *@description Text used to tell the user they are viewing an event that has a function embedded in it, which is referred to as the \"callback function\".\n */\n callbackFunction: 'Callback function',\n /**\n *@description Text used to show the relevant range of a file - e.g. \"lines 2-10\".\n */\n range: 'Range',\n /**\n *@description Text used to refer to the amount of time some event or code was given to complete within.\n */\n allottedTime: 'Allotted time',\n /**\n *@description Text used to tell a user that a particular event or function was automatically run by a timeout.\n */\n invokedByTimeout: 'Invoked by timeout',\n /**\n *@description Text that refers to some types\n */\n type: 'Type',\n /**\n *@description Text for the size of something\n */\n size: 'Size',\n /**\n *@description Text for the details of something\n */\n details: 'Details',\n /**\n *@description Title in Timeline for Cumulative Layout Shifts\n */\n cumulativeLayoutShifts: 'Cumulative Layout Shifts',\n /**\n *@description Text for the link to the evolved CLS website\n */\n evolvedClsLink: 'evolved',\n /**\n *@description Warning in Timeline that CLS can cause a poor user experience. It contains a link to inform developers about the recent changes to how CLS is measured. The new CLS metric is said to have evolved from the previous version.\n *@example {Link to web.dev/metrics} PH1\n *@example {Link to web.dev/evolving-cls which will always have the text 'evolved'} PH2\n */\n sCLSInformation: '{PH1} can result in poor user experiences. It has recently {PH2}.',\n /**\n *@description Text to indicate an item is a warning\n */\n warning: 'Warning',\n /**\n *@description Title for the Timeline CLS Score\n */\n score: 'Score',\n /**\n *@description Text in Timeline for the cumulative CLS score\n */\n cumulativeScore: 'Cumulative score',\n /**\n *@description Text in Timeline for the current CLS score\n */\n currentClusterScore: 'Current cluster score',\n /**\n *@description Text in Timeline for the current CLS cluster\n */\n currentClusterId: 'Current cluster ID',\n /**\n *@description Text in Timeline for whether input happened recently\n */\n hadRecentInput: 'Had recent input',\n /**\n *@description Text in Timeline indicating that input has happened recently\n */\n yes: 'Yes',\n /**\n *@description Text in Timeline indicating that input has not happened recently\n */\n no: 'No',\n /**\n *@description Label for Cumulative Layout records, indicating where they moved from\n */\n movedFrom: 'Moved from',\n /**\n *@description Label for Cumulative Layout records, indicating where they moved to\n */\n movedTo: 'Moved to',\n /**\n *@description Text that indicates a particular HTML element or node is related to what the user is viewing.\n */\n relatedNode: 'Related node',\n /**\n *@description Text for previewing items\n */\n preview: 'Preview',\n /**\n *@description Text used to refer to the total time summed up across multiple events.\n */\n aggregatedTime: 'Aggregated time',\n /**\n *@description Text for the duration of something\n */\n duration: 'Duration',\n /**\n *@description Text for the stack trace of the initiator of something. The Initiator is the event or factor that directly triggered or precipitated a subsequent action.\n */\n initiatorStackTrace: 'Initiator stack trace',\n /**\n *@description Text for the event initiated by another one\n */\n initiatedBy: 'Initiated by',\n /**\n *@description Text for the event that is an initiator for another one\n */\n initiatorFor: 'Initiator for',\n /**\n *@description Text for the underlying data behing a specific flamechart selection. Trace events are the browser instrumentation that are emitted as JSON objects.\n */\n traceEvent: 'Trace event',\n /**\n *@description Call site stack label in Timeline UIUtils of the Performance panel\n */\n timerInstalled: 'Timer installed',\n /**\n *@description Call site stack label in Timeline UIUtils of the Performance panel\n */\n animationFrameRequested: 'Animation frame requested',\n /**\n *@description Call site stack label in Timeline UIUtils of the Performance panel\n */\n idleCallbackRequested: 'Idle callback requested',\n /**\n *@description Stack label in Timeline UIUtils of the Performance panel\n */\n recalculationForced: 'Recalculation forced',\n /**\n *@description Call site stack label in Timeline UIUtils of the Performance panel\n */\n firstLayoutInvalidation: 'First layout invalidation',\n /**\n *@description Stack label in Timeline UIUtils of the Performance panel\n */\n layoutForced: 'Layout forced',\n /**\n *@description Label in front of CSS property (eg `opacity`) being animated or a CSS animation name (eg `layer-4-fade-in-out`)\n */\n animating: 'Animating',\n /**\n *@description Label in front of reasons why a CSS animation wasn't composited (aka hardware accelerated)\n */\n compositingFailed: 'Compositing failed',\n /**\n * @description [ICU Syntax] Descriptive reason for why a user-provided animation failed to be optimized by the browser due to the animated CSS property not being supported on the compositor. Shown in a table with a list of other potential failure reasons.\n * @example {height, width} properties\n */\n unsupportedCSSProperty: `{propertyCount, plural,\n =1 {Unsupported CSS property: {properties}}\n other {Unsupported CSS properties: {properties}}\n }`,\n /** Descriptive reason for why a user-provided animation failed to be optimized by the browser due to a `transform` property being dependent on the size of the element itself. Shown in a table with a list of other potential failure reasons. */\n transformDependsBoxSize: 'Transform-related property depends on box size',\n /** Descriptive reason for why a user-provided animation failed to be optimized by the browser due to a `filter` property possibly moving pixels. Shown in a table with a list of other potential failure reasons. */\n filterMayMovePixels: 'Filter-related property may move pixels',\n /** Descriptive reason for why a user-provided animation failed to be optimized by the browser due to an effect having a composite mode which is not `replace`. Shown in a table with a list of other potential failure reasons. */\n nonReplaceCompositeMode: 'Effect has composite mode other than \"replace\"',\n /** Descriptive reason for why a user-provided animation failed to be optimized by the browser due to another animation on the same target being incompatible. Shown in a table with a list of other potential failure reasons. */\n incompatibleAnimations: 'Target has another animation which is incompatible',\n /** Descriptive reason for why a user-provided animation failed to be optimized by the browser due to an effect having unsupported timing parameters. Shown in a table with a list of other potential failure reasons. */\n unsupportedTimingParameters: 'Effect has unsupported timing parameters',\n\n /**\n *@description Text for the execution stack trace\n */\n stackTrace: 'Stack trace',\n /**\n *@description Text used to show any invalidations for a particular event that caused the browser to have to do more work to update the page.\n * @example {2} PH1\n */\n invalidations: 'Invalidations ({PH1} total)',\n /**\n * @description Text in Timeline UIUtils of the Performance panel. Phrase is followed by a number of milliseconds.\n * Some events or tasks might have been only started, but have not ended yet. Such events or tasks are considered\n * \"pending\".\n */\n pendingFor: 'Pending for',\n /**\n *@description Noun label for a stack trace which indicates the first time some condition was invalidated.\n */\n firstInvalidated: 'First invalidated',\n /**\n *@description Title of the paint profiler, old name of the performance pane\n */\n paintProfiler: 'Paint profiler',\n /**\n *@description Text in Timeline Flame Chart View of the Performance panel\n *@example {Frame} PH1\n *@example {10ms} PH2\n */\n sAtS: '{PH1} at {PH2}',\n /**\n *@description Text used next to a time to indicate that the particular event took that much time itself. In context this might look like \"3ms blink.console (self)\"\n *@example {blink.console} PH1\n */\n sSelf: '{PH1} (self)',\n /**\n *@description Text used next to a time to indicate that the event's children took that much time. In context this might look like \"3ms blink.console (children)\"\n *@example {blink.console} PH1\n */\n sChildren: '{PH1} (children)',\n /**\n *@description Text used to show the user how much time the browser spent on rendering (drawing the page onto the screen).\n */\n timeSpentInRendering: 'Time spent in rendering',\n /**\n *@description Text for a rendering frame\n */\n frame: 'Frame',\n /**\n *@description Text used to refer to the duration of an event at a given offset - e.g. \"2ms at 10ms\" which can be read as \"2ms starting after 10ms\".\n *@example {10ms} PH1\n *@example {10ms} PH2\n */\n sAtSParentheses: '{PH1} (at {PH2})',\n /**\n *@description Text of a DOM element in Timeline UIUtils of the Performance panel\n */\n UnknownNode: '[ unknown node ]',\n /**\n *@description Text used to refer to a particular element and the file it was referred to in.\n *@example {node} PH1\n *@example {app.js} PH2\n */\n invalidationWithCallFrame: '{PH1} at {PH2}',\n /**\n *@description Text indicating that something is outside of the Performace Panel Timeline Minimap range\n */\n outsideBreadcrumbRange: '(outside of the breadcrumb range)',\n /**\n *@description Text indicating that something is hidden from the Performace Panel Timeline\n */\n entryIsHidden: '(entry is hidden)',\n /**\n * @description Title of a row in the details view for a `Recalculate Styles` event that contains more info about selector stats tracing.\n */\n selectorStatsTitle: 'Selector stats',\n /**\n * @description Info text that explains to the user how to enable selector stats tracing.\n * @example {Setting Name} PH1\n */\n sSelectorStatsInfo: 'Select \"{PH1}\" to collect detailed CSS selector matching statistics.',\n /**\n * @description Label for a description text of a metric.\n */\n description: 'Description',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/TimelineUIUtils.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nlet eventDispatchDesciptors: EventDispatchTypeDescriptor[];\n\nlet colorGenerator: Common.Color.Generator;\n\ntype LinkifyLocationOptions = {\n scriptId: Protocol.Runtime.ScriptId|null,\n url: string,\n lineNumber: number,\n target: SDK.Target.Target|null,\n linkifier: LegacyComponents.Linkifier.Linkifier,\n isFreshRecording?: boolean,\n columnNumber?: number,\n};\n\nexport class TimelineUIUtils {\n static frameDisplayName(frame: Protocol.Runtime.CallFrame): string {\n if (!TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.isNativeRuntimeFrame(frame)) {\n return UI.UIUtils.beautifyFunctionName(frame.functionName);\n }\n const nativeGroup = TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.nativeGroup(frame.functionName);\n switch (nativeGroup) {\n case TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.NativeGroups.COMPILE:\n return i18nString(UIStrings.compile);\n case TimelineModel.TimelineJSProfile.TimelineJSProfileProcessor.NativeGroups.PARSE:\n return i18nString(UIStrings.parse);\n }\n return frame.functionName;\n }\n\n static testContentMatching(\n traceEvent: Trace.Types.Events.Event, regExp: RegExp, parsedTrace?: Trace.Handlers.Types.ParsedTrace): boolean {\n const title = TimelineUIUtils.eventStyle(traceEvent).title;\n const tokens = [title];\n\n if (Trace.Types.Events.isProfileCall(traceEvent)) {\n // In the future this case will not be possible - wherever we call this\n // function we will be able to pass in the data from the new engine. But\n // currently this is called in a variety of places including from the\n // legacy model which does not have a reference to the new engine's data.\n // So if we are missing the data, we just fallback to the name from the\n // callFrame.\n if (!parsedTrace || !parsedTrace.Samples) {\n tokens.push(traceEvent.callFrame.functionName);\n } else {\n tokens.push(Trace.Handlers.ModelHandlers.Samples.getProfileCallFunctionName(parsedTrace.Samples, traceEvent));\n }\n }\n if (parsedTrace) {\n const url = Trace.Extras.URLForEntry.get(parsedTrace, traceEvent);\n if (url) {\n tokens.push(url);\n }\n }\n // This works for both legacy and new engine events.\n appendObjectProperties(traceEvent.args as ContentObject, 2);\n const result = tokens.join('|').match(regExp);\n return result ? result.length > 0 : false;\n\n interface ContentObject {\n [x: string]: number|string|ContentObject;\n }\n function appendObjectProperties(object: ContentObject, depth: number): void {\n if (!depth) {\n return;\n }\n for (const key in object) {\n const value = object[key];\n if (typeof value === 'string') {\n tokens.push(value);\n } else if (typeof value === 'number') {\n tokens.push(String(value));\n } else if (typeof value === 'object' && value !== null) {\n appendObjectProperties(value, depth - 1);\n }\n }\n }\n }\n\n static eventStyle(event: Trace.Types.Events.Event): TimelineComponents.EntryStyles.TimelineRecordStyle {\n if (Trace.Types.Events.isProfileCall(event) && event.callFrame.functionName === '(idle)') {\n return new TimelineComponents.EntryStyles.TimelineRecordStyle(\n event.name, TimelineComponents.EntryStyles.getCategoryStyles().idle);\n }\n\n if (event.cat === Trace.Types.Events.Categories.Console || event.cat === Trace.Types.Events.Categories.UserTiming) {\n return new TimelineComponents.EntryStyles.TimelineRecordStyle(\n event.name, TimelineComponents.EntryStyles.getCategoryStyles()['scripting']);\n }\n\n return TimelineComponents.EntryStyles.getEventStyle(event.name as Trace.Types.Events.Name) ??\n new TimelineComponents.EntryStyles.TimelineRecordStyle(\n event.name, TimelineComponents.EntryStyles.getCategoryStyles().other);\n }\n\n static eventColor(event: Trace.Types.Events.Event): string {\n if (Trace.Types.Events.isProfileCall(event)) {\n const frame = event.callFrame;\n if (TimelineUIUtils.isUserFrame(frame)) {\n return TimelineUIUtils.colorForId(frame.url);\n }\n }\n if (Trace.Types.Extensions.isSyntheticExtensionEntry(event)) {\n return Extensions.ExtensionUI.extensionEntryColor(event);\n }\n let parsedColor = TimelineUIUtils.eventStyle(event).category.getComputedColorValue();\n // This event is considered idle time but still rendered as a scripting event here\n // to connect the StreamingCompileScriptParsing events it belongs to.\n if (event.name === Trace.Types.Events.Name.STREAMING_COMPILE_SCRIPT_WAITING) {\n parsedColor = TimelineComponents.EntryStyles.getCategoryStyles().scripting.getComputedColorValue();\n if (!parsedColor) {\n throw new Error('Unable to parse color from getCategoryStyles().scripting.color');\n }\n }\n return parsedColor;\n }\n\n static eventTitle(event: Trace.Types.Events.Event): string {\n // Profile call events do not have a args.data property, thus, we\n // need to check for profile calls in the beginning of this\n // function.\n if (Trace.Types.Events.isProfileCall(event)) {\n const maybeResolvedName = SourceMapsResolver.resolvedNodeNameForEntry(event);\n const displayName = maybeResolvedName || TimelineUIUtils.frameDisplayName(event.callFrame);\n return displayName;\n }\n if (event.name === 'EventTiming' && Trace.Types.Events.isSyntheticInteraction(event)) {\n // TODO(crbug.com/365047728): replace this entire method with this call.\n return TimelineComponents.EntryName.nameForEntry(event);\n }\n const title = TimelineUIUtils.eventStyle(event).title;\n if (Trace.Helpers.Trace.eventHasCategory(event, Trace.Types.Events.Categories.Console)) {\n return title;\n }\n if (Trace.Types.Events.isTimeStamp(event)) {\n return i18nString(UIStrings.sS, {PH1: title, PH2: event.args.data.message});\n }\n if (Trace.Types.Events.isAnimation(event) && event.args.data.name) {\n return i18nString(UIStrings.sS, {PH1: title, PH2: event.args.data.name});\n }\n if (Trace.Types.Events.isDispatch(event)) {\n return i18nString(UIStrings.sS, {PH1: title, PH2: event.args.data.type});\n }\n return title;\n }\n\n static isUserFrame(frame: Protocol.Runtime.CallFrame): boolean {\n return frame.scriptId !== '0' && !(frame.url && frame.url.startsWith('native '));\n }\n\n static async buildDetailsTextForTraceEvent(\n event: Trace.Types.Events.Event, parsedTrace: Trace.Handlers.Types.ParsedTrace): Promise {\n let detailsText;\n\n // TODO(40287735): update this code with type-safe data checks.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const unsafeEventArgs = event.args as Record;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const unsafeEventData = event.args?.data as Record;\n\n switch (event.name) {\n case Trace.Types.Events.Name.GC:\n case Trace.Types.Events.Name.MAJOR_GC:\n case Trace.Types.Events.Name.MINOR_GC: {\n const delta = unsafeEventArgs['usedHeapSizeBefore'] - unsafeEventArgs['usedHeapSizeAfter'];\n detailsText = i18nString(UIStrings.sCollected, {PH1: Platform.NumberUtilities.bytesToString(delta)});\n break;\n }\n case Trace.Types.Events.Name.FUNCTION_CALL: {\n const {lineNumber, columnNumber} = Trace.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event);\n if (lineNumber !== undefined && columnNumber !== undefined) {\n detailsText = unsafeEventData.url + ':' + (lineNumber + 1) + ':' + (columnNumber + 1);\n }\n break;\n }\n case Trace.Types.Events.Name.EVENT_DISPATCH:\n detailsText = unsafeEventData ? unsafeEventData['type'] : null;\n break;\n case Trace.Types.Events.Name.PAINT: {\n const width = TimelineUIUtils.quadWidth(unsafeEventData.clip);\n const height = TimelineUIUtils.quadHeight(unsafeEventData.clip);\n if (width && height) {\n detailsText = i18nString(UIStrings.sSDimensions, {PH1: width, PH2: height});\n }\n break;\n }\n case Trace.Types.Events.Name.PARSE_HTML: {\n const startLine = unsafeEventArgs['beginData']['startLine'];\n const endLine = unsafeEventArgs['endData'] && unsafeEventArgs['endData']['endLine'];\n const url = Bindings.ResourceUtils.displayNameForURL(unsafeEventArgs['beginData']['url']);\n if (endLine >= 0) {\n detailsText = i18nString(UIStrings.sSs, {PH1: url, PH2: startLine + 1, PH3: endLine + 1});\n } else {\n detailsText = i18nString(UIStrings.sSSquareBrackets, {PH1: url, PH2: startLine + 1});\n }\n break;\n }\n case Trace.Types.Events.Name.COMPILE_MODULE:\n case Trace.Types.Events.Name.CACHE_MODULE:\n detailsText = Bindings.ResourceUtils.displayNameForURL(unsafeEventArgs['fileName']);\n break;\n case Trace.Types.Events.Name.COMPILE_SCRIPT:\n case Trace.Types.Events.Name.CACHE_SCRIPT:\n case Trace.Types.Events.Name.EVALUATE_SCRIPT: {\n const {lineNumber} = Trace.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event);\n const url = unsafeEventData && unsafeEventData['url'];\n if (url) {\n detailsText = Bindings.ResourceUtils.displayNameForURL(url) + ':' + ((lineNumber || 0) + 1);\n }\n break;\n }\n case Trace.Types.Events.Name.WASM_COMPILED_MODULE:\n case Trace.Types.Events.Name.WASM_MODULE_CACHE_HIT: {\n const url = unsafeEventArgs['url'];\n if (url) {\n detailsText = Bindings.ResourceUtils.displayNameForURL(url);\n }\n break;\n }\n\n case Trace.Types.Events.Name.STREAMING_COMPILE_SCRIPT:\n case Trace.Types.Events.Name.BACKGROUND_DESERIALIZE:\n case Trace.Types.Events.Name.XHR_READY_STATE_CHANGED:\n case Trace.Types.Events.Name.XHR_LOAD: {\n const url = unsafeEventData['url'];\n if (url) {\n detailsText = Bindings.ResourceUtils.displayNameForURL(url);\n }\n break;\n }\n case Trace.Types.Events.Name.TIME_STAMP:\n detailsText = unsafeEventData['message'];\n break;\n\n case Trace.Types.Events.Name.WEB_SOCKET_CREATE:\n case Trace.Types.Events.Name.WEB_SOCKET_SEND_HANDSHAKE_REQUEST:\n case Trace.Types.Events.Name.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST:\n case Trace.Types.Events.Name.WEB_SOCKET_SEND:\n case Trace.Types.Events.Name.WEB_SOCKET_RECEIVE:\n case Trace.Types.Events.Name.WEB_SOCKET_DESTROY:\n case Trace.Types.Events.Name.RESOURCE_WILL_SEND_REQUEST:\n case Trace.Types.Events.Name.RESOURCE_SEND_REQUEST:\n case Trace.Types.Events.Name.RESOURCE_RECEIVE_DATA:\n case Trace.Types.Events.Name.RESOURCE_RECEIVE_RESPONSE:\n case Trace.Types.Events.Name.RESOURCE_FINISH:\n case Trace.Types.Events.Name.PAINT_IMAGE:\n case Trace.Types.Events.Name.DECODE_IMAGE:\n case Trace.Types.Events.Name.DECODE_LAZY_PIXEL_REF: {\n const url = Trace.Extras.URLForEntry.get(parsedTrace, event);\n if (url) {\n detailsText = Bindings.ResourceUtils.displayNameForURL(url);\n }\n break;\n }\n\n case Trace.Types.Events.Name.EMBEDDER_CALLBACK:\n detailsText = unsafeEventData['callbackName'];\n break;\n\n case Trace.Types.Events.Name.ASYNC_TASK:\n detailsText = unsafeEventData ? unsafeEventData['name'] : null;\n break;\n\n default:\n if (Trace.Helpers.Trace.eventHasCategory(event, Trace.Types.Events.Categories.Console)) {\n detailsText = null;\n } else {\n detailsText = linkifyTopCallFrameAsText();\n }\n break;\n }\n\n return detailsText;\n\n function linkifyTopCallFrameAsText(): string|null {\n const frame = Trace.Helpers.Trace.getZeroIndexedStackTraceForEvent(event)?.at(0) ?? null;\n if (!frame) {\n return null;\n }\n\n return frame.url + ':' + (frame.lineNumber + 1) + ':' + (frame.columnNumber + 1);\n }\n }\n\n static async buildDetailsNodeForTraceEvent(\n event: Trace.Types.Events.Event, target: SDK.Target.Target|null, linkifier: LegacyComponents.Linkifier.Linkifier,\n isFreshRecording = false, parsedTrace: Trace.Handlers.Types.ParsedTrace): Promise {\n let details: HTMLElement|HTMLSpanElement|(Element | null)|Text|null = null;\n let detailsText;\n // TODO(40287735): update this code with type-safe data checks.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const unsafeEventArgs = event.args as Record;\n // TODO(40287735): update this code with type-safe data checks.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const unsafeEventData = event.args?.data as Record;\n\n switch (event.name) {\n case Trace.Types.Events.Name.GC:\n case Trace.Types.Events.Name.MAJOR_GC:\n case Trace.Types.Events.Name.MINOR_GC:\n case Trace.Types.Events.Name.EVENT_DISPATCH:\n case Trace.Types.Events.Name.PAINT:\n case Trace.Types.Events.Name.ANIMATION:\n case Trace.Types.Events.Name.EMBEDDER_CALLBACK:\n case Trace.Types.Events.Name.PARSE_HTML:\n case Trace.Types.Events.Name.WASM_STREAM_FROM_RESPONSE_CALLBACK:\n case Trace.Types.Events.Name.WASM_COMPILED_MODULE:\n case Trace.Types.Events.Name.WASM_MODULE_CACHE_HIT:\n case Trace.Types.Events.Name.WASM_CACHED_MODULE:\n case Trace.Types.Events.Name.WASM_MODULE_CACHE_INVALID:\n case Trace.Types.Events.Name.WEB_SOCKET_CREATE:\n case Trace.Types.Events.Name.WEB_SOCKET_SEND_HANDSHAKE_REQUEST:\n case Trace.Types.Events.Name.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST:\n case Trace.Types.Events.Name.WEB_SOCKET_SEND:\n case Trace.Types.Events.Name.WEB_SOCKET_RECEIVE:\n case Trace.Types.Events.Name.WEB_SOCKET_DESTROY: {\n detailsText = await TimelineUIUtils.buildDetailsTextForTraceEvent(event, parsedTrace);\n break;\n }\n\n case Trace.Types.Events.Name.PAINT_IMAGE:\n case Trace.Types.Events.Name.DECODE_IMAGE:\n case Trace.Types.Events.Name.DECODE_LAZY_PIXEL_REF:\n case Trace.Types.Events.Name.XHR_READY_STATE_CHANGED:\n case Trace.Types.Events.Name.XHR_LOAD:\n case Trace.Types.Events.Name.RESOURCE_WILL_SEND_REQUEST:\n case Trace.Types.Events.Name.RESOURCE_SEND_REQUEST:\n case Trace.Types.Events.Name.RESOURCE_RECEIVE_DATA:\n case Trace.Types.Events.Name.RESOURCE_RECEIVE_RESPONSE:\n case Trace.Types.Events.Name.RESOURCE_FINISH: {\n const url = Trace.Extras.URLForEntry.get(parsedTrace, event);\n if (url) {\n const options = {\n tabStop: true,\n showColumnNumber: false,\n inlineFrameIndex: 0,\n };\n details = LegacyComponents.Linkifier.Linkifier.linkifyURL(url, options);\n }\n break;\n }\n\n case Trace.Types.Events.Name.FUNCTION_CALL: {\n details = document.createElement('span');\n\n // FunctionCall events have an args.data that could be a CallFrame, if all the details are present, so we check for that.\n if (Trace.Types.Events.isFunctionCall(event) && event.args.data &&\n Trace.Types.Events.objectIsCallFrame(event.args.data)) {\n UI.UIUtils.createTextChild(\n details,\n TimelineUIUtils.frameDisplayName(\n {...event.args.data, scriptId: String(event.args.data.scriptId) as Protocol.Runtime.ScriptId}));\n }\n const {lineNumber, columnNumber} = Trace.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event);\n const location = this.linkifyLocation({\n scriptId: unsafeEventData['scriptId'],\n url: unsafeEventData['url'],\n lineNumber: lineNumber || 0,\n columnNumber,\n target,\n isFreshRecording,\n linkifier,\n });\n if (location) {\n UI.UIUtils.createTextChild(details, ' @ ');\n details.appendChild(location);\n }\n break;\n }\n\n case Trace.Types.Events.Name.COMPILE_MODULE:\n case Trace.Types.Events.Name.CACHE_MODULE: {\n details = this.linkifyLocation({\n scriptId: null,\n url: unsafeEventArgs['fileName'],\n lineNumber: 0,\n columnNumber: 0,\n target,\n isFreshRecording,\n linkifier,\n });\n break;\n }\n\n case Trace.Types.Events.Name.COMPILE_SCRIPT:\n case Trace.Types.Events.Name.CACHE_SCRIPT:\n case Trace.Types.Events.Name.EVALUATE_SCRIPT: {\n const url = unsafeEventData['url'];\n if (url) {\n const {lineNumber} = Trace.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event);\n details = this.linkifyLocation({\n scriptId: null,\n url,\n lineNumber: lineNumber || 0,\n columnNumber: 0,\n target,\n isFreshRecording,\n linkifier,\n });\n }\n break;\n }\n\n case Trace.Types.Events.Name.BACKGROUND_DESERIALIZE:\n case Trace.Types.Events.Name.STREAMING_COMPILE_SCRIPT: {\n const url = unsafeEventData['url'];\n if (url) {\n details = this.linkifyLocation(\n {scriptId: null, url, lineNumber: 0, columnNumber: 0, target, isFreshRecording, linkifier});\n }\n break;\n }\n case Trace.Types.Events.Name.PROFILE_CALL: {\n details = document.createElement('span');\n // This check is only added for convenience with the type checker.\n if (!Trace.Types.Events.isProfileCall(event)) {\n break;\n }\n const maybeResolvedName = SourceMapsResolver.resolvedNodeNameForEntry(event);\n const functionName = maybeResolvedName || TimelineUIUtils.frameDisplayName(event.callFrame);\n UI.UIUtils.createTextChild(details, functionName);\n const location = this.linkifyLocation({\n scriptId: event.callFrame['scriptId'],\n url: event.callFrame['url'],\n lineNumber: event.callFrame['lineNumber'],\n columnNumber: event.callFrame['columnNumber'],\n target,\n isFreshRecording,\n linkifier,\n });\n if (location) {\n UI.UIUtils.createTextChild(details, ' @ ');\n details.appendChild(location);\n }\n break;\n }\n\n default: {\n /**\n * Some events have a stack trace which is extracted by default at @see TimelineUIUtils.generateCauses\n * thus, we prevent extracting the stack trace again here.\n */\n if (Trace.Helpers.Trace.eventHasCategory(event, Trace.Types.Events.Categories.Console) ||\n Trace.Types.Events.isUserTiming(event) || Trace.Types.Extensions.isSyntheticExtensionEntry(event)) {\n detailsText = null;\n } else {\n details = this.linkifyTopCallFrame(event, target, linkifier, isFreshRecording) ?? null;\n }\n break;\n }\n }\n\n if (!details && detailsText) {\n details = document.createTextNode(detailsText);\n }\n return details;\n }\n\n static linkifyLocation(linkifyOptions: LinkifyLocationOptions): Element|null {\n const {scriptId, url, lineNumber, columnNumber, isFreshRecording, linkifier, target} = linkifyOptions;\n const options = {\n lineNumber,\n columnNumber,\n showColumnNumber: true,\n inlineFrameIndex: 0,\n className: 'timeline-details',\n tabStop: true,\n };\n if (isFreshRecording) {\n return linkifier.linkifyScriptLocation(\n target, scriptId, url as Platform.DevToolsPath.UrlString, lineNumber, options);\n }\n return LegacyComponents.Linkifier.Linkifier.linkifyURL(url as Platform.DevToolsPath.UrlString, options);\n }\n\n static linkifyTopCallFrame(\n event: Trace.Types.Events.Event, target: SDK.Target.Target|null, linkifier: LegacyComponents.Linkifier.Linkifier,\n isFreshRecording = false): Element|null {\n let frame = Trace.Helpers.Trace.getZeroIndexedStackTraceForEvent(event)?.[0];\n if (Trace.Types.Events.isProfileCall(event)) {\n frame = event.callFrame;\n }\n if (!frame) {\n return null;\n }\n const options = {\n className: 'timeline-details',\n tabStop: true,\n inlineFrameIndex: 0,\n showColumnNumber: true,\n columnNumber: frame.columnNumber,\n lineNumber: frame.lineNumber,\n };\n if (isFreshRecording) {\n return linkifier.maybeLinkifyConsoleCallFrame(target, frame, {showColumnNumber: true, inlineFrameIndex: 0});\n }\n return LegacyComponents.Linkifier.Linkifier.linkifyURL(frame.url as Platform.DevToolsPath.UrlString, options);\n }\n\n static buildDetailsNodeForMarkerEvents(event: Trace.Types.Events.MarkerEvent): HTMLElement {\n let link = 'https://web.dev/user-centric-performance-metrics/';\n let name = 'page performance metrics';\n switch (event.name) {\n case Trace.Types.Events.Name.MARK_LCP_CANDIDATE:\n link = 'https://web.dev/lcp/';\n name = 'largest contentful paint';\n break;\n case Trace.Types.Events.Name.MARK_FCP:\n link = 'https://web.dev/first-contentful-paint/';\n name = 'first contentful paint';\n break;\n default:\n break;\n }\n\n const html = UI.Fragment.html`
${\n UI.XLink.XLink.create(\n link, i18nString(UIStrings.learnMore), undefined, undefined, 'learn-more')} about ${name}.
`;\n return html as HTMLElement;\n }\n\n static buildConsumeCacheDetails(\n eventData: {\n consumedCacheSize?: number,\n cacheRejected?: boolean,\n cacheKind?: string,\n },\n contentHelper: TimelineDetailsContentHelper): void {\n if (typeof eventData.consumedCacheSize === 'number') {\n contentHelper.appendTextRow(\n i18nString(UIStrings.compilationCacheStatus), i18nString(UIStrings.scriptLoadedFromCache));\n contentHelper.appendTextRow(\n i18nString(UIStrings.compilationCacheSize),\n Platform.NumberUtilities.bytesToString(eventData.consumedCacheSize));\n const cacheKind = eventData.cacheKind;\n if (cacheKind) {\n contentHelper.appendTextRow(i18nString(UIStrings.compilationCacheKind), cacheKind);\n }\n } else if ('cacheRejected' in eventData && eventData['cacheRejected']) {\n // Version mismatch or similar.\n contentHelper.appendTextRow(\n i18nString(UIStrings.compilationCacheStatus), i18nString(UIStrings.failedToLoadScriptFromCache));\n } else {\n contentHelper.appendTextRow(\n i18nString(UIStrings.compilationCacheStatus), i18nString(UIStrings.scriptNotEligibleToBeLoadedFromCache));\n }\n }\n\n static async buildTraceEventDetails(\n parsedTrace: Trace.Handlers.Types.ParsedTrace,\n event: Trace.Types.Events.Event,\n linkifier: LegacyComponents.Linkifier.Linkifier,\n detailed: boolean,\n ): Promise {\n const maybeTarget = targetForEvent(parsedTrace, event);\n const {duration} = Trace.Helpers.Timing.eventTimingsMilliSeconds(event);\n const selfTime = getEventSelfTime(event, parsedTrace);\n const relatedNodesMap = await Trace.Extras.FetchNodes.extractRelatedDOMNodesFromEvent(\n parsedTrace,\n event,\n );\n\n if (maybeTarget) {\n // @ts-ignore TODO(crbug.com/1011811): Remove symbol usage.\n if (typeof event[previewElementSymbol] === 'undefined') {\n let previewElement: (Element|null)|null = null;\n const url = Trace.Extras.URLForEntry.get(parsedTrace, event);\n if (url) {\n previewElement = await LegacyComponents.ImagePreview.ImagePreview.build(maybeTarget, url, false, {\n imageAltText: LegacyComponents.ImagePreview.ImagePreview.defaultAltTextForImageURL(url),\n precomputedFeatures: undefined,\n align: LegacyComponents.ImagePreview.Align.START,\n });\n } else if (Trace.Types.Events.isPaint(event)) {\n previewElement = await TimelineUIUtils.buildPicturePreviewContent(parsedTrace, event, maybeTarget);\n }\n // @ts-ignore TODO(crbug.com/1011811): Remove symbol usage.\n event[previewElementSymbol] = previewElement;\n }\n }\n\n if (Trace.Types.Events.isSyntheticLayoutShift(event)) {\n // Ensure that there are no pie charts or extended info for layout shifts.\n detailed = false;\n }\n\n // This message may vary per event.name;\n let relatedNodeLabel;\n\n const contentHelper = new TimelineDetailsContentHelper(targetForEvent(parsedTrace, event), linkifier);\n\n const defaultColorForEvent = this.eventColor(event);\n const isMarker = parsedTrace && isMarkerEvent(parsedTrace, event);\n const color = isMarker ? TimelineUIUtils.markerStyleForEvent(event).color : defaultColorForEvent;\n\n contentHelper.addSection(TimelineUIUtils.eventTitle(event), color);\n\n // TODO: as part of the removal of the old engine, produce a typesafe way\n // to look up args and data for events.\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const unsafeEventArgs = event.args as Record;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const unsafeEventData = event.args?.data as Record;\n const initiator = parsedTrace.Initiators.eventToInitiator.get(event) ?? null;\n const initiatorFor = parsedTrace.Initiators.initiatorToEvents.get(event) ?? null;\n\n let url: Platform.DevToolsPath.UrlString|null = null;\n\n if (parsedTrace) {\n const warnings = TimelineComponents.DetailsView.buildWarningElementsForEvent(event, parsedTrace);\n for (const warning of warnings) {\n contentHelper.appendElementRow(i18nString(UIStrings.warning), warning, true);\n }\n }\n\n // Add timestamp to user timings.\n if (Trace.Helpers.Trace.eventHasCategory(event, Trace.Types.Events.Categories.UserTiming)) {\n const adjustedEventTimeStamp = timeStampForEventAdjustedForClosestNavigationIfPossible(\n event,\n parsedTrace,\n );\n contentHelper.appendTextRow(\n i18nString(UIStrings.timestamp), i18n.TimeUtilities.preciseMillisToString(adjustedEventTimeStamp, 1));\n }\n\n // Only show total time and self time for events with non-zero durations.\n if (detailed && !Number.isNaN(duration || 0) && duration !== 0) {\n contentHelper.appendTextRow(\n i18nString(UIStrings.totalTime), i18n.TimeUtilities.millisToString(duration || 0, true));\n contentHelper.appendTextRow(i18nString(UIStrings.selfTime), i18n.TimeUtilities.millisToString(selfTime, true));\n }\n\n if (Trace.Types.Events.isPerformanceMark(event) && event.args.data?.detail) {\n const detailContainer = TimelineUIUtils.renderObjectJson(JSON.parse(event.args.data?.detail));\n contentHelper.appendElementRow(i18nString(UIStrings.details), detailContainer);\n }\n if (Trace.Types.Events.isSyntheticUserTiming(event) && event.args?.data?.beginEvent.args.detail) {\n const detailContainer = TimelineUIUtils.renderObjectJson(JSON.parse(event.args?.data?.beginEvent.args.detail));\n contentHelper.appendElementRow(i18nString(UIStrings.details), detailContainer);\n }\n\n if (parsedTrace.Meta.traceIsGeneric) {\n TimelineUIUtils.renderEventJson(event, contentHelper);\n return contentHelper.fragment;\n }\n\n if (Trace.Types.Events.isV8Compile(event)) {\n url = event.args.data?.url as Platform.DevToolsPath.UrlString;\n if (url) {\n const {lineNumber, columnNumber} = Trace.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event);\n contentHelper.appendLocationRow(i18nString(UIStrings.script), url, lineNumber || 0, columnNumber);\n }\n const isEager = Boolean(event.args.data?.eager);\n if (isEager) {\n contentHelper.appendTextRow(i18nString(UIStrings.eagerCompile), true);\n }\n\n const isStreamed = Boolean(event.args.data?.streamed);\n contentHelper.appendTextRow(\n i18nString(UIStrings.streamed),\n isStreamed + (isStreamed ? '' : `: ${event.args.data?.notStreamedReason || ''}`));\n if (event.args.data) {\n TimelineUIUtils.buildConsumeCacheDetails(event.args.data, contentHelper);\n }\n }\n\n if (Trace.Types.Extensions.isSyntheticExtensionEntry(event)) {\n for (const [key, value] of event.args.properties || []) {\n contentHelper.appendTextRow(key, value);\n }\n }\n\n if (Trace.Types.Events.isSyntheticServerTiming(event) && event.args.data.desc) {\n contentHelper.appendTextRow(i18nString(UIStrings.description), event.args.data.desc);\n }\n\n const isFreshRecording = Boolean(parsedTrace && Tracker.instance().recordingIsFresh(parsedTrace));\n\n switch (event.name) {\n case Trace.Types.Events.Name.GC:\n case Trace.Types.Events.Name.MAJOR_GC:\n case Trace.Types.Events.Name.MINOR_GC: {\n const delta = unsafeEventArgs['usedHeapSizeBefore'] - unsafeEventArgs['usedHeapSizeAfter'];\n contentHelper.appendTextRow(i18nString(UIStrings.collected), Platform.NumberUtilities.bytesToString(delta));\n break;\n }\n\n case Trace.Types.Events.Name.PROFILE_CALL:\n case Trace.Types.Events.Name.FUNCTION_CALL: {\n const detailsNode = await TimelineUIUtils.buildDetailsNodeForTraceEvent(\n event, targetForEvent(parsedTrace, event), linkifier, isFreshRecording, parsedTrace);\n if (detailsNode) {\n contentHelper.appendElementRow(i18nString(UIStrings.function), detailsNode);\n }\n break;\n }\n\n case Trace.Types.Events.Name.TIMER_FIRE:\n case Trace.Types.Events.Name.TIMER_INSTALL:\n case Trace.Types.Events.Name.TIMER_REMOVE: {\n contentHelper.appendTextRow(i18nString(UIStrings.timerId), unsafeEventData.timerId);\n\n if (event.name === Trace.Types.Events.Name.TIMER_INSTALL) {\n contentHelper.appendTextRow(\n i18nString(UIStrings.timeout), i18n.TimeUtilities.millisToString(unsafeEventData['timeout']));\n contentHelper.appendTextRow(i18nString(UIStrings.repeats), !unsafeEventData['singleShot']);\n }\n break;\n }\n\n case Trace.Types.Events.Name.FIRE_ANIMATION_FRAME: {\n contentHelper.appendTextRow(i18nString(UIStrings.callbackId), unsafeEventData['id']);\n break;\n }\n\n case Trace.Types.Events.Name.COMPILE_MODULE: {\n contentHelper.appendLocationRow(i18nString(UIStrings.module), unsafeEventArgs['fileName'], 0);\n break;\n }\n case Trace.Types.Events.Name.COMPILE_SCRIPT: {\n // This case is handled above\n break;\n }\n\n case Trace.Types.Events.Name.CACHE_MODULE: {\n url = unsafeEventData && unsafeEventData['url'] as Platform.DevToolsPath.UrlString;\n contentHelper.appendTextRow(\n i18nString(UIStrings.compilationCacheSize),\n Platform.NumberUtilities.bytesToString(unsafeEventData['producedCacheSize']));\n break;\n }\n\n case Trace.Types.Events.Name.CACHE_SCRIPT: {\n url = unsafeEventData && unsafeEventData['url'] as Platform.DevToolsPath.UrlString;\n if (url) {\n const {lineNumber, columnNumber} = Trace.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event);\n contentHelper.appendLocationRow(i18nString(UIStrings.script), url, lineNumber || 0, columnNumber);\n }\n contentHelper.appendTextRow(\n i18nString(UIStrings.compilationCacheSize),\n Platform.NumberUtilities.bytesToString(unsafeEventData['producedCacheSize']));\n break;\n }\n\n case Trace.Types.Events.Name.EVALUATE_SCRIPT: {\n url = unsafeEventData && unsafeEventData['url'] as Platform.DevToolsPath.UrlString;\n if (url) {\n const {lineNumber, columnNumber} = Trace.Helpers.Trace.getZeroIndexedLineAndColumnForEvent(event);\n contentHelper.appendLocationRow(i18nString(UIStrings.script), url, lineNumber || 0, columnNumber);\n }\n break;\n }\n\n case Trace.Types.Events.Name.WASM_STREAM_FROM_RESPONSE_CALLBACK:\n case Trace.Types.Events.Name.WASM_COMPILED_MODULE:\n case Trace.Types.Events.Name.WASM_CACHED_MODULE:\n case Trace.Types.Events.Name.WASM_MODULE_CACHE_HIT:\n case Trace.Types.Events.Name.WASM_MODULE_CACHE_INVALID: {\n if (unsafeEventData) {\n url = unsafeEventArgs['url'] as Platform.DevToolsPath.UrlString;\n if (url) {\n contentHelper.appendTextRow(i18nString(UIStrings.url), url);\n }\n const producedCachedSize = unsafeEventArgs['producedCachedSize'];\n if (producedCachedSize) {\n contentHelper.appendTextRow(i18nString(UIStrings.producedCacheSize), producedCachedSize);\n }\n const consumedCachedSize = unsafeEventArgs['consumedCachedSize'];\n if (consumedCachedSize) {\n contentHelper.appendTextRow(i18nString(UIStrings.consumedCacheSize), consumedCachedSize);\n }\n }\n break;\n }\n\n // @ts-ignore Fall-through intended.\n case Trace.Types.Events.Name.PAINT: {\n const clip = unsafeEventData['clip'];\n contentHelper.appendTextRow(\n i18nString(UIStrings.location), i18nString(UIStrings.sSCurlyBrackets, {PH1: clip[0], PH2: clip[1]}));\n const clipWidth = TimelineUIUtils.quadWidth(clip);\n const clipHeight = TimelineUIUtils.quadHeight(clip);\n contentHelper.appendTextRow(\n i18nString(UIStrings.dimensions), i18nString(UIStrings.sSDimensions, {PH1: clipWidth, PH2: clipHeight}));\n }\n\n case Trace.Types.Events.Name.PAINT_SETUP:\n case Trace.Types.Events.Name.RASTERIZE:\n case Trace.Types.Events.Name.SCROLL_LAYER: {\n relatedNodeLabel = i18nString(UIStrings.layerRoot);\n break;\n }\n\n case Trace.Types.Events.Name.PAINT_IMAGE:\n case Trace.Types.Events.Name.DECODE_LAZY_PIXEL_REF:\n case Trace.Types.Events.Name.DECODE_IMAGE:\n case Trace.Types.Events.Name.DRAW_LAZY_PIXEL_REF: {\n relatedNodeLabel = i18nString(UIStrings.ownerElement);\n url = Trace.Extras.URLForEntry.get(parsedTrace, event);\n if (url) {\n const options = {\n tabStop: true,\n showColumnNumber: false,\n inlineFrameIndex: 0,\n };\n contentHelper.appendElementRow(\n i18nString(UIStrings.imageUrl), LegacyComponents.Linkifier.Linkifier.linkifyURL(url, options));\n }\n break;\n }\n\n case Trace.Types.Events.Name.PARSE_AUTHOR_STYLE_SHEET: {\n url = unsafeEventData['styleSheetUrl'] as Platform.DevToolsPath.UrlString;\n if (url) {\n const options = {\n tabStop: true,\n showColumnNumber: false,\n inlineFrameIndex: 0,\n };\n contentHelper.appendElementRow(\n i18nString(UIStrings.stylesheetUrl), LegacyComponents.Linkifier.Linkifier.linkifyURL(url, options));\n }\n break;\n }\n\n case Trace.Types.Events.Name.UPDATE_LAYOUT_TREE: {\n contentHelper.appendTextRow(i18nString(UIStrings.elementsAffected), unsafeEventArgs['elementCount']);\n\n const selectorStatsSetting =\n Common.Settings.Settings.instance().createSetting('timeline-capture-selector-stats', false);\n if (!selectorStatsSetting.get()) {\n const note = document.createElement('span');\n note.textContent = i18nString(UIStrings.sSelectorStatsInfo, {PH1: selectorStatsSetting.title()});\n contentHelper.appendElementRow(i18nString(UIStrings.selectorStatsTitle), note);\n }\n\n break;\n }\n\n case Trace.Types.Events.Name.LAYOUT: {\n const beginData = unsafeEventArgs['beginData'];\n contentHelper.appendTextRow(\n i18nString(UIStrings.nodesThatNeedLayout),\n i18nString(UIStrings.sOfS, {PH1: beginData['dirtyObjects'], PH2: beginData['totalObjects']}));\n relatedNodeLabel = i18nString(UIStrings.layoutRoot);\n break;\n }\n\n case Trace.Types.Events.Name.CONSOLE_TIME: {\n contentHelper.appendTextRow(i18nString(UIStrings.message), event.name);\n break;\n }\n\n case Trace.Types.Events.Name.WEB_SOCKET_CREATE:\n case Trace.Types.Events.Name.WEB_SOCKET_SEND_HANDSHAKE_REQUEST:\n case Trace.Types.Events.Name.WEB_SOCKET_RECEIVE_HANDSHAKE_REQUEST:\n case Trace.Types.Events.Name.WEB_SOCKET_SEND:\n case Trace.Types.Events.Name.WEB_SOCKET_RECEIVE:\n case Trace.Types.Events.Name.WEB_SOCKET_DESTROY: {\n if (Trace.Types.Events.isWebSocketTraceEvent(event)) {\n const rows = TimelineComponents.DetailsView.buildRowsForWebSocketEvent(event, parsedTrace);\n for (const {key, value} of rows) {\n contentHelper.appendTextRow(key, value);\n }\n }\n break;\n }\n\n case Trace.Types.Events.Name.EMBEDDER_CALLBACK: {\n contentHelper.appendTextRow(i18nString(UIStrings.callbackFunction), unsafeEventData['callbackName']);\n break;\n }\n\n case Trace.Types.Events.Name.ANIMATION: {\n if (!Trace.Types.Events.isSyntheticAnimation(event)) {\n break;\n }\n const {displayName, nodeName} = event.args.data.beginEvent.args.data;\n displayName && contentHelper.appendTextRow(i18nString(UIStrings.animating), displayName);\n // If relatedNodes is empty (maybe saved trace), then print the text description of the DOM node.\n if (!relatedNodesMap?.size && nodeName) {\n contentHelper.appendTextRow(i18nString(UIStrings.relatedNode), nodeName);\n }\n\n const CLSInsight = Trace.Insights.InsightRunners.CumulativeLayoutShift;\n const failures = CLSInsight.getNonCompositedFailure(event);\n if (!failures.length) {\n break;\n }\n\n const failureReasons = new Set(failures.map(f => f.failureReasons).flat().filter(Boolean));\n const unsupportedProperties =\n new Set(failures.map(f => f.unsupportedProperties).flat().filter(Boolean)) as Set;\n\n for (const reason of failureReasons) {\n let str;\n switch (reason) {\n case CLSInsight.AnimationFailureReasons.UNSUPPORTED_CSS_PROPERTY:\n str = i18nString(UIStrings.unsupportedCSSProperty, {\n propertyCount: unsupportedProperties.size,\n properties:\n new Intl.ListFormat(undefined, {style: 'short', type: 'conjunction'}).format(unsupportedProperties),\n });\n break;\n case CLSInsight.AnimationFailureReasons.TRANSFROM_BOX_SIZE_DEPENDENT:\n str = i18nString(UIStrings.transformDependsBoxSize);\n break;\n case CLSInsight.AnimationFailureReasons.FILTER_MAY_MOVE_PIXELS:\n str = i18nString(UIStrings.filterMayMovePixels);\n break;\n case CLSInsight.AnimationFailureReasons.NON_REPLACE_COMPOSITE_MODE:\n str = i18nString(UIStrings.nonReplaceCompositeMode);\n break;\n case CLSInsight.AnimationFailureReasons.INCOMPATIBLE_ANIMATIONS:\n str = i18nString(UIStrings.incompatibleAnimations);\n break;\n case CLSInsight.AnimationFailureReasons.UNSUPPORTED_TIMING_PARAMS:\n str = i18nString(UIStrings.unsupportedTimingParameters);\n break;\n default:\n break;\n }\n str && contentHelper.appendElementRow(i18nString(UIStrings.compositingFailed), str, true);\n }\n\n break;\n }\n\n case Trace.Types.Events.Name.PARSE_HTML: {\n const beginData = unsafeEventArgs['beginData'];\n const startLine = beginData['startLine'] - 1;\n const endLine = unsafeEventArgs['endData'] ? unsafeEventArgs['endData']['endLine'] - 1 : undefined;\n url = beginData['url'];\n if (url) {\n contentHelper.appendLocationRange(i18nString(UIStrings.range), url, startLine, endLine);\n }\n break;\n }\n\n // @ts-ignore Fall-through intended.\n case Trace.Types.Events.Name.FIRE_IDLE_CALLBACK: {\n contentHelper.appendTextRow(\n i18nString(UIStrings.allottedTime),\n i18n.TimeUtilities.millisToString(unsafeEventData['allottedMilliseconds']));\n contentHelper.appendTextRow(i18nString(UIStrings.invokedByTimeout), unsafeEventData['timedOut']);\n }\n\n case Trace.Types.Events.Name.REQUEST_IDLE_CALLBACK:\n case Trace.Types.Events.Name.CANCEL_IDLE_CALLBACK: {\n contentHelper.appendTextRow(i18nString(UIStrings.callbackId), unsafeEventData['id']);\n break;\n }\n\n case Trace.Types.Events.Name.EVENT_DISPATCH: {\n contentHelper.appendTextRow(i18nString(UIStrings.type), unsafeEventData['type']);\n break;\n }\n\n // @ts-ignore Fall-through intended.\n case Trace.Types.Events.Name.MARK_LCP_CANDIDATE: {\n contentHelper.appendTextRow(i18nString(UIStrings.type), String(unsafeEventData['type']));\n contentHelper.appendTextRow(i18nString(UIStrings.size), String(unsafeEventData['size']));\n }\n\n case Trace.Types.Events.Name.MARK_FIRST_PAINT:\n case Trace.Types.Events.Name.MARK_FCP:\n case Trace.Types.Events.Name.MARK_LOAD:\n case Trace.Types.Events.Name.MARK_DOM_CONTENT: {\n const adjustedEventTimeStamp = timeStampForEventAdjustedForClosestNavigationIfPossible(\n event,\n parsedTrace,\n );\n\n contentHelper.appendTextRow(\n i18nString(UIStrings.timestamp), i18n.TimeUtilities.preciseMillisToString(adjustedEventTimeStamp, 1));\n\n if (Trace.Types.Events.isMarkerEvent(event)) {\n contentHelper.appendElementRow(\n i18nString(UIStrings.details), TimelineUIUtils.buildDetailsNodeForMarkerEvents(event));\n }\n\n break;\n }\n\n case Trace.Types.Events.Name.EVENT_TIMING: {\n const detailsNode = await TimelineUIUtils.buildDetailsNodeForTraceEvent(\n event, targetForEvent(parsedTrace, event), linkifier, isFreshRecording, parsedTrace);\n if (detailsNode) {\n contentHelper.appendElementRow(i18nString(UIStrings.details), detailsNode);\n }\n if (Trace.Types.Events.isSyntheticInteraction(event)) {\n const inputDelay = i18n.TimeUtilities.formatMicroSecondsAsMillisFixed(event.inputDelay);\n const mainThreadTime = i18n.TimeUtilities.formatMicroSecondsAsMillisFixed(event.mainThreadHandling);\n const presentationDelay = i18n.TimeUtilities.formatMicroSecondsAsMillisFixed(event.presentationDelay);\n contentHelper.appendTextRow(i18nString(UIStrings.interactionID), event.interactionId);\n contentHelper.appendTextRow(i18nString(UIStrings.inputDelay), inputDelay);\n contentHelper.appendTextRow(i18nString(UIStrings.processingDuration), mainThreadTime);\n contentHelper.appendTextRow(i18nString(UIStrings.presentationDelay), presentationDelay);\n }\n break;\n }\n\n case Trace.Types.Events.Name.LAYOUT_SHIFT: {\n if (!Trace.Types.Events.isSyntheticLayoutShift(event)) {\n console.error('Unexpected type for LayoutShift event');\n break;\n }\n const layoutShift = event as Trace.Types.Events.SyntheticLayoutShift;\n const layoutShiftEventData = layoutShift.args.data;\n const warning = document.createElement('span');\n const clsLink = UI.XLink.XLink.create(\n 'https://web.dev/cls/', i18nString(UIStrings.cumulativeLayoutShifts), undefined, undefined,\n 'cumulative-layout-shifts');\n const evolvedClsLink = UI.XLink.XLink.create(\n 'https://web.dev/evolving-cls/', i18nString(UIStrings.evolvedClsLink), undefined, undefined, 'evolved-cls');\n\n warning.appendChild(\n i18n.i18n.getFormatLocalizedString(str_, UIStrings.sCLSInformation, {PH1: clsLink, PH2: evolvedClsLink}));\n contentHelper.appendElementRow(i18nString(UIStrings.warning), warning, true);\n if (!layoutShiftEventData) {\n break;\n }\n contentHelper.appendTextRow(i18nString(UIStrings.score), layoutShiftEventData['score'].toPrecision(4));\n contentHelper.appendTextRow(\n i18nString(UIStrings.cumulativeScore), layoutShiftEventData['cumulative_score'].toPrecision(4));\n contentHelper.appendTextRow(\n i18nString(UIStrings.currentClusterId), layoutShift.parsedData.sessionWindowData.id);\n contentHelper.appendTextRow(\n i18nString(UIStrings.currentClusterScore),\n layoutShift.parsedData.sessionWindowData.cumulativeWindowScore.toPrecision(4));\n contentHelper.appendTextRow(\n i18nString(UIStrings.hadRecentInput),\n unsafeEventData['had_recent_input'] ? i18nString(UIStrings.yes) : i18nString(UIStrings.no));\n\n for (const impactedNode of unsafeEventData['impacted_nodes']) {\n const oldRect = new CLSRect(impactedNode['old_rect']);\n const newRect = new CLSRect(impactedNode['new_rect']);\n\n const linkedOldRect = await Common.Linkifier.Linkifier.linkify(oldRect);\n const linkedNewRect = await Common.Linkifier.Linkifier.linkify(newRect);\n\n contentHelper.appendElementRow(i18nString(UIStrings.movedFrom), linkedOldRect);\n contentHelper.appendElementRow(i18nString(UIStrings.movedTo), linkedNewRect);\n }\n\n break;\n }\n\n default: {\n const detailsNode = await TimelineUIUtils.buildDetailsNodeForTraceEvent(\n event, targetForEvent(parsedTrace, event), linkifier, isFreshRecording, parsedTrace);\n if (detailsNode) {\n contentHelper.appendElementRow(i18nString(UIStrings.details), detailsNode);\n }\n break;\n }\n }\n const relatedNodes = relatedNodesMap?.values() || [];\n for (const relatedNode of relatedNodes) {\n if (relatedNode) {\n const nodeSpan = await Common.Linkifier.Linkifier.linkify(relatedNode);\n contentHelper.appendElementRow(relatedNodeLabel || i18nString(UIStrings.relatedNode), nodeSpan);\n }\n }\n\n // @ts-ignore TODO(crbug.com/1011811): Remove symbol usage.\n if (event[previewElementSymbol]) {\n contentHelper.addSection(i18nString(UIStrings.preview));\n // @ts-ignore TODO(crbug.com/1011811): Remove symbol usage.\n contentHelper.appendElementRow('', event[previewElementSymbol]);\n }\n\n const stackTrace = Trace.Helpers.Trace.getZeroIndexedStackTraceForEvent(event);\n if (initiator || initiatorFor || stackTrace || parsedTrace?.Invalidations.invalidationsForEvent.get(event)) {\n await TimelineUIUtils.generateCauses(event, contentHelper, parsedTrace);\n }\n\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_DEBUG_MODE)) {\n TimelineUIUtils.renderEventJson(event, contentHelper);\n }\n\n const stats: {\n [x: string]: number,\n } = {};\n const showPieChart =\n detailed && parsedTrace && TimelineUIUtils.aggregatedStatsForTraceEvent(stats, parsedTrace, event);\n if (showPieChart) {\n contentHelper.addSection(i18nString(UIStrings.aggregatedTime));\n const pieChart = TimelineUIUtils.generatePieChart(stats, TimelineUIUtils.eventStyle(event).category, selfTime);\n contentHelper.appendElementRow('', pieChart);\n }\n\n return contentHelper.fragment;\n }\n\n static statsForTimeRange(\n events: Trace.Types.Events.Event[], startTime: Trace.Types.Timing.MilliSeconds,\n endTime: Trace.Types.Timing.MilliSeconds): {\n [x: string]: number,\n } {\n if (!events.length) {\n return {idle: endTime - startTime};\n }\n\n buildRangeStatsCacheIfNeeded(events);\n const aggregatedStats = subtractStats(aggregatedStatsAtTime(endTime), aggregatedStatsAtTime(startTime));\n const aggregatedTotal = Object.values(aggregatedStats).reduce((a, b) => a + b, 0);\n aggregatedStats['idle'] = Math.max(0, endTime - startTime - aggregatedTotal);\n return aggregatedStats;\n\n function aggregatedStatsAtTime(time: number): {\n [x: string]: number,\n } {\n const stats: {\n [x: string]: number,\n } = {};\n // @ts-ignore TODO(crbug.com/1011811): Remove symbol usage.\n const cache = events[categoryBreakdownCacheSymbol];\n for (const category in cache) {\n const categoryCache = cache[category];\n const index =\n Platform.ArrayUtilities.upperBound(categoryCache.time, time, Platform.ArrayUtilities.DEFAULT_COMPARATOR);\n let value;\n if (index === 0) {\n value = 0;\n } else if (index === categoryCache.time.length) {\n value = categoryCache.value[categoryCache.value.length - 1];\n } else {\n const t0 = categoryCache.time[index - 1];\n const t1 = categoryCache.time[index];\n const v0 = categoryCache.value[index - 1];\n const v1 = categoryCache.value[index];\n value = v0 + (v1 - v0) * (time - t0) / (t1 - t0);\n }\n stats[category] = value;\n }\n return stats;\n }\n\n function subtractStats(\n a: {\n [x: string]: number,\n },\n b: {\n [x: string]: number,\n }): {\n [x: string]: number,\n } {\n const result = Object.assign({}, a);\n for (const key in b) {\n result[key] -= b[key];\n }\n return result;\n }\n\n function buildRangeStatsCacheIfNeeded(events: Trace.Types.Events.Event[]): void {\n // @ts-ignore TODO(crbug.com/1011811): Remove symbol usage.\n if (events[categoryBreakdownCacheSymbol]) {\n return;\n }\n\n // aggeregatedStats is a map by categories. For each category there's an array\n // containing sorted time points which records accumulated value of the category.\n const aggregatedStats: {\n [x: string]: {\n time: number[],\n value: number[],\n },\n } = {};\n const categoryStack: string[] = [];\n let lastTime = 0;\n Trace.Helpers.Trace.forEachEvent(events, {\n onStartEvent,\n onEndEvent,\n });\n\n function updateCategory(category: string, time: number): void {\n let statsArrays: {\n time: number[],\n value: number[],\n } = aggregatedStats[category];\n if (!statsArrays) {\n statsArrays = {time: [], value: []};\n aggregatedStats[category] = statsArrays;\n }\n if (statsArrays.time.length && statsArrays.time[statsArrays.time.length - 1] === time || lastTime > time) {\n return;\n }\n const lastValue = statsArrays.value.length > 0 ? statsArrays.value[statsArrays.value.length - 1] : 0;\n statsArrays.value.push(lastValue + time - lastTime);\n statsArrays.time.push(time);\n }\n\n function categoryChange(from: string|null, to: string|null, time: number): void {\n if (from) {\n updateCategory(from, time);\n }\n lastTime = time;\n if (to) {\n updateCategory(to, time);\n }\n }\n\n function onStartEvent(e: Trace.Types.Events.Event): void {\n const {startTime} = Trace.Helpers.Timing.eventTimingsMilliSeconds(e);\n const category =\n TimelineComponents.EntryStyles.getEventStyle(e.name as Trace.Types.Events.Name)?.category.name ||\n TimelineComponents.EntryStyles.getCategoryStyles().other.name;\n const parentCategory = categoryStack.length ? categoryStack[categoryStack.length - 1] : null;\n if (category !== parentCategory) {\n categoryChange(parentCategory || null, category, startTime);\n }\n categoryStack.push(category);\n }\n\n function onEndEvent(e: Trace.Types.Events.Event): void {\n const {endTime} = Trace.Helpers.Timing.eventTimingsMilliSeconds(e);\n const category = categoryStack.pop();\n const parentCategory = categoryStack.length ? categoryStack[categoryStack.length - 1] : null;\n if (category !== parentCategory) {\n categoryChange(category || null, parentCategory || null, endTime || 0);\n }\n }\n\n const obj = (events as Object);\n // @ts-ignore TODO(crbug.com/1011811): Remove symbol usage.\n obj[categoryBreakdownCacheSymbol] = aggregatedStats;\n }\n }\n\n private static renderEventJson(event: Trace.Types.Events.Event, contentHelper: TimelineDetailsContentHelper): void {\n contentHelper.addSection(i18nString(UIStrings.traceEvent));\n\n const eventWithArgsFirst = {\n ...{args: event.args},\n ...event,\n };\n const highlightContainer = TimelineUIUtils.renderObjectJson(eventWithArgsFirst);\n contentHelper.appendElementRow('', highlightContainer);\n }\n\n private static renderObjectJson(obj: Object): HTMLDivElement {\n const indentLength = Common.Settings.Settings.instance().moduleSetting('text-editor-indent').get().length;\n // Elide if the data is huge. Then remove the initial new-line for a denser UI\n const eventStr = JSON.stringify(obj, null, indentLength).slice(0, 10_000).replace(/{\\n /, '{ ');\n\n // Use CodeHighlighter for syntax highlighting.\n const highlightContainer = document.createElement('div');\n const shadowRoot =\n UI.UIUtils.createShadowRootWithCoreStyles(highlightContainer, {cssFile: [codeHighlighterStyles]});\n const elem = shadowRoot.createChild('div');\n elem.classList.add('monospace', 'source-code');\n elem.textContent = eventStr;\n void CodeHighlighter.CodeHighlighter.highlightNode(elem, 'text/javascript');\n return highlightContainer;\n }\n\n static stackTraceFromCallFrames(callFrames: Protocol.Runtime.CallFrame[]|\n Trace.Types.Events.CallFrame[]): Protocol.Runtime.StackTrace {\n return {callFrames} as Protocol.Runtime.StackTrace;\n }\n\n private static async generateCauses(\n event: Trace.Types.Events.Event, contentHelper: TimelineDetailsContentHelper,\n parsedTrace: Trace.Handlers.Types.ParsedTrace): Promise {\n const {startTime} = Trace.Helpers.Timing.eventTimingsMilliSeconds(event);\n let initiatorStackLabel = i18nString(UIStrings.initiatorStackTrace);\n let stackLabel = i18nString(UIStrings.stackTrace);\n\n switch (event.name) {\n case Trace.Types.Events.Name.TIMER_FIRE:\n initiatorStackLabel = i18nString(UIStrings.timerInstalled);\n break;\n case Trace.Types.Events.Name.FIRE_ANIMATION_FRAME:\n initiatorStackLabel = i18nString(UIStrings.animationFrameRequested);\n break;\n case Trace.Types.Events.Name.FIRE_IDLE_CALLBACK:\n initiatorStackLabel = i18nString(UIStrings.idleCallbackRequested);\n break;\n case Trace.Types.Events.Name.UPDATE_LAYOUT_TREE:\n initiatorStackLabel = i18nString(UIStrings.firstInvalidated);\n stackLabel = i18nString(UIStrings.recalculationForced);\n break;\n case Trace.Types.Events.Name.LAYOUT:\n initiatorStackLabel = i18nString(UIStrings.firstLayoutInvalidation);\n stackLabel = i18nString(UIStrings.layoutForced);\n break;\n }\n\n const stackTrace = Trace.Helpers.Trace.getZeroIndexedStackTraceForEvent(event);\n if (stackTrace && stackTrace.length) {\n contentHelper.addSection(stackLabel);\n contentHelper.createChildStackTraceElement(TimelineUIUtils.stackTraceFromCallFrames(stackTrace));\n }\n\n const initiator = parsedTrace.Initiators.eventToInitiator.get(event);\n const initiatorFor = parsedTrace.Initiators.initiatorToEvents.get(event);\n const invalidations = parsedTrace.Invalidations.invalidationsForEvent.get(event);\n\n if (initiator) {\n // If we have an initiator for the event, we can show its stack trace, a link to reveal the initiator,\n // and the time since the initiator (Pending For).\n const stackTrace = Trace.Helpers.Trace.getZeroIndexedStackTraceForEvent(initiator);\n if (stackTrace) {\n contentHelper.addSection(initiatorStackLabel);\n contentHelper.createChildStackTraceElement(TimelineUIUtils.stackTraceFromCallFrames(stackTrace.map(frame => {\n return {\n ...frame,\n scriptId: String(frame.scriptId) as Protocol.Runtime.ScriptId,\n };\n })));\n }\n\n const link = this.createEntryLink(initiator);\n contentHelper.appendElementRow(i18nString(UIStrings.initiatedBy), link);\n\n const {startTime: initiatorStartTime} = Trace.Helpers.Timing.eventTimingsMilliSeconds(initiator);\n const delay = startTime - initiatorStartTime;\n contentHelper.appendTextRow(i18nString(UIStrings.pendingFor), i18n.TimeUtilities.preciseMillisToString(delay, 1));\n }\n\n if (initiatorFor) {\n // If the event is an initiator for some entries, add links to reveal them.\n const links = document.createElement('div');\n initiatorFor.map((initiator, i) => {\n links.appendChild(this.createEntryLink(initiator));\n // Add space between each link if it's not last\n if (i < initiatorFor.length - 1) {\n links.append(' ');\n }\n });\n contentHelper.appendElementRow(UIStrings.initiatorFor, links);\n }\n\n if (invalidations && invalidations.length) {\n const totalInvalidations = parsedTrace.Invalidations.invalidationCountForEvent.get(event) ??\n 0; // Won't be 0, but saves us dealing with undefined.\n contentHelper.addSection(i18nString(UIStrings.invalidations, {PH1: totalInvalidations}));\n await TimelineUIUtils.generateInvalidationsList(invalidations, contentHelper);\n }\n }\n\n private static createEntryLink(entry: Trace.Types.Events.Event): HTMLElement {\n const link = document.createElement('span');\n\n const traceBoundsState = TraceBounds.TraceBounds.BoundsManager.instance().state();\n\n if (!traceBoundsState) {\n console.error('Tried to link to an entry without any traceBoundsState. This should never happen.');\n return link;\n }\n\n // Check is the entry is outside of the current breadcrumb. If it is, don't create a link to navigate to it because there is no way to navigate outside breadcrumb without removing it. Instead, just display the name and \"outside breadcrumb\" text\n // Consider entry outside breadcrumb only if it is fully outside. If a part of it is visible, we can still select it.\n const isEntryOutsideBreadcrumb = traceBoundsState.micro.minimapTraceBounds.min > entry.ts + (entry.dur || 0) ||\n traceBoundsState.micro.minimapTraceBounds.max < entry.ts;\n\n // Check if it is in the hidden array\n const isEntryHidden = ModificationsManager.activeManager()?.getEntriesFilter().entryIsInvisible(entry);\n\n if (!isEntryOutsideBreadcrumb) {\n link.classList.add('devtools-link');\n UI.ARIAUtils.markAsLink(link);\n link.tabIndex = 0;\n link.addEventListener('click', () => {\n TimelinePanel.instance().select(TimelineSelection.fromTraceEvent((entry)));\n });\n\n link.addEventListener('keydown', event => {\n if (event.key === 'Enter') {\n TimelinePanel.instance().select(TimelineSelection.fromTraceEvent((entry)));\n event.consume(true);\n }\n });\n }\n\n if (isEntryHidden) {\n link.textContent = this.eventTitle(entry) + ' ' + i18nString(UIStrings.entryIsHidden);\n } else if (isEntryOutsideBreadcrumb) {\n link.textContent = this.eventTitle(entry) + ' ' + i18nString(UIStrings.outsideBreadcrumbRange);\n } else {\n link.textContent = this.eventTitle(entry);\n }\n\n return link;\n }\n\n private static async generateInvalidationsList(\n invalidations: Trace.Types.Events.InvalidationTrackingEvent[],\n contentHelper: TimelineDetailsContentHelper): Promise {\n const {groupedByReason, backendNodeIds} = TimelineComponents.DetailsView.generateInvalidationsList(invalidations);\n\n let relatedNodesMap: Map|null = null;\n const target = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n const domModel = target?.model(SDK.DOMModel.DOMModel);\n if (domModel) {\n relatedNodesMap = await domModel.pushNodesByBackendIdsToFrontend(backendNodeIds);\n }\n\n Object.keys(groupedByReason).forEach(reason => {\n TimelineUIUtils.generateInvalidationsForReason(reason, groupedByReason[reason], relatedNodesMap, contentHelper);\n });\n }\n\n private static generateInvalidationsForReason(\n reason: string, invalidations: Trace.Types.Events.InvalidationTrackingEvent[],\n relatedNodesMap: Map|null, contentHelper: TimelineDetailsContentHelper): void {\n function createLinkForInvalidationNode(invalidation: Trace.Types.Events.InvalidationTrackingEvent):\n HTMLSpanElement {\n const node = (invalidation.args.data.nodeId && relatedNodesMap) ?\n relatedNodesMap.get(invalidation.args.data.nodeId) :\n null;\n if (node) {\n const nodeSpan = document.createElement('span');\n void Common.Linkifier.Linkifier.linkify(node).then(link => nodeSpan.appendChild(link));\n return nodeSpan;\n }\n if (invalidation.args.data.nodeName) {\n const nodeSpan = document.createElement('span');\n nodeSpan.textContent = invalidation.args.data.nodeName;\n return nodeSpan;\n }\n const nodeSpan = document.createElement('span');\n UI.UIUtils.createTextChild(nodeSpan, i18nString(UIStrings.UnknownNode));\n return nodeSpan;\n }\n\n const generatedItems = new Set();\n\n for (const invalidation of invalidations) {\n const stackTrace = Trace.Helpers.Trace.getZeroIndexedStackTraceForEvent(invalidation);\n let scriptLink: HTMLElement|null = null;\n const callFrame = stackTrace?.at(0);\n if (callFrame) {\n scriptLink = contentHelper.linkifier()?.maybeLinkifyScriptLocation(\n SDK.TargetManager.TargetManager.instance().rootTarget(),\n callFrame.scriptId as Protocol.Runtime.ScriptId,\n callFrame.url as Platform.DevToolsPath.UrlString,\n callFrame.lineNumber,\n ) ||\n null;\n }\n\n const niceNodeLink = createLinkForInvalidationNode(invalidation);\n\n const text = scriptLink ?\n i18n.i18n.getFormatLocalizedString(\n str_, UIStrings.invalidationWithCallFrame, {PH1: niceNodeLink, PH2: scriptLink}) as HTMLElement :\n niceNodeLink;\n\n // Sometimes we can get different Invalidation events which cause\n // the same text for the same element for the same reason to be\n // generated. Rather than show the user duplicates, if we have\n // generated text that looks identical to this before, we will\n // bail.\n const generatedText: string = (typeof text === 'string' ? text : text.innerText);\n if (generatedItems.has(generatedText)) {\n continue;\n }\n\n generatedItems.add(generatedText);\n contentHelper.appendElementRow(reason, text);\n }\n }\n\n private static aggregatedStatsForTraceEvent(\n total: {\n [x: string]: number,\n },\n parsedTrace: Trace.Handlers.Types.ParsedTrace, event: Trace.Types.Events.Event): boolean {\n const events = parsedTrace.Renderer?.allTraceEntries || [];\n const {startTime, endTime} = Trace.Helpers.Timing.eventTimingsMilliSeconds(event);\n function eventComparator(startTime: number, e: Trace.Types.Events.Event): number {\n const {startTime: eventStartTime} = Trace.Helpers.Timing.eventTimingsMilliSeconds(e);\n return startTime - eventStartTime;\n }\n\n const index = Platform.ArrayUtilities.binaryIndexOf(events, startTime, eventComparator);\n // Not a main thread event?\n if (index < 0) {\n return false;\n }\n let hasChildren = false;\n if (endTime) {\n for (let i = index; i < events.length; i++) {\n const nextEvent = events[i];\n const {startTime: nextEventStartTime} = Trace.Helpers.Timing.eventTimingsMilliSeconds(nextEvent);\n if (nextEventStartTime >= endTime) {\n break;\n }\n const nextEventSelfTime = getEventSelfTime(nextEvent, parsedTrace);\n if (!nextEventSelfTime) {\n continue;\n }\n if (nextEvent.tid !== event.tid) {\n continue;\n }\n if (i > index) {\n hasChildren = true;\n }\n const categoryName = TimelineUIUtils.eventStyle(nextEvent).category.name;\n total[categoryName] = (total[categoryName] || 0) + nextEventSelfTime;\n }\n }\n if (Trace.Types.Events.isPhaseAsync(event.ph)) {\n if (endTime) {\n let aggregatedTotal = 0;\n for (const categoryName in total) {\n aggregatedTotal += total[categoryName];\n }\n total['idle'] = Math.max(0, endTime - startTime - aggregatedTotal);\n }\n return false;\n }\n return hasChildren;\n }\n\n static async buildPicturePreviewContent(\n parsedTrace: Trace.Handlers.Types.ParsedTrace, event: Trace.Types.Events.Paint,\n target: SDK.Target.Target): Promise {\n const snapshotEvent = parsedTrace.LayerTree.paintsToSnapshots.get(event);\n if (!snapshotEvent) {\n return null;\n }\n\n const paintProfilerModel = target.model(SDK.PaintProfiler.PaintProfilerModel);\n if (!paintProfilerModel) {\n return null;\n }\n const snapshot = await paintProfilerModel.loadSnapshot(snapshotEvent.args.snapshot.skp64);\n if (!snapshot) {\n return null;\n }\n\n const snapshotWithRect = {\n snapshot,\n rect: snapshotEvent.args.snapshot.params?.layer_rect,\n };\n\n if (!snapshotWithRect) {\n return null;\n }\n const imageURLPromise = snapshotWithRect.snapshot.replay();\n snapshotWithRect.snapshot.release();\n const imageURL = await imageURLPromise as Platform.DevToolsPath.UrlString;\n if (!imageURL) {\n return null;\n }\n const stylesContainer = document.createElement('div');\n const shadowRoot = stylesContainer.attachShadow({mode: 'open'});\n shadowRoot.adoptedStyleSheets = [imagePreviewStyles];\n const container = shadowRoot.createChild('div') as HTMLDivElement;\n container.classList.add('image-preview-container', 'vbox', 'link');\n const img = (container.createChild('img') as HTMLImageElement);\n img.src = imageURL;\n img.alt = LegacyComponents.ImagePreview.ImagePreview.defaultAltTextForImageURL(imageURL);\n const paintProfilerButton = container.createChild('a');\n paintProfilerButton.textContent = i18nString(UIStrings.paintProfiler);\n UI.ARIAUtils.markAsLink(container);\n container.tabIndex = 0;\n container.addEventListener(\n 'click', () => TimelinePanel.instance().select(TimelineSelection.fromTraceEvent(event)), false);\n container.addEventListener('keydown', keyEvent => {\n if (keyEvent.key === 'Enter') {\n TimelinePanel.instance().select(TimelineSelection.fromTraceEvent(event));\n keyEvent.consume(true);\n }\n });\n return stylesContainer;\n }\n\n static createEventDivider(event: Trace.Types.Events.Event, zeroTime: number): Element {\n const eventDivider = document.createElement('div');\n eventDivider.classList.add('resources-event-divider');\n const {startTime: eventStartTime} = Trace.Helpers.Timing.eventTimingsMilliSeconds(event);\n\n const startTime = i18n.TimeUtilities.millisToString(eventStartTime - zeroTime);\n UI.Tooltip.Tooltip.install(\n eventDivider, i18nString(UIStrings.sAtS, {PH1: TimelineUIUtils.eventTitle(event), PH2: startTime}));\n const style = TimelineUIUtils.markerStyleForEvent(event);\n if (style.tall) {\n eventDivider.style.backgroundColor = style.color;\n }\n return eventDivider;\n }\n\n static visibleEventsFilter(): TimelineModel.TimelineModelFilter.TimelineModelFilter {\n return new TimelineModel.TimelineModelFilter.TimelineVisibleEventsFilter(\n TimelineComponents.EntryStyles.visibleTypes());\n }\n\n // Included only for layout tests.\n // TODO(crbug.com/1386091): Fix/port layout tests and remove.\n static categories(): TimelineComponents.EntryStyles.CategoryPalette {\n return TimelineComponents.EntryStyles.getCategoryStyles();\n }\n\n static generatePieChart(\n aggregatedStats: {\n [x: string]: number,\n },\n selfCategory?: TimelineComponents.EntryStyles.TimelineCategory, selfTime?: number): Element {\n let total = 0;\n for (const categoryName in aggregatedStats) {\n total += aggregatedStats[categoryName];\n }\n\n const element = document.createElement('div');\n element.classList.add('timeline-details-view-pie-chart-wrapper');\n element.classList.add('hbox');\n\n const pieChart = new PerfUI.PieChart.PieChart();\n const slices: {\n value: number,\n color: string,\n title: string,\n }[] = [];\n\n function appendLegendRow(name: string, title: string, value: number, color: string): void {\n if (!value) {\n return;\n }\n slices.push({value, color, title});\n }\n\n // In case of self time, first add self, then children of the same category.\n if (selfCategory) {\n if (selfTime) {\n appendLegendRow(\n selfCategory.name, i18nString(UIStrings.sSelf, {PH1: selfCategory.title}), selfTime,\n selfCategory.getCSSValue());\n }\n // Children of the same category.\n const categoryTime = aggregatedStats[selfCategory.name];\n const value = categoryTime - (selfTime || 0);\n if (value > 0) {\n appendLegendRow(\n selfCategory.name, i18nString(UIStrings.sChildren, {PH1: selfCategory.title}), value,\n selfCategory.getCSSValue());\n }\n }\n\n // Add other categories.\n for (const categoryName in TimelineComponents.EntryStyles.getCategoryStyles()) {\n const category = TimelineComponents.EntryStyles\n .getCategoryStyles()[categoryName as keyof TimelineComponents.EntryStyles.CategoryPalette];\n if (categoryName === selfCategory?.name) {\n // Do not add an entry for this event's self category because 2\n // entries for it where added just before this for loop (for\n // self and children times).\n continue;\n }\n appendLegendRow(category.name, category.title, aggregatedStats[category.name], category.getCSSValue());\n }\n\n pieChart.data = {\n chartName: i18nString(UIStrings.timeSpentInRendering),\n size: 110,\n formatter: (value: number) => i18n.TimeUtilities.preciseMillisToString(value),\n showLegend: true,\n total,\n slices,\n };\n const pieChartContainer = element.createChild('div', 'vbox');\n pieChartContainer.appendChild(pieChart);\n\n return element;\n }\n\n static generateDetailsContentForFrame(\n frame: Trace.Types.Events.LegacyTimelineFrame, filmStrip: Trace.Extras.FilmStrip.Data|null,\n filmStripFrame: Trace.Extras.FilmStrip.Frame|null): DocumentFragment {\n const contentHelper = new TimelineDetailsContentHelper(null, null);\n contentHelper.addSection(i18nString(UIStrings.frame));\n\n const duration = TimelineUIUtils.frameDuration(frame);\n contentHelper.appendElementRow(i18nString(UIStrings.duration), duration);\n if (filmStrip && filmStripFrame) {\n const filmStripPreview = document.createElement('div');\n filmStripPreview.classList.add('timeline-filmstrip-preview');\n void UI.UIUtils.loadImage(filmStripFrame.screenshotEvent.args.dataUri)\n .then(image => image && filmStripPreview.appendChild(image));\n contentHelper.appendElementRow('', filmStripPreview);\n filmStripPreview.addEventListener('click', frameClicked.bind(null, filmStrip, filmStripFrame), false);\n }\n\n function frameClicked(filmStrip: Trace.Extras.FilmStrip.Data, filmStripFrame: Trace.Extras.FilmStrip.Frame): void {\n PerfUI.FilmStripView.Dialog.fromFilmStrip(filmStrip, filmStripFrame.index);\n }\n\n return contentHelper.fragment;\n }\n\n static frameDuration(frame: Trace.Types.Events.LegacyTimelineFrame): Element {\n const offsetMilli = Trace.Helpers.Timing.microSecondsToMilliseconds(frame.startTimeOffset);\n const durationMilli = Trace.Helpers.Timing.microSecondsToMilliseconds(\n Trace.Types.Timing.MicroSeconds(frame.endTime - frame.startTime));\n\n const durationText = i18nString(UIStrings.sAtSParentheses, {\n PH1: i18n.TimeUtilities.millisToString(durationMilli, true),\n PH2: i18n.TimeUtilities.millisToString(offsetMilli, true),\n });\n return i18n.i18n.getFormatLocalizedString(str_, UIStrings.emptyPlaceholder, {PH1: durationText});\n }\n\n static quadWidth(quad: number[]): number {\n return Math.round(Math.sqrt(Math.pow(quad[0] - quad[2], 2) + Math.pow(quad[1] - quad[3], 2)));\n }\n\n static quadHeight(quad: number[]): number {\n return Math.round(Math.sqrt(Math.pow(quad[0] - quad[6], 2) + Math.pow(quad[1] - quad[7], 2)));\n }\n\n static eventDispatchDesciptors(): EventDispatchTypeDescriptor[] {\n if (eventDispatchDesciptors) {\n return eventDispatchDesciptors;\n }\n const lightOrange = 'hsl(40,100%,80%)';\n const orange = 'hsl(40,100%,50%)';\n const green = 'hsl(90,100%,40%)';\n const purple = 'hsl(256,100%,75%)';\n eventDispatchDesciptors = [\n new EventDispatchTypeDescriptor(\n 1, lightOrange, ['mousemove', 'mouseenter', 'mouseleave', 'mouseout', 'mouseover']),\n new EventDispatchTypeDescriptor(\n 1, lightOrange, ['pointerover', 'pointerout', 'pointerenter', 'pointerleave', 'pointermove']),\n new EventDispatchTypeDescriptor(2, green, ['wheel']),\n new EventDispatchTypeDescriptor(3, orange, ['click', 'mousedown', 'mouseup']),\n new EventDispatchTypeDescriptor(3, orange, ['touchstart', 'touchend', 'touchmove', 'touchcancel']),\n new EventDispatchTypeDescriptor(\n 3, orange, ['pointerdown', 'pointerup', 'pointercancel', 'gotpointercapture', 'lostpointercapture']),\n new EventDispatchTypeDescriptor(3, purple, ['keydown', 'keyup', 'keypress']),\n ];\n return eventDispatchDesciptors;\n }\n\n static markerStyleForEvent(event: Trace.Types.Events.Event): TimelineMarkerStyle {\n const tallMarkerDashStyle = [6, 4];\n const title = TimelineUIUtils.eventTitle(event);\n\n if (event.name !== Trace.Types.Events.Name.NAVIGATION_START &&\n Trace.Helpers.Trace.eventHasCategory(event, Trace.Types.Events.Categories.Console) ||\n Trace.Helpers.Trace.eventHasCategory(event, Trace.Types.Events.Categories.UserTiming)) {\n return {\n title,\n dashStyle: tallMarkerDashStyle,\n lineWidth: 0.5,\n color: Trace.Helpers.Trace.eventHasCategory(event, Trace.Types.Events.Categories.Console) ? 'purple' : 'orange',\n tall: false,\n lowPriority: false,\n };\n }\n let tall = false;\n let color = 'grey';\n switch (event.name) {\n case Trace.Types.Events.Name.NAVIGATION_START:\n color = '#FF9800';\n tall = true;\n break;\n case Trace.Types.Events.Name.FRAME_STARTED_LOADING:\n color = 'green';\n tall = true;\n break;\n case Trace.Types.Events.Name.MARK_DOM_CONTENT:\n color = '#0867CB';\n tall = true;\n break;\n case Trace.Types.Events.Name.MARK_LOAD:\n color = '#B31412';\n tall = true;\n break;\n case Trace.Types.Events.Name.MARK_FIRST_PAINT:\n color = '#228847';\n tall = true;\n break;\n case Trace.Types.Events.Name.MARK_FCP:\n color = '#1A6937';\n tall = true;\n break;\n case Trace.Types.Events.Name.MARK_LCP_CANDIDATE:\n color = '#1A3422';\n tall = true;\n break;\n case Trace.Types.Events.Name.TIME_STAMP:\n color = 'orange';\n break;\n }\n return {\n title,\n dashStyle: tallMarkerDashStyle,\n lineWidth: 0.5,\n color,\n tall,\n lowPriority: false,\n };\n }\n\n static colorForId(id: string): string {\n if (!colorGenerator) {\n colorGenerator =\n new Common.Color.Generator({min: 30, max: 330, count: undefined}, {min: 50, max: 80, count: 3}, 85);\n colorGenerator.setColorForID('', '#f2ecdc');\n }\n return colorGenerator.colorForID(id);\n }\n\n static displayNameForFrame(frame: Trace.Types.Events.TraceFrame, trimAt: number = 80): string {\n const url = frame.url as Platform.DevToolsPath.UrlString;\n return Common.ParsedURL.schemeIs(url, 'about:') ? `\"${Platform.StringUtilities.trimMiddle(frame.name, trimAt)}\"` :\n frame.url.slice(0, trimAt);\n }\n}\n\nexport const aggregatedStatsKey = Symbol('aggregatedStats');\n\nexport const previewElementSymbol = Symbol('previewElement');\n\nexport class EventDispatchTypeDescriptor {\n priority: number;\n color: string;\n eventTypes: string[];\n\n constructor(priority: number, color: string, eventTypes: string[]) {\n this.priority = priority;\n this.color = color;\n this.eventTypes = eventTypes;\n }\n}\n\nexport class TimelineDetailsContentHelper {\n fragment: DocumentFragment;\n private linkifierInternal: LegacyComponents.Linkifier.Linkifier|null;\n private target: SDK.Target.Target|null;\n element: HTMLDivElement;\n private tableElement: HTMLElement;\n\n constructor(target: SDK.Target.Target|null, linkifier: LegacyComponents.Linkifier.Linkifier|null) {\n this.fragment = document.createDocumentFragment();\n\n this.linkifierInternal = linkifier;\n this.target = target;\n\n this.element = document.createElement('div');\n this.element.classList.add('timeline-details-view-block');\n this.tableElement = this.element.createChild('div', 'vbox timeline-details-chip-body');\n this.fragment.appendChild(this.element);\n }\n\n addSection(title: string, swatchColor?: string): void {\n if (!this.tableElement.hasChildNodes()) {\n this.element.removeChildren();\n } else {\n this.element = document.createElement('div');\n this.element.classList.add('timeline-details-view-block');\n this.fragment.appendChild(this.element);\n }\n\n if (title) {\n const titleElement = this.element.createChild('div', 'timeline-details-chip-title');\n if (swatchColor) {\n titleElement.createChild('div').style.backgroundColor = swatchColor;\n }\n UI.UIUtils.createTextChild(titleElement, title);\n }\n\n this.tableElement = this.element.createChild('div', 'vbox timeline-details-chip-body');\n this.fragment.appendChild(this.element);\n }\n\n linkifier(): LegacyComponents.Linkifier.Linkifier|null {\n return this.linkifierInternal;\n }\n\n appendTextRow(title: string, value: string|number|boolean): void {\n const rowElement = this.tableElement.createChild('div', 'timeline-details-view-row');\n rowElement.createChild('div', 'timeline-details-view-row-title').textContent = title;\n rowElement.createChild('div', 'timeline-details-view-row-value').textContent = value.toString();\n }\n\n appendElementRow(title: string, content: string|Node, isWarning?: boolean, isStacked?: boolean): void {\n const rowElement = this.tableElement.createChild('div', 'timeline-details-view-row');\n rowElement.setAttribute('data-row-title', title);\n if (isWarning) {\n rowElement.classList.add('timeline-details-warning');\n }\n if (isStacked) {\n rowElement.classList.add('timeline-details-stack-values');\n }\n const titleElement = rowElement.createChild('div', 'timeline-details-view-row-title');\n titleElement.textContent = title;\n const valueElement = rowElement.createChild('div', 'timeline-details-view-row-value');\n if (content instanceof Node) {\n valueElement.appendChild(content);\n } else {\n UI.UIUtils.createTextChild(valueElement, content || '');\n }\n }\n\n appendLocationRow(title: string, url: string, startLine: number, startColumn?: number): void {\n if (!this.linkifierInternal) {\n return;\n }\n\n const options = {\n tabStop: true,\n columnNumber: startColumn,\n showColumnNumber: true,\n inlineFrameIndex: 0,\n };\n const link = this.linkifierInternal.maybeLinkifyScriptLocation(\n this.target, null, url as Platform.DevToolsPath.UrlString, startLine, options);\n if (!link) {\n return;\n }\n this.appendElementRow(title, link);\n }\n\n appendLocationRange(title: string, url: Platform.DevToolsPath.UrlString, startLine: number, endLine?: number): void {\n if (!this.linkifierInternal || !this.target) {\n return;\n }\n const locationContent = document.createElement('span');\n const link = this.linkifierInternal.maybeLinkifyScriptLocation(\n this.target, null, url, startLine, {tabStop: true, inlineFrameIndex: 0});\n if (!link) {\n return;\n }\n locationContent.appendChild(link);\n UI.UIUtils.createTextChild(\n locationContent, Platform.StringUtilities.sprintf(' [%s…%s]', startLine + 1, (endLine || 0) + 1 || ''));\n this.appendElementRow(title, locationContent);\n }\n\n createChildStackTraceElement(stackTrace: Protocol.Runtime.StackTrace): void {\n if (!this.linkifierInternal) {\n return;\n }\n\n const stackTraceElement =\n this.tableElement.createChild('div', 'timeline-details-view-row timeline-details-stack-values');\n const callFrameContents = LegacyComponents.JSPresentationUtils.buildStackTracePreviewContents(\n this.target, this.linkifierInternal, {stackTrace, tabStops: true, showColumnNumber: true});\n stackTraceElement.appendChild(callFrameContents.element);\n }\n}\n\nexport const categoryBreakdownCacheSymbol = Symbol('categoryBreakdownCache');\nexport interface TimelineMarkerStyle {\n title: string;\n color: string;\n lineWidth: number;\n dashStyle: number[];\n tall: boolean;\n lowPriority: boolean;\n}\n\n/**\n * Given a particular event, this method can adjust its timestamp by\n * substracting the timestamp of the previous navigation. This helps in cases\n * where the user has navigated multiple times in the trace, so that we can show\n * the LCP (for example) relative to the last navigation.\n **/\nexport function timeStampForEventAdjustedForClosestNavigationIfPossible(\n event: Trace.Types.Events.Event,\n parsedTrace: Trace.Handlers.Types.ParsedTrace|null): Trace.Types.Timing.MilliSeconds {\n if (!parsedTrace) {\n const {startTime} = Trace.Helpers.Timing.eventTimingsMilliSeconds(event);\n return startTime;\n }\n\n const time = Trace.Helpers.Timing.timeStampForEventAdjustedByClosestNavigation(\n event,\n parsedTrace.Meta.traceBounds,\n parsedTrace.Meta.navigationsByNavigationId,\n parsedTrace.Meta.navigationsByFrameId,\n );\n return Trace.Helpers.Timing.microSecondsToMilliseconds(time);\n}\n\n/**\n * Determines if an event is potentially a marker event. A marker event here\n * is a single moment in time that we want to highlight on the timeline, such as\n * the LCP time. This method does not filter out events: for example, it treats\n * every LCP Candidate event as a potential marker event.\n **/\nexport function isMarkerEvent(parsedTrace: Trace.Handlers.Types.ParsedTrace, event: Trace.Types.Events.Event): boolean {\n const {Name} = Trace.Types.Events;\n\n if (event.name === Name.TIME_STAMP) {\n return true;\n }\n\n if (Trace.Types.Events.isFirstContentfulPaint(event) || Trace.Types.Events.isFirstPaint(event)) {\n return event.args.frame === parsedTrace.Meta.mainFrameId;\n }\n\n if (Trace.Types.Events.isMarkDOMContent(event) || Trace.Types.Events.isMarkLoad(event) ||\n Trace.Types.Events.isLargestContentfulPaintCandidate(event)) {\n // isOutermostMainFrame was added in 2022, so we fallback to isMainFrame\n // for older traces.\n if (!event.args.data) {\n return false;\n }\n const {isOutermostMainFrame, isMainFrame} = event.args.data;\n if (typeof isOutermostMainFrame !== 'undefined') {\n // If isOutermostMainFrame is defined we want to use that and not\n // fallback to isMainFrame, even if isOutermostMainFrame is false. Hence\n // this check.\n return isOutermostMainFrame;\n }\n return Boolean(isMainFrame);\n }\n\n return false;\n}\n\nfunction getEventSelfTime(\n event: Trace.Types.Events.Event, parsedTrace: Trace.Handlers.Types.ParsedTrace): Trace.Types.Timing.MilliSeconds {\n const mapToUse = Trace.Types.Extensions.isSyntheticExtensionEntry(event) ?\n parsedTrace.ExtensionTraceData.entryToNode :\n parsedTrace.Renderer.entryToNode;\n const selfTime = mapToUse.get(event)?.selfTime;\n return selfTime ? Trace.Helpers.Timing.microSecondsToMilliseconds(selfTime) : Trace.Types.Timing.MilliSeconds(0);\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimelineUIUtils.test.js b/public/panels/timeline/TimelineUIUtils.test.js index ef584b512..8f6f84a0e 100644 --- a/public/panels/timeline/TimelineUIUtils.test.js +++ b/public/panels/timeline/TimelineUIUtils.test.js @@ -4,7 +4,7 @@ import * as Common from '../../core/common/common.js'; import * as SDK from '../../core/sdk/sdk.js'; import * as Bindings from '../../models/bindings/bindings.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as Workspace from '../../models/workspace/workspace.js'; import * as Elements from '../../panels/elements/elements.js'; import { doubleRaf, renderElementIntoDOM } from '../../testing/DOMHelpers.js'; @@ -41,30 +41,30 @@ describeWithMockConnection('TimelineUIUtils', function () { clearMockConnectionResponseHandler('DOM.pushNodesByBackendIdsToFrontend'); }); it('creates top frame location text for function calls', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz'); - const functionCallEvent = traceData.Renderer.allTraceEntries.find(TraceEngine.Types.TraceEvents.isTraceEventFunctionCall); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz'); + const functionCallEvent = parsedTrace.Renderer.allTraceEntries.find(Trace.Types.Events.isFunctionCall); assert.isOk(functionCallEvent); - assert.strictEqual('chrome-extension://blijaeebfebmkmekmdnehcmmcjnblkeo/lib/utils.js:11:43', await Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsTextForTraceEvent(functionCallEvent, traceData)); + assert.strictEqual('chrome-extension://blijaeebfebmkmekmdnehcmmcjnblkeo/lib/utils.js:11:43', await Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsTextForTraceEvent(functionCallEvent, parsedTrace)); }); it('creates top frame location text as a fallback', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const timerInstallEvent = traceData.Renderer.allTraceEntries.find(TraceEngine.Types.TraceEvents.isTraceEventTimerInstall); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const timerInstallEvent = parsedTrace.Renderer.allTraceEntries.find(Trace.Types.Events.isTimerInstall); assert.isOk(timerInstallEvent); - assert.strictEqual('https://web.dev/js/index-7b6f3de4.js:96:533', await Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsTextForTraceEvent(timerInstallEvent, traceData)); + assert.strictEqual('https://web.dev/js/index-7b6f3de4.js:96:533', await Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsTextForTraceEvent(timerInstallEvent, parsedTrace)); }); describe('script location as an URL', function () { it('makes the script location of a call frame a full URL when the inspected target is not the same the call frame was taken from (e.g. a loaded file)', async function () { // The actual trace doesn't matter here, just need one so we can pass // it into buildDetailsNodeForTraceEvent - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); const fakeFunctionCall = { - name: "FunctionCall" /* TraceEngine.Types.TraceEvents.KnownEventName.FUNCTION_CALL */, - ph: "X" /* TraceEngine.Types.TraceEvents.Phase.COMPLETE */, + name: "FunctionCall" /* Trace.Types.Events.Name.FUNCTION_CALL */, + ph: "X" /* Trace.Types.Events.Phase.COMPLETE */, cat: 'devtools-timeline', - dur: TraceEngine.Types.Timing.MicroSeconds(100), - ts: TraceEngine.Types.Timing.MicroSeconds(100), - pid: TraceEngine.Types.TraceEvents.ProcessID(1), - tid: TraceEngine.Types.TraceEvents.ThreadID(1), + dur: Trace.Types.Timing.MicroSeconds(100), + ts: Trace.Types.Timing.MicroSeconds(100), + pid: Trace.Types.Events.ProcessID(1), + tid: Trace.Types.Events.ThreadID(1), args: { data: { functionName: 'test', @@ -76,7 +76,7 @@ describeWithMockConnection('TimelineUIUtils', function () { }, }; target.setInspectedURL('https://not-google.com'); - const node = await Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsNodeForTraceEvent(fakeFunctionCall, target, new Components.Linkifier.Linkifier(), false, traceData); + const node = await Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsNodeForTraceEvent(fakeFunctionCall, target, new Components.Linkifier.Linkifier(), false, parsedTrace); if (!node) { throw new Error('Node was unexpectedly null'); } @@ -85,15 +85,15 @@ describeWithMockConnection('TimelineUIUtils', function () { it('makes the script location of a call frame a script name when the inspected target is the one the call frame was taken from', async function () { // The actual trace doesn't matter here, just need one so we can pass // it into buildDetailsNodeForTraceEvent - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); const fakeFunctionCall = { - name: "FunctionCall" /* TraceEngine.Types.TraceEvents.KnownEventName.FUNCTION_CALL */, - ph: "X" /* TraceEngine.Types.TraceEvents.Phase.COMPLETE */, + name: "FunctionCall" /* Trace.Types.Events.Name.FUNCTION_CALL */, + ph: "X" /* Trace.Types.Events.Phase.COMPLETE */, cat: 'devtools-timeline', - dur: TraceEngine.Types.Timing.MicroSeconds(100), - ts: TraceEngine.Types.Timing.MicroSeconds(100), - pid: TraceEngine.Types.TraceEvents.ProcessID(1), - tid: TraceEngine.Types.TraceEvents.ThreadID(1), + dur: Trace.Types.Timing.MicroSeconds(100), + ts: Trace.Types.Timing.MicroSeconds(100), + pid: Trace.Types.Events.ProcessID(1), + tid: Trace.Types.Events.ThreadID(1), args: { data: { functionName: 'test', @@ -105,7 +105,7 @@ describeWithMockConnection('TimelineUIUtils', function () { }, }; target.setInspectedURL('https://google.com'); - const node = await Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsNodeForTraceEvent(fakeFunctionCall, target, new Components.Linkifier.Linkifier(), false, traceData); + const node = await Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsNodeForTraceEvent(fakeFunctionCall, target, new Components.Linkifier.Linkifier(), false, parsedTrace); if (!node) { throw new Error('Node was unexpectedly null'); } @@ -187,7 +187,7 @@ describeWithMockConnection('TimelineUIUtils', function () { // map however the current status of the source map helpers makes // it difficult to do so. const columnNumber = 51; - const profileCall = makeProfileCall('function', 10, 100, TraceEngine.Types.TraceEvents.ProcessID(1), TraceEngine.Types.TraceEvents.ThreadID(1)); + const profileCall = makeProfileCall('function', 10, 100, Trace.Types.Events.ProcessID(1), Trace.Types.Events.ThreadID(1)); profileCall.callFrame = { columnNumber, functionName: 'minified', @@ -201,14 +201,14 @@ describeWithMockConnection('TimelineUIUtils', function () { workerURLById: new Map(), }; // This only includes data used in the SourceMapsResolver - const traceData = { + const parsedTrace = { Samples: makeMockSamplesHandlerData([profileCall]), Workers: workersData, }; - const resolver = new Timeline.SourceMapsResolver.SourceMapsResolver(traceData); + const resolver = new Timeline.SourceMapsResolver.SourceMapsResolver(parsedTrace); await resolver.install(); const linkifier = new Components.Linkifier.Linkifier(); - const node = await Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsNodeForTraceEvent(profileCall, target, linkifier, true, traceData); + const node = await Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsNodeForTraceEvent(profileCall, target, linkifier, true, parsedTrace); if (!node) { throw new Error('Node was unexpectedly null'); } @@ -217,34 +217,33 @@ describeWithMockConnection('TimelineUIUtils', function () { }); describe('adjusting timestamps for events and navigations', function () { it('adjusts the time for a DCL event after a navigation', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const mainFrameID = traceData.Meta.mainFrameId; - const dclEvent = traceData.PageLoadMetrics.allMarkerEvents.find(event => { - return TraceEngine.Types.TraceEvents.isTraceEventMarkDOMContent(event) && - event.args.data?.frame === mainFrameID; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const mainFrameID = parsedTrace.Meta.mainFrameId; + const dclEvent = parsedTrace.PageLoadMetrics.allMarkerEvents.find(event => { + return Trace.Types.Events.isMarkDOMContent(event) && event.args.data?.frame === mainFrameID; }); if (!dclEvent) { throw new Error('Could not find DCL event'); } - const traceMinBound = traceData.Meta.traceBounds.min; + const traceMinBound = parsedTrace.Meta.traceBounds.min; // Round the time to 2DP to avoid needlessly long expectation numbers! - const unadjustedStartTimeMilliseconds = TraceEngine.Helpers.Timing - .microSecondsToMilliseconds(TraceEngine.Types.Timing.MicroSeconds(dclEvent.ts - traceMinBound)) + const unadjustedStartTimeMilliseconds = Trace.Helpers.Timing + .microSecondsToMilliseconds(Trace.Types.Timing.MicroSeconds(dclEvent.ts - traceMinBound)) .toFixed(2); assert.strictEqual(unadjustedStartTimeMilliseconds, String(190.79)); - const adjustedTime = Timeline.TimelineUIUtils.timeStampForEventAdjustedForClosestNavigationIfPossible(dclEvent, traceData); + const adjustedTime = Timeline.TimelineUIUtils.timeStampForEventAdjustedForClosestNavigationIfPossible(dclEvent, parsedTrace); assert.strictEqual(adjustedTime.toFixed(2), String(178.92)); }); it('can adjust the times for events that are not PageLoad markers', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'user-timings.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'user-timings.json.gz'); // Use a performance.mark event. Exact event is unimportant except that // it should not be a Page Load event as those are covered by the tests // above. - const userMark = traceData.UserTimings.performanceMarks.find(event => event.name === 'mark1'); + const userMark = parsedTrace.UserTimings.performanceMarks.find(event => event.name === 'mark1'); if (!userMark) { throw new Error('Could not find user mark'); } - const adjustedMarkTime = Timeline.TimelineUIUtils.timeStampForEventAdjustedForClosestNavigationIfPossible(userMark, traceData); + const adjustedMarkTime = Timeline.TimelineUIUtils.timeStampForEventAdjustedForClosestNavigationIfPossible(userMark, parsedTrace); assert.strictEqual(adjustedMarkTime.toFixed(2), String(79.88)); }); }); @@ -347,32 +346,32 @@ describeWithMockConnection('TimelineUIUtils', function () { assert.strictEqual('var(--app-color-scripting)', cssVariable); }); it('treats the v8.parseOnBackgroundWaiting as scripting even though it would usually be idle', function () { - const event = makeCompleteEvent("v8.parseOnBackgroundWaiting" /* TraceEngine.Types.TraceEvents.KnownEventName.STREAMING_COMPILE_SCRIPT_WAITING */, 1, 1, 'v8,devtools.timeline,disabled-by-default-v8.compile'); + const event = makeCompleteEvent("v8.parseOnBackgroundWaiting" /* Trace.Types.Events.Name.STREAMING_COMPILE_SCRIPT_WAITING */, 1, 1, 'v8,devtools.timeline,disabled-by-default-v8.compile'); assert.strictEqual('rgb(2 2 2)', Timeline.TimelineUIUtils.TimelineUIUtils.eventColor(event)); }); it('assigns the correct color to the swatch of an event\'s title', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'lcp-web-font.json.gz'); - const events = traceData.Renderer.allTraceEntries; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'lcp-web-font.json.gz'); + const events = parsedTrace.Renderer.allTraceEntries; const task = events.find(event => { return event.name.includes('RunTask'); }); if (!task) { throw new Error('Could not find expected event.'); } - const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(traceData, task, new Components.Linkifier.Linkifier(), false); + const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(parsedTrace, task, new Components.Linkifier.Linkifier(), false); const titleSwatch = details.querySelector('.timeline-details-chip-title div'); assert.strictEqual(titleSwatch?.style.backgroundColor, 'rgb(10, 10, 10)'); }); }); describe('testContentMatching', () => { it('matches call frame events based on a regular expression and the contents of the event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'react-hello-world.json.gz'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'react-hello-world.json.gz'); // Find an event from the trace that represents some work that React did. This // event is not chosen for any particular reason other than it was the example // used in the bug report: crbug.com/1484504 - const mainThread = getMainThread(traceData.Renderer); + const mainThread = getMainThread(parsedTrace.Renderer); const performConcurrentWorkEvent = mainThread.entries.find(entry => { - if (TraceEngine.Types.TraceEvents.isProfileCall(entry)) { + if (Trace.Types.Events.isProfileCall(entry)) { return entry.callFrame.functionName === 'performConcurrentWorkOnRoot'; } return false; @@ -380,19 +379,19 @@ describeWithMockConnection('TimelineUIUtils', function () { if (!performConcurrentWorkEvent) { throw new Error('Could not find expected event'); } - assert.isTrue(Timeline.TimelineUIUtils.TimelineUIUtils.testContentMatching(performConcurrentWorkEvent, /perfo/, traceData)); + assert.isTrue(Timeline.TimelineUIUtils.TimelineUIUtils.testContentMatching(performConcurrentWorkEvent, /perfo/, parsedTrace)); }); }); describe('traceEventDetails', function () { it('shows the interaction ID and INP breakdown metrics for a given interaction', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz'); - const interactionEvent = traceData.UserInteractions.interactionEventsWithNoNesting.find(entry => { + const { parsedTrace } = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz'); + const interactionEvent = parsedTrace.UserInteractions.interactionEventsWithNoNesting.find(entry => { return entry.dur === 979974 && entry.type === 'click'; }); if (!interactionEvent) { throw new Error('Could not find expected event'); } - const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(traceData, interactionEvent, new Components.Linkifier.Linkifier(), false); + const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(parsedTrace, interactionEvent, new Components.Linkifier.Linkifier(), false); const rowData = getRowDataForDetailsElement(details); assert.deepEqual(rowData, [ { @@ -418,14 +417,14 @@ describeWithMockConnection('TimelineUIUtils', function () { ]); }); it('renders all event data for a generic trace', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'generic-about-tracing.json.gz'); - const event = traceData.Renderer.allTraceEntries.find(entry => { + const { parsedTrace } = await TraceLoader.traceEngine(this, 'generic-about-tracing.json.gz'); + const event = parsedTrace.Renderer.allTraceEntries.find(entry => { return entry.name === 'ThreadControllerImpl::RunTask'; }); if (!event) { throw new Error('Could not find event.'); } - const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(traceData, event, new Components.Linkifier.Linkifier(), false); + const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(parsedTrace, event, new Components.Linkifier.Linkifier(), false); const rowData = getRowDataForDetailsElement(details); assert.deepEqual(rowData, [ { @@ -436,8 +435,8 @@ describeWithMockConnection('TimelineUIUtils', function () { ]); }); it('renders invalidations correctly', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'style-invalidation-change-attribute.json.gz'); - TraceLoader.initTraceBoundsManager(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'style-invalidation-change-attribute.json.gz'); + TraceLoader.initTraceBoundsManager(parsedTrace); // Set up a fake DOM so that we can request nodes by backend Ids (even // though we return none, we need to mock these calls else the frontend // will not work.) @@ -448,14 +447,14 @@ describeWithMockConnection('TimelineUIUtils', function () { nodeIds: [], }; }); - const updateLayoutTreeEvent = traceData.Renderer.allTraceEntries.find(event => { - return TraceEngine.Types.TraceEvents.isTraceEventUpdateLayoutTree(event) && + const updateLayoutTreeEvent = parsedTrace.Renderer.allTraceEntries.find(event => { + return Trace.Types.Events.isUpdateLayoutTree(event) && event.args.beginData?.stackTrace?.[0].functionName === 'testFuncs.changeAttributeAndDisplay'; }); if (!updateLayoutTreeEvent) { throw new Error('Could not find update layout tree event'); } - const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(traceData, updateLayoutTreeEvent, new Components.Linkifier.Linkifier(), false); + const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(parsedTrace, updateLayoutTreeEvent, new Components.Linkifier.Linkifier(), false); const rowData = getRowDataForDetailsElement(details); assert.deepEqual(rowData, [ { @@ -502,12 +501,12 @@ describeWithMockConnection('TimelineUIUtils', function () { ]); }); it('renders details for performance.mark', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'user-timings-details.json.gz'); - const mark = traceData.UserTimings.performanceMarks[0]; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'user-timings-details.json.gz'); + const mark = parsedTrace.UserTimings.performanceMarks[0]; if (!mark) { throw new Error('Could not find expected event'); } - const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(traceData, mark, new Components.Linkifier.Linkifier(), false); + const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(parsedTrace, mark, new Components.Linkifier.Linkifier(), false); const rowData = getRowDataForDetailsElement(details); assert.deepEqual(rowData, [ { @@ -518,12 +517,12 @@ describeWithMockConnection('TimelineUIUtils', function () { ]); }); it('renders details for performance.measure', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'user-timings-details.json.gz'); - const measure = traceData.UserTimings.performanceMeasures[0]; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'user-timings-details.json.gz'); + const measure = parsedTrace.UserTimings.performanceMeasures[0]; if (!measure) { throw new Error('Could not find expected event'); } - const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(traceData, measure, new Components.Linkifier.Linkifier(), false); + const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(parsedTrace, measure, new Components.Linkifier.Linkifier(), false); const rowData = getRowDataForDetailsElement(details); assert.deepEqual(rowData, [ { @@ -537,12 +536,12 @@ describeWithMockConnection('TimelineUIUtils', function () { ]); }); it('renders details for a v8.compile ("Compile Script") event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'user-timings.json.gz'); - const compileEvent = traceData.Renderer.allTraceEntries.find(TraceEngine.Types.TraceEvents.isTraceEventV8Compile); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'user-timings.json.gz'); + const compileEvent = parsedTrace.Renderer.allTraceEntries.find(Trace.Types.Events.isV8Compile); if (!compileEvent) { throw new Error('Could not find expected event'); } - const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(traceData, compileEvent, new Components.Linkifier.Linkifier(), false); + const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(parsedTrace, compileEvent, new Components.Linkifier.Linkifier(), false); const rowData = getRowDataForDetailsElement(details); assert.deepEqual(rowData, [ { @@ -571,8 +570,8 @@ describeWithMockConnection('TimelineUIUtils', function () { await domModel.requestDocument(); domModel.registerNode(domNode2); domNode2.init(docc, false, { nodeName: 'A test node name', nodeId: domID }); - const { traceData } = await TraceLoader.traceEngine(this, 'cls-single-frame.json.gz'); - const layoutShift = traceData.LayoutShifts.clusters[0].events[0]; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'cls-single-frame.json.gz'); + const layoutShift = parsedTrace.LayoutShifts.clusters[0].events[0]; Common.Linkifier.registerLinkifier({ contextTypes() { return [Timeline.CLSLinkifier.CLSRect]; @@ -594,7 +593,7 @@ describeWithMockConnection('TimelineUIUtils', function () { if (!layoutShift) { throw new Error('Could not find LayoutShift event.'); } - const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(traceData, layoutShift, new Components.Linkifier.Linkifier(), false); + const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(parsedTrace, layoutShift, new Components.Linkifier.Linkifier(), false); const rowData = getRowDataForDetailsElement(details); assert.deepEqual(rowData, [ { @@ -612,12 +611,12 @@ describeWithMockConnection('TimelineUIUtils', function () { ]); }); it('renders the details for an extension entry properly', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz'); - const extensionEntry = traceData.ExtensionTraceData.extensionTrackData[1].entriesByTrack['An Extension Track'][0]; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz'); + const extensionEntry = parsedTrace.ExtensionTraceData.extensionTrackData[1].entriesByTrack['An Extension Track'][0]; if (!extensionEntry) { throw new Error('Could not find extension entry.'); } - const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(traceData, extensionEntry, new Components.Linkifier.Linkifier(), false); + const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(parsedTrace, extensionEntry, new Components.Linkifier.Linkifier(), false); const rowData = getRowDataForDetailsElement(details); assert.deepEqual(rowData, [ { @@ -629,12 +628,12 @@ describeWithMockConnection('TimelineUIUtils', function () { ]); }); it('renders the details for an extension marker properly', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz'); - const extensionMark = traceData.ExtensionTraceData.extensionMarkers[0]; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz'); + const extensionMark = parsedTrace.ExtensionTraceData.extensionMarkers[0]; if (!extensionMark) { throw new Error('Could not find extension mark.'); } - const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(traceData, extensionMark, new Components.Linkifier.Linkifier(), false); + const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(parsedTrace, extensionMark, new Components.Linkifier.Linkifier(), false); const rowData = getRowDataForDetailsElement(details); assert.deepEqual(rowData, [ { @@ -653,14 +652,14 @@ describeWithMockConnection('TimelineUIUtils', function () { return Timeline.CLSLinkifier.Linkifier.instance(); }, }); - const { traceData } = await TraceLoader.traceEngine(this, 'simple-js-program.json.gz'); - const [process] = traceData.Renderer.processes.values(); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'simple-js-program.json.gz'); + const [process] = parsedTrace.Renderer.processes.values(); const [thread] = process.threads.values(); - const profileCalls = thread.entries.filter(entry => TraceEngine.Types.TraceEvents.isProfileCall(entry)); + const profileCalls = thread.entries.filter(entry => Trace.Types.Events.isProfileCall(entry)); if (!profileCalls) { throw new Error('Could not find renderer events'); } - const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(traceData, profileCalls[0], new Components.Linkifier.Linkifier(), false); + const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(parsedTrace, profileCalls[0], new Components.Linkifier.Linkifier(), false); const rowData = getRowDataForDetailsElement(details); assert.deepEqual(rowData, [ { @@ -678,12 +677,12 @@ describeWithMockConnection('TimelineUIUtils', function () { return Timeline.CLSLinkifier.Linkifier.instance(); }, }); - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - TraceLoader.initTraceBoundsManager(traceData); - const [process] = traceData.Renderer.processes.values(); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + TraceLoader.initTraceBoundsManager(parsedTrace); + const [process] = parsedTrace.Renderer.processes.values(); const [thread] = process.threads.values(); - const scheduleStyleRecalcs = thread.entries.filter(entry => TraceEngine.Types.TraceEvents.isTraceEventScheduleStyleRecalculation(entry)); - const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(traceData, scheduleStyleRecalcs[1], new Components.Linkifier.Linkifier(), false); + const scheduleStyleRecalcs = thread.entries.filter(entry => Trace.Types.Events.isScheduleStyleRecalculation(entry)); + const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(parsedTrace, scheduleStyleRecalcs[1], new Components.Linkifier.Linkifier(), false); const rowData = getRowDataForDetailsElement(details)[0]; assert.deepEqual(rowData, { title: 'Details', @@ -701,12 +700,12 @@ describeWithMockConnection('TimelineUIUtils', function () { return Timeline.CLSLinkifier.Linkifier.instance(); }, }); - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - TraceLoader.initTraceBoundsManager(traceData); - const [process] = traceData.Renderer.processes.values(); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + TraceLoader.initTraceBoundsManager(parsedTrace); + const [process] = parsedTrace.Renderer.processes.values(); const [thread] = process.threads.values(); - const stylesRecalc = thread.entries.filter(entry => entry.name === "UpdateLayoutTree" /* TraceEngine.Types.TraceEvents.KnownEventName.UPDATE_LAYOUT_TREE */); - const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(traceData, stylesRecalc[3], new Components.Linkifier.Linkifier(), false); + const stylesRecalc = thread.entries.filter(entry => entry.name === "UpdateLayoutTree" /* Trace.Types.Events.Name.UPDATE_LAYOUT_TREE */); + const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(parsedTrace, stylesRecalc[3], new Components.Linkifier.Linkifier(), false); const stackTraceData = getStackTraceForDetailsElement(details); assert.deepEqual(stackTraceData, ['(anonymous) @ web.dev/js/app.js?v=1423cda3:1:183']); }); @@ -719,15 +718,15 @@ describeWithMockConnection('TimelineUIUtils', function () { return Timeline.CLSLinkifier.Linkifier.instance(); }, }); - const { traceData } = await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz'); - TraceLoader.initTraceBoundsManager(traceData); - const [extensionMarker] = traceData.ExtensionTraceData.extensionMarkers.values(); - const [extensionTrackData] = traceData.ExtensionTraceData.extensionTrackData.values(); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz'); + TraceLoader.initTraceBoundsManager(parsedTrace); + const [extensionMarker] = parsedTrace.ExtensionTraceData.extensionMarkers.values(); + const [extensionTrackData] = parsedTrace.ExtensionTraceData.extensionTrackData.values(); const [[extensionTrackEntry]] = Object.values(extensionTrackData.entriesByTrack); - const markerDetails = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(traceData, extensionMarker, new Components.Linkifier.Linkifier(), false); + const markerDetails = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(parsedTrace, extensionMarker, new Components.Linkifier.Linkifier(), false); const markerStackTraceData = getStackTraceForDetailsElement(markerDetails); assert.deepEqual(markerStackTraceData, ['mockChangeDetection @ localhost:3000/static/js/bundle.js:295:17']); - const trackEntryDetails = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(traceData, extensionTrackEntry, new Components.Linkifier.Linkifier(), false); + const trackEntryDetails = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(parsedTrace, extensionTrackEntry, new Components.Linkifier.Linkifier(), false); const trackEntryStackTraceData = getStackTraceForDetailsElement(trackEntryDetails); assert.deepEqual(trackEntryStackTraceData, ['appendACorgi @ localhost:3000/static/js/bundle.js:274:19']); }); @@ -740,25 +739,25 @@ describeWithMockConnection('TimelineUIUtils', function () { return Timeline.CLSLinkifier.Linkifier.instance(); }, }); - const { traceData } = await TraceLoader.traceEngine(this, 'user-timings.json.gz'); - TraceLoader.initTraceBoundsManager(traceData); - const [performanceMark] = traceData.UserTimings.performanceMarks.values(); - const [performanceMeasure] = traceData.UserTimings.performanceMeasures.values(); - const markDetails = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(traceData, performanceMark, new Components.Linkifier.Linkifier(), false); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'user-timings.json.gz'); + TraceLoader.initTraceBoundsManager(parsedTrace); + const [performanceMark] = parsedTrace.UserTimings.performanceMarks.values(); + const [performanceMeasure] = parsedTrace.UserTimings.performanceMeasures.values(); + const markDetails = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(parsedTrace, performanceMark, new Components.Linkifier.Linkifier(), false); const markStackTraceData = getStackTraceForDetailsElement(markDetails); assert.deepEqual(markStackTraceData, ['addTimingMark @ chromedevtools.github.io/performance-stories/user-timings/app.js:2:1']); - const measureDetails = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(traceData, performanceMeasure, new Components.Linkifier.Linkifier(), false); + const measureDetails = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(parsedTrace, performanceMeasure, new Components.Linkifier.Linkifier(), false); const measureStackTraceData = getStackTraceForDetailsElement(measureDetails); assert.deepEqual(measureStackTraceData, ['addTimingMeasure @ chromedevtools.github.io/performance-stories/user-timings/app.js:2:1']); }); it('renders the warning for a trace event in its details', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'simple-js-program.json.gz'); - const events = traceData.Renderer.allTraceEntries; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'simple-js-program.json.gz'); + const events = parsedTrace.Renderer.allTraceEntries; const longTask = events.find(e => (e.dur || 0) > 1_000_000); if (!longTask) { throw new Error('Could not find Long Task event.'); } - const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(traceData, longTask, new Components.Linkifier.Linkifier(), false); + const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(parsedTrace, longTask, new Components.Linkifier.Linkifier(), false); const rowData = getRowDataForDetailsElement(details); assert.deepEqual(rowData, [ { @@ -768,13 +767,13 @@ describeWithMockConnection('TimelineUIUtils', function () { ]); }); it('shows information for the WebSocketCreate initiator when viewing a WebSocketSendHandshakeRequest event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-sockets.json.gz'); - TraceLoader.initTraceBoundsManager(traceData); - const sendHandshake = traceData.Renderer.allTraceEntries.find(TraceEngine.Types.TraceEvents.isTraceEventWebSocketSendHandshakeRequest); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-sockets.json.gz'); + TraceLoader.initTraceBoundsManager(parsedTrace); + const sendHandshake = parsedTrace.Renderer.allTraceEntries.find(Trace.Types.Events.isWebSocketSendHandshakeRequest); if (!sendHandshake) { throw new Error('Could not find handshake event.'); } - const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(traceData, sendHandshake, new Components.Linkifier.Linkifier(), false); + const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(parsedTrace, sendHandshake, new Components.Linkifier.Linkifier(), false); const rowData = getRowDataForDetailsElement(details); const expectedRowData = [ { title: 'URL', value: 'wss://socketsbay.com/wss/v2/1/demo/' }, @@ -786,13 +785,13 @@ describeWithMockConnection('TimelineUIUtils', function () { assert.deepEqual(rowData, expectedRowData); }); it('shows information for the events initiated by WebSocketCreate when viewing a WebSocketCreate event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-sockets.json.gz'); - TraceLoader.initTraceBoundsManager(traceData); - const sendHandshake = traceData.Renderer.allTraceEntries.find(TraceEngine.Types.TraceEvents.isTraceEventWebSocketCreate); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-sockets.json.gz'); + TraceLoader.initTraceBoundsManager(parsedTrace); + const sendHandshake = parsedTrace.Renderer.allTraceEntries.find(Trace.Types.Events.isWebSocketCreate); if (!sendHandshake) { throw new Error('Could not find handshake event.'); } - const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(traceData, sendHandshake, new Components.Linkifier.Linkifier(), false); + const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(parsedTrace, sendHandshake, new Components.Linkifier.Linkifier(), false); const rowData = getRowDataForDetailsElement(details); const expectedRowData = [ { title: 'URL', value: 'wss://socketsbay.com/wss/v2/1/demo/' }, @@ -804,12 +803,12 @@ describeWithMockConnection('TimelineUIUtils', function () { assert.deepEqual(rowData, expectedRowData); }); it('shows the aggregated time information for an event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const event = traceData.Renderer.allTraceEntries.find(e => e.ts === 1020034919877 && e.name === 'RunTask'); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const event = parsedTrace.Renderer.allTraceEntries.find(e => e.ts === 1020034919877 && e.name === 'RunTask'); if (!event) { throw new Error('Could not find renderer events'); } - const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(traceData, event, new Components.Linkifier.Linkifier(), true); + const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(parsedTrace, event, new Components.Linkifier.Linkifier(), true); const pieChartData = getPieChartDataForDetailsElement(details); const expectedPieChartData = [ { title: 'System (self)', value: '2\u00A0ms' }, @@ -821,10 +820,10 @@ describeWithMockConnection('TimelineUIUtils', function () { assert.deepEqual(pieChartData, expectedPieChartData); }); it('renders details for synthetic server timings', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'server-timings.json.gz'); - const serverTimings = traceData.ServerTimings.serverTimings; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'server-timings.json.gz'); + const serverTimings = parsedTrace.ServerTimings.serverTimings; const serverTiming = serverTimings[0]; - const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(traceData, serverTiming, new Components.Linkifier.Linkifier(), false); + const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(parsedTrace, serverTiming, new Components.Linkifier.Linkifier(), false); const rowData = getRowDataForDetailsElement(details); assert.deepEqual(rowData, [ { @@ -835,12 +834,12 @@ describeWithMockConnection('TimelineUIUtils', function () { }); }); it('can generate details for a frame', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); - const frame = traceData.Frames.frames.at(0); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); + const frame = parsedTrace.Frames.frames.at(0); if (!frame) { throw new Error('Could not find expected frame'); } - const filmStrip = TraceEngine.Extras.FilmStrip.fromTraceData(traceData); + const filmStrip = Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace); const details = Timeline.TimelineUIUtils.TimelineUIUtils.generateDetailsContentForFrame(frame, filmStrip, filmStrip.frames[0]); const container = document.createElement('div'); renderElementIntoDOM(container); @@ -861,19 +860,19 @@ describeWithMockConnection('TimelineUIUtils', function () { }); describe('eventTitle', function () { it('renders the correct title for an EventTiming interaction event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'slow-interaction-button-click.json.gz'); - const interactionEvent = traceData.UserInteractions.interactionEventsWithNoNesting[0]; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'slow-interaction-button-click.json.gz'); + const interactionEvent = parsedTrace.UserInteractions.interactionEventsWithNoNesting[0]; const details = Timeline.TimelineUIUtils.TimelineUIUtils.eventTitle(interactionEvent); assert.deepEqual(details, 'Pointer'); }); it('will use the resolved function name for a profile node that has a sourcemap', async function () { // Timeline.SourceMapsResolver.SourceMapsResolver. - const { traceData } = await TraceLoader.traceEngine(this, 'slow-interaction-button-click.json.gz'); - const mainThread = getMainThread(traceData.Renderer); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'slow-interaction-button-click.json.gz'); + const mainThread = getMainThread(parsedTrace.Renderer); const profileEntry = mainThread.entries.find(entry => { - return TraceEngine.Types.TraceEvents.isProfileCall(entry); + return Trace.Types.Events.isProfileCall(entry); }); - if (!profileEntry || !TraceEngine.Types.TraceEvents.isProfileCall(profileEntry)) { + if (!profileEntry || !Trace.Types.Events.isProfileCall(profileEntry)) { throw new Error('Could not find a profile entry'); } // Fake that we resolved the entry's name from a sourcemap. @@ -884,14 +883,14 @@ describeWithMockConnection('TimelineUIUtils', function () { }); describe('eventStyle', function () { it('returns the correct style for profile calls', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'simple-js-program.json.gz'); - const rendererHandler = traceData.Renderer; + const { parsedTrace } = await TraceLoader.traceEngine(this, 'simple-js-program.json.gz'); + const rendererHandler = parsedTrace.Renderer; if (!rendererHandler) { throw new Error('RendererHandler is undefined'); } const [process] = rendererHandler.processes.values(); const [thread] = process.threads.values(); - const profileCalls = thread.entries.filter(entry => TraceEngine.Types.TraceEvents.isProfileCall(entry)); + const profileCalls = thread.entries.filter(entry => Trace.Types.Events.isProfileCall(entry)); const style = Timeline.TimelineUIUtils.TimelineUIUtils.eventStyle(profileCalls[0]); assert.strictEqual(style.category.name, 'scripting'); assert.strictEqual(style.category.color, 'rgb(250 204 21 / 100%)'); @@ -899,16 +898,16 @@ describeWithMockConnection('TimelineUIUtils', function () { }); describe('statsForTimeRange', () => { it('correctly aggregates up stats', async () => { - const mainThread = TraceEngine.Types.TraceEvents.ThreadID(1); - const pid = TraceEngine.Types.TraceEvents.ProcessID(100); + const mainThread = Trace.Types.Events.ThreadID(1); + const pid = Trace.Types.Events.ProcessID(100); function microsec(x) { - return TraceEngine.Types.Timing.MicroSeconds(x); + return Trace.Types.Timing.MicroSeconds(x); } const events = [ { cat: 'disabled-by-default-devtools.timeline', name: 'TracingStartedInBrowser', - ph: "I" /* TraceEngine.Types.TraceEvents.Phase.INSTANT */, + ph: "I" /* Trace.Types.Events.Phase.INSTANT */, pid, tid: mainThread, ts: microsec(100), @@ -923,7 +922,7 @@ describeWithMockConnection('TimelineUIUtils', function () { { cat: 'disabled-by-default-devtools.timeline', name: 'SetLayerTreeId', - ph: "I" /* TraceEngine.Types.TraceEvents.Phase.INSTANT */, + ph: "I" /* Trace.Types.Events.Phase.INSTANT */, pid, tid: mainThread, ts: microsec(101), @@ -932,7 +931,7 @@ describeWithMockConnection('TimelineUIUtils', function () { { cat: 'toplevel', name: 'Program', - ph: "X" /* TraceEngine.Types.TraceEvents.Phase.COMPLETE */, + ph: "X" /* Trace.Types.Events.Phase.COMPLETE */, ts: microsec(100000), dur: microsec(3000), tid: mainThread, @@ -942,7 +941,7 @@ describeWithMockConnection('TimelineUIUtils', function () { { cat: 'disabled-by-default-devtools.timeline', name: 'FunctionCall', - ph: "X" /* TraceEngine.Types.TraceEvents.Phase.COMPLETE */, + ph: "X" /* Trace.Types.Events.Phase.COMPLETE */, ts: microsec(100500), dur: microsec(1500), tid: mainThread, @@ -952,7 +951,7 @@ describeWithMockConnection('TimelineUIUtils', function () { { cat: 'disabled-by-default-devtools.timeline', name: 'Layout', - ph: "X" /* TraceEngine.Types.TraceEvents.Phase.COMPLETE */, + ph: "X" /* Trace.Types.Events.Phase.COMPLETE */, ts: microsec(101000), dur: microsec(1000), tid: mainThread, @@ -970,7 +969,7 @@ describeWithMockConnection('TimelineUIUtils', function () { { cat: 'toplevel', name: 'Program', - ph: "X" /* TraceEngine.Types.TraceEvents.Phase.COMPLETE */, + ph: "X" /* Trace.Types.Events.Phase.COMPLETE */, ts: microsec(104000), dur: microsec(4000), tid: mainThread, @@ -980,7 +979,7 @@ describeWithMockConnection('TimelineUIUtils', function () { { cat: 'disabled-by-default-devtools.timeline', name: 'FunctionCall', - ph: "X" /* TraceEngine.Types.TraceEvents.Phase.COMPLETE */, + ph: "X" /* Trace.Types.Events.Phase.COMPLETE */, ts: microsec(104000), dur: microsec(1000), tid: mainThread, @@ -990,7 +989,7 @@ describeWithMockConnection('TimelineUIUtils', function () { { cat: 'disabled-by-default-devtools.timeline', name: 'CommitLoad', - ph: "X" /* TraceEngine.Types.TraceEvents.Phase.COMPLETE */, + ph: "X" /* Trace.Types.Events.Phase.COMPLETE */, ts: microsec(105000), dur: microsec(1000), tid: mainThread, @@ -1000,7 +999,7 @@ describeWithMockConnection('TimelineUIUtils', function () { { cat: 'disabled-by-default-devtools.timeline', name: 'Layout', - ph: "X" /* TraceEngine.Types.TraceEvents.Phase.COMPLETE */, + ph: "X" /* Trace.Types.Events.Phase.COMPLETE */, ts: microsec(107000), dur: microsec(1000), tid: mainThread, @@ -1016,14 +1015,14 @@ describeWithMockConnection('TimelineUIUtils', function () { }, }, ]; - const rangeStats101To103 = Timeline.TimelineUIUtils.TimelineUIUtils.statsForTimeRange(events, TraceEngine.Types.Timing.MilliSeconds(101), TraceEngine.Types.Timing.MilliSeconds(103)); + const rangeStats101To103 = Timeline.TimelineUIUtils.TimelineUIUtils.statsForTimeRange(events, Trace.Types.Timing.MilliSeconds(101), Trace.Types.Timing.MilliSeconds(103)); assert.deepEqual(rangeStats101To103, { other: 1, rendering: 1, scripting: 0, idle: 0, }); - const rangeStats104To109 = Timeline.TimelineUIUtils.TimelineUIUtils.statsForTimeRange(events, TraceEngine.Types.Timing.MilliSeconds(104), TraceEngine.Types.Timing.MilliSeconds(109)); + const rangeStats104To109 = Timeline.TimelineUIUtils.TimelineUIUtils.statsForTimeRange(events, Trace.Types.Timing.MilliSeconds(104), Trace.Types.Timing.MilliSeconds(109)); assert.deepEqual(rangeStats104To109, { other: 2, rendering: 1, @@ -1034,54 +1033,54 @@ describeWithMockConnection('TimelineUIUtils', function () { }); describe('isMarkerEvent', () => { it('is true for a timestamp event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz'); - const timestamp = traceData.Renderer.allTraceEntries.find(TraceEngine.Types.TraceEvents.isTraceEventTimeStamp); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz'); + const timestamp = parsedTrace.Renderer.allTraceEntries.find(Trace.Types.Events.isTimeStamp); assert.isOk(timestamp); - assert.isTrue(Timeline.TimelineUIUtils.isMarkerEvent(traceData, timestamp)); + assert.isTrue(Timeline.TimelineUIUtils.isMarkerEvent(parsedTrace, timestamp)); }); it('is true for a Mark First Paint event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz'); - const markFirstPaint = traceData.PageLoadMetrics.allMarkerEvents.find(TraceEngine.Types.TraceEvents.isTraceEventFirstPaint); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz'); + const markFirstPaint = parsedTrace.PageLoadMetrics.allMarkerEvents.find(Trace.Types.Events.isFirstPaint); assert.isOk(markFirstPaint); - assert.isTrue(Timeline.TimelineUIUtils.isMarkerEvent(traceData, markFirstPaint)); + assert.isTrue(Timeline.TimelineUIUtils.isMarkerEvent(parsedTrace, markFirstPaint)); }); it('is true for a Mark FCP event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz'); - const markFCPEvent = traceData.PageLoadMetrics.allMarkerEvents.find(TraceEngine.Types.TraceEvents.isTraceEventFirstContentfulPaint); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz'); + const markFCPEvent = parsedTrace.PageLoadMetrics.allMarkerEvents.find(Trace.Types.Events.isFirstContentfulPaint); assert.isOk(markFCPEvent); - assert.isTrue(Timeline.TimelineUIUtils.isMarkerEvent(traceData, markFCPEvent)); + assert.isTrue(Timeline.TimelineUIUtils.isMarkerEvent(parsedTrace, markFCPEvent)); }); it('is false for a Mark FCP event not on the main frame', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz'); - const markFCPEvent = traceData.PageLoadMetrics.allMarkerEvents.find(TraceEngine.Types.TraceEvents.isTraceEventFirstContentfulPaint); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz'); + const markFCPEvent = parsedTrace.PageLoadMetrics.allMarkerEvents.find(Trace.Types.Events.isFirstContentfulPaint); assert.isOk(markFCPEvent); assert.isOk(markFCPEvent.args); // Now make a copy (so we do not mutate any data) and pretend it is not on the main frame. const copyOfEvent = { ...markFCPEvent, args: { ...markFCPEvent.args } }; copyOfEvent.args.frame = 'not-the-main-frame'; - assert.isFalse(Timeline.TimelineUIUtils.isMarkerEvent(traceData, copyOfEvent)); + assert.isFalse(Timeline.TimelineUIUtils.isMarkerEvent(parsedTrace, copyOfEvent)); }); it('is true for a MarkDOMContent event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz'); - const markDOMContentEvent = traceData.PageLoadMetrics.allMarkerEvents.find(TraceEngine.Types.TraceEvents.isTraceEventMarkDOMContent); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz'); + const markDOMContentEvent = parsedTrace.PageLoadMetrics.allMarkerEvents.find(Trace.Types.Events.isMarkDOMContent); assert.isOk(markDOMContentEvent); - assert.isTrue(Timeline.TimelineUIUtils.isMarkerEvent(traceData, markDOMContentEvent)); + assert.isTrue(Timeline.TimelineUIUtils.isMarkerEvent(parsedTrace, markDOMContentEvent)); }); it('is true for a MarkLoad event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz'); - const markLoadEvent = traceData.PageLoadMetrics.allMarkerEvents.find(TraceEngine.Types.TraceEvents.isTraceEventMarkLoad); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz'); + const markLoadEvent = parsedTrace.PageLoadMetrics.allMarkerEvents.find(Trace.Types.Events.isMarkLoad); assert.isOk(markLoadEvent); - assert.isTrue(Timeline.TimelineUIUtils.isMarkerEvent(traceData, markLoadEvent)); + assert.isTrue(Timeline.TimelineUIUtils.isMarkerEvent(parsedTrace, markLoadEvent)); }); it('is true for a LCP candiadate event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz'); - const markLCPCandidate = traceData.PageLoadMetrics.allMarkerEvents.find(TraceEngine.Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz'); + const markLCPCandidate = parsedTrace.PageLoadMetrics.allMarkerEvents.find(Trace.Types.Events.isLargestContentfulPaintCandidate); assert.isOk(markLCPCandidate); - assert.isTrue(Timeline.TimelineUIUtils.isMarkerEvent(traceData, markLCPCandidate)); + assert.isTrue(Timeline.TimelineUIUtils.isMarkerEvent(parsedTrace, markLCPCandidate)); }); it('is false for a MarkDOMContent event not on outermost main frame', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz'); - const markDOMContentEvent = traceData.PageLoadMetrics.allMarkerEvents.find(TraceEngine.Types.TraceEvents.isTraceEventMarkDOMContent); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz'); + const markDOMContentEvent = parsedTrace.PageLoadMetrics.allMarkerEvents.find(Trace.Types.Events.isMarkDOMContent); assert.isOk(markDOMContentEvent); assert.isOk(markDOMContentEvent.args); assert.isOk(markDOMContentEvent.args.data); @@ -1095,7 +1094,7 @@ describeWithMockConnection('TimelineUIUtils', function () { }, }, }; - assert.isFalse(Timeline.TimelineUIUtils.isMarkerEvent(traceData, copyOfEventNotOutermostFrame)); + assert.isFalse(Timeline.TimelineUIUtils.isMarkerEvent(parsedTrace, copyOfEventNotOutermostFrame)); }); }); describe('displayNameForFrame', () => { @@ -1105,7 +1104,7 @@ describeWithMockConnection('TimelineUIUtils', function () { url: 'https://' + 'a'.repeat(80), frame: 'frame-id', - processId: TraceEngine.Types.TraceEvents.ProcessID(1), + processId: Trace.Types.Events.ProcessID(1), }; const name = Timeline.TimelineUIUtils.TimelineUIUtils.displayNameForFrame(frame); assert.strictEqual(name, `https://${'a'.repeat(72) /* 80 minus the 8 chars for 'https://' */}`); @@ -1116,7 +1115,7 @@ describeWithMockConnection('TimelineUIUtils', function () { name: 'test-frame', url: 'about:blank', frame: 'frame-id', - processId: TraceEngine.Types.TraceEvents.ProcessID(1), + processId: Trace.Types.Events.ProcessID(1), }; const name = Timeline.TimelineUIUtils.TimelineUIUtils.displayNameForFrame(frame); assert.strictEqual(name, '"test-frame"'); @@ -1126,7 +1125,7 @@ describeWithMockConnection('TimelineUIUtils', function () { name: 'test-frame-that-is-long', url: 'about:blank', frame: 'frame-id', - processId: TraceEngine.Types.TraceEvents.ProcessID(1), + processId: Trace.Types.Events.ProcessID(1), }; const name = Timeline.TimelineUIUtils.TimelineUIUtils.displayNameForFrame(frame, 10); assert.strictEqual(name, '"test-…long"'); @@ -1134,24 +1133,24 @@ describeWithMockConnection('TimelineUIUtils', function () { }); describe('buildDetailsNodeForMarkerEvents', () => { it('builds the right link for an LCP Event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const markLCPEvent = getEventOfType(traceData.PageLoadMetrics.allMarkerEvents, TraceEngine.Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const markLCPEvent = getEventOfType(parsedTrace.PageLoadMetrics.allMarkerEvents, Trace.Types.Events.isLargestContentfulPaintCandidate); const html = Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsNodeForMarkerEvents(markLCPEvent); const url = html.querySelector('x-link')?.getAttribute('href'); assert.strictEqual(url, 'https://web.dev/lcp/'); assert.strictEqual(html.innerText, 'Learn more about largest contentful paint.'); }); it('builds the right link for an FCP Event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const markFCPEvent = getEventOfType(traceData.PageLoadMetrics.allMarkerEvents, TraceEngine.Types.TraceEvents.isTraceEventFirstContentfulPaint); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const markFCPEvent = getEventOfType(parsedTrace.PageLoadMetrics.allMarkerEvents, Trace.Types.Events.isFirstContentfulPaint); const html = Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsNodeForMarkerEvents(markFCPEvent); const url = html.querySelector('x-link')?.getAttribute('href'); assert.strictEqual(url, 'https://web.dev/first-contentful-paint/'); assert.strictEqual(html.innerText, 'Learn more about first contentful paint.'); }); it('builds a generic event for other marker events', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const markLoadEvent = getEventOfType(traceData.PageLoadMetrics.allMarkerEvents, TraceEngine.Types.TraceEvents.isTraceEventMarkLoad); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const markLoadEvent = getEventOfType(parsedTrace.PageLoadMetrics.allMarkerEvents, Trace.Types.Events.isMarkLoad); const html = Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsNodeForMarkerEvents(markLoadEvent); const url = html.querySelector('x-link')?.getAttribute('href'); assert.strictEqual(url, 'https://web.dev/user-centric-performance-metrics/'); diff --git a/public/panels/timeline/TimelineUIUtils.test.js.map b/public/panels/timeline/TimelineUIUtils.test.js.map index 5a94af5a9..1e2a9d89b 100644 --- a/public/panels/timeline/TimelineUIUtils.test.js.map +++ b/public/panels/timeline/TimelineUIUtils.test.js.map @@ -1 +1 @@ -{"version":3,"file":"TimelineUIUtils.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineUIUtils.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2021 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport type * as Platform from '../../core/platform/platform.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport type * as Protocol from '../../generated/protocol.js';\nimport * as Bindings from '../../models/bindings/bindings.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as Workspace from '../../models/workspace/workspace.js';\nimport * as Elements from '../../panels/elements/elements.js';\nimport {doubleRaf, renderElementIntoDOM} from '../../testing/DOMHelpers.js';\nimport {createTarget} from '../../testing/EnvironmentHelpers.js';\nimport {\n clearMockConnectionResponseHandler,\n describeWithMockConnection,\n setMockConnectionResponseHandler,\n} from '../../testing/MockConnection.js';\nimport {\n loadBasicSourceMapExample,\n setupPageResourceLoaderForSourceMap,\n} from '../../testing/SourceMapHelpers.js';\nimport {\n getEventOfType,\n getMainThread,\n makeCompleteEvent,\n makeMockSamplesHandlerData,\n makeProfileCall,\n} from '../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\nimport * as Components from '../../ui/legacy/components/utils/utils.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\n\nimport * as TimelineComponents from './components/components.js';\nimport * as Timeline from './timeline.js';\n\ndescribeWithMockConnection('TimelineUIUtils', function() {\n let target: SDK.Target.Target;\n // Trace events contain script ids as strings. However, the linkifier\n // utilities assume it is a number because that's how it's defined at\n // the protocol level. For practicality, we declare these two\n // variables so that we can satisfy type checking throughout the tests.\n const SCRIPT_ID_NUMBER = 1;\n const SCRIPT_ID_STRING = String(SCRIPT_ID_NUMBER) as Protocol.Runtime.ScriptId;\n\n beforeEach(() => {\n target = createTarget();\n\n const workspace = Workspace.Workspace.WorkspaceImpl.instance();\n const targetManager = SDK.TargetManager.TargetManager.instance();\n const resourceMapping = new Bindings.ResourceMapping.ResourceMapping(targetManager, workspace);\n const debuggerWorkspaceBinding = Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance({\n forceNew: true,\n resourceMapping,\n targetManager,\n });\n Bindings.IgnoreListManager.IgnoreListManager.instance({forceNew: true, debuggerWorkspaceBinding});\n });\n\n afterEach(() => {\n clearMockConnectionResponseHandler('DOM.pushNodesByBackendIdsToFrontend');\n });\n\n it('creates top frame location text for function calls', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz');\n const functionCallEvent =\n traceData.Renderer.allTraceEntries.find(TraceEngine.Types.TraceEvents.isTraceEventFunctionCall);\n assert.isOk(functionCallEvent);\n assert.strictEqual(\n 'chrome-extension://blijaeebfebmkmekmdnehcmmcjnblkeo/lib/utils.js:11:43',\n await Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsTextForTraceEvent(functionCallEvent, traceData));\n });\n\n it('creates top frame location text as a fallback', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const timerInstallEvent =\n traceData.Renderer.allTraceEntries.find(TraceEngine.Types.TraceEvents.isTraceEventTimerInstall);\n assert.isOk(timerInstallEvent);\n assert.strictEqual(\n 'https://web.dev/js/index-7b6f3de4.js:96:533',\n await Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsTextForTraceEvent(timerInstallEvent, traceData));\n });\n\n describe('script location as an URL', function() {\n it('makes the script location of a call frame a full URL when the inspected target is not the same the call frame was taken from (e.g. a loaded file)',\n async function() {\n // The actual trace doesn't matter here, just need one so we can pass\n // it into buildDetailsNodeForTraceEvent\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n\n const fakeFunctionCall: TraceEngine.Types.TraceEvents.TraceEventFunctionCall = {\n name: TraceEngine.Types.TraceEvents.KnownEventName.FUNCTION_CALL,\n ph: TraceEngine.Types.TraceEvents.Phase.COMPLETE,\n cat: 'devtools-timeline',\n dur: TraceEngine.Types.Timing.MicroSeconds(100),\n ts: TraceEngine.Types.Timing.MicroSeconds(100),\n pid: TraceEngine.Types.TraceEvents.ProcessID(1),\n tid: TraceEngine.Types.TraceEvents.ThreadID(1),\n args: {\n data: {\n functionName: 'test',\n url: 'https://google.com/test.js',\n scriptId: Number(SCRIPT_ID_STRING),\n lineNumber: 1,\n columnNumber: 1,\n },\n },\n };\n\n target.setInspectedURL('https://not-google.com' as Platform.DevToolsPath.UrlString);\n const node = await Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsNodeForTraceEvent(\n fakeFunctionCall, target, new Components.Linkifier.Linkifier(), false, traceData);\n if (!node) {\n throw new Error('Node was unexpectedly null');\n }\n assert.strictEqual(node.textContent, 'test @ google.com/test.js:1:1');\n });\n\n it('makes the script location of a call frame a script name when the inspected target is the one the call frame was taken from',\n async function() {\n // The actual trace doesn't matter here, just need one so we can pass\n // it into buildDetailsNodeForTraceEvent\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n const fakeFunctionCall: TraceEngine.Types.TraceEvents.TraceEventFunctionCall = {\n name: TraceEngine.Types.TraceEvents.KnownEventName.FUNCTION_CALL,\n ph: TraceEngine.Types.TraceEvents.Phase.COMPLETE,\n cat: 'devtools-timeline',\n dur: TraceEngine.Types.Timing.MicroSeconds(100),\n ts: TraceEngine.Types.Timing.MicroSeconds(100),\n pid: TraceEngine.Types.TraceEvents.ProcessID(1),\n tid: TraceEngine.Types.TraceEvents.ThreadID(1),\n args: {\n data: {\n functionName: 'test',\n url: 'https://google.com/test.js',\n scriptId: Number(SCRIPT_ID_STRING),\n lineNumber: 1,\n columnNumber: 1,\n },\n },\n };\n target.setInspectedURL('https://google.com' as Platform.DevToolsPath.UrlString);\n const node = await Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsNodeForTraceEvent(\n fakeFunctionCall, target, new Components.Linkifier.Linkifier(), false, traceData);\n if (!node) {\n throw new Error('Node was unexpectedly null');\n }\n assert.strictEqual(node.textContent, 'test @ /test.js:1:1');\n });\n });\n\n describe('mapping to authored script when recording is fresh', function() {\n beforeEach(async () => {\n // Register mock script and source map.\n\n const sourceMapContent = JSON.stringify({\n version: 3,\n names: ['unminified', 'par1', 'par2', 'console', 'log'],\n sources: [\n '/original-script.ts',\n ],\n file: '/test.js',\n sourcesContent: ['function unminified(par1, par2) {\\n console.log(par1, par2);\\n}\\n'],\n mappings: 'AAAA,SAASA,EAAWC,EAAMC,GACxBC,QAAQC,IAAIH,EAAMC',\n });\n setupPageResourceLoaderForSourceMap(sourceMapContent);\n target.setInspectedURL('https://google.com' as Platform.DevToolsPath.UrlString);\n const scriptUrl = 'https://google.com/script.js' as Platform.DevToolsPath.UrlString;\n const sourceMapUrl = 'script.js.map' as Platform.DevToolsPath.UrlString;\n const debuggerModel = target.model(SDK.DebuggerModel.DebuggerModel);\n assert.isNotNull(debuggerModel);\n if (debuggerModel === null) {\n return;\n }\n const sourceMapManager = debuggerModel.sourceMapManager();\n const script = debuggerModel.parsedScriptSource(\n SCRIPT_ID_STRING, scriptUrl, 0, 0, 0, 0, 0, '', undefined, false, sourceMapUrl, true, false, length, false,\n null, null, null, null, null);\n await sourceMapManager.sourceMapForClientPromise(script);\n });\n it('maps to the authored script when a call frame is provided', async function() {\n const linkifier = new Components.Linkifier.Linkifier();\n const node = Timeline.TimelineUIUtils.TimelineUIUtils.linkifyLocation({\n scriptId: SCRIPT_ID_STRING,\n url: 'https://google.com/test.js',\n lineNumber: 0,\n columnNumber: 0,\n isFreshRecording: true,\n target,\n linkifier,\n });\n if (!node) {\n throw new Error('Node was unexpectedly null');\n }\n // Wait for the location to be resolved using the registered source map.\n await Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance().pendingLiveLocationChangesPromise();\n\n assert.strictEqual(node.textContent, 'original-script.ts:1:1');\n });\n\n it('maps to the authored script when a trace event from the new engine with a stack trace is provided',\n async function() {\n const functionCallEvent = makeCompleteEvent('FunctionCall', 10, 100);\n functionCallEvent.args = ({\n data: {\n stackTrace: [{\n functionName: 'test',\n url: 'https://google.com/test.js',\n scriptId: SCRIPT_ID_NUMBER,\n lineNumber: 0,\n columnNumber: 0,\n }],\n },\n });\n const linkifier = new Components.Linkifier.Linkifier();\n const node =\n Timeline.TimelineUIUtils.TimelineUIUtils.linkifyTopCallFrame(functionCallEvent, target, linkifier, true);\n if (!node) {\n throw new Error('Node was unexpectedly null');\n }\n // Wait for the location to be resolved using the registered source map.\n await Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance()\n .pendingLiveLocationChangesPromise();\n\n assert.strictEqual(node.textContent, 'original-script.ts:1:1');\n });\n });\n\n describe('mapping to authored function name when recording is fresh', function() {\n it('maps to the authored name and script of a profile call', async function() {\n const {script} = await loadBasicSourceMapExample(target);\n // Ideally we would get a column number we can use from the source\n // map however the current status of the source map helpers makes\n // it difficult to do so.\n const columnNumber = 51;\n const profileCall = makeProfileCall(\n 'function', 10, 100, TraceEngine.Types.TraceEvents.ProcessID(1), TraceEngine.Types.TraceEvents.ThreadID(1));\n\n profileCall.callFrame = {\n columnNumber,\n functionName: 'minified',\n lineNumber: 0,\n scriptId: script.scriptId,\n url: 'file://gen.js',\n };\n const workersData: TraceEngine.Handlers.ModelHandlers.Workers.WorkersData = {\n workerSessionIdEvents: [],\n workerIdByThread: new Map(),\n workerURLById: new Map(),\n };\n // This only includes data used in the SourceMapsResolver\n const traceData = {\n Samples: makeMockSamplesHandlerData([profileCall]),\n Workers: workersData,\n } as TraceEngine.Handlers.Types.TraceParseData;\n\n const resolver = new Timeline.SourceMapsResolver.SourceMapsResolver(traceData);\n await resolver.install();\n\n const linkifier = new Components.Linkifier.Linkifier();\n const node = await Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsNodeForTraceEvent(\n profileCall, target, linkifier, true, traceData);\n if (!node) {\n throw new Error('Node was unexpectedly null');\n }\n assert.isTrue(node.textContent?.startsWith('someFunction @'));\n });\n });\n describe('adjusting timestamps for events and navigations', function() {\n it('adjusts the time for a DCL event after a navigation', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n\n const mainFrameID = traceData.Meta.mainFrameId;\n\n const dclEvent = traceData.PageLoadMetrics.allMarkerEvents.find(event => {\n return TraceEngine.Types.TraceEvents.isTraceEventMarkDOMContent(event) &&\n event.args.data?.frame === mainFrameID;\n });\n if (!dclEvent) {\n throw new Error('Could not find DCL event');\n }\n\n const traceMinBound = traceData.Meta.traceBounds.min;\n\n // Round the time to 2DP to avoid needlessly long expectation numbers!\n const unadjustedStartTimeMilliseconds =\n TraceEngine.Helpers.Timing\n .microSecondsToMilliseconds(\n TraceEngine.Types.Timing.MicroSeconds(dclEvent.ts - traceMinBound),\n )\n .toFixed(2);\n assert.strictEqual(unadjustedStartTimeMilliseconds, String(190.79));\n\n const adjustedTime =\n Timeline.TimelineUIUtils.timeStampForEventAdjustedForClosestNavigationIfPossible(dclEvent, traceData);\n assert.strictEqual(adjustedTime.toFixed(2), String(178.92));\n });\n\n it('can adjust the times for events that are not PageLoad markers', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'user-timings.json.gz');\n // Use a performance.mark event. Exact event is unimportant except that\n // it should not be a Page Load event as those are covered by the tests\n // above.\n const userMark = traceData.UserTimings.performanceMarks.find(event => event.name === 'mark1');\n if (!userMark) {\n throw new Error('Could not find user mark');\n }\n\n const adjustedMarkTime =\n Timeline.TimelineUIUtils.timeStampForEventAdjustedForClosestNavigationIfPossible(userMark, traceData);\n assert.strictEqual(adjustedMarkTime.toFixed(2), String(79.88));\n });\n });\n\n function getInnerTextAcrossShadowRoots(root: Node|null): string {\n // Don't recurse into STYLE elements\n if (!root || root.nodeName === 'STYLE') {\n return '';\n }\n if (root.nodeType === Node.TEXT_NODE) {\n return root.nodeValue || '';\n }\n if (root instanceof HTMLElement && root.shadowRoot) {\n return getInnerTextAcrossShadowRoots(root.shadowRoot);\n }\n return Array.from(root.childNodes).map(getInnerTextAcrossShadowRoots).join('');\n }\n\n function getRowDataForDetailsElement(details: DocumentFragment) {\n return Array.from(details.querySelectorAll('.timeline-details-view-row')).map(row => {\n const title = row.querySelector('.timeline-details-view-row-title')?.innerText;\n const valueEl = row.querySelector('.timeline-details-view-row-value') ??\n row.querySelector('div,span');\n let value = valueEl?.innerText || '';\n if (!value && valueEl) {\n // Stack traces and renderEventJson have the contents within a shadowRoot.\n value = getInnerTextAcrossShadowRoots(valueEl).trim();\n }\n return {title, value};\n });\n }\n\n function getStackTraceForDetailsElement(details: DocumentFragment): string[]|null {\n const stackTraceContainer =\n details\n .querySelector(\n '.timeline-details-view-row.timeline-details-stack-values .stack-preview-container')\n ?.shadowRoot;\n if (!stackTraceContainer) {\n return null;\n }\n return Array.from(stackTraceContainer.querySelectorAll('tr')).map(row => {\n const functionName = row.querySelector('.function-name')?.innerText;\n const url = row.querySelector('.link')?.innerText;\n return `${functionName || ''} @ ${url || ''}`;\n });\n }\n\n function getPieChartDataForDetailsElement(details: DocumentFragment) {\n const pieChartComp = details.querySelector('devtools-perf-piechart');\n if (!pieChartComp?.shadowRoot) {\n return [];\n }\n return Array.from(pieChartComp.shadowRoot.querySelectorAll('.pie-chart-legend-row')).map(row => {\n const title = row.querySelector('.pie-chart-name')?.innerText;\n const value = row.querySelector('.pie-chart-size')?.innerText;\n return {title, value};\n });\n }\n\n describe('colors', function() {\n before(() => {\n // Rather than use the real colours here and burden the test with having to\n // inject loads of CSS, we fake out the colours. this is fine for our tests as\n // the exact value of the colours is not important; we just make sure that it\n // parses them out correctly. Each variable is given a different rgb() value to\n // ensure we know the code is working and using the right one.\n const styleElement = document.createElement('style');\n styleElement.id = 'fake-perf-panel-colors';\n styleElement.textContent = `\n:root {\n --app-color-loading: rgb(0 0 0);\n --app-color-loading-children: rgb(1 1 1);\n --app-color-scripting: rgb(2 2 2);\n --app-color-scripting-children: rgb(3 3 3);\n --app-color-rendering: rgb(4 4 4);\n --app-color-rendering-children: rgb(5 5 5);\n --app-color-painting: rgb(6 6 6);\n --app-color-painting-children: rgb(7 7 7);\n --app-color-task: rgb(8 8 8);\n --app-color-task-children: rgb(9 9 9);\n --app-color-system: rgb(10 10 10);\n --app-color-system-children: rgb(11 11 11);\n --app-color-idle: rgb(12 12 12);\n --app-color-idle-children: rgb(13 13 13);\n --app-color-async: rgb(14 14 14);\n --app-color-async-children: rgb(15 15 15);\n --app-color-other: rgb(16 16 16);\n}\n`;\n document.documentElement.appendChild(styleElement);\n ThemeSupport.ThemeSupport.clearThemeCache();\n });\n\n after(() => {\n const styleElementToRemove = document.documentElement.querySelector('#fake-perf-panel-colors');\n if (styleElementToRemove) {\n document.documentElement.removeChild(styleElementToRemove);\n }\n ThemeSupport.ThemeSupport.clearThemeCache();\n });\n\n it('should return the correct rgb value for a corresponding CSS variable', function() {\n const parsedColor = TimelineComponents.EntryStyles.getCategoryStyles().scripting.getComputedColorValue();\n assert.strictEqual('rgb(2 2 2)', parsedColor);\n });\n\n it('should return the color as a CSS variable', function() {\n const cssVariable = TimelineComponents.EntryStyles.getCategoryStyles().scripting.getCSSValue();\n assert.strictEqual('var(--app-color-scripting)', cssVariable);\n });\n\n it('treats the v8.parseOnBackgroundWaiting as scripting even though it would usually be idle', function() {\n const event = makeCompleteEvent(\n TraceEngine.Types.TraceEvents.KnownEventName.STREAMING_COMPILE_SCRIPT_WAITING,\n 1,\n 1,\n 'v8,devtools.timeline,disabled-by-default-v8.compile',\n );\n assert.strictEqual('rgb(2 2 2)', Timeline.TimelineUIUtils.TimelineUIUtils.eventColor(event));\n });\n\n it('assigns the correct color to the swatch of an event\\'s title', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'lcp-web-font.json.gz');\n const events = traceData.Renderer.allTraceEntries;\n const task = events.find(event => {\n return event.name.includes('RunTask');\n });\n if (!task) {\n throw new Error('Could not find expected event.');\n }\n\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n traceData,\n task,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const titleSwatch: HTMLElement|null = details.querySelector('.timeline-details-chip-title div');\n assert.strictEqual(titleSwatch?.style.backgroundColor, 'rgb(10, 10, 10)');\n });\n });\n\n describe('testContentMatching', () => {\n it('matches call frame events based on a regular expression and the contents of the event', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'react-hello-world.json.gz');\n // Find an event from the trace that represents some work that React did. This\n // event is not chosen for any particular reason other than it was the example\n // used in the bug report: crbug.com/1484504\n const mainThread = getMainThread(traceData.Renderer);\n const performConcurrentWorkEvent = mainThread.entries.find(entry => {\n if (TraceEngine.Types.TraceEvents.isProfileCall(entry)) {\n return entry.callFrame.functionName === 'performConcurrentWorkOnRoot';\n }\n return false;\n });\n if (!performConcurrentWorkEvent) {\n throw new Error('Could not find expected event');\n }\n assert.isTrue(\n Timeline.TimelineUIUtils.TimelineUIUtils.testContentMatching(performConcurrentWorkEvent, /perfo/, traceData));\n });\n });\n\n describe('traceEventDetails', function() {\n it('shows the interaction ID and INP breakdown metrics for a given interaction', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz');\n const interactionEvent = traceData.UserInteractions.interactionEventsWithNoNesting.find(entry => {\n return entry.dur === 979974 && entry.type === 'click';\n });\n if (!interactionEvent) {\n throw new Error('Could not find expected event');\n }\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n traceData,\n interactionEvent,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n assert.deepEqual(rowData, [\n {\n title: 'Warning',\n value: 'Long interaction is indicating poor page responsiveness.',\n },\n {\n title: 'ID',\n value: '4122',\n },\n {\n title: 'Input delay',\n value: '1\\xA0ms',\n },\n {\n title: 'Processing duration',\n value: '977\\xA0ms',\n },\n {\n title: 'Presentation delay',\n value: '2\\xA0ms',\n },\n ]);\n });\n\n it('renders all event data for a generic trace', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'generic-about-tracing.json.gz');\n const event = traceData.Renderer.allTraceEntries.find(entry => {\n return entry.name === 'ThreadControllerImpl::RunTask';\n });\n if (!event) {\n throw new Error('Could not find event.');\n }\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n traceData,\n event,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n assert.deepEqual(rowData, [\n {\n title: '',\n // Generic traces get their events rendered as JSON\n value:\n '{ \"args\": {\\n \"chrome_task_annotator\": {\\n \"delay_policy\": \"PRECISE\",\\n \"task_delay_us\": 7159\\n },\\n \"src_file\": \"cc/scheduler/scheduler.cc\",\\n \"src_func\": \"ScheduleBeginImplFrameDeadline\"\\n },\\n \"cat\": \"toplevel\",\\n \"dur\": 222,\\n \"name\": \"ThreadControllerImpl::RunTask\",\\n \"ph\": \"X\",\\n \"pid\": 1214129,\\n \"tdur\": 163,\\n \"tid\": 7,\\n \"ts\": 1670373249790,\\n \"tts\": 5752392\\n}',\n },\n ]);\n });\n\n it('renders invalidations correctly', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'style-invalidation-change-attribute.json.gz');\n TraceLoader.initTraceBoundsManager(traceData);\n\n // Set up a fake DOM so that we can request nodes by backend Ids (even\n // though we return none, we need to mock these calls else the frontend\n // will not work.)\n const documentNode = {nodeId: 1 as Protocol.DOM.BackendNodeId};\n setMockConnectionResponseHandler('DOM.getDocument', () => ({root: documentNode}));\n setMockConnectionResponseHandler('DOM.pushNodesByBackendIdsToFrontend', () => {\n return {\n nodeIds: [],\n };\n });\n\n const updateLayoutTreeEvent = traceData.Renderer.allTraceEntries.find(event => {\n return TraceEngine.Types.TraceEvents.isTraceEventUpdateLayoutTree(event) &&\n event.args.beginData?.stackTrace?.[0].functionName === 'testFuncs.changeAttributeAndDisplay';\n });\n if (!updateLayoutTreeEvent) {\n throw new Error('Could not find update layout tree event');\n }\n\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n traceData,\n updateLayoutTreeEvent,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n assert.deepEqual(rowData, [\n {\n title: 'Elements affected',\n value: '3',\n },\n {\n title: 'Selector stats',\n value: 'Select \"\" to collect detailed CSS selector matching statistics.',\n },\n {\n // The \"Recalculation forced\" Stack trace\n title: undefined,\n value:\n 'testFuncs.changeAttributeAndDisplay @ chromedevtools.github.io/performance-stories/style-invalidations/app.js:47:40',\n },\n {\n title: 'Initiated by',\n value: 'Schedule style recalculation',\n },\n {\n title: 'Pending for',\n value: '7.1 ms',\n },\n {\n title: 'PseudoClass:active',\n value: 'BUTTON id=\\'changeAttributeAndDisplay\\'',\n },\n {\n title: 'Attribute (dir)',\n value:\n 'DIV id=\\'testElementFour\\' at chromedevtools.github.io/performance-stories/style-invalidations/app.js:46',\n },\n {\n title: 'Attribute (dir)',\n value:\n 'DIV id=\\'testElementFive\\' at chromedevtools.github.io/performance-stories/style-invalidations/app.js:47',\n },\n {\n title: 'Element has pending invalidation list',\n value: 'DIV id=\\'testElementFour\\'',\n },\n {\n title: 'Element has pending invalidation list',\n value: 'DIV id=\\'testElementFive\\'',\n },\n ]);\n });\n\n it('renders details for performance.mark', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'user-timings-details.json.gz');\n const mark = traceData.UserTimings.performanceMarks[0];\n if (!mark) {\n throw new Error('Could not find expected event');\n }\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n traceData,\n mark,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n assert.deepEqual(rowData, [\n {\n title: 'Timestamp',\n value: '1058.3\\xA0ms',\n },\n {title: 'Details', value: '{ \"hello\": \"world\"\\n}'},\n ]);\n });\n\n it('renders details for performance.measure', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'user-timings-details.json.gz');\n const measure = traceData.UserTimings.performanceMeasures[0];\n if (!measure) {\n throw new Error('Could not find expected event');\n }\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n traceData,\n measure,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n assert.deepEqual(rowData, [\n {\n title: 'Timestamp',\n value: '1005.5\\xA0ms',\n },\n {\n title: 'Details',\n value:\n '{ \"devtools\": {\\n \"metadata\": {\\n \"extensionName\": \"hello\",\\n \"dataType\": \"track-entry\"\\n },\\n \"color\": \"error\",\\n \"track\": \"An extension track\"\\n }\\n}',\n },\n ]);\n });\n\n it('renders details for a v8.compile (\"Compile Script\") event', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'user-timings.json.gz');\n\n const compileEvent = traceData.Renderer.allTraceEntries.find(TraceEngine.Types.TraceEvents.isTraceEventV8Compile);\n if (!compileEvent) {\n throw new Error('Could not find expected event');\n }\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n traceData,\n compileEvent,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n assert.deepEqual(rowData, [\n {\n title: 'Script',\n // URL plus line/col number\n value: 'chrome-extension://blijaeebfebmkmekmdnehcmmcjnblkeo/lib/utils.js:1:1',\n },\n {\n title: 'Streamed',\n value: 'false: inline script',\n },\n {title: 'Compilation cache status', value: 'script not eligible'},\n ]);\n });\n\n it('renders the details for a layout shift properly', async function() {\n // Set related CDP methods responses to return our mock document and node.\n const domModel = target.model(SDK.DOMModel.DOMModel);\n assert.exists(domModel);\n const documentNode = {nodeId: 1 as Protocol.DOM.NodeId};\n const docc = new SDK.DOMModel.DOMNode(domModel) as SDK.DOMModel.DOMDocument;\n const domNode2 = new SDK.DOMModel.DOMNode(domModel);\n const domID = 58 as Protocol.DOM.NodeId;\n domNode2.id = domID;\n\n setMockConnectionResponseHandler('DOM.pushNodesByBackendIdsToFrontend', () => ({nodeIds: [domID]}));\n\n setMockConnectionResponseHandler('DOM.getDocument', () => ({root: documentNode}));\n await domModel.requestDocument();\n domModel.registerNode(domNode2);\n domNode2.init(docc, false, {nodeName: 'A test node name', nodeId: domID} as Protocol.DOM.Node);\n const {traceData} = await TraceLoader.traceEngine(this, 'cls-single-frame.json.gz');\n const layoutShift = traceData.LayoutShifts.clusters[0].events[0];\n Common.Linkifier.registerLinkifier({\n contextTypes() {\n return [Timeline.CLSLinkifier.CLSRect];\n },\n async loadLinkifier() {\n return Timeline.CLSLinkifier.Linkifier.instance();\n },\n });\n Common.Linkifier.registerLinkifier({\n contextTypes() {\n return [\n SDK.DOMModel.DOMNode,\n ];\n },\n async loadLinkifier() {\n return Elements.DOMLinkifier.Linkifier.instance();\n },\n });\n\n if (!layoutShift) {\n throw new Error('Could not find LayoutShift event.');\n }\n\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n traceData,\n layoutShift,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n assert.deepEqual(\n rowData,\n [\n {\n title: 'Warning',\n value: 'Cumulative Layout Shifts can result in poor user experiences. It has recently evolved.',\n },\n {title: 'Score', value: '0.04218'},\n {title: 'Cumulative score', value: '0.04218'},\n {title: 'Current cluster ID', value: '1'},\n {title: 'Current cluster score', value: '0.2952'},\n {title: 'Had recent input', value: 'No'},\n {title: 'Moved from', value: 'Location: [120,670], Size: [900x900]'},\n {title: 'Moved to', value: 'Location: [120,1270], Size: [900x478]'},\n {title: 'Related node', value: 'A test node name'},\n ],\n );\n });\n\n it('renders the details for an extension entry properly', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz');\n const extensionEntry = traceData.ExtensionTraceData.extensionTrackData[1].entriesByTrack['An Extension Track'][0];\n\n if (!extensionEntry) {\n throw new Error('Could not find extension entry.');\n }\n\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n traceData,\n extensionEntry,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n assert.deepEqual(\n rowData,\n [\n {\n title: 'Description',\n value: 'This is a child task',\n },\n {title: 'Tip', value: 'Do something about it'},\n {title: undefined, value: 'appendACorgi @ localhost:3000/static/js/bundle.js:274:19'},\n ],\n );\n });\n\n it('renders the details for an extension marker properly', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz');\n const extensionMark = traceData.ExtensionTraceData.extensionMarkers[0];\n\n if (!extensionMark) {\n throw new Error('Could not find extension mark.');\n }\n\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n traceData,\n extensionMark,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n assert.deepEqual(\n rowData,\n [\n {\n title: 'Description',\n value: 'This marks the start of a task',\n },\n {title: undefined, value: 'mockChangeDetection @ localhost:3000/static/js/bundle.js:295:17'},\n ],\n );\n });\n\n it('renders the details for a profile call properly', async function() {\n Common.Linkifier.registerLinkifier({\n contextTypes() {\n return [Timeline.CLSLinkifier.CLSRect];\n },\n async loadLinkifier() {\n return Timeline.CLSLinkifier.Linkifier.instance();\n },\n });\n\n const {traceData} = await TraceLoader.traceEngine(this, 'simple-js-program.json.gz');\n const [process] = traceData.Renderer.processes.values();\n const [thread] = process.threads.values();\n const profileCalls = thread.entries.filter(entry => TraceEngine.Types.TraceEvents.isProfileCall(entry));\n\n if (!profileCalls) {\n throw new Error('Could not find renderer events');\n }\n\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n traceData,\n profileCalls[0],\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n assert.deepEqual(\n rowData,\n [\n {\n title: 'Function',\n value: '(anonymous) @ www.google.com:21:17',\n },\n ],\n );\n });\n it('renders the stack trace of a ScheduleStyleRecalculation properly', async function() {\n Common.Linkifier.registerLinkifier({\n contextTypes() {\n return [Timeline.CLSLinkifier.CLSRect];\n },\n async loadLinkifier() {\n return Timeline.CLSLinkifier.Linkifier.instance();\n },\n });\n\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n TraceLoader.initTraceBoundsManager(traceData);\n const [process] = traceData.Renderer.processes.values();\n const [thread] = process.threads.values();\n const scheduleStyleRecalcs =\n thread.entries.filter(entry => TraceEngine.Types.TraceEvents.isTraceEventScheduleStyleRecalculation(entry));\n\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n traceData,\n scheduleStyleRecalcs[1],\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details)[0];\n assert.deepEqual(\n rowData,\n {\n title: 'Details',\n value: 'web.dev/js/app.js?v=1423cda3:1:183',\n },\n );\n const stackTraceData = getStackTraceForDetailsElement(details);\n assert.deepEqual(\n stackTraceData,\n ['(anonymous) @ web.dev/js/app.js?v=1423cda3:1:183'],\n );\n });\n\n it('renders the stack trace of a RecalculateStyles properly', async function() {\n Common.Linkifier.registerLinkifier({\n contextTypes() {\n return [Timeline.CLSLinkifier.CLSRect];\n },\n async loadLinkifier() {\n return Timeline.CLSLinkifier.Linkifier.instance();\n },\n });\n\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n TraceLoader.initTraceBoundsManager(traceData);\n const [process] = traceData.Renderer.processes.values();\n const [thread] = process.threads.values();\n const stylesRecalc = thread.entries.filter(\n entry => entry.name === TraceEngine.Types.TraceEvents.KnownEventName.UPDATE_LAYOUT_TREE);\n\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n traceData,\n stylesRecalc[3],\n new Components.Linkifier.Linkifier(),\n false,\n );\n const stackTraceData = getStackTraceForDetailsElement(details);\n assert.deepEqual(\n stackTraceData,\n ['(anonymous) @ web.dev/js/app.js?v=1423cda3:1:183'],\n );\n });\n it('renders the stack trace of extension entries properly', async function() {\n Common.Linkifier.registerLinkifier({\n contextTypes() {\n return [Timeline.CLSLinkifier.CLSRect];\n },\n async loadLinkifier() {\n return Timeline.CLSLinkifier.Linkifier.instance();\n },\n });\n\n const {traceData} = await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz');\n TraceLoader.initTraceBoundsManager(traceData);\n const [extensionMarker] = traceData.ExtensionTraceData.extensionMarkers.values();\n const [extensionTrackData] = traceData.ExtensionTraceData.extensionTrackData.values();\n const [[extensionTrackEntry]] = Object.values(extensionTrackData.entriesByTrack);\n\n const markerDetails = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n traceData,\n extensionMarker,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const markerStackTraceData = getStackTraceForDetailsElement(markerDetails);\n assert.deepEqual(\n markerStackTraceData,\n ['mockChangeDetection @ localhost:3000/static/js/bundle.js:295:17'],\n );\n\n const trackEntryDetails = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n traceData,\n extensionTrackEntry,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const trackEntryStackTraceData = getStackTraceForDetailsElement(trackEntryDetails);\n assert.deepEqual(\n trackEntryStackTraceData,\n ['appendACorgi @ localhost:3000/static/js/bundle.js:274:19'],\n );\n });\n it('renders the stack trace of user timings properly', async function() {\n Common.Linkifier.registerLinkifier({\n contextTypes() {\n return [Timeline.CLSLinkifier.CLSRect];\n },\n async loadLinkifier() {\n return Timeline.CLSLinkifier.Linkifier.instance();\n },\n });\n\n const {traceData} = await TraceLoader.traceEngine(this, 'user-timings.json.gz');\n TraceLoader.initTraceBoundsManager(traceData);\n const [performanceMark] = traceData.UserTimings.performanceMarks.values();\n const [performanceMeasure] = traceData.UserTimings.performanceMeasures.values();\n\n const markDetails = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n traceData,\n performanceMark,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const markStackTraceData = getStackTraceForDetailsElement(markDetails);\n assert.deepEqual(\n markStackTraceData,\n ['addTimingMark @ chromedevtools.github.io/performance-stories/user-timings/app.js:2:1'],\n );\n\n const measureDetails = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n traceData,\n performanceMeasure,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const measureStackTraceData = getStackTraceForDetailsElement(measureDetails);\n assert.deepEqual(\n measureStackTraceData,\n ['addTimingMeasure @ chromedevtools.github.io/performance-stories/user-timings/app.js:2:1'],\n );\n });\n it('renders the warning for a trace event in its details', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'simple-js-program.json.gz');\n\n const events = traceData.Renderer.allTraceEntries;\n const longTask = events.find(e => (e.dur || 0) > 1_000_000);\n if (!longTask) {\n throw new Error('Could not find Long Task event.');\n }\n\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n traceData,\n longTask,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n assert.deepEqual(\n rowData,\n [\n {\n title: 'Warning',\n value: 'Long task took 1.30\\u00A0s.',\n },\n ],\n );\n });\n\n it('shows information for the WebSocketCreate initiator when viewing a WebSocketSendHandshakeRequest event',\n async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-sockets.json.gz');\n TraceLoader.initTraceBoundsManager(traceData);\n\n const sendHandshake = traceData.Renderer.allTraceEntries.find(\n TraceEngine.Types.TraceEvents.isTraceEventWebSocketSendHandshakeRequest);\n if (!sendHandshake) {\n throw new Error('Could not find handshake event.');\n }\n\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n traceData,\n sendHandshake,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n const expectedRowData = [\n {title: 'URL', value: 'wss://socketsbay.com/wss/v2/1/demo/'},\n // The 'First Invalidated' Stack trace\n {title: undefined, value: 'connect @ socketsbay.com/test-websockets:314:25'},\n {title: 'Initiated by', value: 'Create WebSocket'},\n {title: 'Pending for', value: '72.0 ms'},\n ];\n assert.deepEqual(\n rowData,\n expectedRowData,\n );\n });\n\n it('shows information for the events initiated by WebSocketCreate when viewing a WebSocketCreate event',\n async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-sockets.json.gz');\n TraceLoader.initTraceBoundsManager(traceData);\n\n const sendHandshake =\n traceData.Renderer.allTraceEntries.find(TraceEngine.Types.TraceEvents.isTraceEventWebSocketCreate);\n if (!sendHandshake) {\n throw new Error('Could not find handshake event.');\n }\n\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n traceData,\n sendHandshake,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n const expectedRowData = [\n {title: 'URL', value: 'wss://socketsbay.com/wss/v2/1/demo/'},\n // The initiator stack trace\n {title: undefined, value: 'connect @ socketsbay.com/test-websockets:314:25'},\n // The 2 entries under \"Initiator for\" are displayed as seperate links and in the UI it is obvious they are seperate\n {title: 'Initiator for', value: 'Send WebSocket handshake Receive WebSocket handshake'},\n ];\n assert.deepEqual(\n rowData,\n expectedRowData,\n );\n });\n\n it('shows the aggregated time information for an event', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const event = traceData.Renderer.allTraceEntries.find(e => e.ts === 1020034919877 && e.name === 'RunTask');\n if (!event) {\n throw new Error('Could not find renderer events');\n }\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n traceData,\n event,\n new Components.Linkifier.Linkifier(),\n true,\n );\n const pieChartData = getPieChartDataForDetailsElement(details);\n\n const expectedPieChartData = [\n {title: 'System (self)', value: '2\\u00A0ms'},\n {title: 'System (children)', value: '2\\u00A0ms'},\n {title: 'Rendering', value: '28\\u00A0ms'},\n {title: 'Painting', value: '2\\u00A0ms'},\n {title: 'Total', value: '34\\u00A0ms'},\n ];\n assert.deepEqual(\n pieChartData,\n expectedPieChartData,\n );\n });\n\n it('renders details for synthetic server timings', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'server-timings.json.gz');\n const serverTimings = traceData.ServerTimings.serverTimings;\n const serverTiming = serverTimings[0];\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n traceData,\n serverTiming,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n assert.deepEqual(rowData, [\n {\n title: 'Description',\n value: 'Description of top level task 1',\n },\n ]);\n });\n });\n\n it('can generate details for a frame', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n const frame = traceData.Frames.frames.at(0);\n if (!frame) {\n throw new Error('Could not find expected frame');\n }\n const filmStrip = TraceEngine.Extras.FilmStrip.fromTraceData(traceData);\n const details =\n Timeline.TimelineUIUtils.TimelineUIUtils.generateDetailsContentForFrame(frame, filmStrip, filmStrip.frames[0]);\n const container = document.createElement('div');\n renderElementIntoDOM(container);\n container.appendChild(details);\n // Give the image element time to render and load.\n await doubleRaf();\n const img = container.querySelector('.timeline-filmstrip-preview img');\n assert.isTrue(img?.currentSrc.includes(filmStrip.frames[0].screenshotEvent.args.dataUri));\n\n const durationRow = container.querySelector('[data-row-title=\"Duration\"]');\n const durationValue = durationRow?.querySelector('.timeline-details-view-row-value span');\n if (!durationValue) {\n throw new Error('Could not find duration');\n }\n // Strip the unicode spaces out and replace with simple spaces for easy\n // assertions.\n const value = (durationValue.innerText.replaceAll(/\\s/g, ' '));\n assert.strictEqual(value, '37.85 ms (at 109.82 ms)');\n });\n\n describe('eventTitle', function() {\n it('renders the correct title for an EventTiming interaction event', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'slow-interaction-button-click.json.gz');\n const interactionEvent = traceData.UserInteractions.interactionEventsWithNoNesting[0];\n const details = Timeline.TimelineUIUtils.TimelineUIUtils.eventTitle(interactionEvent);\n assert.deepEqual(details, 'Pointer');\n });\n\n it('will use the resolved function name for a profile node that has a sourcemap', async function() {\n // Timeline.SourceMapsResolver.SourceMapsResolver.\n const {traceData} = await TraceLoader.traceEngine(this, 'slow-interaction-button-click.json.gz');\n\n const mainThread = getMainThread(traceData.Renderer);\n const profileEntry = mainThread.entries.find(entry => {\n return TraceEngine.Types.TraceEvents.isProfileCall(entry);\n });\n if (!profileEntry || !TraceEngine.Types.TraceEvents.isProfileCall(profileEntry)) {\n throw new Error('Could not find a profile entry');\n }\n\n // Fake that we resolved the entry's name from a sourcemap.\n Timeline.SourceMapsResolver.SourceMapsResolver.storeResolvedNodeNameForEntry(\n profileEntry.pid, profileEntry.tid, profileEntry.nodeId, 'resolved-function-test');\n\n const title = Timeline.TimelineUIUtils.TimelineUIUtils.eventTitle(profileEntry);\n assert.strictEqual(title, 'resolved-function-test');\n });\n });\n\n describe('eventStyle', function() {\n it('returns the correct style for profile calls', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'simple-js-program.json.gz');\n const rendererHandler = traceData.Renderer;\n if (!rendererHandler) {\n throw new Error('RendererHandler is undefined');\n }\n const [process] = rendererHandler.processes.values();\n const [thread] = process.threads.values();\n const profileCalls = thread.entries.filter(entry => TraceEngine.Types.TraceEvents.isProfileCall(entry));\n const style = Timeline.TimelineUIUtils.TimelineUIUtils.eventStyle(profileCalls[0]);\n assert.strictEqual(style.category.name, 'scripting');\n assert.strictEqual(style.category.color, 'rgb(250 204 21 / 100%)');\n });\n });\n\n describe('statsForTimeRange', () => {\n it('correctly aggregates up stats', async () => {\n const mainThread = TraceEngine.Types.TraceEvents.ThreadID(1);\n const pid = TraceEngine.Types.TraceEvents.ProcessID(100);\n function microsec(x: number): TraceEngine.Types.Timing.MicroSeconds {\n return TraceEngine.Types.Timing.MicroSeconds(x);\n }\n\n const events: TraceEngine.Types.TraceEvents.TraceEventData[] = [\n {\n cat: 'disabled-by-default-devtools.timeline',\n name: 'TracingStartedInBrowser',\n ph: TraceEngine.Types.TraceEvents.Phase.INSTANT,\n pid,\n tid: mainThread,\n ts: microsec(100),\n args: {\n data: {\n frames: [\n {frame: 'frame1', url: 'frameurl', name: 'frame-name'},\n ],\n },\n },\n } as TraceEngine.Types.TraceEvents.TraceEventTracingStartedInBrowser,\n {\n cat: 'disabled-by-default-devtools.timeline',\n name: 'SetLayerTreeId',\n ph: TraceEngine.Types.TraceEvents.Phase.INSTANT,\n pid,\n tid: mainThread,\n ts: microsec(101),\n args: {data: {frame: 'frame1', layerTreeId: 17}},\n } as TraceEngine.Types.TraceEvents.TraceEventSetLayerTreeId,\n {\n cat: 'toplevel',\n name: 'Program',\n ph: TraceEngine.Types.TraceEvents.Phase.COMPLETE,\n ts: microsec(100000),\n dur: microsec(3000),\n tid: mainThread,\n pid,\n args: {},\n },\n {\n cat: 'disabled-by-default-devtools.timeline',\n name: 'FunctionCall',\n ph: TraceEngine.Types.TraceEvents.Phase.COMPLETE,\n ts: microsec(100500),\n dur: microsec(1500),\n tid: mainThread,\n pid,\n args: {},\n },\n {\n cat: 'disabled-by-default-devtools.timeline',\n name: 'Layout',\n ph: TraceEngine.Types.TraceEvents.Phase.COMPLETE,\n ts: microsec(101000),\n dur: microsec(1000),\n tid: mainThread,\n pid,\n args: {\n beginData: {\n frame: 'FAKE_FRAME_ID',\n dirtyObjects: 0,\n partialLayout: false,\n totalObjects: 1,\n },\n endData: {layoutRoots: []},\n },\n } as TraceEngine.Types.TraceEvents.TraceEventLayout,\n\n {\n cat: 'toplevel',\n name: 'Program',\n ph: TraceEngine.Types.TraceEvents.Phase.COMPLETE,\n ts: microsec(104000),\n dur: microsec(4000),\n tid: mainThread,\n pid,\n args: {},\n },\n {\n cat: 'disabled-by-default-devtools.timeline',\n name: 'FunctionCall',\n ph: TraceEngine.Types.TraceEvents.Phase.COMPLETE,\n ts: microsec(104000),\n dur: microsec(1000),\n tid: mainThread,\n pid,\n args: {},\n },\n {\n cat: 'disabled-by-default-devtools.timeline',\n name: 'CommitLoad',\n ph: TraceEngine.Types.TraceEvents.Phase.COMPLETE,\n ts: microsec(105000),\n dur: microsec(1000),\n tid: mainThread,\n pid,\n args: {},\n },\n {\n cat: 'disabled-by-default-devtools.timeline',\n name: 'Layout',\n ph: TraceEngine.Types.TraceEvents.Phase.COMPLETE,\n ts: microsec(107000),\n dur: microsec(1000),\n tid: mainThread,\n pid,\n args: {\n beginData: {\n frame: 'FAKE_FRAME_ID',\n dirtyObjects: 0,\n partialLayout: false,\n totalObjects: 1,\n },\n endData: {layoutRoots: []},\n },\n } as TraceEngine.Types.TraceEvents.TraceEventLayout,\n ];\n\n const rangeStats101To103 = Timeline.TimelineUIUtils.TimelineUIUtils.statsForTimeRange(\n events,\n TraceEngine.Types.Timing.MilliSeconds(101),\n TraceEngine.Types.Timing.MilliSeconds(103),\n );\n assert.deepEqual(rangeStats101To103, {\n other: 1,\n rendering: 1,\n scripting: 0,\n idle: 0,\n });\n const rangeStats104To109 = Timeline.TimelineUIUtils.TimelineUIUtils.statsForTimeRange(\n events,\n TraceEngine.Types.Timing.MilliSeconds(104),\n TraceEngine.Types.Timing.MilliSeconds(109),\n );\n assert.deepEqual(rangeStats104To109, {\n other: 2,\n rendering: 1,\n scripting: 1,\n idle: 1,\n });\n });\n });\n\n describe('isMarkerEvent', () => {\n it('is true for a timestamp event', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz');\n const timestamp = traceData.Renderer.allTraceEntries.find(TraceEngine.Types.TraceEvents.isTraceEventTimeStamp);\n assert.isOk(timestamp);\n assert.isTrue(Timeline.TimelineUIUtils.isMarkerEvent(traceData, timestamp));\n });\n\n it('is true for a Mark First Paint event', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz');\n const markFirstPaint =\n traceData.PageLoadMetrics.allMarkerEvents.find(TraceEngine.Types.TraceEvents.isTraceEventFirstPaint);\n assert.isOk(markFirstPaint);\n assert.isTrue(Timeline.TimelineUIUtils.isMarkerEvent(traceData, markFirstPaint));\n });\n\n it('is true for a Mark FCP event', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz');\n const markFCPEvent = traceData.PageLoadMetrics.allMarkerEvents.find(\n TraceEngine.Types.TraceEvents.isTraceEventFirstContentfulPaint);\n assert.isOk(markFCPEvent);\n assert.isTrue(Timeline.TimelineUIUtils.isMarkerEvent(traceData, markFCPEvent));\n });\n\n it('is false for a Mark FCP event not on the main frame', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz');\n const markFCPEvent = traceData.PageLoadMetrics.allMarkerEvents.find(\n TraceEngine.Types.TraceEvents.isTraceEventFirstContentfulPaint);\n assert.isOk(markFCPEvent);\n assert.isOk(markFCPEvent.args);\n // Now make a copy (so we do not mutate any data) and pretend it is not on the main frame.\n const copyOfEvent = {...markFCPEvent, args: {...markFCPEvent.args}};\n copyOfEvent.args.frame = 'not-the-main-frame';\n assert.isFalse(Timeline.TimelineUIUtils.isMarkerEvent(traceData, copyOfEvent));\n });\n\n it('is true for a MarkDOMContent event', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz');\n const markDOMContentEvent =\n traceData.PageLoadMetrics.allMarkerEvents.find(TraceEngine.Types.TraceEvents.isTraceEventMarkDOMContent);\n assert.isOk(markDOMContentEvent);\n assert.isTrue(Timeline.TimelineUIUtils.isMarkerEvent(traceData, markDOMContentEvent));\n });\n\n it('is true for a MarkLoad event', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz');\n const markLoadEvent =\n traceData.PageLoadMetrics.allMarkerEvents.find(TraceEngine.Types.TraceEvents.isTraceEventMarkLoad);\n assert.isOk(markLoadEvent);\n assert.isTrue(Timeline.TimelineUIUtils.isMarkerEvent(traceData, markLoadEvent));\n });\n\n it('is true for a LCP candiadate event', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz');\n const markLCPCandidate = traceData.PageLoadMetrics.allMarkerEvents.find(\n TraceEngine.Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate);\n assert.isOk(markLCPCandidate);\n assert.isTrue(Timeline.TimelineUIUtils.isMarkerEvent(traceData, markLCPCandidate));\n });\n\n it('is false for a MarkDOMContent event not on outermost main frame', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz');\n const markDOMContentEvent =\n traceData.PageLoadMetrics.allMarkerEvents.find(TraceEngine.Types.TraceEvents.isTraceEventMarkDOMContent);\n assert.isOk(markDOMContentEvent);\n assert.isOk(markDOMContentEvent.args);\n assert.isOk(markDOMContentEvent.args.data);\n\n const copyOfEventNotOutermostFrame = {\n ...markDOMContentEvent,\n args: {\n ...markDOMContentEvent.args,\n data: {\n ...markDOMContentEvent.args.data,\n isOutermostMainFrame: false,\n },\n },\n\n };\n assert.isFalse(Timeline.TimelineUIUtils.isMarkerEvent(traceData, copyOfEventNotOutermostFrame));\n });\n });\n\n describe('displayNameForFrame', () => {\n it('trims the URL at 80 chars by default', async () => {\n const frame: TraceEngine.Types.TraceEvents.TraceFrame = {\n name: 'test-frame',\n url: 'https://' +\n 'a'.repeat(80),\n frame: 'frame-id',\n processId: TraceEngine.Types.TraceEvents.ProcessID(1),\n };\n const name = Timeline.TimelineUIUtils.TimelineUIUtils.displayNameForFrame(frame);\n assert.strictEqual(name, `https://${'a'.repeat(72) /* 80 minus the 8 chars for 'https://' */}`);\n assert.lengthOf(name, 80);\n });\n\n it('uses the frame name if the URL is about:', async () => {\n const frame: TraceEngine.Types.TraceEvents.TraceFrame = {\n name: 'test-frame',\n url: 'about:blank',\n frame: 'frame-id',\n processId: TraceEngine.Types.TraceEvents.ProcessID(1),\n };\n const name = Timeline.TimelineUIUtils.TimelineUIUtils.displayNameForFrame(frame);\n assert.strictEqual(name, '\"test-frame\"');\n });\n\n it('trims the frame name from the middle if it is too long', async () => {\n const frame: TraceEngine.Types.TraceEvents.TraceFrame = {\n name: 'test-frame-that-is-long',\n url: 'about:blank',\n frame: 'frame-id',\n processId: TraceEngine.Types.TraceEvents.ProcessID(1),\n };\n const name = Timeline.TimelineUIUtils.TimelineUIUtils.displayNameForFrame(frame, 10);\n assert.strictEqual(name, '\"test-…long\"');\n });\n });\n\n describe('buildDetailsNodeForMarkerEvents', () => {\n it('builds the right link for an LCP Event', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const markLCPEvent = getEventOfType(\n traceData.PageLoadMetrics.allMarkerEvents,\n TraceEngine.Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate);\n const html = Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsNodeForMarkerEvents(\n markLCPEvent,\n );\n const url = html.querySelector('x-link')?.getAttribute('href');\n assert.strictEqual(url, 'https://web.dev/lcp/');\n assert.strictEqual(html.innerText, 'Learn more about largest contentful paint.');\n });\n\n it('builds the right link for an FCP Event', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const markFCPEvent = getEventOfType(\n traceData.PageLoadMetrics.allMarkerEvents, TraceEngine.Types.TraceEvents.isTraceEventFirstContentfulPaint);\n const html = Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsNodeForMarkerEvents(\n markFCPEvent,\n );\n const url = html.querySelector('x-link')?.getAttribute('href');\n assert.strictEqual(url, 'https://web.dev/first-contentful-paint/');\n assert.strictEqual(html.innerText, 'Learn more about first contentful paint.');\n });\n\n it('builds a generic event for other marker events', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const markLoadEvent =\n getEventOfType(traceData.PageLoadMetrics.allMarkerEvents, TraceEngine.Types.TraceEvents.isTraceEventMarkLoad);\n const html = Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsNodeForMarkerEvents(\n markLoadEvent,\n );\n const url = html.querySelector('x-link')?.getAttribute('href');\n assert.strictEqual(url, 'https://web.dev/user-centric-performance-metrics/');\n assert.strictEqual(html.innerText, 'Learn more about page performance metrics.');\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"TimelineUIUtils.test.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimelineUIUtils.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2021 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../core/common/common.js';\nimport type * as Platform from '../../core/platform/platform.js';\nimport * as SDK from '../../core/sdk/sdk.js';\nimport type * as Protocol from '../../generated/protocol.js';\nimport * as Bindings from '../../models/bindings/bindings.js';\nimport * as Trace from '../../models/trace/trace.js';\nimport * as Workspace from '../../models/workspace/workspace.js';\nimport * as Elements from '../../panels/elements/elements.js';\nimport {doubleRaf, renderElementIntoDOM} from '../../testing/DOMHelpers.js';\nimport {createTarget} from '../../testing/EnvironmentHelpers.js';\nimport {\n clearMockConnectionResponseHandler,\n describeWithMockConnection,\n setMockConnectionResponseHandler,\n} from '../../testing/MockConnection.js';\nimport {\n loadBasicSourceMapExample,\n setupPageResourceLoaderForSourceMap,\n} from '../../testing/SourceMapHelpers.js';\nimport {\n getEventOfType,\n getMainThread,\n makeCompleteEvent,\n makeMockSamplesHandlerData,\n makeProfileCall,\n} from '../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../testing/TraceLoader.js';\nimport * as Components from '../../ui/legacy/components/utils/utils.js';\nimport * as ThemeSupport from '../../ui/legacy/theme_support/theme_support.js';\n\nimport * as TimelineComponents from './components/components.js';\nimport * as Timeline from './timeline.js';\n\ndescribeWithMockConnection('TimelineUIUtils', function() {\n let target: SDK.Target.Target;\n // Trace events contain script ids as strings. However, the linkifier\n // utilities assume it is a number because that's how it's defined at\n // the protocol level. For practicality, we declare these two\n // variables so that we can satisfy type checking throughout the tests.\n const SCRIPT_ID_NUMBER = 1;\n const SCRIPT_ID_STRING = String(SCRIPT_ID_NUMBER) as Protocol.Runtime.ScriptId;\n\n beforeEach(() => {\n target = createTarget();\n\n const workspace = Workspace.Workspace.WorkspaceImpl.instance();\n const targetManager = SDK.TargetManager.TargetManager.instance();\n const resourceMapping = new Bindings.ResourceMapping.ResourceMapping(targetManager, workspace);\n const debuggerWorkspaceBinding = Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance({\n forceNew: true,\n resourceMapping,\n targetManager,\n });\n Bindings.IgnoreListManager.IgnoreListManager.instance({forceNew: true, debuggerWorkspaceBinding});\n });\n\n afterEach(() => {\n clearMockConnectionResponseHandler('DOM.pushNodesByBackendIdsToFrontend');\n });\n\n it('creates top frame location text for function calls', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz');\n const functionCallEvent = parsedTrace.Renderer.allTraceEntries.find(Trace.Types.Events.isFunctionCall);\n assert.isOk(functionCallEvent);\n assert.strictEqual(\n 'chrome-extension://blijaeebfebmkmekmdnehcmmcjnblkeo/lib/utils.js:11:43',\n await Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsTextForTraceEvent(functionCallEvent, parsedTrace));\n });\n\n it('creates top frame location text as a fallback', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const timerInstallEvent = parsedTrace.Renderer.allTraceEntries.find(Trace.Types.Events.isTimerInstall);\n assert.isOk(timerInstallEvent);\n assert.strictEqual(\n 'https://web.dev/js/index-7b6f3de4.js:96:533',\n await Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsTextForTraceEvent(timerInstallEvent, parsedTrace));\n });\n\n describe('script location as an URL', function() {\n it('makes the script location of a call frame a full URL when the inspected target is not the same the call frame was taken from (e.g. a loaded file)',\n async function() {\n // The actual trace doesn't matter here, just need one so we can pass\n // it into buildDetailsNodeForTraceEvent\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n\n const fakeFunctionCall: Trace.Types.Events.FunctionCall = {\n name: Trace.Types.Events.Name.FUNCTION_CALL,\n ph: Trace.Types.Events.Phase.COMPLETE,\n cat: 'devtools-timeline',\n dur: Trace.Types.Timing.MicroSeconds(100),\n ts: Trace.Types.Timing.MicroSeconds(100),\n pid: Trace.Types.Events.ProcessID(1),\n tid: Trace.Types.Events.ThreadID(1),\n args: {\n data: {\n functionName: 'test',\n url: 'https://google.com/test.js',\n scriptId: Number(SCRIPT_ID_STRING),\n lineNumber: 1,\n columnNumber: 1,\n },\n },\n };\n\n target.setInspectedURL('https://not-google.com' as Platform.DevToolsPath.UrlString);\n const node = await Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsNodeForTraceEvent(\n fakeFunctionCall, target, new Components.Linkifier.Linkifier(), false, parsedTrace);\n if (!node) {\n throw new Error('Node was unexpectedly null');\n }\n assert.strictEqual(node.textContent, 'test @ google.com/test.js:1:1');\n });\n\n it('makes the script location of a call frame a script name when the inspected target is the one the call frame was taken from',\n async function() {\n // The actual trace doesn't matter here, just need one so we can pass\n // it into buildDetailsNodeForTraceEvent\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n const fakeFunctionCall: Trace.Types.Events.FunctionCall = {\n name: Trace.Types.Events.Name.FUNCTION_CALL,\n ph: Trace.Types.Events.Phase.COMPLETE,\n cat: 'devtools-timeline',\n dur: Trace.Types.Timing.MicroSeconds(100),\n ts: Trace.Types.Timing.MicroSeconds(100),\n pid: Trace.Types.Events.ProcessID(1),\n tid: Trace.Types.Events.ThreadID(1),\n args: {\n data: {\n functionName: 'test',\n url: 'https://google.com/test.js',\n scriptId: Number(SCRIPT_ID_STRING),\n lineNumber: 1,\n columnNumber: 1,\n },\n },\n };\n target.setInspectedURL('https://google.com' as Platform.DevToolsPath.UrlString);\n const node = await Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsNodeForTraceEvent(\n fakeFunctionCall, target, new Components.Linkifier.Linkifier(), false, parsedTrace);\n if (!node) {\n throw new Error('Node was unexpectedly null');\n }\n assert.strictEqual(node.textContent, 'test @ /test.js:1:1');\n });\n });\n\n describe('mapping to authored script when recording is fresh', function() {\n beforeEach(async () => {\n // Register mock script and source map.\n\n const sourceMapContent = JSON.stringify({\n version: 3,\n names: ['unminified', 'par1', 'par2', 'console', 'log'],\n sources: [\n '/original-script.ts',\n ],\n file: '/test.js',\n sourcesContent: ['function unminified(par1, par2) {\\n console.log(par1, par2);\\n}\\n'],\n mappings: 'AAAA,SAASA,EAAWC,EAAMC,GACxBC,QAAQC,IAAIH,EAAMC',\n });\n setupPageResourceLoaderForSourceMap(sourceMapContent);\n target.setInspectedURL('https://google.com' as Platform.DevToolsPath.UrlString);\n const scriptUrl = 'https://google.com/script.js' as Platform.DevToolsPath.UrlString;\n const sourceMapUrl = 'script.js.map' as Platform.DevToolsPath.UrlString;\n const debuggerModel = target.model(SDK.DebuggerModel.DebuggerModel);\n assert.isNotNull(debuggerModel);\n if (debuggerModel === null) {\n return;\n }\n const sourceMapManager = debuggerModel.sourceMapManager();\n const script = debuggerModel.parsedScriptSource(\n SCRIPT_ID_STRING, scriptUrl, 0, 0, 0, 0, 0, '', undefined, false, sourceMapUrl, true, false, length, false,\n null, null, null, null, null);\n await sourceMapManager.sourceMapForClientPromise(script);\n });\n it('maps to the authored script when a call frame is provided', async function() {\n const linkifier = new Components.Linkifier.Linkifier();\n const node = Timeline.TimelineUIUtils.TimelineUIUtils.linkifyLocation({\n scriptId: SCRIPT_ID_STRING,\n url: 'https://google.com/test.js',\n lineNumber: 0,\n columnNumber: 0,\n isFreshRecording: true,\n target,\n linkifier,\n });\n if (!node) {\n throw new Error('Node was unexpectedly null');\n }\n // Wait for the location to be resolved using the registered source map.\n await Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance().pendingLiveLocationChangesPromise();\n\n assert.strictEqual(node.textContent, 'original-script.ts:1:1');\n });\n\n it('maps to the authored script when a trace event from the new engine with a stack trace is provided',\n async function() {\n const functionCallEvent = makeCompleteEvent('FunctionCall', 10, 100);\n functionCallEvent.args = ({\n data: {\n stackTrace: [{\n functionName: 'test',\n url: 'https://google.com/test.js',\n scriptId: SCRIPT_ID_NUMBER,\n lineNumber: 0,\n columnNumber: 0,\n }],\n },\n });\n const linkifier = new Components.Linkifier.Linkifier();\n const node =\n Timeline.TimelineUIUtils.TimelineUIUtils.linkifyTopCallFrame(functionCallEvent, target, linkifier, true);\n if (!node) {\n throw new Error('Node was unexpectedly null');\n }\n // Wait for the location to be resolved using the registered source map.\n await Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance()\n .pendingLiveLocationChangesPromise();\n\n assert.strictEqual(node.textContent, 'original-script.ts:1:1');\n });\n });\n\n describe('mapping to authored function name when recording is fresh', function() {\n it('maps to the authored name and script of a profile call', async function() {\n const {script} = await loadBasicSourceMapExample(target);\n // Ideally we would get a column number we can use from the source\n // map however the current status of the source map helpers makes\n // it difficult to do so.\n const columnNumber = 51;\n const profileCall =\n makeProfileCall('function', 10, 100, Trace.Types.Events.ProcessID(1), Trace.Types.Events.ThreadID(1));\n\n profileCall.callFrame = {\n columnNumber,\n functionName: 'minified',\n lineNumber: 0,\n scriptId: script.scriptId,\n url: 'file://gen.js',\n };\n const workersData: Trace.Handlers.ModelHandlers.Workers.WorkersData = {\n workerSessionIdEvents: [],\n workerIdByThread: new Map(),\n workerURLById: new Map(),\n };\n // This only includes data used in the SourceMapsResolver\n const parsedTrace = {\n Samples: makeMockSamplesHandlerData([profileCall]),\n Workers: workersData,\n } as Trace.Handlers.Types.ParsedTrace;\n\n const resolver = new Timeline.SourceMapsResolver.SourceMapsResolver(parsedTrace);\n await resolver.install();\n\n const linkifier = new Components.Linkifier.Linkifier();\n const node = await Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsNodeForTraceEvent(\n profileCall, target, linkifier, true, parsedTrace);\n if (!node) {\n throw new Error('Node was unexpectedly null');\n }\n assert.isTrue(node.textContent?.startsWith('someFunction @'));\n });\n });\n describe('adjusting timestamps for events and navigations', function() {\n it('adjusts the time for a DCL event after a navigation', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n\n const mainFrameID = parsedTrace.Meta.mainFrameId;\n\n const dclEvent = parsedTrace.PageLoadMetrics.allMarkerEvents.find(event => {\n return Trace.Types.Events.isMarkDOMContent(event) && event.args.data?.frame === mainFrameID;\n });\n if (!dclEvent) {\n throw new Error('Could not find DCL event');\n }\n\n const traceMinBound = parsedTrace.Meta.traceBounds.min;\n\n // Round the time to 2DP to avoid needlessly long expectation numbers!\n const unadjustedStartTimeMilliseconds = Trace.Helpers.Timing\n .microSecondsToMilliseconds(\n Trace.Types.Timing.MicroSeconds(dclEvent.ts - traceMinBound),\n )\n .toFixed(2);\n assert.strictEqual(unadjustedStartTimeMilliseconds, String(190.79));\n\n const adjustedTime =\n Timeline.TimelineUIUtils.timeStampForEventAdjustedForClosestNavigationIfPossible(dclEvent, parsedTrace);\n assert.strictEqual(adjustedTime.toFixed(2), String(178.92));\n });\n\n it('can adjust the times for events that are not PageLoad markers', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'user-timings.json.gz');\n // Use a performance.mark event. Exact event is unimportant except that\n // it should not be a Page Load event as those are covered by the tests\n // above.\n const userMark = parsedTrace.UserTimings.performanceMarks.find(event => event.name === 'mark1');\n if (!userMark) {\n throw new Error('Could not find user mark');\n }\n\n const adjustedMarkTime =\n Timeline.TimelineUIUtils.timeStampForEventAdjustedForClosestNavigationIfPossible(userMark, parsedTrace);\n assert.strictEqual(adjustedMarkTime.toFixed(2), String(79.88));\n });\n });\n\n function getInnerTextAcrossShadowRoots(root: Node|null): string {\n // Don't recurse into STYLE elements\n if (!root || root.nodeName === 'STYLE') {\n return '';\n }\n if (root.nodeType === Node.TEXT_NODE) {\n return root.nodeValue || '';\n }\n if (root instanceof HTMLElement && root.shadowRoot) {\n return getInnerTextAcrossShadowRoots(root.shadowRoot);\n }\n return Array.from(root.childNodes).map(getInnerTextAcrossShadowRoots).join('');\n }\n\n function getRowDataForDetailsElement(details: DocumentFragment) {\n return Array.from(details.querySelectorAll('.timeline-details-view-row')).map(row => {\n const title = row.querySelector('.timeline-details-view-row-title')?.innerText;\n const valueEl = row.querySelector('.timeline-details-view-row-value') ??\n row.querySelector('div,span');\n let value = valueEl?.innerText || '';\n if (!value && valueEl) {\n // Stack traces and renderEventJson have the contents within a shadowRoot.\n value = getInnerTextAcrossShadowRoots(valueEl).trim();\n }\n return {title, value};\n });\n }\n\n function getStackTraceForDetailsElement(details: DocumentFragment): string[]|null {\n const stackTraceContainer =\n details\n .querySelector(\n '.timeline-details-view-row.timeline-details-stack-values .stack-preview-container')\n ?.shadowRoot;\n if (!stackTraceContainer) {\n return null;\n }\n return Array.from(stackTraceContainer.querySelectorAll('tr')).map(row => {\n const functionName = row.querySelector('.function-name')?.innerText;\n const url = row.querySelector('.link')?.innerText;\n return `${functionName || ''} @ ${url || ''}`;\n });\n }\n\n function getPieChartDataForDetailsElement(details: DocumentFragment) {\n const pieChartComp = details.querySelector('devtools-perf-piechart');\n if (!pieChartComp?.shadowRoot) {\n return [];\n }\n return Array.from(pieChartComp.shadowRoot.querySelectorAll('.pie-chart-legend-row')).map(row => {\n const title = row.querySelector('.pie-chart-name')?.innerText;\n const value = row.querySelector('.pie-chart-size')?.innerText;\n return {title, value};\n });\n }\n\n describe('colors', function() {\n before(() => {\n // Rather than use the real colours here and burden the test with having to\n // inject loads of CSS, we fake out the colours. this is fine for our tests as\n // the exact value of the colours is not important; we just make sure that it\n // parses them out correctly. Each variable is given a different rgb() value to\n // ensure we know the code is working and using the right one.\n const styleElement = document.createElement('style');\n styleElement.id = 'fake-perf-panel-colors';\n styleElement.textContent = `\n:root {\n --app-color-loading: rgb(0 0 0);\n --app-color-loading-children: rgb(1 1 1);\n --app-color-scripting: rgb(2 2 2);\n --app-color-scripting-children: rgb(3 3 3);\n --app-color-rendering: rgb(4 4 4);\n --app-color-rendering-children: rgb(5 5 5);\n --app-color-painting: rgb(6 6 6);\n --app-color-painting-children: rgb(7 7 7);\n --app-color-task: rgb(8 8 8);\n --app-color-task-children: rgb(9 9 9);\n --app-color-system: rgb(10 10 10);\n --app-color-system-children: rgb(11 11 11);\n --app-color-idle: rgb(12 12 12);\n --app-color-idle-children: rgb(13 13 13);\n --app-color-async: rgb(14 14 14);\n --app-color-async-children: rgb(15 15 15);\n --app-color-other: rgb(16 16 16);\n}\n`;\n document.documentElement.appendChild(styleElement);\n ThemeSupport.ThemeSupport.clearThemeCache();\n });\n\n after(() => {\n const styleElementToRemove = document.documentElement.querySelector('#fake-perf-panel-colors');\n if (styleElementToRemove) {\n document.documentElement.removeChild(styleElementToRemove);\n }\n ThemeSupport.ThemeSupport.clearThemeCache();\n });\n\n it('should return the correct rgb value for a corresponding CSS variable', function() {\n const parsedColor = TimelineComponents.EntryStyles.getCategoryStyles().scripting.getComputedColorValue();\n assert.strictEqual('rgb(2 2 2)', parsedColor);\n });\n\n it('should return the color as a CSS variable', function() {\n const cssVariable = TimelineComponents.EntryStyles.getCategoryStyles().scripting.getCSSValue();\n assert.strictEqual('var(--app-color-scripting)', cssVariable);\n });\n\n it('treats the v8.parseOnBackgroundWaiting as scripting even though it would usually be idle', function() {\n const event = makeCompleteEvent(\n Trace.Types.Events.Name.STREAMING_COMPILE_SCRIPT_WAITING,\n 1,\n 1,\n 'v8,devtools.timeline,disabled-by-default-v8.compile',\n );\n assert.strictEqual('rgb(2 2 2)', Timeline.TimelineUIUtils.TimelineUIUtils.eventColor(event));\n });\n\n it('assigns the correct color to the swatch of an event\\'s title', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'lcp-web-font.json.gz');\n const events = parsedTrace.Renderer.allTraceEntries;\n const task = events.find(event => {\n return event.name.includes('RunTask');\n });\n if (!task) {\n throw new Error('Could not find expected event.');\n }\n\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n parsedTrace,\n task,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const titleSwatch: HTMLElement|null = details.querySelector('.timeline-details-chip-title div');\n assert.strictEqual(titleSwatch?.style.backgroundColor, 'rgb(10, 10, 10)');\n });\n });\n\n describe('testContentMatching', () => {\n it('matches call frame events based on a regular expression and the contents of the event', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'react-hello-world.json.gz');\n // Find an event from the trace that represents some work that React did. This\n // event is not chosen for any particular reason other than it was the example\n // used in the bug report: crbug.com/1484504\n const mainThread = getMainThread(parsedTrace.Renderer);\n const performConcurrentWorkEvent = mainThread.entries.find(entry => {\n if (Trace.Types.Events.isProfileCall(entry)) {\n return entry.callFrame.functionName === 'performConcurrentWorkOnRoot';\n }\n return false;\n });\n if (!performConcurrentWorkEvent) {\n throw new Error('Could not find expected event');\n }\n assert.isTrue(Timeline.TimelineUIUtils.TimelineUIUtils.testContentMatching(\n performConcurrentWorkEvent, /perfo/, parsedTrace));\n });\n });\n\n describe('traceEventDetails', function() {\n it('shows the interaction ID and INP breakdown metrics for a given interaction', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'one-second-interaction.json.gz');\n const interactionEvent = parsedTrace.UserInteractions.interactionEventsWithNoNesting.find(entry => {\n return entry.dur === 979974 && entry.type === 'click';\n });\n if (!interactionEvent) {\n throw new Error('Could not find expected event');\n }\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n parsedTrace,\n interactionEvent,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n assert.deepEqual(rowData, [\n {\n title: 'Warning',\n value: 'Long interaction is indicating poor page responsiveness.',\n },\n {\n title: 'ID',\n value: '4122',\n },\n {\n title: 'Input delay',\n value: '1\\xA0ms',\n },\n {\n title: 'Processing duration',\n value: '977\\xA0ms',\n },\n {\n title: 'Presentation delay',\n value: '2\\xA0ms',\n },\n ]);\n });\n\n it('renders all event data for a generic trace', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'generic-about-tracing.json.gz');\n const event = parsedTrace.Renderer.allTraceEntries.find(entry => {\n return entry.name === 'ThreadControllerImpl::RunTask';\n });\n if (!event) {\n throw new Error('Could not find event.');\n }\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n parsedTrace,\n event,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n assert.deepEqual(rowData, [\n {\n title: '',\n // Generic traces get their events rendered as JSON\n value:\n '{ \"args\": {\\n \"chrome_task_annotator\": {\\n \"delay_policy\": \"PRECISE\",\\n \"task_delay_us\": 7159\\n },\\n \"src_file\": \"cc/scheduler/scheduler.cc\",\\n \"src_func\": \"ScheduleBeginImplFrameDeadline\"\\n },\\n \"cat\": \"toplevel\",\\n \"dur\": 222,\\n \"name\": \"ThreadControllerImpl::RunTask\",\\n \"ph\": \"X\",\\n \"pid\": 1214129,\\n \"tdur\": 163,\\n \"tid\": 7,\\n \"ts\": 1670373249790,\\n \"tts\": 5752392\\n}',\n },\n ]);\n });\n\n it('renders invalidations correctly', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'style-invalidation-change-attribute.json.gz');\n TraceLoader.initTraceBoundsManager(parsedTrace);\n\n // Set up a fake DOM so that we can request nodes by backend Ids (even\n // though we return none, we need to mock these calls else the frontend\n // will not work.)\n const documentNode = {nodeId: 1 as Protocol.DOM.BackendNodeId};\n setMockConnectionResponseHandler('DOM.getDocument', () => ({root: documentNode}));\n setMockConnectionResponseHandler('DOM.pushNodesByBackendIdsToFrontend', () => {\n return {\n nodeIds: [],\n };\n });\n\n const updateLayoutTreeEvent = parsedTrace.Renderer.allTraceEntries.find(event => {\n return Trace.Types.Events.isUpdateLayoutTree(event) &&\n event.args.beginData?.stackTrace?.[0].functionName === 'testFuncs.changeAttributeAndDisplay';\n });\n if (!updateLayoutTreeEvent) {\n throw new Error('Could not find update layout tree event');\n }\n\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n parsedTrace,\n updateLayoutTreeEvent,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n assert.deepEqual(rowData, [\n {\n title: 'Elements affected',\n value: '3',\n },\n {\n title: 'Selector stats',\n value: 'Select \"\" to collect detailed CSS selector matching statistics.',\n },\n {\n // The \"Recalculation forced\" Stack trace\n title: undefined,\n value:\n 'testFuncs.changeAttributeAndDisplay @ chromedevtools.github.io/performance-stories/style-invalidations/app.js:47:40',\n },\n {\n title: 'Initiated by',\n value: 'Schedule style recalculation',\n },\n {\n title: 'Pending for',\n value: '7.1 ms',\n },\n {\n title: 'PseudoClass:active',\n value: 'BUTTON id=\\'changeAttributeAndDisplay\\'',\n },\n {\n title: 'Attribute (dir)',\n value:\n 'DIV id=\\'testElementFour\\' at chromedevtools.github.io/performance-stories/style-invalidations/app.js:46',\n },\n {\n title: 'Attribute (dir)',\n value:\n 'DIV id=\\'testElementFive\\' at chromedevtools.github.io/performance-stories/style-invalidations/app.js:47',\n },\n {\n title: 'Element has pending invalidation list',\n value: 'DIV id=\\'testElementFour\\'',\n },\n {\n title: 'Element has pending invalidation list',\n value: 'DIV id=\\'testElementFive\\'',\n },\n ]);\n });\n\n it('renders details for performance.mark', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'user-timings-details.json.gz');\n const mark = parsedTrace.UserTimings.performanceMarks[0];\n if (!mark) {\n throw new Error('Could not find expected event');\n }\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n parsedTrace,\n mark,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n assert.deepEqual(rowData, [\n {\n title: 'Timestamp',\n value: '1058.3\\xA0ms',\n },\n {title: 'Details', value: '{ \"hello\": \"world\"\\n}'},\n ]);\n });\n\n it('renders details for performance.measure', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'user-timings-details.json.gz');\n const measure = parsedTrace.UserTimings.performanceMeasures[0];\n if (!measure) {\n throw new Error('Could not find expected event');\n }\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n parsedTrace,\n measure,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n assert.deepEqual(rowData, [\n {\n title: 'Timestamp',\n value: '1005.5\\xA0ms',\n },\n {\n title: 'Details',\n value:\n '{ \"devtools\": {\\n \"metadata\": {\\n \"extensionName\": \"hello\",\\n \"dataType\": \"track-entry\"\\n },\\n \"color\": \"error\",\\n \"track\": \"An extension track\"\\n }\\n}',\n },\n ]);\n });\n\n it('renders details for a v8.compile (\"Compile Script\") event', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'user-timings.json.gz');\n\n const compileEvent = parsedTrace.Renderer.allTraceEntries.find(Trace.Types.Events.isV8Compile);\n if (!compileEvent) {\n throw new Error('Could not find expected event');\n }\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n parsedTrace,\n compileEvent,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n assert.deepEqual(rowData, [\n {\n title: 'Script',\n // URL plus line/col number\n value: 'chrome-extension://blijaeebfebmkmekmdnehcmmcjnblkeo/lib/utils.js:1:1',\n },\n {\n title: 'Streamed',\n value: 'false: inline script',\n },\n {title: 'Compilation cache status', value: 'script not eligible'},\n ]);\n });\n\n it('renders the details for a layout shift properly', async function() {\n // Set related CDP methods responses to return our mock document and node.\n const domModel = target.model(SDK.DOMModel.DOMModel);\n assert.exists(domModel);\n const documentNode = {nodeId: 1 as Protocol.DOM.NodeId};\n const docc = new SDK.DOMModel.DOMNode(domModel) as SDK.DOMModel.DOMDocument;\n const domNode2 = new SDK.DOMModel.DOMNode(domModel);\n const domID = 58 as Protocol.DOM.NodeId;\n domNode2.id = domID;\n\n setMockConnectionResponseHandler('DOM.pushNodesByBackendIdsToFrontend', () => ({nodeIds: [domID]}));\n\n setMockConnectionResponseHandler('DOM.getDocument', () => ({root: documentNode}));\n await domModel.requestDocument();\n domModel.registerNode(domNode2);\n domNode2.init(docc, false, {nodeName: 'A test node name', nodeId: domID} as Protocol.DOM.Node);\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'cls-single-frame.json.gz');\n const layoutShift = parsedTrace.LayoutShifts.clusters[0].events[0];\n Common.Linkifier.registerLinkifier({\n contextTypes() {\n return [Timeline.CLSLinkifier.CLSRect];\n },\n async loadLinkifier() {\n return Timeline.CLSLinkifier.Linkifier.instance();\n },\n });\n Common.Linkifier.registerLinkifier({\n contextTypes() {\n return [\n SDK.DOMModel.DOMNode,\n ];\n },\n async loadLinkifier() {\n return Elements.DOMLinkifier.Linkifier.instance();\n },\n });\n\n if (!layoutShift) {\n throw new Error('Could not find LayoutShift event.');\n }\n\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n parsedTrace,\n layoutShift,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n assert.deepEqual(\n rowData,\n [\n {\n title: 'Warning',\n value: 'Cumulative Layout Shifts can result in poor user experiences. It has recently evolved.',\n },\n {title: 'Score', value: '0.04218'},\n {title: 'Cumulative score', value: '0.04218'},\n {title: 'Current cluster ID', value: '1'},\n {title: 'Current cluster score', value: '0.2952'},\n {title: 'Had recent input', value: 'No'},\n {title: 'Moved from', value: 'Location: [120,670], Size: [900x900]'},\n {title: 'Moved to', value: 'Location: [120,1270], Size: [900x478]'},\n {title: 'Related node', value: 'A test node name'},\n ],\n );\n });\n\n it('renders the details for an extension entry properly', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz');\n const extensionEntry =\n parsedTrace.ExtensionTraceData.extensionTrackData[1].entriesByTrack['An Extension Track'][0];\n\n if (!extensionEntry) {\n throw new Error('Could not find extension entry.');\n }\n\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n parsedTrace,\n extensionEntry,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n assert.deepEqual(\n rowData,\n [\n {\n title: 'Description',\n value: 'This is a child task',\n },\n {title: 'Tip', value: 'Do something about it'},\n {title: undefined, value: 'appendACorgi @ localhost:3000/static/js/bundle.js:274:19'},\n ],\n );\n });\n\n it('renders the details for an extension marker properly', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz');\n const extensionMark = parsedTrace.ExtensionTraceData.extensionMarkers[0];\n\n if (!extensionMark) {\n throw new Error('Could not find extension mark.');\n }\n\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n parsedTrace,\n extensionMark,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n assert.deepEqual(\n rowData,\n [\n {\n title: 'Description',\n value: 'This marks the start of a task',\n },\n {title: undefined, value: 'mockChangeDetection @ localhost:3000/static/js/bundle.js:295:17'},\n ],\n );\n });\n\n it('renders the details for a profile call properly', async function() {\n Common.Linkifier.registerLinkifier({\n contextTypes() {\n return [Timeline.CLSLinkifier.CLSRect];\n },\n async loadLinkifier() {\n return Timeline.CLSLinkifier.Linkifier.instance();\n },\n });\n\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'simple-js-program.json.gz');\n const [process] = parsedTrace.Renderer.processes.values();\n const [thread] = process.threads.values();\n const profileCalls = thread.entries.filter(entry => Trace.Types.Events.isProfileCall(entry));\n\n if (!profileCalls) {\n throw new Error('Could not find renderer events');\n }\n\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n parsedTrace,\n profileCalls[0],\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n assert.deepEqual(\n rowData,\n [\n {\n title: 'Function',\n value: '(anonymous) @ www.google.com:21:17',\n },\n ],\n );\n });\n it('renders the stack trace of a ScheduleStyleRecalculation properly', async function() {\n Common.Linkifier.registerLinkifier({\n contextTypes() {\n return [Timeline.CLSLinkifier.CLSRect];\n },\n async loadLinkifier() {\n return Timeline.CLSLinkifier.Linkifier.instance();\n },\n });\n\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n TraceLoader.initTraceBoundsManager(parsedTrace);\n const [process] = parsedTrace.Renderer.processes.values();\n const [thread] = process.threads.values();\n const scheduleStyleRecalcs =\n thread.entries.filter(entry => Trace.Types.Events.isScheduleStyleRecalculation(entry));\n\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n parsedTrace,\n scheduleStyleRecalcs[1],\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details)[0];\n assert.deepEqual(\n rowData,\n {\n title: 'Details',\n value: 'web.dev/js/app.js?v=1423cda3:1:183',\n },\n );\n const stackTraceData = getStackTraceForDetailsElement(details);\n assert.deepEqual(\n stackTraceData,\n ['(anonymous) @ web.dev/js/app.js?v=1423cda3:1:183'],\n );\n });\n\n it('renders the stack trace of a RecalculateStyles properly', async function() {\n Common.Linkifier.registerLinkifier({\n contextTypes() {\n return [Timeline.CLSLinkifier.CLSRect];\n },\n async loadLinkifier() {\n return Timeline.CLSLinkifier.Linkifier.instance();\n },\n });\n\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n TraceLoader.initTraceBoundsManager(parsedTrace);\n const [process] = parsedTrace.Renderer.processes.values();\n const [thread] = process.threads.values();\n const stylesRecalc = thread.entries.filter(entry => entry.name === Trace.Types.Events.Name.UPDATE_LAYOUT_TREE);\n\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n parsedTrace,\n stylesRecalc[3],\n new Components.Linkifier.Linkifier(),\n false,\n );\n const stackTraceData = getStackTraceForDetailsElement(details);\n assert.deepEqual(\n stackTraceData,\n ['(anonymous) @ web.dev/js/app.js?v=1423cda3:1:183'],\n );\n });\n it('renders the stack trace of extension entries properly', async function() {\n Common.Linkifier.registerLinkifier({\n contextTypes() {\n return [Timeline.CLSLinkifier.CLSRect];\n },\n async loadLinkifier() {\n return Timeline.CLSLinkifier.Linkifier.instance();\n },\n });\n\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz');\n TraceLoader.initTraceBoundsManager(parsedTrace);\n const [extensionMarker] = parsedTrace.ExtensionTraceData.extensionMarkers.values();\n const [extensionTrackData] = parsedTrace.ExtensionTraceData.extensionTrackData.values();\n const [[extensionTrackEntry]] = Object.values(extensionTrackData.entriesByTrack);\n\n const markerDetails = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n parsedTrace,\n extensionMarker,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const markerStackTraceData = getStackTraceForDetailsElement(markerDetails);\n assert.deepEqual(\n markerStackTraceData,\n ['mockChangeDetection @ localhost:3000/static/js/bundle.js:295:17'],\n );\n\n const trackEntryDetails = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n parsedTrace,\n extensionTrackEntry,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const trackEntryStackTraceData = getStackTraceForDetailsElement(trackEntryDetails);\n assert.deepEqual(\n trackEntryStackTraceData,\n ['appendACorgi @ localhost:3000/static/js/bundle.js:274:19'],\n );\n });\n it('renders the stack trace of user timings properly', async function() {\n Common.Linkifier.registerLinkifier({\n contextTypes() {\n return [Timeline.CLSLinkifier.CLSRect];\n },\n async loadLinkifier() {\n return Timeline.CLSLinkifier.Linkifier.instance();\n },\n });\n\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'user-timings.json.gz');\n TraceLoader.initTraceBoundsManager(parsedTrace);\n const [performanceMark] = parsedTrace.UserTimings.performanceMarks.values();\n const [performanceMeasure] = parsedTrace.UserTimings.performanceMeasures.values();\n\n const markDetails = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n parsedTrace,\n performanceMark,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const markStackTraceData = getStackTraceForDetailsElement(markDetails);\n assert.deepEqual(\n markStackTraceData,\n ['addTimingMark @ chromedevtools.github.io/performance-stories/user-timings/app.js:2:1'],\n );\n\n const measureDetails = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n parsedTrace,\n performanceMeasure,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const measureStackTraceData = getStackTraceForDetailsElement(measureDetails);\n assert.deepEqual(\n measureStackTraceData,\n ['addTimingMeasure @ chromedevtools.github.io/performance-stories/user-timings/app.js:2:1'],\n );\n });\n it('renders the warning for a trace event in its details', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'simple-js-program.json.gz');\n\n const events = parsedTrace.Renderer.allTraceEntries;\n const longTask = events.find(e => (e.dur || 0) > 1_000_000);\n if (!longTask) {\n throw new Error('Could not find Long Task event.');\n }\n\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n parsedTrace,\n longTask,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n assert.deepEqual(\n rowData,\n [\n {\n title: 'Warning',\n value: 'Long task took 1.30\\u00A0s.',\n },\n ],\n );\n });\n\n it('shows information for the WebSocketCreate initiator when viewing a WebSocketSendHandshakeRequest event',\n async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-sockets.json.gz');\n TraceLoader.initTraceBoundsManager(parsedTrace);\n\n const sendHandshake =\n parsedTrace.Renderer.allTraceEntries.find(Trace.Types.Events.isWebSocketSendHandshakeRequest);\n if (!sendHandshake) {\n throw new Error('Could not find handshake event.');\n }\n\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n parsedTrace,\n sendHandshake,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n const expectedRowData = [\n {title: 'URL', value: 'wss://socketsbay.com/wss/v2/1/demo/'},\n // The 'First Invalidated' Stack trace\n {title: undefined, value: 'connect @ socketsbay.com/test-websockets:314:25'},\n {title: 'Initiated by', value: 'Create WebSocket'},\n {title: 'Pending for', value: '72.0 ms'},\n ];\n assert.deepEqual(\n rowData,\n expectedRowData,\n );\n });\n\n it('shows information for the events initiated by WebSocketCreate when viewing a WebSocketCreate event',\n async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-sockets.json.gz');\n TraceLoader.initTraceBoundsManager(parsedTrace);\n\n const sendHandshake = parsedTrace.Renderer.allTraceEntries.find(Trace.Types.Events.isWebSocketCreate);\n if (!sendHandshake) {\n throw new Error('Could not find handshake event.');\n }\n\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n parsedTrace,\n sendHandshake,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n const expectedRowData = [\n {title: 'URL', value: 'wss://socketsbay.com/wss/v2/1/demo/'},\n // The initiator stack trace\n {title: undefined, value: 'connect @ socketsbay.com/test-websockets:314:25'},\n // The 2 entries under \"Initiator for\" are displayed as seperate links and in the UI it is obvious they are seperate\n {title: 'Initiator for', value: 'Send WebSocket handshake Receive WebSocket handshake'},\n ];\n assert.deepEqual(\n rowData,\n expectedRowData,\n );\n });\n\n it('shows the aggregated time information for an event', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const event = parsedTrace.Renderer.allTraceEntries.find(e => e.ts === 1020034919877 && e.name === 'RunTask');\n if (!event) {\n throw new Error('Could not find renderer events');\n }\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n parsedTrace,\n event,\n new Components.Linkifier.Linkifier(),\n true,\n );\n const pieChartData = getPieChartDataForDetailsElement(details);\n\n const expectedPieChartData = [\n {title: 'System (self)', value: '2\\u00A0ms'},\n {title: 'System (children)', value: '2\\u00A0ms'},\n {title: 'Rendering', value: '28\\u00A0ms'},\n {title: 'Painting', value: '2\\u00A0ms'},\n {title: 'Total', value: '34\\u00A0ms'},\n ];\n assert.deepEqual(\n pieChartData,\n expectedPieChartData,\n );\n });\n\n it('renders details for synthetic server timings', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'server-timings.json.gz');\n const serverTimings = parsedTrace.ServerTimings.serverTimings;\n const serverTiming = serverTimings[0];\n const details = await Timeline.TimelineUIUtils.TimelineUIUtils.buildTraceEventDetails(\n parsedTrace,\n serverTiming,\n new Components.Linkifier.Linkifier(),\n false,\n );\n const rowData = getRowDataForDetailsElement(details);\n assert.deepEqual(rowData, [\n {\n title: 'Description',\n value: 'Description of top level task 1',\n },\n ]);\n });\n });\n\n it('can generate details for a frame', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n const frame = parsedTrace.Frames.frames.at(0);\n if (!frame) {\n throw new Error('Could not find expected frame');\n }\n const filmStrip = Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace);\n const details =\n Timeline.TimelineUIUtils.TimelineUIUtils.generateDetailsContentForFrame(frame, filmStrip, filmStrip.frames[0]);\n const container = document.createElement('div');\n renderElementIntoDOM(container);\n container.appendChild(details);\n // Give the image element time to render and load.\n await doubleRaf();\n const img = container.querySelector('.timeline-filmstrip-preview img');\n assert.isTrue(img?.currentSrc.includes(filmStrip.frames[0].screenshotEvent.args.dataUri));\n\n const durationRow = container.querySelector('[data-row-title=\"Duration\"]');\n const durationValue = durationRow?.querySelector('.timeline-details-view-row-value span');\n if (!durationValue) {\n throw new Error('Could not find duration');\n }\n // Strip the unicode spaces out and replace with simple spaces for easy\n // assertions.\n const value = (durationValue.innerText.replaceAll(/\\s/g, ' '));\n assert.strictEqual(value, '37.85 ms (at 109.82 ms)');\n });\n\n describe('eventTitle', function() {\n it('renders the correct title for an EventTiming interaction event', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'slow-interaction-button-click.json.gz');\n const interactionEvent = parsedTrace.UserInteractions.interactionEventsWithNoNesting[0];\n const details = Timeline.TimelineUIUtils.TimelineUIUtils.eventTitle(interactionEvent);\n assert.deepEqual(details, 'Pointer');\n });\n\n it('will use the resolved function name for a profile node that has a sourcemap', async function() {\n // Timeline.SourceMapsResolver.SourceMapsResolver.\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'slow-interaction-button-click.json.gz');\n\n const mainThread = getMainThread(parsedTrace.Renderer);\n const profileEntry = mainThread.entries.find(entry => {\n return Trace.Types.Events.isProfileCall(entry);\n });\n if (!profileEntry || !Trace.Types.Events.isProfileCall(profileEntry)) {\n throw new Error('Could not find a profile entry');\n }\n\n // Fake that we resolved the entry's name from a sourcemap.\n Timeline.SourceMapsResolver.SourceMapsResolver.storeResolvedNodeNameForEntry(\n profileEntry.pid, profileEntry.tid, profileEntry.nodeId, 'resolved-function-test');\n\n const title = Timeline.TimelineUIUtils.TimelineUIUtils.eventTitle(profileEntry);\n assert.strictEqual(title, 'resolved-function-test');\n });\n });\n\n describe('eventStyle', function() {\n it('returns the correct style for profile calls', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'simple-js-program.json.gz');\n const rendererHandler = parsedTrace.Renderer;\n if (!rendererHandler) {\n throw new Error('RendererHandler is undefined');\n }\n const [process] = rendererHandler.processes.values();\n const [thread] = process.threads.values();\n const profileCalls = thread.entries.filter(entry => Trace.Types.Events.isProfileCall(entry));\n const style = Timeline.TimelineUIUtils.TimelineUIUtils.eventStyle(profileCalls[0]);\n assert.strictEqual(style.category.name, 'scripting');\n assert.strictEqual(style.category.color, 'rgb(250 204 21 / 100%)');\n });\n });\n\n describe('statsForTimeRange', () => {\n it('correctly aggregates up stats', async () => {\n const mainThread = Trace.Types.Events.ThreadID(1);\n const pid = Trace.Types.Events.ProcessID(100);\n function microsec(x: number): Trace.Types.Timing.MicroSeconds {\n return Trace.Types.Timing.MicroSeconds(x);\n }\n\n const events: Trace.Types.Events.Event[] = [\n {\n cat: 'disabled-by-default-devtools.timeline',\n name: 'TracingStartedInBrowser',\n ph: Trace.Types.Events.Phase.INSTANT,\n pid,\n tid: mainThread,\n ts: microsec(100),\n args: {\n data: {\n frames: [\n {frame: 'frame1', url: 'frameurl', name: 'frame-name'},\n ],\n },\n },\n } as Trace.Types.Events.TracingStartedInBrowser,\n {\n cat: 'disabled-by-default-devtools.timeline',\n name: 'SetLayerTreeId',\n ph: Trace.Types.Events.Phase.INSTANT,\n pid,\n tid: mainThread,\n ts: microsec(101),\n args: {data: {frame: 'frame1', layerTreeId: 17}},\n } as Trace.Types.Events.SetLayerTreeId,\n {\n cat: 'toplevel',\n name: 'Program',\n ph: Trace.Types.Events.Phase.COMPLETE,\n ts: microsec(100000),\n dur: microsec(3000),\n tid: mainThread,\n pid,\n args: {},\n },\n {\n cat: 'disabled-by-default-devtools.timeline',\n name: 'FunctionCall',\n ph: Trace.Types.Events.Phase.COMPLETE,\n ts: microsec(100500),\n dur: microsec(1500),\n tid: mainThread,\n pid,\n args: {},\n },\n {\n cat: 'disabled-by-default-devtools.timeline',\n name: 'Layout',\n ph: Trace.Types.Events.Phase.COMPLETE,\n ts: microsec(101000),\n dur: microsec(1000),\n tid: mainThread,\n pid,\n args: {\n beginData: {\n frame: 'FAKE_FRAME_ID',\n dirtyObjects: 0,\n partialLayout: false,\n totalObjects: 1,\n },\n endData: {layoutRoots: []},\n },\n } as Trace.Types.Events.Layout,\n\n {\n cat: 'toplevel',\n name: 'Program',\n ph: Trace.Types.Events.Phase.COMPLETE,\n ts: microsec(104000),\n dur: microsec(4000),\n tid: mainThread,\n pid,\n args: {},\n },\n {\n cat: 'disabled-by-default-devtools.timeline',\n name: 'FunctionCall',\n ph: Trace.Types.Events.Phase.COMPLETE,\n ts: microsec(104000),\n dur: microsec(1000),\n tid: mainThread,\n pid,\n args: {},\n },\n {\n cat: 'disabled-by-default-devtools.timeline',\n name: 'CommitLoad',\n ph: Trace.Types.Events.Phase.COMPLETE,\n ts: microsec(105000),\n dur: microsec(1000),\n tid: mainThread,\n pid,\n args: {},\n },\n {\n cat: 'disabled-by-default-devtools.timeline',\n name: 'Layout',\n ph: Trace.Types.Events.Phase.COMPLETE,\n ts: microsec(107000),\n dur: microsec(1000),\n tid: mainThread,\n pid,\n args: {\n beginData: {\n frame: 'FAKE_FRAME_ID',\n dirtyObjects: 0,\n partialLayout: false,\n totalObjects: 1,\n },\n endData: {layoutRoots: []},\n },\n } as Trace.Types.Events.Layout,\n ];\n\n const rangeStats101To103 = Timeline.TimelineUIUtils.TimelineUIUtils.statsForTimeRange(\n events,\n Trace.Types.Timing.MilliSeconds(101),\n Trace.Types.Timing.MilliSeconds(103),\n );\n assert.deepEqual(rangeStats101To103, {\n other: 1,\n rendering: 1,\n scripting: 0,\n idle: 0,\n });\n const rangeStats104To109 = Timeline.TimelineUIUtils.TimelineUIUtils.statsForTimeRange(\n events,\n Trace.Types.Timing.MilliSeconds(104),\n Trace.Types.Timing.MilliSeconds(109),\n );\n assert.deepEqual(rangeStats104To109, {\n other: 2,\n rendering: 1,\n scripting: 1,\n idle: 1,\n });\n });\n });\n\n describe('isMarkerEvent', () => {\n it('is true for a timestamp event', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz');\n const timestamp = parsedTrace.Renderer.allTraceEntries.find(Trace.Types.Events.isTimeStamp);\n assert.isOk(timestamp);\n assert.isTrue(Timeline.TimelineUIUtils.isMarkerEvent(parsedTrace, timestamp));\n });\n\n it('is true for a Mark First Paint event', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz');\n const markFirstPaint = parsedTrace.PageLoadMetrics.allMarkerEvents.find(Trace.Types.Events.isFirstPaint);\n assert.isOk(markFirstPaint);\n assert.isTrue(Timeline.TimelineUIUtils.isMarkerEvent(parsedTrace, markFirstPaint));\n });\n\n it('is true for a Mark FCP event', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz');\n const markFCPEvent = parsedTrace.PageLoadMetrics.allMarkerEvents.find(Trace.Types.Events.isFirstContentfulPaint);\n assert.isOk(markFCPEvent);\n assert.isTrue(Timeline.TimelineUIUtils.isMarkerEvent(parsedTrace, markFCPEvent));\n });\n\n it('is false for a Mark FCP event not on the main frame', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz');\n const markFCPEvent = parsedTrace.PageLoadMetrics.allMarkerEvents.find(Trace.Types.Events.isFirstContentfulPaint);\n assert.isOk(markFCPEvent);\n assert.isOk(markFCPEvent.args);\n // Now make a copy (so we do not mutate any data) and pretend it is not on the main frame.\n const copyOfEvent = {...markFCPEvent, args: {...markFCPEvent.args}};\n copyOfEvent.args.frame = 'not-the-main-frame';\n assert.isFalse(Timeline.TimelineUIUtils.isMarkerEvent(parsedTrace, copyOfEvent));\n });\n\n it('is true for a MarkDOMContent event', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz');\n const markDOMContentEvent = parsedTrace.PageLoadMetrics.allMarkerEvents.find(Trace.Types.Events.isMarkDOMContent);\n assert.isOk(markDOMContentEvent);\n assert.isTrue(Timeline.TimelineUIUtils.isMarkerEvent(parsedTrace, markDOMContentEvent));\n });\n\n it('is true for a MarkLoad event', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz');\n const markLoadEvent = parsedTrace.PageLoadMetrics.allMarkerEvents.find(Trace.Types.Events.isMarkLoad);\n assert.isOk(markLoadEvent);\n assert.isTrue(Timeline.TimelineUIUtils.isMarkerEvent(parsedTrace, markLoadEvent));\n });\n\n it('is true for a LCP candiadate event', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz');\n const markLCPCandidate =\n parsedTrace.PageLoadMetrics.allMarkerEvents.find(Trace.Types.Events.isLargestContentfulPaintCandidate);\n assert.isOk(markLCPCandidate);\n assert.isTrue(Timeline.TimelineUIUtils.isMarkerEvent(parsedTrace, markLCPCandidate));\n });\n\n it('is false for a MarkDOMContent event not on outermost main frame', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-initial-url.json.gz');\n const markDOMContentEvent = parsedTrace.PageLoadMetrics.allMarkerEvents.find(Trace.Types.Events.isMarkDOMContent);\n assert.isOk(markDOMContentEvent);\n assert.isOk(markDOMContentEvent.args);\n assert.isOk(markDOMContentEvent.args.data);\n\n const copyOfEventNotOutermostFrame = {\n ...markDOMContentEvent,\n args: {\n ...markDOMContentEvent.args,\n data: {\n ...markDOMContentEvent.args.data,\n isOutermostMainFrame: false,\n },\n },\n\n };\n assert.isFalse(Timeline.TimelineUIUtils.isMarkerEvent(parsedTrace, copyOfEventNotOutermostFrame));\n });\n });\n\n describe('displayNameForFrame', () => {\n it('trims the URL at 80 chars by default', async () => {\n const frame: Trace.Types.Events.TraceFrame = {\n name: 'test-frame',\n url: 'https://' +\n 'a'.repeat(80),\n frame: 'frame-id',\n processId: Trace.Types.Events.ProcessID(1),\n };\n const name = Timeline.TimelineUIUtils.TimelineUIUtils.displayNameForFrame(frame);\n assert.strictEqual(name, `https://${'a'.repeat(72) /* 80 minus the 8 chars for 'https://' */}`);\n assert.lengthOf(name, 80);\n });\n\n it('uses the frame name if the URL is about:', async () => {\n const frame: Trace.Types.Events.TraceFrame = {\n name: 'test-frame',\n url: 'about:blank',\n frame: 'frame-id',\n processId: Trace.Types.Events.ProcessID(1),\n };\n const name = Timeline.TimelineUIUtils.TimelineUIUtils.displayNameForFrame(frame);\n assert.strictEqual(name, '\"test-frame\"');\n });\n\n it('trims the frame name from the middle if it is too long', async () => {\n const frame: Trace.Types.Events.TraceFrame = {\n name: 'test-frame-that-is-long',\n url: 'about:blank',\n frame: 'frame-id',\n processId: Trace.Types.Events.ProcessID(1),\n };\n const name = Timeline.TimelineUIUtils.TimelineUIUtils.displayNameForFrame(frame, 10);\n assert.strictEqual(name, '\"test-…long\"');\n });\n });\n\n describe('buildDetailsNodeForMarkerEvents', () => {\n it('builds the right link for an LCP Event', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const markLCPEvent = getEventOfType(\n parsedTrace.PageLoadMetrics.allMarkerEvents, Trace.Types.Events.isLargestContentfulPaintCandidate);\n const html = Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsNodeForMarkerEvents(\n markLCPEvent,\n );\n const url = html.querySelector('x-link')?.getAttribute('href');\n assert.strictEqual(url, 'https://web.dev/lcp/');\n assert.strictEqual(html.innerText, 'Learn more about largest contentful paint.');\n });\n\n it('builds the right link for an FCP Event', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const markFCPEvent =\n getEventOfType(parsedTrace.PageLoadMetrics.allMarkerEvents, Trace.Types.Events.isFirstContentfulPaint);\n const html = Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsNodeForMarkerEvents(\n markFCPEvent,\n );\n const url = html.querySelector('x-link')?.getAttribute('href');\n assert.strictEqual(url, 'https://web.dev/first-contentful-paint/');\n assert.strictEqual(html.innerText, 'Learn more about first contentful paint.');\n });\n\n it('builds a generic event for other marker events', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const markLoadEvent = getEventOfType(parsedTrace.PageLoadMetrics.allMarkerEvents, Trace.Types.Events.isMarkLoad);\n const html = Timeline.TimelineUIUtils.TimelineUIUtils.buildDetailsNodeForMarkerEvents(\n markLoadEvent,\n );\n const url = html.querySelector('x-link')?.getAttribute('href');\n assert.strictEqual(url, 'https://web.dev/user-centric-performance-metrics/');\n assert.strictEqual(html.innerText, 'Learn more about page performance metrics.');\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/TimingsTrackAppender.d.ts b/public/panels/timeline/TimingsTrackAppender.d.ts index fc405ded6..9f5f309db 100644 --- a/public/panels/timeline/TimingsTrackAppender.d.ts +++ b/public/panels/timeline/TimingsTrackAppender.d.ts @@ -1,5 +1,5 @@ import type * as Common from '../../core/common/common.js'; -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import { type CompatibilityTracksAppender, type HighlightedEntryInfo, type TrackAppender, type TrackAppenderName } from './CompatibilityTracksAppender.js'; import { type TimelineMarkerStyle } from './TimelineUIUtils.js'; /** @@ -12,7 +12,7 @@ export declare const SORT_ORDER_PAGE_LOAD_MARKERS: Readonly !TraceEngine.Handlers.ModelHandlers.ExtensionTraceData.extensionDataInTiming(m)); - const performanceMeasures = this.#traceParsedData.UserTimings.performanceMeasures.filter(m => !TraceEngine.Handlers.ModelHandlers.ExtensionTraceData.extensionDataInTiming(m)); - const timestampEvents = this.#traceParsedData.UserTimings.timestampEvents; - const consoleTimings = this.#traceParsedData.UserTimings.consoleTimings; + const performanceMarks = this.#parsedTrace.UserTimings.performanceMarks.filter(m => !Trace.Handlers.ModelHandlers.ExtensionTraceData.extensionDataInTiming(m)); + const performanceMeasures = this.#parsedTrace.UserTimings.performanceMeasures.filter(m => !Trace.Handlers.ModelHandlers.ExtensionTraceData.extensionDataInTiming(m)); + const timestampEvents = this.#parsedTrace.UserTimings.timestampEvents; + const consoleTimings = this.#parsedTrace.UserTimings.consoleTimings; if (extensionMarkersAreEmpty && pageloadMarkers.length === 0 && performanceMarks.length === 0 && performanceMeasures.length === 0 && timestampEvents.length === 0 && consoleTimings.length === 0) { return trackStartLevel; @@ -86,7 +86,7 @@ export class TimingsTrackAppender { * appended. */ #appendTrackHeaderAtLevel(currentLevel, expanded) { - const trackIsCollapsible = this.#traceParsedData.UserTimings.performanceMeasures.length > 0; + const trackIsCollapsible = this.#parsedTrace.UserTimings.performanceMeasures.length > 0; const style = buildGroupStyle({ useFirstLineForOverview: true, collapsible: trackIsCollapsible }); const group = buildTrackHeader("timings" /* VisualLoggingTrackName.TIMINGS */, currentLevel, i18nString(UIStrings.timings), style, /* selectable= */ true, expanded); this.#compatibilityBuilder.registerTrackForGroup(group, this); @@ -129,7 +129,7 @@ export class TimingsTrackAppender { * page load markers (the first available level to append more data). */ #appendMarkersAtLevel(currentLevel) { - let markers = this.#traceParsedData.PageLoadMetrics.allMarkerEvents; + let markers = this.#parsedTrace.PageLoadMetrics.allMarkerEvents; markers = markers.concat(ExtensionDataGatherer.instance().getExtensionData().extensionMarkers) .sort((m1, m2) => m1.ts - m2.ts); if (markers.length === 0) { @@ -142,15 +142,15 @@ export class TimingsTrackAppender { this.#compatibilityBuilder.getFlameChartTimelineData().entryTotalTimes[index] = Number.NaN; } } - const minTimeMs = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(this.#traceParsedData.Meta.traceBounds.min); + const minTimeMs = Trace.Helpers.Timing.microSecondsToMilliseconds(this.#parsedTrace.Meta.traceBounds.min); const flameChartMarkers = markers.map(marker => { // The timestamp for user timing trace events is set to the // start time passed by the user at the call site of the timing // (based on the UserTiming spec), meaning we can use event.ts // directly. // https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/timing/performance_user_timing.cc;l=236;drc=494419358caf690316f160a1f27d9e771a14c033 - const startTimeMs = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(marker.ts); - const style = TraceEngine.Types.Extensions.isSyntheticExtensionEntry(marker) ? + const startTimeMs = Trace.Helpers.Timing.microSecondsToMilliseconds(marker.ts); + const style = Trace.Types.Extensions.isSyntheticExtensionEntry(marker) ? this.markerStyleForExtensionMarker(marker) : this.markerStyleForPageLoadEvent(marker); return new TimelineFlameChartMarker(startTimeMs, startTimeMs - minTimeMs, style); @@ -173,27 +173,27 @@ export class TimingsTrackAppender { const tallMarkerDashStyle = [6, 4]; let title = ''; let color = 'grey'; - if (TraceEngine.Types.TraceEvents.isTraceEventMarkDOMContent(markerEvent)) { + if (Trace.Types.Events.isMarkDOMContent(markerEvent)) { color = '#0867CB'; - title = "DCL" /* TraceEngine.Handlers.ModelHandlers.PageLoadMetrics.MetricName.DCL */; + title = "DCL" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.DCL */; } - if (TraceEngine.Types.TraceEvents.isTraceEventMarkLoad(markerEvent)) { + if (Trace.Types.Events.isMarkLoad(markerEvent)) { color = '#B31412'; - title = "L" /* TraceEngine.Handlers.ModelHandlers.PageLoadMetrics.MetricName.L */; + title = "L" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.L */; } - if (TraceEngine.Types.TraceEvents.isTraceEventFirstPaint(markerEvent)) { + if (Trace.Types.Events.isFirstPaint(markerEvent)) { color = '#228847'; - title = "FP" /* TraceEngine.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FP */; + title = "FP" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FP */; } - if (TraceEngine.Types.TraceEvents.isTraceEventFirstContentfulPaint(markerEvent)) { + if (Trace.Types.Events.isFirstContentfulPaint(markerEvent)) { color = '#1A6937'; - title = "FCP" /* TraceEngine.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP */; + title = "FCP" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP */; } - if (TraceEngine.Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate(markerEvent)) { + if (Trace.Types.Events.isLargestContentfulPaintCandidate(markerEvent)) { color = '#1A3422'; - title = "LCP" /* TraceEngine.Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP */; + title = "LCP" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP */; } - if (TraceEngine.Types.TraceEvents.isTraceEventNavigationStart(markerEvent)) { + if (Trace.Types.Events.isNavigationStart(markerEvent)) { color = '#FF9800'; title = ''; } @@ -223,10 +223,10 @@ export class TimingsTrackAppender { * Gets the color an event added by this appender should be rendered with. */ colorForEvent(event) { - if (TraceEngine.Types.TraceEvents.eventIsPageLoadEvent(event)) { + if (Trace.Types.Events.eventIsPageLoadEvent(event)) { return this.markerStyleForPageLoadEvent(event).color; } - if (TraceEngine.Types.Extensions.isSyntheticExtensionEntry(event)) { + if (Trace.Types.Extensions.isSyntheticExtensionEntry(event)) { return Extensions.ExtensionUI.extensionEntryColor(event); } // Performance and console timings. @@ -236,8 +236,8 @@ export class TimingsTrackAppender { * Gets the title an event added by this appender should be rendered with. */ titleForEvent(event) { - const metricsHandler = TraceEngine.Handlers.ModelHandlers.PageLoadMetrics; - if (TraceEngine.Types.TraceEvents.eventIsPageLoadEvent(event)) { + const metricsHandler = Trace.Handlers.ModelHandlers.PageLoadMetrics; + if (Trace.Types.Events.eventIsPageLoadEvent(event)) { switch (event.name) { case 'MarkDOMContent': return "DCL" /* metricsHandler.MetricName.DCL */; @@ -255,10 +255,10 @@ export class TimingsTrackAppender { return event.name; } } - if (TraceEngine.Types.TraceEvents.isTraceEventTimeStamp(event)) { + if (Trace.Types.Events.isTimeStamp(event)) { return `${event.name}: ${event.args.data.message}`; } - if (TraceEngine.Types.TraceEvents.isTraceEventPerformanceMark(event)) { + if (Trace.Types.Events.isPerformanceMark(event)) { return `[mark]: ${event.name}`; } return event.name; @@ -268,17 +268,16 @@ export class TimingsTrackAppender { * is hovered in the timeline. */ highlightedEntryInfo(event) { - const title = TraceEngine.Types.Extensions.isSyntheticExtensionEntry(event) && event.args.tooltipText ? + const title = Trace.Types.Extensions.isSyntheticExtensionEntry(event) && event.args.tooltipText ? event.args.tooltipText : this.titleForEvent(event); // If an event is a marker event, rather than show a duration of 0, we can instead show the time that the event happened, which is much more useful. We do this currently for: // Page load events: DCL, FCP and LCP // performance.mark() events // console.timestamp() events - if (TraceEngine.Types.TraceEvents.isTraceEventMarkerEvent(event) || - TraceEngine.Types.TraceEvents.isTraceEventPerformanceMark(event) || - TraceEngine.Types.TraceEvents.isTraceEventTimeStamp(event)) { - const timeOfEvent = TraceEngine.Helpers.Timing.timeStampForEventAdjustedByClosestNavigation(event, this.#traceParsedData.Meta.traceBounds, this.#traceParsedData.Meta.navigationsByNavigationId, this.#traceParsedData.Meta.navigationsByFrameId); + if (Trace.Types.Events.isMarkerEvent(event) || Trace.Types.Events.isPerformanceMark(event) || + Trace.Types.Events.isTimeStamp(event)) { + const timeOfEvent = Trace.Helpers.Timing.timeStampForEventAdjustedByClosestNavigation(event, this.#parsedTrace.Meta.traceBounds, this.#parsedTrace.Meta.navigationsByNavigationId, this.#parsedTrace.Meta.navigationsByFrameId); return { title, formattedTime: getFormattedTime(timeOfEvent) }; } return { title, formattedTime: getFormattedTime(event.dur) }; diff --git a/public/panels/timeline/TimingsTrackAppender.js.map b/public/panels/timeline/TimingsTrackAppender.js.map index 9a8f09917..5df4168db 100644 --- a/public/panels/timeline/TimingsTrackAppender.js.map +++ b/public/panels/timeline/TimingsTrackAppender.js.map @@ -1 +1 @@ -{"version":3,"file":"TimingsTrackAppender.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimingsTrackAppender.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport type * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\n\nimport {buildGroupStyle, buildTrackHeader, getFormattedTime} from './AppenderUtils.js';\nimport {\n type CompatibilityTracksAppender,\n type HighlightedEntryInfo,\n type TrackAppender,\n type TrackAppenderName,\n VisualLoggingTrackName,\n} from './CompatibilityTracksAppender.js';\nimport {ExtensionDataGatherer} from './ExtensionDataGatherer.js';\nimport * as Extensions from './extensions/extensions.js';\nimport {TimelineFlameChartMarker} from './TimelineFlameChartView.js';\nimport {type TimelineMarkerStyle} from './TimelineUIUtils.js';\n\nconst UIStrings = {\n /**\n *@description Text in Timeline Flame Chart Data Provider of the Performance panel\n */\n timings: 'Timings',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/TimingsTrackAppender.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\ntype TimelineMarkerEntry =\n TraceEngine.Types.Extensions.SyntheticExtensionMarker|TraceEngine.Types.TraceEvents.PageLoadEvent;\n\n/**\n * This defines the order these markers will be rendered if they are at the\n * same timestamp. The smaller number will be shown first - e.g. so if MarkFCP,\n * MarkDOMContent and MarkLCPCandidate have the same timestamp, visually we\n * will render [FCP][DCL][LCP] everytime.\n */\nexport const SORT_ORDER_PAGE_LOAD_MARKERS: Readonly> = {\n [TraceEngine.Types.TraceEvents.KnownEventName.NAVIGATION_START]: 0,\n [TraceEngine.Types.TraceEvents.KnownEventName.MARK_LOAD]: 1,\n [TraceEngine.Types.TraceEvents.KnownEventName.MARK_FCP]: 2,\n [TraceEngine.Types.TraceEvents.KnownEventName.MARK_FIRST_PAINT]: 2,\n [TraceEngine.Types.TraceEvents.KnownEventName.MARK_DOM_CONTENT]: 3,\n [TraceEngine.Types.TraceEvents.KnownEventName.MARK_LCP_CANDIDATE]: 4,\n};\n\nexport class TimingsTrackAppender implements TrackAppender {\n readonly appenderName: TrackAppenderName = 'Timings';\n\n #colorGenerator: Common.Color.Generator;\n #compatibilityBuilder: CompatibilityTracksAppender;\n #traceParsedData: Readonly;\n\n /**\n * Before rendering the markers we group them by timestamp. This is because\n * if we have multiple markers (e.g. FCP and LCP) at the same time, we want\n * to ensure that we visually render FCP before LCP - else it's confusing\n * to the user to see LCP appear before FCP, even though they are at the\n * same timestamp.\n * We only do this for PageLoadMarkers - any extension based markers are\n * not sorted. If an extension marker happens to be at the same time as\n * LCP, the native LCP event is preferred and shown first.\n * Because we create an instance of an Appender per trace, we can cache this rather than calculate on each run.\n */\n #cachedMarkersByTimestamp: Map|null = null;\n\n constructor(\n compatibilityBuilder: CompatibilityTracksAppender, traceParsedData: TraceEngine.Handlers.Types.TraceParseData,\n colorGenerator: Common.Color.Generator) {\n this.#compatibilityBuilder = compatibilityBuilder;\n this.#colorGenerator = colorGenerator;\n this.#traceParsedData = traceParsedData;\n }\n\n /**\n * Appends into the flame chart data the data corresponding to the\n * timings track.\n * @param trackStartLevel the horizontal level of the flame chart events where\n * the track's events will start being appended.\n * @param expanded wether the track should be rendered expanded.\n * @returns the first available level to append more data after having\n * appended the track's events.\n */\n appendTrackAtLevel(trackStartLevel: number, expanded?: boolean): number {\n const extensionMarkers = ExtensionDataGatherer.instance().getExtensionData().extensionMarkers;\n const pageloadMarkers = this.#traceParsedData.PageLoadMetrics.allMarkerEvents;\n const extensionMarkersAreEmpty = extensionMarkers.length === 0;\n const performanceMarks = this.#traceParsedData.UserTimings.performanceMarks.filter(\n m => !TraceEngine.Handlers.ModelHandlers.ExtensionTraceData.extensionDataInTiming(m));\n const performanceMeasures = this.#traceParsedData.UserTimings.performanceMeasures.filter(\n m => !TraceEngine.Handlers.ModelHandlers.ExtensionTraceData.extensionDataInTiming(m));\n const timestampEvents = this.#traceParsedData.UserTimings.timestampEvents;\n const consoleTimings = this.#traceParsedData.UserTimings.consoleTimings;\n\n if (extensionMarkersAreEmpty && pageloadMarkers.length === 0 && performanceMarks.length === 0 &&\n performanceMeasures.length === 0 && timestampEvents.length === 0 && consoleTimings.length === 0) {\n return trackStartLevel;\n }\n this.#appendTrackHeaderAtLevel(trackStartLevel, expanded);\n let newLevel = this.#appendMarkersAtLevel(trackStartLevel);\n newLevel = this.#compatibilityBuilder.appendEventsAtLevel(performanceMarks, newLevel, this);\n newLevel = this.#compatibilityBuilder.appendEventsAtLevel(performanceMeasures, newLevel, this);\n newLevel = this.#compatibilityBuilder.appendEventsAtLevel(timestampEvents, newLevel, this);\n return this.#compatibilityBuilder.appendEventsAtLevel(consoleTimings, newLevel, this);\n }\n\n /**\n * Adds into the flame chart data the header corresponding to the\n * timings track. A header is added in the shape of a group in the\n * flame chart data. A group has a predefined style and a reference\n * to the definition of the legacy track (which should be removed\n * in the future).\n * @param currentLevel the flame chart level at which the header is\n * appended.\n */\n #appendTrackHeaderAtLevel(currentLevel: number, expanded?: boolean): void {\n const trackIsCollapsible = this.#traceParsedData.UserTimings.performanceMeasures.length > 0;\n const style = buildGroupStyle({useFirstLineForOverview: true, collapsible: trackIsCollapsible});\n const group = buildTrackHeader(\n VisualLoggingTrackName.TIMINGS, currentLevel, i18nString(UIStrings.timings), style, /* selectable= */ true,\n expanded);\n this.#compatibilityBuilder.registerTrackForGroup(group, this);\n }\n\n #sortMarkersForPreferredVisualOrder(markers: TimelineMarkerEntry[]): void {\n markers.sort((m1, m2) => {\n const m1Index = SORT_ORDER_PAGE_LOAD_MARKERS[m1.name] ?? Infinity;\n const m2Index = SORT_ORDER_PAGE_LOAD_MARKERS[m2.name] ?? Infinity;\n return m1Index - m2Index;\n });\n }\n\n /**\n * Group markers into a map, where keys are timestamps and the values are markers that have the same timestamp.\n */\n #groupMarkersByTimestamp(markers: TimelineMarkerEntry[]):\n Map {\n if (this.#cachedMarkersByTimestamp) {\n return this.#cachedMarkersByTimestamp;\n }\n const markersByTimestamp = new Map();\n\n markers.forEach(marker => {\n const forTime = markersByTimestamp.get(marker.ts) || [];\n forTime.push(marker);\n markersByTimestamp.set(marker.ts, forTime);\n });\n\n for (const markersAtTime of markersByTimestamp.values()) {\n if (markersAtTime.length > 1) {\n this.#sortMarkersForPreferredVisualOrder(markersAtTime);\n }\n }\n\n this.#cachedMarkersByTimestamp = markersByTimestamp;\n return this.#cachedMarkersByTimestamp;\n }\n\n /**\n * Adds into the flame chart data the trace events corresponding\n * to page load markers (LCP, FCP, L, etc.). These are taken straight\n * from the PageLoadMetrics handler.\n * @param currentLevel the flame chart level from which markers will\n * be appended.\n * @returns the next level after the last occupied by the appended\n * page load markers (the first available level to append more data).\n */\n #appendMarkersAtLevel(currentLevel: number): number {\n let markers: TimelineMarkerEntry[] = this.#traceParsedData.PageLoadMetrics.allMarkerEvents;\n markers = markers.concat(ExtensionDataGatherer.instance().getExtensionData().extensionMarkers)\n .sort((m1, m2) => m1.ts - m2.ts);\n if (markers.length === 0) {\n return currentLevel;\n }\n const markersByTimestamp = this.#groupMarkersByTimestamp(markers);\n for (const markersAtTime of markersByTimestamp.values()) {\n for (const marker of markersAtTime) {\n const index = this.#compatibilityBuilder.appendEventAtLevel(marker, currentLevel, this);\n this.#compatibilityBuilder.getFlameChartTimelineData().entryTotalTimes[index] = Number.NaN;\n }\n }\n\n const minTimeMs = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(this.#traceParsedData.Meta.traceBounds.min);\n const flameChartMarkers = markers.map(marker => {\n // The timestamp for user timing trace events is set to the\n // start time passed by the user at the call site of the timing\n // (based on the UserTiming spec), meaning we can use event.ts\n // directly.\n // https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/timing/performance_user_timing.cc;l=236;drc=494419358caf690316f160a1f27d9e771a14c033\n const startTimeMs = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(marker.ts);\n const style = TraceEngine.Types.Extensions.isSyntheticExtensionEntry(marker) ?\n this.markerStyleForExtensionMarker(marker) :\n this.markerStyleForPageLoadEvent(marker);\n return new TimelineFlameChartMarker(startTimeMs, startTimeMs - minTimeMs, style);\n });\n this.#compatibilityBuilder.getFlameChartTimelineData().markers.push(...flameChartMarkers);\n // TODO: we would like to have markers share the level with the rest but...\n // due to how CompatTrackAppender.appendEventsAtLevel tweaks the legacyEntryTypeByLevel array, it would take some work\n return ++currentLevel;\n }\n\n /*\n ------------------------------------------------------------------------------------\n The following methods are invoked by the flame chart renderer to query features about\n events on rendering.\n ------------------------------------------------------------------------------------\n */\n\n /**\n * Gets the style for a page load marker event.\n */\n markerStyleForPageLoadEvent(markerEvent: TraceEngine.Types.TraceEvents.PageLoadEvent): TimelineMarkerStyle {\n const tallMarkerDashStyle = [6, 4];\n let title = '';\n let color = 'grey';\n if (TraceEngine.Types.TraceEvents.isTraceEventMarkDOMContent(markerEvent)) {\n color = '#0867CB';\n title = TraceEngine.Handlers.ModelHandlers.PageLoadMetrics.MetricName.DCL;\n }\n if (TraceEngine.Types.TraceEvents.isTraceEventMarkLoad(markerEvent)) {\n color = '#B31412';\n title = TraceEngine.Handlers.ModelHandlers.PageLoadMetrics.MetricName.L;\n }\n if (TraceEngine.Types.TraceEvents.isTraceEventFirstPaint(markerEvent)) {\n color = '#228847';\n title = TraceEngine.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FP;\n }\n if (TraceEngine.Types.TraceEvents.isTraceEventFirstContentfulPaint(markerEvent)) {\n color = '#1A6937';\n title = TraceEngine.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP;\n }\n if (TraceEngine.Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate(markerEvent)) {\n color = '#1A3422';\n title = TraceEngine.Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP;\n }\n if (TraceEngine.Types.TraceEvents.isTraceEventNavigationStart(markerEvent)) {\n color = '#FF9800';\n title = '';\n }\n return {\n title,\n dashStyle: tallMarkerDashStyle,\n lineWidth: 0.5,\n color,\n tall: true,\n lowPriority: false,\n };\n }\n\n markerStyleForExtensionMarker(markerEvent: TraceEngine.Types.Extensions.SyntheticExtensionMarker):\n TimelineMarkerStyle {\n const tallMarkerDashStyle = [6, 4];\n const title = markerEvent.name;\n const color = Extensions.ExtensionUI.extensionEntryColor(markerEvent);\n return {\n title,\n dashStyle: tallMarkerDashStyle,\n lineWidth: 0.5,\n color,\n tall: true,\n lowPriority: false,\n };\n }\n\n /**\n * Gets the color an event added by this appender should be rendered with.\n */\n colorForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): string {\n if (TraceEngine.Types.TraceEvents.eventIsPageLoadEvent(event)) {\n return this.markerStyleForPageLoadEvent(event).color;\n }\n if (TraceEngine.Types.Extensions.isSyntheticExtensionEntry(event)) {\n return Extensions.ExtensionUI.extensionEntryColor(event);\n }\n // Performance and console timings.\n return this.#colorGenerator.colorForID(event.name);\n }\n\n /**\n * Gets the title an event added by this appender should be rendered with.\n */\n titleForEvent(event: TraceEngine.Types.TraceEvents.TraceEventData): string {\n const metricsHandler = TraceEngine.Handlers.ModelHandlers.PageLoadMetrics;\n if (TraceEngine.Types.TraceEvents.eventIsPageLoadEvent(event)) {\n switch (event.name) {\n case 'MarkDOMContent':\n return metricsHandler.MetricName.DCL;\n case 'MarkLoad':\n return metricsHandler.MetricName.L;\n case 'firstContentfulPaint':\n return metricsHandler.MetricName.FCP;\n case 'firstPaint':\n return metricsHandler.MetricName.FP;\n case 'largestContentfulPaint::Candidate':\n return metricsHandler.MetricName.LCP;\n case 'navigationStart':\n return '';\n default:\n return event.name;\n }\n }\n if (TraceEngine.Types.TraceEvents.isTraceEventTimeStamp(event)) {\n return `${event.name}: ${event.args.data.message}`;\n }\n if (TraceEngine.Types.TraceEvents.isTraceEventPerformanceMark(event)) {\n return `[mark]: ${event.name}`;\n }\n return event.name;\n }\n\n /**\n * Returns the info shown when an event added by this appender\n * is hovered in the timeline.\n */\n highlightedEntryInfo(event: TraceEngine.Types.TraceEvents.TraceEventData): HighlightedEntryInfo {\n const title = TraceEngine.Types.Extensions.isSyntheticExtensionEntry(event) && event.args.tooltipText ?\n event.args.tooltipText :\n this.titleForEvent(event);\n\n // If an event is a marker event, rather than show a duration of 0, we can instead show the time that the event happened, which is much more useful. We do this currently for:\n // Page load events: DCL, FCP and LCP\n // performance.mark() events\n // console.timestamp() events\n if (TraceEngine.Types.TraceEvents.isTraceEventMarkerEvent(event) ||\n TraceEngine.Types.TraceEvents.isTraceEventPerformanceMark(event) ||\n TraceEngine.Types.TraceEvents.isTraceEventTimeStamp(event)) {\n const timeOfEvent = TraceEngine.Helpers.Timing.timeStampForEventAdjustedByClosestNavigation(\n event,\n this.#traceParsedData.Meta.traceBounds,\n this.#traceParsedData.Meta.navigationsByNavigationId,\n this.#traceParsedData.Meta.navigationsByFrameId,\n );\n return {title, formattedTime: getFormattedTime(timeOfEvent)};\n }\n\n return {title, formattedTime: getFormattedTime(event.dur)};\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"TimingsTrackAppender.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/TimingsTrackAppender.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport type * as Common from '../../core/common/common.js';\nimport * as i18n from '../../core/i18n/i18n.js';\nimport * as Trace from '../../models/trace/trace.js';\n\nimport {buildGroupStyle, buildTrackHeader, getFormattedTime} from './AppenderUtils.js';\nimport {\n type CompatibilityTracksAppender,\n type HighlightedEntryInfo,\n type TrackAppender,\n type TrackAppenderName,\n VisualLoggingTrackName,\n} from './CompatibilityTracksAppender.js';\nimport {ExtensionDataGatherer} from './ExtensionDataGatherer.js';\nimport * as Extensions from './extensions/extensions.js';\nimport {TimelineFlameChartMarker} from './TimelineFlameChartView.js';\nimport {type TimelineMarkerStyle} from './TimelineUIUtils.js';\n\nconst UIStrings = {\n /**\n *@description Text in Timeline Flame Chart Data Provider of the Performance panel\n */\n timings: 'Timings',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/TimingsTrackAppender.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\ntype TimelineMarkerEntry = Trace.Types.Extensions.SyntheticExtensionMarker|Trace.Types.Events.PageLoadEvent;\n\n/**\n * This defines the order these markers will be rendered if they are at the\n * same timestamp. The smaller number will be shown first - e.g. so if MarkFCP,\n * MarkDOMContent and MarkLCPCandidate have the same timestamp, visually we\n * will render [FCP][DCL][LCP] everytime.\n */\nexport const SORT_ORDER_PAGE_LOAD_MARKERS: Readonly> = {\n [Trace.Types.Events.Name.NAVIGATION_START]: 0,\n [Trace.Types.Events.Name.MARK_LOAD]: 1,\n [Trace.Types.Events.Name.MARK_FCP]: 2,\n [Trace.Types.Events.Name.MARK_FIRST_PAINT]: 2,\n [Trace.Types.Events.Name.MARK_DOM_CONTENT]: 3,\n [Trace.Types.Events.Name.MARK_LCP_CANDIDATE]: 4,\n};\n\nexport class TimingsTrackAppender implements TrackAppender {\n readonly appenderName: TrackAppenderName = 'Timings';\n\n #colorGenerator: Common.Color.Generator;\n #compatibilityBuilder: CompatibilityTracksAppender;\n #parsedTrace: Readonly;\n\n /**\n * Before rendering the markers we group them by timestamp. This is because\n * if we have multiple markers (e.g. FCP and LCP) at the same time, we want\n * to ensure that we visually render FCP before LCP - else it's confusing\n * to the user to see LCP appear before FCP, even though they are at the\n * same timestamp.\n * We only do this for PageLoadMarkers - any extension based markers are\n * not sorted. If an extension marker happens to be at the same time as\n * LCP, the native LCP event is preferred and shown first.\n * Because we create an instance of an Appender per trace, we can cache this rather than calculate on each run.\n */\n #cachedMarkersByTimestamp: Map|null = null;\n\n constructor(\n compatibilityBuilder: CompatibilityTracksAppender, parsedTrace: Trace.Handlers.Types.ParsedTrace,\n colorGenerator: Common.Color.Generator) {\n this.#compatibilityBuilder = compatibilityBuilder;\n this.#colorGenerator = colorGenerator;\n this.#parsedTrace = parsedTrace;\n }\n\n /**\n * Appends into the flame chart data the data corresponding to the\n * timings track.\n * @param trackStartLevel the horizontal level of the flame chart events where\n * the track's events will start being appended.\n * @param expanded wether the track should be rendered expanded.\n * @returns the first available level to append more data after having\n * appended the track's events.\n */\n appendTrackAtLevel(trackStartLevel: number, expanded?: boolean): number {\n const extensionMarkers = ExtensionDataGatherer.instance().getExtensionData().extensionMarkers;\n const pageloadMarkers = this.#parsedTrace.PageLoadMetrics.allMarkerEvents;\n const extensionMarkersAreEmpty = extensionMarkers.length === 0;\n const performanceMarks = this.#parsedTrace.UserTimings.performanceMarks.filter(\n m => !Trace.Handlers.ModelHandlers.ExtensionTraceData.extensionDataInTiming(m));\n const performanceMeasures = this.#parsedTrace.UserTimings.performanceMeasures.filter(\n m => !Trace.Handlers.ModelHandlers.ExtensionTraceData.extensionDataInTiming(m));\n const timestampEvents = this.#parsedTrace.UserTimings.timestampEvents;\n const consoleTimings = this.#parsedTrace.UserTimings.consoleTimings;\n\n if (extensionMarkersAreEmpty && pageloadMarkers.length === 0 && performanceMarks.length === 0 &&\n performanceMeasures.length === 0 && timestampEvents.length === 0 && consoleTimings.length === 0) {\n return trackStartLevel;\n }\n this.#appendTrackHeaderAtLevel(trackStartLevel, expanded);\n let newLevel = this.#appendMarkersAtLevel(trackStartLevel);\n newLevel = this.#compatibilityBuilder.appendEventsAtLevel(performanceMarks, newLevel, this);\n newLevel = this.#compatibilityBuilder.appendEventsAtLevel(performanceMeasures, newLevel, this);\n newLevel = this.#compatibilityBuilder.appendEventsAtLevel(timestampEvents, newLevel, this);\n return this.#compatibilityBuilder.appendEventsAtLevel(consoleTimings, newLevel, this);\n }\n\n /**\n * Adds into the flame chart data the header corresponding to the\n * timings track. A header is added in the shape of a group in the\n * flame chart data. A group has a predefined style and a reference\n * to the definition of the legacy track (which should be removed\n * in the future).\n * @param currentLevel the flame chart level at which the header is\n * appended.\n */\n #appendTrackHeaderAtLevel(currentLevel: number, expanded?: boolean): void {\n const trackIsCollapsible = this.#parsedTrace.UserTimings.performanceMeasures.length > 0;\n const style = buildGroupStyle({useFirstLineForOverview: true, collapsible: trackIsCollapsible});\n const group = buildTrackHeader(\n VisualLoggingTrackName.TIMINGS, currentLevel, i18nString(UIStrings.timings), style, /* selectable= */ true,\n expanded);\n this.#compatibilityBuilder.registerTrackForGroup(group, this);\n }\n\n #sortMarkersForPreferredVisualOrder(markers: TimelineMarkerEntry[]): void {\n markers.sort((m1, m2) => {\n const m1Index = SORT_ORDER_PAGE_LOAD_MARKERS[m1.name] ?? Infinity;\n const m2Index = SORT_ORDER_PAGE_LOAD_MARKERS[m2.name] ?? Infinity;\n return m1Index - m2Index;\n });\n }\n\n /**\n * Group markers into a map, where keys are timestamps and the values are markers that have the same timestamp.\n */\n #groupMarkersByTimestamp(markers: TimelineMarkerEntry[]):\n Map {\n if (this.#cachedMarkersByTimestamp) {\n return this.#cachedMarkersByTimestamp;\n }\n const markersByTimestamp = new Map();\n\n markers.forEach(marker => {\n const forTime = markersByTimestamp.get(marker.ts) || [];\n forTime.push(marker);\n markersByTimestamp.set(marker.ts, forTime);\n });\n\n for (const markersAtTime of markersByTimestamp.values()) {\n if (markersAtTime.length > 1) {\n this.#sortMarkersForPreferredVisualOrder(markersAtTime);\n }\n }\n\n this.#cachedMarkersByTimestamp = markersByTimestamp;\n return this.#cachedMarkersByTimestamp;\n }\n\n /**\n * Adds into the flame chart data the trace events corresponding\n * to page load markers (LCP, FCP, L, etc.). These are taken straight\n * from the PageLoadMetrics handler.\n * @param currentLevel the flame chart level from which markers will\n * be appended.\n * @returns the next level after the last occupied by the appended\n * page load markers (the first available level to append more data).\n */\n #appendMarkersAtLevel(currentLevel: number): number {\n let markers: TimelineMarkerEntry[] = this.#parsedTrace.PageLoadMetrics.allMarkerEvents;\n markers = markers.concat(ExtensionDataGatherer.instance().getExtensionData().extensionMarkers)\n .sort((m1, m2) => m1.ts - m2.ts);\n if (markers.length === 0) {\n return currentLevel;\n }\n const markersByTimestamp = this.#groupMarkersByTimestamp(markers);\n for (const markersAtTime of markersByTimestamp.values()) {\n for (const marker of markersAtTime) {\n const index = this.#compatibilityBuilder.appendEventAtLevel(marker, currentLevel, this);\n this.#compatibilityBuilder.getFlameChartTimelineData().entryTotalTimes[index] = Number.NaN;\n }\n }\n\n const minTimeMs = Trace.Helpers.Timing.microSecondsToMilliseconds(this.#parsedTrace.Meta.traceBounds.min);\n const flameChartMarkers = markers.map(marker => {\n // The timestamp for user timing trace events is set to the\n // start time passed by the user at the call site of the timing\n // (based on the UserTiming spec), meaning we can use event.ts\n // directly.\n // https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/timing/performance_user_timing.cc;l=236;drc=494419358caf690316f160a1f27d9e771a14c033\n const startTimeMs = Trace.Helpers.Timing.microSecondsToMilliseconds(marker.ts);\n const style = Trace.Types.Extensions.isSyntheticExtensionEntry(marker) ?\n this.markerStyleForExtensionMarker(marker) :\n this.markerStyleForPageLoadEvent(marker);\n return new TimelineFlameChartMarker(startTimeMs, startTimeMs - minTimeMs, style);\n });\n this.#compatibilityBuilder.getFlameChartTimelineData().markers.push(...flameChartMarkers);\n // TODO: we would like to have markers share the level with the rest but...\n // due to how CompatTrackAppender.appendEventsAtLevel tweaks the legacyEntryTypeByLevel array, it would take some work\n return ++currentLevel;\n }\n\n /*\n ------------------------------------------------------------------------------------\n The following methods are invoked by the flame chart renderer to query features about\n events on rendering.\n ------------------------------------------------------------------------------------\n */\n\n /**\n * Gets the style for a page load marker event.\n */\n markerStyleForPageLoadEvent(markerEvent: Trace.Types.Events.PageLoadEvent): TimelineMarkerStyle {\n const tallMarkerDashStyle = [6, 4];\n let title = '';\n let color = 'grey';\n if (Trace.Types.Events.isMarkDOMContent(markerEvent)) {\n color = '#0867CB';\n title = Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.DCL;\n }\n if (Trace.Types.Events.isMarkLoad(markerEvent)) {\n color = '#B31412';\n title = Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.L;\n }\n if (Trace.Types.Events.isFirstPaint(markerEvent)) {\n color = '#228847';\n title = Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FP;\n }\n if (Trace.Types.Events.isFirstContentfulPaint(markerEvent)) {\n color = '#1A6937';\n title = Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP;\n }\n if (Trace.Types.Events.isLargestContentfulPaintCandidate(markerEvent)) {\n color = '#1A3422';\n title = Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP;\n }\n if (Trace.Types.Events.isNavigationStart(markerEvent)) {\n color = '#FF9800';\n title = '';\n }\n return {\n title,\n dashStyle: tallMarkerDashStyle,\n lineWidth: 0.5,\n color,\n tall: true,\n lowPriority: false,\n };\n }\n\n markerStyleForExtensionMarker(markerEvent: Trace.Types.Extensions.SyntheticExtensionMarker): TimelineMarkerStyle {\n const tallMarkerDashStyle = [6, 4];\n const title = markerEvent.name;\n const color = Extensions.ExtensionUI.extensionEntryColor(markerEvent);\n return {\n title,\n dashStyle: tallMarkerDashStyle,\n lineWidth: 0.5,\n color,\n tall: true,\n lowPriority: false,\n };\n }\n\n /**\n * Gets the color an event added by this appender should be rendered with.\n */\n colorForEvent(event: Trace.Types.Events.Event): string {\n if (Trace.Types.Events.eventIsPageLoadEvent(event)) {\n return this.markerStyleForPageLoadEvent(event).color;\n }\n if (Trace.Types.Extensions.isSyntheticExtensionEntry(event)) {\n return Extensions.ExtensionUI.extensionEntryColor(event);\n }\n // Performance and console timings.\n return this.#colorGenerator.colorForID(event.name);\n }\n\n /**\n * Gets the title an event added by this appender should be rendered with.\n */\n titleForEvent(event: Trace.Types.Events.Event): string {\n const metricsHandler = Trace.Handlers.ModelHandlers.PageLoadMetrics;\n if (Trace.Types.Events.eventIsPageLoadEvent(event)) {\n switch (event.name) {\n case 'MarkDOMContent':\n return metricsHandler.MetricName.DCL;\n case 'MarkLoad':\n return metricsHandler.MetricName.L;\n case 'firstContentfulPaint':\n return metricsHandler.MetricName.FCP;\n case 'firstPaint':\n return metricsHandler.MetricName.FP;\n case 'largestContentfulPaint::Candidate':\n return metricsHandler.MetricName.LCP;\n case 'navigationStart':\n return '';\n default:\n return event.name;\n }\n }\n if (Trace.Types.Events.isTimeStamp(event)) {\n return `${event.name}: ${event.args.data.message}`;\n }\n if (Trace.Types.Events.isPerformanceMark(event)) {\n return `[mark]: ${event.name}`;\n }\n return event.name;\n }\n\n /**\n * Returns the info shown when an event added by this appender\n * is hovered in the timeline.\n */\n highlightedEntryInfo(event: Trace.Types.Events.Event): HighlightedEntryInfo {\n const title = Trace.Types.Extensions.isSyntheticExtensionEntry(event) && event.args.tooltipText ?\n event.args.tooltipText :\n this.titleForEvent(event);\n\n // If an event is a marker event, rather than show a duration of 0, we can instead show the time that the event happened, which is much more useful. We do this currently for:\n // Page load events: DCL, FCP and LCP\n // performance.mark() events\n // console.timestamp() events\n if (Trace.Types.Events.isMarkerEvent(event) || Trace.Types.Events.isPerformanceMark(event) ||\n Trace.Types.Events.isTimeStamp(event)) {\n const timeOfEvent = Trace.Helpers.Timing.timeStampForEventAdjustedByClosestNavigation(\n event,\n this.#parsedTrace.Meta.traceBounds,\n this.#parsedTrace.Meta.navigationsByNavigationId,\n this.#parsedTrace.Meta.navigationsByFrameId,\n );\n return {title, formattedTime: getFormattedTime(timeOfEvent)};\n }\n\n return {title, formattedTime: getFormattedTime(event.dur)};\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/components/Breadcrumbs.d.ts b/public/panels/timeline/components/Breadcrumbs.d.ts index adc87ea4e..9dc8ba675 100644 --- a/public/panels/timeline/components/Breadcrumbs.d.ts +++ b/public/panels/timeline/components/Breadcrumbs.d.ts @@ -1,16 +1,16 @@ -import type * as TraceEngine from '../../../models/trace/trace.js'; -export declare function flattenBreadcrumbs(initialBreadcrumb: TraceEngine.Types.File.Breadcrumb): TraceEngine.Types.File.Breadcrumb[]; +import type * as Trace from '../../../models/trace/trace.js'; +export declare function flattenBreadcrumbs(initialBreadcrumb: Trace.Types.File.Breadcrumb): Trace.Types.File.Breadcrumb[]; export interface SetActiveBreadcrumbOptions { removeChildBreadcrumbs: boolean; updateVisibleWindow: boolean; } export declare class Breadcrumbs { - initialBreadcrumb: TraceEngine.Types.File.Breadcrumb; - activeBreadcrumb: TraceEngine.Types.File.Breadcrumb; - constructor(initialTraceWindow: TraceEngine.Types.Timing.TraceWindowMicroSeconds); - add(newBreadcrumbTraceWindow: TraceEngine.Types.Timing.TraceWindowMicroSeconds): TraceEngine.Types.File.Breadcrumb; - isTraceWindowWithinTraceWindow(child: TraceEngine.Types.Timing.TraceWindowMicroSeconds, parent: TraceEngine.Types.Timing.TraceWindowMicroSeconds): boolean; - setInitialBreadcrumbFromLoadedModifications(initialBreadcrumb: TraceEngine.Types.File.Breadcrumb): void; + initialBreadcrumb: Trace.Types.File.Breadcrumb; + activeBreadcrumb: Trace.Types.File.Breadcrumb; + constructor(initialTraceWindow: Trace.Types.Timing.TraceWindowMicroSeconds); + add(newBreadcrumbTraceWindow: Trace.Types.Timing.TraceWindowMicroSeconds): Trace.Types.File.Breadcrumb; + isTraceWindowWithinTraceWindow(child: Trace.Types.Timing.TraceWindowMicroSeconds, parent: Trace.Types.Timing.TraceWindowMicroSeconds): boolean; + setInitialBreadcrumbFromLoadedModifications(initialBreadcrumb: Trace.Types.File.Breadcrumb): void; /** * Sets a breadcrumb to be active. * Doing this will update the minimap bounds and optionally based on the @@ -21,5 +21,5 @@ export declare class Breadcrumbs { * are activating the breadcrumb to show the user that they are now within * this breadcrumb. This is used when revealing insights and annotations. */ - setActiveBreadcrumb(activeBreadcrumb: TraceEngine.Types.File.Breadcrumb, options: SetActiveBreadcrumbOptions): void; + setActiveBreadcrumb(activeBreadcrumb: Trace.Types.File.Breadcrumb, options: SetActiveBreadcrumbOptions): void; } diff --git a/public/panels/timeline/components/Breadcrumbs.js.map b/public/panels/timeline/components/Breadcrumbs.js.map index 1c0c02013..707a8c86e 100644 --- a/public/panels/timeline/components/Breadcrumbs.js.map +++ b/public/panels/timeline/components/Breadcrumbs.js.map @@ -1 +1 @@ -{"version":3,"file":"Breadcrumbs.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/components/Breadcrumbs.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as TraceEngine from '../../../models/trace/trace.js';\nimport * as TraceBounds from '../../../services/trace_bounds/trace_bounds.js';\n\nexport function flattenBreadcrumbs(initialBreadcrumb: TraceEngine.Types.File.Breadcrumb):\n TraceEngine.Types.File.Breadcrumb[] {\n const allBreadcrumbs: TraceEngine.Types.File.Breadcrumb[] = [initialBreadcrumb];\n let breadcrumbsIter: TraceEngine.Types.File.Breadcrumb = initialBreadcrumb;\n\n while (breadcrumbsIter.child !== null) {\n const iterChild = breadcrumbsIter.child;\n if (iterChild !== null) {\n allBreadcrumbs.push(iterChild);\n breadcrumbsIter = iterChild;\n }\n }\n\n return allBreadcrumbs;\n}\n\nexport interface SetActiveBreadcrumbOptions {\n removeChildBreadcrumbs: boolean;\n updateVisibleWindow: boolean;\n}\n\nexport class Breadcrumbs {\n initialBreadcrumb: TraceEngine.Types.File.Breadcrumb;\n activeBreadcrumb: TraceEngine.Types.File.Breadcrumb;\n\n constructor(initialTraceWindow: TraceEngine.Types.Timing.TraceWindowMicroSeconds) {\n this.initialBreadcrumb = {\n window: initialTraceWindow,\n child: null,\n };\n let lastBreadcrumb = this.initialBreadcrumb;\n while (lastBreadcrumb.child !== null) {\n lastBreadcrumb = lastBreadcrumb.child;\n }\n this.activeBreadcrumb = lastBreadcrumb;\n }\n\n add(newBreadcrumbTraceWindow: TraceEngine.Types.Timing.TraceWindowMicroSeconds): TraceEngine.Types.File.Breadcrumb {\n if (!this.isTraceWindowWithinTraceWindow(newBreadcrumbTraceWindow, this.activeBreadcrumb.window)) {\n throw new Error('Can not add a breadcrumb that is equal to or is outside of the parent breadcrumb TimeWindow');\n }\n\n const newBreadcrumb = {\n window: newBreadcrumbTraceWindow,\n child: null,\n };\n // To add a new Breadcrumb to the Breadcrumbs Linked List, set the child of active breadcrumb\n // to the new breadcrumb and update the active Breadcrumb to the newly added one\n this.activeBreadcrumb.child = newBreadcrumb;\n this.setActiveBreadcrumb(newBreadcrumb, {removeChildBreadcrumbs: false, updateVisibleWindow: true});\n return newBreadcrumb;\n }\n\n // Breadcumb should be within the bounds of the parent and can not have both start and end be equal to the parent\n isTraceWindowWithinTraceWindow(\n child: TraceEngine.Types.Timing.TraceWindowMicroSeconds,\n parent: TraceEngine.Types.Timing.TraceWindowMicroSeconds): boolean {\n return (child.min >= parent.min && child.max <= parent.max) &&\n !(child.min === parent.min && child.max === parent.max);\n }\n\n // Used to set an initial breadcrumbs from modifications loaded from a file\n setInitialBreadcrumbFromLoadedModifications(initialBreadcrumb: TraceEngine.Types.File.Breadcrumb): void {\n this.initialBreadcrumb = initialBreadcrumb;\n // Make last breadcrumb active\n let lastBreadcrumb = initialBreadcrumb;\n while (lastBreadcrumb.child !== null) {\n lastBreadcrumb = lastBreadcrumb.child;\n }\n this.setActiveBreadcrumb(lastBreadcrumb, {removeChildBreadcrumbs: false, updateVisibleWindow: true});\n }\n\n /**\n * Sets a breadcrumb to be active.\n * Doing this will update the minimap bounds and optionally based on the\n * `updateVisibleWindow` parameter, it will also update the active window.\n * The reason `updateVisibleWindow` is configurable is because if we are\n * changing which breadcrumb is active because we want to reveal something to\n * the user, we may have already updated the visible timeline window, but we\n * are activating the breadcrumb to show the user that they are now within\n * this breadcrumb. This is used when revealing insights and annotations.\n */\n setActiveBreadcrumb(activeBreadcrumb: TraceEngine.Types.File.Breadcrumb, options: SetActiveBreadcrumbOptions): void {\n // If the children of the activated breadcrumb need to be removed, set the child on the\n // activated breadcrumb to null. Since breadcrumbs are a linked list, this will remove all\n // of the following children.\n if (options.removeChildBreadcrumbs) {\n activeBreadcrumb.child = null;\n }\n\n // When we assign a new active breadcrumb, both the minimap bounds and the visible\n // window get set to that breadcrumb's window.\n this.activeBreadcrumb = activeBreadcrumb;\n TraceBounds.TraceBounds.BoundsManager.instance().setMiniMapBounds(\n activeBreadcrumb.window,\n );\n\n if (options.updateVisibleWindow) {\n TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(\n activeBreadcrumb.window,\n );\n }\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"Breadcrumbs.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/components/Breadcrumbs.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Trace from '../../../models/trace/trace.js';\nimport * as TraceBounds from '../../../services/trace_bounds/trace_bounds.js';\n\nexport function flattenBreadcrumbs(initialBreadcrumb: Trace.Types.File.Breadcrumb): Trace.Types.File.Breadcrumb[] {\n const allBreadcrumbs: Trace.Types.File.Breadcrumb[] = [initialBreadcrumb];\n let breadcrumbsIter: Trace.Types.File.Breadcrumb = initialBreadcrumb;\n\n while (breadcrumbsIter.child !== null) {\n const iterChild = breadcrumbsIter.child;\n if (iterChild !== null) {\n allBreadcrumbs.push(iterChild);\n breadcrumbsIter = iterChild;\n }\n }\n\n return allBreadcrumbs;\n}\n\nexport interface SetActiveBreadcrumbOptions {\n removeChildBreadcrumbs: boolean;\n updateVisibleWindow: boolean;\n}\n\nexport class Breadcrumbs {\n initialBreadcrumb: Trace.Types.File.Breadcrumb;\n activeBreadcrumb: Trace.Types.File.Breadcrumb;\n\n constructor(initialTraceWindow: Trace.Types.Timing.TraceWindowMicroSeconds) {\n this.initialBreadcrumb = {\n window: initialTraceWindow,\n child: null,\n };\n let lastBreadcrumb = this.initialBreadcrumb;\n while (lastBreadcrumb.child !== null) {\n lastBreadcrumb = lastBreadcrumb.child;\n }\n this.activeBreadcrumb = lastBreadcrumb;\n }\n\n add(newBreadcrumbTraceWindow: Trace.Types.Timing.TraceWindowMicroSeconds): Trace.Types.File.Breadcrumb {\n if (!this.isTraceWindowWithinTraceWindow(newBreadcrumbTraceWindow, this.activeBreadcrumb.window)) {\n throw new Error('Can not add a breadcrumb that is equal to or is outside of the parent breadcrumb TimeWindow');\n }\n\n const newBreadcrumb = {\n window: newBreadcrumbTraceWindow,\n child: null,\n };\n // To add a new Breadcrumb to the Breadcrumbs Linked List, set the child of active breadcrumb\n // to the new breadcrumb and update the active Breadcrumb to the newly added one\n this.activeBreadcrumb.child = newBreadcrumb;\n this.setActiveBreadcrumb(newBreadcrumb, {removeChildBreadcrumbs: false, updateVisibleWindow: true});\n return newBreadcrumb;\n }\n\n // Breadcumb should be within the bounds of the parent and can not have both start and end be equal to the parent\n isTraceWindowWithinTraceWindow(\n child: Trace.Types.Timing.TraceWindowMicroSeconds, parent: Trace.Types.Timing.TraceWindowMicroSeconds): boolean {\n return (child.min >= parent.min && child.max <= parent.max) &&\n !(child.min === parent.min && child.max === parent.max);\n }\n\n // Used to set an initial breadcrumbs from modifications loaded from a file\n setInitialBreadcrumbFromLoadedModifications(initialBreadcrumb: Trace.Types.File.Breadcrumb): void {\n this.initialBreadcrumb = initialBreadcrumb;\n // Make last breadcrumb active\n let lastBreadcrumb = initialBreadcrumb;\n while (lastBreadcrumb.child !== null) {\n lastBreadcrumb = lastBreadcrumb.child;\n }\n this.setActiveBreadcrumb(lastBreadcrumb, {removeChildBreadcrumbs: false, updateVisibleWindow: true});\n }\n\n /**\n * Sets a breadcrumb to be active.\n * Doing this will update the minimap bounds and optionally based on the\n * `updateVisibleWindow` parameter, it will also update the active window.\n * The reason `updateVisibleWindow` is configurable is because if we are\n * changing which breadcrumb is active because we want to reveal something to\n * the user, we may have already updated the visible timeline window, but we\n * are activating the breadcrumb to show the user that they are now within\n * this breadcrumb. This is used when revealing insights and annotations.\n */\n setActiveBreadcrumb(activeBreadcrumb: Trace.Types.File.Breadcrumb, options: SetActiveBreadcrumbOptions): void {\n // If the children of the activated breadcrumb need to be removed, set the child on the\n // activated breadcrumb to null. Since breadcrumbs are a linked list, this will remove all\n // of the following children.\n if (options.removeChildBreadcrumbs) {\n activeBreadcrumb.child = null;\n }\n\n // When we assign a new active breadcrumb, both the minimap bounds and the visible\n // window get set to that breadcrumb's window.\n this.activeBreadcrumb = activeBreadcrumb;\n TraceBounds.TraceBounds.BoundsManager.instance().setMiniMapBounds(\n activeBreadcrumb.window,\n );\n\n if (options.updateVisibleWindow) {\n TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(\n activeBreadcrumb.window,\n );\n }\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/components/BreadcrumbsUI.d.ts b/public/panels/timeline/components/BreadcrumbsUI.d.ts index 94380b21c..fd1e9f788 100644 --- a/public/panels/timeline/components/BreadcrumbsUI.d.ts +++ b/public/panels/timeline/components/BreadcrumbsUI.d.ts @@ -1,13 +1,13 @@ -import * as TraceEngine from '../../../models/trace/trace.js'; +import * as Trace from '../../../models/trace/trace.js'; export interface BreadcrumbsUIData { - initialBreadcrumb: TraceEngine.Types.File.Breadcrumb; - activeBreadcrumb: TraceEngine.Types.File.Breadcrumb; + initialBreadcrumb: Trace.Types.File.Breadcrumb; + activeBreadcrumb: Trace.Types.File.Breadcrumb; } export declare class BreadcrumbActivatedEvent extends Event { - breadcrumb: TraceEngine.Types.File.Breadcrumb; + breadcrumb: Trace.Types.File.Breadcrumb; childBreadcrumbsRemoved?: boolean | undefined; static readonly eventName = "breadcrumbactivated"; - constructor(breadcrumb: TraceEngine.Types.File.Breadcrumb, childBreadcrumbsRemoved?: boolean | undefined); + constructor(breadcrumb: Trace.Types.File.Breadcrumb, childBreadcrumbsRemoved?: boolean | undefined); } export declare class BreadcrumbsUI extends HTMLElement { #private; diff --git a/public/panels/timeline/components/BreadcrumbsUI.js b/public/panels/timeline/components/BreadcrumbsUI.js index 82eb77b73..ebf43544b 100644 --- a/public/panels/timeline/components/BreadcrumbsUI.js +++ b/public/panels/timeline/components/BreadcrumbsUI.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as i18n from '../../../core/i18n/i18n.js'; -import * as TraceEngine from '../../../models/trace/trace.js'; +import * as Trace from '../../../models/trace/trace.js'; import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js'; import * as IconButton from '../../../ui/components/icon_button/icon_button.js'; import * as UI from '../../../ui/legacy/legacy.js'; @@ -88,7 +88,7 @@ export class BreadcrumbsUI extends HTMLElement { void menu.show(); } #renderElement(breadcrumb, index) { - const breadcrumbRange = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(breadcrumb.window.range); + const breadcrumbRange = Trace.Helpers.Timing.microSecondsToMilliseconds(breadcrumb.window.range); // clang-format off return html `
`;\n }\n\n return contents;\n })}\n \n `;\n // clang-format on\n LitHtml.render(LitHtml.html`${html}`, this.#shadow, {host: this});\n }\n}\n\ncustomElements.define('devtools-performance-sidebar-insights', SidebarInsightsTab);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-sidebar-insights': SidebarInsightsTab;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"SidebarInsightsTab.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/components/SidebarInsightsTab.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Trace from '../../../models/trace/trace.js';\nimport * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';\nimport * as LitHtml from '../../../ui/lit-html/lit-html.js';\nimport * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';\n\nimport * as Insights from './insights/insights.js';\nimport {type ActiveInsight} from './Sidebar.js';\nimport styles from './sidebarInsightsTab.css.js';\nimport {SidebarSingleNavigation, type SidebarSingleNavigationData} from './SidebarSingleNavigation.js';\n\nexport enum InsightsCategories {\n ALL = 'All',\n INP = 'INP',\n LCP = 'LCP',\n CLS = 'CLS',\n OTHER = 'Other',\n}\n\n/** Represents the portion of the trace that insights have been collected for. */\ninterface InsightSet {\n /** If for a navigation, this is the navigationId. Else it is NO_NAVIGATION. */\n id: string;\n /** The URL. Shown in the accordion list. */\n label: string;\n}\n\nexport class SidebarInsightsTab extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-performance-sidebar-insights`;\n readonly #boundRender = this.#render.bind(this);\n readonly #shadow = this.attachShadow({mode: 'open'});\n\n #parsedTrace: Trace.Handlers.Types.ParsedTrace|null = null;\n #insights: Trace.Insights.Types.TraceInsightSets|null = null;\n #insightSets: InsightSet[]|null = null;\n #activeInsight: ActiveInsight|null = null;\n #selectedCategory: InsightsCategories = InsightsCategories.ALL;\n /**\n * When a trace has multiple navigations, we show an accordion with each\n * navigation in. You can only have one of these open at any time, and we\n * track it via this ID.\n */\n #activeNavigationId: string|null = null;\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [styles];\n }\n\n set parsedTrace(data: Trace.Handlers.Types.ParsedTrace|null) {\n if (data === this.#parsedTrace) {\n return;\n }\n this.#parsedTrace = data;\n this.#activeNavigationId = null;\n\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n set insights(data: Trace.Insights.Types.TraceInsightSets|null) {\n if (data === this.#insights) {\n return;\n }\n\n this.#insights = data;\n this.#insightSets = [];\n this.#activeNavigationId = null;\n if (!this.#insights || !this.#parsedTrace) {\n return;\n }\n\n for (const insightSets of this.#insights.values()) {\n // TODO(crbug.com/366049346): move \"shouldShow\" logic to insight result (rather than the component),\n // and if none are visible, don't push the insight set.\n this.#insightSets.push({\n id: insightSets.id,\n label: insightSets.label,\n });\n }\n\n // TODO(crbug.com/366049346): skip the first insight set if trivial.\n this.#activeNavigationId = this.#insightSets[0]?.id ?? null;\n\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n set activeInsight(active: ActiveInsight|null) {\n if (active === this.#activeInsight) {\n return;\n }\n this.#activeInsight = active;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n #onCategoryDropdownChange(event: Event): void {\n const target = event.target as HTMLOptionElement;\n const value = target.value as InsightsCategories;\n this.#selectedCategory = value;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n #navigationClicked(id: string): void {\n // New navigation clicked. Update the active insight.\n if (id !== this.#activeInsight?.navigationId) {\n this.dispatchEvent(new Insights.SidebarInsight.InsightDeactivated());\n }\n this.#activeNavigationId = id;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n #navigationHovered(id: string): void {\n const data = this.#insights?.get(id);\n data && this.dispatchEvent(new Insights.SidebarInsight.NavigationBoundsHovered(data.bounds));\n }\n\n #navigationUnhovered(): void {\n this.dispatchEvent(new Insights.SidebarInsight.NavigationBoundsHovered());\n }\n\n #render(): void {\n if (!this.#parsedTrace || !this.#insights || !this.#insightSets) {\n LitHtml.render(LitHtml.nothing, this.#shadow, {host: this});\n return;\n }\n\n const hasMultipleInsightSets = this.#insightSets.length > 1;\n\n // clang-format off\n const html = LitHtml.html`\n \n\n
\n ${this.#insightSets.map(({id, label}) => {\n const data = {\n parsedTrace: this.#parsedTrace,\n insights: this.#insights,\n navigationId: id, // TODO(crbug.com/366049346): rename `navigationId`.\n activeCategory: this.#selectedCategory,\n activeInsight: this.#activeInsight,\n };\n\n const contents = LitHtml.html`\n <${SidebarSingleNavigation.litTagName}\n .data=${data as SidebarSingleNavigationData}>\n \n `;\n\n if (hasMultipleInsightSets) {\n return LitHtml.html`\n this.#navigationClicked(id)}\n @mouseenter=${() => this.#navigationHovered(id)}\n @mouseleave=${() => this.#navigationUnhovered()}\n >${label}\n ${contents}\n
`;\n }\n\n return contents;\n })}\n \n `;\n // clang-format on\n LitHtml.render(LitHtml.html`${html}`, this.#shadow, {host: this});\n }\n}\n\ncustomElements.define('devtools-performance-sidebar-insights', SidebarInsightsTab);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-sidebar-insights': SidebarInsightsTab;\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/components/SidebarSingleNavigation.d.ts b/public/panels/timeline/components/SidebarSingleNavigation.d.ts index 94971b196..cd43a1491 100644 --- a/public/panels/timeline/components/SidebarSingleNavigation.d.ts +++ b/public/panels/timeline/components/SidebarSingleNavigation.d.ts @@ -1,9 +1,9 @@ -import * as TraceEngine from '../../../models/trace/trace.js'; +import * as Trace from '../../../models/trace/trace.js'; import { type ActiveInsight } from './Sidebar.js'; import { InsightsCategories } from './SidebarInsightsTab.js'; export interface SidebarSingleNavigationData { - traceParsedData: TraceEngine.Handlers.Types.TraceParseData | null; - insights: TraceEngine.Insights.Types.TraceInsightData | null; + parsedTrace: Trace.Handlers.Types.ParsedTrace | null; + insights: Trace.Insights.Types.TraceInsightSets | null; navigationId: string | null; activeCategory: InsightsCategories; activeInsight: ActiveInsight | null; diff --git a/public/panels/timeline/components/SidebarSingleNavigation.js b/public/panels/timeline/components/SidebarSingleNavigation.js index 7b1f91ad3..2bd902c57 100644 --- a/public/panels/timeline/components/SidebarSingleNavigation.js +++ b/public/panels/timeline/components/SidebarSingleNavigation.js @@ -1,8 +1,9 @@ // Copyright 2024 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. +// TODO(crbug.com/366049346): rename file import * as i18n from '../../../core/i18n/i18n.js'; -import * as TraceEngine from '../../../models/trace/trace.js'; +import * as Trace from '../../../models/trace/trace.js'; import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js'; import * as LitHtml from '../../../ui/lit-html/lit-html.js'; import * as Insights from './insights/insights.js'; @@ -14,7 +15,7 @@ export class SidebarSingleNavigation extends HTMLElement { #shadow = this.attachShadow({ mode: 'open' }); #renderBound = this.#render.bind(this); #data = { - traceParsedData: null, + parsedTrace: null, insights: null, navigationId: null, activeCategory: InsightsCategories.ALL, @@ -34,15 +35,22 @@ export class SidebarSingleNavigation extends HTMLElement { } return label === this.#data.activeCategory; } - #referenceEvent(event) { - return () => { - this.dispatchEvent(new EventReferenceClick(event)); - }; + #onClickMetric(event, insightComponentName) { + const el = this.shadowRoot?.querySelector(insightComponentName); + if (el && this.#data.navigationId) { + this.dispatchEvent(new Insights.SidebarInsight.InsightActivated(el.internalName, this.#data.navigationId, el.createOverlays.bind(el))); + } + this.dispatchEvent(new EventReferenceClick(event)); } #renderMetricValue(label, value, classification, event) { + const insightComponentName = { + LCP: Insights.LCPPhases.LCPPhases.litTagName.value, + CLS: Insights.CLSCulprits.CLSCulprits.litTagName.value, + INP: Insights.InteractionToNextPaint.InteractionToNextPaint.litTagName.value, + }[label]; // clang-format off return this.#metricIsVisible(label) ? LitHtml.html ` -
+
${value}
${label}
@@ -55,14 +63,14 @@ export class SidebarSingleNavigation extends HTMLElement { * as if there are no navigations, we do not want to show the user the INP * score. */ - #calculateINP(traceParsedData, navigationId) { - const eventsForNavigation = traceParsedData.UserInteractions.interactionEventsWithNoNesting.filter(e => { + #calculateINP(parsedTrace, navigationId) { + const eventsForNavigation = parsedTrace.UserInteractions.interactionEventsWithNoNesting.filter(e => { return e.args.data.navigationId === navigationId; }); if (eventsForNavigation.length === 0) { return null; } - let maxDuration = TraceEngine.Types.Timing.MicroSeconds(0); + let maxDuration = Trace.Types.Timing.MicroSeconds(0); for (const event of eventsForNavigation) { if (event.dur > maxDuration) { maxDuration = event.dur; @@ -70,9 +78,9 @@ export class SidebarSingleNavigation extends HTMLElement { } return maxDuration; } - #calculateCLSScore(traceParsedData, navigationId) { + #calculateCLSScore(parsedTrace, navigationId) { // Find all clusers associated with this navigation - const clustersForNavigation = traceParsedData.LayoutShifts.clusters.filter(c => c.navigationId === navigationId); + const clustersForNavigation = parsedTrace.LayoutShifts.clusters.filter(c => c.navigationId === navigationId); let maxScore = 0; let worstCluster; for (const cluster of clustersForNavigation) { @@ -83,113 +91,58 @@ export class SidebarSingleNavigation extends HTMLElement { } return { maxScore, worstShfitEvent: worstCluster?.worstShiftEvent ?? null }; } - #renderMetrics(traceParsedData, navigationId) { - const forNavigation = traceParsedData.PageLoadMetrics.metricScoresByFrameId.get(traceParsedData.Meta.mainFrameId)?.get(navigationId); - const lcpMetric = forNavigation?.get("LCP" /* TraceEngine.Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP */); - const { maxScore: clsScore, worstShfitEvent } = this.#calculateCLSScore(traceParsedData, navigationId); - const inp = this.#calculateINP(traceParsedData, navigationId); + #renderMetrics(parsedTrace, navigationId) { + const forNavigation = parsedTrace.PageLoadMetrics.metricScoresByFrameId.get(parsedTrace.Meta.mainFrameId)?.get(navigationId); + const lcpMetric = forNavigation?.get("LCP" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP */); + const { maxScore: clsScore, worstShfitEvent } = this.#calculateCLSScore(parsedTrace, navigationId); + const inp = this.#calculateINP(parsedTrace, navigationId); return LitHtml.html `
${lcpMetric ? this.#renderMetricValue('LCP', i18n.TimeUtilities.formatMicroSecondsAsSeconds(lcpMetric.timing), lcpMetric.classification, lcpMetric.event ?? null) : LitHtml.nothing} - ${this.#renderMetricValue('CLS', clsScore.toFixed(2), TraceEngine.Handlers.ModelHandlers.LayoutShifts.scoreClassificationForLayoutShift(clsScore), worstShfitEvent)} - ${inp ? this.#renderMetricValue('INP', i18n.TimeUtilities.formatMicroSecondsAsMillisFixed(inp), TraceEngine.Handlers.ModelHandlers.UserInteractions.scoreClassificationForInteractionToNextPaint(inp), null) : + ${this.#renderMetricValue('CLS', clsScore.toFixed(2), Trace.Handlers.ModelHandlers.LayoutShifts.scoreClassificationForLayoutShift(clsScore), worstShfitEvent)} + ${inp ? + this.#renderMetricValue('INP', i18n.TimeUtilities.formatMicroSecondsAsMillisFixed(inp), Trace.Handlers.ModelHandlers.UserInteractions.scoreClassificationForInteractionToNextPaint(inp), null) : LitHtml.nothing}
`; } #renderInsights(insights, navigationId) { + // TODO(crbug.com/368135130): sort this in a smart way! + const insightComponents = [ + Insights.LCPPhases.LCPPhases, + Insights.InteractionToNextPaint.InteractionToNextPaint, + Insights.LCPDiscovery.LCPDiscovery, + Insights.RenderBlocking.RenderBlockingRequests, + Insights.SlowCSSSelector.SlowCSSSelector, + Insights.CLSCulprits.CLSCulprits, + Insights.DocumentLatency.DocumentLatency, + Insights.ThirdParties.ThirdParties, + Insights.Viewport.Viewport, + ]; // clang-format off - return LitHtml.html ` -
- <${Insights.LCPPhases.LCPPhases.litTagName} - .insights=${insights} - .navigationId=${navigationId} - .activeInsight=${this.#data.activeInsight} - .activeCategory=${this.#data.activeCategory} - -
-
- <${Insights.InteractionToNextPaint.InteractionToNextPaint.litTagName} - .insights=${insights} - .navigationId=${navigationId} - .activeInsight=${this.#data.activeInsight} - .activeCategory=${this.#data.activeCategory} - -
-
- <${Insights.LCPDiscovery.LCPDiscovery.litTagName} - .insights=${insights} - .navigationId=${navigationId} - .activeInsight=${this.#data.activeInsight} - .activeCategory=${this.#data.activeCategory} - -
-
- <${Insights.RenderBlocking.RenderBlockingRequests.litTagName} - .insights=${insights} - .navigationId=${navigationId} - .activeInsight=${this.#data.activeInsight} - .activeCategory=${this.#data.activeCategory} - -
-
- <${Insights.SlowCSSSelector.SlowCSSSelector.litTagName} - .insights=${insights} - .navigationId=${navigationId} - .activeInsight=${this.#data.activeInsight} - .activeCategory=${this.#data.activeCategory} - -
-
- <${Insights.CLSCulprits.CLSCulprits.litTagName} - .insights=${insights} - .navigationId=${navigationId} - .activeInsight=${this.#data.activeInsight} - .activeCategory=${this.#data.activeCategory} - -
-
- <${Insights.DocumentLatency.DocumentLatency.litTagName} - .insights=${insights} - .navigationId=${navigationId} - .activeInsight=${this.#data.activeInsight} - .activeCategory=${this.#data.activeCategory} - -
-
- <${Insights.ThirdParties.ThirdParties.litTagName} - .insights=${insights} - .navigationId=${navigationId} - .activeInsight=${this.#data.activeInsight} - .activeCategory=${this.#data.activeCategory} - -
-
- <${Insights.Viewport.Viewport.litTagName} - .insights=${insights} - .navigationId=${navigationId} - .activeInsight=${this.#data.activeInsight} - .activeCategory=${this.#data.activeCategory} - -
`; + return LitHtml.html `${insightComponents.map(component => { + return LitHtml.html `
+ <${component.litTagName} + .insights=${insights} + .navigationId=${navigationId} + .activeInsight=${this.#data.activeInsight} + .activeCategory=${this.#data.activeCategory} + +
`; + })}`; // clang-format on } #render() { - const { traceParsedData, insights, navigationId, } = this.#data; - if (!traceParsedData || !insights || !navigationId) { - LitHtml.render(LitHtml.html ``, this.#shadow, { host: this }); - return; - } - const navigation = traceParsedData.Meta.navigationsByNavigationId.get(navigationId); - if (!navigation) { + const { parsedTrace, insights, navigationId, } = this.#data; + if (!parsedTrace || !insights || !navigationId) { LitHtml.render(LitHtml.html ``, this.#shadow, { host: this }); return; } // clang-format off LitHtml.render(LitHtml.html ` `, this.#shadow, { host: this }); diff --git a/public/panels/timeline/components/SidebarSingleNavigation.js.map b/public/panels/timeline/components/SidebarSingleNavigation.js.map index cd649c33a..57c77b6ec 100644 --- a/public/panels/timeline/components/SidebarSingleNavigation.js.map +++ b/public/panels/timeline/components/SidebarSingleNavigation.js.map @@ -1 +1 @@ -{"version":3,"file":"SidebarSingleNavigation.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/components/SidebarSingleNavigation.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../core/i18n/i18n.js';\nimport * as TraceEngine from '../../../models/trace/trace.js';\nimport * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';\nimport * as LitHtml from '../../../ui/lit-html/lit-html.js';\n\nimport * as Insights from './insights/insights.js';\nimport {type ActiveInsight, EventReferenceClick} from './Sidebar.js';\nimport {InsightsCategories} from './SidebarInsightsTab.js';\nimport styles from './sidebarSingleNavigation.css.js';\n\nexport interface SidebarSingleNavigationData {\n traceParsedData: TraceEngine.Handlers.Types.TraceParseData|null;\n insights: TraceEngine.Insights.Types.TraceInsightData|null;\n navigationId: string|null;\n activeCategory: InsightsCategories;\n activeInsight: ActiveInsight|null;\n}\n\nexport class SidebarSingleNavigation extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-performance-sidebar-single-navigation`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n #renderBound = this.#render.bind(this);\n\n #data: SidebarSingleNavigationData = {\n traceParsedData: null,\n insights: null,\n navigationId: null,\n activeCategory: InsightsCategories.ALL,\n activeInsight: null,\n };\n\n set data(data: SidebarSingleNavigationData) {\n this.#data = data;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#renderBound);\n }\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [styles];\n this.#render();\n }\n\n #metricIsVisible(label: 'LCP'|'CLS'|'INP'): boolean {\n if (this.#data.activeCategory === InsightsCategories.ALL) {\n return true;\n }\n return label === this.#data.activeCategory;\n }\n\n #referenceEvent(event: TraceEngine.Types.TraceEvents.TraceEventData) {\n return () => {\n this.dispatchEvent(new EventReferenceClick(event));\n };\n }\n\n #renderMetricValue(\n label: 'LCP'|'CLS'|'INP', value: string,\n classification: TraceEngine.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification,\n event: TraceEngine.Types.TraceEvents.TraceEventData|null): LitHtml.LitTemplate {\n // clang-format off\n return this.#metricIsVisible(label) ? LitHtml.html`\n
\n
${value}
\n
${label}
\n
\n ` : LitHtml.nothing;\n // clang-format on\n }\n\n /**\n * @returns the duration of the longest interaction for the navigation. If\n * there are no interactions, we return `null`. This distinction is important\n * as if there are no navigations, we do not want to show the user the INP\n * score.\n */\n #calculateINP(\n traceParsedData: TraceEngine.Handlers.Types.TraceParseData,\n navigationId: string,\n ): TraceEngine.Types.Timing.MicroSeconds|null {\n const eventsForNavigation = traceParsedData.UserInteractions.interactionEventsWithNoNesting.filter(e => {\n return e.args.data.navigationId === navigationId;\n });\n if (eventsForNavigation.length === 0) {\n return null;\n }\n\n let maxDuration = TraceEngine.Types.Timing.MicroSeconds(0);\n for (const event of eventsForNavigation) {\n if (event.dur > maxDuration) {\n maxDuration = event.dur;\n }\n }\n\n return maxDuration;\n }\n\n #calculateCLSScore(\n traceParsedData: TraceEngine.Handlers.Types.TraceParseData,\n navigationId: string,\n ): {maxScore: number, worstShfitEvent: TraceEngine.Types.TraceEvents.TraceEventData|null} {\n // Find all clusers associated with this navigation\n const clustersForNavigation = traceParsedData.LayoutShifts.clusters.filter(c => c.navigationId === navigationId);\n let maxScore = 0;\n let worstCluster;\n for (const cluster of clustersForNavigation) {\n if (cluster.clusterCumulativeScore > maxScore) {\n maxScore = cluster.clusterCumulativeScore;\n worstCluster = cluster;\n }\n }\n return {maxScore, worstShfitEvent: worstCluster?.worstShiftEvent ?? null};\n }\n\n #renderMetrics(\n traceParsedData: TraceEngine.Handlers.Types.TraceParseData,\n navigationId: string,\n ): LitHtml.TemplateResult {\n const forNavigation =\n traceParsedData.PageLoadMetrics.metricScoresByFrameId.get(traceParsedData.Meta.mainFrameId)?.get(navigationId);\n const lcpMetric = forNavigation?.get(TraceEngine.Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP);\n\n const {maxScore: clsScore, worstShfitEvent} = this.#calculateCLSScore(traceParsedData, navigationId);\n const inp = this.#calculateINP(traceParsedData, navigationId);\n\n return LitHtml.html`\n
\n ${\n lcpMetric ? this.#renderMetricValue(\n 'LCP', i18n.TimeUtilities.formatMicroSecondsAsSeconds(lcpMetric.timing),\n lcpMetric.classification, lcpMetric.event ?? null) :\n LitHtml.nothing}\n ${\n this.#renderMetricValue(\n 'CLS', clsScore.toFixed(2),\n TraceEngine.Handlers.ModelHandlers.LayoutShifts.scoreClassificationForLayoutShift(clsScore),\n worstShfitEvent)}\n ${\n inp ? this.#renderMetricValue(\n 'INP', i18n.TimeUtilities.formatMicroSecondsAsMillisFixed(inp),\n TraceEngine.Handlers.ModelHandlers.UserInteractions.scoreClassificationForInteractionToNextPaint(inp),\n null) :\n LitHtml.nothing}\n
\n `;\n }\n\n #renderInsights(\n insights: TraceEngine.Insights.Types.TraceInsightData|null,\n navigationId: string,\n ): LitHtml.TemplateResult {\n // clang-format off\n return LitHtml.html`\n
\n <${Insights.LCPPhases.LCPPhases.litTagName}\n .insights=${insights}\n .navigationId=${navigationId}\n .activeInsight=${this.#data.activeInsight}\n .activeCategory=${this.#data.activeCategory}\n \n
\n
\n <${Insights.InteractionToNextPaint.InteractionToNextPaint.litTagName}\n .insights=${insights}\n .navigationId=${navigationId}\n .activeInsight=${this.#data.activeInsight}\n .activeCategory=${this.#data.activeCategory}\n \n
\n
\n <${Insights.LCPDiscovery.LCPDiscovery.litTagName}\n .insights=${insights}\n .navigationId=${navigationId}\n .activeInsight=${this.#data.activeInsight}\n .activeCategory=${this.#data.activeCategory}\n \n
\n
\n <${Insights.RenderBlocking.RenderBlockingRequests.litTagName}\n .insights=${insights}\n .navigationId=${navigationId}\n .activeInsight=${this.#data.activeInsight}\n .activeCategory=${this.#data.activeCategory}\n \n
\n
\n <${Insights.SlowCSSSelector.SlowCSSSelector.litTagName}\n .insights=${insights}\n .navigationId=${navigationId}\n .activeInsight=${this.#data.activeInsight}\n .activeCategory=${this.#data.activeCategory}\n \n
\n
\n <${Insights.CLSCulprits.CLSCulprits.litTagName}\n .insights=${insights}\n .navigationId=${navigationId}\n .activeInsight=${this.#data.activeInsight}\n .activeCategory=${this.#data.activeCategory}\n \n
\n
\n <${Insights.DocumentLatency.DocumentLatency.litTagName}\n .insights=${insights}\n .navigationId=${navigationId}\n .activeInsight=${this.#data.activeInsight}\n .activeCategory=${this.#data.activeCategory}\n \n
\n
\n <${Insights.ThirdParties.ThirdParties.litTagName}\n .insights=${insights}\n .navigationId=${navigationId}\n .activeInsight=${this.#data.activeInsight}\n .activeCategory=${this.#data.activeCategory}\n \n
\n
\n <${Insights.Viewport.Viewport.litTagName}\n .insights=${insights}\n .navigationId=${navigationId}\n .activeInsight=${this.#data.activeInsight}\n .activeCategory=${this.#data.activeCategory}\n \n
`;\n // clang-format on\n }\n\n #render(): void {\n const {\n traceParsedData,\n insights,\n navigationId,\n } = this.#data;\n if (!traceParsedData || !insights || !navigationId) {\n LitHtml.render(LitHtml.html``, this.#shadow, {host: this});\n return;\n }\n\n const navigation = traceParsedData.Meta.navigationsByNavigationId.get(navigationId);\n if (!navigation) {\n LitHtml.render(LitHtml.html``, this.#shadow, {host: this});\n return;\n }\n\n // clang-format off\n LitHtml.render(LitHtml.html`\n
\n ${this.#renderMetrics(traceParsedData, navigationId)}\n ${this.#renderInsights(insights, navigationId)}\n
\n `, this.#shadow, {host: this});\n // clang-format on\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-sidebar-single-navigation': SidebarSingleNavigation;\n }\n}\n\ncustomElements.define('devtools-performance-sidebar-single-navigation', SidebarSingleNavigation);\n"]} \ No newline at end of file +{"version":3,"file":"SidebarSingleNavigation.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/components/SidebarSingleNavigation.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// TODO(crbug.com/366049346): rename file\n\nimport * as i18n from '../../../core/i18n/i18n.js';\nimport * as Trace from '../../../models/trace/trace.js';\nimport * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';\nimport * as LitHtml from '../../../ui/lit-html/lit-html.js';\n\nimport {type BaseInsight} from './insights/Helpers.js';\nimport * as Insights from './insights/insights.js';\nimport {type ActiveInsight, EventReferenceClick} from './Sidebar.js';\nimport {InsightsCategories} from './SidebarInsightsTab.js';\nimport styles from './sidebarSingleNavigation.css.js';\n\nexport interface SidebarSingleNavigationData {\n parsedTrace: Trace.Handlers.Types.ParsedTrace|null;\n insights: Trace.Insights.Types.TraceInsightSets|null;\n navigationId: string|null;\n activeCategory: InsightsCategories;\n activeInsight: ActiveInsight|null;\n}\n\nexport class SidebarSingleNavigation extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-performance-sidebar-single-navigation`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n #renderBound = this.#render.bind(this);\n\n #data: SidebarSingleNavigationData = {\n parsedTrace: null,\n insights: null,\n navigationId: null,\n activeCategory: InsightsCategories.ALL,\n activeInsight: null,\n };\n\n set data(data: SidebarSingleNavigationData) {\n this.#data = data;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#renderBound);\n }\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [styles];\n this.#render();\n }\n\n #metricIsVisible(label: 'LCP'|'CLS'|'INP'): boolean {\n if (this.#data.activeCategory === InsightsCategories.ALL) {\n return true;\n }\n return label === this.#data.activeCategory;\n }\n\n #onClickMetric(event: Trace.Types.Events.Event, insightComponentName: string): void {\n const el = this.shadowRoot?.querySelector(insightComponentName) as BaseInsight;\n if (el && this.#data.navigationId) {\n this.dispatchEvent(new Insights.SidebarInsight.InsightActivated(\n el.internalName,\n this.#data.navigationId,\n el.createOverlays.bind(el),\n ));\n }\n\n this.dispatchEvent(new EventReferenceClick(event));\n }\n\n #renderMetricValue(\n label: 'LCP'|'CLS'|'INP', value: string,\n classification: Trace.Handlers.ModelHandlers.PageLoadMetrics.ScoreClassification,\n event: Trace.Types.Events.Event|null): LitHtml.LitTemplate {\n const insightComponentName = {\n LCP: Insights.LCPPhases.LCPPhases.litTagName.value as string,\n CLS: Insights.CLSCulprits.CLSCulprits.litTagName.value as string,\n INP: Insights.InteractionToNextPaint.InteractionToNextPaint.litTagName.value as string,\n }[label];\n\n // clang-format off\n return this.#metricIsVisible(label) ? LitHtml.html`\n
\n
${value}
\n
${label}
\n
\n ` : LitHtml.nothing;\n // clang-format on\n }\n\n /**\n * @returns the duration of the longest interaction for the navigation. If\n * there are no interactions, we return `null`. This distinction is important\n * as if there are no navigations, we do not want to show the user the INP\n * score.\n */\n #calculateINP(\n parsedTrace: Trace.Handlers.Types.ParsedTrace,\n navigationId: string,\n ): Trace.Types.Timing.MicroSeconds|null {\n const eventsForNavigation = parsedTrace.UserInteractions.interactionEventsWithNoNesting.filter(e => {\n return e.args.data.navigationId === navigationId;\n });\n if (eventsForNavigation.length === 0) {\n return null;\n }\n\n let maxDuration = Trace.Types.Timing.MicroSeconds(0);\n for (const event of eventsForNavigation) {\n if (event.dur > maxDuration) {\n maxDuration = event.dur;\n }\n }\n\n return maxDuration;\n }\n\n #calculateCLSScore(\n parsedTrace: Trace.Handlers.Types.ParsedTrace,\n navigationId: string,\n ): {maxScore: number, worstShfitEvent: Trace.Types.Events.Event|null} {\n // Find all clusers associated with this navigation\n const clustersForNavigation = parsedTrace.LayoutShifts.clusters.filter(c => c.navigationId === navigationId);\n let maxScore = 0;\n let worstCluster;\n for (const cluster of clustersForNavigation) {\n if (cluster.clusterCumulativeScore > maxScore) {\n maxScore = cluster.clusterCumulativeScore;\n worstCluster = cluster;\n }\n }\n return {maxScore, worstShfitEvent: worstCluster?.worstShiftEvent ?? null};\n }\n\n #renderMetrics(\n parsedTrace: Trace.Handlers.Types.ParsedTrace,\n navigationId: string,\n ): LitHtml.TemplateResult {\n const forNavigation =\n parsedTrace.PageLoadMetrics.metricScoresByFrameId.get(parsedTrace.Meta.mainFrameId)?.get(navigationId);\n const lcpMetric = forNavigation?.get(Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP);\n\n const {maxScore: clsScore, worstShfitEvent} = this.#calculateCLSScore(parsedTrace, navigationId);\n const inp = this.#calculateINP(parsedTrace, navigationId);\n\n return LitHtml.html`\n
\n ${\n lcpMetric ? this.#renderMetricValue(\n 'LCP', i18n.TimeUtilities.formatMicroSecondsAsSeconds(lcpMetric.timing),\n lcpMetric.classification, lcpMetric.event ?? null) :\n LitHtml.nothing}\n ${\n this.#renderMetricValue(\n 'CLS', clsScore.toFixed(2),\n Trace.Handlers.ModelHandlers.LayoutShifts.scoreClassificationForLayoutShift(clsScore), worstShfitEvent)}\n ${\n inp ?\n this.#renderMetricValue(\n 'INP', i18n.TimeUtilities.formatMicroSecondsAsMillisFixed(inp),\n Trace.Handlers.ModelHandlers.UserInteractions.scoreClassificationForInteractionToNextPaint(inp), null) :\n LitHtml.nothing}\n
\n `;\n }\n\n #renderInsights(\n insights: Trace.Insights.Types.TraceInsightSets|null,\n navigationId: string,\n ): LitHtml.TemplateResult {\n // TODO(crbug.com/368135130): sort this in a smart way!\n const insightComponents = [\n Insights.LCPPhases.LCPPhases,\n Insights.InteractionToNextPaint.InteractionToNextPaint,\n Insights.LCPDiscovery.LCPDiscovery,\n Insights.RenderBlocking.RenderBlockingRequests,\n Insights.SlowCSSSelector.SlowCSSSelector,\n Insights.CLSCulprits.CLSCulprits,\n Insights.DocumentLatency.DocumentLatency,\n Insights.ThirdParties.ThirdParties,\n Insights.Viewport.Viewport,\n ];\n // clang-format off\n return LitHtml.html`${insightComponents.map(component => {\n return LitHtml.html`
\n <${component.litTagName}\n .insights=${insights}\n .navigationId=${navigationId}\n .activeInsight=${this.#data.activeInsight}\n .activeCategory=${this.#data.activeCategory}\n \n
`;\n })}`;\n // clang-format on\n }\n\n #render(): void {\n const {\n parsedTrace,\n insights,\n navigationId,\n } = this.#data;\n if (!parsedTrace || !insights || !navigationId) {\n LitHtml.render(LitHtml.html``, this.#shadow, {host: this});\n return;\n }\n\n // clang-format off\n LitHtml.render(LitHtml.html`\n
\n ${this.#renderMetrics(parsedTrace, navigationId)}\n ${this.#renderInsights(insights, navigationId)}\n
\n `, this.#shadow, {host: this});\n // clang-format on\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-sidebar-single-navigation': SidebarSingleNavigation;\n }\n}\n\ncustomElements.define('devtools-performance-sidebar-single-navigation', SidebarSingleNavigation);\n"]} \ No newline at end of file diff --git a/public/panels/timeline/components/Utils.d.ts b/public/panels/timeline/components/Utils.d.ts index 6c49c4d4b..8fe2401f4 100644 --- a/public/panels/timeline/components/Utils.d.ts +++ b/public/panels/timeline/components/Utils.d.ts @@ -1,4 +1,4 @@ -import type * as TraceEngine from '../../../models/trace/trace.js'; +import type * as Trace from '../../../models/trace/trace.js'; export declare enum NetworkCategory { DOC = "Doc", CSS = "CSS", @@ -10,7 +10,7 @@ export declare enum NetworkCategory { OTHER = "Other" } export declare function colorForNetworkCategory(category: NetworkCategory): string; -export declare function colorForNetworkRequest(request: TraceEngine.Types.TraceEvents.SyntheticNetworkRequest): string; +export declare function colorForNetworkRequest(request: Trace.Types.Events.SyntheticNetworkRequest): string; export type MetricRating = 'good' | 'needs-improvement' | 'poor'; export type MetricThresholds = [number, number]; export declare const LCP_THRESHOLDS: MetricThresholds; diff --git a/public/panels/timeline/components/Utils.js.map b/public/panels/timeline/components/Utils.js.map index 1d91f30b8..baab0494c 100644 --- a/public/panels/timeline/components/Utils.js.map +++ b/public/panels/timeline/components/Utils.js.map @@ -1 +1 @@ -{"version":3,"file":"Utils.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/components/Utils.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as TraceEngine from '../../../models/trace/trace.js';\nimport * as ThemeSupport from '../../../ui/legacy/theme_support/theme_support.js';\nimport * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';\n\nexport enum NetworkCategory {\n DOC = 'Doc',\n CSS = 'CSS',\n JS = 'JS',\n FONT = 'Font',\n IMG = 'Img',\n MEDIA = 'Media',\n WASM = 'Wasm',\n OTHER = 'Other',\n}\n\nfunction syntheticNetworkRequestCategory(request: TraceEngine.Types.TraceEvents.SyntheticNetworkRequest):\n NetworkCategory {\n switch (request.args.data.mimeType) {\n case 'text/html':\n return NetworkCategory.DOC;\n case 'application/javascript':\n case 'application/x-javascript':\n case 'text/javascript':\n return NetworkCategory.JS;\n case 'text/css':\n return NetworkCategory.CSS;\n case 'image/gif':\n case 'image/jpeg':\n case 'image/png':\n case 'image/svg+xml':\n case 'image/webp':\n case 'image/x-icon':\n return NetworkCategory.IMG;\n case 'audio/aac':\n case 'audio/midi':\n case 'audio/x-midi':\n case 'audio/mpeg':\n case 'audio/ogg':\n case 'audio/wav':\n case 'audio/webm':\n return NetworkCategory.MEDIA;\n case 'font/opentype':\n case 'font/woff2':\n case 'font/ttf':\n case 'application/font-woff':\n return NetworkCategory.FONT;\n case 'application/wasm':\n return NetworkCategory.WASM;\n default:\n return NetworkCategory.OTHER;\n }\n}\n\nexport function colorForNetworkCategory(category: NetworkCategory): string {\n let cssVarName = '--app-color-system';\n switch (category) {\n case NetworkCategory.DOC:\n cssVarName = '--app-color-doc';\n break;\n case NetworkCategory.JS:\n cssVarName = '--app-color-scripting';\n break;\n case NetworkCategory.CSS:\n cssVarName = '--app-color-css';\n break;\n case NetworkCategory.IMG:\n cssVarName = '--app-color-image';\n break;\n case NetworkCategory.MEDIA:\n cssVarName = '--app-color-media';\n break;\n case NetworkCategory.FONT:\n cssVarName = '--app-color-font';\n break;\n case NetworkCategory.WASM:\n cssVarName = '--app-color-wasm';\n break;\n case NetworkCategory.OTHER:\n default:\n cssVarName = '--app-color-system';\n break;\n }\n return ThemeSupport.ThemeSupport.instance().getComputedValue(cssVarName);\n}\n\nexport function colorForNetworkRequest(request: TraceEngine.Types.TraceEvents.SyntheticNetworkRequest): string {\n const category = syntheticNetworkRequestCategory(request);\n return colorForNetworkCategory(category);\n}\n\nexport type MetricRating = 'good'|'needs-improvement'|'poor';\nexport type MetricThresholds = [number, number];\n\n// TODO: Consolidate our metric rating logic with the trace engine.\nexport const LCP_THRESHOLDS = [2500, 4000] as MetricThresholds;\nexport const CLS_THRESHOLDS = [0.1, 0.25] as MetricThresholds;\nexport const INP_THRESHOLDS = [200, 500] as MetricThresholds;\n\nexport function rateMetric(value: number, thresholds: MetricThresholds): MetricRating {\n if (value <= thresholds[0]) {\n return 'good';\n }\n if (value <= thresholds[1]) {\n return 'needs-improvement';\n }\n return 'poor';\n}\n\n/**\n * Ensure to also include `metricValueStyles.css` when generating metric value elements.\n */\nexport function renderMetricValue(\n jslogContext: string, value: number|undefined, thresholds: MetricThresholds, format: (value: number) => string,\n options?: {dim?: boolean}): HTMLElement {\n const metricValueEl = document.createElement('span');\n metricValueEl.classList.add('metric-value');\n if (value === undefined) {\n metricValueEl.classList.add('waiting');\n metricValueEl.textContent = '-';\n return metricValueEl;\n }\n\n metricValueEl.textContent = format(value);\n const rating = rateMetric(value, thresholds);\n metricValueEl.classList.add(rating);\n // Ensure we log impressions of each section. We purposefully add this here\n // because if we don't have field data (dealt with in the undefined branch\n // above), we do not want to log an impression on it.\n metricValueEl.setAttribute('jslog', `${VisualLogging.section(jslogContext)}`);\n if (options?.dim) {\n metricValueEl.classList.add('dim');\n }\n\n return metricValueEl;\n}\n"]} \ No newline at end of file +{"version":3,"file":"Utils.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/components/Utils.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Trace from '../../../models/trace/trace.js';\nimport * as ThemeSupport from '../../../ui/legacy/theme_support/theme_support.js';\nimport * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';\n\nexport enum NetworkCategory {\n DOC = 'Doc',\n CSS = 'CSS',\n JS = 'JS',\n FONT = 'Font',\n IMG = 'Img',\n MEDIA = 'Media',\n WASM = 'Wasm',\n OTHER = 'Other',\n}\n\nfunction syntheticNetworkRequestCategory(request: Trace.Types.Events.SyntheticNetworkRequest): NetworkCategory {\n switch (request.args.data.mimeType) {\n case 'text/html':\n return NetworkCategory.DOC;\n case 'application/javascript':\n case 'application/x-javascript':\n case 'text/javascript':\n return NetworkCategory.JS;\n case 'text/css':\n return NetworkCategory.CSS;\n case 'image/gif':\n case 'image/jpeg':\n case 'image/png':\n case 'image/svg+xml':\n case 'image/webp':\n case 'image/x-icon':\n return NetworkCategory.IMG;\n case 'audio/aac':\n case 'audio/midi':\n case 'audio/x-midi':\n case 'audio/mpeg':\n case 'audio/ogg':\n case 'audio/wav':\n case 'audio/webm':\n return NetworkCategory.MEDIA;\n case 'font/opentype':\n case 'font/woff2':\n case 'font/ttf':\n case 'application/font-woff':\n return NetworkCategory.FONT;\n case 'application/wasm':\n return NetworkCategory.WASM;\n default:\n return NetworkCategory.OTHER;\n }\n}\n\nexport function colorForNetworkCategory(category: NetworkCategory): string {\n let cssVarName = '--app-color-system';\n switch (category) {\n case NetworkCategory.DOC:\n cssVarName = '--app-color-doc';\n break;\n case NetworkCategory.JS:\n cssVarName = '--app-color-scripting';\n break;\n case NetworkCategory.CSS:\n cssVarName = '--app-color-css';\n break;\n case NetworkCategory.IMG:\n cssVarName = '--app-color-image';\n break;\n case NetworkCategory.MEDIA:\n cssVarName = '--app-color-media';\n break;\n case NetworkCategory.FONT:\n cssVarName = '--app-color-font';\n break;\n case NetworkCategory.WASM:\n cssVarName = '--app-color-wasm';\n break;\n case NetworkCategory.OTHER:\n default:\n cssVarName = '--app-color-system';\n break;\n }\n return ThemeSupport.ThemeSupport.instance().getComputedValue(cssVarName);\n}\n\nexport function colorForNetworkRequest(request: Trace.Types.Events.SyntheticNetworkRequest): string {\n const category = syntheticNetworkRequestCategory(request);\n return colorForNetworkCategory(category);\n}\n\nexport type MetricRating = 'good'|'needs-improvement'|'poor';\nexport type MetricThresholds = [number, number];\n\n// TODO: Consolidate our metric rating logic with the trace engine.\nexport const LCP_THRESHOLDS = [2500, 4000] as MetricThresholds;\nexport const CLS_THRESHOLDS = [0.1, 0.25] as MetricThresholds;\nexport const INP_THRESHOLDS = [200, 500] as MetricThresholds;\n\nexport function rateMetric(value: number, thresholds: MetricThresholds): MetricRating {\n if (value <= thresholds[0]) {\n return 'good';\n }\n if (value <= thresholds[1]) {\n return 'needs-improvement';\n }\n return 'poor';\n}\n\n/**\n * Ensure to also include `metricValueStyles.css` when generating metric value elements.\n */\nexport function renderMetricValue(\n jslogContext: string, value: number|undefined, thresholds: MetricThresholds, format: (value: number) => string,\n options?: {dim?: boolean}): HTMLElement {\n const metricValueEl = document.createElement('span');\n metricValueEl.classList.add('metric-value');\n if (value === undefined) {\n metricValueEl.classList.add('waiting');\n metricValueEl.textContent = '-';\n return metricValueEl;\n }\n\n metricValueEl.textContent = format(value);\n const rating = rateMetric(value, thresholds);\n metricValueEl.classList.add(rating);\n // Ensure we log impressions of each section. We purposefully add this here\n // because if we don't have field data (dealt with in the undefined branch\n // above), we do not want to log an impression on it.\n metricValueEl.setAttribute('jslog', `${VisualLogging.section(jslogContext)}`);\n if (options?.dim) {\n metricValueEl.classList.add('dim');\n }\n\n return metricValueEl;\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/components/insights/CLSCulprits.d.ts b/public/panels/timeline/components/insights/CLSCulprits.d.ts index bc8d0bd7d..92f4d0a98 100644 --- a/public/panels/timeline/components/insights/CLSCulprits.d.ts +++ b/public/panels/timeline/components/insights/CLSCulprits.d.ts @@ -1,8 +1,8 @@ -import type * as TraceEngine from '../../../../models/trace/trace.js'; +import * as Trace from '../../../../models/trace/trace.js'; import type * as Overlays from '../../overlays/overlays.js'; import { BaseInsight } from './Helpers.js'; import { InsightsCategories } from './types.js'; -export declare function getCLSInsight(insights: TraceEngine.Insights.Types.TraceInsightData | null, navigationId: string | null): TraceEngine.Insights.Types.InsightResults['CumulativeLayoutShift'] | null; +export declare function getCLSInsight(insights: Trace.Insights.Types.TraceInsightSets | null, navigationId: string | null): Trace.Insights.Types.InsightResults['CumulativeLayoutShift'] | null; export declare class CLSCulprits extends BaseInsight { #private; static readonly litTagName: import("../../../../ui/lit-html/static.js").Static; @@ -13,7 +13,7 @@ export declare class CLSCulprits extends BaseInsight { /** * getTopCulprits gets the top 3 shift root causes based on clusters. */ - getTopCulprits(clusters: TraceEngine.Types.TraceEvents.SyntheticLayoutShiftCluster[], culpritsByShift: Map | undefined): string[]; + getTopCulprits(clusters: Trace.Types.Events.SyntheticLayoutShiftCluster[], culpritsByShift: Map | undefined): string[]; render(): void; } declare global { diff --git a/public/panels/timeline/components/insights/CLSCulprits.js b/public/panels/timeline/components/insights/CLSCulprits.js index 21d271986..cbc0e76fa 100644 --- a/public/panels/timeline/components/insights/CLSCulprits.js +++ b/public/panels/timeline/components/insights/CLSCulprits.js @@ -1,10 +1,20 @@ // Copyright 2024 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 * as i18n from '../../../../core/i18n/i18n.js'; +import * as Trace from '../../../../models/trace/trace.js'; import * as LitHtml from '../../../../ui/lit-html/lit-html.js'; import { BaseInsight, shouldRenderForCategory } from './Helpers.js'; import * as SidebarInsight from './SidebarInsight.js'; import { InsightsCategories } from './types.js'; +const UIStrings = { + /** + *@description Text indicating the worst layout shift cluster. + */ + worstCluster: 'Worst layout shift cluster', +}; +const str_ = i18n.i18n.registerUIStrings('panels/timeline/components/insights/CLSCulprits.ts', UIStrings); +const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); export function getCLSInsight(insights, navigationId) { if (!insights || !navigationId) { return null; @@ -13,7 +23,7 @@ export function getCLSInsight(insights, navigationId) { if (!insightsByNavigation) { return null; } - const clsInsight = insightsByNavigation.CumulativeLayoutShift; + const clsInsight = insightsByNavigation.data.CumulativeLayoutShift; if (clsInsight instanceof Error) { return null; } @@ -25,8 +35,23 @@ export class CLSCulprits extends BaseInsight { internalName = 'cls-culprits'; userVisibleTitle = 'Layout shift culprits'; createOverlays() { - // TODO: create overlays - return []; + const insight = getCLSInsight(this.data.insights, this.data.navigationId); + // Clusters are sorted by bad scores, so we can grab the first. + const worstCluster = insight?.clusters[0]; + if (!worstCluster) { + return []; + } + const range = Trace.Types.Timing.MicroSeconds(worstCluster.dur ?? 0); + const max = Trace.Types.Timing.MicroSeconds(worstCluster.ts + range); + const label = LitHtml.html `
${i18nString(UIStrings.worstCluster)}
`; + return [{ + type: 'TIMESPAN_BREAKDOWN', + sections: [ + { bounds: { min: worstCluster.ts, range, max }, label, showDuration: false }, + ], + // This allows for the overlay to sit over the layout shift. + entry: worstCluster.events[0], + }]; } /** * getTopCulprits gets the top 3 shift root causes based on clusters. @@ -72,9 +97,11 @@ export class CLSCulprits extends BaseInsight { }} @insighttoggleclick=${this.onSidebarClick}>
+

Layout shifts happen when existing elements unexpectedly move. - Shifts are caused by nodes changing size or newly added. Investigate - and fix these culprits. + Shifts are caused by nodes changing size or newly added. Investigate + and fix these culprits. +

diff --git a/public/panels/timeline/components/insights/CLSCulprits.js.map b/public/panels/timeline/components/insights/CLSCulprits.js.map index cedb5b8a4..c3cc2e95a 100644 --- a/public/panels/timeline/components/insights/CLSCulprits.js.map +++ b/public/panels/timeline/components/insights/CLSCulprits.js.map @@ -1 +1 @@ -{"version":3,"file":"CLSCulprits.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/CLSCulprits.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAG7B,OAAO,KAAK,OAAO,MAAM,qCAAqC,CAAC;AAG/D,OAAO,EAAC,WAAW,EAAE,uBAAuB,EAAC,MAAM,cAAc,CAAC;AAClE,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAC,kBAAkB,EAAC,MAAM,YAAY,CAAC;AAE9C,MAAM,UAAU,aAAa,CAAC,QAA0D,EAAE,YAAyB;IAEjH,IAAI,CAAC,QAAQ,IAAI,CAAC,YAAY,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,oBAAoB,GAAG,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACxD,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,UAAU,GAAG,oBAAoB,CAAC,qBAAqB,CAAC;IAC9D,IAAI,UAAU,YAAY,KAAK,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,OAAO,WAAY,SAAQ,WAAW;IAC1C,MAAM,CAAU,UAAU,GAAG,OAAO,CAAC,OAAO,CAAA,mCAAmC,CAAC;IACvE,eAAe,GAAuB,kBAAkB,CAAC,GAAG,CAAC;IAC7D,YAAY,GAAW,cAAc,CAAC;IACtC,gBAAgB,GAAW,uBAAuB,CAAC;IAEnD,cAAc;QACrB,wBAAwB;QACxB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED;;OAEG;IACH,cAAc,CACV,QAAqE,EACrE,eAGS;QACX,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,gBAAgB,GAAG,CAAC,CAAC;QAC3B,MAAM,MAAM,GAAkB,EAAE,CAAC;QACjC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,MAAM,CAAC,MAAM,KAAK,gBAAgB,EAAE,CAAC;gBACvC,MAAM;YACR,CAAC;YACD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;YAC9B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;gBAC3B,IAAI,MAAM,CAAC,MAAM,KAAK,gBAAgB,EAAE,CAAC;oBACvC,MAAM;gBACR,CAAC;gBAED,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBAC5C,IAAI,CAAC,QAAQ,EAAE,CAAC;oBACd,SAAS;gBACX,CAAC;gBACD,MAAM,OAAO,GAAG,QAAQ,CAAC,YAAY,CAAC;gBACtC,MAAM,OAAO,GAAG,QAAQ,CAAC,SAAS,CAAC;gBAEnC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,gBAAgB,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC5E,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;gBAC9B,CAAC;gBACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,gBAAgB,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC5E,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;gBACjC,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC;IAC3C,CAAC;IAED,OAAO,CAAC,QAAuB;QAC7B,mBAAmB;QACnB,OAAO,OAAO,CAAC,IAAI,CAAA;;eAER,cAAc,CAAC,cAAc,CAAC,UAAU,UAAU;YACrD,KAAK,EAAE,IAAI,CAAC,gBAAgB;YAC5B,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE;SACS;kCACZ,IAAI,CAAC,cAAc;;;;;;;;;sBAS/B,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;YACvB,OAAO,OAAO,CAAC,IAAI,CAAC;8BACZ,OAAO;uBACd,CAAC;QACJ,CAAC,CAAC;;;gBAGN,cAAc,CAAC,cAAc;eAC9B,CAAC;QACZ,kBAAkB;IACpB,CAAC;IAEQ,MAAM;QACb,MAAM,UAAU,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC7E,MAAM,eAAe,GAAG,UAAU,EAAE,MAAM,CAAC;QAC3C,MAAM,QAAQ,GAAG,UAAU,EAAE,QAAQ,IAAI,EAAE,CAAC;QAE5C,MAAM,MAAM,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;QAC9D,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;QAEtC,MAAM,eAAe,GAAG,uBAAuB,CAAC;YAC9C,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,cAAc;YACxC,eAAe,EAAE,IAAI,CAAC,eAAe;SACtC,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,WAAW,IAAI,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;QACvF,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC,CAAC;IACpD,CAAC;;AASH,cAAc,CAAC,MAAM,CAAC,mCAAmC,EAAE,WAAW,CAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as TraceEngine from '../../../../models/trace/trace.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\nimport type * as Overlays from '../../overlays/overlays.js';\n\nimport {BaseInsight, shouldRenderForCategory} from './Helpers.js';\nimport * as SidebarInsight from './SidebarInsight.js';\nimport {InsightsCategories} from './types.js';\n\nexport function getCLSInsight(insights: TraceEngine.Insights.Types.TraceInsightData|null, navigationId: string|null):\n TraceEngine.Insights.Types.InsightResults['CumulativeLayoutShift']|null {\n if (!insights || !navigationId) {\n return null;\n }\n\n const insightsByNavigation = insights.get(navigationId);\n if (!insightsByNavigation) {\n return null;\n }\n\n const clsInsight = insightsByNavigation.CumulativeLayoutShift;\n if (clsInsight instanceof Error) {\n return null;\n }\n return clsInsight;\n}\n\nexport class CLSCulprits extends BaseInsight {\n static readonly litTagName = LitHtml.literal`devtools-performance-cls-culprits`;\n override insightCategory: InsightsCategories = InsightsCategories.CLS;\n override internalName: string = 'cls-culprits';\n override userVisibleTitle: string = 'Layout shift culprits';\n\n override createOverlays(): Overlays.Overlays.TimelineOverlay[] {\n // TODO: create overlays\n return [];\n }\n\n /**\n * getTopCulprits gets the top 3 shift root causes based on clusters.\n */\n getTopCulprits(\n clusters: TraceEngine.Types.TraceEvents.SyntheticLayoutShiftCluster[],\n culpritsByShift:\n Map|\n undefined): string[] {\n if (!culpritsByShift) {\n return [];\n }\n const MAX_TOP_CULPRITS = 3;\n const causes: Array = [];\n for (const cluster of clusters) {\n if (causes.length === MAX_TOP_CULPRITS) {\n break;\n }\n const shifts = cluster.events;\n for (const shift of shifts) {\n if (causes.length === MAX_TOP_CULPRITS) {\n break;\n }\n\n const culprits = culpritsByShift.get(shift);\n if (!culprits) {\n continue;\n }\n const fontReq = culprits.fontRequests;\n const iframes = culprits.iframeIds;\n\n for (let i = 0; i < fontReq.length && causes.length < MAX_TOP_CULPRITS; i++) {\n causes.push('Font request');\n }\n for (let i = 0; i < iframes.length && causes.length < MAX_TOP_CULPRITS; i++) {\n causes.push('Injected iframe');\n }\n }\n }\n return causes.slice(0, MAX_TOP_CULPRITS);\n }\n\n #render(culprits: Array): LitHtml.TemplateResult {\n // clang-format off\n return LitHtml.html`\n

\n <${SidebarInsight.SidebarInsight.litTagName} .data=${{\n title: this.userVisibleTitle,\n expanded: this.isActive(),\n } as SidebarInsight.InsightDetails}\n @insighttoggleclick=${this.onSidebarClick}>\n
\n Layout shifts happen when existing elements unexpectedly move.\n Shifts are caused by nodes changing size or newly added. Investigate\n and fix these culprits.\n
\n
\n

\n Top layout shift culprits:\n ${culprits.map(culprit => {\n return LitHtml.html `\n

  • ${culprit}
  • \n `;\n })}\n

    \n

    \n \n
    `;\n // clang-format on\n }\n\n override render(): void {\n const clsInsight = getCLSInsight(this.data.insights, this.data.navigationId);\n const culpritsByShift = clsInsight?.shifts;\n const clusters = clsInsight?.clusters ?? [];\n\n const causes = this.getTopCulprits(clusters, culpritsByShift);\n const hasCulprits = causes.length > 0;\n\n const matchesCategory = shouldRenderForCategory({\n activeCategory: this.data.activeCategory,\n insightCategory: this.insightCategory,\n });\n const output = hasCulprits && matchesCategory ? this.#render(causes) : LitHtml.nothing;\n LitHtml.render(output, this.shadow, {host: this});\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-cls-culprits': CLSCulprits;\n }\n}\n\ncustomElements.define('devtools-performance-cls-culprits', CLSCulprits);\n"]} \ No newline at end of file +{"version":3,"file":"CLSCulprits.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/CLSCulprits.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport * as Trace from '../../../../models/trace/trace.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\nimport type * as Overlays from '../../overlays/overlays.js';\n\nimport {BaseInsight, shouldRenderForCategory} from './Helpers.js';\nimport * as SidebarInsight from './SidebarInsight.js';\nimport {InsightsCategories} from './types.js';\n\nconst UIStrings = {\n /**\n *@description Text indicating the worst layout shift cluster.\n */\n worstCluster: 'Worst layout shift cluster',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/components/insights/CLSCulprits.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function getCLSInsight(insights: Trace.Insights.Types.TraceInsightSets|null, navigationId: string|null):\n Trace.Insights.Types.InsightResults['CumulativeLayoutShift']|null {\n if (!insights || !navigationId) {\n return null;\n }\n\n const insightsByNavigation = insights.get(navigationId);\n if (!insightsByNavigation) {\n return null;\n }\n\n const clsInsight = insightsByNavigation.data.CumulativeLayoutShift;\n if (clsInsight instanceof Error) {\n return null;\n }\n return clsInsight;\n}\n\nexport class CLSCulprits extends BaseInsight {\n static readonly litTagName = LitHtml.literal`devtools-performance-cls-culprits`;\n override insightCategory: InsightsCategories = InsightsCategories.CLS;\n override internalName: string = 'cls-culprits';\n override userVisibleTitle: string = 'Layout shift culprits';\n\n override createOverlays(): Overlays.Overlays.TimelineOverlay[] {\n const insight = getCLSInsight(this.data.insights, this.data.navigationId);\n // Clusters are sorted by bad scores, so we can grab the first.\n const worstCluster = insight?.clusters[0];\n if (!worstCluster) {\n return [];\n }\n const range = Trace.Types.Timing.MicroSeconds(worstCluster.dur ?? 0);\n const max = Trace.Types.Timing.MicroSeconds(worstCluster.ts + range);\n\n const label = LitHtml.html`
    ${i18nString(UIStrings.worstCluster)}
    `;\n return [{\n type: 'TIMESPAN_BREAKDOWN',\n sections: [\n {bounds: {min: worstCluster.ts, range, max}, label, showDuration: false},\n ],\n // This allows for the overlay to sit over the layout shift.\n entry: worstCluster.events[0],\n }];\n }\n\n /**\n * getTopCulprits gets the top 3 shift root causes based on clusters.\n */\n getTopCulprits(\n clusters: Trace.Types.Events.SyntheticLayoutShiftCluster[],\n culpritsByShift:\n Map|undefined): string[] {\n if (!culpritsByShift) {\n return [];\n }\n const MAX_TOP_CULPRITS = 3;\n const causes: Array = [];\n for (const cluster of clusters) {\n if (causes.length === MAX_TOP_CULPRITS) {\n break;\n }\n const shifts = cluster.events;\n for (const shift of shifts) {\n if (causes.length === MAX_TOP_CULPRITS) {\n break;\n }\n\n const culprits = culpritsByShift.get(shift);\n if (!culprits) {\n continue;\n }\n const fontReq = culprits.fontRequests;\n const iframes = culprits.iframeIds;\n\n for (let i = 0; i < fontReq.length && causes.length < MAX_TOP_CULPRITS; i++) {\n causes.push('Font request');\n }\n for (let i = 0; i < iframes.length && causes.length < MAX_TOP_CULPRITS; i++) {\n causes.push('Injected iframe');\n }\n }\n }\n return causes.slice(0, MAX_TOP_CULPRITS);\n }\n\n #render(culprits: Array): LitHtml.TemplateResult {\n // clang-format off\n return LitHtml.html`\n
    \n <${SidebarInsight.SidebarInsight.litTagName} .data=${{\n title: this.userVisibleTitle,\n expanded: this.isActive(),\n } as SidebarInsight.InsightDetails}\n @insighttoggleclick=${this.onSidebarClick}>\n
    \n

    \n Layout shifts happen when existing elements unexpectedly move.\n Shifts are caused by nodes changing size or newly added. Investigate\n and fix these culprits.\n

    \n
    \n
    \n

    \n Top layout shift culprits:\n ${culprits.map(culprit => {\n return LitHtml.html `\n

  • ${culprit}
  • \n `;\n })}\n

    \n

    \n \n
    `;\n // clang-format on\n }\n\n override render(): void {\n const clsInsight = getCLSInsight(this.data.insights, this.data.navigationId);\n const culpritsByShift = clsInsight?.shifts;\n const clusters = clsInsight?.clusters ?? [];\n\n const causes = this.getTopCulprits(clusters, culpritsByShift);\n const hasCulprits = causes.length > 0;\n\n const matchesCategory = shouldRenderForCategory({\n activeCategory: this.data.activeCategory,\n insightCategory: this.insightCategory,\n });\n const output = hasCulprits && matchesCategory ? this.#render(causes) : LitHtml.nothing;\n LitHtml.render(output, this.shadow, {host: this});\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-cls-culprits': CLSCulprits;\n }\n}\n\ncustomElements.define('devtools-performance-cls-culprits', CLSCulprits);\n"]} \ No newline at end of file diff --git a/public/panels/timeline/components/insights/DocumentLatency.d.ts b/public/panels/timeline/components/insights/DocumentLatency.d.ts index 0d525eb1e..ff204387b 100644 --- a/public/panels/timeline/components/insights/DocumentLatency.d.ts +++ b/public/panels/timeline/components/insights/DocumentLatency.d.ts @@ -1,8 +1,8 @@ -import type * as TraceEngine from '../../../../models/trace/trace.js'; +import type * as Trace from '../../../../models/trace/trace.js'; import type * as Overlays from '../../overlays/overlays.js'; import { BaseInsight } from './Helpers.js'; import { InsightsCategories } from './types.js'; -export declare function getDocumentLatencyInsight(insights: TraceEngine.Insights.Types.TraceInsightData | null, navigationId: string | null): TraceEngine.Insights.Types.InsightResults['DocumentLatency'] | null; +export declare function getDocumentLatencyInsight(insights: Trace.Insights.Types.TraceInsightSets | null, navigationId: string | null): Trace.Insights.Types.InsightResults['DocumentLatency'] | null; export declare class DocumentLatency extends BaseInsight { #private; static readonly litTagName: import("../../../../ui/lit-html/static.js").Static; diff --git a/public/panels/timeline/components/insights/DocumentLatency.js b/public/panels/timeline/components/insights/DocumentLatency.js index 116c60898..d0351bb61 100644 --- a/public/panels/timeline/components/insights/DocumentLatency.js +++ b/public/panels/timeline/components/insights/DocumentLatency.js @@ -43,7 +43,7 @@ export function getDocumentLatencyInsight(insights, navigationId) { if (!insightsByNavigation) { return null; } - const insight = insightsByNavigation.DocumentLatency; + const insight = insightsByNavigation.data.DocumentLatency; if (insight instanceof Error) { return null; } @@ -66,16 +66,19 @@ export class DocumentLatency extends BaseInsight { } createOverlays() { const insight = getDocumentLatencyInsight(this.data.insights, this.data.navigationId); - if (!insight?.documentRequest) { + if (!insight?.data?.documentRequest) { return []; } // TODO(crbug.com/352244434) add breakdown for server response time, queing, redirects, etc... return [{ type: 'ENTRY_SELECTED', - entry: insight.documentRequest, + entry: insight.data.documentRequest, }]; } #renderInsight(insight) { + if (!insight.data) { + return LitHtml.nothing; + } // clang-format off return LitHtml.html `
    @@ -89,13 +92,13 @@ export class DocumentLatency extends BaseInsight {
    • - ${this.#check(insight.redirectDuration === 0, i18nString(UIStrings.passingRedirects), i18nString(UIStrings.failedRedirects))} + ${this.#check(insight.data.redirectDuration === 0, i18nString(UIStrings.passingRedirects), i18nString(UIStrings.failedRedirects))}
    • - ${this.#check(!insight.serverResponseTooSlow, i18nString(UIStrings.passingServerResponseTime), i18nString(UIStrings.failedServerResponseTime))} + ${this.#check(!insight.data.serverResponseTooSlow, i18nString(UIStrings.passingServerResponseTime), i18nString(UIStrings.failedServerResponseTime))}
    • - ${this.#check(insight.uncompressedResponseBytes === 0, i18nString(UIStrings.passingTextCompression), i18nString(UIStrings.failedTextCompression))} + ${this.#check(insight.data.uncompressedResponseBytes === 0, i18nString(UIStrings.passingTextCompression), i18nString(UIStrings.failedTextCompression))}
    @@ -109,7 +112,7 @@ export class DocumentLatency extends BaseInsight { activeCategory: this.data.activeCategory, insightCategory: this.insightCategory, }); - const output = matchesCategory && insight ? this.#renderInsight(insight) : LitHtml.nothing; + const output = matchesCategory && insight?.data ? this.#renderInsight(insight) : LitHtml.nothing; LitHtml.render(output, this.shadow, { host: this }); } } diff --git a/public/panels/timeline/components/insights/DocumentLatency.js.map b/public/panels/timeline/components/insights/DocumentLatency.js.map index 20f73e9f7..e5e4b5c5f 100644 --- a/public/panels/timeline/components/insights/DocumentLatency.js.map +++ b/public/panels/timeline/components/insights/DocumentLatency.js.map @@ -1 +1 @@ -{"version":3,"file":"DocumentLatency.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/DocumentLatency.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport type * as TraceEngine from '../../../../models/trace/trace.js';\nimport * as IconButton from '../../../../ui/components/icon_button/icon_button.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\nimport type * as Overlays from '../../overlays/overlays.js';\n\nimport {BaseInsight, shouldRenderForCategory} from './Helpers.js';\nimport * as SidebarInsight from './SidebarInsight.js';\nimport {InsightsCategories} from './types.js';\n\nconst UIStrings = {\n /**\n * @description Text to tell the user that the document request does not have redirects.\n */\n passingRedirects: 'Avoids redirects',\n /**\n * @description Text to tell the user that the document request had redirects.\n */\n failedRedirects: 'Had redirects',\n /**\n * @description Text to tell the user that the time starting the document request to when the server started responding is acceptable.\n */\n passingServerResponseTime: 'Server responds quickly',\n /**\n * @description Text to tell the user that the time starting the document request to when the server started responding is not acceptable.\n */\n failedServerResponseTime: 'Server responded slowly',\n /**\n * @description Text to tell the user that text compression (like gzip) was applied.\n */\n passingTextCompression: 'Applies text compression',\n /**\n * @description Text to tell the user that text compression (like gzip) was not applied.\n */\n failedTextCompression: 'No compression applied',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/components/insights/DocumentLatency.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function getDocumentLatencyInsight(\n insights: TraceEngine.Insights.Types.TraceInsightData|null,\n navigationId: string|null): TraceEngine.Insights.Types.InsightResults['DocumentLatency']|null {\n if (!insights || !navigationId) {\n return null;\n }\n\n const insightsByNavigation = insights.get(navigationId);\n if (!insightsByNavigation) {\n return null;\n }\n\n const insight = insightsByNavigation.DocumentLatency;\n if (insight instanceof Error) {\n return null;\n }\n return insight;\n}\n\nexport class DocumentLatency extends BaseInsight {\n static readonly litTagName = LitHtml.literal`devtools-performance-document-latency`;\n override insightCategory: InsightsCategories = InsightsCategories.OTHER;\n override internalName: string = 'document-latency';\n override userVisibleTitle: string = 'Document request latency';\n\n #check(didPass: boolean, good: string, bad: string): LitHtml.TemplateResult {\n const icon = didPass ? 'check-circle' : 'clear';\n\n return LitHtml.html`\n <${IconButton.Icon.Icon.litTagName}\n name=${icon}\n class=${didPass ? 'metric-value-good' : 'metric-value-bad'}\n >\n ${didPass ? good : bad}\n `;\n }\n\n override createOverlays(): Overlays.Overlays.TimelineOverlay[] {\n const insight = getDocumentLatencyInsight(this.data.insights, this.data.navigationId);\n if (!insight?.documentRequest) {\n return [];\n }\n\n // TODO(crbug.com/352244434) add breakdown for server response time, queing, redirects, etc...\n return [{\n type: 'ENTRY_SELECTED',\n entry: insight.documentRequest,\n }];\n }\n\n #renderInsight(insight: TraceEngine.Insights.Types.InsightResults['DocumentLatency']): LitHtml.LitTemplate {\n // clang-format off\n return LitHtml.html`\n
    \n <${SidebarInsight.SidebarInsight.litTagName} .data=${{\n title: this.userVisibleTitle,\n expanded: this.isActive(),\n estimatedSavings: insight.metricSavings?.FCP,\n } as SidebarInsight.InsightDetails}\n @insighttoggleclick=${this.onSidebarClick}\n >\n
    \n
      \n
    • \n ${this.#check(insight.redirectDuration === 0,\n i18nString(UIStrings.passingRedirects), i18nString(UIStrings.failedRedirects))}\n
    • \n
    • \n ${this.#check(!insight.serverResponseTooSlow,\n i18nString(UIStrings.passingServerResponseTime), i18nString(UIStrings.failedServerResponseTime))}\n
    • \n
    • \n ${this.#check(insight.uncompressedResponseBytes === 0,\n i18nString(UIStrings.passingTextCompression), i18nString(UIStrings.failedTextCompression))}\n
    • \n
    \n
    \n \n
    `;\n // clang-format on\n }\n\n override render(): void {\n const insight = getDocumentLatencyInsight(this.data.insights, this.data.navigationId);\n const matchesCategory = shouldRenderForCategory({\n activeCategory: this.data.activeCategory,\n insightCategory: this.insightCategory,\n });\n const output = matchesCategory && insight ? this.#renderInsight(insight) : LitHtml.nothing;\n LitHtml.render(output, this.shadow, {host: this});\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-document-latency': DocumentLatency;\n }\n}\n\ncustomElements.define('devtools-performance-document-latency', DocumentLatency);\n"]} \ No newline at end of file +{"version":3,"file":"DocumentLatency.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/DocumentLatency.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport type * as Trace from '../../../../models/trace/trace.js';\nimport * as IconButton from '../../../../ui/components/icon_button/icon_button.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\nimport type * as Overlays from '../../overlays/overlays.js';\n\nimport {BaseInsight, shouldRenderForCategory} from './Helpers.js';\nimport * as SidebarInsight from './SidebarInsight.js';\nimport {InsightsCategories} from './types.js';\n\nconst UIStrings = {\n /**\n * @description Text to tell the user that the document request does not have redirects.\n */\n passingRedirects: 'Avoids redirects',\n /**\n * @description Text to tell the user that the document request had redirects.\n */\n failedRedirects: 'Had redirects',\n /**\n * @description Text to tell the user that the time starting the document request to when the server started responding is acceptable.\n */\n passingServerResponseTime: 'Server responds quickly',\n /**\n * @description Text to tell the user that the time starting the document request to when the server started responding is not acceptable.\n */\n failedServerResponseTime: 'Server responded slowly',\n /**\n * @description Text to tell the user that text compression (like gzip) was applied.\n */\n passingTextCompression: 'Applies text compression',\n /**\n * @description Text to tell the user that text compression (like gzip) was not applied.\n */\n failedTextCompression: 'No compression applied',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/components/insights/DocumentLatency.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function getDocumentLatencyInsight(\n insights: Trace.Insights.Types.TraceInsightSets|null,\n navigationId: string|null): Trace.Insights.Types.InsightResults['DocumentLatency']|null {\n if (!insights || !navigationId) {\n return null;\n }\n\n const insightsByNavigation = insights.get(navigationId);\n if (!insightsByNavigation) {\n return null;\n }\n\n const insight = insightsByNavigation.data.DocumentLatency;\n if (insight instanceof Error) {\n return null;\n }\n return insight;\n}\n\nexport class DocumentLatency extends BaseInsight {\n static readonly litTagName = LitHtml.literal`devtools-performance-document-latency`;\n override insightCategory: InsightsCategories = InsightsCategories.OTHER;\n override internalName: string = 'document-latency';\n override userVisibleTitle: string = 'Document request latency';\n\n #check(didPass: boolean, good: string, bad: string): LitHtml.TemplateResult {\n const icon = didPass ? 'check-circle' : 'clear';\n\n return LitHtml.html`\n <${IconButton.Icon.Icon.litTagName}\n name=${icon}\n class=${didPass ? 'metric-value-good' : 'metric-value-bad'}\n >\n ${didPass ? good : bad}\n `;\n }\n\n override createOverlays(): Overlays.Overlays.TimelineOverlay[] {\n const insight = getDocumentLatencyInsight(this.data.insights, this.data.navigationId);\n if (!insight?.data?.documentRequest) {\n return [];\n }\n\n // TODO(crbug.com/352244434) add breakdown for server response time, queing, redirects, etc...\n return [{\n type: 'ENTRY_SELECTED',\n entry: insight.data.documentRequest,\n }];\n }\n\n #renderInsight(insight: Trace.Insights.Types.InsightResults['DocumentLatency']): LitHtml.LitTemplate {\n if (!insight.data) {\n return LitHtml.nothing;\n }\n\n // clang-format off\n return LitHtml.html`\n
    \n <${SidebarInsight.SidebarInsight.litTagName} .data=${{\n title: this.userVisibleTitle,\n expanded: this.isActive(),\n estimatedSavings: insight.metricSavings?.FCP,\n } as SidebarInsight.InsightDetails}\n @insighttoggleclick=${this.onSidebarClick}\n >\n
    \n
      \n
    • \n ${this.#check(insight.data.redirectDuration === 0,\n i18nString(UIStrings.passingRedirects), i18nString(UIStrings.failedRedirects))}\n
    • \n
    • \n ${this.#check(!insight.data.serverResponseTooSlow,\n i18nString(UIStrings.passingServerResponseTime), i18nString(UIStrings.failedServerResponseTime))}\n
    • \n
    • \n ${this.#check(insight.data.uncompressedResponseBytes === 0,\n i18nString(UIStrings.passingTextCompression), i18nString(UIStrings.failedTextCompression))}\n
    • \n
    \n
    \n \n
    `;\n // clang-format on\n }\n\n override render(): void {\n const insight = getDocumentLatencyInsight(this.data.insights, this.data.navigationId);\n const matchesCategory = shouldRenderForCategory({\n activeCategory: this.data.activeCategory,\n insightCategory: this.insightCategory,\n });\n const output = matchesCategory && insight?.data ? this.#renderInsight(insight) : LitHtml.nothing;\n LitHtml.render(output, this.shadow, {host: this});\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-document-latency': DocumentLatency;\n }\n}\n\ncustomElements.define('devtools-performance-document-latency', DocumentLatency);\n"]} \ No newline at end of file diff --git a/public/panels/timeline/components/insights/Helpers.d.ts b/public/panels/timeline/components/insights/Helpers.d.ts index 4d5225fe8..b66ca7979 100644 --- a/public/panels/timeline/components/insights/Helpers.d.ts +++ b/public/panels/timeline/components/insights/Helpers.d.ts @@ -1,4 +1,4 @@ -import type * as TraceEngine from '../../../../models/trace/trace.js'; +import type * as Trace from '../../../../models/trace/trace.js'; import * as LitHtml from '../../../../ui/lit-html/lit-html.js'; import type * as Overlays from '../../overlays/overlays.js'; import { type ActiveInsight, InsightsCategories } from './types.js'; @@ -12,7 +12,7 @@ export declare function insightIsActive(options: { insightNavigationId: string | null; }): boolean; export interface BaseInsightData { - insights: TraceEngine.Insights.Types.TraceInsightData | null; + insights: Trace.Insights.Types.TraceInsightSets | null; navigationId: string | null; activeInsight: ActiveInsight | null; activeCategory: InsightsCategories; @@ -26,11 +26,12 @@ export declare abstract class BaseInsight extends HTMLElement { protected data: BaseInsightData; protected scheduleRender(): void; connectedCallback(): void; - set insights(insights: TraceEngine.Insights.Types.TraceInsightData | null); + set insights(insights: Trace.Insights.Types.TraceInsightSets | null); set navigationId(navigationId: string | null); - set activeInsight(activeInsight: ActiveInsight); + set activeInsight(activeInsight: ActiveInsight | null); set activeCategory(activeCategory: InsightsCategories); protected onSidebarClick(): void; + protected onOverlayOverride(overlays: Overlays.Overlays.TimelineOverlay[] | null): void; abstract createOverlays(): Overlays.Overlays.TimelineOverlay[]; abstract render(): void; protected isActive(): boolean; diff --git a/public/panels/timeline/components/insights/Helpers.js b/public/panels/timeline/components/insights/Helpers.js index ca7b6240f..8748d2a9d 100644 --- a/public/panels/timeline/components/insights/Helpers.js +++ b/public/panels/timeline/components/insights/Helpers.js @@ -60,6 +60,12 @@ export class BaseInsight extends HTMLElement { } this.dispatchEvent(new SidebarInsight.InsightActivated(this.internalName, this.data.navigationId, this.createOverlays.bind(this))); } + onOverlayOverride(overlays) { + if (!this.isActive()) { + return; + } + this.dispatchEvent(new SidebarInsight.InsightOverlayOverride(overlays)); + } isActive() { return insightIsActive({ activeInsight: this.data.activeInsight, diff --git a/public/panels/timeline/components/insights/Helpers.js.map b/public/panels/timeline/components/insights/Helpers.js.map index 9b5ef0f2b..340afcf25 100644 --- a/public/panels/timeline/components/insights/Helpers.js.map +++ b/public/panels/timeline/components/insights/Helpers.js.map @@ -1 +1 @@ -{"version":3,"file":"Helpers.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/Helpers.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as TraceEngine from '../../../../models/trace/trace.js';\nimport * as Marked from '../../../../third_party/marked/marked.js';\nimport * as ComponentHelpers from '../../../../ui/components/helpers/helpers.js';\nimport * as MarkdownView from '../../../../ui/components/markdown_view/markdown_view.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\nimport type * as Overlays from '../../overlays/overlays.js';\n\nimport sidebarInsightStyles from './sidebarInsight.css.js';\nimport * as SidebarInsight from './SidebarInsight.js';\nimport {type ActiveInsight, InsightsCategories} from './types.js';\n\nexport function shouldRenderForCategory(options: {\n activeCategory: InsightsCategories,\n insightCategory: InsightsCategories,\n}): boolean {\n return options.activeCategory === InsightsCategories.ALL || options.activeCategory === options.insightCategory;\n}\n\nexport function insightIsActive(options: {\n activeInsight: ActiveInsight|null,\n insightName: string,\n insightNavigationId: string|null,\n}): boolean {\n const active = options.activeInsight && options.activeInsight.name === options.insightName &&\n options.activeInsight.navigationId === options.insightNavigationId;\n return Boolean(active);\n}\n\nexport interface BaseInsightData {\n insights: TraceEngine.Insights.Types.TraceInsightData|null;\n navigationId: string|null;\n activeInsight: ActiveInsight|null;\n activeCategory: InsightsCategories;\n}\n\n// This is an abstract base class so the component naming rules do not apply.\n// eslint-disable-next-line rulesdir/check_component_naming\nexport abstract class BaseInsight extends HTMLElement {\n abstract internalName: string;\n abstract insightCategory: InsightsCategories;\n abstract userVisibleTitle: string;\n\n protected readonly shadow = this.attachShadow({mode: 'open'});\n\n protected data: BaseInsightData = {\n insights: null,\n navigationId: null,\n activeInsight: null,\n activeCategory: InsightsCategories.ALL,\n };\n\n readonly #boundRender = this.render.bind(this);\n\n protected scheduleRender(): void {\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n connectedCallback(): void {\n this.shadow.adoptedStyleSheets.push(sidebarInsightStyles);\n }\n\n set insights(insights: TraceEngine.Insights.Types.TraceInsightData|null) {\n this.data.insights = insights;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n set navigationId(navigationId: string|null) {\n this.data.navigationId = navigationId;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n set activeInsight(activeInsight: ActiveInsight) {\n this.data.activeInsight = activeInsight;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n set activeCategory(activeCategory: InsightsCategories) {\n this.data.activeCategory = activeCategory;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n protected onSidebarClick(): void {\n if (this.isActive()) {\n this.dispatchEvent(new SidebarInsight.InsightDeactivated());\n return;\n }\n if (!this.data.navigationId) {\n // Shouldn't happen, but needed to satisfy TS.\n return;\n }\n\n this.dispatchEvent(new SidebarInsight.InsightActivated(\n this.internalName,\n this.data.navigationId,\n this.createOverlays.bind(this),\n ));\n }\n\n abstract createOverlays(): Overlays.Overlays.TimelineOverlay[];\n\n abstract render(): void;\n\n protected isActive(): boolean {\n return insightIsActive({\n activeInsight: this.data.activeInsight,\n insightName: this.internalName,\n insightNavigationId: this.data.navigationId,\n });\n }\n}\n\n/**\n * Returns a rendered MarkdownView component.\n *\n * This should not be used for markdown that is not guaranteed to be valid.\n */\nexport function md(markdown: string): LitHtml.TemplateResult {\n const tokens = Marked.Marked.lexer(markdown);\n return LitHtml.html`<${MarkdownView.MarkdownView.MarkdownView.litTagName}\n .data=${{tokens} as MarkdownView.MarkdownView.MarkdownViewData}>\n `;\n}\n"]} \ No newline at end of file +{"version":3,"file":"Helpers.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/Helpers.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Trace from '../../../../models/trace/trace.js';\nimport * as Marked from '../../../../third_party/marked/marked.js';\nimport * as ComponentHelpers from '../../../../ui/components/helpers/helpers.js';\nimport * as MarkdownView from '../../../../ui/components/markdown_view/markdown_view.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\nimport type * as Overlays from '../../overlays/overlays.js';\n\nimport sidebarInsightStyles from './sidebarInsight.css.js';\nimport * as SidebarInsight from './SidebarInsight.js';\nimport {type ActiveInsight, InsightsCategories} from './types.js';\n\nexport function shouldRenderForCategory(options: {\n activeCategory: InsightsCategories,\n insightCategory: InsightsCategories,\n}): boolean {\n return options.activeCategory === InsightsCategories.ALL || options.activeCategory === options.insightCategory;\n}\n\nexport function insightIsActive(options: {\n activeInsight: ActiveInsight|null,\n insightName: string,\n insightNavigationId: string|null,\n}): boolean {\n const active = options.activeInsight && options.activeInsight.name === options.insightName &&\n options.activeInsight.navigationId === options.insightNavigationId;\n return Boolean(active);\n}\n\nexport interface BaseInsightData {\n insights: Trace.Insights.Types.TraceInsightSets|null;\n navigationId: string|null;\n activeInsight: ActiveInsight|null;\n activeCategory: InsightsCategories;\n}\n\n// This is an abstract base class so the component naming rules do not apply.\n// eslint-disable-next-line rulesdir/check_component_naming\nexport abstract class BaseInsight extends HTMLElement {\n abstract internalName: string;\n abstract insightCategory: InsightsCategories;\n abstract userVisibleTitle: string;\n\n protected readonly shadow = this.attachShadow({mode: 'open'});\n\n protected data: BaseInsightData = {\n insights: null,\n navigationId: null,\n activeInsight: null,\n activeCategory: InsightsCategories.ALL,\n };\n\n readonly #boundRender = this.render.bind(this);\n\n protected scheduleRender(): void {\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n connectedCallback(): void {\n this.shadow.adoptedStyleSheets.push(sidebarInsightStyles);\n }\n\n set insights(insights: Trace.Insights.Types.TraceInsightSets|null) {\n this.data.insights = insights;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n set navigationId(navigationId: string|null) {\n this.data.navigationId = navigationId;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n set activeInsight(activeInsight: ActiveInsight|null) {\n this.data.activeInsight = activeInsight;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n set activeCategory(activeCategory: InsightsCategories) {\n this.data.activeCategory = activeCategory;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n protected onSidebarClick(): void {\n if (this.isActive()) {\n this.dispatchEvent(new SidebarInsight.InsightDeactivated());\n return;\n }\n if (!this.data.navigationId) {\n // Shouldn't happen, but needed to satisfy TS.\n return;\n }\n\n this.dispatchEvent(new SidebarInsight.InsightActivated(\n this.internalName,\n this.data.navigationId,\n this.createOverlays.bind(this),\n ));\n }\n\n protected onOverlayOverride(overlays: Overlays.Overlays.TimelineOverlay[]|null): void {\n if (!this.isActive()) {\n return;\n }\n\n this.dispatchEvent(new SidebarInsight.InsightOverlayOverride(overlays));\n }\n\n abstract createOverlays(): Overlays.Overlays.TimelineOverlay[];\n\n abstract render(): void;\n\n protected isActive(): boolean {\n return insightIsActive({\n activeInsight: this.data.activeInsight,\n insightName: this.internalName,\n insightNavigationId: this.data.navigationId,\n });\n }\n}\n\n/**\n * Returns a rendered MarkdownView component.\n *\n * This should not be used for markdown that is not guaranteed to be valid.\n */\nexport function md(markdown: string): LitHtml.TemplateResult {\n const tokens = Marked.Marked.lexer(markdown);\n return LitHtml.html`<${MarkdownView.MarkdownView.MarkdownView.litTagName}\n .data=${{tokens} as MarkdownView.MarkdownView.MarkdownViewData}>\n `;\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/components/insights/InteractionToNextPaint.d.ts b/public/panels/timeline/components/insights/InteractionToNextPaint.d.ts index ef72f2eca..4041e82f1 100644 --- a/public/panels/timeline/components/insights/InteractionToNextPaint.d.ts +++ b/public/panels/timeline/components/insights/InteractionToNextPaint.d.ts @@ -1,8 +1,8 @@ -import * as TraceEngine from '../../../../models/trace/trace.js'; +import * as Trace from '../../../../models/trace/trace.js'; import type * as Overlays from '../../overlays/overlays.js'; import { BaseInsight } from './Helpers.js'; import { InsightsCategories } from './types.js'; -export declare function getINPInsight(insights: TraceEngine.Insights.Types.TraceInsightData | null, navigationId: string | null): TraceEngine.Insights.Types.InsightResults['InteractionToNextPaint'] | null; +export declare function getINPInsight(insights: Trace.Insights.Types.TraceInsightSets | null, navigationId: string | null): Trace.Insights.Types.InsightResults['InteractionToNextPaint'] | null; export declare class InteractionToNextPaint extends BaseInsight { #private; static readonly litTagName: import("../../../../ui/lit-html/static.js").Static; diff --git a/public/panels/timeline/components/insights/InteractionToNextPaint.js b/public/panels/timeline/components/insights/InteractionToNextPaint.js index 124722345..f5a9b2f34 100644 --- a/public/panels/timeline/components/insights/InteractionToNextPaint.js +++ b/public/panels/timeline/components/insights/InteractionToNextPaint.js @@ -3,7 +3,7 @@ // found in the LICENSE file. import * as i18n from '../../../../core/i18n/i18n.js'; import * as Platform from '../../../../core/platform/platform.js'; -import * as TraceEngine from '../../../../models/trace/trace.js'; +import * as Trace from '../../../../models/trace/trace.js'; import * as LitHtml from '../../../../ui/lit-html/lit-html.js'; import { BaseInsight, md, shouldRenderForCategory } from './Helpers.js'; import * as SidebarInsight from './SidebarInsight.js'; @@ -13,7 +13,7 @@ const UIStrings = { /** * @description Text to tell the user about the longest user interaction. */ - description: 'Improve user responsiveness by improving the Interaction to Next Paint metric. Learn how to [Optimize INP](https://web.dev/articles/optimize-inp).', + description: 'Optimize user responsiveness by [improving the Interaction to Next Paint metric](https://web.dev/articles/optimize-inp).', /** * @description Title for the performance insight "INP by phase", which shows a breakdown of INP by phases / sections. */ @@ -54,7 +54,7 @@ export function getINPInsight(insights, navigationId) { if (!insightsByNavigation) { return null; } - const insight = insightsByNavigation.InteractionToNextPaint; + const insight = insightsByNavigation.data.InteractionToNextPaint; if (insight instanceof Error) { return null; } @@ -82,9 +82,9 @@ export class InteractionToNextPaint extends BaseInsight { if (!event) { return []; } - const p1 = TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(event.ts, (event.ts + event.inputDelay)); - const p2 = TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(p1.max, (p1.max + event.mainThreadHandling)); - const p3 = TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(p2.max, (p2.max + event.presentationDelay)); + const p1 = Trace.Helpers.Timing.traceWindowFromMicroSeconds(event.ts, (event.ts + event.inputDelay)); + const p2 = Trace.Helpers.Timing.traceWindowFromMicroSeconds(p1.max, (p1.max + event.mainThreadHandling)); + const p3 = Trace.Helpers.Timing.traceWindowFromMicroSeconds(p2.max, (p2.max + event.presentationDelay)); const sections = [ { bounds: p1, label: i18nString(UIStrings.inputDelay), showDuration: true }, { bounds: p2, label: i18nString(UIStrings.processingDuration), showDuration: true }, diff --git a/public/panels/timeline/components/insights/InteractionToNextPaint.js.map b/public/panels/timeline/components/insights/InteractionToNextPaint.js.map index c9e34499a..b5edc4641 100644 --- a/public/panels/timeline/components/insights/InteractionToNextPaint.js.map +++ b/public/panels/timeline/components/insights/InteractionToNextPaint.js.map @@ -1 +1 @@ -{"version":3,"file":"InteractionToNextPaint.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/InteractionToNextPaint.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport * as Platform from '../../../../core/platform/platform.js';\nimport * as TraceEngine from '../../../../models/trace/trace.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\nimport type * as Overlays from '../../overlays/overlays.js';\n\nimport {BaseInsight, md, shouldRenderForCategory} from './Helpers.js';\nimport * as SidebarInsight from './SidebarInsight.js';\nimport {Table, type TableData} from './Table.js';\nimport {InsightsCategories} from './types.js';\n\nconst UIStrings = {\n /**\n * @description Text to tell the user about the longest user interaction.\n */\n description:\n 'Improve user responsiveness by improving the Interaction to Next Paint metric. Learn how to [Optimize INP](https://web.dev/articles/optimize-inp).',\n /**\n * @description Title for the performance insight \"INP by phase\", which shows a breakdown of INP by phases / sections.\n */\n title: 'INP by phase',\n /**\n *@description Label used to denote the longest user interaction.\n */\n longestInteraction: 'Longest interaction',\n /**\n *@description Label used for the phase/component/stage/section of a larger duration.\n */\n phase: 'Phase',\n /**\n *@description Label used for a time duration.\n */\n duration: 'Duration',\n\n // TODO: these are repeated in InteractionBreakdown. Add a place for common strings?\n /**\n *@description Text shown next to the interaction event's input delay time in the detail view.\n */\n inputDelay: 'Input delay',\n /**\n *@description Text shown next to the interaction event's thread processing duration in the detail view.\n */\n processingDuration: 'Processing duration',\n /**\n *@description Text shown next to the interaction event's presentation delay time in the detail view.\n */\n presentationDelay: 'Presentation delay',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/components/insights/InteractionToNextPaint.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function getINPInsight(insights: TraceEngine.Insights.Types.TraceInsightData|null, navigationId: string|null):\n TraceEngine.Insights.Types.InsightResults['InteractionToNextPaint']|null {\n if (!insights || !navigationId) {\n return null;\n }\n\n const insightsByNavigation = insights.get(navigationId);\n if (!insightsByNavigation) {\n return null;\n }\n\n const insight = insightsByNavigation.InteractionToNextPaint;\n if (insight instanceof Error) {\n return null;\n }\n return insight;\n}\n\nexport class InteractionToNextPaint extends BaseInsight {\n static readonly litTagName = LitHtml.literal`devtools-performance-inp`;\n override insightCategory: InsightsCategories = InsightsCategories.INP;\n override internalName: string = 'inp';\n override userVisibleTitle: string = i18nString(UIStrings.title);\n\n override createOverlays(): Overlays.Overlays.TimelineOverlay[] {\n if (!this.data.insights || !this.data.navigationId) {\n return [];\n }\n const {navigationId, insights} = this.data;\n\n const insightsByNavigation = insights.get(navigationId);\n if (!insightsByNavigation) {\n return [];\n }\n\n const insight = getINPInsight(insights, this.data.navigationId);\n if (!insight) {\n return [];\n }\n\n const event = insight.longestInteractionEvent;\n if (!event) {\n return [];\n }\n\n const p1 = TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(\n event.ts,\n (event.ts + event.inputDelay) as TraceEngine.Types.Timing.MicroSeconds,\n );\n const p2 = TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(\n p1.max,\n (p1.max + event.mainThreadHandling) as TraceEngine.Types.Timing.MicroSeconds,\n );\n const p3 = TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(\n p2.max,\n (p2.max + event.presentationDelay) as TraceEngine.Types.Timing.MicroSeconds,\n );\n const sections = [\n {bounds: p1, label: i18nString(UIStrings.inputDelay), showDuration: true},\n {bounds: p2, label: i18nString(UIStrings.processingDuration), showDuration: true},\n {bounds: p3, label: i18nString(UIStrings.presentationDelay), showDuration: true},\n ];\n\n return [\n {\n type: 'TIMESPAN_BREAKDOWN',\n sections,\n },\n {\n type: 'ENTRY_LABEL',\n // TODO(b/351757537) why aren't annotations rendering for synthetic events?\n entry: event,\n label: i18nString(UIStrings.longestInteraction),\n },\n ];\n }\n\n #render(event: TraceEngine.Types.TraceEvents.SyntheticInteractionPair): LitHtml.TemplateResult {\n const time = (us: TraceEngine.Types.Timing.MicroSeconds): string =>\n i18n.TimeUtilities.millisToString(Platform.Timing.microSecondsToMilliSeconds(us));\n\n // clang-format off\n return LitHtml.html`\n
    \n <${SidebarInsight.SidebarInsight.litTagName} .data=${{\n title: this.userVisibleTitle,\n expanded: this.isActive(),\n } as SidebarInsight.InsightDetails}\n @insighttoggleclick=${this.onSidebarClick}>\n
    \n ${md(i18nString(UIStrings.description))}\n
    \n
    \n ${LitHtml.html`<${Table.litTagName}\n .data=${{\n headers: [i18nString(UIStrings.phase), i18nString(UIStrings.duration)],\n rows: [\n [i18nString(UIStrings.inputDelay), time(event.inputDelay)],\n [i18nString(UIStrings.processingDuration), time(event.mainThreadHandling)],\n [i18nString(UIStrings.presentationDelay), time(event.presentationDelay)],\n ],\n } as TableData}>\n `}\n
    \n \n
    `;\n // clang-format on\n }\n\n override render(): void {\n const insight = getINPInsight(this.data.insights, this.data.navigationId);\n const event = insight?.longestInteractionEvent;\n\n const matchesCategory = shouldRenderForCategory({\n activeCategory: this.data.activeCategory,\n insightCategory: this.insightCategory,\n });\n const output = event && matchesCategory ? this.#render(event) : LitHtml.nothing;\n LitHtml.render(output, this.shadow, {host: this});\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-inp': InteractionToNextPaint;\n }\n}\n\ncustomElements.define('devtools-performance-inp', InteractionToNextPaint);\n"]} \ No newline at end of file +{"version":3,"file":"InteractionToNextPaint.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/InteractionToNextPaint.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport * as Platform from '../../../../core/platform/platform.js';\nimport * as Trace from '../../../../models/trace/trace.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\nimport type * as Overlays from '../../overlays/overlays.js';\n\nimport {BaseInsight, md, shouldRenderForCategory} from './Helpers.js';\nimport * as SidebarInsight from './SidebarInsight.js';\nimport {Table, type TableData} from './Table.js';\nimport {InsightsCategories} from './types.js';\n\nconst UIStrings = {\n /**\n * @description Text to tell the user about the longest user interaction.\n */\n description:\n 'Optimize user responsiveness by [improving the Interaction to Next Paint metric](https://web.dev/articles/optimize-inp).',\n /**\n * @description Title for the performance insight \"INP by phase\", which shows a breakdown of INP by phases / sections.\n */\n title: 'INP by phase',\n /**\n *@description Label used to denote the longest user interaction.\n */\n longestInteraction: 'Longest interaction',\n /**\n *@description Label used for the phase/component/stage/section of a larger duration.\n */\n phase: 'Phase',\n /**\n *@description Label used for a time duration.\n */\n duration: 'Duration',\n\n // TODO: these are repeated in InteractionBreakdown. Add a place for common strings?\n /**\n *@description Text shown next to the interaction event's input delay time in the detail view.\n */\n inputDelay: 'Input delay',\n /**\n *@description Text shown next to the interaction event's thread processing duration in the detail view.\n */\n processingDuration: 'Processing duration',\n /**\n *@description Text shown next to the interaction event's presentation delay time in the detail view.\n */\n presentationDelay: 'Presentation delay',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/components/insights/InteractionToNextPaint.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function getINPInsight(insights: Trace.Insights.Types.TraceInsightSets|null, navigationId: string|null):\n Trace.Insights.Types.InsightResults['InteractionToNextPaint']|null {\n if (!insights || !navigationId) {\n return null;\n }\n\n const insightsByNavigation = insights.get(navigationId);\n if (!insightsByNavigation) {\n return null;\n }\n\n const insight = insightsByNavigation.data.InteractionToNextPaint;\n if (insight instanceof Error) {\n return null;\n }\n return insight;\n}\n\nexport class InteractionToNextPaint extends BaseInsight {\n static readonly litTagName = LitHtml.literal`devtools-performance-inp`;\n override insightCategory: InsightsCategories = InsightsCategories.INP;\n override internalName: string = 'inp';\n override userVisibleTitle: string = i18nString(UIStrings.title);\n\n override createOverlays(): Overlays.Overlays.TimelineOverlay[] {\n if (!this.data.insights || !this.data.navigationId) {\n return [];\n }\n const {navigationId, insights} = this.data;\n\n const insightsByNavigation = insights.get(navigationId);\n if (!insightsByNavigation) {\n return [];\n }\n\n const insight = getINPInsight(insights, this.data.navigationId);\n if (!insight) {\n return [];\n }\n\n const event = insight.longestInteractionEvent;\n if (!event) {\n return [];\n }\n\n const p1 = Trace.Helpers.Timing.traceWindowFromMicroSeconds(\n event.ts,\n (event.ts + event.inputDelay) as Trace.Types.Timing.MicroSeconds,\n );\n const p2 = Trace.Helpers.Timing.traceWindowFromMicroSeconds(\n p1.max,\n (p1.max + event.mainThreadHandling) as Trace.Types.Timing.MicroSeconds,\n );\n const p3 = Trace.Helpers.Timing.traceWindowFromMicroSeconds(\n p2.max,\n (p2.max + event.presentationDelay) as Trace.Types.Timing.MicroSeconds,\n );\n const sections = [\n {bounds: p1, label: i18nString(UIStrings.inputDelay), showDuration: true},\n {bounds: p2, label: i18nString(UIStrings.processingDuration), showDuration: true},\n {bounds: p3, label: i18nString(UIStrings.presentationDelay), showDuration: true},\n ];\n\n return [\n {\n type: 'TIMESPAN_BREAKDOWN',\n sections,\n },\n {\n type: 'ENTRY_LABEL',\n // TODO(b/351757537) why aren't annotations rendering for synthetic events?\n entry: event,\n label: i18nString(UIStrings.longestInteraction),\n },\n ];\n }\n\n #render(event: Trace.Types.Events.SyntheticInteractionPair): LitHtml.TemplateResult {\n const time = (us: Trace.Types.Timing.MicroSeconds): string =>\n i18n.TimeUtilities.millisToString(Platform.Timing.microSecondsToMilliSeconds(us));\n\n // clang-format off\n return LitHtml.html`\n
    \n <${SidebarInsight.SidebarInsight.litTagName} .data=${{\n title: this.userVisibleTitle,\n expanded: this.isActive(),\n } as SidebarInsight.InsightDetails}\n @insighttoggleclick=${this.onSidebarClick}>\n
    \n ${md(i18nString(UIStrings.description))}\n
    \n
    \n ${LitHtml.html`<${Table.litTagName}\n .data=${{\n headers: [i18nString(UIStrings.phase), i18nString(UIStrings.duration)],\n rows: [\n [i18nString(UIStrings.inputDelay), time(event.inputDelay)],\n [i18nString(UIStrings.processingDuration), time(event.mainThreadHandling)],\n [i18nString(UIStrings.presentationDelay), time(event.presentationDelay)],\n ],\n } as TableData}>\n `}\n
    \n \n
    `;\n // clang-format on\n }\n\n override render(): void {\n const insight = getINPInsight(this.data.insights, this.data.navigationId);\n const event = insight?.longestInteractionEvent;\n\n const matchesCategory = shouldRenderForCategory({\n activeCategory: this.data.activeCategory,\n insightCategory: this.insightCategory,\n });\n const output = event && matchesCategory ? this.#render(event) : LitHtml.nothing;\n LitHtml.render(output, this.shadow, {host: this});\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-inp': InteractionToNextPaint;\n }\n}\n\ncustomElements.define('devtools-performance-inp', InteractionToNextPaint);\n"]} \ No newline at end of file diff --git a/public/panels/timeline/components/insights/LCPDiscovery.d.ts b/public/panels/timeline/components/insights/LCPDiscovery.d.ts index ec84ff976..5ccdaf535 100644 --- a/public/panels/timeline/components/insights/LCPDiscovery.d.ts +++ b/public/panels/timeline/components/insights/LCPDiscovery.d.ts @@ -1,8 +1,8 @@ -import * as TraceEngine from '../../../../models/trace/trace.js'; +import * as Trace from '../../../../models/trace/trace.js'; import type * as Overlays from '../../overlays/overlays.js'; import { BaseInsight } from './Helpers.js'; import { InsightsCategories } from './types.js'; -export declare function getLCPInsightData(insights: TraceEngine.Insights.Types.TraceInsightData | null, navigationId: string | null): TraceEngine.Insights.Types.InsightResults['LargestContentfulPaint'] | null; +export declare function getLCPInsightData(insights: Trace.Insights.Types.TraceInsightSets | null, navigationId: string | null): Trace.Insights.Types.InsightResults['LargestContentfulPaint'] | null; export declare class LCPDiscovery extends BaseInsight { #private; static readonly litTagName: import("../../../../ui/lit-html/static.js").Static; diff --git a/public/panels/timeline/components/insights/LCPDiscovery.js b/public/panels/timeline/components/insights/LCPDiscovery.js index 588425db6..77c59fe02 100644 --- a/public/panels/timeline/components/insights/LCPDiscovery.js +++ b/public/panels/timeline/components/insights/LCPDiscovery.js @@ -4,7 +4,7 @@ import * as Common from '../../../../core/common/common.js'; import * as i18n from '../../../../core/i18n/i18n.js'; import * as Platform from '../../../../core/platform/platform.js'; -import * as TraceEngine from '../../../../models/trace/trace.js'; +import * as Trace from '../../../../models/trace/trace.js'; import * as IconButton from '../../../../ui/components/icon_button/icon_button.js'; import * as LitHtml from '../../../../ui/lit-html/lit-html.js'; import { BaseInsight, shouldRenderForCategory } from './Helpers.js'; @@ -40,7 +40,7 @@ export function getLCPInsightData(insights, navigationId) { if (!insightsByNavigation) { return null; } - const lcpInsight = insightsByNavigation.LargestContentfulPaint; + const lcpInsight = insightsByNavigation.data.LargestContentfulPaint; if (lcpInsight instanceof Error) { return null; } @@ -72,7 +72,7 @@ function getImageData(insights, navigationId) { }; if (lcpInsight.earliestDiscoveryTimeTs && lcpInsight.lcpRequest) { const discoveryDelay = lcpInsight.lcpRequest.ts - lcpInsight.earliestDiscoveryTimeTs; - data.discoveryDelay = TraceEngine.Types.Timing.MicroSeconds(discoveryDelay); + data.discoveryDelay = Trace.Types.Timing.MicroSeconds(discoveryDelay); } return data; } @@ -105,7 +105,7 @@ export class LCPDiscovery extends BaseInsight { if (!imageResults || !imageResults.discoveryDelay) { return []; } - const delay = TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(TraceEngine.Types.Timing.MicroSeconds(imageResults.request.ts - imageResults.discoveryDelay), imageResults.request.ts); + const delay = Trace.Helpers.Timing.traceWindowFromMicroSeconds(Trace.Types.Timing.MicroSeconds(imageResults.request.ts - imageResults.discoveryDelay), imageResults.request.ts); const label = LitHtml.html `
    ${this.#renderDiscoveryDelay(delay.range)}
    `; return [ { diff --git a/public/panels/timeline/components/insights/LCPDiscovery.js.map b/public/panels/timeline/components/insights/LCPDiscovery.js.map index 387a99fcd..18447b338 100644 --- a/public/panels/timeline/components/insights/LCPDiscovery.js.map +++ b/public/panels/timeline/components/insights/LCPDiscovery.js.map @@ -1 +1 @@ -{"version":3,"file":"LCPDiscovery.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/LCPDiscovery.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,MAAM,MAAM,mCAAmC,CAAC;AAC5D,OAAO,KAAK,IAAI,MAAM,+BAA+B,CAAC;AACtD,OAAO,KAAK,QAAQ,MAAM,uCAAuC,CAAC;AAClE,OAAO,KAAK,WAAW,MAAM,mCAAmC,CAAC;AACjE,OAAO,KAAK,UAAU,MAAM,sDAAsD,CAAC;AACnF,OAAO,KAAK,OAAO,MAAM,qCAAqC,CAAC;AAG/D,OAAO,EAAC,WAAW,EAAE,uBAAuB,EAAC,MAAM,cAAc,CAAC;AAClE,OAAO,eAAe,MAAM,uBAAuB,CAAC;AACpD,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAC,kBAAkB,EAAC,MAAM,YAAY,CAAC;AAE9C,MAAM,SAAS,GAAG;IAChB;;;OAGG;IACH,YAAY,EAAE,oDAAoD;IAClE;;OAEG;IACH,oBAAoB,EAAE,4BAA4B;IAClD;;OAEG;IACH,mBAAmB,EAAE,6CAA6C;IAClE;;OAEG;IACH,kBAAkB,EAAE,uBAAuB;CAE5C,CAAC;AAEF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,qDAAqD,EAAE,SAAS,CAAC,CAAC;AAC3G,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAUtE,MAAM,UAAU,iBAAiB,CAC7B,QAA0D,EAC1D,YAAyB;IAC3B,IAAI,CAAC,QAAQ,IAAI,CAAC,YAAY,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,oBAAoB,GAAG,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACxD,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,UAAU,GAAG,oBAAoB,CAAC,sBAAsB,CAAC;IAC/D,IAAI,UAAU,YAAY,KAAK,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAS,YAAY,CACjB,QAA0D,EAAE,YAAyB;IACvF,MAAM,UAAU,GAAG,iBAAiB,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;IAC7D,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,UAAU,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;QACxC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,0BAA0B,GAAG,UAAU,CAAC,0BAA0B,CAAC;IACzE,MAAM,kBAAkB,GAAG,UAAU,CAAC,kBAAkB,CAAC;IACzD,MAAM,uBAAuB,GAAG,UAAU,CAAC,uBAAuB,CAAC;IAEnE,MAAM,QAAQ,GAAG,0BAA0B,KAAK,SAAS,IAAI,kBAAkB,KAAK,SAAS;QACzF,uBAAuB,KAAK,SAAS,CAAC;IAE1C,mEAAmE;IACnE,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,IAAI,GAA0B;QAClC,0BAA0B;QAC1B,kBAAkB;QAClB,uBAAuB;QACvB,OAAO,EAAE,UAAU,CAAC,UAAU;QAC9B,cAAc,EAAE,IAAI;KACrB,CAAC;IAEF,IAAI,UAAU,CAAC,uBAAuB,IAAI,UAAU,CAAC,UAAU,EAAE,CAAC;QAChE,MAAM,cAAc,GAAG,UAAU,CAAC,UAAU,CAAC,EAAE,GAAG,UAAU,CAAC,uBAAuB,CAAC;QACrF,IAAI,CAAC,cAAc,GAAG,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,cAAc,CAAC,CAAC;IAC9E,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,OAAO,YAAa,SAAQ,WAAW;IAC3C,MAAM,CAAU,UAAU,GAAG,OAAO,CAAC,OAAO,CAAA,oCAAoC,CAAC;IACxE,eAAe,GAAuB,kBAAkB,CAAC,GAAG,CAAC;IAC7D,YAAY,GAAW,eAAe,CAAC;IACvC,gBAAgB,GAAW,uBAAuB,CAAC;IAEnD,iBAAiB;QACxB,KAAK,CAAC,iBAAiB,EAAE,CAAC;QAC1B,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IACvD,CAAC;IAED,WAAW,CAAC,OAAgB;QAC1B,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC;QAEhD,OAAO,OAAO,CAAC,IAAI,CAAA;SACd,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU;aAC3B,IAAI;cACH,OAAO,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,CAAC,mBAAmB;WACrD,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU;KACrC,CAAC;IACJ,CAAC;IAED,qBAAqB,CAAC,KAA4C;QAChE,MAAM,WAAW,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACnD,WAAW,CAAC,SAAS,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QAC/C,WAAW,CAAC,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC;QACzE,OAAO,IAAI,CAAC,IAAI,CAAC,wBAAwB,CAAC,IAAI,EAAE,SAAS,CAAC,YAAY,EAAE,EAAC,GAAG,EAAE,WAAW,EAAC,CAAC,CAAC;IAC9F,CAAC;IAEQ,cAAc;QACrB,MAAM,YAAY,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC9E,IAAI,CAAC,YAAY,IAAI,CAAC,YAAY,CAAC,cAAc,EAAE,CAAC;YAClD,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,KAAK,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,2BAA2B,CAChE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,GAAG,YAAY,CAAC,cAAc,CAAC,EAC5F,YAAY,CAAC,OAAO,CAAC,EAAE,CAC1B,CAAC;QAEF,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,CAAA,iCAAiC,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC;QAE3G,OAAO;YACL;gBACE,IAAI,EAAE,eAAe;gBACrB,KAAK,EAAE,YAAY,CAAC,OAAO;gBAC3B,aAAa,EAAE,OAAO;aACvB;YACD;gBACE,IAAI,EAAE,0BAA0B;gBAChC,MAAM,EAAE,KAAK;gBACb,KAAK,EAAE,YAAY,CAAC,OAAO;aAC5B;YACD;gBACE,IAAI,EAAE,oBAAoB;gBAC1B,QAAQ,EAAE,CAAC;wBACT,MAAM,EAAE,KAAK;wBACb,KAAK;wBACL,YAAY,EAAE,KAAK;qBACpB,CAAC;gBACF,KAAK,EAAE,YAAY,CAAC,OAAO;aAC5B;SACF,CAAC;IACJ,CAAC;IAED,gBAAgB,CAAC,SAAgC;QAC/C,mBAAmB;QACnB,OAAO,OAAO,CAAC,IAAI,CAAA;;aAEV,cAAc,CAAC,cAAc,CAAC,UAAU,UAAU;YACnD,KAAK,EAAE,IAAI,CAAC,gBAAgB;YAC5B,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE;SACO;gCACZ,IAAI,CAAC,cAAc;;;YAGvC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAA,gCAAgC,IAAI,CAAC,qBAAqB,CAAC,SAAS,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO;;;kBAG/I,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,0BAA0B,CAAC;wBAChD,UAAU,CAAC,SAAS,CAAC,oBAAoB,CAAC;;;kBAGhD,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,kBAAkB,CAAC;wBACxC,UAAU,CAAC,SAAS,CAAC,mBAAmB,CAAC;;;kBAG/C,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,uBAAuB,CAAC;wBAC7C,UAAU,CAAC,SAAS,CAAC,kBAAkB,CAAC;;;;;gDAKhB,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,QAAQ,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;;gBAEtG,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,WAAW,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC;sDACvC,QAAQ,CAAC,eAAe,CAAC,aAAa,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,IAAI,CAAC,CAAC;;;YAGpI,cAAc,CAAC,cAAc;aAC5B,CAAC;QACV,kBAAkB;IACpB,CAAC;IAEQ,MAAM;QACb,MAAM,YAAY,GAAG,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC9E,MAAM,eAAe,GAAG,uBAAuB,CAAC;YAC9C,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,cAAc;YACxC,eAAe,EAAE,IAAI,CAAC,eAAe;SACtC,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,YAAY,IAAI,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;QACvG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC,CAAC;IACpD,CAAC;;AASH,cAAc,CAAC,MAAM,CAAC,oCAAoC,EAAE,YAAY,CAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../../../core/common/common.js';\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport * as Platform from '../../../../core/platform/platform.js';\nimport * as TraceEngine from '../../../../models/trace/trace.js';\nimport * as IconButton from '../../../../ui/components/icon_button/icon_button.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\nimport type * as Overlays from '../../overlays/overlays.js';\n\nimport {BaseInsight, shouldRenderForCategory} from './Helpers.js';\nimport discoveryStyles from './lcpDiscovery.css.js';\nimport * as SidebarInsight from './SidebarInsight.js';\nimport {InsightsCategories} from './types.js';\n\nconst UIStrings = {\n /**\n * @description Text to tell the user how long after the earliest discovery time their LCP element loaded.\n * @example {401ms} PH1\n */\n lcpLoadDelay: 'LCP image loaded {PH1} after earliest start point.',\n /**\n * @description Text to tell the user that a fetchpriority property value of \"high\" is applied to the LCP request.\n */\n fetchPriorityApplied: 'fetchpriority=high applied',\n /**\n * @description Text to tell the user that the LCP request is discoverable in the initial document.\n */\n requestDiscoverable: 'Request is discoverable in initial document',\n /**\n * @description Text to tell the user that the LCP request does not have the lazy load property applied.\n */\n lazyLoadNotApplied: 'lazy load not applied',\n\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/components/insights/LCPDiscovery.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\ninterface LCPImageDiscoveryData {\n shouldIncreasePriorityHint: boolean;\n shouldPreloadImage: boolean;\n shouldRemoveLazyLoading: boolean;\n request: TraceEngine.Types.TraceEvents.SyntheticNetworkRequest;\n discoveryDelay: TraceEngine.Types.Timing.MicroSeconds|null;\n}\n\nexport function getLCPInsightData(\n insights: TraceEngine.Insights.Types.TraceInsightData|null,\n navigationId: string|null): TraceEngine.Insights.Types.InsightResults['LargestContentfulPaint']|null {\n if (!insights || !navigationId) {\n return null;\n }\n\n const insightsByNavigation = insights.get(navigationId);\n if (!insightsByNavigation) {\n return null;\n }\n\n const lcpInsight = insightsByNavigation.LargestContentfulPaint;\n if (lcpInsight instanceof Error) {\n return null;\n }\n return lcpInsight;\n}\n\nfunction getImageData(\n insights: TraceEngine.Insights.Types.TraceInsightData|null, navigationId: string|null): LCPImageDiscoveryData|null {\n const lcpInsight = getLCPInsightData(insights, navigationId);\n if (!lcpInsight) {\n return null;\n }\n\n if (lcpInsight.lcpRequest === undefined) {\n return null;\n }\n\n const shouldIncreasePriorityHint = lcpInsight.shouldIncreasePriorityHint;\n const shouldPreloadImage = lcpInsight.shouldPreloadImage;\n const shouldRemoveLazyLoading = lcpInsight.shouldRemoveLazyLoading;\n\n const imageLCP = shouldIncreasePriorityHint !== undefined && shouldPreloadImage !== undefined &&\n shouldRemoveLazyLoading !== undefined;\n\n // Shouldn't render anything if lcp insight is null or lcp is text.\n if (!imageLCP) {\n return null;\n }\n\n const data: LCPImageDiscoveryData = {\n shouldIncreasePriorityHint,\n shouldPreloadImage,\n shouldRemoveLazyLoading,\n request: lcpInsight.lcpRequest,\n discoveryDelay: null,\n };\n\n if (lcpInsight.earliestDiscoveryTimeTs && lcpInsight.lcpRequest) {\n const discoveryDelay = lcpInsight.lcpRequest.ts - lcpInsight.earliestDiscoveryTimeTs;\n data.discoveryDelay = TraceEngine.Types.Timing.MicroSeconds(discoveryDelay);\n }\n\n return data;\n}\n\nexport class LCPDiscovery extends BaseInsight {\n static readonly litTagName = LitHtml.literal`devtools-performance-lcp-discovery`;\n override insightCategory: InsightsCategories = InsightsCategories.LCP;\n override internalName: string = 'lcp-discovery';\n override userVisibleTitle: string = 'LCP request discovery';\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.shadow.adoptedStyleSheets.push(discoveryStyles);\n }\n\n #adviceIcon(didFail: boolean): LitHtml.TemplateResult {\n const icon = didFail ? 'clear' : 'check-circle';\n\n return LitHtml.html`\n <${IconButton.Icon.Icon.litTagName}\n name=${icon}\n class=${didFail ? 'metric-value-bad' : 'metric-value-good'}\n >\n `;\n }\n\n #renderDiscoveryDelay(delay: TraceEngine.Types.Timing.MicroSeconds): Element {\n const timeWrapper = document.createElement('span');\n timeWrapper.classList.add('discovery-time-ms');\n timeWrapper.innerText = i18n.TimeUtilities.formatMicroSecondsTime(delay);\n return i18n.i18n.getFormatLocalizedString(str_, UIStrings.lcpLoadDelay, {PH1: timeWrapper});\n }\n\n override createOverlays(): Overlays.Overlays.TimelineOverlay[] {\n const imageResults = getImageData(this.data.insights, this.data.navigationId);\n if (!imageResults || !imageResults.discoveryDelay) {\n return [];\n }\n\n const delay = TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(\n TraceEngine.Types.Timing.MicroSeconds(imageResults.request.ts - imageResults.discoveryDelay),\n imageResults.request.ts,\n );\n\n const label = LitHtml.html`
    ${this.#renderDiscoveryDelay(delay.range)}
    `;\n\n return [\n {\n type: 'ENTRY_OUTLINE',\n entry: imageResults.request,\n outlineReason: 'ERROR',\n },\n {\n type: 'CANDY_STRIPED_TIME_RANGE',\n bounds: delay,\n entry: imageResults.request,\n },\n {\n type: 'TIMESPAN_BREAKDOWN',\n sections: [{\n bounds: delay,\n label,\n showDuration: false,\n }],\n entry: imageResults.request,\n },\n ];\n }\n\n #renderDiscovery(imageData: LCPImageDiscoveryData): LitHtml.TemplateResult {\n // clang-format off\n return LitHtml.html`\n
    \n <${SidebarInsight.SidebarInsight.litTagName} .data=${{\n title: this.userVisibleTitle,\n expanded: this.isActive(),\n } as SidebarInsight.InsightDetails}\n @insighttoggleclick=${this.onSidebarClick}\n >\n
    \n ${imageData.discoveryDelay ? LitHtml.html`
    ${this.#renderDiscoveryDelay(imageData.discoveryDelay)}
    ` : LitHtml.nothing}\n
      \n
    • \n ${this.#adviceIcon(imageData.shouldIncreasePriorityHint)}\n ${i18nString(UIStrings.fetchPriorityApplied)}\n
    • \n
    • \n ${this.#adviceIcon(imageData.shouldPreloadImage)}\n ${i18nString(UIStrings.requestDiscoverable)}\n
    • \n
    • \n ${this.#adviceIcon(imageData.shouldRemoveLazyLoading)}\n ${i18nString(UIStrings.lazyLoadNotApplied)}\n
    • \n
    \n
    \n
    \n \n
    \n ${Common.ParsedURL.ParsedURL.extractName(imageData.request.args.data.url ?? '')}\n
    ${Platform.NumberUtilities.bytesToString(imageData.request.args.data.decodedBodyLength ?? 0)}
    \n
    \n
    \n \n
    `;\n // clang-format on\n }\n\n override render(): void {\n const imageResults = getImageData(this.data.insights, this.data.navigationId);\n const matchesCategory = shouldRenderForCategory({\n activeCategory: this.data.activeCategory,\n insightCategory: this.insightCategory,\n });\n const output = imageResults && matchesCategory ? this.#renderDiscovery(imageResults) : LitHtml.nothing;\n LitHtml.render(output, this.shadow, {host: this});\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-lcp-discovery': LCPDiscovery;\n }\n}\n\ncustomElements.define('devtools-performance-lcp-discovery', LCPDiscovery);\n"]} \ No newline at end of file +{"version":3,"file":"LCPDiscovery.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/LCPDiscovery.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../../../core/common/common.js';\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport * as Platform from '../../../../core/platform/platform.js';\nimport * as Trace from '../../../../models/trace/trace.js';\nimport * as IconButton from '../../../../ui/components/icon_button/icon_button.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\nimport type * as Overlays from '../../overlays/overlays.js';\n\nimport {BaseInsight, shouldRenderForCategory} from './Helpers.js';\nimport discoveryStyles from './lcpDiscovery.css.js';\nimport * as SidebarInsight from './SidebarInsight.js';\nimport {InsightsCategories} from './types.js';\n\nconst UIStrings = {\n /**\n * @description Text to tell the user how long after the earliest discovery time their LCP element loaded.\n * @example {401ms} PH1\n */\n lcpLoadDelay: 'LCP image loaded {PH1} after earliest start point.',\n /**\n * @description Text to tell the user that a fetchpriority property value of \"high\" is applied to the LCP request.\n */\n fetchPriorityApplied: 'fetchpriority=high applied',\n /**\n * @description Text to tell the user that the LCP request is discoverable in the initial document.\n */\n requestDiscoverable: 'Request is discoverable in initial document',\n /**\n * @description Text to tell the user that the LCP request does not have the lazy load property applied.\n */\n lazyLoadNotApplied: 'lazy load not applied',\n\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/components/insights/LCPDiscovery.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\ninterface LCPImageDiscoveryData {\n shouldIncreasePriorityHint: boolean;\n shouldPreloadImage: boolean;\n shouldRemoveLazyLoading: boolean;\n request: Trace.Types.Events.SyntheticNetworkRequest;\n discoveryDelay: Trace.Types.Timing.MicroSeconds|null;\n}\n\nexport function getLCPInsightData(insights: Trace.Insights.Types.TraceInsightSets|null, navigationId: string|null):\n Trace.Insights.Types.InsightResults['LargestContentfulPaint']|null {\n if (!insights || !navigationId) {\n return null;\n }\n\n const insightsByNavigation = insights.get(navigationId);\n if (!insightsByNavigation) {\n return null;\n }\n\n const lcpInsight = insightsByNavigation.data.LargestContentfulPaint;\n if (lcpInsight instanceof Error) {\n return null;\n }\n return lcpInsight;\n}\n\nfunction getImageData(\n insights: Trace.Insights.Types.TraceInsightSets|null, navigationId: string|null): LCPImageDiscoveryData|null {\n const lcpInsight = getLCPInsightData(insights, navigationId);\n if (!lcpInsight) {\n return null;\n }\n\n if (lcpInsight.lcpRequest === undefined) {\n return null;\n }\n\n const shouldIncreasePriorityHint = lcpInsight.shouldIncreasePriorityHint;\n const shouldPreloadImage = lcpInsight.shouldPreloadImage;\n const shouldRemoveLazyLoading = lcpInsight.shouldRemoveLazyLoading;\n\n const imageLCP = shouldIncreasePriorityHint !== undefined && shouldPreloadImage !== undefined &&\n shouldRemoveLazyLoading !== undefined;\n\n // Shouldn't render anything if lcp insight is null or lcp is text.\n if (!imageLCP) {\n return null;\n }\n\n const data: LCPImageDiscoveryData = {\n shouldIncreasePriorityHint,\n shouldPreloadImage,\n shouldRemoveLazyLoading,\n request: lcpInsight.lcpRequest,\n discoveryDelay: null,\n };\n\n if (lcpInsight.earliestDiscoveryTimeTs && lcpInsight.lcpRequest) {\n const discoveryDelay = lcpInsight.lcpRequest.ts - lcpInsight.earliestDiscoveryTimeTs;\n data.discoveryDelay = Trace.Types.Timing.MicroSeconds(discoveryDelay);\n }\n\n return data;\n}\n\nexport class LCPDiscovery extends BaseInsight {\n static readonly litTagName = LitHtml.literal`devtools-performance-lcp-discovery`;\n override insightCategory: InsightsCategories = InsightsCategories.LCP;\n override internalName: string = 'lcp-discovery';\n override userVisibleTitle: string = 'LCP request discovery';\n\n override connectedCallback(): void {\n super.connectedCallback();\n this.shadow.adoptedStyleSheets.push(discoveryStyles);\n }\n\n #adviceIcon(didFail: boolean): LitHtml.TemplateResult {\n const icon = didFail ? 'clear' : 'check-circle';\n\n return LitHtml.html`\n <${IconButton.Icon.Icon.litTagName}\n name=${icon}\n class=${didFail ? 'metric-value-bad' : 'metric-value-good'}\n >\n `;\n }\n\n #renderDiscoveryDelay(delay: Trace.Types.Timing.MicroSeconds): Element {\n const timeWrapper = document.createElement('span');\n timeWrapper.classList.add('discovery-time-ms');\n timeWrapper.innerText = i18n.TimeUtilities.formatMicroSecondsTime(delay);\n return i18n.i18n.getFormatLocalizedString(str_, UIStrings.lcpLoadDelay, {PH1: timeWrapper});\n }\n\n override createOverlays(): Overlays.Overlays.TimelineOverlay[] {\n const imageResults = getImageData(this.data.insights, this.data.navigationId);\n if (!imageResults || !imageResults.discoveryDelay) {\n return [];\n }\n\n const delay = Trace.Helpers.Timing.traceWindowFromMicroSeconds(\n Trace.Types.Timing.MicroSeconds(imageResults.request.ts - imageResults.discoveryDelay),\n imageResults.request.ts,\n );\n\n const label = LitHtml.html`
    ${this.#renderDiscoveryDelay(delay.range)}
    `;\n\n return [\n {\n type: 'ENTRY_OUTLINE',\n entry: imageResults.request,\n outlineReason: 'ERROR',\n },\n {\n type: 'CANDY_STRIPED_TIME_RANGE',\n bounds: delay,\n entry: imageResults.request,\n },\n {\n type: 'TIMESPAN_BREAKDOWN',\n sections: [{\n bounds: delay,\n label,\n showDuration: false,\n }],\n entry: imageResults.request,\n },\n ];\n }\n\n #renderDiscovery(imageData: LCPImageDiscoveryData): LitHtml.TemplateResult {\n // clang-format off\n return LitHtml.html`\n
    \n <${SidebarInsight.SidebarInsight.litTagName} .data=${{\n title: this.userVisibleTitle,\n expanded: this.isActive(),\n } as SidebarInsight.InsightDetails}\n @insighttoggleclick=${this.onSidebarClick}\n >\n
    \n ${imageData.discoveryDelay ? LitHtml.html`
    ${this.#renderDiscoveryDelay(imageData.discoveryDelay)}
    ` : LitHtml.nothing}\n
      \n
    • \n ${this.#adviceIcon(imageData.shouldIncreasePriorityHint)}\n ${i18nString(UIStrings.fetchPriorityApplied)}\n
    • \n
    • \n ${this.#adviceIcon(imageData.shouldPreloadImage)}\n ${i18nString(UIStrings.requestDiscoverable)}\n
    • \n
    • \n ${this.#adviceIcon(imageData.shouldRemoveLazyLoading)}\n ${i18nString(UIStrings.lazyLoadNotApplied)}\n
    • \n
    \n
    \n
    \n \n
    \n ${Common.ParsedURL.ParsedURL.extractName(imageData.request.args.data.url ?? '')}\n
    ${Platform.NumberUtilities.bytesToString(imageData.request.args.data.decodedBodyLength ?? 0)}
    \n
    \n
    \n \n
    `;\n // clang-format on\n }\n\n override render(): void {\n const imageResults = getImageData(this.data.insights, this.data.navigationId);\n const matchesCategory = shouldRenderForCategory({\n activeCategory: this.data.activeCategory,\n insightCategory: this.insightCategory,\n });\n const output = imageResults && matchesCategory ? this.#renderDiscovery(imageResults) : LitHtml.nothing;\n LitHtml.render(output, this.shadow, {host: this});\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-lcp-discovery': LCPDiscovery;\n }\n}\n\ncustomElements.define('devtools-performance-lcp-discovery', LCPDiscovery);\n"]} \ No newline at end of file diff --git a/public/panels/timeline/components/insights/LCPPhases.js b/public/panels/timeline/components/insights/LCPPhases.js index 84556bda2..89df81d71 100644 --- a/public/panels/timeline/components/insights/LCPPhases.js +++ b/public/panels/timeline/components/insights/LCPPhases.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as i18n from '../../../../core/i18n/i18n.js'; -import * as TraceEngine from '../../../../models/trace/trace.js'; +import * as Trace from '../../../../models/trace/trace.js'; import * as LitHtml from '../../../../ui/lit-html/lit-html.js'; import { BaseInsight, shouldRenderForCategory } from './Helpers.js'; import * as SidebarInsight from './SidebarInsight.js'; @@ -41,7 +41,7 @@ export class LCPPhases extends BaseInsight { if (!insightsByNavigation) { return []; } - const lcpInsight = insightsByNavigation.LargestContentfulPaint; + const lcpInsight = insightsByNavigation.data.LargestContentfulPaint; if (lcpInsight instanceof Error) { return []; } @@ -92,7 +92,7 @@ export class LCPPhases extends BaseInsight { if (!insightsByNavigation) { return []; } - const lcpInsight = insightsByNavigation.LargestContentfulPaint; + const lcpInsight = insightsByNavigation.data.LargestContentfulPaint; if (lcpInsight instanceof Error) { return []; } @@ -101,25 +101,25 @@ export class LCPPhases extends BaseInsight { if (!phases || !lcpTs) { return []; } - const lcpMicroseconds = TraceEngine.Types.Timing.MicroSeconds(TraceEngine.Helpers.Timing.millisecondsToMicroseconds(lcpTs)); + const lcpMicroseconds = Trace.Types.Timing.MicroSeconds(Trace.Helpers.Timing.millisecondsToMicroseconds(lcpTs)); const sections = []; // For text LCP, we should only have ttfb and renderDelay sections. if (!phases?.loadDelay && !phases?.loadTime) { - const renderBegin = TraceEngine.Types.Timing.MicroSeconds(lcpMicroseconds - TraceEngine.Helpers.Timing.millisecondsToMicroseconds(phases.renderDelay)); - const renderDelay = TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(renderBegin, lcpMicroseconds); - const mainReqStart = TraceEngine.Types.Timing.MicroSeconds(renderBegin - TraceEngine.Helpers.Timing.millisecondsToMicroseconds(phases.ttfb)); - const ttfb = TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(mainReqStart, renderBegin); + const renderBegin = Trace.Types.Timing.MicroSeconds(lcpMicroseconds - Trace.Helpers.Timing.millisecondsToMicroseconds(phases.renderDelay)); + const renderDelay = Trace.Helpers.Timing.traceWindowFromMicroSeconds(renderBegin, lcpMicroseconds); + const mainReqStart = Trace.Types.Timing.MicroSeconds(renderBegin - Trace.Helpers.Timing.millisecondsToMicroseconds(phases.ttfb)); + const ttfb = Trace.Helpers.Timing.traceWindowFromMicroSeconds(mainReqStart, renderBegin); sections.push({ bounds: ttfb, label: i18nString(UIStrings.timeToFirstByte), showDuration: true }, { bounds: renderDelay, label: i18nString(UIStrings.elementRenderDelay), showDuration: true }); } else if (phases?.loadDelay && phases?.loadTime) { - const renderBegin = TraceEngine.Types.Timing.MicroSeconds(lcpMicroseconds - TraceEngine.Helpers.Timing.millisecondsToMicroseconds(phases.renderDelay)); - const renderDelay = TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(renderBegin, lcpMicroseconds); - const loadBegin = TraceEngine.Types.Timing.MicroSeconds(renderBegin - TraceEngine.Helpers.Timing.millisecondsToMicroseconds(phases.loadTime)); - const loadTime = TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(loadBegin, renderBegin); - const loadDelayStart = TraceEngine.Types.Timing.MicroSeconds(loadBegin - TraceEngine.Helpers.Timing.millisecondsToMicroseconds(phases.loadDelay)); - const loadDelay = TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(loadDelayStart, loadBegin); - const mainReqStart = TraceEngine.Types.Timing.MicroSeconds(loadDelayStart - TraceEngine.Helpers.Timing.millisecondsToMicroseconds(phases.ttfb)); - const ttfb = TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(mainReqStart, loadDelayStart); + const renderBegin = Trace.Types.Timing.MicroSeconds(lcpMicroseconds - Trace.Helpers.Timing.millisecondsToMicroseconds(phases.renderDelay)); + const renderDelay = Trace.Helpers.Timing.traceWindowFromMicroSeconds(renderBegin, lcpMicroseconds); + const loadBegin = Trace.Types.Timing.MicroSeconds(renderBegin - Trace.Helpers.Timing.millisecondsToMicroseconds(phases.loadTime)); + const loadTime = Trace.Helpers.Timing.traceWindowFromMicroSeconds(loadBegin, renderBegin); + const loadDelayStart = Trace.Types.Timing.MicroSeconds(loadBegin - Trace.Helpers.Timing.millisecondsToMicroseconds(phases.loadDelay)); + const loadDelay = Trace.Helpers.Timing.traceWindowFromMicroSeconds(loadDelayStart, loadBegin); + const mainReqStart = Trace.Types.Timing.MicroSeconds(loadDelayStart - Trace.Helpers.Timing.millisecondsToMicroseconds(phases.ttfb)); + const ttfb = Trace.Helpers.Timing.traceWindowFromMicroSeconds(mainReqStart, loadDelayStart); sections.push({ bounds: ttfb, label: i18nString(UIStrings.timeToFirstByte), showDuration: true }, { bounds: loadDelay, label: i18nString(UIStrings.resourceLoadDelay), showDuration: true }, { bounds: loadTime, label: i18nString(UIStrings.resourceLoadDuration), showDuration: true }, { bounds: renderDelay, label: i18nString(UIStrings.elementRenderDelay), showDuration: true }); } return [{ @@ -139,9 +139,11 @@ export class LCPPhases extends BaseInsight { @insighttoggleclick=${this.onSidebarClick} >
    - Each - phase has specific recommendations to improve. - In an ideal load, the two delay phases should be quite short. +

    + Each + phase has specific recommendations to improve. + In an ideal load, the two delay phases should be quite short. +

    ${LitHtml.html `<${Table.litTagName} diff --git a/public/panels/timeline/components/insights/LCPPhases.js.map b/public/panels/timeline/components/insights/LCPPhases.js.map index bc907946a..503cded6e 100644 --- a/public/panels/timeline/components/insights/LCPPhases.js.map +++ b/public/panels/timeline/components/insights/LCPPhases.js.map @@ -1 +1 @@ -{"version":3,"file":"LCPPhases.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/LCPPhases.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport * as TraceEngine from '../../../../models/trace/trace.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\nimport type * as Overlays from '../../overlays/overlays.js';\n\nimport {BaseInsight, shouldRenderForCategory} from './Helpers.js';\nimport * as SidebarInsight from './SidebarInsight.js';\nimport {Table, type TableData} from './Table.js';\nimport {InsightsCategories} from './types.js';\n\nconst UIStrings = {\n /**\n *@description Time to first byte title for the Largest Contentful Paint's phases timespan breakdown.\n */\n timeToFirstByte: 'Time to first byte',\n /**\n *@description Resource load delay title for the Largest Contentful Paint phases timespan breakdown.\n */\n resourceLoadDelay: 'Resource load delay',\n /**\n *@description Resource load duration title for the Largest Contentful Paint phases timespan breakdown.\n */\n resourceLoadDuration: 'Resource load duration',\n /**\n *@description Element render delay title for the Largest Contentful Paint phases timespan breakdown.\n */\n elementRenderDelay: 'Element render delay',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/components/insights/LCPPhases.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\ninterface PhaseData {\n phase: string;\n timing: number|TraceEngine.Types.Timing.MilliSeconds;\n percent: string;\n}\n\nexport class LCPPhases extends BaseInsight {\n static readonly litTagName = LitHtml.literal`devtools-performance-lcp-by-phases`;\n override insightCategory: InsightsCategories = InsightsCategories.LCP;\n override internalName: string = 'lcp-by-phase';\n override userVisibleTitle: string = 'LCP by phase';\n\n #getPhaseData(insights: TraceEngine.Insights.Types.TraceInsightData|null, navigationId: string|null): PhaseData[] {\n if (!insights || !navigationId) {\n return [];\n }\n const insightsByNavigation = insights.get(navigationId);\n if (!insightsByNavigation) {\n return [];\n }\n const lcpInsight = insightsByNavigation.LargestContentfulPaint;\n if (lcpInsight instanceof Error) {\n return [];\n }\n\n const timing = lcpInsight.lcpMs;\n const phases = lcpInsight.phases;\n\n if (!timing || !phases) {\n return [];\n }\n\n const {ttfb, loadDelay, loadTime, renderDelay} = phases;\n\n if (loadDelay && loadTime) {\n const phaseData = [\n {phase: i18nString(UIStrings.timeToFirstByte), timing: ttfb, percent: `${(100 * ttfb / timing).toFixed(0)}%`},\n {\n phase: i18nString(UIStrings.resourceLoadDelay),\n timing: loadDelay,\n percent: `${(100 * loadDelay / timing).toFixed(0)}%`,\n },\n {\n phase: i18nString(UIStrings.resourceLoadDuration),\n timing: loadTime,\n percent: `${(100 * loadTime / timing).toFixed(0)}%`,\n },\n {\n phase: i18nString(UIStrings.elementRenderDelay),\n timing: renderDelay,\n percent: `${(100 * renderDelay / timing).toFixed(0)}%`,\n },\n ];\n return phaseData;\n }\n\n // If the lcp is text, we only have ttfb and render delay.\n const phaseData = [\n {phase: i18nString(UIStrings.timeToFirstByte), timing: ttfb, percent: `${(100 * ttfb / timing).toFixed(0)}%`},\n {\n phase: i18nString(UIStrings.elementRenderDelay),\n timing: renderDelay,\n percent: `${(100 * renderDelay / timing).toFixed(0)}%`,\n },\n ];\n return phaseData;\n }\n\n override createOverlays(): Overlays.Overlays.TimelineOverlay[] {\n if (!this.data.insights || !this.data.navigationId) {\n return [];\n }\n const {navigationId, insights} = this.data;\n\n const insightsByNavigation = insights.get(navigationId);\n if (!insightsByNavigation) {\n return [];\n }\n\n const lcpInsight = insightsByNavigation.LargestContentfulPaint;\n if (lcpInsight instanceof Error) {\n return [];\n }\n\n const phases = lcpInsight.phases;\n const lcpTs = lcpInsight.lcpTs;\n if (!phases || !lcpTs) {\n return [];\n }\n const lcpMicroseconds =\n TraceEngine.Types.Timing.MicroSeconds(TraceEngine.Helpers.Timing.millisecondsToMicroseconds(lcpTs));\n\n const sections = [];\n // For text LCP, we should only have ttfb and renderDelay sections.\n if (!phases?.loadDelay && !phases?.loadTime) {\n const renderBegin: TraceEngine.Types.Timing.MicroSeconds = TraceEngine.Types.Timing.MicroSeconds(\n lcpMicroseconds - TraceEngine.Helpers.Timing.millisecondsToMicroseconds(phases.renderDelay));\n const renderDelay = TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(\n renderBegin,\n lcpMicroseconds,\n );\n\n const mainReqStart = TraceEngine.Types.Timing.MicroSeconds(\n renderBegin - TraceEngine.Helpers.Timing.millisecondsToMicroseconds(phases.ttfb));\n const ttfb = TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(\n mainReqStart,\n renderBegin,\n );\n sections.push(\n {bounds: ttfb, label: i18nString(UIStrings.timeToFirstByte), showDuration: true},\n {bounds: renderDelay, label: i18nString(UIStrings.elementRenderDelay), showDuration: true});\n } else if (phases?.loadDelay && phases?.loadTime) {\n const renderBegin: TraceEngine.Types.Timing.MicroSeconds = TraceEngine.Types.Timing.MicroSeconds(\n lcpMicroseconds - TraceEngine.Helpers.Timing.millisecondsToMicroseconds(phases.renderDelay));\n const renderDelay = TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(\n renderBegin,\n lcpMicroseconds,\n );\n\n const loadBegin = TraceEngine.Types.Timing.MicroSeconds(\n renderBegin - TraceEngine.Helpers.Timing.millisecondsToMicroseconds(phases.loadTime));\n const loadTime = TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(\n loadBegin,\n renderBegin,\n );\n\n const loadDelayStart = TraceEngine.Types.Timing.MicroSeconds(\n loadBegin - TraceEngine.Helpers.Timing.millisecondsToMicroseconds(phases.loadDelay));\n const loadDelay = TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(\n loadDelayStart,\n loadBegin,\n );\n\n const mainReqStart = TraceEngine.Types.Timing.MicroSeconds(\n loadDelayStart - TraceEngine.Helpers.Timing.millisecondsToMicroseconds(phases.ttfb));\n const ttfb = TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(\n mainReqStart,\n loadDelayStart,\n );\n\n sections.push(\n {bounds: ttfb, label: i18nString(UIStrings.timeToFirstByte), showDuration: true},\n {bounds: loadDelay, label: i18nString(UIStrings.resourceLoadDelay), showDuration: true},\n {bounds: loadTime, label: i18nString(UIStrings.resourceLoadDuration), showDuration: true},\n {bounds: renderDelay, label: i18nString(UIStrings.elementRenderDelay), showDuration: true},\n );\n }\n return [{\n type: 'TIMESPAN_BREAKDOWN',\n sections,\n }];\n }\n\n #renderLCPPhases(phaseData: PhaseData[]): LitHtml.LitTemplate {\n const rows = phaseData.map(({phase, percent}) => [phase, percent]);\n\n // clang-format off\n return LitHtml.html`\n
    \n <${SidebarInsight.SidebarInsight.litTagName} .data=${{\n title: this.userVisibleTitle,\n expanded: this.isActive(),\n } as SidebarInsight.InsightDetails}\n @insighttoggleclick=${this.onSidebarClick}\n >\n
    \n Each\n phase has specific recommendations to improve.\n In an ideal load, the two delay phases should be quite short.\n
    \n
    \n ${LitHtml.html`<${Table.litTagName}\n .data=${{\n headers: ['Phase', '% of LCP'],\n rows,\n } as TableData}>\n `}\n
    \n \n
    `;\n // clang-format on\n }\n\n #hasDataToRender(phaseData: PhaseData[]): boolean {\n return phaseData ? phaseData.length > 0 : false;\n }\n\n override render(): void {\n const phaseData = this.#getPhaseData(this.data.insights, this.data.navigationId);\n const matchesCategory = shouldRenderForCategory({\n activeCategory: this.data.activeCategory,\n insightCategory: this.insightCategory,\n });\n const shouldRender = matchesCategory && this.#hasDataToRender(phaseData);\n const output = shouldRender ? this.#renderLCPPhases(phaseData) : LitHtml.nothing;\n LitHtml.render(output, this.shadow, {host: this});\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-lcp-by-phases': LCPPhases;\n }\n}\n\ncustomElements.define('devtools-performance-lcp-by-phases', LCPPhases);\n"]} \ No newline at end of file +{"version":3,"file":"LCPPhases.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/LCPPhases.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport * as Trace from '../../../../models/trace/trace.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\nimport type * as Overlays from '../../overlays/overlays.js';\n\nimport {BaseInsight, shouldRenderForCategory} from './Helpers.js';\nimport * as SidebarInsight from './SidebarInsight.js';\nimport {Table, type TableData} from './Table.js';\nimport {InsightsCategories} from './types.js';\n\nconst UIStrings = {\n /**\n *@description Time to first byte title for the Largest Contentful Paint's phases timespan breakdown.\n */\n timeToFirstByte: 'Time to first byte',\n /**\n *@description Resource load delay title for the Largest Contentful Paint phases timespan breakdown.\n */\n resourceLoadDelay: 'Resource load delay',\n /**\n *@description Resource load duration title for the Largest Contentful Paint phases timespan breakdown.\n */\n resourceLoadDuration: 'Resource load duration',\n /**\n *@description Element render delay title for the Largest Contentful Paint phases timespan breakdown.\n */\n elementRenderDelay: 'Element render delay',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/components/insights/LCPPhases.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\ninterface PhaseData {\n phase: string;\n timing: number|Trace.Types.Timing.MilliSeconds;\n percent: string;\n}\n\nexport class LCPPhases extends BaseInsight {\n static readonly litTagName = LitHtml.literal`devtools-performance-lcp-by-phases`;\n override insightCategory: InsightsCategories = InsightsCategories.LCP;\n override internalName: string = 'lcp-by-phase';\n override userVisibleTitle: string = 'LCP by phase';\n\n #getPhaseData(insights: Trace.Insights.Types.TraceInsightSets|null, navigationId: string|null): PhaseData[] {\n if (!insights || !navigationId) {\n return [];\n }\n const insightsByNavigation = insights.get(navigationId);\n if (!insightsByNavigation) {\n return [];\n }\n const lcpInsight = insightsByNavigation.data.LargestContentfulPaint;\n if (lcpInsight instanceof Error) {\n return [];\n }\n\n const timing = lcpInsight.lcpMs;\n const phases = lcpInsight.phases;\n\n if (!timing || !phases) {\n return [];\n }\n\n const {ttfb, loadDelay, loadTime, renderDelay} = phases;\n\n if (loadDelay && loadTime) {\n const phaseData = [\n {phase: i18nString(UIStrings.timeToFirstByte), timing: ttfb, percent: `${(100 * ttfb / timing).toFixed(0)}%`},\n {\n phase: i18nString(UIStrings.resourceLoadDelay),\n timing: loadDelay,\n percent: `${(100 * loadDelay / timing).toFixed(0)}%`,\n },\n {\n phase: i18nString(UIStrings.resourceLoadDuration),\n timing: loadTime,\n percent: `${(100 * loadTime / timing).toFixed(0)}%`,\n },\n {\n phase: i18nString(UIStrings.elementRenderDelay),\n timing: renderDelay,\n percent: `${(100 * renderDelay / timing).toFixed(0)}%`,\n },\n ];\n return phaseData;\n }\n\n // If the lcp is text, we only have ttfb and render delay.\n const phaseData = [\n {phase: i18nString(UIStrings.timeToFirstByte), timing: ttfb, percent: `${(100 * ttfb / timing).toFixed(0)}%`},\n {\n phase: i18nString(UIStrings.elementRenderDelay),\n timing: renderDelay,\n percent: `${(100 * renderDelay / timing).toFixed(0)}%`,\n },\n ];\n return phaseData;\n }\n\n override createOverlays(): Overlays.Overlays.TimelineOverlay[] {\n if (!this.data.insights || !this.data.navigationId) {\n return [];\n }\n const {navigationId, insights} = this.data;\n\n const insightsByNavigation = insights.get(navigationId);\n if (!insightsByNavigation) {\n return [];\n }\n\n const lcpInsight = insightsByNavigation.data.LargestContentfulPaint;\n if (lcpInsight instanceof Error) {\n return [];\n }\n\n const phases = lcpInsight.phases;\n const lcpTs = lcpInsight.lcpTs;\n if (!phases || !lcpTs) {\n return [];\n }\n const lcpMicroseconds = Trace.Types.Timing.MicroSeconds(Trace.Helpers.Timing.millisecondsToMicroseconds(lcpTs));\n\n const sections = [];\n // For text LCP, we should only have ttfb and renderDelay sections.\n if (!phases?.loadDelay && !phases?.loadTime) {\n const renderBegin: Trace.Types.Timing.MicroSeconds = Trace.Types.Timing.MicroSeconds(\n lcpMicroseconds - Trace.Helpers.Timing.millisecondsToMicroseconds(phases.renderDelay));\n const renderDelay = Trace.Helpers.Timing.traceWindowFromMicroSeconds(\n renderBegin,\n lcpMicroseconds,\n );\n\n const mainReqStart =\n Trace.Types.Timing.MicroSeconds(renderBegin - Trace.Helpers.Timing.millisecondsToMicroseconds(phases.ttfb));\n const ttfb = Trace.Helpers.Timing.traceWindowFromMicroSeconds(\n mainReqStart,\n renderBegin,\n );\n sections.push(\n {bounds: ttfb, label: i18nString(UIStrings.timeToFirstByte), showDuration: true},\n {bounds: renderDelay, label: i18nString(UIStrings.elementRenderDelay), showDuration: true});\n } else if (phases?.loadDelay && phases?.loadTime) {\n const renderBegin: Trace.Types.Timing.MicroSeconds = Trace.Types.Timing.MicroSeconds(\n lcpMicroseconds - Trace.Helpers.Timing.millisecondsToMicroseconds(phases.renderDelay));\n const renderDelay = Trace.Helpers.Timing.traceWindowFromMicroSeconds(\n renderBegin,\n lcpMicroseconds,\n );\n\n const loadBegin = Trace.Types.Timing.MicroSeconds(\n renderBegin - Trace.Helpers.Timing.millisecondsToMicroseconds(phases.loadTime));\n const loadTime = Trace.Helpers.Timing.traceWindowFromMicroSeconds(\n loadBegin,\n renderBegin,\n );\n\n const loadDelayStart = Trace.Types.Timing.MicroSeconds(\n loadBegin - Trace.Helpers.Timing.millisecondsToMicroseconds(phases.loadDelay));\n const loadDelay = Trace.Helpers.Timing.traceWindowFromMicroSeconds(\n loadDelayStart,\n loadBegin,\n );\n\n const mainReqStart = Trace.Types.Timing.MicroSeconds(\n loadDelayStart - Trace.Helpers.Timing.millisecondsToMicroseconds(phases.ttfb));\n const ttfb = Trace.Helpers.Timing.traceWindowFromMicroSeconds(\n mainReqStart,\n loadDelayStart,\n );\n\n sections.push(\n {bounds: ttfb, label: i18nString(UIStrings.timeToFirstByte), showDuration: true},\n {bounds: loadDelay, label: i18nString(UIStrings.resourceLoadDelay), showDuration: true},\n {bounds: loadTime, label: i18nString(UIStrings.resourceLoadDuration), showDuration: true},\n {bounds: renderDelay, label: i18nString(UIStrings.elementRenderDelay), showDuration: true},\n );\n }\n return [{\n type: 'TIMESPAN_BREAKDOWN',\n sections,\n }];\n }\n\n #renderLCPPhases(phaseData: PhaseData[]): LitHtml.LitTemplate {\n const rows = phaseData.map(({phase, percent}) => [phase, percent]);\n\n // clang-format off\n return LitHtml.html`\n
    \n <${SidebarInsight.SidebarInsight.litTagName} .data=${{\n title: this.userVisibleTitle,\n expanded: this.isActive(),\n } as SidebarInsight.InsightDetails}\n @insighttoggleclick=${this.onSidebarClick}\n >\n
    \n

    \n Each\n phase has specific recommendations to improve.\n In an ideal load, the two delay phases should be quite short.\n

    \n
    \n
    \n ${LitHtml.html`<${Table.litTagName}\n .data=${{\n headers: ['Phase', '% of LCP'],\n rows,\n } as TableData}>\n `}\n
    \n \n
    `;\n // clang-format on\n }\n\n #hasDataToRender(phaseData: PhaseData[]): boolean {\n return phaseData ? phaseData.length > 0 : false;\n }\n\n override render(): void {\n const phaseData = this.#getPhaseData(this.data.insights, this.data.navigationId);\n const matchesCategory = shouldRenderForCategory({\n activeCategory: this.data.activeCategory,\n insightCategory: this.insightCategory,\n });\n const shouldRender = matchesCategory && this.#hasDataToRender(phaseData);\n const output = shouldRender ? this.#renderLCPPhases(phaseData) : LitHtml.nothing;\n LitHtml.render(output, this.shadow, {host: this});\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-lcp-by-phases': LCPPhases;\n }\n}\n\ncustomElements.define('devtools-performance-lcp-by-phases', LCPPhases);\n"]} \ No newline at end of file diff --git a/public/panels/timeline/components/insights/NodeLink.js b/public/panels/timeline/components/insights/NodeLink.js index 6fcfb7a2d..350db8bf0 100644 --- a/public/panels/timeline/components/insights/NodeLink.js +++ b/public/panels/timeline/components/insights/NodeLink.js @@ -18,8 +18,8 @@ export class NodeLink extends HTMLElement { void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender); } async #linkify() { - // TODO: consider using `TraceEngine.Extras.FetchNodes.extractRelatedDOMNodesFromEvent`, which - // requires traceParsedData. + // TODO: consider using `Trace.Extras.FetchNodes.extractRelatedDOMNodesFromEvent`, which + // requires parsedTrace. if (this.#backendNodeId === undefined) { return; } diff --git a/public/panels/timeline/components/insights/NodeLink.js.map b/public/panels/timeline/components/insights/NodeLink.js.map index f88798f01..8935d9018 100644 --- a/public/panels/timeline/components/insights/NodeLink.js.map +++ b/public/panels/timeline/components/insights/NodeLink.js.map @@ -1 +1 @@ -{"version":3,"file":"NodeLink.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/NodeLink.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,yCAAyC;AAEzC,OAAO,KAAK,MAAM,MAAM,mCAAmC,CAAC;AAC5D,OAAO,KAAK,GAAG,MAAM,6BAA6B,CAAC;AAEnD,OAAO,KAAK,gBAAgB,MAAM,8CAA8C,CAAC;AACjF,OAAO,KAAK,OAAO,MAAM,qCAAqC,CAAC;AAO/D,MAAM,OAAO,QAAS,SAAQ,WAAW;IACvC,MAAM,CAAU,UAAU,GAAG,OAAO,CAAC,OAAO,CAAA,gCAAgC,CAAC;IAEpE,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,EAAC,IAAI,EAAE,MAAM,EAAC,CAAC,CAAC;IAC5C,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChD,cAAc,CAA8B;IAC5C,QAAQ,CAA4B;IAEpC,IAAI,IAAI,CAAC,IAAkB;QACzB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC;QACzC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC;QAC7B,KAAK,gBAAgB,CAAC,eAAe,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IAChF,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,8FAA8F;QAC9F,4BAA4B;QAE5B,IAAI,IAAI,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;YACtC,OAAO;QACT,CAAC;QAED,MAAM,UAAU,GAAG,GAAG,CAAC,aAAa,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,iBAAiB,EAAE,CAAC;QAClF,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACzD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO;QACT,CAAC;QAED,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;QACtD,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,+BAA+B,CAAC,cAAc,CAAC,CAAC;QACnF,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QAED,oEAAoE;QACpE,6EAA6E;QAC7E,OAAO,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACjE,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC5C,OAAO,CAAC,MAAM,CACV,OAAO,CAAC,IAAI,CAAA;UACV,aAAa;aACV,EACL,IAAI,CAAC,OAAO,EAAE,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC,CAAC;IAClC,CAAC;;AASH,cAAc,CAAC,MAAM,CAAC,gCAAgC,EAAE,QAAQ,CAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// TODO: move to ui/components/node_link?\n\nimport * as Common from '../../../../core/common/common.js';\nimport * as SDK from '../../../../core/sdk/sdk.js';\nimport type * as Protocol from '../../../../generated/protocol.js';\nimport * as ComponentHelpers from '../../../../ui/components/helpers/helpers.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\n\nexport interface NodeLinkData {\n backendNodeId: Protocol.DOM.BackendNodeId;\n options?: Common.Linkifier.Options;\n}\n\nexport class NodeLink extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-performance-node-link`;\n\n readonly #shadow = this.attachShadow({mode: 'open'});\n readonly #boundRender = this.#render.bind(this);\n #backendNodeId?: Protocol.DOM.BackendNodeId;\n #options?: Common.Linkifier.Options;\n\n set data(data: NodeLinkData) {\n this.#backendNodeId = data.backendNodeId;\n this.#options = data.options;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n async #linkify(): Promise {\n // TODO: consider using `TraceEngine.Extras.FetchNodes.extractRelatedDOMNodesFromEvent`, which\n // requires traceParsedData.\n\n if (this.#backendNodeId === undefined) {\n return;\n }\n\n const mainTarget = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n if (!mainTarget) {\n return;\n }\n\n const domModel = mainTarget.model(SDK.DOMModel.DOMModel);\n if (!domModel) {\n return;\n }\n\n const backendNodeIds = new Set([this.#backendNodeId]);\n const domNodesMap = await domModel.pushNodesByBackendIdsToFrontend(backendNodeIds);\n if (!domNodesMap) {\n return;\n }\n\n const node = domNodesMap.get(this.#backendNodeId);\n if (!node) {\n return;\n }\n\n // TODO: it'd be nice if we could specify what attributes to render,\n // ex for the Viewport insight: (instead of just )\n return Common.Linkifier.Linkifier.linkify(node, this.#options);\n }\n\n async #render(): Promise {\n const relatedNodeEl = await this.#linkify();\n LitHtml.render(\n LitHtml.html``,\n this.#shadow, {host: this});\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-node-link': NodeLink;\n }\n}\n\ncustomElements.define('devtools-performance-node-link', NodeLink);\n"]} \ No newline at end of file +{"version":3,"file":"NodeLink.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/NodeLink.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,yCAAyC;AAEzC,OAAO,KAAK,MAAM,MAAM,mCAAmC,CAAC;AAC5D,OAAO,KAAK,GAAG,MAAM,6BAA6B,CAAC;AAEnD,OAAO,KAAK,gBAAgB,MAAM,8CAA8C,CAAC;AACjF,OAAO,KAAK,OAAO,MAAM,qCAAqC,CAAC;AAO/D,MAAM,OAAO,QAAS,SAAQ,WAAW;IACvC,MAAM,CAAU,UAAU,GAAG,OAAO,CAAC,OAAO,CAAA,gCAAgC,CAAC;IAEpE,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,EAAC,IAAI,EAAE,MAAM,EAAC,CAAC,CAAC;IAC5C,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChD,cAAc,CAA8B;IAC5C,QAAQ,CAA4B;IAEpC,IAAI,IAAI,CAAC,IAAkB;QACzB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC;QACzC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC;QAC7B,KAAK,gBAAgB,CAAC,eAAe,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IAChF,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,wFAAwF;QACxF,wBAAwB;QAExB,IAAI,IAAI,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;YACtC,OAAO;QACT,CAAC;QAED,MAAM,UAAU,GAAG,GAAG,CAAC,aAAa,CAAC,aAAa,CAAC,QAAQ,EAAE,CAAC,iBAAiB,EAAE,CAAC;QAClF,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACzD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO;QACT,CAAC;QAED,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;QACtD,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,+BAA+B,CAAC,cAAc,CAAC,CAAC;QACnF,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,OAAO;QACT,CAAC;QAED,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,OAAO;QACT,CAAC;QAED,oEAAoE;QACpE,6EAA6E;QAC7E,OAAO,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACjE,CAAC;IAED,KAAK,CAAC,OAAO;QACX,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC5C,OAAO,CAAC,MAAM,CACV,OAAO,CAAC,IAAI,CAAA;UACV,aAAa;aACV,EACL,IAAI,CAAC,OAAO,EAAE,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC,CAAC;IAClC,CAAC;;AASH,cAAc,CAAC,MAAM,CAAC,gCAAgC,EAAE,QAAQ,CAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n// TODO: move to ui/components/node_link?\n\nimport * as Common from '../../../../core/common/common.js';\nimport * as SDK from '../../../../core/sdk/sdk.js';\nimport type * as Protocol from '../../../../generated/protocol.js';\nimport * as ComponentHelpers from '../../../../ui/components/helpers/helpers.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\n\nexport interface NodeLinkData {\n backendNodeId: Protocol.DOM.BackendNodeId;\n options?: Common.Linkifier.Options;\n}\n\nexport class NodeLink extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-performance-node-link`;\n\n readonly #shadow = this.attachShadow({mode: 'open'});\n readonly #boundRender = this.#render.bind(this);\n #backendNodeId?: Protocol.DOM.BackendNodeId;\n #options?: Common.Linkifier.Options;\n\n set data(data: NodeLinkData) {\n this.#backendNodeId = data.backendNodeId;\n this.#options = data.options;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n async #linkify(): Promise {\n // TODO: consider using `Trace.Extras.FetchNodes.extractRelatedDOMNodesFromEvent`, which\n // requires parsedTrace.\n\n if (this.#backendNodeId === undefined) {\n return;\n }\n\n const mainTarget = SDK.TargetManager.TargetManager.instance().primaryPageTarget();\n if (!mainTarget) {\n return;\n }\n\n const domModel = mainTarget.model(SDK.DOMModel.DOMModel);\n if (!domModel) {\n return;\n }\n\n const backendNodeIds = new Set([this.#backendNodeId]);\n const domNodesMap = await domModel.pushNodesByBackendIdsToFrontend(backendNodeIds);\n if (!domNodesMap) {\n return;\n }\n\n const node = domNodesMap.get(this.#backendNodeId);\n if (!node) {\n return;\n }\n\n // TODO: it'd be nice if we could specify what attributes to render,\n // ex for the Viewport insight: (instead of just )\n return Common.Linkifier.Linkifier.linkify(node, this.#options);\n }\n\n async #render(): Promise {\n const relatedNodeEl = await this.#linkify();\n LitHtml.render(\n LitHtml.html``,\n this.#shadow, {host: this});\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-node-link': NodeLink;\n }\n}\n\ncustomElements.define('devtools-performance-node-link', NodeLink);\n"]} \ No newline at end of file diff --git a/public/panels/timeline/components/insights/RenderBlocking.d.ts b/public/panels/timeline/components/insights/RenderBlocking.d.ts index a3c6a3d7b..9bb1de2a3 100644 --- a/public/panels/timeline/components/insights/RenderBlocking.d.ts +++ b/public/panels/timeline/components/insights/RenderBlocking.d.ts @@ -1,14 +1,15 @@ -import type * as TraceEngine from '../../../../models/trace/trace.js'; +import type * as Trace from '../../../../models/trace/trace.js'; import type * as Overlays from '../../overlays/overlays.js'; import { BaseInsight } from './Helpers.js'; import { InsightsCategories } from './types.js'; -export declare function getRenderBlockingInsight(insights: TraceEngine.Insights.Types.TraceInsightData | null, navigationId: string | null): TraceEngine.Insights.Types.InsightResults['RenderBlocking'] | null; +export declare function getRenderBlockingInsight(insights: Trace.Insights.Types.TraceInsightSets | null, navigationId: string | null): Trace.Insights.Types.InsightResults['RenderBlocking'] | null; export declare class RenderBlockingRequests extends BaseInsight { #private; static readonly litTagName: import("../../../../ui/lit-html/static.js").Static; insightCategory: InsightsCategories; internalName: string; userVisibleTitle: string; + connectedCallback(): void; createOverlays(): Overlays.Overlays.TimelineOverlay[]; render(): void; } diff --git a/public/panels/timeline/components/insights/RenderBlocking.js b/public/panels/timeline/components/insights/RenderBlocking.js index f7336794c..5e18da59c 100644 --- a/public/panels/timeline/components/insights/RenderBlocking.js +++ b/public/panels/timeline/components/insights/RenderBlocking.js @@ -2,10 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as i18n from '../../../../core/i18n/i18n.js'; +import * as LegacyComponents from '../../../../ui/legacy/components/utils/utils.js'; +import * as UI from '../../../../ui/legacy/legacy.js'; import * as LitHtml from '../../../../ui/lit-html/lit-html.js'; import { BaseInsight, md, shouldRenderForCategory } from './Helpers.js'; import * as SidebarInsight from './SidebarInsight.js'; import { InsightsCategories } from './types.js'; +const MAX_URL_LENGTH = 80; const UIStrings = { /** * @description Text to describe that there are requests blocking rendering, which may affect LCP. @@ -24,7 +27,7 @@ export function getRenderBlockingInsight(insights, navigationId) { if (!insightsByNavigation) { return null; } - const insight = insightsByNavigation.RenderBlocking; + const insight = insightsByNavigation.data.RenderBlocking; if (insight instanceof Error) { return null; } @@ -35,6 +38,11 @@ export class RenderBlockingRequests extends BaseInsight { insightCategory = InsightsCategories.LCP; internalName = 'render-blocking-requests'; userVisibleTitle = 'Render-blocking requests'; + connectedCallback() { + super.connectedCallback(); + // Button style for linkified url. + UI.UIUtils.injectTextButtonStyles(this.shadow); + } createOverlays() { const renderBlockingResults = getRenderBlockingInsight(this.data.insights, this.data.navigationId); if (!renderBlockingResults) { @@ -49,8 +57,20 @@ export class RenderBlockingRequests extends BaseInsight { }); return entryOutlineOverlays; } + #linkifyUrl(url) { + const options = { + tabStop: true, + showColumnNumber: false, + inlineFrameIndex: 0, + maxLength: MAX_URL_LENGTH, + }; + const linkifiedURL = LegacyComponents.Linkifier.Linkifier.linkifyURL(url, options); + return linkifiedURL; + } #renderRenderBlocking(insightResult) { const estimatedSavings = insightResult.metricSavings?.FCP; + const MAX_REQUESTS = 3; + const topRequests = insightResult.renderBlockingRequests.slice(0, MAX_REQUESTS); // clang-format off return LitHtml.html `
    @@ -64,6 +84,18 @@ export class RenderBlockingRequests extends BaseInsight {
    ${md(i18nString(UIStrings.description))}
    +
    +

    + Longest blocking requests: +

      + ${topRequests.map(req => { + return LitHtml.html ` +
    • ${this.#linkifyUrl(req.args.data.url)}
    • + `; + })} +
    +

    +

    `; // clang-format on diff --git a/public/panels/timeline/components/insights/RenderBlocking.js.map b/public/panels/timeline/components/insights/RenderBlocking.js.map index 40530ac88..17ef23f7b 100644 --- a/public/panels/timeline/components/insights/RenderBlocking.js.map +++ b/public/panels/timeline/components/insights/RenderBlocking.js.map @@ -1 +1 @@ -{"version":3,"file":"RenderBlocking.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/RenderBlocking.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport type * as TraceEngine from '../../../../models/trace/trace.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\nimport type * as Overlays from '../../overlays/overlays.js';\n\nimport {BaseInsight, md, shouldRenderForCategory} from './Helpers.js';\nimport * as SidebarInsight from './SidebarInsight.js';\nimport {InsightsCategories} from './types.js';\n\nconst UIStrings = {\n /**\n * @description Text to describe that there are requests blocking rendering, which may affect LCP.\n */\n description: 'Requests are blocking the page\\'s initial render, which may delay LCP. ' +\n '[Deferring or inlining](https://web.dev/learn/performance/understanding-the-critical-path#render-blocking_resources/) ' +\n 'can move these network requests out of the critical path.',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/components/insights/RenderBlocking.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function getRenderBlockingInsight(\n insights: TraceEngine.Insights.Types.TraceInsightData|null,\n navigationId: string|null): TraceEngine.Insights.Types.InsightResults['RenderBlocking']|null {\n if (!insights || !navigationId) {\n return null;\n }\n\n const insightsByNavigation = insights.get(navigationId);\n if (!insightsByNavigation) {\n return null;\n }\n\n const insight = insightsByNavigation.RenderBlocking;\n if (insight instanceof Error) {\n return null;\n }\n return insight;\n}\n\nexport class RenderBlockingRequests extends BaseInsight {\n static readonly litTagName = LitHtml.literal`devtools-performance-render-blocking-requests`;\n override insightCategory: InsightsCategories = InsightsCategories.LCP;\n override internalName: string = 'render-blocking-requests';\n override userVisibleTitle: string = 'Render-blocking requests';\n\n override createOverlays(): Overlays.Overlays.TimelineOverlay[] {\n const renderBlockingResults = getRenderBlockingInsight(this.data.insights, this.data.navigationId);\n if (!renderBlockingResults) {\n return [];\n }\n\n const entryOutlineOverlays: Array =\n renderBlockingResults.renderBlockingRequests.map(req => {\n return {\n type: 'ENTRY_OUTLINE',\n entry: req,\n outlineReason: 'ERROR',\n };\n });\n return entryOutlineOverlays;\n }\n\n #renderRenderBlocking(insightResult: TraceEngine.Insights.Types.InsightResults['RenderBlocking']):\n LitHtml.TemplateResult {\n const estimatedSavings = insightResult.metricSavings?.FCP;\n // clang-format off\n return LitHtml.html`\n
    \n <${SidebarInsight.SidebarInsight.litTagName} .data=${{\n title: this.userVisibleTitle,\n expanded: this.isActive(),\n estimatedSavings,\n } as SidebarInsight.InsightDetails}\n @insighttoggleclick=${this.onSidebarClick}\n >\n
    \n ${md(i18nString(UIStrings.description))}\n
    \n \n
    `;\n // clang-format on\n }\n\n override render(): void {\n const renderBlockingResults = getRenderBlockingInsight(this.data.insights, this.data.navigationId);\n const hasBlockingRequests =\n renderBlockingResults?.renderBlockingRequests && renderBlockingResults.renderBlockingRequests.length > 0;\n const matchesCategory = shouldRenderForCategory({\n activeCategory: this.data.activeCategory,\n insightCategory: this.insightCategory,\n });\n const output =\n hasBlockingRequests && matchesCategory ? this.#renderRenderBlocking(renderBlockingResults) : LitHtml.nothing;\n LitHtml.render(output, this.shadow, {host: this});\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-render-blocking-requests': RenderBlockingRequests;\n }\n}\n\ncustomElements.define('devtools-performance-render-blocking-requests', RenderBlockingRequests);\n"]} \ No newline at end of file +{"version":3,"file":"RenderBlocking.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/RenderBlocking.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport type * as Platform from '../../../../core/platform/platform.js';\nimport type * as Trace from '../../../../models/trace/trace.js';\nimport * as LegacyComponents from '../../../../ui/legacy/components/utils/utils.js';\nimport * as UI from '../../../../ui/legacy/legacy.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\nimport type * as Overlays from '../../overlays/overlays.js';\n\nimport {BaseInsight, md, shouldRenderForCategory} from './Helpers.js';\nimport * as SidebarInsight from './SidebarInsight.js';\nimport {InsightsCategories} from './types.js';\n\nconst MAX_URL_LENGTH = 80;\n\nconst UIStrings = {\n /**\n * @description Text to describe that there are requests blocking rendering, which may affect LCP.\n */\n description: 'Requests are blocking the page\\'s initial render, which may delay LCP. ' +\n '[Deferring or inlining](https://web.dev/learn/performance/understanding-the-critical-path#render-blocking_resources/) ' +\n 'can move these network requests out of the critical path.',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/components/insights/RenderBlocking.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function getRenderBlockingInsight(\n insights: Trace.Insights.Types.TraceInsightSets|null,\n navigationId: string|null): Trace.Insights.Types.InsightResults['RenderBlocking']|null {\n if (!insights || !navigationId) {\n return null;\n }\n\n const insightsByNavigation = insights.get(navigationId);\n if (!insightsByNavigation) {\n return null;\n }\n\n const insight = insightsByNavigation.data.RenderBlocking;\n if (insight instanceof Error) {\n return null;\n }\n return insight;\n}\n\nexport class RenderBlockingRequests extends BaseInsight {\n static readonly litTagName = LitHtml.literal`devtools-performance-render-blocking-requests`;\n override insightCategory: InsightsCategories = InsightsCategories.LCP;\n override internalName: string = 'render-blocking-requests';\n override userVisibleTitle: string = 'Render-blocking requests';\n\n override connectedCallback(): void {\n super.connectedCallback();\n // Button style for linkified url.\n UI.UIUtils.injectTextButtonStyles(this.shadow);\n }\n\n override createOverlays(): Overlays.Overlays.TimelineOverlay[] {\n const renderBlockingResults = getRenderBlockingInsight(this.data.insights, this.data.navigationId);\n if (!renderBlockingResults) {\n return [];\n }\n\n const entryOutlineOverlays: Array =\n renderBlockingResults.renderBlockingRequests.map(req => {\n return {\n type: 'ENTRY_OUTLINE',\n entry: req,\n outlineReason: 'ERROR',\n };\n });\n return entryOutlineOverlays;\n }\n\n #linkifyUrl(url: string): HTMLElement {\n const options = {\n tabStop: true,\n showColumnNumber: false,\n inlineFrameIndex: 0,\n maxLength: MAX_URL_LENGTH,\n };\n\n const linkifiedURL =\n LegacyComponents.Linkifier.Linkifier.linkifyURL(url as Platform.DevToolsPath.UrlString, options);\n return linkifiedURL;\n }\n\n #renderRenderBlocking(insightResult: Trace.Insights.Types.InsightResults['RenderBlocking']): LitHtml.TemplateResult {\n const estimatedSavings = insightResult.metricSavings?.FCP;\n const MAX_REQUESTS = 3;\n const topRequests = insightResult.renderBlockingRequests.slice(0, MAX_REQUESTS);\n // clang-format off\n return LitHtml.html`\n
    \n <${SidebarInsight.SidebarInsight.litTagName} .data=${{\n title: this.userVisibleTitle,\n expanded: this.isActive(),\n estimatedSavings,\n } as SidebarInsight.InsightDetails}\n @insighttoggleclick=${this.onSidebarClick}\n >\n
    \n ${md(i18nString(UIStrings.description))}\n
    \n
    \n

    \n Longest blocking requests:\n

      \n ${topRequests.map(req => {\n return LitHtml.html `\n
    • ${this.#linkifyUrl(req.args.data.url)}
    • \n `;\n })}\n
    \n

    \n

    \n \n
    `;\n // clang-format on\n }\n\n override render(): void {\n const renderBlockingResults = getRenderBlockingInsight(this.data.insights, this.data.navigationId);\n const hasBlockingRequests =\n renderBlockingResults?.renderBlockingRequests && renderBlockingResults.renderBlockingRequests.length > 0;\n const matchesCategory = shouldRenderForCategory({\n activeCategory: this.data.activeCategory,\n insightCategory: this.insightCategory,\n });\n const output =\n hasBlockingRequests && matchesCategory ? this.#renderRenderBlocking(renderBlockingResults) : LitHtml.nothing;\n LitHtml.render(output, this.shadow, {host: this});\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-render-blocking-requests': RenderBlockingRequests;\n }\n}\n\ncustomElements.define('devtools-performance-render-blocking-requests', RenderBlockingRequests);\n"]} \ No newline at end of file diff --git a/public/panels/timeline/components/insights/SidebarInsight.d.ts b/public/panels/timeline/components/insights/SidebarInsight.d.ts index c7bedaf98..0fedd78cb 100644 --- a/public/panels/timeline/components/insights/SidebarInsight.d.ts +++ b/public/panels/timeline/components/insights/SidebarInsight.d.ts @@ -1,3 +1,4 @@ +import type * as Trace from '../../../../models/trace/trace.js'; import type * as Overlays from '../../overlays/overlays.js'; export interface InsightDetails { title: string; @@ -15,10 +16,22 @@ export declare class InsightDeactivated extends Event { static readonly eventName = "insightdeactivated"; constructor(); } +export declare class NavigationBoundsHovered extends Event { + bounds?: Trace.Types.Timing.TraceWindowMicroSeconds | undefined; + static readonly eventName = "navigationhovered"; + constructor(bounds?: Trace.Types.Timing.TraceWindowMicroSeconds | undefined); +} +export declare class InsightOverlayOverride extends Event { + overlays: Array | null; + static readonly eventName = "insightoverlayoverride"; + constructor(overlays: Array | null); +} declare global { interface GlobalEventHandlersEventMap { [InsightActivated.eventName]: InsightActivated; [InsightDeactivated.eventName]: InsightDeactivated; + [NavigationBoundsHovered.eventName]: NavigationBoundsHovered; + [InsightOverlayOverride.eventName]: InsightOverlayOverride; } } export declare class SidebarInsight extends HTMLElement { diff --git a/public/panels/timeline/components/insights/SidebarInsight.js b/public/panels/timeline/components/insights/SidebarInsight.js index 1297e637f..2d2327a3f 100644 --- a/public/panels/timeline/components/insights/SidebarInsight.js +++ b/public/panels/timeline/components/insights/SidebarInsight.js @@ -34,6 +34,22 @@ export class InsightDeactivated extends Event { super(InsightDeactivated.eventName, { bubbles: true, composed: true }); } } +export class NavigationBoundsHovered extends Event { + bounds; + static eventName = 'navigationhovered'; + constructor(bounds) { + super(NavigationBoundsHovered.eventName, { bubbles: true, composed: true }); + this.bounds = bounds; + } +} +export class InsightOverlayOverride extends Event { + overlays; + static eventName = 'insightoverlayoverride'; + constructor(overlays) { + super(InsightOverlayOverride.eventName, { bubbles: true, composed: true }); + this.overlays = overlays; + } +} export class SidebarInsight extends HTMLElement { static litTagName = LitHtml.literal `devtools-performance-sidebar-insight`; #shadow = this.attachShadow({ mode: 'open' }); diff --git a/public/panels/timeline/components/insights/SidebarInsight.js.map b/public/panels/timeline/components/insights/SidebarInsight.js.map index fdfab7059..b5e6328ba 100644 --- a/public/panels/timeline/components/insights/SidebarInsight.js.map +++ b/public/panels/timeline/components/insights/SidebarInsight.js.map @@ -1 +1 @@ -{"version":3,"file":"SidebarInsight.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/SidebarInsight.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport type * as TraceEngine from '../../../../models/trace/trace.js';\nimport * as Buttons from '../../../../ui/components/buttons/buttons.js';\nimport * as ComponentHelpers from '../../../../ui/components/helpers/helpers.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\nimport * as VisualLogging from '../../../../ui/visual_logging/visual_logging.js';\nimport type * as Overlays from '../../overlays/overlays.js';\n\nimport sidebarInsightStyles from './sidebarInsight.css.js';\n\nconst UIStrings = {\n /**\n * @description Text to tell the user the estimated savings for this insight.\n * @example {401ms} PH1\n */\n estimatedSavings: 'Est savings: {PH1}',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/components/insights/SidebarInsight.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport interface InsightDetails {\n title: string;\n expanded: boolean;\n estimatedSavings?: number|undefined;\n}\n\nexport class InsightActivated extends Event {\n static readonly eventName = 'insightactivated';\n\n constructor(\n public name: string, public navigationId: string,\n public createOverlayFn: () => Array) {\n super(InsightActivated.eventName, {bubbles: true, composed: true});\n }\n}\n\nexport class InsightDeactivated extends Event {\n static readonly eventName = 'insightdeactivated';\n constructor() {\n super(InsightDeactivated.eventName, {bubbles: true, composed: true});\n }\n}\n\ndeclare global {\n interface GlobalEventHandlersEventMap {\n [InsightActivated.eventName]: InsightActivated;\n [InsightDeactivated.eventName]: InsightDeactivated;\n }\n}\n\nexport class SidebarInsight extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-performance-sidebar-insight`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n readonly #boundRender = this.#render.bind(this);\n #insightTitle: string = '';\n #expanded: boolean = false;\n #estimatedSavings: number|undefined = undefined;\n\n set data(data: InsightDetails) {\n this.#insightTitle = data.title;\n this.#expanded = data.expanded;\n this.#estimatedSavings = data.estimatedSavings;\n\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [sidebarInsightStyles];\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n #dispatchInsightToggle(): void {\n this.dispatchEvent(new CustomEvent('insighttoggleclick'));\n }\n\n #renderHoverIcon(insightIsActive: boolean): LitHtml.TemplateResult {\n // clang-format off\n const containerClasses = LitHtml.Directives.classMap({\n 'insight-hover-icon': true,\n active: insightIsActive,\n });\n return LitHtml.html`\n
    \n <${Buttons.Button.Button.litTagName} .data=${{\n variant: Buttons.Button.Variant.ICON,\n iconName: 'chevron-down',\n size: Buttons.Button.Size.SMALL,\n } as Buttons.Button.ButtonData}\n >\n
    \n\n `;\n // clang-format on\n }\n\n #render(): void {\n const containerClasses = LitHtml.Directives.classMap({\n insight: true,\n closed: !this.#expanded,\n });\n\n // clang-format off\n const output = LitHtml.html`\n
    \n
    \n ${this.#renderHoverIcon(this.#expanded)}\n

    ${this.#insightTitle}

    \n ${this.#estimatedSavings && this.#estimatedSavings > 0 ?\n LitHtml.html`\n \n ${i18nString(UIStrings.estimatedSavings, {PH1: i18n.TimeUtilities.millisToString(this.#estimatedSavings as TraceEngine.Types.Timing.MilliSeconds)})}\n \n
    `\n : LitHtml.nothing}\n \n ${this.#expanded ? LitHtml.html`\n
    \n \n \n
    `\n : LitHtml.nothing\n }\n
    \n `;\n // clang-format on\n LitHtml.render(output, this.#shadow, {host: this});\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-sidebar-insight': SidebarInsight;\n }\n}\n\ncustomElements.define('devtools-performance-sidebar-insight', SidebarInsight);\n"]} \ No newline at end of file +{"version":3,"file":"SidebarInsight.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/SidebarInsight.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport type * as Trace from '../../../../models/trace/trace.js';\nimport * as Buttons from '../../../../ui/components/buttons/buttons.js';\nimport * as ComponentHelpers from '../../../../ui/components/helpers/helpers.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\nimport * as VisualLogging from '../../../../ui/visual_logging/visual_logging.js';\nimport type * as Overlays from '../../overlays/overlays.js';\n\nimport sidebarInsightStyles from './sidebarInsight.css.js';\n\nconst UIStrings = {\n /**\n * @description Text to tell the user the estimated savings for this insight.\n * @example {401ms} PH1\n */\n estimatedSavings: 'Est savings: {PH1}',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/components/insights/SidebarInsight.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport interface InsightDetails {\n title: string;\n expanded: boolean;\n estimatedSavings?: number|undefined;\n}\n\nexport class InsightActivated extends Event {\n static readonly eventName = 'insightactivated';\n\n constructor(\n public name: string, public navigationId: string,\n public createOverlayFn: () => Array) {\n super(InsightActivated.eventName, {bubbles: true, composed: true});\n }\n}\n\nexport class InsightDeactivated extends Event {\n static readonly eventName = 'insightdeactivated';\n constructor() {\n super(InsightDeactivated.eventName, {bubbles: true, composed: true});\n }\n}\n\nexport class NavigationBoundsHovered extends Event {\n static readonly eventName = 'navigationhovered';\n constructor(public bounds?: Trace.Types.Timing.TraceWindowMicroSeconds) {\n super(NavigationBoundsHovered.eventName, {bubbles: true, composed: true});\n }\n}\n\nexport class InsightOverlayOverride extends Event {\n static readonly eventName = 'insightoverlayoverride';\n\n constructor(public overlays: Array|null) {\n super(InsightOverlayOverride.eventName, {bubbles: true, composed: true});\n }\n}\n\ndeclare global {\n interface GlobalEventHandlersEventMap {\n [InsightActivated.eventName]: InsightActivated;\n [InsightDeactivated.eventName]: InsightDeactivated;\n [NavigationBoundsHovered.eventName]: NavigationBoundsHovered;\n [InsightOverlayOverride.eventName]: InsightOverlayOverride;\n }\n}\n\nexport class SidebarInsight extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-performance-sidebar-insight`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n readonly #boundRender = this.#render.bind(this);\n #insightTitle: string = '';\n #expanded: boolean = false;\n #estimatedSavings: number|undefined = undefined;\n\n set data(data: InsightDetails) {\n this.#insightTitle = data.title;\n this.#expanded = data.expanded;\n this.#estimatedSavings = data.estimatedSavings;\n\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [sidebarInsightStyles];\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n #dispatchInsightToggle(): void {\n this.dispatchEvent(new CustomEvent('insighttoggleclick'));\n }\n\n #renderHoverIcon(insightIsActive: boolean): LitHtml.TemplateResult {\n // clang-format off\n const containerClasses = LitHtml.Directives.classMap({\n 'insight-hover-icon': true,\n active: insightIsActive,\n });\n return LitHtml.html`\n
    \n <${Buttons.Button.Button.litTagName} .data=${{\n variant: Buttons.Button.Variant.ICON,\n iconName: 'chevron-down',\n size: Buttons.Button.Size.SMALL,\n } as Buttons.Button.ButtonData}\n >\n
    \n\n `;\n // clang-format on\n }\n\n #render(): void {\n const containerClasses = LitHtml.Directives.classMap({\n insight: true,\n closed: !this.#expanded,\n });\n\n // clang-format off\n const output = LitHtml.html`\n
    \n
    \n ${this.#renderHoverIcon(this.#expanded)}\n

    ${this.#insightTitle}

    \n ${this.#estimatedSavings && this.#estimatedSavings > 0 ?\n LitHtml.html`\n \n ${i18nString(UIStrings.estimatedSavings, {PH1: i18n.TimeUtilities.millisToString(this.#estimatedSavings as Trace.Types.Timing.MilliSeconds)})}\n \n
    `\n : LitHtml.nothing}\n \n ${this.#expanded ? LitHtml.html`\n
    \n \n \n
    `\n : LitHtml.nothing\n }\n
    \n `;\n // clang-format on\n LitHtml.render(output, this.#shadow, {host: this});\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-sidebar-insight': SidebarInsight;\n }\n}\n\ncustomElements.define('devtools-performance-sidebar-insight', SidebarInsight);\n"]} \ No newline at end of file diff --git a/public/panels/timeline/components/insights/SlowCSSSelector.d.ts b/public/panels/timeline/components/insights/SlowCSSSelector.d.ts index 9d514fba3..2fc4d45a1 100644 --- a/public/panels/timeline/components/insights/SlowCSSSelector.d.ts +++ b/public/panels/timeline/components/insights/SlowCSSSelector.d.ts @@ -1,4 +1,4 @@ -import type * as TraceEngine from '../../../../models/trace/trace.js'; +import type * as Trace from '../../../../models/trace/trace.js'; import * as LitHtml from '../../../../ui/lit-html/lit-html.js'; import type * as Overlays from '../../overlays/overlays.js'; import { BaseInsight } from './Helpers.js'; @@ -9,7 +9,7 @@ export declare class SlowCSSSelector extends BaseInsight { insightCategory: InsightsCategories; internalName: string; userVisibleTitle: string; - getSlowCSSSelectorData(insights: TraceEngine.Insights.Types.TraceInsightData | null, navigationId: string | null): TraceEngine.Insights.InsightRunners.SlowCSSSelector.SlowCSSSelectorInsightResult | null; + getSlowCSSSelectorData(insights: Trace.Insights.Types.TraceInsightSets | null, navigationId: string | null): Trace.Insights.InsightRunners.SlowCSSSelector.SlowCSSSelectorInsightResult | null; createOverlays(): Overlays.Overlays.TimelineOverlay[]; renderSlowCSSSelector(): LitHtml.LitTemplate; render(): void; diff --git a/public/panels/timeline/components/insights/SlowCSSSelector.js b/public/panels/timeline/components/insights/SlowCSSSelector.js index 547119ead..3ab968293 100644 --- a/public/panels/timeline/components/insights/SlowCSSSelector.js +++ b/public/panels/timeline/components/insights/SlowCSSSelector.js @@ -21,7 +21,7 @@ export class SlowCSSSelector extends BaseInsight { if (!insightsByNavigation) { return null; } - const slowCSSSelector = insightsByNavigation.SlowCSSSelector; + const slowCSSSelector = insightsByNavigation.data.SlowCSSSelector; if (slowCSSSelector instanceof Error) { return null; } @@ -36,7 +36,7 @@ export class SlowCSSSelector extends BaseInsight { if (!insightsByNavigation) { return []; } - const scsInsight = insightsByNavigation.SlowCSSSelector; + const scsInsight = insightsByNavigation.data.SlowCSSSelector; if (scsInsight instanceof Error) { return []; } diff --git a/public/panels/timeline/components/insights/SlowCSSSelector.js.map b/public/panels/timeline/components/insights/SlowCSSSelector.js.map index 14893dec1..558fa4f11 100644 --- a/public/panels/timeline/components/insights/SlowCSSSelector.js.map +++ b/public/panels/timeline/components/insights/SlowCSSSelector.js.map @@ -1 +1 @@ -{"version":3,"file":"SlowCSSSelector.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/SlowCSSSelector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../../../core/common/common.js';\nimport type * as TraceEngine from '../../../../models/trace/trace.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\nimport type * as Components from '../../overlays/components/components.js';\nimport type * as Overlays from '../../overlays/overlays.js';\n\nimport {BaseInsight, shouldRenderForCategory} from './Helpers.js';\nimport * as SidebarInsight from './SidebarInsight.js';\nimport {Table, type TableData} from './Table.js';\nimport {InsightsCategories} from './types.js';\n\nexport class SlowCSSSelector extends BaseInsight {\n static readonly litTagName = LitHtml.literal`devtools-performance-slow-css-selector`;\n override insightCategory: InsightsCategories = InsightsCategories.OTHER;\n override internalName: string = 'slow-css-selector';\n override userVisibleTitle: string = 'Slow CSS Selectors';\n #slowCSSSelector: TraceEngine.Insights.InsightRunners.SlowCSSSelector.SlowCSSSelectorInsightResult|null = null;\n\n getSlowCSSSelectorData(insights: TraceEngine.Insights.Types.TraceInsightData|null, navigationId: string|null):\n TraceEngine.Insights.InsightRunners.SlowCSSSelector.SlowCSSSelectorInsightResult|null {\n if (!insights || !navigationId) {\n return null;\n }\n\n const insightsByNavigation = insights.get(navigationId);\n if (!insightsByNavigation) {\n return null;\n }\n\n const slowCSSSelector = insightsByNavigation.SlowCSSSelector;\n if (slowCSSSelector instanceof Error) {\n return null;\n }\n\n return slowCSSSelector;\n }\n\n override createOverlays(): Overlays.Overlays.TimelineOverlay[] {\n if (!this.data.insights || !this.data.navigationId) {\n return [];\n }\n const {navigationId, insights} = this.data;\n\n const insightsByNavigation = insights.get(navigationId);\n if (!insightsByNavigation) {\n return [];\n }\n\n const scsInsight: Error|TraceEngine.Insights.InsightRunners.SlowCSSSelector.SlowCSSSelectorInsightResult =\n insightsByNavigation.SlowCSSSelector;\n if (scsInsight instanceof Error) {\n return [];\n }\n\n const sections: Array = [];\n\n return [{\n type: 'TIMESPAN_BREAKDOWN',\n sections,\n }];\n }\n\n renderSlowCSSSelector(): LitHtml.LitTemplate {\n // clang-format off\n return this.#slowCSSSelector ? LitHtml.html`\n
    \n <${SidebarInsight.SidebarInsight.litTagName} .data=${{\n title: this.userVisibleTitle,\n expanded: this.isActive(),\n } as SidebarInsight.InsightDetails}\n @insighttoggleclick=${this.onSidebarClick}\n >\n
    \n ${LitHtml.html`<${Table.litTagName}\n .data=${{\n headers: ['Total', 'Stats'],\n rows: [\n ['Elapsed in ms', this.#slowCSSSelector.totalElapsedMs],\n ['Match Attempts', this.#slowCSSSelector.totalMatchAttempts],\n ['Match Count', this.#slowCSSSelector.totalMatchCount],\n ],\n } as TableData}>\n `}\n ${LitHtml.html`<${Table.litTagName}\n .data=${{\n headers: ['Top Selectors', 'Elapsed Time (ms)'],\n rows: this.#slowCSSSelector.topElapsedMs.map(selector => {\n return [selector.selector, selector['elapsed (us)'] / 1000.0];\n }),\n } as TableData}>\n `}\n ${LitHtml.html`<${Table.litTagName}\n .data=${{\n headers: ['Top Selectors', 'Match Attempts'],\n rows: this.#slowCSSSelector.topMatchAttempts.map(selector => {\n return [selector.selector, selector['match_attempts']];\n }),\n } as TableData}>\n `}\n
    \n \n
    ` : LitHtml.nothing;\n // clang-format on\n }\n\n #hasDataToRender(): boolean {\n const selectorStatsFeatureEnabled =\n Common.Settings.Settings.instance().createSetting('timeline-capture-selector-stats', false);\n this.#slowCSSSelector = selectorStatsFeatureEnabled.get() ?\n this.getSlowCSSSelectorData(this.data.insights, this.data.navigationId) :\n null;\n return this.#slowCSSSelector !== null;\n }\n\n override render(): void {\n const matchesCategory = shouldRenderForCategory({\n activeCategory: this.data.activeCategory,\n insightCategory: this.insightCategory,\n });\n const shouldRender = matchesCategory && this.#hasDataToRender();\n const output = shouldRender ? this.renderSlowCSSSelector() : LitHtml.nothing;\n LitHtml.render(output, this.shadow, {host: this});\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-slow-css-selector': SlowCSSSelector;\n }\n}\n\ncustomElements.define('devtools-performance-slow-css-selector', SlowCSSSelector);\n"]} \ No newline at end of file +{"version":3,"file":"SlowCSSSelector.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/SlowCSSSelector.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../../../core/common/common.js';\nimport type * as Trace from '../../../../models/trace/trace.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\nimport type * as Components from '../../overlays/components/components.js';\nimport type * as Overlays from '../../overlays/overlays.js';\n\nimport {BaseInsight, shouldRenderForCategory} from './Helpers.js';\nimport * as SidebarInsight from './SidebarInsight.js';\nimport {Table, type TableData} from './Table.js';\nimport {InsightsCategories} from './types.js';\n\nexport class SlowCSSSelector extends BaseInsight {\n static readonly litTagName = LitHtml.literal`devtools-performance-slow-css-selector`;\n override insightCategory: InsightsCategories = InsightsCategories.OTHER;\n override internalName: string = 'slow-css-selector';\n override userVisibleTitle: string = 'Slow CSS Selectors';\n #slowCSSSelector: Trace.Insights.InsightRunners.SlowCSSSelector.SlowCSSSelectorInsightResult|null = null;\n\n getSlowCSSSelectorData(insights: Trace.Insights.Types.TraceInsightSets|null, navigationId: string|null):\n Trace.Insights.InsightRunners.SlowCSSSelector.SlowCSSSelectorInsightResult|null {\n if (!insights || !navigationId) {\n return null;\n }\n\n const insightsByNavigation = insights.get(navigationId);\n if (!insightsByNavigation) {\n return null;\n }\n\n const slowCSSSelector = insightsByNavigation.data.SlowCSSSelector;\n if (slowCSSSelector instanceof Error) {\n return null;\n }\n\n return slowCSSSelector;\n }\n\n override createOverlays(): Overlays.Overlays.TimelineOverlay[] {\n if (!this.data.insights || !this.data.navigationId) {\n return [];\n }\n const {navigationId, insights} = this.data;\n\n const insightsByNavigation = insights.get(navigationId);\n if (!insightsByNavigation) {\n return [];\n }\n\n const scsInsight: Error|Trace.Insights.InsightRunners.SlowCSSSelector.SlowCSSSelectorInsightResult =\n insightsByNavigation.data.SlowCSSSelector;\n if (scsInsight instanceof Error) {\n return [];\n }\n\n const sections: Array = [];\n\n return [{\n type: 'TIMESPAN_BREAKDOWN',\n sections,\n }];\n }\n\n renderSlowCSSSelector(): LitHtml.LitTemplate {\n // clang-format off\n return this.#slowCSSSelector ? LitHtml.html`\n
    \n <${SidebarInsight.SidebarInsight.litTagName} .data=${{\n title: this.userVisibleTitle,\n expanded: this.isActive(),\n } as SidebarInsight.InsightDetails}\n @insighttoggleclick=${this.onSidebarClick}\n >\n
    \n ${LitHtml.html`<${Table.litTagName}\n .data=${{\n headers: ['Total', 'Stats'],\n rows: [\n ['Elapsed in ms', this.#slowCSSSelector.totalElapsedMs],\n ['Match Attempts', this.#slowCSSSelector.totalMatchAttempts],\n ['Match Count', this.#slowCSSSelector.totalMatchCount],\n ],\n } as TableData}>\n `}\n ${LitHtml.html`<${Table.litTagName}\n .data=${{\n headers: ['Top Selectors', 'Elapsed Time (ms)'],\n rows: this.#slowCSSSelector.topElapsedMs.map(selector => {\n return [selector.selector, selector['elapsed (us)'] / 1000.0];\n }),\n } as TableData}>\n `}\n ${LitHtml.html`<${Table.litTagName}\n .data=${{\n headers: ['Top Selectors', 'Match Attempts'],\n rows: this.#slowCSSSelector.topMatchAttempts.map(selector => {\n return [selector.selector, selector['match_attempts']];\n }),\n } as TableData}>\n `}\n
    \n \n
    ` : LitHtml.nothing;\n // clang-format on\n }\n\n #hasDataToRender(): boolean {\n const selectorStatsFeatureEnabled =\n Common.Settings.Settings.instance().createSetting('timeline-capture-selector-stats', false);\n this.#slowCSSSelector = selectorStatsFeatureEnabled.get() ?\n this.getSlowCSSSelectorData(this.data.insights, this.data.navigationId) :\n null;\n return this.#slowCSSSelector !== null;\n }\n\n override render(): void {\n const matchesCategory = shouldRenderForCategory({\n activeCategory: this.data.activeCategory,\n insightCategory: this.insightCategory,\n });\n const shouldRender = matchesCategory && this.#hasDataToRender();\n const output = shouldRender ? this.renderSlowCSSSelector() : LitHtml.nothing;\n LitHtml.render(output, this.shadow, {host: this});\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-slow-css-selector': SlowCSSSelector;\n }\n}\n\ncustomElements.define('devtools-performance-slow-css-selector', SlowCSSSelector);\n"]} \ No newline at end of file diff --git a/public/panels/timeline/components/insights/Table.d.ts b/public/panels/timeline/components/insights/Table.d.ts index 6ea785438..43be3166f 100644 --- a/public/panels/timeline/components/insights/Table.d.ts +++ b/public/panels/timeline/components/insights/Table.d.ts @@ -2,6 +2,9 @@ export interface TableData { headers: string[]; /** Each row is a tuple of values. */ rows: Array>; + onHoverRow?: (index: number, rowEl: HTMLElement) => void; + onClickRow?: (index: number, rowEl: HTMLElement) => void; + onMouseLeave?: () => void; } export declare class Table extends HTMLElement { #private; diff --git a/public/panels/timeline/components/insights/Table.js b/public/panels/timeline/components/insights/Table.js index 44f31b9fa..3dd88abc7 100644 --- a/public/panels/timeline/components/insights/Table.js +++ b/public/panels/timeline/components/insights/Table.js @@ -10,25 +10,75 @@ export class Table extends HTMLElement { #boundRender = this.#render.bind(this); #headers; #rows; + #onHoverRowCallback; + #onClickRowCallback; + #onMouseLeaveCallback; + #currentHoverIndex = null; set data(data) { this.#headers = data.headers; this.#rows = data.rows; + this.#onHoverRowCallback = data.onHoverRow; + this.#onClickRowCallback = data.onClickRow; + this.#onMouseLeaveCallback = data.onMouseLeave; void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender); } connectedCallback() { this.#shadow.adoptedStyleSheets.push(tableStyles); } + #onHoverRow(e) { + if (!this.#onHoverRowCallback || !(e.target instanceof HTMLElement)) { + return; + } + const rowEl = e.target.closest('tr'); + if (!rowEl || !rowEl.parentElement) { + return; + } + const index = [...rowEl.parentElement.children].indexOf(rowEl); + if (index === -1 || index === this.#currentHoverIndex) { + return; + } + this.#currentHoverIndex = index; + this.#onHoverRowCallback(index, rowEl); + } + #onClickRow(e) { + if (!this.#onClickRowCallback || !(e.target instanceof HTMLElement)) { + return; + } + const rowEl = e.target.closest('tr'); + if (!rowEl || !rowEl.parentElement) { + return; + } + const index = [...rowEl.parentElement.children].indexOf(rowEl); + if (index === -1) { + return; + } + this.#onClickRowCallback(index, rowEl); + } + #onMouseLeave() { + if (!this.#onMouseLeaveCallback) { + return; + } + this.#currentHoverIndex = null; + this.#onMouseLeaveCallback(); + } async #render() { if (!this.#headers || !this.#rows) { return; } - LitHtml.render(LitHtml.html ` + LitHtml.render(LitHtml.html `
    ${this.#headers.map(h => LitHtml.html ``)} - + ${this.#rows.map(row => { const rowsEls = row.map((value, i) => i === 0 ? LitHtml.html `` : LitHtml.html ``); return LitHtml.html `${rowsEls}`; diff --git a/public/panels/timeline/components/insights/Table.js.map b/public/panels/timeline/components/insights/Table.js.map index 3015f4faa..479e727a9 100644 --- a/public/panels/timeline/components/insights/Table.js.map +++ b/public/panels/timeline/components/insights/Table.js.map @@ -1 +1 @@ -{"version":3,"file":"Table.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/Table.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,gBAAgB,MAAM,8CAA8C,CAAC;AACjF,OAAO,KAAK,OAAO,MAAM,qCAAqC,CAAC;AAE/D,OAAO,WAAW,MAAM,gBAAgB,CAAC;AAQzC,MAAM,OAAO,KAAM,SAAQ,WAAW;IACpC,MAAM,CAAU,UAAU,GAAG,OAAO,CAAC,OAAO,CAAA,4BAA4B,CAAC;IAEhE,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,EAAC,IAAI,EAAE,MAAM,EAAC,CAAC,CAAC;IAC5C,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChD,QAAQ,CAAY;IACpB,KAAK,CAA+B;IAEpC,IAAI,IAAI,CAAC,IAAe;QACtB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC;QAC7B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC;QACvB,KAAK,gBAAgB,CAAC,eAAe,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IAChF,CAAC;IAED,iBAAiB;QACf,IAAI,CAAC,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACpD,CAAC;IAED,KAAK,CAAC,OAAO;QACX,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAClC,OAAO;QACT,CAAC;QAED,OAAO,CAAC,MAAM,CACV,OAAO,CAAC,IAAI,CAAA;;;YAGR,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAA,mBAAmB,CAAC,OAAO,CAAC;;;;YAI/D,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;YACvB,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,CACnB,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAA,mBAAmB,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAA,OAAO,KAAK,OAAO,CAAC,CAAC;YAC3G,OAAO,OAAO,CAAC,IAAI,CAAA,OAAO,OAAO,OAAO,CAAC;QAC3C,CAAC,CAAC;;aAEG,EACL,IAAI,CAAC,OAAO,EAAE,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC,CAAC;IAClC,CAAC;;AASH,cAAc,CAAC,MAAM,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as ComponentHelpers from '../../../../ui/components/helpers/helpers.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\n\nimport tableStyles from './table.css.js';\n\nexport interface TableData {\n headers: string[];\n /** Each row is a tuple of values. */\n rows: Array>;\n}\n\nexport class Table extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-performance-table`;\n\n readonly #shadow = this.attachShadow({mode: 'open'});\n readonly #boundRender = this.#render.bind(this);\n #headers?: string[];\n #rows?: Array>;\n\n set data(data: TableData) {\n this.#headers = data.headers;\n this.#rows = data.rows;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets.push(tableStyles);\n }\n\n async #render(): Promise {\n if (!this.#headers || !this.#rows) {\n return;\n }\n\n LitHtml.render(\n LitHtml.html`
    ${h}
    ${value}${value}
    \n \n \n ${this.#headers.map(h => LitHtml.html``)}\n \n \n \n ${this.#rows.map(row => {\n const rowsEls = row.map(\n (value, i) => i === 0 ? LitHtml.html`` : LitHtml.html``);\n return LitHtml.html`${rowsEls}`;\n })}\n \n `,\n this.#shadow, {host: this});\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-table': Table;\n }\n}\n\ncustomElements.define('devtools-performance-table', Table);\n"]} \ No newline at end of file +{"version":3,"file":"Table.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/Table.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as ComponentHelpers from '../../../../ui/components/helpers/helpers.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\n\nimport tableStyles from './table.css.js';\n\nexport interface TableData {\n headers: string[];\n /** Each row is a tuple of values. */\n rows: Array>;\n onHoverRow?: (index: number, rowEl: HTMLElement) => void;\n onClickRow?: (index: number, rowEl: HTMLElement) => void;\n onMouseLeave?: () => void;\n}\n\nexport class Table extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-performance-table`;\n\n readonly #shadow = this.attachShadow({mode: 'open'});\n readonly #boundRender = this.#render.bind(this);\n #headers?: string[];\n #rows?: Array>;\n #onHoverRowCallback?: (index: number, rowEl: HTMLElement) => void;\n #onClickRowCallback?: (index: number, rowEl: HTMLElement) => void;\n #onMouseLeaveCallback?: () => void;\n #currentHoverIndex: number|null = null;\n\n set data(data: TableData) {\n this.#headers = data.headers;\n this.#rows = data.rows;\n this.#onHoverRowCallback = data.onHoverRow;\n this.#onClickRowCallback = data.onClickRow;\n this.#onMouseLeaveCallback = data.onMouseLeave;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets.push(tableStyles);\n }\n\n #onHoverRow(e: MouseEvent): void {\n if (!this.#onHoverRowCallback || !(e.target instanceof HTMLElement)) {\n return;\n }\n\n const rowEl = e.target.closest('tr');\n if (!rowEl || !rowEl.parentElement) {\n return;\n }\n\n const index = [...rowEl.parentElement.children].indexOf(rowEl);\n if (index === -1 || index === this.#currentHoverIndex) {\n return;\n }\n\n this.#currentHoverIndex = index;\n this.#onHoverRowCallback(index, rowEl);\n }\n\n #onClickRow(e: MouseEvent): void {\n if (!this.#onClickRowCallback || !(e.target instanceof HTMLElement)) {\n return;\n }\n\n const rowEl = e.target.closest('tr');\n if (!rowEl || !rowEl.parentElement) {\n return;\n }\n\n const index = [...rowEl.parentElement.children].indexOf(rowEl);\n if (index === -1) {\n return;\n }\n\n this.#onClickRowCallback(index, rowEl);\n }\n\n #onMouseLeave(): void {\n if (!this.#onMouseLeaveCallback) {\n return;\n }\n\n this.#currentHoverIndex = null;\n this.#onMouseLeaveCallback();\n }\n\n async #render(): Promise {\n if (!this.#headers || !this.#rows) {\n return;\n }\n\n LitHtml.render(\n LitHtml.html`\n \n \n ${this.#headers.map(h => LitHtml.html``)}\n \n \n \n ${this.#rows.map(row => {\n const rowsEls = row.map(\n (value, i) => i === 0 ? LitHtml.html`` : LitHtml.html``);\n return LitHtml.html`${rowsEls}`;\n })}\n \n `,\n this.#shadow, {host: this});\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-table': Table;\n }\n}\n\ncustomElements.define('devtools-performance-table', Table);\n"]} \ No newline at end of file diff --git a/public/panels/timeline/components/insights/ThirdParties.d.ts b/public/panels/timeline/components/insights/ThirdParties.d.ts index bb83cc9ae..f02bf50b3 100644 --- a/public/panels/timeline/components/insights/ThirdParties.d.ts +++ b/public/panels/timeline/components/insights/ThirdParties.d.ts @@ -1,8 +1,8 @@ -import type * as TraceEngine from '../../../../models/trace/trace.js'; +import type * as Trace from '../../../../models/trace/trace.js'; import type * as Overlays from '../../overlays/overlays.js'; import { BaseInsight } from './Helpers.js'; import { InsightsCategories } from './types.js'; -export declare function getThirdPartiesInsight(insights: TraceEngine.Insights.Types.TraceInsightData | null, navigationId: string | null): TraceEngine.Insights.Types.InsightResults['ThirdPartyWeb'] | null; +export declare function getThirdPartiesInsight(insights: Trace.Insights.Types.TraceInsightSets | null, navigationId: string | null): Trace.Insights.Types.InsightResults['ThirdPartyWeb'] | null; export declare class ThirdParties extends BaseInsight { #private; static readonly litTagName: import("../../../../ui/lit-html/static.js").Static; diff --git a/public/panels/timeline/components/insights/ThirdParties.js b/public/panels/timeline/components/insights/ThirdParties.js index acf7849b0..6490d0653 100644 --- a/public/panels/timeline/components/insights/ThirdParties.js +++ b/public/panels/timeline/components/insights/ThirdParties.js @@ -9,19 +9,18 @@ import * as SidebarInsight from './SidebarInsight.js'; import { Table } from './Table.js'; import { InsightsCategories } from './types.js'; const UIStrings = { - /** Title of a diagnostic audit that provides details about the code on a web page that the user doesn't control (referred to as "third-party code"). */ - title: 'Minimize third-party usage', + /** Title of an insight that provides details about the code on a web page that the user doesn't control (referred to as "third-party code"). */ + title: 'Third parties', /** * @description Description of a DevTools insight that identifies the code on the page that the user doesn't control. * This is displayed after a user expands the section to see more. No character length limits. * The last sentence starting with 'Learn' becomes link text to additional documentation. */ - description: 'Third-party code can significantly impact load performance. ' + - 'Limit the number of redundant third-party providers and try to load third-party code after ' + - 'your page has primarily finished loading. ' + - '[Learn how to minimize third-party impact](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/).', + description: 'Third party code can significantly impact load performance. ' + + 'Assess and reduce the ' + + '[amount of third party code](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/) on the page, and try to load what you can after the page has finished loading the main content.', /** Label for a table column that displays the name of a third-party provider. */ - columnThirdParty: 'Third-party', + columnThirdParty: 'Third party', /** Label for a column in a data table; entries will be the download size of a web resource in kilobytes. */ columnTransferSize: 'Transfer size', /** Label for a table column that displays how much time each row spent blocking other work on the main thread, entries will be the number of milliseconds spent. */ @@ -37,7 +36,7 @@ export function getThirdPartiesInsight(insights, navigationId) { if (!insightsByNavigation) { return null; } - const thirdPartiesInsight = insightsByNavigation.ThirdPartyWeb; + const thirdPartiesInsight = insightsByNavigation.data.ThirdPartyWeb; if (thirdPartiesInsight instanceof Error) { return null; } @@ -48,7 +47,11 @@ export class ThirdParties extends BaseInsight { insightCategory = InsightsCategories.OTHER; internalName = 'third-parties'; userVisibleTitle = i18nString(UIStrings.title); + #overlaysForEntity = new Map(); + #currentSelectedRowEl = null; + #currentSelectionIsSticky = false; createOverlays() { + this.#overlaysForEntity.clear(); const insight = getThirdPartiesInsight(this.data.insights, this.data.navigationId); if (!insight) { return []; @@ -58,33 +61,48 @@ export class ThirdParties extends BaseInsight { if (entity === insight.firstPartyEntity) { continue; } + const overlaysForThisEntity = []; for (const request of requests) { - overlays.push({ + const overlay = { type: 'ENTRY_OUTLINE', entry: request, outlineReason: 'INFO', - }); + }; + overlaysForThisEntity.push(overlay); + overlays.push(overlay); } + this.#overlaysForEntity.set(entity, overlaysForThisEntity); } return overlays; } - #render(data) { - const entries = [...data.summaryByEntity.entries()].filter(kv => kv[0] !== data.firstPartyEntity); + #onSelectedRowChanged(entity, rowEl, sticky) { + if (this.#currentSelectionIsSticky && !sticky) { + return; + } + // Unselect a sticky-selection when clicking it for a second time. + if (this.#currentSelectionIsSticky && rowEl === this.#currentSelectedRowEl) { + entity = null; + rowEl = null; + sticky = false; + } + if (entity) { + const overlays = this.#overlaysForEntity.get(entity); + if (overlays) { + this.onOverlayOverride(overlays); + } + } + else { + this.onOverlayOverride(null); + } + this.#currentSelectedRowEl?.classList.remove('selected'); + rowEl?.classList.add('selected'); + this.#currentSelectedRowEl = rowEl; + this.#currentSelectionIsSticky = sticky; + } + #render(entries) { + const topTransferSizeEntries = entries.sort((a, b) => b[1].transferSize - a[1].transferSize).slice(0, 6); + const topMainThreadTimeEntries = entries.sort((a, b) => b[1].mainThreadTime - a[1].mainThreadTime).slice(0, 6); // clang-format off - const rows1 = entries - .sort((a, b) => b[1].transferSize - a[1].transferSize) - .slice(0, 6) - .map(([entity, summary]) => [ - entity.name, - Platform.NumberUtilities.bytesToString(summary.transferSize), - ]); - const rows2 = entries - .sort((a, b) => b[1].mainThreadTime - a[1].mainThreadTime) - .slice(0, 6) - .map(([entity, summary]) => [ - entity.name, - i18n.TimeUtilities.millisToString(Platform.Timing.microSecondsToMilliSeconds(summary.mainThreadTime)), - ]); return LitHtml.html `
    <${SidebarInsight.SidebarInsight.litTagName} .data=${{ @@ -99,13 +117,25 @@ export class ThirdParties extends BaseInsight { ${LitHtml.html `<${Table.litTagName} .data=${{ headers: [i18nString(UIStrings.columnThirdParty), i18nString(UIStrings.columnTransferSize)], - rows: rows1, + rows: topTransferSizeEntries.map(([entity, summary]) => [ + entity.name, + Platform.NumberUtilities.bytesToString(summary.transferSize), + ]), + onHoverRow: (index, rowEl) => this.#onSelectedRowChanged(topTransferSizeEntries[index][0], rowEl, false), + onClickRow: (index, rowEl) => this.#onSelectedRowChanged(topTransferSizeEntries[index][0], rowEl, true), + onMouseLeave: () => this.#onSelectedRowChanged(null, null, false), }}> `} ${LitHtml.html `<${Table.litTagName} .data=${{ headers: [i18nString(UIStrings.columnThirdParty), i18nString(UIStrings.columnBlockingTime)], - rows: rows2, + rows: topMainThreadTimeEntries.map(([entity, summary]) => [ + entity.name, + i18n.TimeUtilities.millisToString(Platform.Timing.microSecondsToMilliSeconds(summary.mainThreadTime)), + ]), + onHoverRow: (index, rowEl) => this.#onSelectedRowChanged(topMainThreadTimeEntries[index][0], rowEl, false), + onClickRow: (index, rowEl) => this.#onSelectedRowChanged(topMainThreadTimeEntries[index][0], rowEl, true), + onMouseLeave: () => this.#onSelectedRowChanged(null, null, false), }}> `}
    @@ -115,12 +145,13 @@ export class ThirdParties extends BaseInsight { } render() { const insight = getThirdPartiesInsight(this.data.insights, this.data.navigationId); - const shouldShow = insight && insight.summaryByEntity.size; + const entries = insight && [...insight.summaryByEntity.entries()].filter(kv => kv[0] !== insight.firstPartyEntity); + const shouldShow = entries?.length; const matchesCategory = shouldRenderForCategory({ activeCategory: this.data.activeCategory, insightCategory: this.insightCategory, }); - const output = shouldShow && matchesCategory ? this.#render(insight) : LitHtml.nothing; + const output = shouldShow && matchesCategory ? this.#render(entries) : LitHtml.nothing; LitHtml.render(output, this.shadow, { host: this }); } } diff --git a/public/panels/timeline/components/insights/ThirdParties.js.map b/public/panels/timeline/components/insights/ThirdParties.js.map index 6555abce7..1d55feefe 100644 --- a/public/panels/timeline/components/insights/ThirdParties.js.map +++ b/public/panels/timeline/components/insights/ThirdParties.js.map @@ -1 +1 @@ -{"version":3,"file":"ThirdParties.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/ThirdParties.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport * as Platform from '../../../../core/platform/platform.js';\nimport type * as TraceEngine from '../../../../models/trace/trace.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\nimport type * as Overlays from '../../overlays/overlays.js';\n\nimport {BaseInsight, md, shouldRenderForCategory} from './Helpers.js';\nimport * as SidebarInsight from './SidebarInsight.js';\nimport {Table, type TableData} from './Table.js';\nimport {InsightsCategories} from './types.js';\n\nconst UIStrings = {\n /** Title of a diagnostic audit that provides details about the code on a web page that the user doesn't control (referred to as \"third-party code\"). */\n title: 'Minimize third-party usage',\n /**\n * @description Description of a DevTools insight that identifies the code on the page that the user doesn't control.\n * This is displayed after a user expands the section to see more. No character length limits.\n * The last sentence starting with 'Learn' becomes link text to additional documentation.\n */\n description: 'Third-party code can significantly impact load performance. ' +\n 'Limit the number of redundant third-party providers and try to load third-party code after ' +\n 'your page has primarily finished loading. ' +\n '[Learn how to minimize third-party impact](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/).',\n /** Label for a table column that displays the name of a third-party provider. */\n columnThirdParty: 'Third-party',\n /** Label for a column in a data table; entries will be the download size of a web resource in kilobytes. */\n columnTransferSize: 'Transfer size',\n /** Label for a table column that displays how much time each row spent blocking other work on the main thread, entries will be the number of milliseconds spent. */\n columnBlockingTime: 'Blocking time',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/components/insights/ThirdParties.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function getThirdPartiesInsight(\n insights: TraceEngine.Insights.Types.TraceInsightData|null,\n navigationId: string|null): TraceEngine.Insights.Types.InsightResults['ThirdPartyWeb']|null {\n if (!insights || !navigationId) {\n return null;\n }\n\n const insightsByNavigation = insights.get(navigationId);\n if (!insightsByNavigation) {\n return null;\n }\n\n const thirdPartiesInsight = insightsByNavigation.ThirdPartyWeb;\n if (thirdPartiesInsight instanceof Error) {\n return null;\n }\n return thirdPartiesInsight;\n}\n\nexport class ThirdParties extends BaseInsight {\n static readonly litTagName = LitHtml.literal`devtools-performance-third-parties`;\n override insightCategory: InsightsCategories = InsightsCategories.OTHER;\n override internalName: string = 'third-parties';\n override userVisibleTitle: string = i18nString(UIStrings.title);\n\n override createOverlays(): Overlays.Overlays.TimelineOverlay[] {\n const insight = getThirdPartiesInsight(this.data.insights, this.data.navigationId);\n if (!insight) {\n return [];\n }\n\n const overlays: Overlays.Overlays.TimelineOverlay[] = [];\n for (const [entity, requests] of insight.requestsByEntity) {\n if (entity === insight.firstPartyEntity) {\n continue;\n }\n\n for (const request of requests) {\n overlays.push({\n type: 'ENTRY_OUTLINE',\n entry: request,\n outlineReason: 'INFO',\n });\n }\n }\n\n return overlays;\n }\n\n #render(data: TraceEngine.Insights.Types.InsightResults['ThirdPartyWeb']): LitHtml.TemplateResult {\n const entries = [...data.summaryByEntity.entries()].filter(kv => kv[0] !== data.firstPartyEntity);\n // clang-format off\n const rows1 = entries\n .sort((a, b) => b[1].transferSize - a[1].transferSize)\n .slice(0, 6)\n .map(([entity, summary]) => [\n entity.name,\n Platform.NumberUtilities.bytesToString(summary.transferSize),\n ]);\n const rows2 = entries\n .sort((a, b) => b[1].mainThreadTime - a[1].mainThreadTime)\n .slice(0, 6)\n .map(([entity, summary]) => [\n entity.name,\n i18n.TimeUtilities.millisToString(Platform.Timing.microSecondsToMilliSeconds(summary.mainThreadTime)),\n ]);\n\n return LitHtml.html`\n
    \n <${SidebarInsight.SidebarInsight.litTagName} .data=${{\n title: this.userVisibleTitle,\n expanded: this.isActive(),\n } as SidebarInsight.InsightDetails}\n @insighttoggleclick=${this.onSidebarClick}>\n
    \n ${md(i18nString(UIStrings.description))}\n
    \n
    \n ${LitHtml.html`<${Table.litTagName}\n .data=${{\n headers: [i18nString(UIStrings.columnThirdParty), i18nString(UIStrings.columnTransferSize)],\n rows: rows1,\n } as TableData}>\n `}\n ${LitHtml.html`<${Table.litTagName}\n .data=${{\n headers: [i18nString(UIStrings.columnThirdParty), i18nString(UIStrings.columnBlockingTime)],\n rows: rows2,\n } as TableData}>\n `}\n
    \n \n
    `;\n // clang-format on\n }\n\n override render(): void {\n const insight = getThirdPartiesInsight(this.data.insights, this.data.navigationId);\n const shouldShow = insight && insight.summaryByEntity.size;\n\n const matchesCategory = shouldRenderForCategory({\n activeCategory: this.data.activeCategory,\n insightCategory: this.insightCategory,\n });\n const output = shouldShow && matchesCategory ? this.#render(insight) : LitHtml.nothing;\n LitHtml.render(output, this.shadow, {host: this});\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-third-parties': ThirdParties;\n }\n}\n\ncustomElements.define('devtools-performance-third-parties', ThirdParties);\n"]} \ No newline at end of file +{"version":3,"file":"ThirdParties.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/ThirdParties.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport * as Platform from '../../../../core/platform/platform.js';\nimport type * as Trace from '../../../../models/trace/trace.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\nimport type * as Overlays from '../../overlays/overlays.js';\n\nimport {BaseInsight, md, shouldRenderForCategory} from './Helpers.js';\nimport * as SidebarInsight from './SidebarInsight.js';\nimport {Table, type TableData} from './Table.js';\nimport {InsightsCategories} from './types.js';\n\ntype ThirdPartiesEntires = Array<[\n Trace.Insights.InsightRunners.ThirdPartyWeb.Entity,\n Trace.Insights.InsightRunners.ThirdPartyWeb.Summary,\n]>;\n\nconst UIStrings = {\n /** Title of an insight that provides details about the code on a web page that the user doesn't control (referred to as \"third-party code\"). */\n title: 'Third parties',\n /**\n * @description Description of a DevTools insight that identifies the code on the page that the user doesn't control.\n * This is displayed after a user expands the section to see more. No character length limits.\n * The last sentence starting with 'Learn' becomes link text to additional documentation.\n */\n description: 'Third party code can significantly impact load performance. ' +\n 'Assess and reduce the ' +\n '[amount of third party code](https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/loading-third-party-javascript/) on the page, and try to load what you can after the page has finished loading the main content.',\n /** Label for a table column that displays the name of a third-party provider. */\n columnThirdParty: 'Third party',\n /** Label for a column in a data table; entries will be the download size of a web resource in kilobytes. */\n columnTransferSize: 'Transfer size',\n /** Label for a table column that displays how much time each row spent blocking other work on the main thread, entries will be the number of milliseconds spent. */\n columnBlockingTime: 'Blocking time',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/components/insights/ThirdParties.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function getThirdPartiesInsight(insights: Trace.Insights.Types.TraceInsightSets|null, navigationId: string|null):\n Trace.Insights.Types.InsightResults['ThirdPartyWeb']|null {\n if (!insights || !navigationId) {\n return null;\n }\n\n const insightsByNavigation = insights.get(navigationId);\n if (!insightsByNavigation) {\n return null;\n }\n\n const thirdPartiesInsight = insightsByNavigation.data.ThirdPartyWeb;\n if (thirdPartiesInsight instanceof Error) {\n return null;\n }\n return thirdPartiesInsight;\n}\n\nexport class ThirdParties extends BaseInsight {\n static readonly litTagName = LitHtml.literal`devtools-performance-third-parties`;\n override insightCategory: InsightsCategories = InsightsCategories.OTHER;\n override internalName: string = 'third-parties';\n override userVisibleTitle: string = i18nString(UIStrings.title);\n\n #overlaysForEntity =\n new Map();\n #currentSelectedRowEl: HTMLElement|null = null;\n #currentSelectionIsSticky = false;\n\n override createOverlays(): Overlays.Overlays.TimelineOverlay[] {\n this.#overlaysForEntity.clear();\n\n const insight = getThirdPartiesInsight(this.data.insights, this.data.navigationId);\n if (!insight) {\n return [];\n }\n\n const overlays: Overlays.Overlays.TimelineOverlay[] = [];\n for (const [entity, requests] of insight.requestsByEntity) {\n if (entity === insight.firstPartyEntity) {\n continue;\n }\n\n const overlaysForThisEntity = [];\n for (const request of requests) {\n const overlay: Overlays.Overlays.TimelineOverlay = {\n type: 'ENTRY_OUTLINE',\n entry: request,\n outlineReason: 'INFO',\n };\n overlaysForThisEntity.push(overlay);\n overlays.push(overlay);\n }\n\n this.#overlaysForEntity.set(entity, overlaysForThisEntity);\n }\n\n return overlays;\n }\n\n #onSelectedRowChanged(\n entity: Trace.Insights.InsightRunners.ThirdPartyWeb.Entity|null, rowEl: HTMLElement|null, sticky: boolean): void {\n if (this.#currentSelectionIsSticky && !sticky) {\n return;\n }\n\n // Unselect a sticky-selection when clicking it for a second time.\n if (this.#currentSelectionIsSticky && rowEl === this.#currentSelectedRowEl) {\n entity = null;\n rowEl = null;\n sticky = false;\n }\n\n if (entity) {\n const overlays = this.#overlaysForEntity.get(entity);\n if (overlays) {\n this.onOverlayOverride(overlays);\n }\n } else {\n this.onOverlayOverride(null);\n }\n\n this.#currentSelectedRowEl?.classList.remove('selected');\n rowEl?.classList.add('selected');\n this.#currentSelectedRowEl = rowEl;\n this.#currentSelectionIsSticky = sticky;\n }\n\n #render(entries: ThirdPartiesEntires): LitHtml.TemplateResult {\n const topTransferSizeEntries = entries.sort((a, b) => b[1].transferSize - a[1].transferSize).slice(0, 6);\n const topMainThreadTimeEntries = entries.sort((a, b) => b[1].mainThreadTime - a[1].mainThreadTime).slice(0, 6);\n\n // clang-format off\n return LitHtml.html`\n
    \n <${SidebarInsight.SidebarInsight.litTagName} .data=${{\n title: this.userVisibleTitle,\n expanded: this.isActive(),\n } as SidebarInsight.InsightDetails}\n @insighttoggleclick=${this.onSidebarClick}>\n
    \n ${md(i18nString(UIStrings.description))}\n
    \n
    \n ${LitHtml.html`<${Table.litTagName}\n .data=${{\n headers: [i18nString(UIStrings.columnThirdParty), i18nString(UIStrings.columnTransferSize)],\n rows: topTransferSizeEntries.map(([entity, summary]) => [\n entity.name,\n Platform.NumberUtilities.bytesToString(summary.transferSize),\n ]),\n onHoverRow: (index: number, rowEl: HTMLElement) => this.#onSelectedRowChanged(topTransferSizeEntries[index][0], rowEl, false),\n onClickRow: (index: number, rowEl: HTMLElement) => this.#onSelectedRowChanged(topTransferSizeEntries[index][0], rowEl, true),\n onMouseLeave: () => this.#onSelectedRowChanged(null, null, false),\n } as TableData}>\n `}\n ${LitHtml.html`<${Table.litTagName}\n .data=${{\n headers: [i18nString(UIStrings.columnThirdParty), i18nString(UIStrings.columnBlockingTime)],\n rows: topMainThreadTimeEntries.map(([entity, summary]) => [\n entity.name,\n i18n.TimeUtilities.millisToString(Platform.Timing.microSecondsToMilliSeconds(summary.mainThreadTime)),\n ]),\n onHoverRow: (index: number, rowEl: HTMLElement) => this.#onSelectedRowChanged(topMainThreadTimeEntries[index][0], rowEl, false),\n onClickRow: (index: number, rowEl: HTMLElement) => this.#onSelectedRowChanged(topMainThreadTimeEntries[index][0], rowEl, true),\n onMouseLeave: () => this.#onSelectedRowChanged(null, null, false),\n } as TableData}>\n `}\n
    \n \n
    `;\n // clang-format on\n }\n\n override render(): void {\n const insight = getThirdPartiesInsight(this.data.insights, this.data.navigationId);\n const entries = insight && [...insight.summaryByEntity.entries()].filter(kv => kv[0] !== insight.firstPartyEntity);\n const shouldShow = entries?.length;\n\n const matchesCategory = shouldRenderForCategory({\n activeCategory: this.data.activeCategory,\n insightCategory: this.insightCategory,\n });\n const output = shouldShow && matchesCategory ? this.#render(entries) : LitHtml.nothing;\n LitHtml.render(output, this.shadow, {host: this});\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-third-parties': ThirdParties;\n }\n}\n\ncustomElements.define('devtools-performance-third-parties', ThirdParties);\n"]} \ No newline at end of file diff --git a/public/panels/timeline/components/insights/Viewport.d.ts b/public/panels/timeline/components/insights/Viewport.d.ts index e34b6202f..536b22138 100644 --- a/public/panels/timeline/components/insights/Viewport.d.ts +++ b/public/panels/timeline/components/insights/Viewport.d.ts @@ -1,8 +1,8 @@ -import type * as TraceEngine from '../../../../models/trace/trace.js'; +import type * as Trace from '../../../../models/trace/trace.js'; import type * as Overlays from '../../overlays/overlays.js'; import { BaseInsight } from './Helpers.js'; import { InsightsCategories } from './types.js'; -export declare function getViewportInsight(insights: TraceEngine.Insights.Types.TraceInsightData | null, navigationId: string | null): TraceEngine.Insights.Types.InsightResults['Viewport'] | null; +export declare function getViewportInsight(insights: Trace.Insights.Types.TraceInsightSets | null, navigationId: string | null): Trace.Insights.Types.InsightResults['Viewport'] | null; export declare class Viewport extends BaseInsight { #private; static readonly litTagName: import("../../../../ui/lit-html/static.js").Static; diff --git a/public/panels/timeline/components/insights/Viewport.js b/public/panels/timeline/components/insights/Viewport.js index 25753095b..ff4d78411 100644 --- a/public/panels/timeline/components/insights/Viewport.js +++ b/public/panels/timeline/components/insights/Viewport.js @@ -24,7 +24,7 @@ export function getViewportInsight(insights, navigationId) { if (!insightsByNavigation) { return null; } - const viewportInsight = insightsByNavigation.Viewport; + const viewportInsight = insightsByNavigation.data.Viewport; if (viewportInsight instanceof Error) { return null; } @@ -66,7 +66,7 @@ export class Viewport extends BaseInsight { } render() { const viewportInsight = getViewportInsight(this.data.insights, this.data.navigationId); - const shouldShow = viewportInsight && !viewportInsight.mobileOptimized; + const shouldShow = viewportInsight && viewportInsight.mobileOptimized === false; const matchesCategory = shouldRenderForCategory({ activeCategory: this.data.activeCategory, insightCategory: this.insightCategory, diff --git a/public/panels/timeline/components/insights/Viewport.js.map b/public/panels/timeline/components/insights/Viewport.js.map index 606e1a5ee..2d4c34160 100644 --- a/public/panels/timeline/components/insights/Viewport.js.map +++ b/public/panels/timeline/components/insights/Viewport.js.map @@ -1 +1 @@ -{"version":3,"file":"Viewport.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/Viewport.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport type * as TraceEngine from '../../../../models/trace/trace.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\nimport type * as Overlays from '../../overlays/overlays.js';\n\nimport {BaseInsight, md, shouldRenderForCategory} from './Helpers.js';\nimport {NodeLink, type NodeLinkData} from './NodeLink.js';\nimport * as SidebarInsight from './SidebarInsight.js';\nimport {InsightsCategories} from './types.js';\n\nconst UIStrings = {\n /**\n * @description Text to tell the user how a viewport meta element can improve performance.\n */\n description: 'A viewport meta element not only optimizes your app for mobile screen sizes, ' +\n 'but also [prevents a 300 millisecond delay to user input](https://developer.chrome.com/blog/300ms-tap-delay-gone-away/).',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/components/insights/Viewport.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function getViewportInsight(\n insights: TraceEngine.Insights.Types.TraceInsightData|null,\n navigationId: string|null): TraceEngine.Insights.Types.InsightResults['Viewport']|null {\n if (!insights || !navigationId) {\n return null;\n }\n\n const insightsByNavigation = insights.get(navigationId);\n if (!insightsByNavigation) {\n return null;\n }\n\n const viewportInsight = insightsByNavigation.Viewport;\n if (viewportInsight instanceof Error) {\n return null;\n }\n return viewportInsight;\n}\n\nexport class Viewport extends BaseInsight {\n static readonly litTagName = LitHtml.literal`devtools-performance-viewport`;\n override insightCategory: InsightsCategories = InsightsCategories.INP;\n override internalName: string = 'viewport';\n override userVisibleTitle: string = 'Mobile-optimized viewport';\n\n override createOverlays(): Overlays.Overlays.TimelineOverlay[] {\n // TODO(b/351757418): create overlay for synthetic input delay events\n return [];\n }\n\n #render(data: TraceEngine.Insights.Types.InsightResults['Viewport']): LitHtml.TemplateResult {\n const backendNodeId = data.viewportEvent?.args.data.node_id;\n\n // clang-format off\n return LitHtml.html`\n
    \n <${SidebarInsight.SidebarInsight.litTagName} .data=${{\n title: this.userVisibleTitle,\n expanded: this.isActive(),\n } as SidebarInsight.InsightDetails}\n @insighttoggleclick=${this.onSidebarClick}>\n
    \n ${md(i18nString(UIStrings.description))}\n
    \n
    \n ${backendNodeId !== undefined ? LitHtml.html`<${NodeLink.litTagName}\n .data=${{\n backendNodeId,\n options: {tooltip: data.viewportEvent?.args.data.content},\n } as NodeLinkData}>\n ` : LitHtml.nothing}\n
    \n \n
    `;\n // clang-format on\n }\n\n override render(): void {\n const viewportInsight = getViewportInsight(this.data.insights, this.data.navigationId);\n const shouldShow = viewportInsight && !viewportInsight.mobileOptimized;\n\n const matchesCategory = shouldRenderForCategory({\n activeCategory: this.data.activeCategory,\n insightCategory: this.insightCategory,\n });\n const output = shouldShow && matchesCategory ? this.#render(viewportInsight) : LitHtml.nothing;\n LitHtml.render(output, this.shadow, {host: this});\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-viewport': Viewport;\n }\n}\n\ncustomElements.define('devtools-performance-viewport', Viewport);\n"]} \ No newline at end of file +{"version":3,"file":"Viewport.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/components/insights/Viewport.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport type * as Trace from '../../../../models/trace/trace.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\nimport type * as Overlays from '../../overlays/overlays.js';\n\nimport {BaseInsight, md, shouldRenderForCategory} from './Helpers.js';\nimport {NodeLink, type NodeLinkData} from './NodeLink.js';\nimport * as SidebarInsight from './SidebarInsight.js';\nimport {InsightsCategories} from './types.js';\n\nconst UIStrings = {\n /**\n * @description Text to tell the user how a viewport meta element can improve performance.\n */\n description: 'A viewport meta element not only optimizes your app for mobile screen sizes, ' +\n 'but also [prevents a 300 millisecond delay to user input](https://developer.chrome.com/blog/300ms-tap-delay-gone-away/).',\n};\n\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/components/insights/Viewport.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function getViewportInsight(insights: Trace.Insights.Types.TraceInsightSets|null, navigationId: string|null):\n Trace.Insights.Types.InsightResults['Viewport']|null {\n if (!insights || !navigationId) {\n return null;\n }\n\n const insightsByNavigation = insights.get(navigationId);\n if (!insightsByNavigation) {\n return null;\n }\n\n const viewportInsight = insightsByNavigation.data.Viewport;\n if (viewportInsight instanceof Error) {\n return null;\n }\n return viewportInsight;\n}\n\nexport class Viewport extends BaseInsight {\n static readonly litTagName = LitHtml.literal`devtools-performance-viewport`;\n override insightCategory: InsightsCategories = InsightsCategories.INP;\n override internalName: string = 'viewport';\n override userVisibleTitle: string = 'Mobile-optimized viewport';\n\n override createOverlays(): Overlays.Overlays.TimelineOverlay[] {\n // TODO(b/351757418): create overlay for synthetic input delay events\n return [];\n }\n\n #render(data: Trace.Insights.Types.InsightResults['Viewport']): LitHtml.TemplateResult {\n const backendNodeId = data.viewportEvent?.args.data.node_id;\n\n // clang-format off\n return LitHtml.html`\n
    \n <${SidebarInsight.SidebarInsight.litTagName} .data=${{\n title: this.userVisibleTitle,\n expanded: this.isActive(),\n } as SidebarInsight.InsightDetails}\n @insighttoggleclick=${this.onSidebarClick}>\n
    \n ${md(i18nString(UIStrings.description))}\n
    \n
    \n ${backendNodeId !== undefined ? LitHtml.html`<${NodeLink.litTagName}\n .data=${{\n backendNodeId,\n options: {tooltip: data.viewportEvent?.args.data.content},\n } as NodeLinkData}>\n ` : LitHtml.nothing}\n
    \n \n
    `;\n // clang-format on\n }\n\n override render(): void {\n const viewportInsight = getViewportInsight(this.data.insights, this.data.navigationId);\n const shouldShow = viewportInsight && viewportInsight.mobileOptimized === false;\n\n const matchesCategory = shouldRenderForCategory({\n activeCategory: this.data.activeCategory,\n insightCategory: this.insightCategory,\n });\n const output = shouldShow && matchesCategory ? this.#render(viewportInsight) : LitHtml.nothing;\n LitHtml.render(output, this.shadow, {host: this});\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-performance-viewport': Viewport;\n }\n}\n\ncustomElements.define('devtools-performance-viewport', Viewport);\n"]} \ No newline at end of file diff --git a/public/panels/timeline/components/insights/sidebarInsight.css.js b/public/panels/timeline/components/insights/sidebarInsight.css.js index bd995b9a2..ba3816eee 100644 --- a/public/panels/timeline/components/insights/sidebarInsight.css.js +++ b/public/panels/timeline/components/insights/sidebarInsight.css.js @@ -16,10 +16,10 @@ styles.replaceSync( position: relative; width: auto; height: auto; - margin: 10px 0; + margin: var(--sys-size-6) 0; border-radius: var(--sys-shape-corner-extra-small); overflow: hidden; - border: 1px solid var(--sys-color-divider); + border: var(--sys-size-1) solid var(--sys-color-divider); background-color: var(--sys-color-base); &.closed { @@ -28,7 +28,7 @@ styles.replaceSync( } header { - padding: 10px; + padding: var(--sys-size-5) var(--sys-size-6); h3 { font: var(--sys-typescale-body4-medium); @@ -38,8 +38,8 @@ styles.replaceSync( .insight-hover-icon { position: absolute; - top: 10px; - right: 10px; + top: var(--sys-size-5); + right: var(--sys-size-5); border: none; width: var(--sys-size-9); height: var(--sys-size-9); @@ -63,7 +63,7 @@ styles.replaceSync( } .insight-body { - padding: 0 10px; + padding: var(--sys-size-5) var(--sys-size-6); } .insight-title { @@ -72,8 +72,7 @@ styles.replaceSync( } .insight-description { - border-bottom: 1px solid var(--sys-color-divider); - padding-bottom: 10px; + border-bottom: var(--sys-size-1) solid var(--sys-color-divider); } .link { @@ -102,7 +101,7 @@ dd.dl-title { .insight-entry { font: var(--sys-typescale-body4-medium); - padding-block: 2px; + padding-block: var(--sys-size-3); display: flex; align-items: center; } @@ -111,7 +110,7 @@ dd.dl-title { display: grid; grid-template-columns: 1fr 1fr; align-items: center; - padding-block: 10px; + padding: var(--sys-size-5) var(--sys-size-6); } .element-img { @@ -143,7 +142,7 @@ ul.insight-icon-results { display: flex; align-items: flex-start; justify-content: flex-start; - gap: 4px; + gap: var(--sys-size-3); span { /* push the text down to align slightly better with the icons */ @@ -152,6 +151,27 @@ ul.insight-icon-results { } } +ul.url-list { + list-style-position: inside; + padding: 0; + + li { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } +} + +.devtools-link { + cursor: pointer; + text-decoration: underline; + color: var(--sys-color-primary); +} + +.devtools-link.invalid-link { + color: var(--sys-color-state-disabled); +} + /*# sourceURL=sidebarInsight.css */ `); diff --git a/public/panels/timeline/components/insights/table.css.js b/public/panels/timeline/components/insights/table.css.js index de700737d..b7975164d 100644 --- a/public/panels/timeline/components/insights/table.css.js +++ b/public/panels/timeline/components/insights/table.css.js @@ -14,6 +14,13 @@ styles.replaceSync( table { width: 100%; padding: 5px 0; + border-collapse: collapse; + /* TODO(cjamcl): figure out the styling. This is from the mocks but other stuff needs to change too else + it looks awful. */ + /* + border: 1px solid #D3E3FD; + border-radius: 4px; */ + margin: 5px 0; } table tr > * { @@ -24,8 +31,14 @@ table tr > *:first-child { text-align: left; } +table.hoverable tbody tr:hover, +table.hoverable tbody tr.selected { + background-color: var(--app-color-performance-sidebar-table-row-hover); +} + table th[scope="row"] { font-weight: normal; + padding: 3px 0; } td { diff --git a/public/panels/timeline/components/liveMetricsView.css.js b/public/panels/timeline/components/liveMetricsView.css.js index f1eded9b8..43a906e36 100644 --- a/public/panels/timeline/components/liveMetricsView.css.js +++ b/public/panels/timeline/components/liveMetricsView.css.js @@ -18,6 +18,7 @@ styles.replaceSync( font-size: var(--sys-typescale-body4-size); line-height: var(--sys-typescale-body4-line-height); font-weight: var(--ref-typeface-weight-regular); + user-select: text; } .live-metrics-view { @@ -119,9 +120,9 @@ styles.replaceSync( } .related-element-info { - overflow: hidden; text-wrap: nowrap; margin-top: 8px; + display: flex; } .related-element-label { @@ -132,6 +133,8 @@ styles.replaceSync( background-color: var(--sys-color-cdt-base-container); border-radius: 2px; padding: 0 2px; + min-width: 0; + margin-left: 4px; } .interactions-section { @@ -176,9 +179,9 @@ styles.replaceSync( } .interaction-node { - overflow: hidden; flex-grow: 1; margin-right: 32px; + min-width: 0; } .interaction-info { diff --git a/public/panels/timeline/components/sidebarAnnotationsTab.css.js b/public/panels/timeline/components/sidebarAnnotationsTab.css.js index 6637760ea..30f35febc 100644 --- a/public/panels/timeline/components/sidebarAnnotationsTab.css.js +++ b/public/panels/timeline/components/sidebarAnnotationsTab.css.js @@ -50,7 +50,7 @@ styles.replaceSync( display: flex; flex-direction: column; align-items: flex-start; - word-break: break-all; + word-break: break-word; padding-top: 15px; gap: 6px; } @@ -59,6 +59,8 @@ styles.replaceSync( padding: 4px 8px; border-radius: 10px; font-weight: bold; + /* The identifier text will always be black to match the event title in the flame chart */ + color: var(--app-color-performance-sidebar-label-text); &.time-range { background-color: var(--app-color-performance-sidebar-time-range); diff --git a/public/panels/timeline/components/sidebarInsightsTab.css.js b/public/panels/timeline/components/sidebarInsightsTab.css.js index ba8bca9b1..4de076a0d 100644 --- a/public/panels/timeline/components/sidebarInsightsTab.css.js +++ b/public/panels/timeline/components/sidebarInsightsTab.css.js @@ -17,6 +17,7 @@ styles.replaceSync( flex-grow: 1; } +/* TODO(crbug.com/366049346): rename */ .navigations-wrapper { display: flex; flex-flow: column nowrap; diff --git a/public/panels/timeline/components/sidebarSingleNavigation.css.js b/public/panels/timeline/components/sidebarSingleNavigation.css.js index eff3593c4..4b67e8091 100644 --- a/public/panels/timeline/components/sidebarSingleNavigation.css.js +++ b/public/panels/timeline/components/sidebarSingleNavigation.css.js @@ -24,10 +24,6 @@ styles.replaceSync( .metric { margin-top: 10px; flex: 1; - - &:hover { - transform: scale(1.05); - } } .metric-value { diff --git a/public/panels/timeline/extensions/ExtensionUI.d.ts b/public/panels/timeline/extensions/ExtensionUI.d.ts index c2d3a8929..d85c620d0 100644 --- a/public/panels/timeline/extensions/ExtensionUI.d.ts +++ b/public/panels/timeline/extensions/ExtensionUI.d.ts @@ -1,2 +1,2 @@ -import type * as TraceEngine from '../../../models/trace/trace.js'; -export declare function extensionEntryColor(event: TraceEngine.Types.Extensions.SyntheticExtensionEntry): string; +import type * as Trace from '../../../models/trace/trace.js'; +export declare function extensionEntryColor(event: Trace.Types.Extensions.SyntheticExtensionEntry): string; diff --git a/public/panels/timeline/extensions/ExtensionUI.js.map b/public/panels/timeline/extensions/ExtensionUI.js.map index adc96ad9d..b64d665e5 100644 --- a/public/panels/timeline/extensions/ExtensionUI.js.map +++ b/public/panels/timeline/extensions/ExtensionUI.js.map @@ -1 +1 @@ -{"version":3,"file":"ExtensionUI.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/extensions/ExtensionUI.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAG7B,OAAO,KAAK,YAAY,MAAM,mDAAmD,CAAC;AAElF,MAAM,UAAU,mBAAmB,CAAC,KAA2D;IAC7F,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;IAC/B,gEAAgE;IAChE,8CAA8C;IAC9C,IAAI,UAAU,GAAG,yBAAyB,CAAC;IAC3C,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,SAAS;YACZ,UAAU,GAAG,yBAAyB,CAAC;YACvC,MAAM;QACR,KAAK,eAAe;YAClB,UAAU,GAAG,yBAAyB,CAAC;YACvC,MAAM;QACR,KAAK,cAAc;YACjB,UAAU,GAAG,yBAAyB,CAAC;YACvC,MAAM;QACR,KAAK,WAAW;YACd,UAAU,GAAG,2BAA2B,CAAC;YACzC,MAAM;QACR,KAAK,iBAAiB;YACpB,UAAU,GAAG,2BAA2B,CAAC;YACzC,MAAM;QACR,KAAK,gBAAgB;YACnB,UAAU,GAAG,2BAA2B,CAAC;YACzC,MAAM;QACR,KAAK,UAAU;YACb,UAAU,GAAG,0BAA0B,CAAC;YACxC,MAAM;QACR,KAAK,gBAAgB;YACnB,UAAU,GAAG,0BAA0B,CAAC;YACxC,MAAM;QACR,KAAK,eAAe;YAClB,UAAU,GAAG,0BAA0B,CAAC;YACxC,MAAM;QACR,KAAK,OAAO;YACV,UAAU,GAAG,uBAAuB,CAAC;YACrC,MAAM;IACV,CAAC;IACD,OAAO,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;AAC3E,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as TraceEngine from '../../../models/trace/trace.js';\nimport * as ThemeSupport from '../../../ui/legacy/theme_support/theme_support.js';\n\nexport function extensionEntryColor(event: TraceEngine.Types.Extensions.SyntheticExtensionEntry): string {\n const color = event.args.color;\n // Use a default value for when the color of the extension entry\n // was not passed or was set an unknown value.\n let themeColor = '--ref-palette-primary70';\n switch (color) {\n case 'primary':\n themeColor = '--ref-palette-primary70';\n break;\n case 'primary-light':\n themeColor = '--ref-palette-primary80';\n break;\n case 'primary-dark':\n themeColor = '--ref-palette-primary60';\n break;\n case 'secondary':\n themeColor = '--ref-palette-secondary70';\n break;\n case 'secondary-light':\n themeColor = '--ref-palette-secondary80';\n break;\n case 'secondary-dark':\n themeColor = '--ref-palette-secondary60';\n break;\n case 'tertiary':\n themeColor = '--ref-palette-tertiary70';\n break;\n case 'tertiary-light':\n themeColor = '--ref-palette-tertiary80';\n break;\n case 'tertiary-dark':\n themeColor = '--ref-palette-tertiary60';\n break;\n case 'error':\n themeColor = '--ref-palette-error50';\n break;\n }\n return ThemeSupport.ThemeSupport.instance().getComputedValue(themeColor);\n}\n"]} \ No newline at end of file +{"version":3,"file":"ExtensionUI.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/extensions/ExtensionUI.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAG7B,OAAO,KAAK,YAAY,MAAM,mDAAmD,CAAC;AAElF,MAAM,UAAU,mBAAmB,CAAC,KAAqD;IACvF,MAAM,KAAK,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;IAC/B,gEAAgE;IAChE,8CAA8C;IAC9C,IAAI,UAAU,GAAG,yBAAyB,CAAC;IAC3C,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,SAAS;YACZ,UAAU,GAAG,yBAAyB,CAAC;YACvC,MAAM;QACR,KAAK,eAAe;YAClB,UAAU,GAAG,yBAAyB,CAAC;YACvC,MAAM;QACR,KAAK,cAAc;YACjB,UAAU,GAAG,yBAAyB,CAAC;YACvC,MAAM;QACR,KAAK,WAAW;YACd,UAAU,GAAG,2BAA2B,CAAC;YACzC,MAAM;QACR,KAAK,iBAAiB;YACpB,UAAU,GAAG,2BAA2B,CAAC;YACzC,MAAM;QACR,KAAK,gBAAgB;YACnB,UAAU,GAAG,2BAA2B,CAAC;YACzC,MAAM;QACR,KAAK,UAAU;YACb,UAAU,GAAG,0BAA0B,CAAC;YACxC,MAAM;QACR,KAAK,gBAAgB;YACnB,UAAU,GAAG,0BAA0B,CAAC;YACxC,MAAM;QACR,KAAK,eAAe;YAClB,UAAU,GAAG,0BAA0B,CAAC;YACxC,MAAM;QACR,KAAK,OAAO;YACV,UAAU,GAAG,uBAAuB,CAAC;YACrC,MAAM;IACV,CAAC;IACD,OAAO,YAAY,CAAC,YAAY,CAAC,QAAQ,EAAE,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;AAC3E,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Trace from '../../../models/trace/trace.js';\nimport * as ThemeSupport from '../../../ui/legacy/theme_support/theme_support.js';\n\nexport function extensionEntryColor(event: Trace.Types.Extensions.SyntheticExtensionEntry): string {\n const color = event.args.color;\n // Use a default value for when the color of the extension entry\n // was not passed or was set an unknown value.\n let themeColor = '--ref-palette-primary70';\n switch (color) {\n case 'primary':\n themeColor = '--ref-palette-primary70';\n break;\n case 'primary-light':\n themeColor = '--ref-palette-primary80';\n break;\n case 'primary-dark':\n themeColor = '--ref-palette-primary60';\n break;\n case 'secondary':\n themeColor = '--ref-palette-secondary70';\n break;\n case 'secondary-light':\n themeColor = '--ref-palette-secondary80';\n break;\n case 'secondary-dark':\n themeColor = '--ref-palette-secondary60';\n break;\n case 'tertiary':\n themeColor = '--ref-palette-tertiary70';\n break;\n case 'tertiary-light':\n themeColor = '--ref-palette-tertiary80';\n break;\n case 'tertiary-dark':\n themeColor = '--ref-palette-tertiary60';\n break;\n case 'error':\n themeColor = '--ref-palette-error50';\n break;\n }\n return ThemeSupport.ThemeSupport.instance().getComputedValue(themeColor);\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/fixtures/traces/enhanced-traces.json.gz b/public/panels/timeline/fixtures/traces/enhanced-traces.json.gz index f4cc39680..f45f97ab7 100644 Binary files a/public/panels/timeline/fixtures/traces/enhanced-traces.json.gz and b/public/panels/timeline/fixtures/traces/enhanced-traces.json.gz differ diff --git a/public/panels/timeline/fixtures/traces/font-display.json.gz b/public/panels/timeline/fixtures/traces/font-display.json.gz new file mode 100644 index 000000000..83036edc1 Binary files /dev/null and b/public/panels/timeline/fixtures/traces/font-display.json.gz differ diff --git a/public/panels/timeline/overlays/OverlaysImpl.d.ts b/public/panels/timeline/overlays/OverlaysImpl.d.ts index d605dca5b..ce35e64b8 100644 --- a/public/panels/timeline/overlays/OverlaysImpl.d.ts +++ b/public/panels/timeline/overlays/OverlaysImpl.d.ts @@ -1,7 +1,7 @@ -import * as TraceEngine from '../../../models/trace/trace.js'; +import * as Trace from '../../../models/trace/trace.js'; import type * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js'; import * as Components from './components/components.js'; -export declare const LAYOUT_SHIFT_SYNTHETIC_DURATION: TraceEngine.Types.Timing.MicroSeconds; +export declare const LAYOUT_SHIFT_SYNTHETIC_DURATION: Trace.Types.Timing.MicroSeconds; /** * Represents which flamechart an entry is rendered in. * We need to know this because when we place an overlay for an entry we need @@ -17,7 +17,7 @@ export type EntryChartLocation = 'main' | 'network'; * support TimelineFrame instances (which themselves will be removed from the * codebase.) */ -export type OverlayEntry = TraceEngine.Types.TraceEvents.TraceEventData | TraceEngine.Types.TraceEvents.LegacyTimelineFrame; +export type OverlayEntry = Trace.Types.Events.Event | Trace.Types.Events.LegacyTimelineFrame; /** * Represents when a user has selected an entry in the timeline */ @@ -49,13 +49,21 @@ export interface EntriesLink { entryFrom: OverlayEntry; entryTo?: OverlayEntry; } +/** + * Represents an object created when a user double click an entry and before + * creating a link between two entries. + */ +export interface CreateEntriesLink { + type: 'ENTRIES_LINK_CREATE_BUTTON'; + entry: OverlayEntry; +} /** * Represents a time range on the trace. Also used when the user shift+clicks * and drags to create a time range. */ export interface TimeRangeLabel { type: 'TIME_RANGE'; - bounds: TraceEngine.Types.Timing.TraceWindowMicroSeconds; + bounds: Trace.Types.Timing.TraceWindowMicroSeconds; label: string; showDuration: boolean; } @@ -63,7 +71,7 @@ export interface TimeRangeLabel { * Given a list of overlays, this method will calculate the smallest possible * trace window that will contain all of the overlays. */ -export declare function traceWindowContainingOverlays(overlays: TimelineOverlay[]): TraceEngine.Types.Timing.TraceWindowMicroSeconds; +export declare function traceWindowContainingOverlays(overlays: TimelineOverlay[]): Trace.Types.Timing.TraceWindowMicroSeconds; /** * Get a list of entries for a given overlay. */ @@ -71,6 +79,7 @@ export declare function entriesForOverlay(overlay: TimelineOverlay): readonly Ov export declare function chartForEntry(entry: OverlayEntry): EntryChartLocation; export declare function isTimeRangeLabel(annotation: TimelineOverlay): annotation is TimeRangeLabel; export declare function isEntriesLink(annotation: TimelineOverlay): annotation is EntriesLink; +export declare function isEntryLabel(annotation: TimelineOverlay): annotation is EntryLabel; /** * Used to highlight with a red-candy stripe a time range. It takes an entry * because this entry is the row that will be used to place the candy stripe, @@ -78,8 +87,8 @@ export declare function isEntriesLink(annotation: TimelineOverlay): annotation i */ export interface CandyStripedTimeRange { type: 'CANDY_STRIPED_TIME_RANGE'; - bounds: TraceEngine.Types.Timing.TraceWindowMicroSeconds; - entry: TraceEngine.Types.TraceEvents.TraceEventData; + bounds: Trace.Types.Timing.TraceWindowMicroSeconds; + entry: Trace.Types.Events.Event; } /** * Represents a timespan on a trace broken down into parts. Each part has a label to it. @@ -88,22 +97,22 @@ export interface CandyStripedTimeRange { export interface TimespanBreakdown { type: 'TIMESPAN_BREAKDOWN'; sections: Array; - entry?: TraceEngine.Types.TraceEvents.TraceEventData; + entry?: Trace.Types.Events.Event; } export interface CursorTimestampMarker { type: 'CURSOR_TIMESTAMP_MARKER'; - timestamp: TraceEngine.Types.Timing.MicroSeconds; + timestamp: Trace.Types.Timing.MicroSeconds; } /** * All supported overlay types. Expected to grow in time! */ -export type TimelineOverlay = EntrySelected | EntryOutline | TimeRangeLabel | EntryLabel | EntriesLink | TimespanBreakdown | CursorTimestampMarker | CandyStripedTimeRange; +export type TimelineOverlay = EntrySelected | EntryOutline | TimeRangeLabel | EntryLabel | EntriesLink | CreateEntriesLink | TimespanBreakdown | CursorTimestampMarker | CandyStripedTimeRange; /** * Denotes overlays that are singletons; only one of these will be allowed to * exist at any given time. If one exists and the add() method is called, the * new overlay will replace the existing one. */ -type SingletonOverlay = EntrySelected | CursorTimestampMarker; +type SingletonOverlay = EntrySelected | CursorTimestampMarker | CreateEntriesLink; export declare function overlayIsSingleton(overlay: TimelineOverlay): overlay is SingletonOverlay; /** * The dimensions each flame chart reports. Note that in the current UI they @@ -124,10 +133,10 @@ export interface TimelineCharts { networkProvider: PerfUI.FlameChart.FlameChartDataProvider; } export interface OverlayEntryQueries { - isEntryCollapsedByUser: (entry: TraceEngine.Types.TraceEvents.TraceEventData) => boolean; - firstVisibleParentForEntry: (entry: TraceEngine.Types.TraceEvents.TraceEventData) => TraceEngine.Types.TraceEvents.TraceEventData | null; + isEntryCollapsedByUser: (entry: Trace.Types.Events.Event) => boolean; + firstVisibleParentForEntry: (entry: Trace.Types.Events.Event) => Trace.Types.Events.Event | null; } -export type UpdateAction = 'Remove' | 'Update'; +export type UpdateAction = 'Remove' | 'Update' | 'CreateLink'; export declare class AnnotationOverlayActionEvent extends Event { overlay: TimelineOverlay; action: UpdateAction; @@ -165,6 +174,7 @@ export declare class Overlays extends EventTarget { * old overlay and re-creating the new one. */ updateExisting(existingOverlay: T, newData: Partial): void; + enterLabelEditMode(overlay: EntryLabel): void; /** * @returns the list of overlays associated with a given entry. */ @@ -192,7 +202,7 @@ export declare class Overlays extends EventTarget { * Update the visible window of the UI. * IMPORTANT: this does not trigger a re-draw. You must call the render() method manually. */ - updateVisibleWindow(visibleWindow: TraceEngine.Types.Timing.TraceWindowMicroSeconds): void; + updateVisibleWindow(visibleWindow: Trace.Types.Timing.TraceWindowMicroSeconds): void; /** * Clears all overlays and all data. Call this when the trace is changing * (e.g. the user has imported/recorded a new trace) and we need to start from @@ -258,5 +268,5 @@ export declare class Overlays extends EventTarget { * helper exists to return a consistent set of timings regardless of the type * of entry. */ -export declare function timingsForOverlayEntry(entry: OverlayEntry): TraceEngine.Helpers.Timing.EventTimingsData; +export declare function timingsForOverlayEntry(entry: OverlayEntry): Trace.Helpers.Timing.EventTimingsData; export {}; diff --git a/public/panels/timeline/overlays/OverlaysImpl.js b/public/panels/timeline/overlays/OverlaysImpl.js index d7be2d870..9298d1cee 100644 --- a/public/panels/timeline/overlays/OverlaysImpl.js +++ b/public/panels/timeline/overlays/OverlaysImpl.js @@ -3,14 +3,14 @@ // found in the LICENSE file. import * as Common from '../../../core/common/common.js'; import * as Platform from '../../../core/platform/platform.js'; -import * as TraceEngine from '../../../models/trace/trace.js'; +import * as Trace from '../../../models/trace/trace.js'; import * as Components from './components/components.js'; // Bit of a hack: LayoutShifts are instant events, so have no duration. But // OPP doesn't do well at making tiny events easy to spot and click. So we // set it to a small duration so that the user is able to see and click // them more easily. Long term we will explore a better UI solution to // allow us to do this properly and not hack around it. -export const LAYOUT_SHIFT_SYNTHETIC_DURATION = TraceEngine.Types.Timing.MicroSeconds(5_000); +export const LAYOUT_SHIFT_SYNTHETIC_DURATION = Trace.Types.Timing.MicroSeconds(5_000); /** * Below the network track there is a resize bar the user can click and drag. */ @@ -20,8 +20,8 @@ const NETWORK_RESIZE_ELEM_HEIGHT_PX = 8; * trace window that will contain all of the overlays. */ export function traceWindowContainingOverlays(overlays) { - let minTime = TraceEngine.Types.Timing.MicroSeconds(Number.POSITIVE_INFINITY); - let maxTime = TraceEngine.Types.Timing.MicroSeconds(Number.NEGATIVE_INFINITY); + let minTime = Trace.Types.Timing.MicroSeconds(Number.POSITIVE_INFINITY); + let maxTime = Trace.Types.Timing.MicroSeconds(Number.NEGATIVE_INFINITY); for (const overlay of overlays) { const windowForOverlay = traceWindowForOverlay(overlay); if (windowForOverlay.min < minTime) { @@ -31,7 +31,7 @@ export function traceWindowContainingOverlays(overlays) { maxTime = windowForOverlay.max; } } - return TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(minTime, maxTime); + return Trace.Helpers.Timing.traceWindowFromMicroSeconds(minTime, maxTime); } function traceWindowForOverlay(overlay) { const overlayMinBounds = []; @@ -75,6 +75,12 @@ function traceWindowForOverlay(overlay) { } break; } + case 'ENTRIES_LINK_CREATE_BUTTON': { + const timings = timingsForOverlayEntry(overlay.entry); + overlayMinBounds.push(timings.startTime); + overlayMaxBounds.push(timings.endTime); + break; + } case 'TIMESPAN_BREAKDOWN': { if (overlay.entry) { const timings = timingsForOverlayEntry(overlay.entry); @@ -102,9 +108,9 @@ function traceWindowForOverlay(overlay) { default: Platform.TypeScriptUtilities.assertNever(overlay, `Unexpected overlay ${overlay}`); } - const min = TraceEngine.Types.Timing.MicroSeconds(Math.min(...overlayMinBounds)); - const max = TraceEngine.Types.Timing.MicroSeconds(Math.max(...overlayMaxBounds)); - return TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(min, max); + const min = Trace.Types.Timing.MicroSeconds(Math.min(...overlayMinBounds)); + const max = Trace.Types.Timing.MicroSeconds(Math.max(...overlayMaxBounds)); + return Trace.Helpers.Timing.traceWindowFromMicroSeconds(min, max); } /** * Get a list of entries for a given overlay. @@ -135,6 +141,10 @@ export function entriesForOverlay(overlay) { } break; } + case 'ENTRIES_LINK_CREATE_BUTTON': { + entries.push(overlay.entry); + break; + } case 'TIMESPAN_BREAKDOWN': { if (overlay.entry) { entries.push(overlay.entry); @@ -154,7 +164,7 @@ export function entriesForOverlay(overlay) { return entries; } export function chartForEntry(entry) { - if (TraceEngine.Types.TraceEvents.isNetworkTrackEntry(entry)) { + if (Trace.Types.Events.isNetworkTrackEntry(entry)) { return 'network'; } return 'main'; @@ -165,8 +175,12 @@ export function isTimeRangeLabel(annotation) { export function isEntriesLink(annotation) { return annotation.type === 'ENTRIES_LINK'; } +export function isEntryLabel(annotation) { + return annotation.type === 'ENTRY_LABEL'; +} export function overlayIsSingleton(overlay) { - return overlay.type === 'CURSOR_TIMESTAMP_MARKER' || overlay.type === 'ENTRY_SELECTED'; + return overlay.type === 'CURSOR_TIMESTAMP_MARKER' || overlay.type === 'ENTRY_SELECTED' || + overlay.type === 'ENTRIES_LINK_CREATE_BUTTON'; } export class AnnotationOverlayActionEvent extends Event { overlay; @@ -317,6 +331,16 @@ export class Overlays extends EventTarget { existingOverlay[k] = value; } } + enterLabelEditMode(overlay) { + // Entry edit state can be triggered from outside the label component by clicking on the + // Entry that already has a label. Instead of creating a new label, set the existing entry + // label into an editable state. + const element = this.#overlaysToElements.get(overlay); + const component = element?.querySelector('devtools-entry-label-overlay'); + if (component) { + component.setLabelEditabilityAndRemoveEmptyLabel(true); + } + } /** * @returns the list of overlays associated with a given entry. */ @@ -406,15 +430,15 @@ export class Overlays extends EventTarget { const timeRangeOverlays = []; for (const [overlay, existingElement] of this.#overlaysToElements) { const element = existingElement || this.#createElementForNewOverlay(overlay); - if (existingElement) { - this.#updateOverlayElementIfRequired(overlay, element); - } - else { + if (!existingElement) { // This is a new overlay, so we have to store the element and add it to the DOM. this.#overlaysToElements.set(overlay, element); this.#overlaysContainer.appendChild(element); } + // Now we position the overlay on the timeline. this.#positionOverlay(overlay, element); + // And now we give every overlay a chance to react to its new position, if it needs to + this.#updateOverlayElementAfterPositioning(overlay, element); if (overlay.type === 'TIME_RANGE') { timeRangeOverlays.push(overlay); } @@ -445,7 +469,7 @@ export class Overlays extends EventTarget { // Walk through subsequent overlays and find stop when you find the next one that does not overlap. for (let j = i + 1; j < overlaysSorted.length; j++) { const next = overlaysSorted[j]; - const currentAndNextOverlap = TraceEngine.Helpers.Timing.boundsIncludeTimeRange({ + const currentAndNextOverlap = Trace.Helpers.Timing.boundsIncludeTimeRange({ bounds: current.bounds, timeRange: next.bounds, }); @@ -508,10 +532,6 @@ export class Overlays extends EventTarget { this.#setOverlayElementVisibility(element, !annotationsAreHidden); } this.#positionTimeRangeOverlay(overlay, element); - const component = element.querySelector('devtools-time-range-overlay'); - if (component) { - component.afterOverlayUpdate(); - } break; } case 'ENTRY_LABEL': { @@ -536,31 +556,45 @@ export class Overlays extends EventTarget { this.#setOverlayElementVisibility(element, false); break; } - // If either entry is in a track that the user has collapsed, we do not show the connection at all. + // If both entries are in collapsed tracks, we hide the overlay completely. const fromEntryInCollapsedTrack = this.#entryIsInCollapsedTrack(entriesToConnect.entryFrom); const toEntryInCollapsedTrack = entriesToConnect.entryTo && this.#entryIsInCollapsedTrack(entriesToConnect.entryTo); - if (fromEntryInCollapsedTrack || toEntryInCollapsedTrack) { + const bothEntriesInCollapsedTrack = Boolean(fromEntryInCollapsedTrack && toEntryInCollapsedTrack); + if (bothEntriesInCollapsedTrack) { this.#setOverlayElementVisibility(element, false); - break; + return; } const isVisible = !annotationsAreHidden; this.#setOverlayElementVisibility(element, isVisible); if (isVisible) { this.#positionEntriesLinkOverlay(overlay, element, entriesToConnect); + // If either entry (but not both) is in a track that the user has collapsed, we do not + // show the connection at all, but we still show the borders around + // the entry. So in this case we mark the overlay as visible, but + // tell it to not draw the arrow. + const hideArrow = Boolean(fromEntryInCollapsedTrack || toEntryInCollapsedTrack); + const component = element.querySelector('devtools-entries-link-overlay'); + if (component) { + component.hideArrow = hideArrow; + } + } + break; + } + case 'ENTRIES_LINK_CREATE_BUTTON': { + const isVisible = this.entryIsVisibleOnChart(overlay.entry); + this.#setOverlayElementVisibility(element, isVisible); + if (isVisible) { + this.#positionCreateEntriesLinkOverlay(overlay, element); } break; } case 'TIMESPAN_BREAKDOWN': { this.#positionTimespanBreakdownOverlay(overlay, element); - const component = element.querySelector('devtools-timespan-breakdown-overlay'); - if (component) { - component.afterOverlayUpdate(); - } // TODO: Have the timespan squeeze instead. if (overlay.entry) { const { visibleWindow } = this.#dimensions.trace; const isVisible = Boolean(visibleWindow && this.#entryIsVerticallyVisibleOnChart(overlay.entry) && - TraceEngine.Helpers.Timing.boundsIncludeTimeRange({ + Trace.Helpers.Timing.boundsIncludeTimeRange({ bounds: visibleWindow, timeRange: overlay.sections[0].bounds, })); @@ -572,7 +606,7 @@ export class Overlays extends EventTarget { const { visibleWindow } = this.#dimensions.trace; // Only update the position if the timestamp of this marker is within // the visible bounds. - const isVisible = Boolean(visibleWindow && TraceEngine.Helpers.Timing.timestampIsInBounds(visibleWindow, overlay.timestamp)); + const isVisible = Boolean(visibleWindow && Trace.Helpers.Timing.timestampIsInBounds(visibleWindow, overlay.timestamp)); this.#setOverlayElementVisibility(element, isVisible); if (isVisible) { this.#positionTimestampMarker(overlay, element); @@ -584,7 +618,7 @@ export class Overlays extends EventTarget { // If the bounds of this overlay are not within the visible bounds, we // can skip updating its position and just hide it. const isVisible = Boolean(visibleWindow && this.#entryIsVerticallyVisibleOnChart(overlay.entry) && - TraceEngine.Helpers.Timing.boundsIncludeTimeRange({ + Trace.Helpers.Timing.boundsIncludeTimeRange({ bounds: visibleWindow, timeRange: overlay.bounds, })); @@ -638,27 +672,37 @@ export class Overlays extends EventTarget { } // Handle vertical positioning based on the entry's vertical position. if (overlay.entry) { - const chartName = chartForEntry(overlay.entry); - if (chartName === 'network') { - const y = this.yPixelForEventOnChart(overlay.entry); - if (y === null) { - return; - } - // Max height for the overlay box. - const MAX_BOX_HEIGHT = 50; - // Some padding so the box hovers just on top. - const PADDING = 7; - // Where the timespan breakdown should sit. Slightly on top of the entry. - const bottom = y - PADDING; - // Available space between the bottom of the overlay and top of the chart. - const minSpace = Math.max(bottom, 0); - // Contrain height to available space. - const height = Math.min(MAX_BOX_HEIGHT, minSpace); - elementSections[0].style.maxHeight = `${MAX_BOX_HEIGHT}px`; - elementSections[0].style.height = `${height}px`; - const top = bottom - height; - element.style.top = `${top}px`; - element.style.fontStyle = 'italic'; + const y = this.yPixelForEventOnChart(overlay.entry); + if (y === null) { + return; + } + // Max height for the overlay box. + const MAX_BOX_HEIGHT = 50; + // Some padding so the box hovers just on top. + const PADDING = 7; + // Where the timespan breakdown should sit. Slightly on top of the entry. + const bottom = y - PADDING; + // Available space between the bottom of the overlay and top of the chart. + const minSpace = Math.max(bottom, 0); + // Contrain height to available space. + const height = Math.min(MAX_BOX_HEIGHT, minSpace); + elementSections[0].style.maxHeight = `${MAX_BOX_HEIGHT}px`; + elementSections[0].style.height = `${height}px`; + const top = bottom - height; + element.style.top = `${top}px`; + } + } + #positionCreateEntriesLinkOverlay(overlay, element) { + const componentDefault = element.querySelector('devtools-create-entries-link-overlay'); + if (componentDefault) { + const component = componentDefault.querySelector('devtools-entries-link-overlay'); + if (!component) { + const entryStartX = this.xPixelForEventStartOnChart(overlay.entry) ?? 0; + const entryEndX = this.xPixelForEventEndOnChart(overlay.entry) ?? 0; + const entryWidth = entryEndX - entryStartX; + const entryStartY = (this.yPixelForEventOnChart(overlay.entry) ?? 0); + const entryHeight = this.pixelHeightForEventOnChart(overlay.entry) ?? 0; + componentDefault.fromEntryData = { entryStartX, entryStartY, entryWidth, entryHeight }; } } } @@ -889,7 +933,7 @@ export class Overlays extends EventTarget { if (x === null || y === null) { return; } - const { endTime, duration } = timingsForOverlayEntry(overlay.entry); + const { endTime } = timingsForOverlayEntry(overlay.entry); const endX = this.#xPixelForMicroSeconds(chartName, endTime); if (endX === null) { return; @@ -904,21 +948,15 @@ export class Overlays extends EventTarget { // we modify that for instant events like LCP markers, and also ensure a // minimum width. let widthPixels = endX - x; - if (!duration) { - // No duration = instant event, so we check in case it's a marker. - const provider = chartName === 'main' ? this.#charts.mainProvider : this.#charts.networkProvider; - const chart = chartName === 'main' ? this.#charts.mainChart : this.#charts.networkChart; - // It could be a marker event, in which case we need to know the - // exact position the marker was rendered. This is because markers - // which have the same timestamp are rendered next to each other, so - // the timestamp is not necessarily exactly where the marker was - // rendered. - const index = provider.indexForEvent?.(overlay.entry); - const markerPixels = chart.getMarkerPixelsForEntryIndex(index ?? -1); - if (markerPixels) { - x = markerPixels.x; - widthPixels = markerPixels.width; - } + const provider = chartName === 'main' ? this.#charts.mainProvider : this.#charts.networkProvider; + const chart = chartName === 'main' ? this.#charts.mainChart : this.#charts.networkChart; + const index = provider.indexForEvent?.(overlay.entry); + const customPos = chart.getCustomDrawnPositionForEntryIndex(index ?? -1); + if (customPos) { + // Some events like markers and layout shifts define their exact coordinates explicitly. + // If this is one of those events we should change the overlay coordinates to match. + x = customPos.x; + widthPixels = customPos.width; } // The entry selected overlay is always at least 2px wide. const finalWidth = Math.max(2, widthPixels); @@ -1011,7 +1049,7 @@ export class Overlays extends EventTarget { div.classList.add('overlay-item', `overlay-type-${overlay.type}`); switch (overlay.type) { case 'ENTRY_LABEL': { - const shouldDrawLabelBelowEntry = TraceEngine.Types.TraceEvents.isLegacyTimelineFrame(overlay.entry); + const shouldDrawLabelBelowEntry = Trace.Types.Events.isLegacyTimelineFrame(overlay.entry); const component = new Components.EntryLabelOverlay.EntryLabelOverlay(overlay.label, chartForEntry(overlay.entry) === 'main', shouldDrawLabelBelowEntry); component.addEventListener(Components.EntryLabelOverlay.EmptyEntryLabelRemoveEvent.eventName, () => { this.dispatchEvent(new AnnotationOverlayActionEvent(overlay, 'Remove')); @@ -1041,6 +1079,19 @@ export class Overlays extends EventTarget { div.appendChild(component); return div; } + case 'ENTRIES_LINK_CREATE_BUTTON': { + const entryStartX = this.xPixelForEventStartOnChart(overlay.entry) ?? 0; + const entryEndX = this.xPixelForEventEndOnChart(overlay.entry) ?? 0; + const entryWidth = entryEndX - entryStartX; + const entryStartY = (this.yPixelForEventOnChart(overlay.entry) ?? 0); + const entryHeight = this.pixelHeightForEventOnChart(overlay.entry) ?? 0; + const component = new Components.EntriesLinkOverlay.CreateEntriesLinkOverlay({ entryStartX, entryStartY, entryWidth, entryHeight }); + component.addEventListener(Components.EntriesLinkOverlay.CreateEntriesLinkRemoveEvent.eventName, () => { + this.dispatchEvent(new AnnotationOverlayActionEvent(overlay, 'CreateLink')); + }); + div.appendChild(component); + return div; + } case 'ENTRY_OUTLINE': { div.classList.add(`outline-reason-${overlay.outlineReason}`); return div; @@ -1076,7 +1127,7 @@ export class Overlays extends EventTarget { * Some of the HTML elements for overlays might need updating between each render * (for example, if a time range has changed, we update its duration text) */ - #updateOverlayElementIfRequired(overlay, element) { + #updateOverlayElementAfterPositioning(overlay, element) { switch (overlay.type) { case 'ENTRY_SELECTED': // Nothing to do here. @@ -1086,15 +1137,20 @@ export class Overlays extends EventTarget { if (component) { component.duration = overlay.showDuration ? overlay.bounds.range : null; component.canvasRect = this.#charts.mainChart.canvasBoundingClientRect(); + component.updateLabelPositioning(); } break; } + case 'ENTRY_LABEL': case 'ENTRY_OUTLINE': + case 'ENTRIES_LINK_CREATE_BUTTON': + // Nothing to do here. break; case 'ENTRIES_LINK': { - break; - } - case 'ENTRY_LABEL': { + const component = element.querySelector('devtools-entries-link-overlay'); + if (component) { + component.canvasRect = this.#charts.mainChart.canvasBoundingClientRect(); + } break; } case 'TIMESPAN_BREAKDOWN': { @@ -1102,6 +1158,7 @@ export class Overlays extends EventTarget { if (component) { component.sections = overlay.sections; component.canvasRect = this.#charts.mainChart.canvasBoundingClientRect(); + component.checkSectionLabelPositioning(); } break; } @@ -1133,8 +1190,8 @@ export class Overlays extends EventTarget { return false; } const { startTime, endTime } = timingsForOverlayEntry(entry); - const entryTimeRange = TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(startTime, endTime); - return TraceEngine.Helpers.Timing.boundsIncludeTimeRange({ + const entryTimeRange = Trace.Helpers.Timing.traceWindowFromMicroSeconds(startTime, endTime); + return Trace.Helpers.Timing.boundsIncludeTimeRange({ bounds: this.#dimensions.trace.visibleWindow, timeRange: entryTimeRange, }); @@ -1354,21 +1411,21 @@ export class Overlays extends EventTarget { * of entry. */ export function timingsForOverlayEntry(entry) { - if (TraceEngine.Types.TraceEvents.isLegacyTimelineFrame(entry)) { + if (Trace.Types.Events.isLegacyTimelineFrame(entry)) { return { startTime: entry.startTime, endTime: entry.endTime, duration: entry.duration, }; } - if (TraceEngine.Types.TraceEvents.isSyntheticLayoutShift(entry)) { - const endTime = TraceEngine.Types.Timing.MicroSeconds(entry.ts + LAYOUT_SHIFT_SYNTHETIC_DURATION); + if (Trace.Types.Events.isSyntheticLayoutShift(entry)) { + const endTime = Trace.Types.Timing.MicroSeconds(entry.ts + LAYOUT_SHIFT_SYNTHETIC_DURATION); return { endTime, duration: LAYOUT_SHIFT_SYNTHETIC_DURATION, startTime: entry.ts, }; } - return TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(entry); + return Trace.Helpers.Timing.eventTimingsMicroSeconds(entry); } //# sourceMappingURL=OverlaysImpl.js.map \ No newline at end of file diff --git a/public/panels/timeline/overlays/OverlaysImpl.js.map b/public/panels/timeline/overlays/OverlaysImpl.js.map index 7c4eace77..9951a57e3 100644 --- a/public/panels/timeline/overlays/OverlaysImpl.js.map +++ b/public/panels/timeline/overlays/OverlaysImpl.js.map @@ -1 +1 @@ -{"version":3,"file":"OverlaysImpl.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/overlays/OverlaysImpl.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as Common from '../../../core/common/common.js';\nimport * as Platform from '../../../core/platform/platform.js';\nimport * as TraceEngine from '../../../models/trace/trace.js';\nimport type * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\n\nimport * as Components from './components/components.js';\n\n// Bit of a hack: LayoutShifts are instant events, so have no duration. But\n// OPP doesn't do well at making tiny events easy to spot and click. So we\n// set it to a small duration so that the user is able to see and click\n// them more easily. Long term we will explore a better UI solution to\n// allow us to do this properly and not hack around it.\nexport const LAYOUT_SHIFT_SYNTHETIC_DURATION = TraceEngine.Types.Timing.MicroSeconds(5_000);\n\n/**\n * Below the network track there is a resize bar the user can click and drag.\n */\nconst NETWORK_RESIZE_ELEM_HEIGHT_PX = 8;\n\n/**\n * Represents which flamechart an entry is rendered in.\n * We need to know this because when we place an overlay for an entry we need\n * to adjust its Y value if it's in the main chart which is drawn below the\n * network chart\n */\nexport type EntryChartLocation = 'main'|'network';\n\n/**\n * You can add overlays to trace events, but also right now frames are drawn on\n * the timeline but they are not trace events, so we need to allow for that.\n * In the future when the frames track has been migrated to be powered by\n * animation frames (crbug.com/345144583), we can remove the requirement to\n * support TimelineFrame instances (which themselves will be removed from the\n * codebase.)\n */\nexport type OverlayEntry =\n TraceEngine.Types.TraceEvents.TraceEventData|TraceEngine.Types.TraceEvents.LegacyTimelineFrame;\n\n/**\n * Represents when a user has selected an entry in the timeline\n */\nexport interface EntrySelected {\n type: 'ENTRY_SELECTED';\n entry: OverlayEntry;\n}\n\n/**\n * Drawn around an entry when we want to highlight it to the user.\n */\nexport interface EntryOutline {\n type: 'ENTRY_OUTLINE';\n entry: OverlayEntry;\n outlineReason: 'ERROR'|'INFO';\n}\n\n/**\n * Represents an object created when a user creates a label for an entry in the timeline.\n */\nexport interface EntryLabel {\n type: 'ENTRY_LABEL';\n entry: OverlayEntry;\n label: string;\n}\n\n/**\n * Represents an object created when a user creates a link between two entries.\n */\nexport interface EntriesLink {\n type: 'ENTRIES_LINK';\n entryFrom: OverlayEntry;\n entryTo?: OverlayEntry;\n}\n\n/**\n * Represents a time range on the trace. Also used when the user shift+clicks\n * and drags to create a time range.\n */\nexport interface TimeRangeLabel {\n type: 'TIME_RANGE';\n bounds: TraceEngine.Types.Timing.TraceWindowMicroSeconds;\n label: string;\n showDuration: boolean;\n}\n\n/**\n * Given a list of overlays, this method will calculate the smallest possible\n * trace window that will contain all of the overlays.\n */\nexport function traceWindowContainingOverlays(overlays: TimelineOverlay[]):\n TraceEngine.Types.Timing.TraceWindowMicroSeconds {\n let minTime = TraceEngine.Types.Timing.MicroSeconds(Number.POSITIVE_INFINITY);\n let maxTime = TraceEngine.Types.Timing.MicroSeconds(Number.NEGATIVE_INFINITY);\n\n for (const overlay of overlays) {\n const windowForOverlay = traceWindowForOverlay(overlay);\n if (windowForOverlay.min < minTime) {\n minTime = windowForOverlay.min;\n }\n if (windowForOverlay.max > maxTime) {\n maxTime = windowForOverlay.max;\n }\n }\n\n return TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(minTime, maxTime);\n}\n\nfunction traceWindowForOverlay(overlay: TimelineOverlay): TraceEngine.Types.Timing.TraceWindowMicroSeconds {\n const overlayMinBounds: TraceEngine.Types.Timing.MicroSeconds[] = [];\n const overlayMaxBounds: TraceEngine.Types.Timing.MicroSeconds[] = [];\n\n switch (overlay.type) {\n case 'ENTRY_SELECTED': {\n const timings = timingsForOverlayEntry(overlay.entry);\n overlayMinBounds.push(timings.startTime);\n overlayMaxBounds.push(timings.endTime);\n break;\n }\n case 'ENTRY_OUTLINE': {\n const timings = timingsForOverlayEntry(overlay.entry);\n overlayMinBounds.push(timings.startTime);\n overlayMaxBounds.push(timings.endTime);\n break;\n }\n\n case 'TIME_RANGE': {\n overlayMinBounds.push(overlay.bounds.min);\n overlayMaxBounds.push(overlay.bounds.max);\n break;\n }\n case 'ENTRY_LABEL': {\n const timings = timingsForOverlayEntry(overlay.entry);\n overlayMinBounds.push(timings.startTime);\n overlayMaxBounds.push(timings.endTime);\n break;\n }\n\n case 'ENTRIES_LINK': {\n const timingsFrom = timingsForOverlayEntry(overlay.entryFrom);\n overlayMinBounds.push(timingsFrom.startTime);\n if (overlay.entryTo) {\n const timingsTo = timingsForOverlayEntry(overlay.entryTo);\n // No need to push the startTime; it must be larger than the entryFrom start time.\n overlayMaxBounds.push(timingsTo.endTime);\n } else {\n // Only use the end time if we have no entryTo; otherwise the entryTo\n // endTime is guaranteed to be larger than the entryFrom endTime.\n overlayMaxBounds.push(timingsFrom.endTime);\n }\n\n break;\n }\n\n case 'TIMESPAN_BREAKDOWN': {\n if (overlay.entry) {\n const timings = timingsForOverlayEntry(overlay.entry);\n overlayMinBounds.push(timings.startTime);\n overlayMaxBounds.push(timings.endTime);\n }\n for (const section of overlay.sections) {\n overlayMinBounds.push(section.bounds.min);\n overlayMaxBounds.push(section.bounds.max);\n }\n break;\n }\n case 'CURSOR_TIMESTAMP_MARKER': {\n overlayMinBounds.push(overlay.timestamp);\n break;\n }\n case 'CANDY_STRIPED_TIME_RANGE': {\n const timings = timingsForOverlayEntry(overlay.entry);\n overlayMinBounds.push(timings.startTime);\n overlayMaxBounds.push(timings.endTime);\n overlayMinBounds.push(overlay.bounds.min);\n overlayMaxBounds.push(overlay.bounds.max);\n break;\n }\n default:\n Platform.TypeScriptUtilities.assertNever(overlay, `Unexpected overlay ${overlay}`);\n }\n\n const min = TraceEngine.Types.Timing.MicroSeconds(Math.min(...overlayMinBounds));\n const max = TraceEngine.Types.Timing.MicroSeconds(Math.max(...overlayMaxBounds));\n return TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(min, max);\n}\n\n/**\n * Get a list of entries for a given overlay.\n */\nexport function entriesForOverlay(overlay: TimelineOverlay): readonly OverlayEntry[] {\n const entries: OverlayEntry[] = [];\n\n switch (overlay.type) {\n case 'ENTRY_SELECTED': {\n entries.push(overlay.entry);\n break;\n }\n case 'ENTRY_OUTLINE': {\n entries.push(overlay.entry);\n break;\n }\n case 'TIME_RANGE': {\n // Time ranges are not associated with entries.\n break;\n }\n case 'ENTRY_LABEL': {\n entries.push(overlay.entry);\n break;\n }\n case 'ENTRIES_LINK': {\n entries.push(overlay.entryFrom);\n if (overlay.entryTo) {\n entries.push(overlay.entryTo);\n }\n break;\n }\n case 'TIMESPAN_BREAKDOWN': {\n if (overlay.entry) {\n entries.push(overlay.entry);\n }\n break;\n }\n case 'CURSOR_TIMESTAMP_MARKER': {\n break;\n }\n case 'CANDY_STRIPED_TIME_RANGE': {\n entries.push(overlay.entry);\n break;\n }\n default:\n Platform.assertNever(overlay, `Unknown overlay type ${JSON.stringify(overlay)}`);\n }\n\n return entries;\n}\nexport function chartForEntry(entry: OverlayEntry): EntryChartLocation {\n if (TraceEngine.Types.TraceEvents.isNetworkTrackEntry(entry)) {\n return 'network';\n }\n\n return 'main';\n}\n\nexport function isTimeRangeLabel(annotation: TimelineOverlay): annotation is TimeRangeLabel {\n return annotation.type === 'TIME_RANGE';\n}\n\nexport function isEntriesLink(annotation: TimelineOverlay): annotation is EntriesLink {\n return annotation.type === 'ENTRIES_LINK';\n}\n\n/**\n * Used to highlight with a red-candy stripe a time range. It takes an entry\n * because this entry is the row that will be used to place the candy stripe,\n * and its height will be set to the height of that row.\n */\nexport interface CandyStripedTimeRange {\n type: 'CANDY_STRIPED_TIME_RANGE';\n bounds: TraceEngine.Types.Timing.TraceWindowMicroSeconds;\n entry: TraceEngine.Types.TraceEvents.TraceEventData;\n}\n\n/**\n * Represents a timespan on a trace broken down into parts. Each part has a label to it.\n * If an entry is defined, the breakdown will be vertically positioned based on it.\n */\nexport interface TimespanBreakdown {\n type: 'TIMESPAN_BREAKDOWN';\n sections: Array;\n entry?: TraceEngine.Types.TraceEvents.TraceEventData;\n}\n\nexport interface CursorTimestampMarker {\n type: 'CURSOR_TIMESTAMP_MARKER';\n timestamp: TraceEngine.Types.Timing.MicroSeconds;\n}\n\n/**\n * All supported overlay types. Expected to grow in time!\n */\nexport type TimelineOverlay = EntrySelected|EntryOutline|TimeRangeLabel|EntryLabel|EntriesLink|TimespanBreakdown|\n CursorTimestampMarker|CandyStripedTimeRange;\n\n/**\n * Denotes overlays that are singletons; only one of these will be allowed to\n * exist at any given time. If one exists and the add() method is called, the\n * new overlay will replace the existing one.\n */\ntype SingletonOverlay = EntrySelected|CursorTimestampMarker;\nexport function overlayIsSingleton(overlay: TimelineOverlay): overlay is SingletonOverlay {\n return overlay.type === 'CURSOR_TIMESTAMP_MARKER' || overlay.type === 'ENTRY_SELECTED';\n}\n\n/**\n * To be able to draw overlays accurately at the correct pixel position, we\n * need a variety of pixel values from both flame charts (Network and \"Rest\").\n * As each FlameChart draws, it emits an event with its latest set of\n * dimensions. That updates the Overlays and causes them to redraw.\n * Note that we can't use the visible trace window from the TraceBounds\n * service as that can get out of sync with rapid FlameChart draws. To ensure\n * we draw overlays smoothly as the FlameChart renders we use the latest values\n * provided to us from the FlameChart. In `FlameChart#draw` we dispatch an\n * event containing the latest dimensions, and those are passed into the\n * Overlays system via TimelineFlameChartView.\n */\ninterface ActiveDimensions {\n trace: {\n visibleWindow: TraceEngine.Types.Timing.TraceWindowMicroSeconds|null,\n };\n charts: {\n main: FlameChartDimensions|null,\n network: FlameChartDimensions|null,\n };\n}\n\n/**\n * The dimensions each flame chart reports. Note that in the current UI they\n * will always have the same width, so theoretically we could only gather that\n * from one chart, but we gather it from both for simplicity and to cover us in\n * the future should the UI change and the charts have different widths.\n */\ninterface FlameChartDimensions {\n widthPixels: number;\n heightPixels: number;\n scrollOffsetPixels: number;\n // If every single group (e.g. track) within the chart is collapsed or not.\n // This matters because in the network track if every group (there is only\n // one) is collapsed, there is no resizer bar shown, which impacts our pixel\n // calculations for overlay positioning.\n allGroupsCollapsed: boolean;\n}\n\nexport interface TimelineCharts {\n mainChart: PerfUI.FlameChart.FlameChart;\n mainProvider: PerfUI.FlameChart.FlameChartDataProvider;\n networkChart: PerfUI.FlameChart.FlameChart;\n networkProvider: PerfUI.FlameChart.FlameChartDataProvider;\n}\n\nexport interface OverlayEntryQueries {\n isEntryCollapsedByUser: (entry: TraceEngine.Types.TraceEvents.TraceEventData) => boolean;\n firstVisibleParentForEntry:\n (entry: TraceEngine.Types.TraceEvents.TraceEventData) => TraceEngine.Types.TraceEvents.TraceEventData | null;\n}\n\n// An event dispatched when one of the Annotation Overlays (overlay created by the user,\n// ex. EntryLabel) is removed or updated. When one of the Annotation Overlays is removed or updated,\n// ModificationsManager listens to this event and updates the current annotations.\nexport type UpdateAction = 'Remove'|'Update';\nexport class AnnotationOverlayActionEvent extends Event {\n static readonly eventName = 'annotationoverlayactionsevent';\n\n constructor(public overlay: TimelineOverlay, public action: UpdateAction) {\n super(AnnotationOverlayActionEvent.eventName);\n }\n}\n\ninterface EntriesLinkVisibleEntries {\n entryFrom: TraceEngine.Types.TraceEvents.TraceEventData;\n entryTo: TraceEngine.Types.TraceEvents.TraceEventData|undefined;\n entryFromIsSource: boolean;\n entryToIsSource: boolean;\n}\n\n/**\n * This class manages all the overlays that get drawn onto the performance\n * timeline. Overlays are DOM and are drawn above the network and main flame\n * chart.\n *\n * For more documentation, see `timeline/README.md` which has a section on overlays.\n */\nexport class Overlays extends EventTarget {\n /**\n * The list of active overlays. Overlays can't be marked as visible or\n * hidden; every overlay in this list is rendered.\n * We track each overlay against the HTML Element we have rendered. This is\n * because on first render of a new overlay, we create it, but then on\n * subsequent renders we do not destroy and recreate it, instead we update it\n * based on the new position of the timeline.\n */\n #overlaysToElements: Map = new Map();\n\n // When the Entries Link Annotation is created, the arrow needs to follow the mouse.\n // Update the mouse coordinates while it is being created.\n #lastMouseOffsetX: number|null = null;\n #lastMouseOffsetY: number|null = null;\n // `entriesLinkInProgress` is the entries link Overlay that has not yet been fully created\n // and only has the entry that the link starts from set.\n // We save it as a separate variable because when the second entry of the link is not chosen yet,\n // the arrow follows the mouse. To achieve that, update the coordinates of `entriesLinkInProgress`\n // on mousemove. There can only be one link in the process on being created so the mousemove\n // only needs to update `entriesLinkInProgress` link overlay.\n #entriesLinkInProgress: EntriesLink|null;\n\n #dimensions: ActiveDimensions = {\n trace: {\n visibleWindow: null,\n },\n charts: {\n main: null,\n network: null,\n },\n };\n\n /**\n * To calculate the Y pixel value for an event we need access to the chart\n * and data provider in order to find out what level the event is on, and from\n * there calculate the pixel value for that level.\n */\n #charts: TimelineCharts;\n\n /**\n * The Overlays class will take each overlay, generate its HTML, and add it\n * to the container. This container is provided for us when the class is\n * created so we can manage its contents as overlays come and go.\n */\n #overlaysContainer: HTMLElement;\n\n // Setting that specififed if the annotations overlays need to be visible.\n // It is switched on/off from the annotations tab in the sidebar.\n readonly #annotationsHiddenSetting: Common.Settings.Setting;\n\n /**\n * The OverlaysManager sometimes needs to find out if an entry is visible or\n * not, and if not, why not - for example, if the user has collapsed its\n * parent. We define these query functions that must be supplied in order to\n * answer these questions.\n */\n #queries: OverlayEntryQueries;\n\n constructor(init: {\n container: HTMLElement,\n flameChartsContainers: {\n main: HTMLElement,\n network: HTMLElement,\n },\n charts: TimelineCharts,\n entryQueries: OverlayEntryQueries,\n }) {\n super();\n this.#overlaysContainer = init.container;\n this.#charts = init.charts;\n this.#queries = init.entryQueries;\n this.#entriesLinkInProgress = null;\n this.#annotationsHiddenSetting = Common.Settings.Settings.instance().moduleSetting('annotations-hidden');\n this.#annotationsHiddenSetting.addChangeListener(this.update.bind(this));\n\n // HTMLElements of both Flamecharts. They are used to get the mouse position over the Flamecharts.\n init.flameChartsContainers.main.addEventListener(\n 'mousemove', event => this.#updateMouseCoordinatesProgressEntriesLink.bind(this)(event, 'main'));\n init.flameChartsContainers.network.addEventListener(\n 'mousemove', event => this.#updateMouseCoordinatesProgressEntriesLink.bind(this)(event, 'network'));\n }\n\n // Mousemove event listener to get mouse coordinates and update them for the entries link that is being created.\n //\n // The 'mousemove' event is attached to `flameChartsContainers` instead of `overlaysContainer`\n // because `overlaysContainer` doesn't have events to enable the interaction with the\n // Flamecharts beneath it.\n #updateMouseCoordinatesProgressEntriesLink(event: Event, chart: EntryChartLocation): void {\n const mouseEvent = (event as MouseEvent);\n this.#lastMouseOffsetX = mouseEvent.offsetX;\n this.#lastMouseOffsetY = mouseEvent.offsetY;\n\n if (!this.#entriesLinkInProgress || this.#entriesLinkInProgress.entryTo) {\n return;\n }\n\n // The Overlays layer coordinates cover both Network and Main Charts, while the mousemove\n // coordinates are received from the charts individually and start from 0 for each chart.\n //\n // To make it work on the overlays, we need to know which chart the entry belongs to and,\n // if it is on the main chart, add the height of the Network chart to get correct Entry\n // coordinates on the Overlays layer.\n const networkHeight = this.#dimensions.charts.network?.heightPixels ?? 0;\n const linkInProgressElement = this.#overlaysToElements.get(this.#entriesLinkInProgress);\n\n if (linkInProgressElement) {\n const component = linkInProgressElement.querySelector('devtools-entries-link-overlay') as\n Components.EntriesLinkOverlay.EntriesLinkOverlay;\n const yCoordinate = mouseEvent.offsetY + ((chart === 'main') ? networkHeight : 0);\n component.toEntryCoordinateAndDimentions = {x: mouseEvent.offsetX, y: yCoordinate};\n }\n }\n\n /**\n * Add a new overlay to the view.\n */\n add(newOverlay: T): T {\n if (this.#overlaysToElements.has(newOverlay)) {\n return newOverlay;\n }\n\n /**\n * If the overlay type is a singleton, and we already have one, we update\n * the existing one, rather than create a new one. This ensures you can only\n * ever have one instance of the overlay type.\n */\n const existing = this.overlaysOfType(newOverlay.type);\n if (overlayIsSingleton(newOverlay) && existing[0]) {\n this.updateExisting(existing[0], newOverlay);\n return existing[0];\n }\n\n // By setting the value to null, we ensure that on the next render that the\n // overlay will have a new HTML element created for it.\n this.#overlaysToElements.set(newOverlay, null);\n return newOverlay;\n }\n\n /**\n * Update an existing overlay without destroying and recreating its\n * associated DOM.\n *\n * This is useful if you need to rapidly update an overlay's data - e.g.\n * dragging to create time ranges - without the thrashing of destroying the\n * old overlay and re-creating the new one.\n */\n updateExisting(existingOverlay: T, newData: Partial): void {\n if (!this.#overlaysToElements.has(existingOverlay)) {\n console.error('Trying to update an overlay that does not exist.');\n return;\n }\n\n for (const [key, value] of Object.entries(newData)) {\n // newData is of type Partial, so each key must exist in T, but\n // Object.entries doesn't carry that information.\n const k = key as keyof T;\n existingOverlay[k] = value;\n }\n }\n\n /**\n * @returns the list of overlays associated with a given entry.\n */\n overlaysForEntry(entry: OverlayEntry): TimelineOverlay[] {\n const matches: TimelineOverlay[] = [];\n for (const [overlay] of this.#overlaysToElements) {\n if ('entry' in overlay && overlay.entry === entry) {\n matches.push(overlay);\n }\n }\n return matches;\n }\n\n /**\n * Removes any active overlays that match the provided type.\n * @returns the number of overlays that were removed.\n */\n removeOverlaysOfType(type: TimelineOverlay['type']): number {\n const overlaysToRemove = Array.from(this.#overlaysToElements.keys()).filter(overlay => {\n return overlay.type === type;\n });\n for (const overlay of overlaysToRemove) {\n this.remove(overlay);\n }\n return overlaysToRemove.length;\n }\n\n /**\n * @returns all overlays that match the provided type.\n */\n overlaysOfType(type: T['type']): NoInfer[] {\n const matches: T[] = [];\n\n function overlayIsOfType(overlay: TimelineOverlay): overlay is T {\n return overlay.type === type;\n }\n\n for (const [overlay] of this.#overlaysToElements) {\n if (overlayIsOfType(overlay)) {\n matches.push(overlay);\n }\n }\n return matches;\n }\n\n /**\n * Removes the provided overlay from the list of overlays and destroys any\n * DOM associated with it.\n */\n remove(overlay: TimelineOverlay): void {\n const htmlElement = this.#overlaysToElements.get(overlay);\n if (htmlElement && this.#overlaysContainer) {\n this.#overlaysContainer.removeChild(htmlElement);\n }\n this.#overlaysToElements.delete(overlay);\n }\n\n /**\n * Update the dimenions of a chart.\n * IMPORTANT: this does not trigger a re-draw. You must call the render() method manually.\n */\n updateChartDimensions(chart: EntryChartLocation, dimensions: FlameChartDimensions): void {\n this.#dimensions.charts[chart] = dimensions;\n }\n\n /**\n * Update the visible window of the UI.\n * IMPORTANT: this does not trigger a re-draw. You must call the render() method manually.\n */\n updateVisibleWindow(visibleWindow: TraceEngine.Types.Timing.TraceWindowMicroSeconds): void {\n this.#dimensions.trace.visibleWindow = visibleWindow;\n }\n\n /**\n * Clears all overlays and all data. Call this when the trace is changing\n * (e.g. the user has imported/recorded a new trace) and we need to start from\n * scratch and remove all overlays relating to the preivous trace.\n */\n reset(): void {\n if (this.#overlaysContainer) {\n this.#overlaysContainer.innerHTML = '';\n }\n this.#overlaysToElements.clear();\n\n // Clear out dimensions from the old Flame Charts.\n this.#dimensions.trace.visibleWindow = null;\n this.#dimensions.charts.main = null;\n this.#dimensions.charts.network = null;\n }\n\n /**\n * Updates the Overlays UI: new overlays will be rendered onto the view, and\n * existing overlays will have their positions changed to ensure they are\n * rendered in the right place.\n */\n update(): void {\n const timeRangeOverlays: TimeRangeLabel[] = [];\n for (const [overlay, existingElement] of this.#overlaysToElements) {\n const element = existingElement || this.#createElementForNewOverlay(overlay);\n if (existingElement) {\n this.#updateOverlayElementIfRequired(overlay, element);\n } else {\n // This is a new overlay, so we have to store the element and add it to the DOM.\n this.#overlaysToElements.set(overlay, element);\n this.#overlaysContainer.appendChild(element);\n }\n this.#positionOverlay(overlay, element);\n if (overlay.type === 'TIME_RANGE') {\n timeRangeOverlays.push(overlay);\n }\n }\n\n if (timeRangeOverlays.length > 1) { // If there are 0 or 1 overlays, they can't overlap\n this.#positionOverlappingTimeRangeLabels(timeRangeOverlays);\n }\n }\n\n /**\n * If any time-range overlays overlap, we try to adjust their horizontal\n * position in order to make sure you can distinguish them and that the labels\n * do not entirely overlap.\n * This is very much minimal best effort, and does not guarantee that all\n * labels will remain readable.\n */\n #positionOverlappingTimeRangeLabels(overlays: readonly TimeRangeLabel[]): void {\n const overlaysSorted = overlays.toSorted((o1, o2) => {\n return o1.bounds.min - o2.bounds.min;\n });\n\n // Track the overlays which overlap other overlays.\n // This isn't bi-directional: if we find that O2 overlaps O1, we will\n // store O1 => [O2]. We will not then also store O2 => [O1], because we\n // only need to deal with the overlap once.\n const overlapsByOverlay: Map = new Map();\n\n for (let i = 0; i < overlaysSorted.length; i++) {\n const current = overlaysSorted[i];\n const overlaps: TimeRangeLabel[] = [];\n\n // Walk through subsequent overlays and find stop when you find the next one that does not overlap.\n for (let j = i + 1; j < overlaysSorted.length; j++) {\n const next = overlaysSorted[j];\n const currentAndNextOverlap = TraceEngine.Helpers.Timing.boundsIncludeTimeRange({\n bounds: current.bounds,\n timeRange: next.bounds,\n });\n if (currentAndNextOverlap) {\n overlaps.push(next);\n } else {\n // Overlays are sorted by time, if this one does not overlap, the next one will not, so we can break.\n break;\n }\n }\n overlapsByOverlay.set(current, overlaps);\n }\n for (const [firstOverlay, overlappingOverlays] of overlapsByOverlay) {\n const element = this.#overlaysToElements.get(firstOverlay);\n if (!element) {\n continue;\n }\n\n // If the first overlay is adjusted, we can start back from 0 again\n // rather than continually increment up.\n let firstIndexForOverlapClass = 1;\n if (element.getAttribute('class')?.includes('overlap-')) {\n firstIndexForOverlapClass = 0;\n }\n\n overlappingOverlays.forEach(overlay => {\n const element = this.#overlaysToElements.get(overlay);\n element?.classList.add(`overlap-${firstIndexForOverlapClass++}`);\n });\n }\n }\n\n #positionOverlay(overlay: TimelineOverlay, element: HTMLElement): void {\n const annotationsAreHidden = this.#annotationsHiddenSetting.get();\n switch (overlay.type) {\n case 'ENTRY_SELECTED': {\n const isVisible = this.entryIsVisibleOnChart(overlay.entry);\n this.#setOverlayElementVisibility(element, isVisible);\n if (isVisible) {\n this.#positionEntryBorderOutlineType(overlay, element);\n }\n break;\n }\n case 'ENTRY_OUTLINE': {\n const selectedOverlay = this.overlaysOfType('ENTRY_SELECTED')?.at(0);\n // Check if this entry has also been selected by the user. If it has,\n // do not show the outline, but only show the selected outline.\n const outlinedEntryIsSelected = Boolean(selectedOverlay && selectedOverlay.entry === overlay.entry);\n if (!outlinedEntryIsSelected && this.entryIsVisibleOnChart(overlay.entry)) {\n this.#setOverlayElementVisibility(element, true);\n this.#positionEntryBorderOutlineType(overlay, element);\n } else {\n this.#setOverlayElementVisibility(element, false);\n }\n break;\n }\n\n case 'TIME_RANGE': {\n // The time range annotation can also be used to measure a selection in the timeline and is not saved if no label is added.\n // Therefore, we only care about the annotation hidden setting if the time range has a label.\n if (overlay.label.length) {\n this.#setOverlayElementVisibility(element, !annotationsAreHidden);\n }\n this.#positionTimeRangeOverlay(overlay, element);\n const component = element.querySelector('devtools-time-range-overlay');\n if (component) {\n component.afterOverlayUpdate();\n }\n break;\n }\n case 'ENTRY_LABEL': {\n const entryVisible = this.entryIsVisibleOnChart(overlay.entry);\n this.#setOverlayElementVisibility(element, entryVisible && !annotationsAreHidden);\n if (entryVisible) {\n const entryLabelParams = this.#positionEntryLabelOverlay(overlay, element);\n const component = element.querySelector('devtools-entry-label-overlay');\n if (component && entryLabelParams) {\n component.entryLabelParams = entryLabelParams;\n }\n }\n break;\n }\n case 'ENTRIES_LINK': {\n // The exact entries that are linked to could be collapsed in a flame\n // chart, so we figure out the best visible entry pairs to draw\n // between.\n const entriesToConnect = this.#calculateFromAndToForEntriesLink(overlay);\n if (entriesToConnect === null) {\n // Unexpected situation: hide the overlay and move on\n this.#setOverlayElementVisibility(element, false);\n break;\n }\n\n // If either entry is in a track that the user has collapsed, we do not show the connection at all.\n const fromEntryInCollapsedTrack = this.#entryIsInCollapsedTrack(entriesToConnect.entryFrom);\n const toEntryInCollapsedTrack =\n entriesToConnect.entryTo && this.#entryIsInCollapsedTrack(entriesToConnect.entryTo);\n if (fromEntryInCollapsedTrack || toEntryInCollapsedTrack) {\n this.#setOverlayElementVisibility(element, false);\n break;\n }\n\n const isVisible = !annotationsAreHidden;\n this.#setOverlayElementVisibility(element, isVisible);\n if (isVisible) {\n this.#positionEntriesLinkOverlay(overlay, element, entriesToConnect);\n }\n break;\n }\n case 'TIMESPAN_BREAKDOWN': {\n this.#positionTimespanBreakdownOverlay(overlay, element);\n const component = element.querySelector('devtools-timespan-breakdown-overlay');\n if (component) {\n component.afterOverlayUpdate();\n }\n // TODO: Have the timespan squeeze instead.\n if (overlay.entry) {\n const {visibleWindow} = this.#dimensions.trace;\n const isVisible = Boolean(\n visibleWindow && this.#entryIsVerticallyVisibleOnChart(overlay.entry) &&\n TraceEngine.Helpers.Timing.boundsIncludeTimeRange({\n bounds: visibleWindow,\n timeRange: overlay.sections[0].bounds,\n }),\n );\n this.#setOverlayElementVisibility(element, isVisible);\n }\n break;\n }\n\n case 'CURSOR_TIMESTAMP_MARKER': {\n const {visibleWindow} = this.#dimensions.trace;\n // Only update the position if the timestamp of this marker is within\n // the visible bounds.\n const isVisible =\n Boolean(visibleWindow && TraceEngine.Helpers.Timing.timestampIsInBounds(visibleWindow, overlay.timestamp));\n this.#setOverlayElementVisibility(element, isVisible);\n if (isVisible) {\n this.#positionTimestampMarker(overlay, element);\n }\n break;\n }\n\n case 'CANDY_STRIPED_TIME_RANGE': {\n const {visibleWindow} = this.#dimensions.trace;\n // If the bounds of this overlay are not within the visible bounds, we\n // can skip updating its position and just hide it.\n\n const isVisible = Boolean(\n visibleWindow && this.#entryIsVerticallyVisibleOnChart(overlay.entry) &&\n TraceEngine.Helpers.Timing.boundsIncludeTimeRange({\n bounds: visibleWindow,\n timeRange: overlay.bounds,\n }));\n this.#setOverlayElementVisibility(element, isVisible);\n if (isVisible) {\n this.#positionCandyStripedTimeRange(overlay, element);\n }\n break;\n }\n\n default: {\n Platform.TypeScriptUtilities.assertNever(overlay, `Unknown overlay: ${JSON.stringify(overlay)}`);\n }\n }\n }\n\n #positionTimestampMarker(overlay: CursorTimestampMarker, element: HTMLElement): void {\n // Because we are adjusting the x position, we can use either chart here.\n const x = this.#xPixelForMicroSeconds('main', overlay.timestamp);\n element.style.left = `${x}px`;\n }\n\n #positionTimespanBreakdownOverlay(overlay: TimespanBreakdown, element: HTMLElement): void {\n const component = element.querySelector('devtools-timespan-breakdown-overlay');\n const shadow = component?.shadowRoot;\n const elementSections = shadow?.querySelectorAll('.timespan-breakdown-overlay-section');\n\n if (overlay.sections.length === 0) {\n return;\n }\n // Handle horizontal positioning.\n const leftEdgePixel = this.#xPixelForMicroSeconds('main', overlay.sections[0].bounds.min);\n const rightEdgePixel =\n this.#xPixelForMicroSeconds('main', overlay.sections[overlay.sections.length - 1].bounds.max);\n if (leftEdgePixel === null || rightEdgePixel === null) {\n return;\n }\n\n const rangeWidth = rightEdgePixel - leftEdgePixel;\n element.style.left = `${leftEdgePixel}px`;\n element.style.width = `${rangeWidth}px`;\n\n if (!(elementSections?.length)) {\n return;\n }\n\n let count = 0;\n for (const section of overlay.sections) {\n const leftPixel = this.#xPixelForMicroSeconds('main', section.bounds.min);\n const rightPixel = this.#xPixelForMicroSeconds('main', section.bounds.max);\n if (leftPixel === null || rightPixel === null) {\n return;\n }\n const rangeWidth = rightPixel - leftPixel;\n const sectionElement = elementSections[count];\n\n sectionElement.style.left = `${leftPixel}px`;\n sectionElement.style.width = `${rangeWidth}px`;\n count++;\n }\n\n // Handle vertical positioning based on the entry's vertical position.\n if (overlay.entry) {\n const chartName = chartForEntry(overlay.entry);\n if (chartName === 'network') {\n const y = this.yPixelForEventOnChart(overlay.entry);\n if (y === null) {\n return;\n }\n\n // Max height for the overlay box.\n const MAX_BOX_HEIGHT = 50;\n // Some padding so the box hovers just on top.\n const PADDING = 7;\n\n // Where the timespan breakdown should sit. Slightly on top of the entry.\n const bottom = y - PADDING;\n\n // Available space between the bottom of the overlay and top of the chart.\n const minSpace = Math.max(bottom, 0);\n // Contrain height to available space.\n const height = Math.min(MAX_BOX_HEIGHT, minSpace);\n\n elementSections[0].style.maxHeight = `${MAX_BOX_HEIGHT}px`;\n elementSections[0].style.height = `${height}px`;\n\n const top = bottom - height;\n element.style.top = `${top}px`;\n element.style.fontStyle = 'italic';\n }\n }\n }\n\n /**\n * Positions the arrow between two entries. Takes in the entriesToConnect\n * because if one of the original entries is hidden in a collapsed main thread\n * icicle, we use its parent to connect to.\n */\n #positionEntriesLinkOverlay(overlay: EntriesLink, element: HTMLElement, entriesToConnect: EntriesLinkVisibleEntries):\n void {\n const component = element.querySelector('devtools-entries-link-overlay');\n if (component) {\n const {entryFrom, entryTo, entryFromIsSource, entryToIsSource} = entriesToConnect;\n const fromEntryStartX = this.xPixelForEventStartOnChart(entryFrom) ?? 0;\n const fromEntryEndX = this.xPixelForEventEndOnChart(entryFrom) ?? 0;\n const fromEntryLength = fromEntryEndX - fromEntryStartX;\n const fromEntryHeight = this.pixelHeightForEventOnChart(entryFrom) ?? 0;\n\n const entryFromVisibility = this.entryIsVisibleOnChart(entryFrom);\n const entryToVisibility = entryTo ? this.entryIsVisibleOnChart(entryTo) : false;\n\n // If the 'from' entry is visible, set the entry Y as an arrow start coordinate. Ff not, get the canvas edge coordinate to for the arrow to start from.\n const yPixelForFromArrow = (entryFromVisibility ? this.yPixelForEventOnChart(entryFrom) :\n this.#yCoordinateForNotVisibleEntry(entryFrom)) ??\n 0;\n\n component.fromEntryIsSource = entryFromIsSource;\n component.toEntryIsSource = entryToIsSource;\n\n component.entriesVisibility = {\n fromEntryVisibility: entryFromVisibility,\n toEntryVisibility: entryToVisibility,\n };\n\n component.fromEntryCoordinateAndDimentions =\n {x: fromEntryStartX, y: yPixelForFromArrow, length: fromEntryLength, height: fromEntryHeight};\n\n // If entryTo exists, pass the coordinates and dimentions of the entry that the arrow snaps to.\n // If it does not, the event tracking mouse coordinates updates 'to coordinates' so the arrow follows the mouse instead.\n if (entryTo) {\n const toEntryStartX = this.xPixelForEventStartOnChart(entryTo) ?? 0;\n const toEntryEndX = this.xPixelForEventEndOnChart(entryTo) ?? 0;\n const toEntryWidth = toEntryEndX - toEntryStartX;\n const toEntryHeight = this.pixelHeightForEventOnChart(entryTo) ?? 0;\n\n // If the 'to' entry is visible, set the entry Y as an arrow coordinate to point ot. Ff not, get the canvas edge coordate to point the arrow to.\n const yPixelForToArrow =\n ((this.entryIsVisibleOnChart(entryTo)) ? this.yPixelForEventOnChart(entryTo) :\n this.#yCoordinateForNotVisibleEntry(entryTo)) ??\n 0;\n component.toEntryCoordinateAndDimentions = {\n x: toEntryStartX ?? 0,\n y: yPixelForToArrow,\n length: toEntryWidth,\n height: toEntryHeight,\n };\n\n } else if (this.#lastMouseOffsetX && this.#lastMouseOffsetY) {\n // The second coordinate for in progress link gets updated on mousemove\n this.#entriesLinkInProgress = overlay;\n }\n }\n }\n\n /**\n * Return Y coordinate for an arrow connecting 2 entries to attach to if the entry is not visible.\n * For example, if the entry is scrolled up from the visible area , return the y index of the edge of the track:\n * --\n * | | - entry off the visible chart\n * --\n *\n * --Y--------------- -- Y is the returned coordinate that the arrow should point to\n *\n * flamechart data -- visible flamechart data between the 2 lines\n * ------------------\n *\n * On the contrary, if the entry is scrolled off the bottom, get the coordinate of the top of the visible canvas.\n */\n #yCoordinateForNotVisibleEntry(entry: OverlayEntry): number {\n const chartName = chartForEntry(entry);\n\n const y = this.yPixelForEventOnChart(entry);\n if (y === null) {\n return 0;\n }\n\n if (chartName === 'main') {\n if (!this.#dimensions.charts.main?.heightPixels) {\n // Shouldn't happen, but if the main chart has no height, nothing on it is visible.\n return 0;\n }\n\n const yWithoutNetwork = y - this.networkChartOffsetHeight();\n // Check if the y position is less than 0. If it, the entry is off the top of the track canvas.\n // In that case, return the height of network track, which is also the top of main track.\n if (yWithoutNetwork < 0) {\n return this.networkChartOffsetHeight();\n }\n }\n\n if (chartName === 'network') {\n if (!this.#dimensions.charts.network) {\n return 0;\n }\n\n // The event is off the bottom of the network chart. In this case return the bottom of the network chart.\n if (y > this.#dimensions.charts.network.heightPixels ?? 0) {\n return this.#dimensions.charts.network.heightPixels;\n }\n }\n\n // In other cases, return the y of the entry\n return y;\n }\n\n #positionTimeRangeOverlay(overlay: TimeRangeLabel, element: HTMLElement): void {\n // Time ranges span both charts, it doesn't matter which one we pass here.\n // It's used to get the width of the container, and both charts have the\n // same width.\n const leftEdgePixel = this.#xPixelForMicroSeconds('main', overlay.bounds.min);\n const rightEdgePixel = this.#xPixelForMicroSeconds('main', overlay.bounds.max);\n if (leftEdgePixel === null || rightEdgePixel === null) {\n return;\n }\n\n const rangeWidth = rightEdgePixel - leftEdgePixel;\n\n element.style.left = `${leftEdgePixel}px`;\n element.style.width = `${rangeWidth}px`;\n }\n\n /**\n * Positions an EntryLabel overlay\n * @param overlay - the EntrySelected overlay that we need to position.\n * @param element - the DOM element representing the overlay\n */\n #positionEntryLabelOverlay(overlay: EntryLabel, element: HTMLElement):\n {height: number, width: number, cutOffEntryHeight: number, chart: string}|null {\n const chartName = chartForEntry(overlay.entry);\n const x = this.xPixelForEventStartOnChart(overlay.entry);\n const y = this.yPixelForEventOnChart(overlay.entry);\n const {endTime} = timingsForOverlayEntry(overlay.entry);\n const endX = this.#xPixelForMicroSeconds(chartName, endTime);\n const entryHeight = this.pixelHeightForEventOnChart(overlay.entry) ?? 0;\n\n if (x === null || y === null || endX === null) {\n return null;\n }\n\n // The width of the overlay is by default the width of the entry. However\n // we modify that for instant events like LCP markers, and also ensure a\n // minimum width.\n const widthPixels = endX - x;\n // The part of the overlay that draws a box around an entry is always at least 2px wide.\n const entryWidth = Math.max(2, widthPixels);\n const networkHeight = this.#dimensions.charts.network?.heightPixels ?? 0;\n\n // Find the part of the entry that is covered by resizer to not draw it over the resizer.\n // If the entry is in the main flamechart, find the part of the entry that is covered from the top.\n // If it is in the network track, find the part covered by the resizer from the bottom.\n const entryHiddenTop = this.networkChartOffsetHeight() - y;\n const entryHiddenBottom = entryHeight + y - networkHeight;\n // If the covered part is negative, the entry is fully visible and the cut off part is 0.\n const cutOffEntryHeight = Math.max((chartName === 'main') ? entryHiddenTop : entryHiddenBottom, 0);\n\n let topOffset = y - Components.EntryLabelOverlay.EntryLabelOverlay.LABEL_AND_CONNECTOR_HEIGHT;\n // If part of the entry height is not visible in the main flamechart, take that into the account in the top offset.\n if (chartName === 'main') {\n topOffset += cutOffEntryHeight;\n }\n\n // Position the start of label overlay at the start of the entry + length of connector + legth of the label element\n element.style.top = `${topOffset}px`;\n // Position the start of the entry label overlay in the the middle of the entry.\n element.style.left = `${x + entryWidth / 2}px`;\n\n return {height: entryHeight, width: entryWidth, cutOffEntryHeight, chart: chartName};\n }\n\n #positionCandyStripedTimeRange(overlay: CandyStripedTimeRange, element: HTMLElement): void {\n const chartName = chartForEntry(overlay.entry);\n\n const startX = this.#xPixelForMicroSeconds(chartName, overlay.bounds.min);\n const endX = this.#xPixelForMicroSeconds(chartName, overlay.bounds.max);\n if (startX === null || endX === null) {\n return;\n }\n\n const widthPixels = endX - startX;\n // The entry selected overlay is always at least 2px wide.\n const finalWidth = Math.max(2, widthPixels);\n element.style.width = `${finalWidth}px`;\n element.style.left = `${startX}px`;\n\n let y = this.yPixelForEventOnChart(overlay.entry);\n if (y === null) {\n return;\n }\n\n const totalHeight = this.pixelHeightForEventOnChart(overlay.entry) ?? 0;\n\n // We might modify the height we use when drawing the overlay, hence copying the totalHeight.\n let height = totalHeight;\n if (height === null) {\n return;\n }\n\n // If the event is on the main chart, we need to adjust its selected border\n // if the event is cut off the top of the screen, because we need to ensure\n // that it does not overlap the resize element. Unfortunately we cannot\n // z-index our way out of this, so instead we calculate if the event is cut\n // off, and if it is, we draw the partial selected outline and do not draw\n // the top border, making it appear like it is going behind the resizer.\n // We don't need to worry about it going off the bottom, because in that\n // case we don't draw the overlay anyway.\n if (chartName === 'main') {\n const chartTopPadding = this.networkChartOffsetHeight();\n // We now calculate the available height: if the entry is cut off we don't\n // show the border for the part that is cut off.\n const cutOffTop = y < chartTopPadding;\n\n height = cutOffTop ? Math.abs(y + height - chartTopPadding) : height;\n element.classList.toggle('cut-off-top', cutOffTop);\n if (cutOffTop) {\n // Adjust the y position: we need to move it down from the top Y\n // position to the Y position of the first visible pixel. The\n // adjustment is totalHeight - height because if the totalHeight is 17,\n // and the visibleHeight is 5, we need to draw the overay at 17-5=12px\n // vertically from the top of the event.\n y = y + totalHeight - height;\n }\n } else {\n // If the event is on the network chart, we use the same logic as above\n // for the main chart, but to check if the event is cut off the bottom of\n // the network track and only part of the overlay is visible.\n // We don't need to worry about the event going off the top of the panel\n // as we can show the full overlay and it gets cut off by the minimap UI.\n const networkHeight = this.#dimensions.charts.network?.heightPixels ?? 0;\n const lastVisibleY = y + totalHeight;\n const cutOffBottom = lastVisibleY > networkHeight;\n const cutOffTop = y > networkHeight;\n element.classList.toggle('cut-off-top', cutOffTop);\n element.classList.toggle('cut-off-bottom', cutOffBottom);\n if (cutOffBottom) {\n // Adjust the height of the overlay to be the amount of visible pixels.\n height = networkHeight - y;\n }\n }\n\n element.style.height = `${height}px`;\n element.style.top = `${y}px`;\n }\n\n /**\n * Positions an EntrySelected or EntryOutline overlay. These share the same\n * method as they are both borders around an entry.\n * @param overlay - the EntrySelected/EntryOutline overlay that we need to position.\n * @param element - the DOM element representing the overlay\n */\n #positionEntryBorderOutlineType(overlay: EntrySelected|EntryOutline, element: HTMLElement): void {\n const chartName = chartForEntry(overlay.entry);\n let x = this.xPixelForEventStartOnChart(overlay.entry);\n let y = this.yPixelForEventOnChart(overlay.entry);\n\n if (x === null || y === null) {\n return;\n }\n\n const {endTime, duration} = timingsForOverlayEntry(overlay.entry);\n const endX = this.#xPixelForMicroSeconds(chartName, endTime);\n if (endX === null) {\n return;\n }\n\n const totalHeight = this.pixelHeightForEventOnChart(overlay.entry) ?? 0;\n\n // We might modify the height we use when drawing the overlay, hence copying the totalHeight.\n let height = totalHeight;\n if (height === null) {\n return;\n }\n\n // The width of the overlay is by default the width of the entry. However\n // we modify that for instant events like LCP markers, and also ensure a\n // minimum width.\n let widthPixels = endX - x;\n\n if (!duration) {\n // No duration = instant event, so we check in case it's a marker.\n const provider = chartName === 'main' ? this.#charts.mainProvider : this.#charts.networkProvider;\n const chart = chartName === 'main' ? this.#charts.mainChart : this.#charts.networkChart;\n // It could be a marker event, in which case we need to know the\n // exact position the marker was rendered. This is because markers\n // which have the same timestamp are rendered next to each other, so\n // the timestamp is not necessarily exactly where the marker was\n // rendered.\n const index = provider.indexForEvent?.(overlay.entry);\n const markerPixels = chart.getMarkerPixelsForEntryIndex(index ?? -1);\n if (markerPixels) {\n x = markerPixels.x;\n widthPixels = markerPixels.width;\n }\n }\n\n // The entry selected overlay is always at least 2px wide.\n const finalWidth = Math.max(2, widthPixels);\n element.style.width = `${finalWidth}px`;\n\n // If the event is on the main chart, we need to adjust its selected border\n // if the event is cut off the top of the screen, because we need to ensure\n // that it does not overlap the resize element. Unfortunately we cannot\n // z-index our way out of this, so instead we calculate if the event is cut\n // off, and if it is, we draw the partial selected outline and do not draw\n // the top border, making it appear like it is going behind the resizer.\n // We don't need to worry about it going off the bottom, because in that\n // case we don't draw the overlay anyway.\n if (chartName === 'main') {\n const chartTopPadding = this.networkChartOffsetHeight();\n // We now calculate the available height: if the entry is cut off we don't\n // show the border for the part that is cut off.\n const cutOffTop = y < chartTopPadding;\n\n height = cutOffTop ? Math.abs(y + height - chartTopPadding) : height;\n element.classList.toggle('cut-off-top', cutOffTop);\n if (cutOffTop) {\n // Adjust the y position: we need to move it down from the top Y\n // position to the Y position of the first visible pixel. The\n // adjustment is totalHeight - height because if the totalHeight is 17,\n // and the visibleHeight is 5, we need to draw the overay at 17-5=12px\n // vertically from the top of the event.\n y = y + totalHeight - height;\n }\n } else {\n // If the event is on the network chart, we use the same logic as above\n // for the main chart, but to check if the event is cut off the bottom of\n // the network track and only part of the overlay is visible.\n // We don't need to worry about the even going off the top of the panel\n // as we can show the full overlay and it gets cut off by the minimap UI.\n const networkHeight = this.#dimensions.charts.network?.heightPixels ?? 0;\n const lastVisibleY = y + totalHeight;\n const cutOffBottom = lastVisibleY > networkHeight;\n element.classList.toggle('cut-off-bottom', cutOffBottom);\n if (cutOffBottom) {\n // Adjust the height of the overlay to be the amount of visible pixels.\n height = networkHeight - y;\n }\n }\n\n element.style.height = `${height}px`;\n element.style.top = `${y}px`;\n element.style.left = `${x}px`;\n }\n\n /**\n * We draw an arrow between connected entries but this can get complicated\n * depending on if the entries are visible or not. For example, the user might\n * draw a connection to an entry in the main thread but then collapse the\n * parent of that entry. In this case the entry we want to draw to is the\n * first visible parent of that entry rather than the (invisible) entry.\n */\n #calculateFromAndToForEntriesLink(overlay: EntriesLink): EntriesLinkVisibleEntries|null {\n if (!overlay.entryTo) {\n // This case is where the user has clicked on the first entry and needs\n // to pick a second. In this case they can only pick from visible\n // entries, so we don't need to do any checks and can just return.\n return {\n entryFrom: overlay.entryFrom,\n entryTo: overlay.entryTo,\n entryFromIsSource: true,\n entryToIsSource: true,\n };\n }\n\n let entryFrom: OverlayEntry|null = overlay.entryFrom;\n let entryTo: OverlayEntry|null = overlay.entryTo ?? null;\n\n if (this.#queries.isEntryCollapsedByUser(overlay.entryFrom)) {\n entryFrom = this.#queries.firstVisibleParentForEntry(overlay.entryFrom);\n }\n if (overlay.entryTo && this.#queries.isEntryCollapsedByUser(overlay.entryTo)) {\n entryTo = this.#queries.firstVisibleParentForEntry(overlay.entryTo);\n }\n\n if (entryFrom === null || entryTo === null) {\n // We cannot draw this overlay; so return null;\n // The only valid case of entryTo being null/undefined has been dealt\n // with already at the start of this function.\n return null;\n }\n\n return {\n entryFrom,\n entryFromIsSource: entryFrom === overlay.entryFrom,\n entryTo,\n entryToIsSource: entryTo === overlay.entryTo,\n };\n }\n\n #createElementForNewOverlay(overlay: TimelineOverlay): HTMLElement {\n const div = document.createElement('div');\n div.classList.add('overlay-item', `overlay-type-${overlay.type}`);\n switch (overlay.type) {\n case 'ENTRY_LABEL': {\n const shouldDrawLabelBelowEntry = TraceEngine.Types.TraceEvents.isLegacyTimelineFrame(overlay.entry);\n const component = new Components.EntryLabelOverlay.EntryLabelOverlay(\n overlay.label, chartForEntry(overlay.entry) === 'main', shouldDrawLabelBelowEntry);\n component.addEventListener(Components.EntryLabelOverlay.EmptyEntryLabelRemoveEvent.eventName, () => {\n this.dispatchEvent(new AnnotationOverlayActionEvent(overlay, 'Remove'));\n });\n component.addEventListener(Components.EntryLabelOverlay.EntryLabelChangeEvent.eventName, event => {\n const newLabel = (event as Components.EntryLabelOverlay.EntryLabelChangeEvent).newLabel;\n overlay.label = newLabel;\n this.dispatchEvent(new AnnotationOverlayActionEvent(overlay, 'Update'));\n });\n div.appendChild(component);\n return div;\n }\n case 'ENTRIES_LINK': {\n const entries = this.#calculateFromAndToForEntriesLink(overlay);\n if (entries === null) {\n // For some reason, we don't have two entries we can draw between\n // (can happen if the user has collapsed an icicle in the flame\n // chart, or a track), so just draw an empty div.\n return div;\n }\n const entryEndX = this.xPixelForEventEndOnChart(entries.entryFrom) ?? 0;\n const entryStartX = this.xPixelForEventEndOnChart(entries.entryFrom) ?? 0;\n const entryStartY = (this.yPixelForEventOnChart(entries.entryFrom) ?? 0);\n const entryWidth = entryEndX - entryStartX;\n const entryHeight = this.pixelHeightForEventOnChart(entries.entryFrom) ?? 0;\n\n const component = new Components.EntriesLinkOverlay.EntriesLinkOverlay(\n {x: entryEndX, y: entryStartY, width: entryWidth, height: entryHeight});\n div.appendChild(component);\n return div;\n }\n case 'ENTRY_OUTLINE': {\n div.classList.add(`outline-reason-${overlay.outlineReason}`);\n return div;\n }\n case 'TIME_RANGE': {\n const component = new Components.TimeRangeOverlay.TimeRangeOverlay(overlay.label);\n component.duration = overlay.showDuration ? overlay.bounds.range : null;\n component.canvasRect = this.#charts.mainChart.canvasBoundingClientRect();\n component.addEventListener(Components.TimeRangeOverlay.TimeRangeLabelChangeEvent.eventName, event => {\n const newLabel = (event as Components.TimeRangeOverlay.TimeRangeLabelChangeEvent).newLabel;\n overlay.label = newLabel;\n this.dispatchEvent(new AnnotationOverlayActionEvent(overlay, 'Update'));\n });\n component.addEventListener(Components.TimeRangeOverlay.TimeRangeRemoveEvent.eventName, () => {\n this.dispatchEvent(new AnnotationOverlayActionEvent(overlay, 'Remove'));\n });\n div.appendChild(component);\n return div;\n }\n case 'TIMESPAN_BREAKDOWN': {\n const component = new Components.TimespanBreakdownOverlay.TimespanBreakdownOverlay();\n component.sections = overlay.sections;\n component.canvasRect = this.#charts.mainChart.canvasBoundingClientRect();\n div.appendChild(component);\n return div;\n }\n default: {\n return div;\n }\n }\n }\n\n /**\n * Some of the HTML elements for overlays might need updating between each render\n * (for example, if a time range has changed, we update its duration text)\n */\n #updateOverlayElementIfRequired(overlay: TimelineOverlay, element: HTMLElement): void {\n switch (overlay.type) {\n case 'ENTRY_SELECTED':\n // Nothing to do here.\n break;\n case 'TIME_RANGE': {\n const component = element.querySelector('devtools-time-range-overlay');\n if (component) {\n component.duration = overlay.showDuration ? overlay.bounds.range : null;\n component.canvasRect = this.#charts.mainChart.canvasBoundingClientRect();\n }\n break;\n }\n case 'ENTRY_OUTLINE':\n break;\n case 'ENTRIES_LINK': {\n break;\n }\n case 'ENTRY_LABEL': {\n break;\n }\n case 'TIMESPAN_BREAKDOWN': {\n const component = element.querySelector('devtools-timespan-breakdown-overlay');\n if (component) {\n component.sections = overlay.sections;\n component.canvasRect = this.#charts.mainChart.canvasBoundingClientRect();\n }\n break;\n }\n case 'CURSOR_TIMESTAMP_MARKER':\n // No contents within this that need updating.\n break;\n case 'CANDY_STRIPED_TIME_RANGE':\n break;\n default:\n Platform.TypeScriptUtilities.assertNever(overlay, `Unexpected overlay ${overlay}`);\n }\n }\n\n /**\n * @returns true if the entry is visible on chart, which means that both\n * horizontally and vertically it is at least partially in view.\n */\n entryIsVisibleOnChart(entry: OverlayEntry): boolean {\n const verticallyVisible = this.#entryIsVerticallyVisibleOnChart(entry);\n const horiziontallyVisible = this.#entryIsHorizontallyVisibleOnChart(entry);\n return verticallyVisible && horiziontallyVisible;\n }\n\n /**\n * Calculates if an entry is visible horizontally. This is easy because we\n * don't have to consider any pixels and can instead check that its start and\n * end times intersect with the visible window.\n */\n #entryIsHorizontallyVisibleOnChart(entry: OverlayEntry): boolean {\n if (this.#dimensions.trace.visibleWindow === null) {\n return false;\n }\n const {startTime, endTime} = timingsForOverlayEntry(entry);\n\n const entryTimeRange = TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(startTime, endTime);\n\n return TraceEngine.Helpers.Timing.boundsIncludeTimeRange({\n bounds: this.#dimensions.trace.visibleWindow,\n timeRange: entryTimeRange,\n });\n }\n\n #entryIsInCollapsedTrack(entry: OverlayEntry): boolean {\n const chartName = chartForEntry(entry);\n const provider = chartName === 'main' ? this.#charts.mainProvider : this.#charts.networkProvider;\n\n const entryIndex = provider.indexForEvent?.(entry) ?? null;\n if (entryIndex === null) {\n return false;\n }\n\n const group = provider.groupForEvent?.(entryIndex) ?? null;\n if (!group) {\n return false;\n }\n\n return Boolean(group.expanded) === false;\n }\n\n /**\n * Calculate if an entry is visible vertically on the chart. A bit fiddly as\n * we have to figure out its pixel offset and go on that. Unlike horizontal\n * visibility, we can't work soley from its microsecond values.\n */\n #entryIsVerticallyVisibleOnChart(entry: OverlayEntry): boolean {\n const chartName = chartForEntry(entry);\n\n const y = this.yPixelForEventOnChart(entry);\n if (y === null) {\n return false;\n }\n\n const eventHeight = this.pixelHeightForEventOnChart(entry);\n if (!eventHeight) {\n return false;\n }\n\n if (chartName === 'main') {\n if (!this.#dimensions.charts.main?.heightPixels) {\n // Shouldn't happen, but if the main chart has no height, nothing on it is visible.\n return false;\n }\n\n // The yPixelForEventOnChart method returns the y pixel including an adjustment for the network track.\n // To see if an entry on the main flame chart is visible, we can check\n // its y value without the network track adjustment. If it is < 0, then\n // it's off the top of the screen.\n //\n const yWithoutNetwork = y - this.networkChartOffsetHeight();\n // Check if the y position + the height is less than 0. We add height so\n // that we correctly consider an event only partially scrolled off to be\n // visible.\n if (yWithoutNetwork + eventHeight < 0) {\n return false;\n }\n\n if (yWithoutNetwork > this.#dimensions.charts.main.heightPixels) {\n // The event is off the bottom of the screen.\n return false;\n }\n }\n\n if (chartName === 'network') {\n if (!this.#dimensions.charts.network) {\n // The network chart can be hidden if there are no requests in the trace.\n return false;\n }\n if (y <= -14) {\n // Weird value, but the network chart has the header row with\n // timestamps on it: events stay visible behind those timestamps, so we\n // want any overlays to treat themselves as visible too.\n return false;\n }\n\n if (y > this.#dimensions.charts.network.heightPixels ?? 0) {\n // The event is off the bottom of the network chart.\n return false;\n }\n }\n // If we got here, none of the conditions to mark an event as invisible got\n // triggered, so the event must be visible.\n return true;\n }\n\n /**\n * Calculate the X pixel position for an event start on the timeline.\n * @param chartName - the chart that the event is on. It is expected that both\n * charts have the same width so this doesn't make a difference - but it might\n * in the future if the UI changes, hence asking for it.\n *\n * @param event - the trace event you want to get the pixel position of\n */\n xPixelForEventStartOnChart(event: OverlayEntry): number|null {\n const chartName = chartForEntry(event);\n const {startTime} = timingsForOverlayEntry(event);\n return this.#xPixelForMicroSeconds(chartName, startTime);\n }\n\n /**\n * Calculate the X pixel position for an event end on the timeline.\n * @param chartName - the chart that the event is on. It is expected that both\n * charts have the same width so this doesn't make a difference - but it might\n * in the future if the UI changes, hence asking for it.\n *\n * @param event - the trace event you want to get the pixel position of\n */\n xPixelForEventEndOnChart(event: OverlayEntry): number|null {\n const chartName = chartForEntry(event);\n const {endTime} = timingsForOverlayEntry(event);\n return this.#xPixelForMicroSeconds(chartName, endTime);\n }\n\n /**\n * Calculate the xPixel for a given timestamp. To do this we calculate how\n * far in microseconds from the left of the visible window an event is, and\n * divide that by the total time span. This gives us a fraction representing\n * how far along the timeline the event is. We can then multiply that by the\n * width of the canvas to get its pixel position.\n */\n #xPixelForMicroSeconds(chart: EntryChartLocation, timestamp: TraceEngine.Types.Timing.MicroSeconds): number|null {\n if (this.#dimensions.trace.visibleWindow === null) {\n console.error('Cannot calculate xPixel without visible trace window.');\n return null;\n }\n const canvasWidthPixels = this.#dimensions.charts[chart]?.widthPixels ?? null;\n if (canvasWidthPixels === null) {\n console.error(`Cannot calculate xPixel without ${chart} dimensions.`);\n return null;\n }\n\n const timeFromLeft = timestamp - this.#dimensions.trace.visibleWindow.min;\n const totalTimeSpan = this.#dimensions.trace.visibleWindow.range;\n return Math.floor(\n timeFromLeft / totalTimeSpan * canvasWidthPixels,\n );\n }\n\n /**\n * Calculate the Y pixel position for the event on the timeline relative to\n * the entire window.\n * This means if the event is in the main flame chart and below the network,\n * we add the height of the network chart to the Y value to position it\n * correctly.\n * This can return null if any data was missing, or if the event is not\n * visible (if the level it's on is hidden because the track is collapsed,\n * for example)\n */\n yPixelForEventOnChart(event: OverlayEntry): number|null {\n const chartName = chartForEntry(event);\n const chart = chartName === 'main' ? this.#charts.mainChart : this.#charts.networkChart;\n const provider = chartName === 'main' ? this.#charts.mainProvider : this.#charts.networkProvider;\n\n const indexForEntry = provider.indexForEvent?.(event);\n if (typeof indexForEntry !== 'number') {\n return null;\n }\n const timelineData = provider.timelineData();\n if (timelineData === null) {\n return null;\n }\n const level = timelineData.entryLevels.at(indexForEntry);\n if (typeof level === 'undefined') {\n return null;\n }\n\n if (!chart.levelIsVisible(level)) {\n return null;\n }\n\n const pixelOffsetForLevel = chart.levelToOffset(level);\n // Now we have the offset for the level, we need to adjust it by the user's scroll offset.\n let pixelAdjustedForScroll = pixelOffsetForLevel - (this.#dimensions.charts[chartName]?.scrollOffsetPixels ?? 0);\n\n // Now if the event is in the main chart, we need to pad its Y position\n // down by the height of the network chart + the network resize element.\n if (chartName === 'main') {\n pixelAdjustedForScroll += this.networkChartOffsetHeight();\n }\n\n return pixelAdjustedForScroll;\n }\n\n /**\n * Calculate the height of the event on the timeline.\n */\n pixelHeightForEventOnChart(event: OverlayEntry): number|null {\n const chartName = chartForEntry(event);\n const chart = chartName === 'main' ? this.#charts.mainChart : this.#charts.networkChart;\n const provider = chartName === 'main' ? this.#charts.mainProvider : this.#charts.networkProvider;\n\n const indexForEntry = provider.indexForEvent?.(event);\n if (typeof indexForEntry !== 'number') {\n return null;\n }\n const timelineData = provider.timelineData();\n if (timelineData === null) {\n return null;\n }\n const level = timelineData.entryLevels.at(indexForEntry);\n if (typeof level === 'undefined') {\n return null;\n }\n return chart.levelHeight(level);\n }\n\n /**\n * Calculate the height of the network chart. If the network chart has\n * height, we also allow for the size of the resize handle shown between the\n * two charts.\n *\n * Note that it is possible for the chart to have 0 height if the user is\n * looking at a trace with no network requests.\n */\n networkChartOffsetHeight(): number {\n if (this.#dimensions.charts.network === null) {\n return 0;\n }\n\n if (this.#dimensions.charts.network.heightPixels === 0) {\n return 0;\n }\n\n // At this point we know the network track exists and has height. But we\n // need to check if it is collapsed, because if it is collapsed there is no\n // resizer shown.\n if (this.#dimensions.charts.network.allGroupsCollapsed) {\n return this.#dimensions.charts.network.heightPixels;\n }\n\n return this.#dimensions.charts.network.heightPixels + NETWORK_RESIZE_ELEM_HEIGHT_PX;\n }\n\n /**\n * Hides or shows an element. We used to use visibility rather than display,\n * but a child of an element with visibility: hidden may still be visible if\n * its own `display` property is set.\n */\n #setOverlayElementVisibility(element: HTMLElement, isVisible: boolean): void {\n element.style.display = isVisible ? 'block' : 'none';\n }\n}\n\n/**\n * Because entries can be a TimelineFrame, which is not a trace event, this\n * helper exists to return a consistent set of timings regardless of the type\n * of entry.\n */\nexport function timingsForOverlayEntry(entry: OverlayEntry):\n TraceEngine.Helpers.Timing.EventTimingsData {\n if (TraceEngine.Types.TraceEvents.isLegacyTimelineFrame(entry)) {\n return {\n startTime: entry.startTime,\n endTime: entry.endTime,\n duration: entry.duration,\n };\n }\n if (TraceEngine.Types.TraceEvents.isSyntheticLayoutShift(entry)) {\n const endTime = TraceEngine.Types.Timing.MicroSeconds(entry.ts + LAYOUT_SHIFT_SYNTHETIC_DURATION);\n return {\n endTime,\n duration: LAYOUT_SHIFT_SYNTHETIC_DURATION,\n startTime: entry.ts,\n };\n }\n return TraceEngine.Helpers.Timing.eventTimingsMicroSeconds(entry);\n}\n"]} \ No newline at end of file +{"version":3,"file":"OverlaysImpl.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/overlays/OverlaysImpl.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as Common from '../../../core/common/common.js';\nimport * as Platform from '../../../core/platform/platform.js';\nimport * as Trace from '../../../models/trace/trace.js';\nimport type * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\n\nimport * as Components from './components/components.js';\n\n// Bit of a hack: LayoutShifts are instant events, so have no duration. But\n// OPP doesn't do well at making tiny events easy to spot and click. So we\n// set it to a small duration so that the user is able to see and click\n// them more easily. Long term we will explore a better UI solution to\n// allow us to do this properly and not hack around it.\nexport const LAYOUT_SHIFT_SYNTHETIC_DURATION = Trace.Types.Timing.MicroSeconds(5_000);\n\n/**\n * Below the network track there is a resize bar the user can click and drag.\n */\nconst NETWORK_RESIZE_ELEM_HEIGHT_PX = 8;\n\n/**\n * Represents which flamechart an entry is rendered in.\n * We need to know this because when we place an overlay for an entry we need\n * to adjust its Y value if it's in the main chart which is drawn below the\n * network chart\n */\nexport type EntryChartLocation = 'main'|'network';\n\n/**\n * You can add overlays to trace events, but also right now frames are drawn on\n * the timeline but they are not trace events, so we need to allow for that.\n * In the future when the frames track has been migrated to be powered by\n * animation frames (crbug.com/345144583), we can remove the requirement to\n * support TimelineFrame instances (which themselves will be removed from the\n * codebase.)\n */\nexport type OverlayEntry = Trace.Types.Events.Event|Trace.Types.Events.LegacyTimelineFrame;\n\n/**\n * Represents when a user has selected an entry in the timeline\n */\nexport interface EntrySelected {\n type: 'ENTRY_SELECTED';\n entry: OverlayEntry;\n}\n\n/**\n * Drawn around an entry when we want to highlight it to the user.\n */\nexport interface EntryOutline {\n type: 'ENTRY_OUTLINE';\n entry: OverlayEntry;\n outlineReason: 'ERROR'|'INFO';\n}\n\n/**\n * Represents an object created when a user creates a label for an entry in the timeline.\n */\nexport interface EntryLabel {\n type: 'ENTRY_LABEL';\n entry: OverlayEntry;\n label: string;\n}\n\n/**\n * Represents an object created when a user creates a link between two entries.\n */\nexport interface EntriesLink {\n type: 'ENTRIES_LINK';\n entryFrom: OverlayEntry;\n entryTo?: OverlayEntry;\n}\n\n/**\n * Represents an object created when a user double click an entry and before\n * creating a link between two entries.\n */\nexport interface CreateEntriesLink {\n type: 'ENTRIES_LINK_CREATE_BUTTON';\n entry: OverlayEntry;\n}\n\n/**\n * Represents a time range on the trace. Also used when the user shift+clicks\n * and drags to create a time range.\n */\nexport interface TimeRangeLabel {\n type: 'TIME_RANGE';\n bounds: Trace.Types.Timing.TraceWindowMicroSeconds;\n label: string;\n showDuration: boolean;\n}\n\n/**\n * Given a list of overlays, this method will calculate the smallest possible\n * trace window that will contain all of the overlays.\n */\nexport function traceWindowContainingOverlays(overlays: TimelineOverlay[]): Trace.Types.Timing.TraceWindowMicroSeconds {\n let minTime = Trace.Types.Timing.MicroSeconds(Number.POSITIVE_INFINITY);\n let maxTime = Trace.Types.Timing.MicroSeconds(Number.NEGATIVE_INFINITY);\n\n for (const overlay of overlays) {\n const windowForOverlay = traceWindowForOverlay(overlay);\n if (windowForOverlay.min < minTime) {\n minTime = windowForOverlay.min;\n }\n if (windowForOverlay.max > maxTime) {\n maxTime = windowForOverlay.max;\n }\n }\n\n return Trace.Helpers.Timing.traceWindowFromMicroSeconds(minTime, maxTime);\n}\n\nfunction traceWindowForOverlay(overlay: TimelineOverlay): Trace.Types.Timing.TraceWindowMicroSeconds {\n const overlayMinBounds: Trace.Types.Timing.MicroSeconds[] = [];\n const overlayMaxBounds: Trace.Types.Timing.MicroSeconds[] = [];\n\n switch (overlay.type) {\n case 'ENTRY_SELECTED': {\n const timings = timingsForOverlayEntry(overlay.entry);\n overlayMinBounds.push(timings.startTime);\n overlayMaxBounds.push(timings.endTime);\n break;\n }\n case 'ENTRY_OUTLINE': {\n const timings = timingsForOverlayEntry(overlay.entry);\n overlayMinBounds.push(timings.startTime);\n overlayMaxBounds.push(timings.endTime);\n break;\n }\n\n case 'TIME_RANGE': {\n overlayMinBounds.push(overlay.bounds.min);\n overlayMaxBounds.push(overlay.bounds.max);\n break;\n }\n case 'ENTRY_LABEL': {\n const timings = timingsForOverlayEntry(overlay.entry);\n overlayMinBounds.push(timings.startTime);\n overlayMaxBounds.push(timings.endTime);\n break;\n }\n\n case 'ENTRIES_LINK': {\n const timingsFrom = timingsForOverlayEntry(overlay.entryFrom);\n overlayMinBounds.push(timingsFrom.startTime);\n if (overlay.entryTo) {\n const timingsTo = timingsForOverlayEntry(overlay.entryTo);\n // No need to push the startTime; it must be larger than the entryFrom start time.\n overlayMaxBounds.push(timingsTo.endTime);\n } else {\n // Only use the end time if we have no entryTo; otherwise the entryTo\n // endTime is guaranteed to be larger than the entryFrom endTime.\n overlayMaxBounds.push(timingsFrom.endTime);\n }\n\n break;\n }\n case 'ENTRIES_LINK_CREATE_BUTTON': {\n const timings = timingsForOverlayEntry(overlay.entry);\n overlayMinBounds.push(timings.startTime);\n overlayMaxBounds.push(timings.endTime);\n break;\n }\n case 'TIMESPAN_BREAKDOWN': {\n if (overlay.entry) {\n const timings = timingsForOverlayEntry(overlay.entry);\n overlayMinBounds.push(timings.startTime);\n overlayMaxBounds.push(timings.endTime);\n }\n for (const section of overlay.sections) {\n overlayMinBounds.push(section.bounds.min);\n overlayMaxBounds.push(section.bounds.max);\n }\n break;\n }\n case 'CURSOR_TIMESTAMP_MARKER': {\n overlayMinBounds.push(overlay.timestamp);\n break;\n }\n case 'CANDY_STRIPED_TIME_RANGE': {\n const timings = timingsForOverlayEntry(overlay.entry);\n overlayMinBounds.push(timings.startTime);\n overlayMaxBounds.push(timings.endTime);\n overlayMinBounds.push(overlay.bounds.min);\n overlayMaxBounds.push(overlay.bounds.max);\n break;\n }\n default:\n Platform.TypeScriptUtilities.assertNever(overlay, `Unexpected overlay ${overlay}`);\n }\n\n const min = Trace.Types.Timing.MicroSeconds(Math.min(...overlayMinBounds));\n const max = Trace.Types.Timing.MicroSeconds(Math.max(...overlayMaxBounds));\n return Trace.Helpers.Timing.traceWindowFromMicroSeconds(min, max);\n}\n\n/**\n * Get a list of entries for a given overlay.\n */\nexport function entriesForOverlay(overlay: TimelineOverlay): readonly OverlayEntry[] {\n const entries: OverlayEntry[] = [];\n\n switch (overlay.type) {\n case 'ENTRY_SELECTED': {\n entries.push(overlay.entry);\n break;\n }\n case 'ENTRY_OUTLINE': {\n entries.push(overlay.entry);\n break;\n }\n case 'TIME_RANGE': {\n // Time ranges are not associated with entries.\n break;\n }\n case 'ENTRY_LABEL': {\n entries.push(overlay.entry);\n break;\n }\n case 'ENTRIES_LINK': {\n entries.push(overlay.entryFrom);\n if (overlay.entryTo) {\n entries.push(overlay.entryTo);\n }\n break;\n }\n case 'ENTRIES_LINK_CREATE_BUTTON': {\n entries.push(overlay.entry);\n break;\n }\n case 'TIMESPAN_BREAKDOWN': {\n if (overlay.entry) {\n entries.push(overlay.entry);\n }\n break;\n }\n case 'CURSOR_TIMESTAMP_MARKER': {\n break;\n }\n case 'CANDY_STRIPED_TIME_RANGE': {\n entries.push(overlay.entry);\n break;\n }\n default:\n Platform.assertNever(overlay, `Unknown overlay type ${JSON.stringify(overlay)}`);\n }\n\n return entries;\n}\nexport function chartForEntry(entry: OverlayEntry): EntryChartLocation {\n if (Trace.Types.Events.isNetworkTrackEntry(entry)) {\n return 'network';\n }\n\n return 'main';\n}\n\nexport function isTimeRangeLabel(annotation: TimelineOverlay): annotation is TimeRangeLabel {\n return annotation.type === 'TIME_RANGE';\n}\n\nexport function isEntriesLink(annotation: TimelineOverlay): annotation is EntriesLink {\n return annotation.type === 'ENTRIES_LINK';\n}\nexport function isEntryLabel(annotation: TimelineOverlay): annotation is EntryLabel {\n return annotation.type === 'ENTRY_LABEL';\n}\n\n/**\n * Used to highlight with a red-candy stripe a time range. It takes an entry\n * because this entry is the row that will be used to place the candy stripe,\n * and its height will be set to the height of that row.\n */\nexport interface CandyStripedTimeRange {\n type: 'CANDY_STRIPED_TIME_RANGE';\n bounds: Trace.Types.Timing.TraceWindowMicroSeconds;\n entry: Trace.Types.Events.Event;\n}\n\n/**\n * Represents a timespan on a trace broken down into parts. Each part has a label to it.\n * If an entry is defined, the breakdown will be vertically positioned based on it.\n */\nexport interface TimespanBreakdown {\n type: 'TIMESPAN_BREAKDOWN';\n sections: Array;\n entry?: Trace.Types.Events.Event;\n}\n\nexport interface CursorTimestampMarker {\n type: 'CURSOR_TIMESTAMP_MARKER';\n timestamp: Trace.Types.Timing.MicroSeconds;\n}\n\n/**\n * All supported overlay types. Expected to grow in time!\n */\nexport type TimelineOverlay = EntrySelected|EntryOutline|TimeRangeLabel|EntryLabel|EntriesLink|CreateEntriesLink|\n TimespanBreakdown|CursorTimestampMarker|CandyStripedTimeRange;\n\n/**\n * Denotes overlays that are singletons; only one of these will be allowed to\n * exist at any given time. If one exists and the add() method is called, the\n * new overlay will replace the existing one.\n */\ntype SingletonOverlay = EntrySelected|CursorTimestampMarker|CreateEntriesLink;\nexport function overlayIsSingleton(overlay: TimelineOverlay): overlay is SingletonOverlay {\n return overlay.type === 'CURSOR_TIMESTAMP_MARKER' || overlay.type === 'ENTRY_SELECTED' ||\n overlay.type === 'ENTRIES_LINK_CREATE_BUTTON';\n}\n\n/**\n * To be able to draw overlays accurately at the correct pixel position, we\n * need a variety of pixel values from both flame charts (Network and \"Rest\").\n * As each FlameChart draws, it emits an event with its latest set of\n * dimensions. That updates the Overlays and causes them to redraw.\n * Note that we can't use the visible trace window from the TraceBounds\n * service as that can get out of sync with rapid FlameChart draws. To ensure\n * we draw overlays smoothly as the FlameChart renders we use the latest values\n * provided to us from the FlameChart. In `FlameChart#draw` we dispatch an\n * event containing the latest dimensions, and those are passed into the\n * Overlays system via TimelineFlameChartView.\n */\ninterface ActiveDimensions {\n trace: {\n visibleWindow: Trace.Types.Timing.TraceWindowMicroSeconds|null,\n };\n charts: {\n main: FlameChartDimensions|null,\n network: FlameChartDimensions|null,\n };\n}\n\n/**\n * The dimensions each flame chart reports. Note that in the current UI they\n * will always have the same width, so theoretically we could only gather that\n * from one chart, but we gather it from both for simplicity and to cover us in\n * the future should the UI change and the charts have different widths.\n */\ninterface FlameChartDimensions {\n widthPixels: number;\n heightPixels: number;\n scrollOffsetPixels: number;\n // If every single group (e.g. track) within the chart is collapsed or not.\n // This matters because in the network track if every group (there is only\n // one) is collapsed, there is no resizer bar shown, which impacts our pixel\n // calculations for overlay positioning.\n allGroupsCollapsed: boolean;\n}\n\nexport interface TimelineCharts {\n mainChart: PerfUI.FlameChart.FlameChart;\n mainProvider: PerfUI.FlameChart.FlameChartDataProvider;\n networkChart: PerfUI.FlameChart.FlameChart;\n networkProvider: PerfUI.FlameChart.FlameChartDataProvider;\n}\n\nexport interface OverlayEntryQueries {\n isEntryCollapsedByUser: (entry: Trace.Types.Events.Event) => boolean;\n firstVisibleParentForEntry: (entry: Trace.Types.Events.Event) => Trace.Types.Events.Event | null;\n}\n\n// An event dispatched when one of the Annotation Overlays (overlay created by the user,\n// ex. EntryLabel) is removed or updated. When one of the Annotation Overlays is removed or updated,\n// ModificationsManager listens to this event and updates the current annotations.\nexport type UpdateAction = 'Remove'|'Update'|'CreateLink';\nexport class AnnotationOverlayActionEvent extends Event {\n static readonly eventName = 'annotationoverlayactionsevent';\n\n constructor(public overlay: TimelineOverlay, public action: UpdateAction) {\n super(AnnotationOverlayActionEvent.eventName);\n }\n}\n\ninterface EntriesLinkVisibleEntries {\n entryFrom: Trace.Types.Events.Event;\n entryTo: Trace.Types.Events.Event|undefined;\n entryFromIsSource: boolean;\n entryToIsSource: boolean;\n}\n\n/**\n * This class manages all the overlays that get drawn onto the performance\n * timeline. Overlays are DOM and are drawn above the network and main flame\n * chart.\n *\n * For more documentation, see `timeline/README.md` which has a section on overlays.\n */\nexport class Overlays extends EventTarget {\n /**\n * The list of active overlays. Overlays can't be marked as visible or\n * hidden; every overlay in this list is rendered.\n * We track each overlay against the HTML Element we have rendered. This is\n * because on first render of a new overlay, we create it, but then on\n * subsequent renders we do not destroy and recreate it, instead we update it\n * based on the new position of the timeline.\n */\n #overlaysToElements: Map = new Map();\n\n // When the Entries Link Annotation is created, the arrow needs to follow the mouse.\n // Update the mouse coordinates while it is being created.\n #lastMouseOffsetX: number|null = null;\n #lastMouseOffsetY: number|null = null;\n // `entriesLinkInProgress` is the entries link Overlay that has not yet been fully created\n // and only has the entry that the link starts from set.\n // We save it as a separate variable because when the second entry of the link is not chosen yet,\n // the arrow follows the mouse. To achieve that, update the coordinates of `entriesLinkInProgress`\n // on mousemove. There can only be one link in the process on being created so the mousemove\n // only needs to update `entriesLinkInProgress` link overlay.\n #entriesLinkInProgress: EntriesLink|null;\n\n #dimensions: ActiveDimensions = {\n trace: {\n visibleWindow: null,\n },\n charts: {\n main: null,\n network: null,\n },\n };\n\n /**\n * To calculate the Y pixel value for an event we need access to the chart\n * and data provider in order to find out what level the event is on, and from\n * there calculate the pixel value for that level.\n */\n #charts: TimelineCharts;\n\n /**\n * The Overlays class will take each overlay, generate its HTML, and add it\n * to the container. This container is provided for us when the class is\n * created so we can manage its contents as overlays come and go.\n */\n #overlaysContainer: HTMLElement;\n\n // Setting that specififed if the annotations overlays need to be visible.\n // It is switched on/off from the annotations tab in the sidebar.\n readonly #annotationsHiddenSetting: Common.Settings.Setting;\n\n /**\n * The OverlaysManager sometimes needs to find out if an entry is visible or\n * not, and if not, why not - for example, if the user has collapsed its\n * parent. We define these query functions that must be supplied in order to\n * answer these questions.\n */\n #queries: OverlayEntryQueries;\n\n constructor(init: {\n container: HTMLElement,\n flameChartsContainers: {\n main: HTMLElement,\n network: HTMLElement,\n },\n charts: TimelineCharts,\n entryQueries: OverlayEntryQueries,\n }) {\n super();\n this.#overlaysContainer = init.container;\n this.#charts = init.charts;\n this.#queries = init.entryQueries;\n this.#entriesLinkInProgress = null;\n this.#annotationsHiddenSetting = Common.Settings.Settings.instance().moduleSetting('annotations-hidden');\n this.#annotationsHiddenSetting.addChangeListener(this.update.bind(this));\n\n // HTMLElements of both Flamecharts. They are used to get the mouse position over the Flamecharts.\n init.flameChartsContainers.main.addEventListener(\n 'mousemove', event => this.#updateMouseCoordinatesProgressEntriesLink.bind(this)(event, 'main'));\n init.flameChartsContainers.network.addEventListener(\n 'mousemove', event => this.#updateMouseCoordinatesProgressEntriesLink.bind(this)(event, 'network'));\n }\n\n // Mousemove event listener to get mouse coordinates and update them for the entries link that is being created.\n //\n // The 'mousemove' event is attached to `flameChartsContainers` instead of `overlaysContainer`\n // because `overlaysContainer` doesn't have events to enable the interaction with the\n // Flamecharts beneath it.\n #updateMouseCoordinatesProgressEntriesLink(event: Event, chart: EntryChartLocation): void {\n const mouseEvent = (event as MouseEvent);\n this.#lastMouseOffsetX = mouseEvent.offsetX;\n this.#lastMouseOffsetY = mouseEvent.offsetY;\n\n if (!this.#entriesLinkInProgress || this.#entriesLinkInProgress.entryTo) {\n return;\n }\n\n // The Overlays layer coordinates cover both Network and Main Charts, while the mousemove\n // coordinates are received from the charts individually and start from 0 for each chart.\n //\n // To make it work on the overlays, we need to know which chart the entry belongs to and,\n // if it is on the main chart, add the height of the Network chart to get correct Entry\n // coordinates on the Overlays layer.\n const networkHeight = this.#dimensions.charts.network?.heightPixels ?? 0;\n const linkInProgressElement = this.#overlaysToElements.get(this.#entriesLinkInProgress);\n\n if (linkInProgressElement) {\n const component = linkInProgressElement.querySelector('devtools-entries-link-overlay') as\n Components.EntriesLinkOverlay.EntriesLinkOverlay;\n const yCoordinate = mouseEvent.offsetY + ((chart === 'main') ? networkHeight : 0);\n component.toEntryCoordinateAndDimentions = {x: mouseEvent.offsetX, y: yCoordinate};\n }\n }\n\n /**\n * Add a new overlay to the view.\n */\n add(newOverlay: T): T {\n if (this.#overlaysToElements.has(newOverlay)) {\n return newOverlay;\n }\n\n /**\n * If the overlay type is a singleton, and we already have one, we update\n * the existing one, rather than create a new one. This ensures you can only\n * ever have one instance of the overlay type.\n */\n const existing = this.overlaysOfType(newOverlay.type);\n if (overlayIsSingleton(newOverlay) && existing[0]) {\n this.updateExisting(existing[0], newOverlay);\n return existing[0];\n }\n\n // By setting the value to null, we ensure that on the next render that the\n // overlay will have a new HTML element created for it.\n this.#overlaysToElements.set(newOverlay, null);\n return newOverlay;\n }\n\n /**\n * Update an existing overlay without destroying and recreating its\n * associated DOM.\n *\n * This is useful if you need to rapidly update an overlay's data - e.g.\n * dragging to create time ranges - without the thrashing of destroying the\n * old overlay and re-creating the new one.\n */\n updateExisting(existingOverlay: T, newData: Partial): void {\n if (!this.#overlaysToElements.has(existingOverlay)) {\n console.error('Trying to update an overlay that does not exist.');\n return;\n }\n\n for (const [key, value] of Object.entries(newData)) {\n // newData is of type Partial, so each key must exist in T, but\n // Object.entries doesn't carry that information.\n const k = key as keyof T;\n existingOverlay[k] = value;\n }\n }\n\n enterLabelEditMode(overlay: EntryLabel): void {\n // Entry edit state can be triggered from outside the label component by clicking on the\n // Entry that already has a label. Instead of creating a new label, set the existing entry\n // label into an editable state.\n const element = this.#overlaysToElements.get(overlay);\n const component = element?.querySelector('devtools-entry-label-overlay');\n if (component) {\n component.setLabelEditabilityAndRemoveEmptyLabel(true);\n }\n }\n\n /**\n * @returns the list of overlays associated with a given entry.\n */\n overlaysForEntry(entry: OverlayEntry): TimelineOverlay[] {\n const matches: TimelineOverlay[] = [];\n for (const [overlay] of this.#overlaysToElements) {\n if ('entry' in overlay && overlay.entry === entry) {\n matches.push(overlay);\n }\n }\n return matches;\n }\n\n /**\n * Removes any active overlays that match the provided type.\n * @returns the number of overlays that were removed.\n */\n removeOverlaysOfType(type: TimelineOverlay['type']): number {\n const overlaysToRemove = Array.from(this.#overlaysToElements.keys()).filter(overlay => {\n return overlay.type === type;\n });\n for (const overlay of overlaysToRemove) {\n this.remove(overlay);\n }\n return overlaysToRemove.length;\n }\n\n /**\n * @returns all overlays that match the provided type.\n */\n overlaysOfType(type: T['type']): NoInfer[] {\n const matches: T[] = [];\n\n function overlayIsOfType(overlay: TimelineOverlay): overlay is T {\n return overlay.type === type;\n }\n\n for (const [overlay] of this.#overlaysToElements) {\n if (overlayIsOfType(overlay)) {\n matches.push(overlay);\n }\n }\n return matches;\n }\n\n /**\n * Removes the provided overlay from the list of overlays and destroys any\n * DOM associated with it.\n */\n remove(overlay: TimelineOverlay): void {\n const htmlElement = this.#overlaysToElements.get(overlay);\n if (htmlElement && this.#overlaysContainer) {\n this.#overlaysContainer.removeChild(htmlElement);\n }\n this.#overlaysToElements.delete(overlay);\n }\n\n /**\n * Update the dimenions of a chart.\n * IMPORTANT: this does not trigger a re-draw. You must call the render() method manually.\n */\n updateChartDimensions(chart: EntryChartLocation, dimensions: FlameChartDimensions): void {\n this.#dimensions.charts[chart] = dimensions;\n }\n\n /**\n * Update the visible window of the UI.\n * IMPORTANT: this does not trigger a re-draw. You must call the render() method manually.\n */\n updateVisibleWindow(visibleWindow: Trace.Types.Timing.TraceWindowMicroSeconds): void {\n this.#dimensions.trace.visibleWindow = visibleWindow;\n }\n\n /**\n * Clears all overlays and all data. Call this when the trace is changing\n * (e.g. the user has imported/recorded a new trace) and we need to start from\n * scratch and remove all overlays relating to the preivous trace.\n */\n reset(): void {\n if (this.#overlaysContainer) {\n this.#overlaysContainer.innerHTML = '';\n }\n this.#overlaysToElements.clear();\n\n // Clear out dimensions from the old Flame Charts.\n this.#dimensions.trace.visibleWindow = null;\n this.#dimensions.charts.main = null;\n this.#dimensions.charts.network = null;\n }\n\n /**\n * Updates the Overlays UI: new overlays will be rendered onto the view, and\n * existing overlays will have their positions changed to ensure they are\n * rendered in the right place.\n */\n update(): void {\n const timeRangeOverlays: TimeRangeLabel[] = [];\n for (const [overlay, existingElement] of this.#overlaysToElements) {\n const element = existingElement || this.#createElementForNewOverlay(overlay);\n if (!existingElement) {\n // This is a new overlay, so we have to store the element and add it to the DOM.\n this.#overlaysToElements.set(overlay, element);\n this.#overlaysContainer.appendChild(element);\n }\n\n // Now we position the overlay on the timeline.\n this.#positionOverlay(overlay, element);\n\n // And now we give every overlay a chance to react to its new position, if it needs to\n this.#updateOverlayElementAfterPositioning(overlay, element);\n\n if (overlay.type === 'TIME_RANGE') {\n timeRangeOverlays.push(overlay);\n }\n }\n\n if (timeRangeOverlays.length > 1) { // If there are 0 or 1 overlays, they can't overlap\n this.#positionOverlappingTimeRangeLabels(timeRangeOverlays);\n }\n }\n\n /**\n * If any time-range overlays overlap, we try to adjust their horizontal\n * position in order to make sure you can distinguish them and that the labels\n * do not entirely overlap.\n * This is very much minimal best effort, and does not guarantee that all\n * labels will remain readable.\n */\n #positionOverlappingTimeRangeLabels(overlays: readonly TimeRangeLabel[]): void {\n const overlaysSorted = overlays.toSorted((o1, o2) => {\n return o1.bounds.min - o2.bounds.min;\n });\n\n // Track the overlays which overlap other overlays.\n // This isn't bi-directional: if we find that O2 overlaps O1, we will\n // store O1 => [O2]. We will not then also store O2 => [O1], because we\n // only need to deal with the overlap once.\n const overlapsByOverlay: Map = new Map();\n\n for (let i = 0; i < overlaysSorted.length; i++) {\n const current = overlaysSorted[i];\n const overlaps: TimeRangeLabel[] = [];\n\n // Walk through subsequent overlays and find stop when you find the next one that does not overlap.\n for (let j = i + 1; j < overlaysSorted.length; j++) {\n const next = overlaysSorted[j];\n const currentAndNextOverlap = Trace.Helpers.Timing.boundsIncludeTimeRange({\n bounds: current.bounds,\n timeRange: next.bounds,\n });\n if (currentAndNextOverlap) {\n overlaps.push(next);\n } else {\n // Overlays are sorted by time, if this one does not overlap, the next one will not, so we can break.\n break;\n }\n }\n overlapsByOverlay.set(current, overlaps);\n }\n for (const [firstOverlay, overlappingOverlays] of overlapsByOverlay) {\n const element = this.#overlaysToElements.get(firstOverlay);\n if (!element) {\n continue;\n }\n\n // If the first overlay is adjusted, we can start back from 0 again\n // rather than continually increment up.\n let firstIndexForOverlapClass = 1;\n if (element.getAttribute('class')?.includes('overlap-')) {\n firstIndexForOverlapClass = 0;\n }\n\n overlappingOverlays.forEach(overlay => {\n const element = this.#overlaysToElements.get(overlay);\n element?.classList.add(`overlap-${firstIndexForOverlapClass++}`);\n });\n }\n }\n\n #positionOverlay(overlay: TimelineOverlay, element: HTMLElement): void {\n const annotationsAreHidden = this.#annotationsHiddenSetting.get();\n switch (overlay.type) {\n case 'ENTRY_SELECTED': {\n const isVisible = this.entryIsVisibleOnChart(overlay.entry);\n this.#setOverlayElementVisibility(element, isVisible);\n if (isVisible) {\n this.#positionEntryBorderOutlineType(overlay, element);\n }\n break;\n }\n case 'ENTRY_OUTLINE': {\n const selectedOverlay = this.overlaysOfType('ENTRY_SELECTED')?.at(0);\n // Check if this entry has also been selected by the user. If it has,\n // do not show the outline, but only show the selected outline.\n const outlinedEntryIsSelected = Boolean(selectedOverlay && selectedOverlay.entry === overlay.entry);\n if (!outlinedEntryIsSelected && this.entryIsVisibleOnChart(overlay.entry)) {\n this.#setOverlayElementVisibility(element, true);\n this.#positionEntryBorderOutlineType(overlay, element);\n } else {\n this.#setOverlayElementVisibility(element, false);\n }\n break;\n }\n\n case 'TIME_RANGE': {\n // The time range annotation can also be used to measure a selection in the timeline and is not saved if no label is added.\n // Therefore, we only care about the annotation hidden setting if the time range has a label.\n if (overlay.label.length) {\n this.#setOverlayElementVisibility(element, !annotationsAreHidden);\n }\n this.#positionTimeRangeOverlay(overlay, element);\n break;\n }\n case 'ENTRY_LABEL': {\n const entryVisible = this.entryIsVisibleOnChart(overlay.entry);\n this.#setOverlayElementVisibility(element, entryVisible && !annotationsAreHidden);\n if (entryVisible) {\n const entryLabelParams = this.#positionEntryLabelOverlay(overlay, element);\n const component = element.querySelector('devtools-entry-label-overlay');\n if (component && entryLabelParams) {\n component.entryLabelParams = entryLabelParams;\n }\n }\n break;\n }\n case 'ENTRIES_LINK': {\n // The exact entries that are linked to could be collapsed in a flame\n // chart, so we figure out the best visible entry pairs to draw\n // between.\n const entriesToConnect = this.#calculateFromAndToForEntriesLink(overlay);\n if (entriesToConnect === null) {\n // Unexpected situation: hide the overlay and move on\n this.#setOverlayElementVisibility(element, false);\n break;\n }\n\n // If both entries are in collapsed tracks, we hide the overlay completely.\n const fromEntryInCollapsedTrack = this.#entryIsInCollapsedTrack(entriesToConnect.entryFrom);\n const toEntryInCollapsedTrack =\n entriesToConnect.entryTo && this.#entryIsInCollapsedTrack(entriesToConnect.entryTo);\n const bothEntriesInCollapsedTrack = Boolean(fromEntryInCollapsedTrack && toEntryInCollapsedTrack);\n if (bothEntriesInCollapsedTrack) {\n this.#setOverlayElementVisibility(element, false);\n return;\n }\n\n const isVisible = !annotationsAreHidden;\n this.#setOverlayElementVisibility(element, isVisible);\n if (isVisible) {\n this.#positionEntriesLinkOverlay(overlay, element, entriesToConnect);\n\n // If either entry (but not both) is in a track that the user has collapsed, we do not\n // show the connection at all, but we still show the borders around\n // the entry. So in this case we mark the overlay as visible, but\n // tell it to not draw the arrow.\n const hideArrow = Boolean(fromEntryInCollapsedTrack || toEntryInCollapsedTrack);\n const component = element.querySelector('devtools-entries-link-overlay');\n if (component) {\n component.hideArrow = hideArrow;\n }\n }\n break;\n }\n case 'ENTRIES_LINK_CREATE_BUTTON': {\n const isVisible = this.entryIsVisibleOnChart(overlay.entry);\n this.#setOverlayElementVisibility(element, isVisible);\n if (isVisible) {\n this.#positionCreateEntriesLinkOverlay(overlay, element);\n }\n break;\n }\n case 'TIMESPAN_BREAKDOWN': {\n this.#positionTimespanBreakdownOverlay(overlay, element);\n // TODO: Have the timespan squeeze instead.\n if (overlay.entry) {\n const {visibleWindow} = this.#dimensions.trace;\n const isVisible = Boolean(\n visibleWindow && this.#entryIsVerticallyVisibleOnChart(overlay.entry) &&\n Trace.Helpers.Timing.boundsIncludeTimeRange({\n bounds: visibleWindow,\n timeRange: overlay.sections[0].bounds,\n }),\n );\n this.#setOverlayElementVisibility(element, isVisible);\n }\n break;\n }\n\n case 'CURSOR_TIMESTAMP_MARKER': {\n const {visibleWindow} = this.#dimensions.trace;\n // Only update the position if the timestamp of this marker is within\n // the visible bounds.\n const isVisible =\n Boolean(visibleWindow && Trace.Helpers.Timing.timestampIsInBounds(visibleWindow, overlay.timestamp));\n this.#setOverlayElementVisibility(element, isVisible);\n if (isVisible) {\n this.#positionTimestampMarker(overlay, element);\n }\n break;\n }\n\n case 'CANDY_STRIPED_TIME_RANGE': {\n const {visibleWindow} = this.#dimensions.trace;\n // If the bounds of this overlay are not within the visible bounds, we\n // can skip updating its position and just hide it.\n\n const isVisible = Boolean(\n visibleWindow && this.#entryIsVerticallyVisibleOnChart(overlay.entry) &&\n Trace.Helpers.Timing.boundsIncludeTimeRange({\n bounds: visibleWindow,\n timeRange: overlay.bounds,\n }));\n this.#setOverlayElementVisibility(element, isVisible);\n if (isVisible) {\n this.#positionCandyStripedTimeRange(overlay, element);\n }\n break;\n }\n\n default: {\n Platform.TypeScriptUtilities.assertNever(overlay, `Unknown overlay: ${JSON.stringify(overlay)}`);\n }\n }\n }\n\n #positionTimestampMarker(overlay: CursorTimestampMarker, element: HTMLElement): void {\n // Because we are adjusting the x position, we can use either chart here.\n const x = this.#xPixelForMicroSeconds('main', overlay.timestamp);\n element.style.left = `${x}px`;\n }\n\n #positionTimespanBreakdownOverlay(overlay: TimespanBreakdown, element: HTMLElement): void {\n const component = element.querySelector('devtools-timespan-breakdown-overlay');\n const shadow = component?.shadowRoot;\n const elementSections = shadow?.querySelectorAll('.timespan-breakdown-overlay-section');\n\n if (overlay.sections.length === 0) {\n return;\n }\n // Handle horizontal positioning.\n const leftEdgePixel = this.#xPixelForMicroSeconds('main', overlay.sections[0].bounds.min);\n const rightEdgePixel =\n this.#xPixelForMicroSeconds('main', overlay.sections[overlay.sections.length - 1].bounds.max);\n if (leftEdgePixel === null || rightEdgePixel === null) {\n return;\n }\n\n const rangeWidth = rightEdgePixel - leftEdgePixel;\n element.style.left = `${leftEdgePixel}px`;\n element.style.width = `${rangeWidth}px`;\n\n if (!(elementSections?.length)) {\n return;\n }\n\n let count = 0;\n for (const section of overlay.sections) {\n const leftPixel = this.#xPixelForMicroSeconds('main', section.bounds.min);\n const rightPixel = this.#xPixelForMicroSeconds('main', section.bounds.max);\n if (leftPixel === null || rightPixel === null) {\n return;\n }\n const rangeWidth = rightPixel - leftPixel;\n const sectionElement = elementSections[count];\n\n sectionElement.style.left = `${leftPixel}px`;\n sectionElement.style.width = `${rangeWidth}px`;\n count++;\n }\n\n // Handle vertical positioning based on the entry's vertical position.\n if (overlay.entry) {\n const y = this.yPixelForEventOnChart(overlay.entry);\n if (y === null) {\n return;\n }\n\n // Max height for the overlay box.\n const MAX_BOX_HEIGHT = 50;\n // Some padding so the box hovers just on top.\n const PADDING = 7;\n\n // Where the timespan breakdown should sit. Slightly on top of the entry.\n const bottom = y - PADDING;\n\n // Available space between the bottom of the overlay and top of the chart.\n const minSpace = Math.max(bottom, 0);\n // Contrain height to available space.\n const height = Math.min(MAX_BOX_HEIGHT, minSpace);\n\n elementSections[0].style.maxHeight = `${MAX_BOX_HEIGHT}px`;\n elementSections[0].style.height = `${height}px`;\n\n const top = bottom - height;\n element.style.top = `${top}px`;\n }\n }\n\n #positionCreateEntriesLinkOverlay(overlay: CreateEntriesLink, element: HTMLElement): void {\n const componentDefault = element.querySelector('devtools-create-entries-link-overlay');\n\n if (componentDefault) {\n const component = componentDefault.querySelector('devtools-entries-link-overlay');\n if (!component) {\n const entryStartX = this.xPixelForEventStartOnChart(overlay.entry) ?? 0;\n const entryEndX = this.xPixelForEventEndOnChart(overlay.entry) ?? 0;\n const entryWidth = entryEndX - entryStartX;\n const entryStartY = (this.yPixelForEventOnChart(overlay.entry) ?? 0);\n const entryHeight = this.pixelHeightForEventOnChart(overlay.entry) ?? 0;\n\n componentDefault.fromEntryData = {entryStartX, entryStartY, entryWidth, entryHeight};\n }\n }\n }\n /**\n * Positions the arrow between two entries. Takes in the entriesToConnect\n * because if one of the original entries is hidden in a collapsed main thread\n * icicle, we use its parent to connect to.\n */\n #positionEntriesLinkOverlay(overlay: EntriesLink, element: HTMLElement, entriesToConnect: EntriesLinkVisibleEntries):\n void {\n const component = element.querySelector('devtools-entries-link-overlay');\n if (component) {\n const {entryFrom, entryTo, entryFromIsSource, entryToIsSource} = entriesToConnect;\n const fromEntryStartX = this.xPixelForEventStartOnChart(entryFrom) ?? 0;\n const fromEntryEndX = this.xPixelForEventEndOnChart(entryFrom) ?? 0;\n const fromEntryLength = fromEntryEndX - fromEntryStartX;\n const fromEntryHeight = this.pixelHeightForEventOnChart(entryFrom) ?? 0;\n\n const entryFromVisibility = this.entryIsVisibleOnChart(entryFrom);\n const entryToVisibility = entryTo ? this.entryIsVisibleOnChart(entryTo) : false;\n\n // If the 'from' entry is visible, set the entry Y as an arrow start coordinate. Ff not, get the canvas edge coordinate to for the arrow to start from.\n const yPixelForFromArrow = (entryFromVisibility ? this.yPixelForEventOnChart(entryFrom) :\n this.#yCoordinateForNotVisibleEntry(entryFrom)) ??\n 0;\n\n component.fromEntryIsSource = entryFromIsSource;\n component.toEntryIsSource = entryToIsSource;\n\n component.entriesVisibility = {\n fromEntryVisibility: entryFromVisibility,\n toEntryVisibility: entryToVisibility,\n };\n\n component.fromEntryCoordinateAndDimentions =\n {x: fromEntryStartX, y: yPixelForFromArrow, length: fromEntryLength, height: fromEntryHeight};\n\n // If entryTo exists, pass the coordinates and dimentions of the entry that the arrow snaps to.\n // If it does not, the event tracking mouse coordinates updates 'to coordinates' so the arrow follows the mouse instead.\n if (entryTo) {\n const toEntryStartX = this.xPixelForEventStartOnChart(entryTo) ?? 0;\n const toEntryEndX = this.xPixelForEventEndOnChart(entryTo) ?? 0;\n const toEntryWidth = toEntryEndX - toEntryStartX;\n const toEntryHeight = this.pixelHeightForEventOnChart(entryTo) ?? 0;\n\n // If the 'to' entry is visible, set the entry Y as an arrow coordinate to point ot. Ff not, get the canvas edge coordate to point the arrow to.\n const yPixelForToArrow =\n ((this.entryIsVisibleOnChart(entryTo)) ? this.yPixelForEventOnChart(entryTo) :\n this.#yCoordinateForNotVisibleEntry(entryTo)) ??\n 0;\n component.toEntryCoordinateAndDimentions = {\n x: toEntryStartX ?? 0,\n y: yPixelForToArrow,\n length: toEntryWidth,\n height: toEntryHeight,\n };\n\n } else if (this.#lastMouseOffsetX && this.#lastMouseOffsetY) {\n // The second coordinate for in progress link gets updated on mousemove\n this.#entriesLinkInProgress = overlay;\n }\n }\n }\n\n /**\n * Return Y coordinate for an arrow connecting 2 entries to attach to if the entry is not visible.\n * For example, if the entry is scrolled up from the visible area , return the y index of the edge of the track:\n * --\n * | | - entry off the visible chart\n * --\n *\n * --Y--------------- -- Y is the returned coordinate that the arrow should point to\n *\n * flamechart data -- visible flamechart data between the 2 lines\n * ------------------\n *\n * On the contrary, if the entry is scrolled off the bottom, get the coordinate of the top of the visible canvas.\n */\n #yCoordinateForNotVisibleEntry(entry: OverlayEntry): number {\n const chartName = chartForEntry(entry);\n\n const y = this.yPixelForEventOnChart(entry);\n if (y === null) {\n return 0;\n }\n\n if (chartName === 'main') {\n if (!this.#dimensions.charts.main?.heightPixels) {\n // Shouldn't happen, but if the main chart has no height, nothing on it is visible.\n return 0;\n }\n\n const yWithoutNetwork = y - this.networkChartOffsetHeight();\n // Check if the y position is less than 0. If it, the entry is off the top of the track canvas.\n // In that case, return the height of network track, which is also the top of main track.\n if (yWithoutNetwork < 0) {\n return this.networkChartOffsetHeight();\n }\n }\n\n if (chartName === 'network') {\n if (!this.#dimensions.charts.network) {\n return 0;\n }\n\n // The event is off the bottom of the network chart. In this case return the bottom of the network chart.\n if (y > this.#dimensions.charts.network.heightPixels ?? 0) {\n return this.#dimensions.charts.network.heightPixels;\n }\n }\n\n // In other cases, return the y of the entry\n return y;\n }\n\n #positionTimeRangeOverlay(overlay: TimeRangeLabel, element: HTMLElement): void {\n // Time ranges span both charts, it doesn't matter which one we pass here.\n // It's used to get the width of the container, and both charts have the\n // same width.\n const leftEdgePixel = this.#xPixelForMicroSeconds('main', overlay.bounds.min);\n const rightEdgePixel = this.#xPixelForMicroSeconds('main', overlay.bounds.max);\n if (leftEdgePixel === null || rightEdgePixel === null) {\n return;\n }\n\n const rangeWidth = rightEdgePixel - leftEdgePixel;\n\n element.style.left = `${leftEdgePixel}px`;\n element.style.width = `${rangeWidth}px`;\n }\n\n /**\n * Positions an EntryLabel overlay\n * @param overlay - the EntrySelected overlay that we need to position.\n * @param element - the DOM element representing the overlay\n */\n #positionEntryLabelOverlay(overlay: EntryLabel, element: HTMLElement):\n {height: number, width: number, cutOffEntryHeight: number, chart: string}|null {\n const chartName = chartForEntry(overlay.entry);\n const x = this.xPixelForEventStartOnChart(overlay.entry);\n const y = this.yPixelForEventOnChart(overlay.entry);\n const {endTime} = timingsForOverlayEntry(overlay.entry);\n const endX = this.#xPixelForMicroSeconds(chartName, endTime);\n const entryHeight = this.pixelHeightForEventOnChart(overlay.entry) ?? 0;\n\n if (x === null || y === null || endX === null) {\n return null;\n }\n\n // The width of the overlay is by default the width of the entry. However\n // we modify that for instant events like LCP markers, and also ensure a\n // minimum width.\n const widthPixels = endX - x;\n // The part of the overlay that draws a box around an entry is always at least 2px wide.\n const entryWidth = Math.max(2, widthPixels);\n const networkHeight = this.#dimensions.charts.network?.heightPixels ?? 0;\n\n // Find the part of the entry that is covered by resizer to not draw it over the resizer.\n // If the entry is in the main flamechart, find the part of the entry that is covered from the top.\n // If it is in the network track, find the part covered by the resizer from the bottom.\n const entryHiddenTop = this.networkChartOffsetHeight() - y;\n const entryHiddenBottom = entryHeight + y - networkHeight;\n // If the covered part is negative, the entry is fully visible and the cut off part is 0.\n const cutOffEntryHeight = Math.max((chartName === 'main') ? entryHiddenTop : entryHiddenBottom, 0);\n\n let topOffset = y - Components.EntryLabelOverlay.EntryLabelOverlay.LABEL_AND_CONNECTOR_HEIGHT;\n // If part of the entry height is not visible in the main flamechart, take that into the account in the top offset.\n if (chartName === 'main') {\n topOffset += cutOffEntryHeight;\n }\n\n // Position the start of label overlay at the start of the entry + length of connector + legth of the label element\n element.style.top = `${topOffset}px`;\n // Position the start of the entry label overlay in the the middle of the entry.\n element.style.left = `${x + entryWidth / 2}px`;\n\n return {height: entryHeight, width: entryWidth, cutOffEntryHeight, chart: chartName};\n }\n\n #positionCandyStripedTimeRange(overlay: CandyStripedTimeRange, element: HTMLElement): void {\n const chartName = chartForEntry(overlay.entry);\n\n const startX = this.#xPixelForMicroSeconds(chartName, overlay.bounds.min);\n const endX = this.#xPixelForMicroSeconds(chartName, overlay.bounds.max);\n if (startX === null || endX === null) {\n return;\n }\n\n const widthPixels = endX - startX;\n // The entry selected overlay is always at least 2px wide.\n const finalWidth = Math.max(2, widthPixels);\n element.style.width = `${finalWidth}px`;\n element.style.left = `${startX}px`;\n\n let y = this.yPixelForEventOnChart(overlay.entry);\n if (y === null) {\n return;\n }\n\n const totalHeight = this.pixelHeightForEventOnChart(overlay.entry) ?? 0;\n\n // We might modify the height we use when drawing the overlay, hence copying the totalHeight.\n let height = totalHeight;\n if (height === null) {\n return;\n }\n\n // If the event is on the main chart, we need to adjust its selected border\n // if the event is cut off the top of the screen, because we need to ensure\n // that it does not overlap the resize element. Unfortunately we cannot\n // z-index our way out of this, so instead we calculate if the event is cut\n // off, and if it is, we draw the partial selected outline and do not draw\n // the top border, making it appear like it is going behind the resizer.\n // We don't need to worry about it going off the bottom, because in that\n // case we don't draw the overlay anyway.\n if (chartName === 'main') {\n const chartTopPadding = this.networkChartOffsetHeight();\n // We now calculate the available height: if the entry is cut off we don't\n // show the border for the part that is cut off.\n const cutOffTop = y < chartTopPadding;\n\n height = cutOffTop ? Math.abs(y + height - chartTopPadding) : height;\n element.classList.toggle('cut-off-top', cutOffTop);\n if (cutOffTop) {\n // Adjust the y position: we need to move it down from the top Y\n // position to the Y position of the first visible pixel. The\n // adjustment is totalHeight - height because if the totalHeight is 17,\n // and the visibleHeight is 5, we need to draw the overay at 17-5=12px\n // vertically from the top of the event.\n y = y + totalHeight - height;\n }\n } else {\n // If the event is on the network chart, we use the same logic as above\n // for the main chart, but to check if the event is cut off the bottom of\n // the network track and only part of the overlay is visible.\n // We don't need to worry about the event going off the top of the panel\n // as we can show the full overlay and it gets cut off by the minimap UI.\n const networkHeight = this.#dimensions.charts.network?.heightPixels ?? 0;\n const lastVisibleY = y + totalHeight;\n const cutOffBottom = lastVisibleY > networkHeight;\n const cutOffTop = y > networkHeight;\n element.classList.toggle('cut-off-top', cutOffTop);\n element.classList.toggle('cut-off-bottom', cutOffBottom);\n if (cutOffBottom) {\n // Adjust the height of the overlay to be the amount of visible pixels.\n height = networkHeight - y;\n }\n }\n\n element.style.height = `${height}px`;\n element.style.top = `${y}px`;\n }\n\n /**\n * Positions an EntrySelected or EntryOutline overlay. These share the same\n * method as they are both borders around an entry.\n * @param overlay - the EntrySelected/EntryOutline overlay that we need to position.\n * @param element - the DOM element representing the overlay\n */\n #positionEntryBorderOutlineType(overlay: EntrySelected|EntryOutline, element: HTMLElement): void {\n const chartName = chartForEntry(overlay.entry);\n let x = this.xPixelForEventStartOnChart(overlay.entry);\n let y = this.yPixelForEventOnChart(overlay.entry);\n\n if (x === null || y === null) {\n return;\n }\n\n const {endTime} = timingsForOverlayEntry(overlay.entry);\n const endX = this.#xPixelForMicroSeconds(chartName, endTime);\n if (endX === null) {\n return;\n }\n\n const totalHeight = this.pixelHeightForEventOnChart(overlay.entry) ?? 0;\n\n // We might modify the height we use when drawing the overlay, hence copying the totalHeight.\n let height = totalHeight;\n if (height === null) {\n return;\n }\n\n // The width of the overlay is by default the width of the entry. However\n // we modify that for instant events like LCP markers, and also ensure a\n // minimum width.\n let widthPixels = endX - x;\n\n const provider = chartName === 'main' ? this.#charts.mainProvider : this.#charts.networkProvider;\n const chart = chartName === 'main' ? this.#charts.mainChart : this.#charts.networkChart;\n const index = provider.indexForEvent?.(overlay.entry);\n const customPos = chart.getCustomDrawnPositionForEntryIndex(index ?? -1);\n if (customPos) {\n // Some events like markers and layout shifts define their exact coordinates explicitly.\n // If this is one of those events we should change the overlay coordinates to match.\n x = customPos.x;\n widthPixels = customPos.width;\n }\n\n // The entry selected overlay is always at least 2px wide.\n const finalWidth = Math.max(2, widthPixels);\n element.style.width = `${finalWidth}px`;\n\n // If the event is on the main chart, we need to adjust its selected border\n // if the event is cut off the top of the screen, because we need to ensure\n // that it does not overlap the resize element. Unfortunately we cannot\n // z-index our way out of this, so instead we calculate if the event is cut\n // off, and if it is, we draw the partial selected outline and do not draw\n // the top border, making it appear like it is going behind the resizer.\n // We don't need to worry about it going off the bottom, because in that\n // case we don't draw the overlay anyway.\n if (chartName === 'main') {\n const chartTopPadding = this.networkChartOffsetHeight();\n // We now calculate the available height: if the entry is cut off we don't\n // show the border for the part that is cut off.\n const cutOffTop = y < chartTopPadding;\n\n height = cutOffTop ? Math.abs(y + height - chartTopPadding) : height;\n element.classList.toggle('cut-off-top', cutOffTop);\n if (cutOffTop) {\n // Adjust the y position: we need to move it down from the top Y\n // position to the Y position of the first visible pixel. The\n // adjustment is totalHeight - height because if the totalHeight is 17,\n // and the visibleHeight is 5, we need to draw the overay at 17-5=12px\n // vertically from the top of the event.\n y = y + totalHeight - height;\n }\n } else {\n // If the event is on the network chart, we use the same logic as above\n // for the main chart, but to check if the event is cut off the bottom of\n // the network track and only part of the overlay is visible.\n // We don't need to worry about the even going off the top of the panel\n // as we can show the full overlay and it gets cut off by the minimap UI.\n const networkHeight = this.#dimensions.charts.network?.heightPixels ?? 0;\n const lastVisibleY = y + totalHeight;\n const cutOffBottom = lastVisibleY > networkHeight;\n element.classList.toggle('cut-off-bottom', cutOffBottom);\n if (cutOffBottom) {\n // Adjust the height of the overlay to be the amount of visible pixels.\n height = networkHeight - y;\n }\n }\n\n element.style.height = `${height}px`;\n element.style.top = `${y}px`;\n element.style.left = `${x}px`;\n }\n\n /**\n * We draw an arrow between connected entries but this can get complicated\n * depending on if the entries are visible or not. For example, the user might\n * draw a connection to an entry in the main thread but then collapse the\n * parent of that entry. In this case the entry we want to draw to is the\n * first visible parent of that entry rather than the (invisible) entry.\n */\n #calculateFromAndToForEntriesLink(overlay: EntriesLink): EntriesLinkVisibleEntries|null {\n if (!overlay.entryTo) {\n // This case is where the user has clicked on the first entry and needs\n // to pick a second. In this case they can only pick from visible\n // entries, so we don't need to do any checks and can just return.\n return {\n entryFrom: overlay.entryFrom,\n entryTo: overlay.entryTo,\n entryFromIsSource: true,\n entryToIsSource: true,\n };\n }\n\n let entryFrom: OverlayEntry|null = overlay.entryFrom;\n let entryTo: OverlayEntry|null = overlay.entryTo ?? null;\n\n if (this.#queries.isEntryCollapsedByUser(overlay.entryFrom)) {\n entryFrom = this.#queries.firstVisibleParentForEntry(overlay.entryFrom);\n }\n if (overlay.entryTo && this.#queries.isEntryCollapsedByUser(overlay.entryTo)) {\n entryTo = this.#queries.firstVisibleParentForEntry(overlay.entryTo);\n }\n\n if (entryFrom === null || entryTo === null) {\n // We cannot draw this overlay; so return null;\n // The only valid case of entryTo being null/undefined has been dealt\n // with already at the start of this function.\n return null;\n }\n\n return {\n entryFrom,\n entryFromIsSource: entryFrom === overlay.entryFrom,\n entryTo,\n entryToIsSource: entryTo === overlay.entryTo,\n };\n }\n\n #createElementForNewOverlay(overlay: TimelineOverlay): HTMLElement {\n const div = document.createElement('div');\n div.classList.add('overlay-item', `overlay-type-${overlay.type}`);\n switch (overlay.type) {\n case 'ENTRY_LABEL': {\n const shouldDrawLabelBelowEntry = Trace.Types.Events.isLegacyTimelineFrame(overlay.entry);\n const component = new Components.EntryLabelOverlay.EntryLabelOverlay(\n overlay.label, chartForEntry(overlay.entry) === 'main', shouldDrawLabelBelowEntry);\n component.addEventListener(Components.EntryLabelOverlay.EmptyEntryLabelRemoveEvent.eventName, () => {\n this.dispatchEvent(new AnnotationOverlayActionEvent(overlay, 'Remove'));\n });\n component.addEventListener(Components.EntryLabelOverlay.EntryLabelChangeEvent.eventName, event => {\n const newLabel = (event as Components.EntryLabelOverlay.EntryLabelChangeEvent).newLabel;\n overlay.label = newLabel;\n this.dispatchEvent(new AnnotationOverlayActionEvent(overlay, 'Update'));\n });\n div.appendChild(component);\n return div;\n }\n case 'ENTRIES_LINK': {\n const entries = this.#calculateFromAndToForEntriesLink(overlay);\n if (entries === null) {\n // For some reason, we don't have two entries we can draw between\n // (can happen if the user has collapsed an icicle in the flame\n // chart, or a track), so just draw an empty div.\n return div;\n }\n const entryEndX = this.xPixelForEventEndOnChart(entries.entryFrom) ?? 0;\n const entryStartX = this.xPixelForEventEndOnChart(entries.entryFrom) ?? 0;\n const entryStartY = (this.yPixelForEventOnChart(entries.entryFrom) ?? 0);\n const entryWidth = entryEndX - entryStartX;\n const entryHeight = this.pixelHeightForEventOnChart(entries.entryFrom) ?? 0;\n\n const component = new Components.EntriesLinkOverlay.EntriesLinkOverlay(\n {x: entryEndX, y: entryStartY, width: entryWidth, height: entryHeight});\n div.appendChild(component);\n return div;\n }\n case 'ENTRIES_LINK_CREATE_BUTTON': {\n const entryStartX = this.xPixelForEventStartOnChart(overlay.entry) ?? 0;\n const entryEndX = this.xPixelForEventEndOnChart(overlay.entry) ?? 0;\n const entryWidth = entryEndX - entryStartX;\n const entryStartY = (this.yPixelForEventOnChart(overlay.entry) ?? 0);\n const entryHeight = this.pixelHeightForEventOnChart(overlay.entry) ?? 0;\n\n const component = new Components.EntriesLinkOverlay.CreateEntriesLinkOverlay(\n {entryStartX, entryStartY, entryWidth, entryHeight});\n\n component.addEventListener(Components.EntriesLinkOverlay.CreateEntriesLinkRemoveEvent.eventName, () => {\n this.dispatchEvent(new AnnotationOverlayActionEvent(overlay, 'CreateLink'));\n });\n div.appendChild(component);\n return div;\n }\n case 'ENTRY_OUTLINE': {\n div.classList.add(`outline-reason-${overlay.outlineReason}`);\n return div;\n }\n case 'TIME_RANGE': {\n const component = new Components.TimeRangeOverlay.TimeRangeOverlay(overlay.label);\n component.duration = overlay.showDuration ? overlay.bounds.range : null;\n component.canvasRect = this.#charts.mainChart.canvasBoundingClientRect();\n component.addEventListener(Components.TimeRangeOverlay.TimeRangeLabelChangeEvent.eventName, event => {\n const newLabel = (event as Components.TimeRangeOverlay.TimeRangeLabelChangeEvent).newLabel;\n overlay.label = newLabel;\n this.dispatchEvent(new AnnotationOverlayActionEvent(overlay, 'Update'));\n });\n component.addEventListener(Components.TimeRangeOverlay.TimeRangeRemoveEvent.eventName, () => {\n this.dispatchEvent(new AnnotationOverlayActionEvent(overlay, 'Remove'));\n });\n div.appendChild(component);\n return div;\n }\n case 'TIMESPAN_BREAKDOWN': {\n const component = new Components.TimespanBreakdownOverlay.TimespanBreakdownOverlay();\n component.sections = overlay.sections;\n component.canvasRect = this.#charts.mainChart.canvasBoundingClientRect();\n div.appendChild(component);\n return div;\n }\n default: {\n return div;\n }\n }\n }\n\n /**\n * Some of the HTML elements for overlays might need updating between each render\n * (for example, if a time range has changed, we update its duration text)\n */\n #updateOverlayElementAfterPositioning(overlay: TimelineOverlay, element: HTMLElement): void {\n switch (overlay.type) {\n case 'ENTRY_SELECTED':\n // Nothing to do here.\n break;\n case 'TIME_RANGE': {\n const component = element.querySelector('devtools-time-range-overlay');\n if (component) {\n component.duration = overlay.showDuration ? overlay.bounds.range : null;\n component.canvasRect = this.#charts.mainChart.canvasBoundingClientRect();\n component.updateLabelPositioning();\n }\n break;\n }\n case 'ENTRY_LABEL':\n case 'ENTRY_OUTLINE':\n case 'ENTRIES_LINK_CREATE_BUTTON':\n // Nothing to do here.\n break;\n case 'ENTRIES_LINK': {\n const component = element.querySelector('devtools-entries-link-overlay');\n if (component) {\n component.canvasRect = this.#charts.mainChart.canvasBoundingClientRect();\n }\n break;\n }\n case 'TIMESPAN_BREAKDOWN': {\n const component = element.querySelector('devtools-timespan-breakdown-overlay');\n if (component) {\n component.sections = overlay.sections;\n component.canvasRect = this.#charts.mainChart.canvasBoundingClientRect();\n component.checkSectionLabelPositioning();\n }\n break;\n }\n case 'CURSOR_TIMESTAMP_MARKER':\n // No contents within this that need updating.\n break;\n case 'CANDY_STRIPED_TIME_RANGE':\n break;\n default:\n Platform.TypeScriptUtilities.assertNever(overlay, `Unexpected overlay ${overlay}`);\n }\n }\n\n /**\n * @returns true if the entry is visible on chart, which means that both\n * horizontally and vertically it is at least partially in view.\n */\n entryIsVisibleOnChart(entry: OverlayEntry): boolean {\n const verticallyVisible = this.#entryIsVerticallyVisibleOnChart(entry);\n const horiziontallyVisible = this.#entryIsHorizontallyVisibleOnChart(entry);\n return verticallyVisible && horiziontallyVisible;\n }\n\n /**\n * Calculates if an entry is visible horizontally. This is easy because we\n * don't have to consider any pixels and can instead check that its start and\n * end times intersect with the visible window.\n */\n #entryIsHorizontallyVisibleOnChart(entry: OverlayEntry): boolean {\n if (this.#dimensions.trace.visibleWindow === null) {\n return false;\n }\n const {startTime, endTime} = timingsForOverlayEntry(entry);\n\n const entryTimeRange = Trace.Helpers.Timing.traceWindowFromMicroSeconds(startTime, endTime);\n\n return Trace.Helpers.Timing.boundsIncludeTimeRange({\n bounds: this.#dimensions.trace.visibleWindow,\n timeRange: entryTimeRange,\n });\n }\n\n #entryIsInCollapsedTrack(entry: OverlayEntry): boolean {\n const chartName = chartForEntry(entry);\n const provider = chartName === 'main' ? this.#charts.mainProvider : this.#charts.networkProvider;\n\n const entryIndex = provider.indexForEvent?.(entry) ?? null;\n if (entryIndex === null) {\n return false;\n }\n\n const group = provider.groupForEvent?.(entryIndex) ?? null;\n if (!group) {\n return false;\n }\n\n return Boolean(group.expanded) === false;\n }\n\n /**\n * Calculate if an entry is visible vertically on the chart. A bit fiddly as\n * we have to figure out its pixel offset and go on that. Unlike horizontal\n * visibility, we can't work soley from its microsecond values.\n */\n #entryIsVerticallyVisibleOnChart(entry: OverlayEntry): boolean {\n const chartName = chartForEntry(entry);\n\n const y = this.yPixelForEventOnChart(entry);\n if (y === null) {\n return false;\n }\n\n const eventHeight = this.pixelHeightForEventOnChart(entry);\n if (!eventHeight) {\n return false;\n }\n\n if (chartName === 'main') {\n if (!this.#dimensions.charts.main?.heightPixels) {\n // Shouldn't happen, but if the main chart has no height, nothing on it is visible.\n return false;\n }\n\n // The yPixelForEventOnChart method returns the y pixel including an adjustment for the network track.\n // To see if an entry on the main flame chart is visible, we can check\n // its y value without the network track adjustment. If it is < 0, then\n // it's off the top of the screen.\n //\n const yWithoutNetwork = y - this.networkChartOffsetHeight();\n // Check if the y position + the height is less than 0. We add height so\n // that we correctly consider an event only partially scrolled off to be\n // visible.\n if (yWithoutNetwork + eventHeight < 0) {\n return false;\n }\n\n if (yWithoutNetwork > this.#dimensions.charts.main.heightPixels) {\n // The event is off the bottom of the screen.\n return false;\n }\n }\n\n if (chartName === 'network') {\n if (!this.#dimensions.charts.network) {\n // The network chart can be hidden if there are no requests in the trace.\n return false;\n }\n if (y <= -14) {\n // Weird value, but the network chart has the header row with\n // timestamps on it: events stay visible behind those timestamps, so we\n // want any overlays to treat themselves as visible too.\n return false;\n }\n\n if (y > this.#dimensions.charts.network.heightPixels ?? 0) {\n // The event is off the bottom of the network chart.\n return false;\n }\n }\n // If we got here, none of the conditions to mark an event as invisible got\n // triggered, so the event must be visible.\n return true;\n }\n\n /**\n * Calculate the X pixel position for an event start on the timeline.\n * @param chartName - the chart that the event is on. It is expected that both\n * charts have the same width so this doesn't make a difference - but it might\n * in the future if the UI changes, hence asking for it.\n *\n * @param event - the trace event you want to get the pixel position of\n */\n xPixelForEventStartOnChart(event: OverlayEntry): number|null {\n const chartName = chartForEntry(event);\n const {startTime} = timingsForOverlayEntry(event);\n return this.#xPixelForMicroSeconds(chartName, startTime);\n }\n\n /**\n * Calculate the X pixel position for an event end on the timeline.\n * @param chartName - the chart that the event is on. It is expected that both\n * charts have the same width so this doesn't make a difference - but it might\n * in the future if the UI changes, hence asking for it.\n *\n * @param event - the trace event you want to get the pixel position of\n */\n xPixelForEventEndOnChart(event: OverlayEntry): number|null {\n const chartName = chartForEntry(event);\n const {endTime} = timingsForOverlayEntry(event);\n return this.#xPixelForMicroSeconds(chartName, endTime);\n }\n\n /**\n * Calculate the xPixel for a given timestamp. To do this we calculate how\n * far in microseconds from the left of the visible window an event is, and\n * divide that by the total time span. This gives us a fraction representing\n * how far along the timeline the event is. We can then multiply that by the\n * width of the canvas to get its pixel position.\n */\n #xPixelForMicroSeconds(chart: EntryChartLocation, timestamp: Trace.Types.Timing.MicroSeconds): number|null {\n if (this.#dimensions.trace.visibleWindow === null) {\n console.error('Cannot calculate xPixel without visible trace window.');\n return null;\n }\n const canvasWidthPixels = this.#dimensions.charts[chart]?.widthPixels ?? null;\n if (canvasWidthPixels === null) {\n console.error(`Cannot calculate xPixel without ${chart} dimensions.`);\n return null;\n }\n\n const timeFromLeft = timestamp - this.#dimensions.trace.visibleWindow.min;\n const totalTimeSpan = this.#dimensions.trace.visibleWindow.range;\n return Math.floor(\n timeFromLeft / totalTimeSpan * canvasWidthPixels,\n );\n }\n\n /**\n * Calculate the Y pixel position for the event on the timeline relative to\n * the entire window.\n * This means if the event is in the main flame chart and below the network,\n * we add the height of the network chart to the Y value to position it\n * correctly.\n * This can return null if any data was missing, or if the event is not\n * visible (if the level it's on is hidden because the track is collapsed,\n * for example)\n */\n yPixelForEventOnChart(event: OverlayEntry): number|null {\n const chartName = chartForEntry(event);\n const chart = chartName === 'main' ? this.#charts.mainChart : this.#charts.networkChart;\n const provider = chartName === 'main' ? this.#charts.mainProvider : this.#charts.networkProvider;\n\n const indexForEntry = provider.indexForEvent?.(event);\n if (typeof indexForEntry !== 'number') {\n return null;\n }\n const timelineData = provider.timelineData();\n if (timelineData === null) {\n return null;\n }\n const level = timelineData.entryLevels.at(indexForEntry);\n if (typeof level === 'undefined') {\n return null;\n }\n\n if (!chart.levelIsVisible(level)) {\n return null;\n }\n\n const pixelOffsetForLevel = chart.levelToOffset(level);\n // Now we have the offset for the level, we need to adjust it by the user's scroll offset.\n let pixelAdjustedForScroll = pixelOffsetForLevel - (this.#dimensions.charts[chartName]?.scrollOffsetPixels ?? 0);\n\n // Now if the event is in the main chart, we need to pad its Y position\n // down by the height of the network chart + the network resize element.\n if (chartName === 'main') {\n pixelAdjustedForScroll += this.networkChartOffsetHeight();\n }\n\n return pixelAdjustedForScroll;\n }\n\n /**\n * Calculate the height of the event on the timeline.\n */\n pixelHeightForEventOnChart(event: OverlayEntry): number|null {\n const chartName = chartForEntry(event);\n const chart = chartName === 'main' ? this.#charts.mainChart : this.#charts.networkChart;\n const provider = chartName === 'main' ? this.#charts.mainProvider : this.#charts.networkProvider;\n\n const indexForEntry = provider.indexForEvent?.(event);\n if (typeof indexForEntry !== 'number') {\n return null;\n }\n const timelineData = provider.timelineData();\n if (timelineData === null) {\n return null;\n }\n const level = timelineData.entryLevels.at(indexForEntry);\n if (typeof level === 'undefined') {\n return null;\n }\n return chart.levelHeight(level);\n }\n\n /**\n * Calculate the height of the network chart. If the network chart has\n * height, we also allow for the size of the resize handle shown between the\n * two charts.\n *\n * Note that it is possible for the chart to have 0 height if the user is\n * looking at a trace with no network requests.\n */\n networkChartOffsetHeight(): number {\n if (this.#dimensions.charts.network === null) {\n return 0;\n }\n\n if (this.#dimensions.charts.network.heightPixels === 0) {\n return 0;\n }\n\n // At this point we know the network track exists and has height. But we\n // need to check if it is collapsed, because if it is collapsed there is no\n // resizer shown.\n if (this.#dimensions.charts.network.allGroupsCollapsed) {\n return this.#dimensions.charts.network.heightPixels;\n }\n\n return this.#dimensions.charts.network.heightPixels + NETWORK_RESIZE_ELEM_HEIGHT_PX;\n }\n\n /**\n * Hides or shows an element. We used to use visibility rather than display,\n * but a child of an element with visibility: hidden may still be visible if\n * its own `display` property is set.\n */\n #setOverlayElementVisibility(element: HTMLElement, isVisible: boolean): void {\n element.style.display = isVisible ? 'block' : 'none';\n }\n}\n\n/**\n * Because entries can be a TimelineFrame, which is not a trace event, this\n * helper exists to return a consistent set of timings regardless of the type\n * of entry.\n */\nexport function timingsForOverlayEntry(entry: OverlayEntry):\n Trace.Helpers.Timing.EventTimingsData {\n if (Trace.Types.Events.isLegacyTimelineFrame(entry)) {\n return {\n startTime: entry.startTime,\n endTime: entry.endTime,\n duration: entry.duration,\n };\n }\n if (Trace.Types.Events.isSyntheticLayoutShift(entry)) {\n const endTime = Trace.Types.Timing.MicroSeconds(entry.ts + LAYOUT_SHIFT_SYNTHETIC_DURATION);\n return {\n endTime,\n duration: LAYOUT_SHIFT_SYNTHETIC_DURATION,\n startTime: entry.ts,\n };\n }\n return Trace.Helpers.Timing.eventTimingsMicroSeconds(entry);\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/overlays/OverlaysImpl.test.js b/public/panels/timeline/overlays/OverlaysImpl.test.js index 805815b7b..e22cf608c 100644 --- a/public/panels/timeline/overlays/OverlaysImpl.test.js +++ b/public/panels/timeline/overlays/OverlaysImpl.test.js @@ -1,7 +1,7 @@ // Copyright 2024 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 * as TraceEngine from '../../../models/trace/trace.js'; +import * as Trace from '../../../models/trace/trace.js'; import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; import { makeInstantEvent, MockFlameChartDelegate, setupIgnoreListManagerEnvironment, } from '../../../testing/TraceHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; @@ -24,15 +24,15 @@ const FAKE_OVERLAY_ENTRY_QUERIES = { * and data providers. This function creates all of those and optionally sets * the trace data for the providers if it is provided. */ -function createCharts(traceData) { +function createCharts(parsedTrace) { const mainProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider(); const networkProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider(); const delegate = new MockFlameChartDelegate(); const mainChart = new PerfUI.FlameChart.FlameChart(mainProvider, delegate); const networkChart = new PerfUI.FlameChart.FlameChart(networkProvider, delegate); - if (traceData) { - mainProvider.setModel(traceData); - networkProvider.setModel(traceData); + if (parsedTrace) { + mainProvider.setModel(parsedTrace); + networkProvider.setModel(parsedTrace); // Force the charts to render. Normally the TimelineFlameChartView would do // this, but we aren't creating one for these tests. mainChart.update(); @@ -76,18 +76,18 @@ describeWithEnvironment('Overlays', () => { scrollOffsetPixels: 0, allGroupsCollapsed: false, }); - const windowMin = TraceEngine.Types.Timing.MicroSeconds(0); - const windowMax = TraceEngine.Types.Timing.MicroSeconds(100); + const windowMin = Trace.Types.Timing.MicroSeconds(0); + const windowMax = Trace.Types.Timing.MicroSeconds(100); // Set the visible window to be 0-100 microseconds - overlays.updateVisibleWindow(TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(windowMin, windowMax)); + overlays.updateVisibleWindow(Trace.Helpers.Timing.traceWindowFromMicroSeconds(windowMin, windowMax)); // Now set an event to be at 50 microseconds. const event = makeInstantEvent('test-event', 50); const xPosition = overlays.xPixelForEventStartOnChart(event); assert.strictEqual(xPosition, 50); }); it('can calculate the y position of a main chart event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const charts = createCharts(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const charts = createCharts(parsedTrace); const flameChartsContainer = document.createElement('div'); const mainFlameChartsContainer = flameChartsContainer.createChild('div'); const networkFlameChartsContainer = flameChartsContainer.createChild('div'); @@ -114,10 +114,10 @@ describeWithEnvironment('Overlays', () => { allGroupsCollapsed: false, }); // Set the visible window to be the entire trace. - overlays.updateVisibleWindow(traceData.Meta.traceBounds); + overlays.updateVisibleWindow(parsedTrace.Meta.traceBounds); // Find an event on the main chart that is not a frame (you cannot add overlays to frames) const event = charts.mainProvider.eventByIndex?.(50); - assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame); + assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame); assert.isOk(event); const yPixel = overlays.yPixelForEventOnChart(event); // The Y offset for the main chart is 233px, but we add 208px on (200px for the @@ -126,8 +126,8 @@ describeWithEnvironment('Overlays', () => { assert.strictEqual(yPixel, 441); }); it('can adjust the y position of a main chart event when the network track is collapsed', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const charts = createCharts(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const charts = createCharts(parsedTrace); const flameChartsContainer = document.createElement('div'); const mainFlameChartsContainer = flameChartsContainer.createChild('div'); const networkFlameChartsContainer = flameChartsContainer.createChild('div'); @@ -155,10 +155,10 @@ describeWithEnvironment('Overlays', () => { allGroupsCollapsed: true, }); // Set the visible window to be the entire trace. - overlays.updateVisibleWindow(traceData.Meta.traceBounds); + overlays.updateVisibleWindow(parsedTrace.Meta.traceBounds); // Find an event on the main chart that is not a frame (you cannot add overlays to frames) const event = charts.mainProvider.eventByIndex?.(50); - assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame); + assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame); assert.isOk(event); const yPixel = overlays.yPixelForEventOnChart(event); // The Y offset for the main chart is 233px, but we add 34px on (the height @@ -167,8 +167,8 @@ describeWithEnvironment('Overlays', () => { assert.strictEqual(yPixel, 267); }); it('can calculate the y position of a network chart event', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const charts = createCharts(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const charts = createCharts(parsedTrace); const flameChartsContainer = document.createElement('div'); const mainFlameChartsContainer = flameChartsContainer.createChild('div'); const networkFlameChartsContainer = flameChartsContainer.createChild('div'); @@ -195,7 +195,7 @@ describeWithEnvironment('Overlays', () => { allGroupsCollapsed: false, }); // Set the visible window to be the entire trace. - overlays.updateVisibleWindow(traceData.Meta.traceBounds); + overlays.updateVisibleWindow(parsedTrace.Meta.traceBounds); // Fake the level being visible: because we don't fully render the chart we // need to fake this for this test. sinon.stub(charts.networkChart, 'levelIsVisible').callsFake(() => true); @@ -209,8 +209,8 @@ describeWithEnvironment('Overlays', () => { assert.strictEqual(yPixel, 34); }); describe('rendering overlays', () => { - function setupChartWithDimensionsAndAnnotationOverlayListeners(traceData) { - const charts = createCharts(traceData); + function setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace) { + const charts = createCharts(parsedTrace); const flameChartsContainer = document.createElement('div'); const mainFlameChartsContainer = flameChartsContainer.createChild('div'); const networkFlameChartsContainer = flameChartsContainer.createChild('div'); @@ -254,15 +254,15 @@ describeWithEnvironment('Overlays', () => { allGroupsCollapsed: false, }); // Set the visible window to be the entire trace. - overlays.updateVisibleWindow(traceData.Meta.traceBounds); + overlays.updateVisibleWindow(parsedTrace.Meta.traceBounds); return { overlays, container, charts }; } it('can render an entry selected overlay', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const { overlays, container, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { overlays, container, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace); const event = charts.mainProvider.eventByIndex?.(50); assert.isOk(event); - assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame); + assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame); overlays.add({ type: 'ENTRY_SELECTED', entry: event, @@ -273,8 +273,8 @@ describeWithEnvironment('Overlays', () => { assert.isOk(overlayDOM); }); it('does not render an ENTRY_OUTLINE if the entry is also the ENTRY_SELECTED entry', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const { overlays, container, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { overlays, container, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace); const event = charts.mainProvider.eventByIndex?.(50); assert.isOk(event); overlays.add({ @@ -295,8 +295,8 @@ describeWithEnvironment('Overlays', () => { assert.isTrue(outlineNowHidden, 'The ENTRY_OUTLINE should be hidden'); }); it('only ever renders a single selected overlay', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const { overlays, container, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { overlays, container, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace); const event1 = charts.mainProvider.eventByIndex?.(50); const event2 = charts.mainProvider.eventByIndex?.(51); assert.isOk(event1); @@ -316,11 +316,11 @@ describeWithEnvironment('Overlays', () => { assert.lengthOf(entrySelectedOverlays, 1); }); it('can render entry label overlay', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const { overlays, container, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { overlays, container, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace); const event = charts.mainProvider.eventByIndex?.(50); assert.isOk(event); - assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame); + assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame); overlays.add({ type: 'ENTRY_LABEL', entry: event, @@ -332,25 +332,25 @@ describeWithEnvironment('Overlays', () => { assert.isOk(overlayDOM); }); it('only renders one CURSOR_TIMESTAMP_MARKER as it is a singleton', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const { overlays, container } = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { overlays, container } = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace); overlays.add({ type: 'CURSOR_TIMESTAMP_MARKER', - timestamp: traceData.Meta.traceBounds.min, + timestamp: parsedTrace.Meta.traceBounds.min, }); overlays.add({ type: 'CURSOR_TIMESTAMP_MARKER', - timestamp: traceData.Meta.traceBounds.max, + timestamp: parsedTrace.Meta.traceBounds.max, }); overlays.update(); assert.lengthOf(container.children, 1); }); it('can render the label for entry label overlay', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const { overlays, container, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { overlays, container, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace); const event = charts.mainProvider.eventByIndex?.(50); assert.isOk(event); - assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame); + assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame); overlays.add({ type: 'ENTRY_LABEL', entry: event, @@ -370,11 +370,11 @@ describeWithEnvironment('Overlays', () => { assert.strictEqual(inputField?.innerText, 'entry label'); }); it('Inputting `Enter`into label overlay makes it non-editable', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const { overlays, container, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { overlays, container, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace); const event = charts.mainProvider.eventByIndex?.(50); assert.isOk(event); - assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame); + assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame); // Create an entry label overlay overlays.add({ type: 'ENTRY_LABEL', @@ -404,18 +404,18 @@ describeWithEnvironment('Overlays', () => { assert.isFalse(inputField.isContentEditable); }); it('Inputting `Enter` into time range label field when the label is empty removes the overlay', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const { overlays, container, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { overlays, container, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace); const event = charts.mainProvider.eventByIndex?.(50); assert.isOk(event); - assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame); + assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame); // Create a time range overlay with an empty label overlays.add({ type: 'TIME_RANGE', label: '', showDuration: true, // Make this overlay the entire span of the trace - bounds: traceData.Meta.traceBounds, + bounds: parsedTrace.Meta.traceBounds, }); overlays.update(); // Ensure that the overlay was created. @@ -436,18 +436,18 @@ describeWithEnvironment('Overlays', () => { assert.strictEqual(overlays.overlaysOfType('TIME_RANGE').length, 0); }); it('Inputting `Enter` into time range label field when the label is not empty does not remove the overlay', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const { overlays, container, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { overlays, container, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace); const event = charts.mainProvider.eventByIndex?.(50); assert.isOk(event); - assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame); + assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame); // Create a time range overlay with a label overlays.add({ type: 'TIME_RANGE', label: 'label', showDuration: true, // Make this overlay the entire span of the trace - bounds: traceData.Meta.traceBounds, + bounds: parsedTrace.Meta.traceBounds, }); overlays.update(); // Ensure that the overlay was created. @@ -468,27 +468,27 @@ describeWithEnvironment('Overlays', () => { assert.strictEqual(overlays.overlaysOfType('TIME_RANGE').length, 1); }); it('Can create multiple Time Range Overlays for Time Range annotations', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const { overlays, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { overlays, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace); const event = charts.mainProvider.eventByIndex?.(50); assert.isOk(event); - assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame); + assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame); Timeline.ModificationsManager.ModificationsManager.activeManager()?.createAnnotation({ type: 'TIME_RANGE', label: 'label', - bounds: traceData.Meta.traceBounds, + bounds: parsedTrace.Meta.traceBounds, }); Timeline.ModificationsManager.ModificationsManager.activeManager()?.createAnnotation({ type: 'TIME_RANGE', label: 'label2', - bounds: traceData.Meta.traceBounds, + bounds: parsedTrace.Meta.traceBounds, }); overlays.update(); assert.strictEqual(overlays.overlaysOfType('TIME_RANGE').length, 2); }); it('Removes empty label if it is empty when navigated away from (removed focused from)', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const { overlays, container, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { overlays, container, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace); const event = charts.mainProvider.eventByIndex?.(50); assert.isOk(event); // Create an entry label overlay @@ -521,8 +521,8 @@ describeWithEnvironment('Overlays', () => { assert.strictEqual(overlays.overlaysForEntry(event).length, 0); }); it('Update label overlay when the label changes', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const { overlays, container, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { overlays, container, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace); const event = charts.mainProvider.eventByIndex?.(50); assert.isOk(event); // Create an entry label overlay @@ -545,49 +545,49 @@ describeWithEnvironment('Overlays', () => { assert.strictEqual(updatedOverlay.label, 'new label'); }); it('creates an overlay for a time range when an time range annotation is created', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const { overlays, container } = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { overlays, container } = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace); // Since TIME_RANGE is AnnotationOverlay, create it through ModificationsManager Timeline.ModificationsManager.ModificationsManager.activeManager()?.createAnnotation({ type: 'TIME_RANGE', label: '', // Make this overlay the entire span of the trace - bounds: traceData.Meta.traceBounds, + bounds: parsedTrace.Meta.traceBounds, }); overlays.update(); const overlayDOM = container.querySelector('.overlay-type-TIME_RANGE'); assert.isOk(overlayDOM); }); it('can render an overlay for a time range', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const { overlays, container } = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { overlays, container } = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace); overlays.add({ type: 'TIME_RANGE', label: '', showDuration: true, // Make this overlay the entire span of the trace - bounds: traceData.Meta.traceBounds, + bounds: parsedTrace.Meta.traceBounds, }); overlays.update(); const overlayDOM = container.querySelector('.overlay-type-TIME_RANGE'); assert.isOk(overlayDOM); }); it('can update a time range overlay with new bounds', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const { overlays, container } = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { overlays, container } = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace); const rangeOverlay = overlays.add({ type: 'TIME_RANGE', label: '', showDuration: true, // Make this overlay the entire span of the trace - bounds: traceData.Meta.traceBounds, + bounds: parsedTrace.Meta.traceBounds, }); overlays.update(); const overlayDOM = container.querySelector('.overlay-type-TIME_RANGE'); assert.isOk(overlayDOM); const firstWidth = window.parseInt(overlayDOM.style.width); // change the bounds so the new min is +1second of time. - const newBounds = TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(TraceEngine.Types.Timing.MicroSeconds(rangeOverlay.bounds.min + (1_000 * 1_000)), rangeOverlay.bounds.max); + const newBounds = Trace.Helpers.Timing.traceWindowFromMicroSeconds(Trace.Types.Timing.MicroSeconds(rangeOverlay.bounds.min + (1_000 * 1_000)), rangeOverlay.bounds.max); overlays.updateExisting(rangeOverlay, { bounds: newBounds }); overlays.update(); const secondWidth = window.parseInt(overlayDOM.style.width); @@ -595,9 +595,9 @@ describeWithEnvironment('Overlays', () => { assert.isTrue(secondWidth < firstWidth); }); it('renders the overlay for a selected layout shift entry correctly', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'cls-single-frame.json.gz'); - const { overlays, container } = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData); - const layoutShiftEvent = traceData.LayoutShifts.clusters.at(0)?.events.at(0); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'cls-single-frame.json.gz'); + const { overlays, container } = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace); + const layoutShiftEvent = parsedTrace.LayoutShifts.clusters.at(0)?.events.at(0); if (!layoutShiftEvent) { throw new Error('layoutShiftEvent was unexpectedly undefined'); } @@ -605,8 +605,8 @@ describeWithEnvironment('Overlays', () => { type: 'ENTRY_SELECTED', entry: layoutShiftEvent, }); - const boundsRange = TraceEngine.Types.Timing.MicroSeconds(20_000); - const boundsMax = TraceEngine.Types.Timing.MicroSeconds(layoutShiftEvent.ts + boundsRange); + const boundsRange = Trace.Types.Timing.MicroSeconds(20_000); + const boundsMax = Trace.Types.Timing.MicroSeconds(layoutShiftEvent.ts + boundsRange); overlays.updateVisibleWindow({ min: layoutShiftEvent.ts, max: boundsMax, range: boundsRange }); overlays.update(); const overlayDOM = container.querySelector('.overlay-type-ENTRY_SELECTED'); @@ -614,14 +614,14 @@ describeWithEnvironment('Overlays', () => { assert.strictEqual(window.parseInt(overlayDOM.style.width), 250); }); it('renders the duration and label for a time range overlay', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const { overlays, container } = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { overlays, container } = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace); overlays.add({ type: 'TIME_RANGE', label: '', showDuration: true, // Make this overlay the entire span of the trace - bounds: traceData.Meta.traceBounds, + bounds: parsedTrace.Meta.traceBounds, }); overlays.update(); await coordinator.done(); @@ -635,11 +635,11 @@ describeWithEnvironment('Overlays', () => { assert.strictEqual(duration?.innerText, '1.26\xA0s'); }); it('can remove an overlay', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const { overlays, container, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { overlays, container, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace); const event = charts.mainProvider.eventByIndex?.(50); assert.isOk(event); - assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame); + assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame); const selectedOverlay = overlays.add({ type: 'ENTRY_SELECTED', entry: event, @@ -651,11 +651,11 @@ describeWithEnvironment('Overlays', () => { assert.lengthOf(container.children, 0); }); it('can render an entry selected overlay for a frame', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); - const { overlays, container, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz'); + const { overlays, container, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace); const timelineFrame = charts.mainProvider.eventByIndex?.(5); assert.isOk(timelineFrame); - assert.instanceOf(timelineFrame, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame); + assert.instanceOf(timelineFrame, Trace.Handlers.ModelHandlers.Frames.TimelineFrame); overlays.add({ type: 'ENTRY_SELECTED', entry: timelineFrame, @@ -666,16 +666,16 @@ describeWithEnvironment('Overlays', () => { assert.isOk(overlayDOM); }); it('can return a list of overlays for an entry', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const { overlays, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { overlays, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace); const event = charts.mainProvider.eventByIndex?.(50); assert.isOk(event); - assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame); + assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame); overlays.add({ type: 'ENTRY_SELECTED', entry: event, }); - assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame); + assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame); const existingOverlays = overlays.overlaysForEntry(event); assert.deepEqual(existingOverlays, [{ type: 'ENTRY_SELECTED', @@ -683,11 +683,11 @@ describeWithEnvironment('Overlays', () => { }]); }); it('can delete overlays and remove them from the DOM', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const { container, overlays, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { container, overlays, charts } = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace); const event = charts.mainProvider.eventByIndex?.(50); assert.isOk(event); - assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame); + assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame); overlays.add({ type: 'ENTRY_SELECTED', entry: event, @@ -699,9 +699,9 @@ describeWithEnvironment('Overlays', () => { assert.lengthOf(container.children, 0); }); it('the label entry field is editable when created', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const { overlays, container } = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData); - const charts = createCharts(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { overlays, container } = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace); + const charts = createCharts(parsedTrace); const event = charts.mainProvider.eventByIndex?.(50); assert.isOk(event); // Since ENTRY_LABEL is AnnotationOverlay, create it through ModificationsManager @@ -723,9 +723,9 @@ describeWithEnvironment('Overlays', () => { assert.isTrue(inputField.isContentEditable); }); it('the label entry field is in focus after being double clicked on', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const { overlays, container } = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData); - const charts = createCharts(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const { overlays, container } = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace); + const charts = createCharts(parsedTrace); const event = charts.mainProvider.eventByIndex?.(50); assert.isOk(event); // Since ENTRY_LABEL is AnnotationOverlay, create it through ModificationsManager diff --git a/public/panels/timeline/overlays/OverlaysImpl.test.js.map b/public/panels/timeline/overlays/OverlaysImpl.test.js.map index 5ca376f48..56de64133 100644 --- a/public/panels/timeline/overlays/OverlaysImpl.test.js.map +++ b/public/panels/timeline/overlays/OverlaysImpl.test.js.map @@ -1 +1 @@ -{"version":3,"file":"OverlaysImpl.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/overlays/OverlaysImpl.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as TraceEngine from '../../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {\n makeInstantEvent,\n MockFlameChartDelegate,\n setupIgnoreListManagerEnvironment,\n} from '../../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as RenderCoordinator from '../../../ui/components/render_coordinator/render_coordinator.js';\nimport * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as Timeline from '../timeline.js';\n\nimport * as Components from './components/components.js';\nimport * as Overlays from './overlays.js';\n\nconst coordinator = RenderCoordinator.RenderCoordinator.RenderCoordinator.instance();\n\nconst FAKE_OVERLAY_ENTRY_QUERIES: Overlays.Overlays.OverlayEntryQueries = {\n isEntryCollapsedByUser() {\n return false;\n },\n firstVisibleParentForEntry() {\n return null;\n },\n};\n\n/**\n * The Overlays expects to be provided with both the main and network charts\n * and data providers. This function creates all of those and optionally sets\n * the trace data for the providers if it is provided.\n */\nfunction createCharts(traceData?: TraceEngine.Handlers.Types.TraceParseData): Overlays.Overlays.TimelineCharts {\n const mainProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();\n const networkProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider();\n\n const delegate = new MockFlameChartDelegate();\n const mainChart = new PerfUI.FlameChart.FlameChart(mainProvider, delegate);\n const networkChart = new PerfUI.FlameChart.FlameChart(networkProvider, delegate);\n\n if (traceData) {\n mainProvider.setModel(traceData);\n networkProvider.setModel(traceData);\n\n // Force the charts to render. Normally the TimelineFlameChartView would do\n // this, but we aren't creating one for these tests.\n mainChart.update();\n networkChart.update();\n }\n\n return {\n mainProvider,\n mainChart,\n networkProvider,\n networkChart,\n };\n}\n\ndescribeWithEnvironment('Overlays', () => {\n beforeEach(() => {\n setupIgnoreListManagerEnvironment();\n });\n\n it('can calculate the x position of an event based on the dimensions and its timestamp', async () => {\n const flameChartsContainer = document.createElement('div');\n const mainFlameChartsContainer = flameChartsContainer.createChild('div');\n const networkFlameChartsContainer = flameChartsContainer.createChild('div');\n const container = flameChartsContainer.createChild('div');\n\n const overlays = new Overlays.Overlays.Overlays({\n container,\n flameChartsContainers: {\n main: mainFlameChartsContainer,\n network: networkFlameChartsContainer,\n },\n charts: createCharts(),\n entryQueries: FAKE_OVERLAY_ENTRY_QUERIES,\n });\n\n // Set up the dimensions so it is 100px wide\n overlays.updateChartDimensions('main', {\n widthPixels: 100,\n heightPixels: 50,\n scrollOffsetPixels: 0,\n allGroupsCollapsed: false,\n });\n overlays.updateChartDimensions('network', {\n widthPixels: 100,\n heightPixels: 50,\n scrollOffsetPixels: 0,\n allGroupsCollapsed: false,\n });\n\n const windowMin = TraceEngine.Types.Timing.MicroSeconds(0);\n const windowMax = TraceEngine.Types.Timing.MicroSeconds(100);\n // Set the visible window to be 0-100 microseconds\n overlays.updateVisibleWindow(TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(windowMin, windowMax));\n\n // Now set an event to be at 50 microseconds.\n const event = makeInstantEvent('test-event', 50);\n\n const xPosition = overlays.xPixelForEventStartOnChart(event);\n assert.strictEqual(xPosition, 50);\n });\n\n it('can calculate the y position of a main chart event', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const charts = createCharts(traceData);\n\n const flameChartsContainer = document.createElement('div');\n const mainFlameChartsContainer = flameChartsContainer.createChild('div');\n const networkFlameChartsContainer = flameChartsContainer.createChild('div');\n const container = flameChartsContainer.createChild('div');\n\n const overlays = new Overlays.Overlays.Overlays({\n container,\n flameChartsContainers: {\n main: mainFlameChartsContainer,\n network: networkFlameChartsContainer,\n },\n charts,\n entryQueries: FAKE_OVERLAY_ENTRY_QUERIES,\n });\n\n overlays.updateChartDimensions('main', {\n widthPixels: 1000,\n heightPixels: 500,\n scrollOffsetPixels: 0,\n allGroupsCollapsed: false,\n });\n overlays.updateChartDimensions('network', {\n widthPixels: 1000,\n heightPixels: 200,\n scrollOffsetPixels: 0,\n allGroupsCollapsed: false,\n });\n\n // Set the visible window to be the entire trace.\n overlays.updateVisibleWindow(traceData.Meta.traceBounds);\n\n // Find an event on the main chart that is not a frame (you cannot add overlays to frames)\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame);\n assert.isOk(event);\n const yPixel = overlays.yPixelForEventOnChart(event);\n // The Y offset for the main chart is 233px, but we add 208px on (200px for the\n // network chart, and 8px for the re-size handle) giving us the expected\n // 441px.\n assert.strictEqual(yPixel, 441);\n });\n\n it('can adjust the y position of a main chart event when the network track is collapsed', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const charts = createCharts(traceData);\n\n const flameChartsContainer = document.createElement('div');\n const mainFlameChartsContainer = flameChartsContainer.createChild('div');\n const networkFlameChartsContainer = flameChartsContainer.createChild('div');\n const container = flameChartsContainer.createChild('div');\n\n const overlays = new Overlays.Overlays.Overlays({\n container,\n flameChartsContainers: {\n main: mainFlameChartsContainer,\n network: networkFlameChartsContainer,\n },\n charts,\n entryQueries: FAKE_OVERLAY_ENTRY_QUERIES,\n });\n\n overlays.updateChartDimensions('main', {\n widthPixels: 1000,\n heightPixels: 500,\n scrollOffsetPixels: 0,\n allGroupsCollapsed: false,\n });\n overlays.updateChartDimensions('network', {\n widthPixels: 1000,\n heightPixels: 34,\n scrollOffsetPixels: 0,\n // Make the network track collapsed\n allGroupsCollapsed: true,\n });\n\n // Set the visible window to be the entire trace.\n overlays.updateVisibleWindow(traceData.Meta.traceBounds);\n\n // Find an event on the main chart that is not a frame (you cannot add overlays to frames)\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame);\n assert.isOk(event);\n const yPixel = overlays.yPixelForEventOnChart(event);\n // The Y offset for the main chart is 233px, but we add 34px on (the height\n // of the collapsed network chart, with no resizer bar as it is hidden when\n // the network track is collapsed). This gives us 233+34 = 267.\n assert.strictEqual(yPixel, 267);\n });\n\n it('can calculate the y position of a network chart event', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const charts = createCharts(traceData);\n\n const flameChartsContainer = document.createElement('div');\n const mainFlameChartsContainer = flameChartsContainer.createChild('div');\n const networkFlameChartsContainer = flameChartsContainer.createChild('div');\n const container = flameChartsContainer.createChild('div');\n\n const overlays = new Overlays.Overlays.Overlays({\n container,\n flameChartsContainers: {\n main: mainFlameChartsContainer,\n network: networkFlameChartsContainer,\n },\n charts,\n entryQueries: FAKE_OVERLAY_ENTRY_QUERIES,\n });\n\n overlays.updateChartDimensions('main', {\n widthPixels: 1000,\n heightPixels: 500,\n scrollOffsetPixels: 0,\n allGroupsCollapsed: false,\n });\n overlays.updateChartDimensions('network', {\n widthPixels: 1000,\n heightPixels: 200,\n scrollOffsetPixels: 0,\n allGroupsCollapsed: false,\n });\n\n // Set the visible window to be the entire trace.\n overlays.updateVisibleWindow(traceData.Meta.traceBounds);\n\n // Fake the level being visible: because we don't fully render the chart we\n // need to fake this for this test.\n sinon.stub(charts.networkChart, 'levelIsVisible').callsFake(() => true);\n\n // Find an event on the network chart\n const event = charts.networkProvider.eventByIndex?.(0);\n assert.isOk(event);\n const yPixel = overlays.yPixelForEventOnChart(event);\n // This event is in the first level, but the first level has some offset\n // above it to allow for the header row and the row with the timestamps on\n // it, hence why this value is not 0px.\n assert.strictEqual(yPixel, 34);\n });\n\n describe('rendering overlays', () => {\n function setupChartWithDimensionsAndAnnotationOverlayListeners(\n traceData: TraceEngine.Handlers.Types.TraceParseData): {\n container: HTMLElement,\n overlays: Overlays.Overlays.Overlays,\n charts: Overlays.Overlays.TimelineCharts,\n } {\n const charts = createCharts(traceData);\n\n const flameChartsContainer = document.createElement('div');\n const mainFlameChartsContainer = flameChartsContainer.createChild('div');\n const networkFlameChartsContainer = flameChartsContainer.createChild('div');\n const container = flameChartsContainer.createChild('div');\n\n const overlays = new Overlays.Overlays.Overlays({\n container,\n flameChartsContainers: {\n main: mainFlameChartsContainer,\n network: networkFlameChartsContainer,\n },\n charts,\n entryQueries: FAKE_OVERLAY_ENTRY_QUERIES,\n });\n const currManager = Timeline.ModificationsManager.ModificationsManager.activeManager();\n // The Annotations Overlays are added through the ModificationsManager listener\n currManager?.addEventListener(Timeline.ModificationsManager.AnnotationModifiedEvent.eventName, event => {\n const {overlay, action} = (event as Timeline.ModificationsManager.AnnotationModifiedEvent);\n if (action === 'Add') {\n overlays.add(overlay);\n }\n overlays.update();\n });\n\n // When an annotation overlay is remomved, this event is dispatched to the Modifications Manager.\n overlays.addEventListener(Overlays.Overlays.AnnotationOverlayActionEvent.eventName, event => {\n const {overlay, action} = (event as Overlays.Overlays.AnnotationOverlayActionEvent);\n if (action === 'Remove') {\n overlays.remove(overlay);\n }\n overlays.update();\n });\n\n overlays.updateChartDimensions('main', {\n widthPixels: 1000,\n heightPixels: 500,\n scrollOffsetPixels: 0,\n allGroupsCollapsed: false,\n });\n overlays.updateChartDimensions('network', {\n widthPixels: 1000,\n heightPixels: 200,\n scrollOffsetPixels: 0,\n allGroupsCollapsed: false,\n });\n\n // Set the visible window to be the entire trace.\n overlays.updateVisibleWindow(traceData.Meta.traceBounds);\n return {overlays, container, charts};\n }\n\n it('can render an entry selected overlay', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame);\n\n overlays.add({\n type: 'ENTRY_SELECTED',\n entry: event,\n });\n overlays.update();\n\n // Ensure that the overlay was created.\n const overlayDOM = container.querySelector('.overlay-type-ENTRY_SELECTED');\n assert.isOk(overlayDOM);\n });\n\n it('does not render an ENTRY_OUTLINE if the entry is also the ENTRY_SELECTED entry', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n overlays.add({\n type: 'ENTRY_OUTLINE',\n entry: event,\n outlineReason: 'ERROR',\n });\n overlays.update();\n\n const outlineVisible =\n container.querySelector('.overlay-type-ENTRY_OUTLINE')?.style.display === 'block';\n assert.isTrue(outlineVisible, 'The ENTRY_OUTLINE should be visible');\n\n // Now make a selected entry too\n overlays.add({\n type: 'ENTRY_SELECTED',\n entry: event,\n });\n overlays.update();\n const outlineNowHidden =\n container.querySelector('.overlay-type-ENTRY_OUTLINE')?.style.display === 'none';\n assert.isTrue(outlineNowHidden, 'The ENTRY_OUTLINE should be hidden');\n });\n\n it('only ever renders a single selected overlay', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData);\n const event1 = charts.mainProvider.eventByIndex?.(50);\n const event2 = charts.mainProvider.eventByIndex?.(51);\n assert.isOk(event1);\n assert.isOk(event2);\n\n overlays.add({\n type: 'ENTRY_SELECTED',\n entry: event1,\n });\n overlays.update();\n overlays.add({\n type: 'ENTRY_SELECTED',\n entry: event2,\n });\n overlays.update();\n\n // There should only be one of these\n const entrySelectedOverlays = container.querySelectorAll('.overlay-type-ENTRY_SELECTED');\n assert.lengthOf(entrySelectedOverlays, 1);\n });\n\n it('can render entry label overlay', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame);\n\n overlays.add({\n type: 'ENTRY_LABEL',\n entry: event,\n label: 'entry label',\n });\n overlays.update();\n\n // Ensure that the overlay was created.\n const overlayDOM = container.querySelector('.overlay-type-ENTRY_LABEL');\n assert.isOk(overlayDOM);\n });\n\n it('only renders one CURSOR_TIMESTAMP_MARKER as it is a singleton', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container} = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData);\n overlays.add({\n type: 'CURSOR_TIMESTAMP_MARKER',\n timestamp: traceData.Meta.traceBounds.min,\n });\n overlays.add({\n type: 'CURSOR_TIMESTAMP_MARKER',\n timestamp: traceData.Meta.traceBounds.max,\n });\n overlays.update();\n assert.lengthOf(container.children, 1);\n });\n\n it('can render the label for entry label overlay', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame);\n\n overlays.add({\n type: 'ENTRY_LABEL',\n entry: event,\n label: 'entry label',\n });\n overlays.update();\n\n const overlayDOM = container.querySelector('.overlay-type-ENTRY_LABEL');\n assert.isOk(overlayDOM);\n const component = overlayDOM?.querySelector('devtools-entry-label-overlay');\n assert.isOk(component?.shadowRoot);\n\n const elementsWrapper = component.shadowRoot.querySelector('.label-parts-wrapper');\n assert.isOk(elementsWrapper);\n\n const labelBox = elementsWrapper.querySelector('.label-box');\n assert.isOk(labelBox);\n\n const inputField = labelBox.querySelector('.input-field');\n assert.isOk(inputField);\n\n assert.strictEqual(inputField?.innerText, 'entry label');\n });\n\n it('Inputting `Enter`into label overlay makes it non-editable', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame);\n\n // Create an entry label overlay\n overlays.add({\n type: 'ENTRY_LABEL',\n entry: event,\n label: 'label',\n });\n overlays.update();\n\n // Ensure that the overlay was created.\n const overlayDOM = container.querySelector('.overlay-type-ENTRY_LABEL');\n assert.isOk(overlayDOM);\n\n const component = overlayDOM?.querySelector('devtools-entry-label-overlay');\n assert.isOk(component?.shadowRoot);\n component.connectedCallback();\n const elementsWrapper = component.shadowRoot.querySelector('.label-parts-wrapper');\n assert.isOk(elementsWrapper);\n\n const label = elementsWrapper.querySelector('.label-box');\n assert.isOk(label);\n const inputField = label.querySelector('.input-field');\n assert.isOk(inputField);\n\n // Double click on the label box to make it editable and focus on it\n inputField.dispatchEvent(new FocusEvent('dblclick', {bubbles: true}));\n\n // Ensure the label content is editable\n assert.isTrue(inputField.isContentEditable);\n\n // Press `Enter` to make the lable not editable\n inputField.dispatchEvent(new KeyboardEvent('keydown', {key: 'Enter', cancelable: true, bubbles: true}));\n\n // Ensure the label content is not editable\n assert.isFalse(inputField.isContentEditable);\n });\n\n it('Inputting `Enter` into time range label field when the label is empty removes the overlay', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame);\n\n // Create a time range overlay with an empty label\n overlays.add({\n type: 'TIME_RANGE',\n label: '',\n showDuration: true,\n // Make this overlay the entire span of the trace\n bounds: traceData.Meta.traceBounds,\n });\n overlays.update();\n\n // Ensure that the overlay was created.\n const overlayDOM = container.querySelector('.overlay-type-TIME_RANGE');\n assert.isOk(overlayDOM);\n\n const component = overlayDOM?.querySelector('devtools-time-range-overlay');\n assert.isOk(component?.shadowRoot);\n component.connectedCallback();\n const rangeContainer = component.shadowRoot.querySelector('.range-container');\n assert.isOk(rangeContainer);\n\n const labelBox = rangeContainer.querySelector('.label-text');\n assert.isOk(labelBox);\n\n // Double click on the label box to make it editable and focus on it\n labelBox.dispatchEvent(new FocusEvent('dblclick', {bubbles: true}));\n\n // Press `Enter` on the label field\n labelBox.dispatchEvent(new KeyboardEvent('keydown', {key: 'Enter', cancelable: true, bubbles: true}));\n\n // Ensure that the entry overlay has been removed because it was saved empty\n assert.strictEqual(overlays.overlaysOfType('TIME_RANGE').length, 0);\n });\n\n it('Inputting `Enter` into time range label field when the label is not empty does not remove the overlay',\n async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame);\n\n // Create a time range overlay with a label\n overlays.add({\n type: 'TIME_RANGE',\n label: 'label',\n showDuration: true,\n // Make this overlay the entire span of the trace\n bounds: traceData.Meta.traceBounds,\n });\n overlays.update();\n\n // Ensure that the overlay was created.\n const overlayDOM = container.querySelector('.overlay-type-TIME_RANGE');\n assert.isOk(overlayDOM);\n\n const component = overlayDOM?.querySelector('devtools-time-range-overlay');\n assert.isOk(component?.shadowRoot);\n component.connectedCallback();\n const rangeContainer = component.shadowRoot.querySelector('.range-container');\n assert.isOk(rangeContainer);\n\n const labelBox = rangeContainer.querySelector('.label-text');\n assert.isOk(labelBox);\n\n // Double click on the label box to make it editable and focus on it\n labelBox.dispatchEvent(new FocusEvent('dblclick', {bubbles: true}));\n\n // Press `Enter` on the label field\n labelBox.dispatchEvent(new KeyboardEvent('keydown', {key: 'Enter', cancelable: true, bubbles: true}));\n\n // Ensure that the entry overlay has not been because it was has a non-empty label\n assert.strictEqual(overlays.overlaysOfType('TIME_RANGE').length, 1);\n });\n\n it('Can create multiple Time Range Overlays for Time Range annotations', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame);\n\n Timeline.ModificationsManager.ModificationsManager.activeManager()?.createAnnotation({\n type: 'TIME_RANGE',\n label: 'label',\n bounds: traceData.Meta.traceBounds,\n });\n\n Timeline.ModificationsManager.ModificationsManager.activeManager()?.createAnnotation({\n type: 'TIME_RANGE',\n label: 'label2',\n bounds: traceData.Meta.traceBounds,\n });\n overlays.update();\n\n assert.strictEqual(overlays.overlaysOfType('TIME_RANGE').length, 2);\n });\n\n it('Removes empty label if it is empty when navigated away from (removed focused from)', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n\n // Create an entry label overlay\n Timeline.ModificationsManager.ModificationsManager.activeManager()?.createAnnotation({\n type: 'ENTRY_LABEL',\n entry: event as TraceEngine.Types.TraceEvents.TraceEventData,\n label: '',\n });\n overlays.update();\n\n // Ensure that the overlay was created.\n const overlayDOM = container.querySelector('.overlay-type-ENTRY_LABEL');\n assert.isOk(overlayDOM);\n const component = overlayDOM?.querySelector('devtools-entry-label-overlay');\n assert.isOk(component?.shadowRoot);\n\n component.connectedCallback();\n const elementsWrapper = component.shadowRoot.querySelector('.label-parts-wrapper');\n assert.isOk(elementsWrapper);\n\n const label = elementsWrapper.querySelector('.label-box');\n assert.isOk(label);\n\n const inputField = elementsWrapper.querySelector('.input-field');\n assert.isOk(inputField);\n\n // Double click on the label box to make it editable and focus on it\n inputField.dispatchEvent(new FocusEvent('dblclick', {bubbles: true}));\n\n // Ensure that the entry has 1 overlay\n assert.strictEqual(overlays.overlaysForEntry(event).length, 1);\n\n // Change the content to not editable by changing the element blur like when clicking outside of it.\n // The label is empty since no initial value was passed into it and no characters were entered.\n inputField.dispatchEvent(new FocusEvent('blur', {bubbles: true}));\n\n // Ensure that the entry overlay has been removed because it was saved empty\n assert.strictEqual(overlays.overlaysForEntry(event).length, 0);\n });\n\n it('Update label overlay when the label changes', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n\n // Create an entry label overlay\n Timeline.ModificationsManager.ModificationsManager.activeManager()?.createAnnotation({\n type: 'ENTRY_LABEL',\n entry: event as TraceEngine.Types.TraceEvents.TraceEventData,\n label: '',\n });\n overlays.update();\n\n // Ensure that the overlay was created.\n const overlayDOM = container.querySelector('.overlay-type-ENTRY_LABEL');\n assert.isOk(overlayDOM);\n const component = overlayDOM?.querySelector('devtools-entry-label-overlay');\n assert.isOk(component?.shadowRoot);\n\n component.connectedCallback();\n component.dispatchEvent(new Components.EntryLabelOverlay.EntryLabelChangeEvent('new label'));\n\n const updatedOverlay = overlays.overlaysForEntry(event)[0] as Overlays.Overlays.EntryLabel;\n assert.isOk(updatedOverlay);\n // Make sure the label was updated in the Overlay Object\n assert.strictEqual(updatedOverlay.label, 'new label');\n });\n\n it('creates an overlay for a time range when an time range annotation is created', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container} = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData);\n\n // Since TIME_RANGE is AnnotationOverlay, create it through ModificationsManager\n Timeline.ModificationsManager.ModificationsManager.activeManager()?.createAnnotation({\n type: 'TIME_RANGE',\n label: '',\n // Make this overlay the entire span of the trace\n bounds: traceData.Meta.traceBounds,\n });\n overlays.update();\n const overlayDOM = container.querySelector('.overlay-type-TIME_RANGE');\n assert.isOk(overlayDOM);\n });\n\n it('can render an overlay for a time range', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container} = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData);\n overlays.add({\n type: 'TIME_RANGE',\n label: '',\n showDuration: true,\n // Make this overlay the entire span of the trace\n bounds: traceData.Meta.traceBounds,\n });\n overlays.update();\n const overlayDOM = container.querySelector('.overlay-type-TIME_RANGE');\n assert.isOk(overlayDOM);\n });\n\n it('can update a time range overlay with new bounds', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container} = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData);\n const rangeOverlay = overlays.add({\n type: 'TIME_RANGE',\n label: '',\n showDuration: true,\n // Make this overlay the entire span of the trace\n bounds: traceData.Meta.traceBounds,\n });\n overlays.update();\n const overlayDOM = container.querySelector('.overlay-type-TIME_RANGE');\n assert.isOk(overlayDOM);\n const firstWidth = window.parseInt(overlayDOM.style.width);\n\n // change the bounds so the new min is +1second of time.\n const newBounds = TraceEngine.Helpers.Timing.traceWindowFromMicroSeconds(\n TraceEngine.Types.Timing.MicroSeconds(rangeOverlay.bounds.min + (1_000 * 1_000)),\n rangeOverlay.bounds.max,\n );\n overlays.updateExisting(rangeOverlay, {bounds: newBounds});\n overlays.update();\n const secondWidth = window.parseInt(overlayDOM.style.width);\n // The new time range is smaller so the DOM element should have less width\n assert.isTrue(secondWidth < firstWidth);\n });\n\n it('renders the overlay for a selected layout shift entry correctly', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'cls-single-frame.json.gz');\n const {overlays, container} = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData);\n const layoutShiftEvent = traceData.LayoutShifts.clusters.at(0)?.events.at(0);\n if (!layoutShiftEvent) {\n throw new Error('layoutShiftEvent was unexpectedly undefined');\n }\n overlays.add({\n type: 'ENTRY_SELECTED',\n entry: layoutShiftEvent,\n });\n const boundsRange = TraceEngine.Types.Timing.MicroSeconds(20_000);\n const boundsMax = TraceEngine.Types.Timing.MicroSeconds(layoutShiftEvent.ts + boundsRange);\n overlays.updateVisibleWindow({min: layoutShiftEvent.ts, max: boundsMax, range: boundsRange});\n overlays.update();\n const overlayDOM = container.querySelector('.overlay-type-ENTRY_SELECTED');\n assert.isOk(overlayDOM);\n assert.strictEqual(window.parseInt(overlayDOM.style.width), 250);\n });\n\n it('renders the duration and label for a time range overlay', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container} = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData);\n overlays.add({\n type: 'TIME_RANGE',\n label: '',\n showDuration: true,\n // Make this overlay the entire span of the trace\n bounds: traceData.Meta.traceBounds,\n });\n overlays.update();\n await coordinator.done();\n const overlayDOM = container.querySelector('.overlay-type-TIME_RANGE');\n const component = overlayDOM?.querySelector('devtools-time-range-overlay');\n assert.isOk(component?.shadowRoot);\n const rangeContainer = component.shadowRoot.querySelector('.range-container');\n assert.isOk(rangeContainer);\n const duration = rangeContainer.querySelector('.duration');\n assert.isOk(duration);\n assert.strictEqual(duration?.innerText, '1.26\\xA0s');\n });\n\n it('can remove an overlay', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame);\n\n const selectedOverlay = overlays.add({\n type: 'ENTRY_SELECTED',\n entry: event,\n });\n overlays.update();\n assert.lengthOf(container.children, 1);\n\n overlays.remove(selectedOverlay);\n overlays.update();\n assert.lengthOf(container.children, 0);\n });\n\n it('can render an entry selected overlay for a frame', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n const {overlays, container, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData);\n const timelineFrame = charts.mainProvider.eventByIndex?.(5);\n assert.isOk(timelineFrame);\n assert.instanceOf(timelineFrame, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame);\n\n overlays.add({\n type: 'ENTRY_SELECTED',\n entry: timelineFrame,\n });\n overlays.update();\n\n // Ensure that the overlay was created.\n const overlayDOM = container.querySelector('.overlay-type-ENTRY_SELECTED');\n assert.isOk(overlayDOM);\n });\n\n it('can return a list of overlays for an entry', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame);\n\n overlays.add({\n type: 'ENTRY_SELECTED',\n entry: event,\n });\n\n assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame);\n const existingOverlays = overlays.overlaysForEntry(event);\n assert.deepEqual(existingOverlays, [{\n type: 'ENTRY_SELECTED',\n entry: event,\n }]);\n });\n\n it('can delete overlays and remove them from the DOM', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {container, overlays, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n\n assert.notInstanceOf(event, TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame);\n overlays.add({\n type: 'ENTRY_SELECTED',\n entry: event,\n });\n overlays.update();\n\n assert.lengthOf(container.children, 1);\n const removedCount = overlays.removeOverlaysOfType('ENTRY_SELECTED');\n assert.strictEqual(removedCount, 1);\n assert.lengthOf(container.children, 0);\n });\n\n it('the label entry field is editable when created', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container} = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData);\n const charts = createCharts(traceData);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n\n // Since ENTRY_LABEL is AnnotationOverlay, create it through ModificationsManager\n Timeline.ModificationsManager.ModificationsManager.activeManager()?.createAnnotation({\n type: 'ENTRY_LABEL',\n label: '',\n entry: event as TraceEngine.Types.TraceEvents.TraceEventData,\n });\n\n overlays.update();\n const overlayDOM = container.querySelector('.overlay-type-ENTRY_LABEL');\n assert.isOk(overlayDOM);\n const component = overlayDOM?.querySelector('devtools-entry-label-overlay');\n assert.isOk(component?.shadowRoot);\n\n const elementsWrapper = component.shadowRoot.querySelector('.label-parts-wrapper');\n const labelBox = elementsWrapper?.querySelector('.label-box') as HTMLSpanElement;\n\n const inputField = labelBox.querySelector('.input-field');\n assert.isOk(inputField);\n // The label input box should be editable after it is created and before anything else happened\n assert.isTrue(inputField.isContentEditable);\n });\n\n it('the label entry field is in focus after being double clicked on', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container} = setupChartWithDimensionsAndAnnotationOverlayListeners(traceData);\n const charts = createCharts(traceData);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n\n // Since ENTRY_LABEL is AnnotationOverlay, create it through ModificationsManager\n Timeline.ModificationsManager.ModificationsManager.activeManager()?.createAnnotation({\n type: 'ENTRY_LABEL',\n label: '',\n entry: event as TraceEngine.Types.TraceEvents.TraceEventData,\n });\n\n overlays.update();\n const overlayDOM = container.querySelector('.overlay-type-ENTRY_LABEL');\n assert.isOk(overlayDOM);\n const component = overlayDOM?.querySelector('devtools-entry-label-overlay');\n assert.isOk(component?.shadowRoot);\n\n const elementsWrapper = component.shadowRoot.querySelector('.label-parts-wrapper');\n assert.isOk(elementsWrapper);\n const labelBox = elementsWrapper.querySelector('.label-box') as HTMLSpanElement;\n\n const inputField = labelBox.querySelector('.input-field');\n assert.isOk(inputField);\n\n // The label input box should be editable after it is created and before anything else happened\n assert.isTrue(inputField.isContentEditable);\n\n // Make the content to editable by changing the element blur like when clicking outside of it.\n // When that happens, the content should be set to not editable.\n inputField.dispatchEvent(new FocusEvent('blur', {bubbles: true}));\n assert.isFalse(inputField.isContentEditable);\n\n // Double click on the label to make it editable again\n inputField.dispatchEvent(new FocusEvent('dblclick', {bubbles: true}));\n assert.isTrue(inputField.isContentEditable);\n });\n });\n\n describe('traceWindowContainingOverlays', () => {\n it('calculates the smallest window that fits the overlay inside', () => {\n const FAKE_EVENT_1 = {\n ts: 0,\n dur: 10,\n } as TraceEngine.Types.TraceEvents.TraceEventData;\n const FAKE_EVENT_2 = {\n ts: 5,\n dur: 100,\n } as TraceEngine.Types.TraceEvents.TraceEventData;\n\n const overlay1: Overlays.Overlays.EntryOutline = {\n entry: FAKE_EVENT_1,\n type: 'ENTRY_OUTLINE',\n outlineReason: 'INFO',\n };\n const overlay2: Overlays.Overlays.EntryOutline = {\n entry: FAKE_EVENT_2,\n type: 'ENTRY_OUTLINE',\n outlineReason: 'INFO',\n };\n const traceWindow = Overlays.Overlays.traceWindowContainingOverlays([overlay1, overlay2]);\n assert.strictEqual(traceWindow.min, 0);\n assert.strictEqual(traceWindow.max, 105);\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"OverlaysImpl.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/overlays/OverlaysImpl.test.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAC7B,OAAO,KAAK,KAAK,MAAM,gCAAgC,CAAC;AACxD,OAAO,EAAC,uBAAuB,EAAC,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,iCAAiC,GAClC,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAC,WAAW,EAAC,MAAM,iCAAiC,CAAC;AAC5D,OAAO,KAAK,iBAAiB,MAAM,iEAAiE,CAAC;AACrG,OAAO,KAAK,MAAM,MAAM,kDAAkD,CAAC;AAC3E,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAE3C,OAAO,KAAK,UAAU,MAAM,4BAA4B,CAAC;AACzD,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAE1C,MAAM,WAAW,GAAG,iBAAiB,CAAC,iBAAiB,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC;AAErF,MAAM,0BAA0B,GAA0C;IACxE,sBAAsB;QACpB,OAAO,KAAK,CAAC;IACf,CAAC;IACD,0BAA0B;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;CACF,CAAC;AAEF;;;;GAIG;AACH,SAAS,YAAY,CAAC,WAA8C;IAClE,MAAM,YAAY,GAAG,IAAI,QAAQ,CAAC,8BAA8B,CAAC,8BAA8B,EAAE,CAAC;IAClG,MAAM,eAAe,GAAG,IAAI,QAAQ,CAAC,qCAAqC,CAAC,qCAAqC,EAAE,CAAC;IAEnH,MAAM,QAAQ,GAAG,IAAI,sBAAsB,EAAE,CAAC;IAC9C,MAAM,SAAS,GAAG,IAAI,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;IAC3E,MAAM,YAAY,GAAG,IAAI,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,eAAe,EAAE,QAAQ,CAAC,CAAC;IAEjF,IAAI,WAAW,EAAE,CAAC;QAChB,YAAY,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QACnC,eAAe,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;QAEtC,2EAA2E;QAC3E,oDAAoD;QACpD,SAAS,CAAC,MAAM,EAAE,CAAC;QACnB,YAAY,CAAC,MAAM,EAAE,CAAC;IACxB,CAAC;IAED,OAAO;QACL,YAAY;QACZ,SAAS;QACT,eAAe;QACf,YAAY;KACb,CAAC;AACJ,CAAC;AAED,uBAAuB,CAAC,UAAU,EAAE,GAAG,EAAE;IACvC,UAAU,CAAC,GAAG,EAAE;QACd,iCAAiC,EAAE,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oFAAoF,EAAE,KAAK,IAAI,EAAE;QAClG,MAAM,oBAAoB,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC3D,MAAM,wBAAwB,GAAG,oBAAoB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACzE,MAAM,2BAA2B,GAAG,oBAAoB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC5E,MAAM,SAAS,GAAG,oBAAoB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAE1D,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAC9C,SAAS;YACT,qBAAqB,EAAE;gBACrB,IAAI,EAAE,wBAAwB;gBAC9B,OAAO,EAAE,2BAA2B;aACrC;YACD,MAAM,EAAE,YAAY,EAAE;YACtB,YAAY,EAAE,0BAA0B;SACzC,CAAC,CAAC;QAEH,4CAA4C;QAC5C,QAAQ,CAAC,qBAAqB,CAAC,MAAM,EAAE;YACrC,WAAW,EAAE,GAAG;YAChB,YAAY,EAAE,EAAE;YAChB,kBAAkB,EAAE,CAAC;YACrB,kBAAkB,EAAE,KAAK;SAC1B,CAAC,CAAC;QACH,QAAQ,CAAC,qBAAqB,CAAC,SAAS,EAAE;YACxC,WAAW,EAAE,GAAG;YAChB,YAAY,EAAE,EAAE;YAChB,kBAAkB,EAAE,CAAC;YACrB,kBAAkB,EAAE,KAAK;SAC1B,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACrD,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QACvD,kDAAkD;QAClD,QAAQ,CAAC,mBAAmB,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,2BAA2B,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC;QAErG,6CAA6C;QAC7C,MAAM,KAAK,GAAG,gBAAgB,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QAEjD,MAAM,SAAS,GAAG,QAAQ,CAAC,0BAA0B,CAAC,KAAK,CAAC,CAAC;QAC7D,MAAM,CAAC,WAAW,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACpC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK;QAC5D,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;QAC7E,MAAM,MAAM,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;QAEzC,MAAM,oBAAoB,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC3D,MAAM,wBAAwB,GAAG,oBAAoB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACzE,MAAM,2BAA2B,GAAG,oBAAoB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC5E,MAAM,SAAS,GAAG,oBAAoB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAE1D,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAC9C,SAAS;YACT,qBAAqB,EAAE;gBACrB,IAAI,EAAE,wBAAwB;gBAC9B,OAAO,EAAE,2BAA2B;aACrC;YACD,MAAM;YACN,YAAY,EAAE,0BAA0B;SACzC,CAAC,CAAC;QAEH,QAAQ,CAAC,qBAAqB,CAAC,MAAM,EAAE;YACrC,WAAW,EAAE,IAAI;YACjB,YAAY,EAAE,GAAG;YACjB,kBAAkB,EAAE,CAAC;YACrB,kBAAkB,EAAE,KAAK;SAC1B,CAAC,CAAC;QACH,QAAQ,CAAC,qBAAqB,CAAC,SAAS,EAAE;YACxC,WAAW,EAAE,IAAI;YACjB,YAAY,EAAE,GAAG;YACjB,kBAAkB,EAAE,CAAC;YACrB,kBAAkB,EAAE,KAAK;SAC1B,CAAC,CAAC;QAEH,iDAAiD;QACjD,QAAQ,CAAC,mBAAmB,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAE3D,0FAA0F;QAC1F,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;QACrD,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QAC/E,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,MAAM,MAAM,GAAG,QAAQ,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;QACrD,+EAA+E;QAC/E,wEAAwE;QACxE,SAAS;QACT,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qFAAqF,EAAE,KAAK;QAC7F,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;QAC7E,MAAM,MAAM,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;QAEzC,MAAM,oBAAoB,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC3D,MAAM,wBAAwB,GAAG,oBAAoB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACzE,MAAM,2BAA2B,GAAG,oBAAoB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC5E,MAAM,SAAS,GAAG,oBAAoB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAE1D,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAC9C,SAAS;YACT,qBAAqB,EAAE;gBACrB,IAAI,EAAE,wBAAwB;gBAC9B,OAAO,EAAE,2BAA2B;aACrC;YACD,MAAM;YACN,YAAY,EAAE,0BAA0B;SACzC,CAAC,CAAC;QAEH,QAAQ,CAAC,qBAAqB,CAAC,MAAM,EAAE;YACrC,WAAW,EAAE,IAAI;YACjB,YAAY,EAAE,GAAG;YACjB,kBAAkB,EAAE,CAAC;YACrB,kBAAkB,EAAE,KAAK;SAC1B,CAAC,CAAC;QACH,QAAQ,CAAC,qBAAqB,CAAC,SAAS,EAAE;YACxC,WAAW,EAAE,IAAI;YACjB,YAAY,EAAE,EAAE;YAChB,kBAAkB,EAAE,CAAC;YACrB,mCAAmC;YACnC,kBAAkB,EAAE,IAAI;SACzB,CAAC,CAAC;QAEH,iDAAiD;QACjD,QAAQ,CAAC,mBAAmB,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAE3D,0FAA0F;QAC1F,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;QACrD,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QAC/E,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,MAAM,MAAM,GAAG,QAAQ,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;QACrD,2EAA2E;QAC3E,2EAA2E;QAC3E,+DAA+D;QAC/D,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,KAAK;QAC/D,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;QAC7E,MAAM,MAAM,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;QAEzC,MAAM,oBAAoB,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC3D,MAAM,wBAAwB,GAAG,oBAAoB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QACzE,MAAM,2BAA2B,GAAG,oBAAoB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAC5E,MAAM,SAAS,GAAG,oBAAoB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAE1D,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;YAC9C,SAAS;YACT,qBAAqB,EAAE;gBACrB,IAAI,EAAE,wBAAwB;gBAC9B,OAAO,EAAE,2BAA2B;aACrC;YACD,MAAM;YACN,YAAY,EAAE,0BAA0B;SACzC,CAAC,CAAC;QAEH,QAAQ,CAAC,qBAAqB,CAAC,MAAM,EAAE;YACrC,WAAW,EAAE,IAAI;YACjB,YAAY,EAAE,GAAG;YACjB,kBAAkB,EAAE,CAAC;YACrB,kBAAkB,EAAE,KAAK;SAC1B,CAAC,CAAC;QACH,QAAQ,CAAC,qBAAqB,CAAC,SAAS,EAAE;YACxC,WAAW,EAAE,IAAI;YACjB,YAAY,EAAE,GAAG;YACjB,kBAAkB,EAAE,CAAC;YACrB,kBAAkB,EAAE,KAAK;SAC1B,CAAC,CAAC;QAEH,iDAAiD;QACjD,QAAQ,CAAC,mBAAmB,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAE3D,2EAA2E;QAC3E,mCAAmC;QACnC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,gBAAgB,CAAC,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAExE,qCAAqC;QACrC,MAAM,KAAK,GAAG,MAAM,CAAC,eAAe,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC;QACvD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACnB,MAAM,MAAM,GAAG,QAAQ,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC;QACrD,wEAAwE;QACxE,0EAA0E;QAC1E,uCAAuC;QACvC,MAAM,CAAC,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAClC,SAAS,qDAAqD,CAAC,WAA6C;YAK1G,MAAM,MAAM,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;YAEzC,MAAM,oBAAoB,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;YAC3D,MAAM,wBAAwB,GAAG,oBAAoB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YACzE,MAAM,2BAA2B,GAAG,oBAAoB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YAC5E,MAAM,SAAS,GAAG,oBAAoB,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YAE1D,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;gBAC9C,SAAS;gBACT,qBAAqB,EAAE;oBACrB,IAAI,EAAE,wBAAwB;oBAC9B,OAAO,EAAE,2BAA2B;iBACrC;gBACD,MAAM;gBACN,YAAY,EAAE,0BAA0B;aACzC,CAAC,CAAC;YACH,MAAM,WAAW,GAAG,QAAQ,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,aAAa,EAAE,CAAC;YACvF,+EAA+E;YAC/E,WAAW,EAAE,gBAAgB,CAAC,QAAQ,CAAC,oBAAoB,CAAC,uBAAuB,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE;gBACrG,MAAM,EAAC,OAAO,EAAE,MAAM,EAAC,GAAI,KAA+D,CAAC;gBAC3F,IAAI,MAAM,KAAK,KAAK,EAAE,CAAC;oBACrB,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;gBACxB,CAAC;gBACD,QAAQ,CAAC,MAAM,EAAE,CAAC;YACpB,CAAC,CAAC,CAAC;YAEH,iGAAiG;YACjG,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,CAAC,QAAQ,CAAC,4BAA4B,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE;gBAC1F,MAAM,EAAC,OAAO,EAAE,MAAM,EAAC,GAAI,KAAwD,CAAC;gBACpF,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;oBACxB,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBAC3B,CAAC;gBACD,QAAQ,CAAC,MAAM,EAAE,CAAC;YACpB,CAAC,CAAC,CAAC;YAEH,QAAQ,CAAC,qBAAqB,CAAC,MAAM,EAAE;gBACrC,WAAW,EAAE,IAAI;gBACjB,YAAY,EAAE,GAAG;gBACjB,kBAAkB,EAAE,CAAC;gBACrB,kBAAkB,EAAE,KAAK;aAC1B,CAAC,CAAC;YACH,QAAQ,CAAC,qBAAqB,CAAC,SAAS,EAAE;gBACxC,WAAW,EAAE,IAAI;gBACjB,YAAY,EAAE,GAAG;gBACjB,kBAAkB,EAAE,CAAC;gBACrB,kBAAkB,EAAE,KAAK;aAC1B,CAAC,CAAC;YAEH,iDAAiD;YACjD,QAAQ,CAAC,mBAAmB,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC3D,OAAO,EAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAC,CAAC;QACvC,CAAC;QAED,EAAE,CAAC,sCAAsC,EAAE,KAAK;YAC9C,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC7E,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAC,GAAG,qDAAqD,CAAC,WAAW,CAAC,CAAC;YACzG,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YAE/E,QAAQ,CAAC,GAAG,CAAC;gBACX,IAAI,EAAE,gBAAgB;gBACtB,KAAK,EAAE,KAAK;aACb,CAAC,CAAC;YACH,QAAQ,CAAC,MAAM,EAAE,CAAC;YAElB,uCAAuC;YACvC,MAAM,UAAU,GAAG,SAAS,CAAC,aAAa,CAAc,8BAA8B,CAAC,CAAC;YACxF,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gFAAgF,EAAE,KAAK;YACxF,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC7E,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAC,GAAG,qDAAqD,CAAC,WAAW,CAAC,CAAC;YACzG,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,QAAQ,CAAC,GAAG,CAAC;gBACX,IAAI,EAAE,eAAe;gBACrB,KAAK,EAAE,KAAK;gBACZ,aAAa,EAAE,OAAO;aACvB,CAAC,CAAC;YACH,QAAQ,CAAC,MAAM,EAAE,CAAC;YAElB,MAAM,cAAc,GAChB,SAAS,CAAC,aAAa,CAAc,6BAA6B,CAAC,EAAE,KAAK,CAAC,OAAO,KAAK,OAAO,CAAC;YACnG,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,qCAAqC,CAAC,CAAC;YAErE,gCAAgC;YAChC,QAAQ,CAAC,GAAG,CAAC;gBACX,IAAI,EAAE,gBAAgB;gBACtB,KAAK,EAAE,KAAK;aACb,CAAC,CAAC;YACH,QAAQ,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,gBAAgB,GAClB,SAAS,CAAC,aAAa,CAAc,6BAA6B,CAAC,EAAE,KAAK,CAAC,OAAO,KAAK,MAAM,CAAC;YAClG,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,oCAAoC,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK;YACrD,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC7E,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAC,GAAG,qDAAqD,CAAC,WAAW,CAAC,CAAC;YACzG,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;YACtD,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;YACtD,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACpB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAEpB,QAAQ,CAAC,GAAG,CAAC;gBACX,IAAI,EAAE,gBAAgB;gBACtB,KAAK,EAAE,MAAM;aACd,CAAC,CAAC;YACH,QAAQ,CAAC,MAAM,EAAE,CAAC;YAClB,QAAQ,CAAC,GAAG,CAAC;gBACX,IAAI,EAAE,gBAAgB;gBACtB,KAAK,EAAE,MAAM;aACd,CAAC,CAAC;YACH,QAAQ,CAAC,MAAM,EAAE,CAAC;YAElB,oCAAoC;YACpC,MAAM,qBAAqB,GAAG,SAAS,CAAC,gBAAgB,CAAc,8BAA8B,CAAC,CAAC;YACtG,MAAM,CAAC,QAAQ,CAAC,qBAAqB,EAAE,CAAC,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gCAAgC,EAAE,KAAK;YACxC,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC7E,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAC,GAAG,qDAAqD,CAAC,WAAW,CAAC,CAAC;YACzG,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YAE/E,QAAQ,CAAC,GAAG,CAAC;gBACX,IAAI,EAAE,aAAa;gBACnB,KAAK,EAAE,KAAK;gBACZ,KAAK,EAAE,aAAa;aACrB,CAAC,CAAC;YACH,QAAQ,CAAC,MAAM,EAAE,CAAC;YAElB,uCAAuC;YACvC,MAAM,UAAU,GAAG,SAAS,CAAC,aAAa,CAAc,2BAA2B,CAAC,CAAC;YACrF,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,+DAA+D,EAAE,KAAK;YACvE,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC7E,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAC,GAAG,qDAAqD,CAAC,WAAW,CAAC,CAAC;YACjG,QAAQ,CAAC,GAAG,CAAC;gBACX,IAAI,EAAE,yBAAyB;gBAC/B,SAAS,EAAE,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG;aAC5C,CAAC,CAAC;YACH,QAAQ,CAAC,GAAG,CAAC;gBACX,IAAI,EAAE,yBAAyB;gBAC/B,SAAS,EAAE,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG;aAC5C,CAAC,CAAC;YACH,QAAQ,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8CAA8C,EAAE,KAAK;YACtD,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC7E,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAC,GAAG,qDAAqD,CAAC,WAAW,CAAC,CAAC;YACzG,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YAE/E,QAAQ,CAAC,GAAG,CAAC;gBACX,IAAI,EAAE,aAAa;gBACnB,KAAK,EAAE,KAAK;gBACZ,KAAK,EAAE,aAAa;aACrB,CAAC,CAAC;YACH,QAAQ,CAAC,MAAM,EAAE,CAAC;YAElB,MAAM,UAAU,GAAG,SAAS,CAAC,aAAa,CAAc,2BAA2B,CAAC,CAAC;YACrF,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACxB,MAAM,SAAS,GAAG,UAAU,EAAE,aAAa,CAAC,8BAA8B,CAAC,CAAC;YAC5E,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;YAEnC,MAAM,eAAe,GAAG,SAAS,CAAC,UAAU,CAAC,aAAa,CAAc,sBAAsB,CAAC,CAAC;YAChG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YAE7B,MAAM,QAAQ,GAAG,eAAe,CAAC,aAAa,CAAc,YAAY,CAAC,CAAC;YAC1E,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAEtB,MAAM,UAAU,GAAG,QAAQ,CAAC,aAAa,CAAc,cAAc,CAAC,CAAC;YACvE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAExB,MAAM,CAAC,WAAW,CAAC,UAAU,EAAE,SAAS,EAAE,aAAa,CAAC,CAAC;QAC3D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK;YACnE,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC7E,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAC,GAAG,qDAAqD,CAAC,WAAW,CAAC,CAAC;YACzG,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YAE/E,gCAAgC;YAChC,QAAQ,CAAC,GAAG,CAAC;gBACX,IAAI,EAAE,aAAa;gBACnB,KAAK,EAAE,KAAK;gBACZ,KAAK,EAAE,OAAO;aACf,CAAC,CAAC;YACH,QAAQ,CAAC,MAAM,EAAE,CAAC;YAElB,uCAAuC;YACvC,MAAM,UAAU,GAAG,SAAS,CAAC,aAAa,CAAc,2BAA2B,CAAC,CAAC;YACrF,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAExB,MAAM,SAAS,GAAG,UAAU,EAAE,aAAa,CAAC,8BAA8B,CAAC,CAAC;YAC5E,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;YACnC,SAAS,CAAC,iBAAiB,EAAE,CAAC;YAC9B,MAAM,eAAe,GAAG,SAAS,CAAC,UAAU,CAAC,aAAa,CAAc,sBAAsB,CAAC,CAAC;YAChG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YAE7B,MAAM,KAAK,GAAG,eAAe,CAAC,aAAa,CAAc,YAAY,CAAC,CAAC;YACvE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,MAAM,UAAU,GAAG,KAAK,CAAC,aAAa,CAAc,cAAc,CAAC,CAAC;YACpE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAExB,oEAAoE;YACpE,UAAU,CAAC,aAAa,CAAC,IAAI,UAAU,CAAC,UAAU,EAAE,EAAC,OAAO,EAAE,IAAI,EAAC,CAAC,CAAC,CAAC;YAEtE,uCAAuC;YACvC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;YAE5C,+CAA+C;YAC/C,UAAU,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,SAAS,EAAE,EAAC,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAC,CAAC,CAAC,CAAC;YAExG,2CAA2C;YAC3C,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2FAA2F,EAAE,KAAK;YACnG,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC7E,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAC,GAAG,qDAAqD,CAAC,WAAW,CAAC,CAAC;YACzG,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YAE/E,kDAAkD;YAClD,QAAQ,CAAC,GAAG,CAAC;gBACX,IAAI,EAAE,YAAY;gBAClB,KAAK,EAAE,EAAE;gBACT,YAAY,EAAE,IAAI;gBAClB,iDAAiD;gBACjD,MAAM,EAAE,WAAW,CAAC,IAAI,CAAC,WAAW;aACrC,CAAC,CAAC;YACH,QAAQ,CAAC,MAAM,EAAE,CAAC;YAElB,uCAAuC;YACvC,MAAM,UAAU,GAAG,SAAS,CAAC,aAAa,CAAc,0BAA0B,CAAC,CAAC;YACpF,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAExB,MAAM,SAAS,GAAG,UAAU,EAAE,aAAa,CAAC,6BAA6B,CAAC,CAAC;YAC3E,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;YACnC,SAAS,CAAC,iBAAiB,EAAE,CAAC;YAC9B,MAAM,cAAc,GAAG,SAAS,CAAC,UAAU,CAAC,aAAa,CAAc,kBAAkB,CAAC,CAAC;YAC3F,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAE5B,MAAM,QAAQ,GAAG,cAAc,CAAC,aAAa,CAAc,aAAa,CAAC,CAAC;YAC1E,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAEtB,oEAAoE;YACpE,QAAQ,CAAC,aAAa,CAAC,IAAI,UAAU,CAAC,UAAU,EAAE,EAAC,OAAO,EAAE,IAAI,EAAC,CAAC,CAAC,CAAC;YAEpE,mCAAmC;YACnC,QAAQ,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,SAAS,EAAE,EAAC,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAC,CAAC,CAAC,CAAC;YAEtG,4EAA4E;YAC5E,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACtE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uGAAuG,EACvG,KAAK;YACH,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC7E,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAC,GAAG,qDAAqD,CAAC,WAAW,CAAC,CAAC;YACzG,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YAE/E,2CAA2C;YAC3C,QAAQ,CAAC,GAAG,CAAC;gBACX,IAAI,EAAE,YAAY;gBAClB,KAAK,EAAE,OAAO;gBACd,YAAY,EAAE,IAAI;gBAClB,iDAAiD;gBACjD,MAAM,EAAE,WAAW,CAAC,IAAI,CAAC,WAAW;aACrC,CAAC,CAAC;YACH,QAAQ,CAAC,MAAM,EAAE,CAAC;YAElB,uCAAuC;YACvC,MAAM,UAAU,GAAG,SAAS,CAAC,aAAa,CAAc,0BAA0B,CAAC,CAAC;YACpF,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAExB,MAAM,SAAS,GAAG,UAAU,EAAE,aAAa,CAAC,6BAA6B,CAAC,CAAC;YAC3E,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;YACnC,SAAS,CAAC,iBAAiB,EAAE,CAAC;YAC9B,MAAM,cAAc,GAAG,SAAS,CAAC,UAAU,CAAC,aAAa,CAAc,kBAAkB,CAAC,CAAC;YAC3F,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAE5B,MAAM,QAAQ,GAAG,cAAc,CAAC,aAAa,CAAc,aAAa,CAAC,CAAC;YAC1E,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAEtB,oEAAoE;YACpE,QAAQ,CAAC,aAAa,CAAC,IAAI,UAAU,CAAC,UAAU,EAAE,EAAC,OAAO,EAAE,IAAI,EAAC,CAAC,CAAC,CAAC;YAEpE,mCAAmC;YACnC,QAAQ,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,SAAS,EAAE,EAAC,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAC,CAAC,CAAC,CAAC;YAEtG,kFAAkF;YAClF,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACtE,CAAC,CAAC,CAAC;QAEN,EAAE,CAAC,oEAAoE,EAAE,KAAK;YAC5E,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC7E,MAAM,EAAC,QAAQ,EAAE,MAAM,EAAC,GAAG,qDAAqD,CAAC,WAAW,CAAC,CAAC;YAC9F,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YAE/E,QAAQ,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,aAAa,EAAE,EAAE,gBAAgB,CAAC;gBACnF,IAAI,EAAE,YAAY;gBAClB,KAAK,EAAE,OAAO;gBACd,MAAM,EAAE,WAAW,CAAC,IAAI,CAAC,WAAW;aACrC,CAAC,CAAC;YAEH,QAAQ,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,aAAa,EAAE,EAAE,gBAAgB,CAAC;gBACnF,IAAI,EAAE,YAAY;gBAClB,KAAK,EAAE,QAAQ;gBACf,MAAM,EAAE,WAAW,CAAC,IAAI,CAAC,WAAW;aACrC,CAAC,CAAC;YACH,QAAQ,CAAC,MAAM,EAAE,CAAC;YAElB,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,cAAc,CAAC,YAAY,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACtE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oFAAoF,EAAE,KAAK;YAC5F,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC7E,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAC,GAAG,qDAAqD,CAAC,WAAW,CAAC,CAAC;YACzG,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAEnB,gCAAgC;YAChC,QAAQ,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,aAAa,EAAE,EAAE,gBAAgB,CAAC;gBACnF,IAAI,EAAE,aAAa;gBACnB,KAAK,EAAE,KAAiC;gBACxC,KAAK,EAAE,EAAE;aACV,CAAC,CAAC;YACH,QAAQ,CAAC,MAAM,EAAE,CAAC;YAElB,uCAAuC;YACvC,MAAM,UAAU,GAAG,SAAS,CAAC,aAAa,CAAc,2BAA2B,CAAC,CAAC;YACrF,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACxB,MAAM,SAAS,GAAG,UAAU,EAAE,aAAa,CAAC,8BAA8B,CAAC,CAAC;YAC5E,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;YAEnC,SAAS,CAAC,iBAAiB,EAAE,CAAC;YAC9B,MAAM,eAAe,GAAG,SAAS,CAAC,UAAU,CAAC,aAAa,CAAc,sBAAsB,CAAC,CAAC;YAChG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YAE7B,MAAM,KAAK,GAAG,eAAe,CAAC,aAAa,CAAc,YAAY,CAAC,CAAC;YACvE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAEnB,MAAM,UAAU,GAAG,eAAe,CAAC,aAAa,CAAc,cAAc,CAAC,CAAC;YAC9E,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAExB,oEAAoE;YACpE,UAAU,CAAC,aAAa,CAAC,IAAI,UAAU,CAAC,UAAU,EAAE,EAAC,OAAO,EAAE,IAAI,EAAC,CAAC,CAAC,CAAC;YAEtE,sCAAsC;YACtC,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;YAE/D,oGAAoG;YACpG,+FAA+F;YAC/F,UAAU,CAAC,aAAa,CAAC,IAAI,UAAU,CAAC,MAAM,EAAE,EAAC,OAAO,EAAE,IAAI,EAAC,CAAC,CAAC,CAAC;YAElE,4EAA4E;YAC5E,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACjE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK;YACrD,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC7E,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAC,GAAG,qDAAqD,CAAC,WAAW,CAAC,CAAC;YACzG,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAEnB,gCAAgC;YAChC,QAAQ,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,aAAa,EAAE,EAAE,gBAAgB,CAAC;gBACnF,IAAI,EAAE,aAAa;gBACnB,KAAK,EAAE,KAAiC;gBACxC,KAAK,EAAE,EAAE;aACV,CAAC,CAAC;YACH,QAAQ,CAAC,MAAM,EAAE,CAAC;YAElB,uCAAuC;YACvC,MAAM,UAAU,GAAG,SAAS,CAAC,aAAa,CAAc,2BAA2B,CAAC,CAAC;YACrF,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACxB,MAAM,SAAS,GAAG,UAAU,EAAE,aAAa,CAAC,8BAA8B,CAAC,CAAC;YAC5E,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;YAEnC,SAAS,CAAC,iBAAiB,EAAE,CAAC;YAC9B,SAAS,CAAC,aAAa,CAAC,IAAI,UAAU,CAAC,iBAAiB,CAAC,qBAAqB,CAAC,WAAW,CAAC,CAAC,CAAC;YAE7F,MAAM,cAAc,GAAG,QAAQ,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAiC,CAAC;YAC3F,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAC5B,wDAAwD;YACxD,MAAM,CAAC,WAAW,CAAC,cAAc,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8EAA8E,EAAE,KAAK;YACtF,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC7E,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAC,GAAG,qDAAqD,CAAC,WAAW,CAAC,CAAC;YAEjG,gFAAgF;YAChF,QAAQ,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,aAAa,EAAE,EAAE,gBAAgB,CAAC;gBACnF,IAAI,EAAE,YAAY;gBAClB,KAAK,EAAE,EAAE;gBACT,iDAAiD;gBACjD,MAAM,EAAE,WAAW,CAAC,IAAI,CAAC,WAAW;aACrC,CAAC,CAAC;YACH,QAAQ,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,UAAU,GAAG,SAAS,CAAC,aAAa,CAAc,0BAA0B,CAAC,CAAC;YACpF,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK;YAChD,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC7E,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAC,GAAG,qDAAqD,CAAC,WAAW,CAAC,CAAC;YACjG,QAAQ,CAAC,GAAG,CAAC;gBACX,IAAI,EAAE,YAAY;gBAClB,KAAK,EAAE,EAAE;gBACT,YAAY,EAAE,IAAI;gBAClB,iDAAiD;gBACjD,MAAM,EAAE,WAAW,CAAC,IAAI,CAAC,WAAW;aACrC,CAAC,CAAC;YACH,QAAQ,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,UAAU,GAAG,SAAS,CAAC,aAAa,CAAc,0BAA0B,CAAC,CAAC;YACpF,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iDAAiD,EAAE,KAAK;YACzD,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC7E,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAC,GAAG,qDAAqD,CAAC,WAAW,CAAC,CAAC;YACjG,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC;gBAChC,IAAI,EAAE,YAAY;gBAClB,KAAK,EAAE,EAAE;gBACT,YAAY,EAAE,IAAI;gBAClB,iDAAiD;gBACjD,MAAM,EAAE,WAAW,CAAC,IAAI,CAAC,WAAW;aACrC,CAAC,CAAC;YACH,QAAQ,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,UAAU,GAAG,SAAS,CAAC,aAAa,CAAc,0BAA0B,CAAC,CAAC;YACpF,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACxB,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAE3D,wDAAwD;YACxD,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,2BAA2B,CAC9D,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC,EAC1E,YAAY,CAAC,MAAM,CAAC,GAAG,CAC1B,CAAC;YACF,QAAQ,CAAC,cAAc,CAAC,YAAY,EAAE,EAAC,MAAM,EAAE,SAAS,EAAC,CAAC,CAAC;YAC3D,QAAQ,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,WAAW,GAAG,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC5D,0EAA0E;YAC1E,MAAM,CAAC,MAAM,CAAC,WAAW,GAAG,UAAU,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iEAAiE,EAAE,KAAK;YACzE,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,0BAA0B,CAAC,CAAC;YACtF,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAC,GAAG,qDAAqD,CAAC,WAAW,CAAC,CAAC;YACjG,MAAM,gBAAgB,GAAG,WAAW,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YAC/E,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACtB,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;YACjE,CAAC;YACD,QAAQ,CAAC,GAAG,CAAC;gBACX,IAAI,EAAE,gBAAgB;gBACtB,KAAK,EAAE,gBAAgB;aACxB,CAAC,CAAC;YACH,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;YAC5D,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,gBAAgB,CAAC,EAAE,GAAG,WAAW,CAAC,CAAC;YACrF,QAAQ,CAAC,mBAAmB,CAAC,EAAC,GAAG,EAAE,gBAAgB,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,EAAC,CAAC,CAAC;YAC7F,QAAQ,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,UAAU,GAAG,SAAS,CAAC,aAAa,CAAc,8BAA8B,CAAC,CAAC;YACxF,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACxB,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,yDAAyD,EAAE,KAAK;YACjE,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC7E,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAC,GAAG,qDAAqD,CAAC,WAAW,CAAC,CAAC;YACjG,QAAQ,CAAC,GAAG,CAAC;gBACX,IAAI,EAAE,YAAY;gBAClB,KAAK,EAAE,EAAE;gBACT,YAAY,EAAE,IAAI;gBAClB,iDAAiD;gBACjD,MAAM,EAAE,WAAW,CAAC,IAAI,CAAC,WAAW;aACrC,CAAC,CAAC;YACH,QAAQ,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,WAAW,CAAC,IAAI,EAAE,CAAC;YACzB,MAAM,UAAU,GAAG,SAAS,CAAC,aAAa,CAAc,0BAA0B,CAAC,CAAC;YACpF,MAAM,SAAS,GAAG,UAAU,EAAE,aAAa,CAAC,6BAA6B,CAAC,CAAC;YAC3E,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;YACnC,MAAM,cAAc,GAAG,SAAS,CAAC,UAAU,CAAC,aAAa,CAAc,kBAAkB,CAAC,CAAC;YAC3F,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YAC5B,MAAM,QAAQ,GAAG,cAAc,CAAC,aAAa,CAAc,WAAW,CAAC,CAAC;YACxE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACtB,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;QACvD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uBAAuB,EAAE,KAAK;YAC/B,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC7E,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAC,GAAG,qDAAqD,CAAC,WAAW,CAAC,CAAC;YACzG,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YAE/E,MAAM,eAAe,GAAG,QAAQ,CAAC,GAAG,CAAC;gBACnC,IAAI,EAAE,gBAAgB;gBACtB,KAAK,EAAE,KAAK;aACb,CAAC,CAAC;YACH,QAAQ,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YAEvC,QAAQ,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;YACjC,QAAQ,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK;YAC1D,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,6BAA6B,CAAC,CAAC;YACzF,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAC,GAAG,qDAAqD,CAAC,WAAW,CAAC,CAAC;YACzG,MAAM,aAAa,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,CAAC;YAC5D,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YAC3B,MAAM,CAAC,UAAU,CAAC,aAAa,EAAE,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YAEpF,QAAQ,CAAC,GAAG,CAAC;gBACX,IAAI,EAAE,gBAAgB;gBACtB,KAAK,EAAE,aAAa;aACrB,CAAC,CAAC;YACH,QAAQ,CAAC,MAAM,EAAE,CAAC;YAElB,uCAAuC;YACvC,MAAM,UAAU,GAAG,SAAS,CAAC,aAAa,CAAc,8BAA8B,CAAC,CAAC;YACxF,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK;YACpD,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC7E,MAAM,EAAC,QAAQ,EAAE,MAAM,EAAC,GAAG,qDAAqD,CAAC,WAAW,CAAC,CAAC;YAC9F,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YAE/E,QAAQ,CAAC,GAAG,CAAC;gBACX,IAAI,EAAE,gBAAgB;gBACtB,KAAK,EAAE,KAAK;aACb,CAAC,CAAC;YAEH,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YAC/E,MAAM,gBAAgB,GAAG,QAAQ,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;YAC1D,MAAM,CAAC,SAAS,CAAC,gBAAgB,EAAE,CAAC;oBACjB,IAAI,EAAE,gBAAgB;oBACtB,KAAK,EAAE,KAAK;iBACb,CAAC,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK;YAC1D,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC7E,MAAM,EAAC,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAC,GAAG,qDAAqD,CAAC,WAAW,CAAC,CAAC;YACzG,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAEnB,MAAM,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;YAC/E,QAAQ,CAAC,GAAG,CAAC;gBACX,IAAI,EAAE,gBAAgB;gBACtB,KAAK,EAAE,KAAK;aACb,CAAC,CAAC;YACH,QAAQ,CAAC,MAAM,EAAE,CAAC;YAElB,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;YACvC,MAAM,YAAY,GAAG,QAAQ,CAAC,oBAAoB,CAAC,gBAAgB,CAAC,CAAC;YACrE,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC;YACpC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gDAAgD,EAAE,KAAK;YACxD,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC7E,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAC,GAAG,qDAAqD,CAAC,WAAW,CAAC,CAAC;YACjG,MAAM,MAAM,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;YACzC,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAEnB,iFAAiF;YACjF,QAAQ,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,aAAa,EAAE,EAAE,gBAAgB,CAAC;gBACnF,IAAI,EAAE,aAAa;gBACnB,KAAK,EAAE,EAAE;gBACT,KAAK,EAAE,KAAiC;aACzC,CAAC,CAAC;YAEH,QAAQ,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,UAAU,GAAG,SAAS,CAAC,aAAa,CAAc,2BAA2B,CAAC,CAAC;YACrF,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACxB,MAAM,SAAS,GAAG,UAAU,EAAE,aAAa,CAAC,8BAA8B,CAAC,CAAC;YAC5E,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;YAEnC,MAAM,eAAe,GAAG,SAAS,CAAC,UAAU,CAAC,aAAa,CAAc,sBAAsB,CAAC,CAAC;YAChG,MAAM,QAAQ,GAAG,eAAe,EAAE,aAAa,CAAc,YAAY,CAAoB,CAAC;YAE9F,MAAM,UAAU,GAAG,QAAQ,CAAC,aAAa,CAAc,cAAc,CAAC,CAAC;YACvE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACxB,+FAA+F;YAC/F,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iEAAiE,EAAE,KAAK;YACzE,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;YAC7E,MAAM,EAAC,QAAQ,EAAE,SAAS,EAAC,GAAG,qDAAqD,CAAC,WAAW,CAAC,CAAC;YACjG,MAAM,MAAM,GAAG,YAAY,CAAC,WAAW,CAAC,CAAC;YACzC,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAEnB,iFAAiF;YACjF,QAAQ,CAAC,oBAAoB,CAAC,oBAAoB,CAAC,aAAa,EAAE,EAAE,gBAAgB,CAAC;gBACnF,IAAI,EAAE,aAAa;gBACnB,KAAK,EAAE,EAAE;gBACT,KAAK,EAAE,KAAiC;aACzC,CAAC,CAAC;YAEH,QAAQ,CAAC,MAAM,EAAE,CAAC;YAClB,MAAM,UAAU,GAAG,SAAS,CAAC,aAAa,CAAc,2BAA2B,CAAC,CAAC;YACrF,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YACxB,MAAM,SAAS,GAAG,UAAU,EAAE,aAAa,CAAC,8BAA8B,CAAC,CAAC;YAC5E,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;YAEnC,MAAM,eAAe,GAAG,SAAS,CAAC,UAAU,CAAC,aAAa,CAAc,sBAAsB,CAAC,CAAC;YAChG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;YAC7B,MAAM,QAAQ,GAAG,eAAe,CAAC,aAAa,CAAc,YAAY,CAAoB,CAAC;YAE7F,MAAM,UAAU,GAAG,QAAQ,CAAC,aAAa,CAAc,cAAc,CAAC,CAAC;YACvE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;YAExB,+FAA+F;YAC/F,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;YAE5C,8FAA8F;YAC9F,gEAAgE;YAChE,UAAU,CAAC,aAAa,CAAC,IAAI,UAAU,CAAC,MAAM,EAAE,EAAC,OAAO,EAAE,IAAI,EAAC,CAAC,CAAC,CAAC;YAClE,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;YAE7C,sDAAsD;YACtD,UAAU,CAAC,aAAa,CAAC,IAAI,UAAU,CAAC,UAAU,EAAE,EAAC,OAAO,EAAE,IAAI,EAAC,CAAC,CAAC,CAAC;YACtE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,+BAA+B,EAAE,GAAG,EAAE;QAC7C,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;YACrE,MAAM,YAAY,GAAG;gBACnB,EAAE,EAAE,CAAC;gBACL,GAAG,EAAE,EAAE;aACoB,CAAC;YAC9B,MAAM,YAAY,GAAG;gBACnB,EAAE,EAAE,CAAC;gBACL,GAAG,EAAE,GAAG;aACmB,CAAC;YAE9B,MAAM,QAAQ,GAAmC;gBAC/C,KAAK,EAAE,YAAY;gBACnB,IAAI,EAAE,eAAe;gBACrB,aAAa,EAAE,MAAM;aACtB,CAAC;YACF,MAAM,QAAQ,GAAmC;gBAC/C,KAAK,EAAE,YAAY;gBACnB,IAAI,EAAE,eAAe;gBACrB,aAAa,EAAE,MAAM;aACtB,CAAC;YACF,MAAM,WAAW,GAAG,QAAQ,CAAC,QAAQ,CAAC,6BAA6B,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;YAC1F,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YACvC,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QAC3C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as Trace from '../../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {\n makeInstantEvent,\n MockFlameChartDelegate,\n setupIgnoreListManagerEnvironment,\n} from '../../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as RenderCoordinator from '../../../ui/components/render_coordinator/render_coordinator.js';\nimport * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as Timeline from '../timeline.js';\n\nimport * as Components from './components/components.js';\nimport * as Overlays from './overlays.js';\n\nconst coordinator = RenderCoordinator.RenderCoordinator.RenderCoordinator.instance();\n\nconst FAKE_OVERLAY_ENTRY_QUERIES: Overlays.Overlays.OverlayEntryQueries = {\n isEntryCollapsedByUser() {\n return false;\n },\n firstVisibleParentForEntry() {\n return null;\n },\n};\n\n/**\n * The Overlays expects to be provided with both the main and network charts\n * and data providers. This function creates all of those and optionally sets\n * the trace data for the providers if it is provided.\n */\nfunction createCharts(parsedTrace?: Trace.Handlers.Types.ParsedTrace): Overlays.Overlays.TimelineCharts {\n const mainProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();\n const networkProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider();\n\n const delegate = new MockFlameChartDelegate();\n const mainChart = new PerfUI.FlameChart.FlameChart(mainProvider, delegate);\n const networkChart = new PerfUI.FlameChart.FlameChart(networkProvider, delegate);\n\n if (parsedTrace) {\n mainProvider.setModel(parsedTrace);\n networkProvider.setModel(parsedTrace);\n\n // Force the charts to render. Normally the TimelineFlameChartView would do\n // this, but we aren't creating one for these tests.\n mainChart.update();\n networkChart.update();\n }\n\n return {\n mainProvider,\n mainChart,\n networkProvider,\n networkChart,\n };\n}\n\ndescribeWithEnvironment('Overlays', () => {\n beforeEach(() => {\n setupIgnoreListManagerEnvironment();\n });\n\n it('can calculate the x position of an event based on the dimensions and its timestamp', async () => {\n const flameChartsContainer = document.createElement('div');\n const mainFlameChartsContainer = flameChartsContainer.createChild('div');\n const networkFlameChartsContainer = flameChartsContainer.createChild('div');\n const container = flameChartsContainer.createChild('div');\n\n const overlays = new Overlays.Overlays.Overlays({\n container,\n flameChartsContainers: {\n main: mainFlameChartsContainer,\n network: networkFlameChartsContainer,\n },\n charts: createCharts(),\n entryQueries: FAKE_OVERLAY_ENTRY_QUERIES,\n });\n\n // Set up the dimensions so it is 100px wide\n overlays.updateChartDimensions('main', {\n widthPixels: 100,\n heightPixels: 50,\n scrollOffsetPixels: 0,\n allGroupsCollapsed: false,\n });\n overlays.updateChartDimensions('network', {\n widthPixels: 100,\n heightPixels: 50,\n scrollOffsetPixels: 0,\n allGroupsCollapsed: false,\n });\n\n const windowMin = Trace.Types.Timing.MicroSeconds(0);\n const windowMax = Trace.Types.Timing.MicroSeconds(100);\n // Set the visible window to be 0-100 microseconds\n overlays.updateVisibleWindow(Trace.Helpers.Timing.traceWindowFromMicroSeconds(windowMin, windowMax));\n\n // Now set an event to be at 50 microseconds.\n const event = makeInstantEvent('test-event', 50);\n\n const xPosition = overlays.xPixelForEventStartOnChart(event);\n assert.strictEqual(xPosition, 50);\n });\n\n it('can calculate the y position of a main chart event', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const charts = createCharts(parsedTrace);\n\n const flameChartsContainer = document.createElement('div');\n const mainFlameChartsContainer = flameChartsContainer.createChild('div');\n const networkFlameChartsContainer = flameChartsContainer.createChild('div');\n const container = flameChartsContainer.createChild('div');\n\n const overlays = new Overlays.Overlays.Overlays({\n container,\n flameChartsContainers: {\n main: mainFlameChartsContainer,\n network: networkFlameChartsContainer,\n },\n charts,\n entryQueries: FAKE_OVERLAY_ENTRY_QUERIES,\n });\n\n overlays.updateChartDimensions('main', {\n widthPixels: 1000,\n heightPixels: 500,\n scrollOffsetPixels: 0,\n allGroupsCollapsed: false,\n });\n overlays.updateChartDimensions('network', {\n widthPixels: 1000,\n heightPixels: 200,\n scrollOffsetPixels: 0,\n allGroupsCollapsed: false,\n });\n\n // Set the visible window to be the entire trace.\n overlays.updateVisibleWindow(parsedTrace.Meta.traceBounds);\n\n // Find an event on the main chart that is not a frame (you cannot add overlays to frames)\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame);\n assert.isOk(event);\n const yPixel = overlays.yPixelForEventOnChart(event);\n // The Y offset for the main chart is 233px, but we add 208px on (200px for the\n // network chart, and 8px for the re-size handle) giving us the expected\n // 441px.\n assert.strictEqual(yPixel, 441);\n });\n\n it('can adjust the y position of a main chart event when the network track is collapsed', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const charts = createCharts(parsedTrace);\n\n const flameChartsContainer = document.createElement('div');\n const mainFlameChartsContainer = flameChartsContainer.createChild('div');\n const networkFlameChartsContainer = flameChartsContainer.createChild('div');\n const container = flameChartsContainer.createChild('div');\n\n const overlays = new Overlays.Overlays.Overlays({\n container,\n flameChartsContainers: {\n main: mainFlameChartsContainer,\n network: networkFlameChartsContainer,\n },\n charts,\n entryQueries: FAKE_OVERLAY_ENTRY_QUERIES,\n });\n\n overlays.updateChartDimensions('main', {\n widthPixels: 1000,\n heightPixels: 500,\n scrollOffsetPixels: 0,\n allGroupsCollapsed: false,\n });\n overlays.updateChartDimensions('network', {\n widthPixels: 1000,\n heightPixels: 34,\n scrollOffsetPixels: 0,\n // Make the network track collapsed\n allGroupsCollapsed: true,\n });\n\n // Set the visible window to be the entire trace.\n overlays.updateVisibleWindow(parsedTrace.Meta.traceBounds);\n\n // Find an event on the main chart that is not a frame (you cannot add overlays to frames)\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame);\n assert.isOk(event);\n const yPixel = overlays.yPixelForEventOnChart(event);\n // The Y offset for the main chart is 233px, but we add 34px on (the height\n // of the collapsed network chart, with no resizer bar as it is hidden when\n // the network track is collapsed). This gives us 233+34 = 267.\n assert.strictEqual(yPixel, 267);\n });\n\n it('can calculate the y position of a network chart event', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const charts = createCharts(parsedTrace);\n\n const flameChartsContainer = document.createElement('div');\n const mainFlameChartsContainer = flameChartsContainer.createChild('div');\n const networkFlameChartsContainer = flameChartsContainer.createChild('div');\n const container = flameChartsContainer.createChild('div');\n\n const overlays = new Overlays.Overlays.Overlays({\n container,\n flameChartsContainers: {\n main: mainFlameChartsContainer,\n network: networkFlameChartsContainer,\n },\n charts,\n entryQueries: FAKE_OVERLAY_ENTRY_QUERIES,\n });\n\n overlays.updateChartDimensions('main', {\n widthPixels: 1000,\n heightPixels: 500,\n scrollOffsetPixels: 0,\n allGroupsCollapsed: false,\n });\n overlays.updateChartDimensions('network', {\n widthPixels: 1000,\n heightPixels: 200,\n scrollOffsetPixels: 0,\n allGroupsCollapsed: false,\n });\n\n // Set the visible window to be the entire trace.\n overlays.updateVisibleWindow(parsedTrace.Meta.traceBounds);\n\n // Fake the level being visible: because we don't fully render the chart we\n // need to fake this for this test.\n sinon.stub(charts.networkChart, 'levelIsVisible').callsFake(() => true);\n\n // Find an event on the network chart\n const event = charts.networkProvider.eventByIndex?.(0);\n assert.isOk(event);\n const yPixel = overlays.yPixelForEventOnChart(event);\n // This event is in the first level, but the first level has some offset\n // above it to allow for the header row and the row with the timestamps on\n // it, hence why this value is not 0px.\n assert.strictEqual(yPixel, 34);\n });\n\n describe('rendering overlays', () => {\n function setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace: Trace.Handlers.Types.ParsedTrace): {\n container: HTMLElement,\n overlays: Overlays.Overlays.Overlays,\n charts: Overlays.Overlays.TimelineCharts,\n } {\n const charts = createCharts(parsedTrace);\n\n const flameChartsContainer = document.createElement('div');\n const mainFlameChartsContainer = flameChartsContainer.createChild('div');\n const networkFlameChartsContainer = flameChartsContainer.createChild('div');\n const container = flameChartsContainer.createChild('div');\n\n const overlays = new Overlays.Overlays.Overlays({\n container,\n flameChartsContainers: {\n main: mainFlameChartsContainer,\n network: networkFlameChartsContainer,\n },\n charts,\n entryQueries: FAKE_OVERLAY_ENTRY_QUERIES,\n });\n const currManager = Timeline.ModificationsManager.ModificationsManager.activeManager();\n // The Annotations Overlays are added through the ModificationsManager listener\n currManager?.addEventListener(Timeline.ModificationsManager.AnnotationModifiedEvent.eventName, event => {\n const {overlay, action} = (event as Timeline.ModificationsManager.AnnotationModifiedEvent);\n if (action === 'Add') {\n overlays.add(overlay);\n }\n overlays.update();\n });\n\n // When an annotation overlay is remomved, this event is dispatched to the Modifications Manager.\n overlays.addEventListener(Overlays.Overlays.AnnotationOverlayActionEvent.eventName, event => {\n const {overlay, action} = (event as Overlays.Overlays.AnnotationOverlayActionEvent);\n if (action === 'Remove') {\n overlays.remove(overlay);\n }\n overlays.update();\n });\n\n overlays.updateChartDimensions('main', {\n widthPixels: 1000,\n heightPixels: 500,\n scrollOffsetPixels: 0,\n allGroupsCollapsed: false,\n });\n overlays.updateChartDimensions('network', {\n widthPixels: 1000,\n heightPixels: 200,\n scrollOffsetPixels: 0,\n allGroupsCollapsed: false,\n });\n\n // Set the visible window to be the entire trace.\n overlays.updateVisibleWindow(parsedTrace.Meta.traceBounds);\n return {overlays, container, charts};\n }\n\n it('can render an entry selected overlay', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame);\n\n overlays.add({\n type: 'ENTRY_SELECTED',\n entry: event,\n });\n overlays.update();\n\n // Ensure that the overlay was created.\n const overlayDOM = container.querySelector('.overlay-type-ENTRY_SELECTED');\n assert.isOk(overlayDOM);\n });\n\n it('does not render an ENTRY_OUTLINE if the entry is also the ENTRY_SELECTED entry', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n overlays.add({\n type: 'ENTRY_OUTLINE',\n entry: event,\n outlineReason: 'ERROR',\n });\n overlays.update();\n\n const outlineVisible =\n container.querySelector('.overlay-type-ENTRY_OUTLINE')?.style.display === 'block';\n assert.isTrue(outlineVisible, 'The ENTRY_OUTLINE should be visible');\n\n // Now make a selected entry too\n overlays.add({\n type: 'ENTRY_SELECTED',\n entry: event,\n });\n overlays.update();\n const outlineNowHidden =\n container.querySelector('.overlay-type-ENTRY_OUTLINE')?.style.display === 'none';\n assert.isTrue(outlineNowHidden, 'The ENTRY_OUTLINE should be hidden');\n });\n\n it('only ever renders a single selected overlay', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace);\n const event1 = charts.mainProvider.eventByIndex?.(50);\n const event2 = charts.mainProvider.eventByIndex?.(51);\n assert.isOk(event1);\n assert.isOk(event2);\n\n overlays.add({\n type: 'ENTRY_SELECTED',\n entry: event1,\n });\n overlays.update();\n overlays.add({\n type: 'ENTRY_SELECTED',\n entry: event2,\n });\n overlays.update();\n\n // There should only be one of these\n const entrySelectedOverlays = container.querySelectorAll('.overlay-type-ENTRY_SELECTED');\n assert.lengthOf(entrySelectedOverlays, 1);\n });\n\n it('can render entry label overlay', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame);\n\n overlays.add({\n type: 'ENTRY_LABEL',\n entry: event,\n label: 'entry label',\n });\n overlays.update();\n\n // Ensure that the overlay was created.\n const overlayDOM = container.querySelector('.overlay-type-ENTRY_LABEL');\n assert.isOk(overlayDOM);\n });\n\n it('only renders one CURSOR_TIMESTAMP_MARKER as it is a singleton', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container} = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace);\n overlays.add({\n type: 'CURSOR_TIMESTAMP_MARKER',\n timestamp: parsedTrace.Meta.traceBounds.min,\n });\n overlays.add({\n type: 'CURSOR_TIMESTAMP_MARKER',\n timestamp: parsedTrace.Meta.traceBounds.max,\n });\n overlays.update();\n assert.lengthOf(container.children, 1);\n });\n\n it('can render the label for entry label overlay', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame);\n\n overlays.add({\n type: 'ENTRY_LABEL',\n entry: event,\n label: 'entry label',\n });\n overlays.update();\n\n const overlayDOM = container.querySelector('.overlay-type-ENTRY_LABEL');\n assert.isOk(overlayDOM);\n const component = overlayDOM?.querySelector('devtools-entry-label-overlay');\n assert.isOk(component?.shadowRoot);\n\n const elementsWrapper = component.shadowRoot.querySelector('.label-parts-wrapper');\n assert.isOk(elementsWrapper);\n\n const labelBox = elementsWrapper.querySelector('.label-box');\n assert.isOk(labelBox);\n\n const inputField = labelBox.querySelector('.input-field');\n assert.isOk(inputField);\n\n assert.strictEqual(inputField?.innerText, 'entry label');\n });\n\n it('Inputting `Enter`into label overlay makes it non-editable', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame);\n\n // Create an entry label overlay\n overlays.add({\n type: 'ENTRY_LABEL',\n entry: event,\n label: 'label',\n });\n overlays.update();\n\n // Ensure that the overlay was created.\n const overlayDOM = container.querySelector('.overlay-type-ENTRY_LABEL');\n assert.isOk(overlayDOM);\n\n const component = overlayDOM?.querySelector('devtools-entry-label-overlay');\n assert.isOk(component?.shadowRoot);\n component.connectedCallback();\n const elementsWrapper = component.shadowRoot.querySelector('.label-parts-wrapper');\n assert.isOk(elementsWrapper);\n\n const label = elementsWrapper.querySelector('.label-box');\n assert.isOk(label);\n const inputField = label.querySelector('.input-field');\n assert.isOk(inputField);\n\n // Double click on the label box to make it editable and focus on it\n inputField.dispatchEvent(new FocusEvent('dblclick', {bubbles: true}));\n\n // Ensure the label content is editable\n assert.isTrue(inputField.isContentEditable);\n\n // Press `Enter` to make the lable not editable\n inputField.dispatchEvent(new KeyboardEvent('keydown', {key: 'Enter', cancelable: true, bubbles: true}));\n\n // Ensure the label content is not editable\n assert.isFalse(inputField.isContentEditable);\n });\n\n it('Inputting `Enter` into time range label field when the label is empty removes the overlay', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame);\n\n // Create a time range overlay with an empty label\n overlays.add({\n type: 'TIME_RANGE',\n label: '',\n showDuration: true,\n // Make this overlay the entire span of the trace\n bounds: parsedTrace.Meta.traceBounds,\n });\n overlays.update();\n\n // Ensure that the overlay was created.\n const overlayDOM = container.querySelector('.overlay-type-TIME_RANGE');\n assert.isOk(overlayDOM);\n\n const component = overlayDOM?.querySelector('devtools-time-range-overlay');\n assert.isOk(component?.shadowRoot);\n component.connectedCallback();\n const rangeContainer = component.shadowRoot.querySelector('.range-container');\n assert.isOk(rangeContainer);\n\n const labelBox = rangeContainer.querySelector('.label-text');\n assert.isOk(labelBox);\n\n // Double click on the label box to make it editable and focus on it\n labelBox.dispatchEvent(new FocusEvent('dblclick', {bubbles: true}));\n\n // Press `Enter` on the label field\n labelBox.dispatchEvent(new KeyboardEvent('keydown', {key: 'Enter', cancelable: true, bubbles: true}));\n\n // Ensure that the entry overlay has been removed because it was saved empty\n assert.strictEqual(overlays.overlaysOfType('TIME_RANGE').length, 0);\n });\n\n it('Inputting `Enter` into time range label field when the label is not empty does not remove the overlay',\n async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame);\n\n // Create a time range overlay with a label\n overlays.add({\n type: 'TIME_RANGE',\n label: 'label',\n showDuration: true,\n // Make this overlay the entire span of the trace\n bounds: parsedTrace.Meta.traceBounds,\n });\n overlays.update();\n\n // Ensure that the overlay was created.\n const overlayDOM = container.querySelector('.overlay-type-TIME_RANGE');\n assert.isOk(overlayDOM);\n\n const component = overlayDOM?.querySelector('devtools-time-range-overlay');\n assert.isOk(component?.shadowRoot);\n component.connectedCallback();\n const rangeContainer = component.shadowRoot.querySelector('.range-container');\n assert.isOk(rangeContainer);\n\n const labelBox = rangeContainer.querySelector('.label-text');\n assert.isOk(labelBox);\n\n // Double click on the label box to make it editable and focus on it\n labelBox.dispatchEvent(new FocusEvent('dblclick', {bubbles: true}));\n\n // Press `Enter` on the label field\n labelBox.dispatchEvent(new KeyboardEvent('keydown', {key: 'Enter', cancelable: true, bubbles: true}));\n\n // Ensure that the entry overlay has not been because it was has a non-empty label\n assert.strictEqual(overlays.overlaysOfType('TIME_RANGE').length, 1);\n });\n\n it('Can create multiple Time Range Overlays for Time Range annotations', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame);\n\n Timeline.ModificationsManager.ModificationsManager.activeManager()?.createAnnotation({\n type: 'TIME_RANGE',\n label: 'label',\n bounds: parsedTrace.Meta.traceBounds,\n });\n\n Timeline.ModificationsManager.ModificationsManager.activeManager()?.createAnnotation({\n type: 'TIME_RANGE',\n label: 'label2',\n bounds: parsedTrace.Meta.traceBounds,\n });\n overlays.update();\n\n assert.strictEqual(overlays.overlaysOfType('TIME_RANGE').length, 2);\n });\n\n it('Removes empty label if it is empty when navigated away from (removed focused from)', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n\n // Create an entry label overlay\n Timeline.ModificationsManager.ModificationsManager.activeManager()?.createAnnotation({\n type: 'ENTRY_LABEL',\n entry: event as Trace.Types.Events.Event,\n label: '',\n });\n overlays.update();\n\n // Ensure that the overlay was created.\n const overlayDOM = container.querySelector('.overlay-type-ENTRY_LABEL');\n assert.isOk(overlayDOM);\n const component = overlayDOM?.querySelector('devtools-entry-label-overlay');\n assert.isOk(component?.shadowRoot);\n\n component.connectedCallback();\n const elementsWrapper = component.shadowRoot.querySelector('.label-parts-wrapper');\n assert.isOk(elementsWrapper);\n\n const label = elementsWrapper.querySelector('.label-box');\n assert.isOk(label);\n\n const inputField = elementsWrapper.querySelector('.input-field');\n assert.isOk(inputField);\n\n // Double click on the label box to make it editable and focus on it\n inputField.dispatchEvent(new FocusEvent('dblclick', {bubbles: true}));\n\n // Ensure that the entry has 1 overlay\n assert.strictEqual(overlays.overlaysForEntry(event).length, 1);\n\n // Change the content to not editable by changing the element blur like when clicking outside of it.\n // The label is empty since no initial value was passed into it and no characters were entered.\n inputField.dispatchEvent(new FocusEvent('blur', {bubbles: true}));\n\n // Ensure that the entry overlay has been removed because it was saved empty\n assert.strictEqual(overlays.overlaysForEntry(event).length, 0);\n });\n\n it('Update label overlay when the label changes', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n\n // Create an entry label overlay\n Timeline.ModificationsManager.ModificationsManager.activeManager()?.createAnnotation({\n type: 'ENTRY_LABEL',\n entry: event as Trace.Types.Events.Event,\n label: '',\n });\n overlays.update();\n\n // Ensure that the overlay was created.\n const overlayDOM = container.querySelector('.overlay-type-ENTRY_LABEL');\n assert.isOk(overlayDOM);\n const component = overlayDOM?.querySelector('devtools-entry-label-overlay');\n assert.isOk(component?.shadowRoot);\n\n component.connectedCallback();\n component.dispatchEvent(new Components.EntryLabelOverlay.EntryLabelChangeEvent('new label'));\n\n const updatedOverlay = overlays.overlaysForEntry(event)[0] as Overlays.Overlays.EntryLabel;\n assert.isOk(updatedOverlay);\n // Make sure the label was updated in the Overlay Object\n assert.strictEqual(updatedOverlay.label, 'new label');\n });\n\n it('creates an overlay for a time range when an time range annotation is created', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container} = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace);\n\n // Since TIME_RANGE is AnnotationOverlay, create it through ModificationsManager\n Timeline.ModificationsManager.ModificationsManager.activeManager()?.createAnnotation({\n type: 'TIME_RANGE',\n label: '',\n // Make this overlay the entire span of the trace\n bounds: parsedTrace.Meta.traceBounds,\n });\n overlays.update();\n const overlayDOM = container.querySelector('.overlay-type-TIME_RANGE');\n assert.isOk(overlayDOM);\n });\n\n it('can render an overlay for a time range', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container} = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace);\n overlays.add({\n type: 'TIME_RANGE',\n label: '',\n showDuration: true,\n // Make this overlay the entire span of the trace\n bounds: parsedTrace.Meta.traceBounds,\n });\n overlays.update();\n const overlayDOM = container.querySelector('.overlay-type-TIME_RANGE');\n assert.isOk(overlayDOM);\n });\n\n it('can update a time range overlay with new bounds', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container} = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace);\n const rangeOverlay = overlays.add({\n type: 'TIME_RANGE',\n label: '',\n showDuration: true,\n // Make this overlay the entire span of the trace\n bounds: parsedTrace.Meta.traceBounds,\n });\n overlays.update();\n const overlayDOM = container.querySelector('.overlay-type-TIME_RANGE');\n assert.isOk(overlayDOM);\n const firstWidth = window.parseInt(overlayDOM.style.width);\n\n // change the bounds so the new min is +1second of time.\n const newBounds = Trace.Helpers.Timing.traceWindowFromMicroSeconds(\n Trace.Types.Timing.MicroSeconds(rangeOverlay.bounds.min + (1_000 * 1_000)),\n rangeOverlay.bounds.max,\n );\n overlays.updateExisting(rangeOverlay, {bounds: newBounds});\n overlays.update();\n const secondWidth = window.parseInt(overlayDOM.style.width);\n // The new time range is smaller so the DOM element should have less width\n assert.isTrue(secondWidth < firstWidth);\n });\n\n it('renders the overlay for a selected layout shift entry correctly', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'cls-single-frame.json.gz');\n const {overlays, container} = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace);\n const layoutShiftEvent = parsedTrace.LayoutShifts.clusters.at(0)?.events.at(0);\n if (!layoutShiftEvent) {\n throw new Error('layoutShiftEvent was unexpectedly undefined');\n }\n overlays.add({\n type: 'ENTRY_SELECTED',\n entry: layoutShiftEvent,\n });\n const boundsRange = Trace.Types.Timing.MicroSeconds(20_000);\n const boundsMax = Trace.Types.Timing.MicroSeconds(layoutShiftEvent.ts + boundsRange);\n overlays.updateVisibleWindow({min: layoutShiftEvent.ts, max: boundsMax, range: boundsRange});\n overlays.update();\n const overlayDOM = container.querySelector('.overlay-type-ENTRY_SELECTED');\n assert.isOk(overlayDOM);\n assert.strictEqual(window.parseInt(overlayDOM.style.width), 250);\n });\n\n it('renders the duration and label for a time range overlay', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container} = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace);\n overlays.add({\n type: 'TIME_RANGE',\n label: '',\n showDuration: true,\n // Make this overlay the entire span of the trace\n bounds: parsedTrace.Meta.traceBounds,\n });\n overlays.update();\n await coordinator.done();\n const overlayDOM = container.querySelector('.overlay-type-TIME_RANGE');\n const component = overlayDOM?.querySelector('devtools-time-range-overlay');\n assert.isOk(component?.shadowRoot);\n const rangeContainer = component.shadowRoot.querySelector('.range-container');\n assert.isOk(rangeContainer);\n const duration = rangeContainer.querySelector('.duration');\n assert.isOk(duration);\n assert.strictEqual(duration?.innerText, '1.26\\xA0s');\n });\n\n it('can remove an overlay', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame);\n\n const selectedOverlay = overlays.add({\n type: 'ENTRY_SELECTED',\n entry: event,\n });\n overlays.update();\n assert.lengthOf(container.children, 1);\n\n overlays.remove(selectedOverlay);\n overlays.update();\n assert.lengthOf(container.children, 0);\n });\n\n it('can render an entry selected overlay for a frame', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev-with-commit.json.gz');\n const {overlays, container, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace);\n const timelineFrame = charts.mainProvider.eventByIndex?.(5);\n assert.isOk(timelineFrame);\n assert.instanceOf(timelineFrame, Trace.Handlers.ModelHandlers.Frames.TimelineFrame);\n\n overlays.add({\n type: 'ENTRY_SELECTED',\n entry: timelineFrame,\n });\n overlays.update();\n\n // Ensure that the overlay was created.\n const overlayDOM = container.querySelector('.overlay-type-ENTRY_SELECTED');\n assert.isOk(overlayDOM);\n });\n\n it('can return a list of overlays for an entry', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame);\n\n overlays.add({\n type: 'ENTRY_SELECTED',\n entry: event,\n });\n\n assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame);\n const existingOverlays = overlays.overlaysForEntry(event);\n assert.deepEqual(existingOverlays, [{\n type: 'ENTRY_SELECTED',\n entry: event,\n }]);\n });\n\n it('can delete overlays and remove them from the DOM', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {container, overlays, charts} = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n\n assert.notInstanceOf(event, Trace.Handlers.ModelHandlers.Frames.TimelineFrame);\n overlays.add({\n type: 'ENTRY_SELECTED',\n entry: event,\n });\n overlays.update();\n\n assert.lengthOf(container.children, 1);\n const removedCount = overlays.removeOverlaysOfType('ENTRY_SELECTED');\n assert.strictEqual(removedCount, 1);\n assert.lengthOf(container.children, 0);\n });\n\n it('the label entry field is editable when created', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container} = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace);\n const charts = createCharts(parsedTrace);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n\n // Since ENTRY_LABEL is AnnotationOverlay, create it through ModificationsManager\n Timeline.ModificationsManager.ModificationsManager.activeManager()?.createAnnotation({\n type: 'ENTRY_LABEL',\n label: '',\n entry: event as Trace.Types.Events.Event,\n });\n\n overlays.update();\n const overlayDOM = container.querySelector('.overlay-type-ENTRY_LABEL');\n assert.isOk(overlayDOM);\n const component = overlayDOM?.querySelector('devtools-entry-label-overlay');\n assert.isOk(component?.shadowRoot);\n\n const elementsWrapper = component.shadowRoot.querySelector('.label-parts-wrapper');\n const labelBox = elementsWrapper?.querySelector('.label-box') as HTMLSpanElement;\n\n const inputField = labelBox.querySelector('.input-field');\n assert.isOk(inputField);\n // The label input box should be editable after it is created and before anything else happened\n assert.isTrue(inputField.isContentEditable);\n });\n\n it('the label entry field is in focus after being double clicked on', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const {overlays, container} = setupChartWithDimensionsAndAnnotationOverlayListeners(parsedTrace);\n const charts = createCharts(parsedTrace);\n const event = charts.mainProvider.eventByIndex?.(50);\n assert.isOk(event);\n\n // Since ENTRY_LABEL is AnnotationOverlay, create it through ModificationsManager\n Timeline.ModificationsManager.ModificationsManager.activeManager()?.createAnnotation({\n type: 'ENTRY_LABEL',\n label: '',\n entry: event as Trace.Types.Events.Event,\n });\n\n overlays.update();\n const overlayDOM = container.querySelector('.overlay-type-ENTRY_LABEL');\n assert.isOk(overlayDOM);\n const component = overlayDOM?.querySelector('devtools-entry-label-overlay');\n assert.isOk(component?.shadowRoot);\n\n const elementsWrapper = component.shadowRoot.querySelector('.label-parts-wrapper');\n assert.isOk(elementsWrapper);\n const labelBox = elementsWrapper.querySelector('.label-box') as HTMLSpanElement;\n\n const inputField = labelBox.querySelector('.input-field');\n assert.isOk(inputField);\n\n // The label input box should be editable after it is created and before anything else happened\n assert.isTrue(inputField.isContentEditable);\n\n // Make the content to editable by changing the element blur like when clicking outside of it.\n // When that happens, the content should be set to not editable.\n inputField.dispatchEvent(new FocusEvent('blur', {bubbles: true}));\n assert.isFalse(inputField.isContentEditable);\n\n // Double click on the label to make it editable again\n inputField.dispatchEvent(new FocusEvent('dblclick', {bubbles: true}));\n assert.isTrue(inputField.isContentEditable);\n });\n });\n\n describe('traceWindowContainingOverlays', () => {\n it('calculates the smallest window that fits the overlay inside', () => {\n const FAKE_EVENT_1 = {\n ts: 0,\n dur: 10,\n } as Trace.Types.Events.Event;\n const FAKE_EVENT_2 = {\n ts: 5,\n dur: 100,\n } as Trace.Types.Events.Event;\n\n const overlay1: Overlays.Overlays.EntryOutline = {\n entry: FAKE_EVENT_1,\n type: 'ENTRY_OUTLINE',\n outlineReason: 'INFO',\n };\n const overlay2: Overlays.Overlays.EntryOutline = {\n entry: FAKE_EVENT_2,\n type: 'ENTRY_OUTLINE',\n outlineReason: 'INFO',\n };\n const traceWindow = Overlays.Overlays.traceWindowContainingOverlays([overlay1, overlay2]);\n assert.strictEqual(traceWindow.min, 0);\n assert.strictEqual(traceWindow.max, 105);\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/overlays/components/EntriesLinkOverlay.d.ts b/public/panels/timeline/overlays/components/EntriesLinkOverlay.d.ts index afa015e46..a5896cda6 100644 --- a/public/panels/timeline/overlays/components/EntriesLinkOverlay.d.ts +++ b/public/panels/timeline/overlays/components/EntriesLinkOverlay.d.ts @@ -7,7 +7,13 @@ export declare class EntriesLinkOverlay extends HTMLElement { width: number; height: number; }); + set canvasRect(rect: DOMRect | null); connectedCallback(): void; + /** + * If one entry that is linked is in a collapsed track, we show the outlines + * but hide only the arrow. + */ + set hideArrow(shouldHide: boolean); set fromEntryCoordinateAndDimentions(fromEntryParams: { x: number; y: number; @@ -27,8 +33,30 @@ export declare class EntriesLinkOverlay extends HTMLElement { set fromEntryIsSource(x: boolean); set toEntryIsSource(x: boolean); } +export declare class CreateEntriesLinkRemoveEvent extends Event { + static readonly eventName = "createentrieslinkremoveevent"; + constructor(); +} +export declare class CreateEntriesLinkOverlay extends HTMLElement { + #private; + static readonly litTagName: import("../../../../ui/lit-html/static.js").Static; + constructor(initialFromEntryParams: { + entryStartX: number; + entryStartY: number; + entryWidth: number; + entryHeight: number; + }); + connectedCallback(): void; + set fromEntryData(fromEntryParams: { + entryStartX: number; + entryStartY: number; + entryWidth: number; + entryHeight: number; + }); +} declare global { interface HTMLElementTagNameMap { 'devtools-entries-link-overlay': EntriesLinkOverlay; + 'devtools-create-entries-link-overlay': CreateEntriesLinkOverlay; } } diff --git a/public/panels/timeline/overlays/components/EntriesLinkOverlay.js b/public/panels/timeline/overlays/components/EntriesLinkOverlay.js index 3304f234a..d86422fef 100644 --- a/public/panels/timeline/overlays/components/EntriesLinkOverlay.js +++ b/public/panels/timeline/overlays/components/EntriesLinkOverlay.js @@ -1,8 +1,21 @@ // Copyright 2024 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 * as i18n from '../../../../core/i18n/i18n.js'; import * as ComponentHelpers from '../../../../ui/components/helpers/helpers.js'; +import * as IconButton from '../../../../ui/components/icon_button/icon_button.js'; +import * as ThemeSupport from '../../../../ui/legacy/theme_support/theme_support.js'; import * as LitHtml from '../../../../ui/lit-html/lit-html.js'; +const UIStrings = { + /** + *@description Accessible label used to explain to a user that they are viewing an arrow representing a link between two entries. + */ + diagram: 'Links bteween entries', +}; +const str_ = i18n.i18n.registerUIStrings('panels/timeline/overlays/components/EntriesLinkOverlay.ts', UIStrings); +const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); +// In other overlays, the border line width is set to 2px. +const BORDER_LINE_WIDTH = 2; import styles from './entriesLinkOverlay.css.js'; export class EntriesLinkOverlay extends HTMLElement { static litTagName = LitHtml.literal `devtools-entries-link-overlay`; @@ -16,14 +29,18 @@ export class EntriesLinkOverlay extends HTMLElement { #connector = null; #entryFromWrapper = null; #entryToWrapper = null; + #entryFromConnector = null; + #entryToConnector = null; #entryFromVisible = true; #entryToVisible = true; + #canvasRect = null; // These flags let us know if the entry we are drawing from/to are the // originals, or if they are the parent, which can happen if an entry is // collapsed. We care about this because if the entry is not the source, we // draw the border as dashed, not solid. #fromEntryIsSource = true; #toEntryIsSource = true; + #arrowHidden = false; constructor(initialFromEntryCoordinateAndDimentions) { super(); this.#render(); @@ -37,10 +54,32 @@ export class EntriesLinkOverlay extends HTMLElement { this.#connector = this.#connectorLineContainer?.querySelector('line') ?? null; this.#entryFromWrapper = this.#connectorLineContainer?.querySelector('.entryFromWrapper') ?? null; this.#entryToWrapper = this.#connectorLineContainer?.querySelector('.entryToWrapper') ?? null; + this.#entryFromConnector = this.#connectorLineContainer?.querySelector('.entryFromConnector') ?? null; + this.#entryToConnector = this.#connectorLineContainer?.querySelector('.entryToConnector') ?? null; + } + set canvasRect(rect) { + if (rect === null) { + return; + } + if (this.#canvasRect && this.#canvasRect.width === rect.width && this.#canvasRect.height === rect.height) { + return; + } + this.#canvasRect = rect; + void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender); } connectedCallback() { this.#shadow.adoptedStyleSheets = [styles]; } + /** + * If one entry that is linked is in a collapsed track, we show the outlines + * but hide only the arrow. + */ + set hideArrow(shouldHide) { + this.#arrowHidden = shouldHide; + if (this.#connector) { + this.#connector.style.display = shouldHide ? 'none' : 'block'; + } + } set fromEntryCoordinateAndDimentions(fromEntryParams) { this.#coordinateFrom = { x: fromEntryParams.x, y: fromEntryParams.y }; this.#fromEntryDimentions = { width: fromEntryParams.length, height: fromEntryParams.height }; @@ -51,7 +90,7 @@ export class EntriesLinkOverlay extends HTMLElement { this.#entryToVisible = entriesVisibility.toEntryVisibility; } // The arrow might be pointing either to an entry or an empty space. - // If the dimentions are not passed, it is pointing at an empty space. + // If the dimensions are not passed, it is pointing at an empty space. set toEntryCoordinateAndDimentions(toEntryParams) { this.#coordinateTo = { x: toEntryParams.x, y: toEntryParams.y }; if (toEntryParams.length && toEntryParams.height) { @@ -77,22 +116,47 @@ export class EntriesLinkOverlay extends HTMLElement { this.#render(); } #redrawConnectionArrow() { - if (!this.#connector || !this.#entryFromWrapper || !this.#entryToWrapper) { + if (!this.#connector || !this.#entryFromWrapper || !this.#entryToWrapper || !this.#entryFromConnector || + !this.#entryToConnector) { console.error('`connector` element is missing.'); return; } + // If the user is zoomed out, the connector circles can be as large as the + // event itself. So if the rectangle for this entry is too small, we + // don't draw the circles. + const minWidthToDrawConnectorCircles = 8; + // We do not draw the connectors if the entry is not visible, or if the + // entry we are connecting to isn't the actual source entry. + // We also don't draw them if an entry is completely hidden, in which case + // we aren't drawing the arrows, so it doesn't make sense to draw the + // connectors. + const drawFromEntryConnectorCircle = this.#entryFromVisible && !this.#arrowHidden && this.#fromEntryIsSource && + this.#fromEntryDimentions.width >= minWidthToDrawConnectorCircles; + const widthOfToEntry = this.#toEntryDimentions?.width ?? 0; + const drawToEntryConnectorCircle = !this.#arrowHidden && this.#entryToVisible && this.#toEntryIsSource && + widthOfToEntry >= minWidthToDrawConnectorCircles && !this.#arrowHidden; + this.#entryFromConnector.setAttribute('visibility', drawFromEntryConnectorCircle ? 'visible' : 'hidden'); + this.#entryToConnector.setAttribute('visibility', drawToEntryConnectorCircle ? 'visible' : 'hidden'); // If the entry is visible, the entry arrow starts from the end on the X axis and middle of the Y axis. // If not, draw it to the same y point without the entry height offset and the box around the entry. // This way it will be attached to the track edge. if (this.#entryFromVisible) { const halfEntryHeight = this.#fromEntryDimentions.height / 2; - this.#connector.setAttribute('x1', (this.#coordinateFrom.x + this.#fromEntryDimentions.width).toString()); - this.#connector.setAttribute('y1', (this.#coordinateFrom.y + Number(halfEntryHeight)).toString()); + const endConnectionPointX = String(this.#coordinateFrom.x + this.#fromEntryDimentions.width); + const endConnectionPointY = String(this.#coordinateFrom.y + halfEntryHeight); + this.#connector.setAttribute('x1', endConnectionPointX); + this.#connector.setAttribute('y1', endConnectionPointY); + this.#entryFromConnector.setAttribute('cx', endConnectionPointX); + this.#entryFromConnector.setAttribute('cy', endConnectionPointY); + const adjustedEntryFromWrapperX = String(this.#coordinateFrom.x + BORDER_LINE_WIDTH / 2); + const adjustedEntryFromWrapperY = String(this.#coordinateFrom.y + BORDER_LINE_WIDTH / 2); + const adjustedWidth = String(this.#fromEntryDimentions.width - BORDER_LINE_WIDTH); + const adjustedHeight = String(this.#fromEntryDimentions.height - BORDER_LINE_WIDTH); this.#entryFromWrapper.setAttribute('visibility', 'visible'); - this.#entryFromWrapper.setAttribute('x', this.#coordinateFrom.x.toString()); - this.#entryFromWrapper.setAttribute('y', this.#coordinateFrom.y.toString()); - this.#entryFromWrapper.setAttribute('width', this.#fromEntryDimentions.width.toString()); - this.#entryFromWrapper.setAttribute('height', this.#fromEntryDimentions.height.toString()); + this.#entryFromWrapper.setAttribute('x', adjustedEntryFromWrapperX); + this.#entryFromWrapper.setAttribute('y', adjustedEntryFromWrapperY); + this.#entryFromWrapper.setAttribute('width', adjustedWidth); + this.#entryFromWrapper.setAttribute('height', adjustedHeight); } else { this.#connector.setAttribute('x1', (this.#coordinateFrom.x + this.#fromEntryDimentions.width).toString()); @@ -102,16 +166,24 @@ export class EntriesLinkOverlay extends HTMLElement { // If the arrow is pointing to the entry, point it to the middle of the entry and draw a box around the entry. // If the arrow is pointing to an entry, but it is not visible, the coordinates are for the edge of the track // and we don't need the half entry height offset. - // Otherwise, thhe arrow is following the mouse so we assign it to the provided coordinates. + // Otherwise, the arrow is following the mouse so we assign it to the provided coordinates. if (this.#toEntryDimentions) { if (this.#entryToVisible) { + const adjustedEntryToWrapperX = String(this.#coordinateTo.x + BORDER_LINE_WIDTH / 2); + const adjustedEntryToWrapperY = String(this.#coordinateTo.y + BORDER_LINE_WIDTH / 2); + const adjustedWidth = String(this.#toEntryDimentions.width - BORDER_LINE_WIDTH); + const adjustedHeight = String(this.#toEntryDimentions.height - BORDER_LINE_WIDTH); this.#entryToWrapper.setAttribute('visibility', 'visible'); - this.#entryToWrapper.setAttribute('x', this.#coordinateTo.x.toString()); - this.#entryToWrapper.setAttribute('y', this.#coordinateTo.y.toString()); - this.#entryToWrapper.setAttribute('width', this.#toEntryDimentions.width.toString()); - this.#entryToWrapper.setAttribute('height', this.#toEntryDimentions.height.toString()); - this.#connector.setAttribute('x2', this.#coordinateTo.x.toString()); - this.#connector.setAttribute('y2', (this.#coordinateTo.y + this.#toEntryDimentions.height / 2).toString()); + this.#entryToWrapper.setAttribute('x', adjustedEntryToWrapperX); + this.#entryToWrapper.setAttribute('y', adjustedEntryToWrapperY); + this.#entryToWrapper.setAttribute('width', adjustedWidth); + this.#entryToWrapper.setAttribute('height', adjustedHeight); + const connectionPointX = String(this.#coordinateTo.x); + const connectionPointY = String(this.#coordinateTo.y + this.#toEntryDimentions.height / 2); + this.#connector.setAttribute('x2', connectionPointX); + this.#connector.setAttribute('y2', connectionPointY); + this.#entryToConnector.setAttribute('cx', connectionPointX); + this.#entryToConnector.setAttribute('cy', connectionPointY); } else { this.#entryToWrapper.setAttribute('visibility', 'hidden'); @@ -124,10 +196,47 @@ export class EntriesLinkOverlay extends HTMLElement { this.#connector.setAttribute('x2', this.#coordinateTo.x.toString()); this.#connector.setAttribute('y2', this.#coordinateTo.y.toString()); } - this.#connector.setAttribute('stroke', 'black'); this.#connector.setAttribute('stroke-width', '2'); + if (this.#toEntryDimentions && this.#entryFromVisible && !this.#entryToVisible) { + this.#connector.setAttribute('stroke', 'url(#fromVisibleLineGradient)'); + } + else if (this.#toEntryDimentions && this.#entryToVisible && !this.#entryFromVisible) { + this.#connector.setAttribute('stroke', 'url(#toVisibleLineGradient)'); + } + else { + const arrowColor = ThemeSupport.ThemeSupport.instance().getComputedValue('--color-text-primary'); + this.#connector.setAttribute('stroke', arrowColor); + } void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender); } + /* + * When only one entry from the connection is visible, the connection + * line becomes a gradient from the visible entry to the edge of + * the screen towards the entry that is not visible. + * + * To achieve this, we need to calculate what percentage of the + * visible screen the connection is currently occupying and apply + * that gradient to the visible connection part. + */ + #partlyVisibleConnectionLinePercentage() { + if (!this.#canvasRect) { + return 100; + } + const lineLength = this.#coordinateTo.x - (this.#coordinateFrom.x + this.#fromEntryDimentions.width); + let visibleLineLength = 0; + // If the visible entry is the 'From' entry, find the length of the visible arrow by + // substracting the point where the arrow starts from the whole canvas length. + // If the 'to' entry is visible, the coordinate of the entry will be equal to + // the visible arrow length. + if (this.#entryFromVisible && !this.#entryToVisible) { + visibleLineLength = this.#canvasRect.width - (this.#coordinateFrom.x + this.#fromEntryDimentions.width); + } + else if (!this.#entryFromVisible && this.#entryToVisible) { + visibleLineLength = this.#coordinateTo.x; + } + const visibleLineFromTotalPercentage = (visibleLineLength * 100) / lineLength; + return (visibleLineFromTotalPercentage < 100) ? visibleLineFromTotalPercentage : 100; + } /* The entries link overlay is an arrow connecting 2 entries. The Entries are drawn by Flamechart and this Overlay is only drawing the arrow between them. @@ -139,32 +248,130 @@ export class EntriesLinkOverlay extends HTMLElement { ➘ |_____entry______| */ #render() { + const arrowColor = ThemeSupport.ThemeSupport.instance().getComputedValue('--color-text-primary'); // clang-format off LitHtml.render(LitHtml.html ` - + + + + + + + + + + - + markerWidth="3" + markerHeight="4" + fill-opacity="1" + refX="4" + refY="2"> + - + + + class="entryFromWrapper" fill="none" stroke=${arrowColor} stroke-width=${BORDER_LINE_WIDTH} stroke-dasharray=${this.#fromEntryIsSource ? 'none' : DASHED_STROKE_AMOUNT} /> + class="entryToWrapper" fill="none" stroke=${arrowColor} stroke-width=${BORDER_LINE_WIDTH} stroke-dasharray=${this.#toEntryIsSource ? 'none' : DASHED_STROKE_AMOUNT} /> + + + `, this.#shadow, { host: this }); // clang-format on } } +const CONNECTOR_CIRCLE_RADIUS = 2; +const CONNECTOR_CIRCLE_STROKE_WIDTH = 1; +export class CreateEntriesLinkRemoveEvent extends Event { + static eventName = 'createentrieslinkremoveevent'; + constructor() { + super(CreateEntriesLinkRemoveEvent.eventName); + } +} +export class CreateEntriesLinkOverlay extends HTMLElement { + static litTagName = LitHtml.literal `devtools-create-entries-link-overlay`; + #shadow = this.attachShadow({ mode: 'open' }); + #fromEntryData; + constructor(initialFromEntryParams) { + super(); + this.#render(); + this.#fromEntryData = initialFromEntryParams; + this.#updateCreateLinkBox(); + const createLinkBox = this.#shadow.querySelector('.create-link-box'); + const createLinkIcon = createLinkBox?.querySelector('.create-link-icon') ?? null; + createLinkIcon?.addEventListener('click', this.#onClick.bind(this)); + } + connectedCallback() { + this.#shadow.adoptedStyleSheets = [styles]; + } + set fromEntryData(fromEntryParams) { + this.#fromEntryData = fromEntryParams; + this.#updateCreateLinkBox(); + } + #updateCreateLinkBox() { + const createLinkBox = this.#shadow.querySelector('.create-link-box'); + const createLinkIcon = createLinkBox?.querySelector('.create-link-icon') ?? null; + const entryHighlightWrapper = createLinkBox?.querySelector('.entry-highlight-wrapper') ?? null; + if (!createLinkBox || !createLinkIcon || !entryHighlightWrapper) { + console.error('creating element is missing.'); + return; + } + const { entryStartX, entryStartY, entryWidth, entryHeight } = this.#fromEntryData; + createLinkIcon.style.left = `${entryStartX + entryWidth}px`; + createLinkIcon.style.top = `${entryStartY}px`; + entryHighlightWrapper.style.left = `${entryStartX}px`; + entryHighlightWrapper.style.top = `${entryStartY}px`; + entryHighlightWrapper.style.width = `${entryWidth}px`; + entryHighlightWrapper.style.height = `${entryHeight}px`; + } + #onClick() { + this.dispatchEvent(new CreateEntriesLinkRemoveEvent()); + } + #render() { + // clang-format off + LitHtml.render(LitHtml.html ` + + `, this.#shadow, { host: this }); + // clang-format on + } +} // Defines the gap in the border when we are drawing a dashed outline. // https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray const DASHED_STROKE_AMOUNT = 4; +const OUT_OF_VIEW_STROKE_OPACITY = 0.2; customElements.define('devtools-entries-link-overlay', EntriesLinkOverlay); +customElements.define('devtools-create-entries-link-overlay', CreateEntriesLinkOverlay); //# sourceMappingURL=EntriesLinkOverlay.js.map \ No newline at end of file diff --git a/public/panels/timeline/overlays/components/EntriesLinkOverlay.js.map b/public/panels/timeline/overlays/components/EntriesLinkOverlay.js.map index 2750a94bc..0d1d59d2b 100644 --- a/public/panels/timeline/overlays/components/EntriesLinkOverlay.js.map +++ b/public/panels/timeline/overlays/components/EntriesLinkOverlay.js.map @@ -1 +1 @@ -{"version":3,"file":"EntriesLinkOverlay.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/overlays/components/EntriesLinkOverlay.ts"],"names":[],"mappings":"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","sourcesContent":["\n// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as ComponentHelpers from '../../../../ui/components/helpers/helpers.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\n\nimport styles from './entriesLinkOverlay.css.js';\n\nexport class EntriesLinkOverlay extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-entries-link-overlay`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n readonly #boundRender = this.#render.bind(this);\n #coordinateFrom: {x: number, y: number};\n #fromEntryDimentions: {width: number, height: number};\n #coordinateTo: {x: number, y: number};\n #toEntryDimentions: {width: number, height: number}|null = null;\n #connectorLineContainer: SVGAElement|null = null;\n #connector: SVGLineElement|null = null;\n #entryFromWrapper: SVGLineElement|null = null;\n #entryToWrapper: SVGLineElement|null = null;\n #entryFromVisible: boolean = true;\n #entryToVisible: boolean = true;\n\n // These flags let us know if the entry we are drawing from/to are the\n // originals, or if they are the parent, which can happen if an entry is\n // collapsed. We care about this because if the entry is not the source, we\n // draw the border as dashed, not solid.\n #fromEntryIsSource: boolean = true;\n #toEntryIsSource: boolean = true;\n\n constructor(initialFromEntryCoordinateAndDimentions: {x: number, y: number, width: number, height: number}) {\n super();\n this.#render();\n this.#coordinateFrom = {x: initialFromEntryCoordinateAndDimentions.x, y: initialFromEntryCoordinateAndDimentions.y};\n this.#fromEntryDimentions = {\n width: initialFromEntryCoordinateAndDimentions.width,\n height: initialFromEntryCoordinateAndDimentions.height,\n };\n this.#coordinateTo = {x: initialFromEntryCoordinateAndDimentions.x, y: initialFromEntryCoordinateAndDimentions.y};\n this.#connectorLineContainer = this.#shadow.querySelector('.connectorContainer') ?? null;\n this.#connector = this.#connectorLineContainer?.querySelector('line') ?? null;\n this.#entryFromWrapper = this.#connectorLineContainer?.querySelector('.entryFromWrapper') ?? null;\n this.#entryToWrapper = this.#connectorLineContainer?.querySelector('.entryToWrapper') ?? null;\n }\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [styles];\n }\n\n set fromEntryCoordinateAndDimentions(fromEntryParams: {x: number, y: number, length: number, height: number}) {\n this.#coordinateFrom = {x: fromEntryParams.x, y: fromEntryParams.y};\n this.#fromEntryDimentions = {width: fromEntryParams.length, height: fromEntryParams.height};\n this.#redrawConnectionArrow();\n }\n\n set entriesVisibility(entriesVisibility: {fromEntryVisibility: boolean, toEntryVisibility: boolean}) {\n this.#entryFromVisible = entriesVisibility.fromEntryVisibility;\n this.#entryToVisible = entriesVisibility.toEntryVisibility;\n }\n\n // The arrow might be pointing either to an entry or an empty space.\n // If the dimentions are not passed, it is pointing at an empty space.\n set toEntryCoordinateAndDimentions(toEntryParams: {x: number, y: number, length?: number, height?: number}) {\n this.#coordinateTo = {x: toEntryParams.x, y: toEntryParams.y};\n if (toEntryParams.length && toEntryParams.height) {\n this.#toEntryDimentions = {width: toEntryParams.length, height: toEntryParams.height};\n } else {\n this.#toEntryDimentions = null;\n }\n\n this.#redrawConnectionArrow();\n }\n\n set fromEntryIsSource(x: boolean) {\n if (x === this.#fromEntryIsSource) {\n return;\n }\n this.#fromEntryIsSource = x;\n this.#render();\n }\n\n set toEntryIsSource(x: boolean) {\n if (x === this.#toEntryIsSource) {\n return;\n }\n this.#toEntryIsSource = x;\n this.#render();\n }\n\n #redrawConnectionArrow(): void {\n if (!this.#connector || !this.#entryFromWrapper || !this.#entryToWrapper) {\n console.error('`connector` element is missing.');\n return;\n }\n\n // If the entry is visible, the entry arrow starts from the end on the X axis and middle of the Y axis.\n // If not, draw it to the same y point without the entry height offset and the box around the entry.\n // This way it will be attached to the track edge.\n if (this.#entryFromVisible) {\n const halfEntryHeight = this.#fromEntryDimentions.height / 2;\n this.#connector.setAttribute('x1', (this.#coordinateFrom.x + this.#fromEntryDimentions.width).toString());\n this.#connector.setAttribute('y1', (this.#coordinateFrom.y + Number(halfEntryHeight)).toString());\n\n this.#entryFromWrapper.setAttribute('visibility', 'visible');\n this.#entryFromWrapper.setAttribute('x', this.#coordinateFrom.x.toString());\n this.#entryFromWrapper.setAttribute('y', this.#coordinateFrom.y.toString());\n this.#entryFromWrapper.setAttribute('width', this.#fromEntryDimentions.width.toString());\n this.#entryFromWrapper.setAttribute('height', this.#fromEntryDimentions.height.toString());\n } else {\n this.#connector.setAttribute('x1', (this.#coordinateFrom.x + this.#fromEntryDimentions.width).toString());\n this.#connector.setAttribute('y1', this.#coordinateFrom.y.toString());\n this.#entryFromWrapper.setAttribute('visibility', 'hidden');\n }\n\n // If the arrow is pointing to the entry, point it to the middle of the entry and draw a box around the entry.\n // If the arrow is pointing to an entry, but it is not visible, the coordinates are for the edge of the track\n // and we don't need the half entry height offset.\n // Otherwise, thhe arrow is following the mouse so we assign it to the provided coordinates.\n if (this.#toEntryDimentions) {\n if (this.#entryToVisible) {\n this.#entryToWrapper.setAttribute('visibility', 'visible');\n this.#entryToWrapper.setAttribute('x', this.#coordinateTo.x.toString());\n this.#entryToWrapper.setAttribute('y', this.#coordinateTo.y.toString());\n this.#entryToWrapper.setAttribute('width', this.#toEntryDimentions.width.toString());\n this.#entryToWrapper.setAttribute('height', this.#toEntryDimentions.height.toString());\n\n this.#connector.setAttribute('x2', this.#coordinateTo.x.toString());\n this.#connector.setAttribute('y2', (this.#coordinateTo.y + this.#toEntryDimentions.height / 2).toString());\n\n } else {\n this.#entryToWrapper.setAttribute('visibility', 'hidden');\n this.#connector.setAttribute('x2', this.#coordinateTo.x.toString());\n this.#connector.setAttribute('y2', (this.#coordinateTo.y).toString());\n }\n\n } else {\n this.#entryToWrapper.setAttribute('visibility', 'hidden');\n this.#connector.setAttribute('x2', this.#coordinateTo.x.toString());\n this.#connector.setAttribute('y2', this.#coordinateTo.y.toString());\n }\n\n this.#connector.setAttribute('stroke', 'black');\n this.#connector.setAttribute('stroke-width', '2');\n\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n /*\n The entries link overlay is an arrow connecting 2 entries.\n The Entries are drawn by Flamechart and this Overlay is only drawing the arrow between them.\n _________\n |__entry__|\\\n \\\n \\ <-- arrow connecting the sides of entries drawn by this overlay\n \\ ________________\n ➘ |_____entry______|\n */\n #render(): void {\n // clang-format off\n LitHtml.render(\n LitHtml.html`\n \n \n \n \n \n \n \n \n \n \n `,\n this.#shadow, {host: this});\n // clang-format on\n }\n}\n\n// Defines the gap in the border when we are drawing a dashed outline.\n// https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray\nconst DASHED_STROKE_AMOUNT = 4;\n\ncustomElements.define('devtools-entries-link-overlay', EntriesLinkOverlay);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-entries-link-overlay': EntriesLinkOverlay;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"EntriesLinkOverlay.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/overlays/components/EntriesLinkOverlay.ts"],"names":[],"mappings":"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","sourcesContent":["\n// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport * as ComponentHelpers from '../../../../ui/components/helpers/helpers.js';\nimport * as IconButton from '../../../../ui/components/icon_button/icon_button.js';\nimport * as ThemeSupport from '../../../../ui/legacy/theme_support/theme_support.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\n\nconst UIStrings = {\n /**\n *@description Accessible label used to explain to a user that they are viewing an arrow representing a link between two entries.\n */\n diagram: 'Links bteween entries',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/overlays/components/EntriesLinkOverlay.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\n// In other overlays, the border line width is set to 2px.\nconst BORDER_LINE_WIDTH = 2;\n\nimport styles from './entriesLinkOverlay.css.js';\n\nexport class EntriesLinkOverlay extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-entries-link-overlay`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n readonly #boundRender = this.#render.bind(this);\n #coordinateFrom: {x: number, y: number};\n #fromEntryDimentions: {width: number, height: number};\n #coordinateTo: {x: number, y: number};\n #toEntryDimentions: {width: number, height: number}|null = null;\n #connectorLineContainer: SVGAElement|null = null;\n #connector: SVGLineElement|null = null;\n #entryFromWrapper: SVGLineElement|null = null;\n #entryToWrapper: SVGLineElement|null = null;\n #entryFromConnector: SVGCircleElement|null = null;\n #entryToConnector: SVGCircleElement|null = null;\n #entryFromVisible: boolean = true;\n #entryToVisible: boolean = true;\n #canvasRect: DOMRect|null = null;\n\n // These flags let us know if the entry we are drawing from/to are the\n // originals, or if they are the parent, which can happen if an entry is\n // collapsed. We care about this because if the entry is not the source, we\n // draw the border as dashed, not solid.\n #fromEntryIsSource: boolean = true;\n #toEntryIsSource: boolean = true;\n #arrowHidden: boolean = false;\n\n constructor(initialFromEntryCoordinateAndDimentions: {x: number, y: number, width: number, height: number}) {\n super();\n this.#render();\n this.#coordinateFrom = {x: initialFromEntryCoordinateAndDimentions.x, y: initialFromEntryCoordinateAndDimentions.y};\n this.#fromEntryDimentions = {\n width: initialFromEntryCoordinateAndDimentions.width,\n height: initialFromEntryCoordinateAndDimentions.height,\n };\n this.#coordinateTo = {x: initialFromEntryCoordinateAndDimentions.x, y: initialFromEntryCoordinateAndDimentions.y};\n this.#connectorLineContainer = this.#shadow.querySelector('.connectorContainer') ?? null;\n this.#connector = this.#connectorLineContainer?.querySelector('line') ?? null;\n this.#entryFromWrapper = this.#connectorLineContainer?.querySelector('.entryFromWrapper') ?? null;\n this.#entryToWrapper = this.#connectorLineContainer?.querySelector('.entryToWrapper') ?? null;\n this.#entryFromConnector = this.#connectorLineContainer?.querySelector('.entryFromConnector') ?? null;\n this.#entryToConnector = this.#connectorLineContainer?.querySelector('.entryToConnector') ?? null;\n }\n\n set canvasRect(rect: DOMRect|null) {\n if (rect === null) {\n return;\n }\n if (this.#canvasRect && this.#canvasRect.width === rect.width && this.#canvasRect.height === rect.height) {\n return;\n }\n this.#canvasRect = rect;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [styles];\n }\n\n /**\n * If one entry that is linked is in a collapsed track, we show the outlines\n * but hide only the arrow.\n */\n set hideArrow(shouldHide: boolean) {\n this.#arrowHidden = shouldHide;\n if (this.#connector) {\n this.#connector.style.display = shouldHide ? 'none' : 'block';\n }\n }\n\n set fromEntryCoordinateAndDimentions(fromEntryParams: {x: number, y: number, length: number, height: number}) {\n this.#coordinateFrom = {x: fromEntryParams.x, y: fromEntryParams.y};\n this.#fromEntryDimentions = {width: fromEntryParams.length, height: fromEntryParams.height};\n this.#redrawConnectionArrow();\n }\n\n set entriesVisibility(entriesVisibility: {fromEntryVisibility: boolean, toEntryVisibility: boolean}) {\n this.#entryFromVisible = entriesVisibility.fromEntryVisibility;\n this.#entryToVisible = entriesVisibility.toEntryVisibility;\n }\n\n // The arrow might be pointing either to an entry or an empty space.\n // If the dimensions are not passed, it is pointing at an empty space.\n set toEntryCoordinateAndDimentions(toEntryParams: {x: number, y: number, length?: number, height?: number}) {\n this.#coordinateTo = {x: toEntryParams.x, y: toEntryParams.y};\n if (toEntryParams.length && toEntryParams.height) {\n this.#toEntryDimentions = {width: toEntryParams.length, height: toEntryParams.height};\n } else {\n this.#toEntryDimentions = null;\n }\n\n this.#redrawConnectionArrow();\n }\n\n set fromEntryIsSource(x: boolean) {\n if (x === this.#fromEntryIsSource) {\n return;\n }\n this.#fromEntryIsSource = x;\n this.#render();\n }\n\n set toEntryIsSource(x: boolean) {\n if (x === this.#toEntryIsSource) {\n return;\n }\n this.#toEntryIsSource = x;\n this.#render();\n }\n\n #redrawConnectionArrow(): void {\n if (!this.#connector || !this.#entryFromWrapper || !this.#entryToWrapper || !this.#entryFromConnector ||\n !this.#entryToConnector) {\n console.error('`connector` element is missing.');\n return;\n }\n\n // If the user is zoomed out, the connector circles can be as large as the\n // event itself. So if the rectangle for this entry is too small, we\n // don't draw the circles.\n const minWidthToDrawConnectorCircles = 8;\n\n // We do not draw the connectors if the entry is not visible, or if the\n // entry we are connecting to isn't the actual source entry.\n // We also don't draw them if an entry is completely hidden, in which case\n // we aren't drawing the arrows, so it doesn't make sense to draw the\n // connectors.\n const drawFromEntryConnectorCircle = this.#entryFromVisible && !this.#arrowHidden && this.#fromEntryIsSource &&\n this.#fromEntryDimentions.width >= minWidthToDrawConnectorCircles;\n\n const widthOfToEntry = this.#toEntryDimentions?.width ?? 0;\n const drawToEntryConnectorCircle = !this.#arrowHidden && this.#entryToVisible && this.#toEntryIsSource &&\n widthOfToEntry >= minWidthToDrawConnectorCircles && !this.#arrowHidden;\n\n this.#entryFromConnector.setAttribute('visibility', drawFromEntryConnectorCircle ? 'visible' : 'hidden');\n this.#entryToConnector.setAttribute('visibility', drawToEntryConnectorCircle ? 'visible' : 'hidden');\n\n // If the entry is visible, the entry arrow starts from the end on the X axis and middle of the Y axis.\n // If not, draw it to the same y point without the entry height offset and the box around the entry.\n // This way it will be attached to the track edge.\n if (this.#entryFromVisible) {\n const halfEntryHeight = this.#fromEntryDimentions.height / 2;\n const endConnectionPointX = String(this.#coordinateFrom.x + this.#fromEntryDimentions.width);\n const endConnectionPointY = String(this.#coordinateFrom.y + halfEntryHeight);\n\n this.#connector.setAttribute('x1', endConnectionPointX);\n this.#connector.setAttribute('y1', endConnectionPointY);\n\n this.#entryFromConnector.setAttribute('cx', endConnectionPointX);\n this.#entryFromConnector.setAttribute('cy', endConnectionPointY);\n\n const adjustedEntryFromWrapperX = String(this.#coordinateFrom.x + BORDER_LINE_WIDTH / 2);\n const adjustedEntryFromWrapperY = String(this.#coordinateFrom.y + BORDER_LINE_WIDTH / 2);\n const adjustedWidth = String(this.#fromEntryDimentions.width - BORDER_LINE_WIDTH);\n const adjustedHeight = String(this.#fromEntryDimentions.height - BORDER_LINE_WIDTH);\n this.#entryFromWrapper.setAttribute('visibility', 'visible');\n this.#entryFromWrapper.setAttribute('x', adjustedEntryFromWrapperX);\n this.#entryFromWrapper.setAttribute('y', adjustedEntryFromWrapperY);\n this.#entryFromWrapper.setAttribute('width', adjustedWidth);\n this.#entryFromWrapper.setAttribute('height', adjustedHeight);\n } else {\n this.#connector.setAttribute('x1', (this.#coordinateFrom.x + this.#fromEntryDimentions.width).toString());\n this.#connector.setAttribute('y1', this.#coordinateFrom.y.toString());\n this.#entryFromWrapper.setAttribute('visibility', 'hidden');\n }\n\n // If the arrow is pointing to the entry, point it to the middle of the entry and draw a box around the entry.\n // If the arrow is pointing to an entry, but it is not visible, the coordinates are for the edge of the track\n // and we don't need the half entry height offset.\n // Otherwise, the arrow is following the mouse so we assign it to the provided coordinates.\n if (this.#toEntryDimentions) {\n if (this.#entryToVisible) {\n const adjustedEntryToWrapperX = String(this.#coordinateTo.x + BORDER_LINE_WIDTH / 2);\n const adjustedEntryToWrapperY = String(this.#coordinateTo.y + BORDER_LINE_WIDTH / 2);\n const adjustedWidth = String(this.#toEntryDimentions.width - BORDER_LINE_WIDTH);\n const adjustedHeight = String(this.#toEntryDimentions.height - BORDER_LINE_WIDTH);\n this.#entryToWrapper.setAttribute('visibility', 'visible');\n this.#entryToWrapper.setAttribute('x', adjustedEntryToWrapperX);\n this.#entryToWrapper.setAttribute('y', adjustedEntryToWrapperY);\n this.#entryToWrapper.setAttribute('width', adjustedWidth);\n this.#entryToWrapper.setAttribute('height', adjustedHeight);\n\n const connectionPointX = String(this.#coordinateTo.x);\n const connectionPointY = String(this.#coordinateTo.y + this.#toEntryDimentions.height / 2);\n\n this.#connector.setAttribute('x2', connectionPointX);\n this.#connector.setAttribute('y2', connectionPointY);\n\n this.#entryToConnector.setAttribute('cx', connectionPointX);\n this.#entryToConnector.setAttribute('cy', connectionPointY);\n\n } else {\n this.#entryToWrapper.setAttribute('visibility', 'hidden');\n this.#connector.setAttribute('x2', this.#coordinateTo.x.toString());\n this.#connector.setAttribute('y2', (this.#coordinateTo.y).toString());\n }\n\n } else {\n this.#entryToWrapper.setAttribute('visibility', 'hidden');\n this.#connector.setAttribute('x2', this.#coordinateTo.x.toString());\n this.#connector.setAttribute('y2', this.#coordinateTo.y.toString());\n }\n\n this.#connector.setAttribute('stroke-width', '2');\n\n if (this.#toEntryDimentions && this.#entryFromVisible && !this.#entryToVisible) {\n this.#connector.setAttribute('stroke', 'url(#fromVisibleLineGradient)');\n } else if (this.#toEntryDimentions && this.#entryToVisible && !this.#entryFromVisible) {\n this.#connector.setAttribute('stroke', 'url(#toVisibleLineGradient)');\n } else {\n const arrowColor = ThemeSupport.ThemeSupport.instance().getComputedValue('--color-text-primary');\n this.#connector.setAttribute('stroke', arrowColor);\n }\n\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n /*\n * When only one entry from the connection is visible, the connection\n * line becomes a gradient from the visible entry to the edge of\n * the screen towards the entry that is not visible.\n *\n * To achieve this, we need to calculate what percentage of the\n * visible screen the connection is currently occupying and apply\n * that gradient to the visible connection part.\n */\n #partlyVisibleConnectionLinePercentage(): number {\n if (!this.#canvasRect) {\n return 100;\n }\n\n const lineLength = this.#coordinateTo.x - (this.#coordinateFrom.x + this.#fromEntryDimentions.width);\n let visibleLineLength = 0;\n\n // If the visible entry is the 'From' entry, find the length of the visible arrow by\n // substracting the point where the arrow starts from the whole canvas length.\n // If the 'to' entry is visible, the coordinate of the entry will be equal to\n // the visible arrow length.\n if (this.#entryFromVisible && !this.#entryToVisible) {\n visibleLineLength = this.#canvasRect.width - (this.#coordinateFrom.x + this.#fromEntryDimentions.width);\n } else if (!this.#entryFromVisible && this.#entryToVisible) {\n visibleLineLength = this.#coordinateTo.x;\n }\n\n const visibleLineFromTotalPercentage = (visibleLineLength * 100) / lineLength;\n\n return (visibleLineFromTotalPercentage < 100) ? visibleLineFromTotalPercentage : 100;\n }\n\n /*\n The entries link overlay is an arrow connecting 2 entries.\n The Entries are drawn by Flamechart and this Overlay is only drawing the arrow between them.\n _________\n |__entry__|\\\n \\\n \\ <-- arrow connecting the sides of entries drawn by this overlay\n \\ ________________\n ➘ |_____entry______|\n */\n #render(): void {\n const arrowColor = ThemeSupport.ThemeSupport.instance().getComputedValue('--color-text-primary');\n // clang-format off\n LitHtml.render(\n LitHtml.html`\n \n \n \n \n \n \n\n \n \n \n \n \n \n \n \n \n\n \n \n\n \n \n \n `,\n this.#shadow, {host: this});\n // clang-format on\n }\n}\n\nconst CONNECTOR_CIRCLE_RADIUS = 2;\nconst CONNECTOR_CIRCLE_STROKE_WIDTH = 1;\n\nexport class CreateEntriesLinkRemoveEvent extends Event {\n static readonly eventName = 'createentrieslinkremoveevent';\n\n constructor() {\n super(CreateEntriesLinkRemoveEvent.eventName);\n }\n}\n\nexport class CreateEntriesLinkOverlay extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-create-entries-link-overlay`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n #fromEntryData: {entryStartX: number, entryStartY: number, entryWidth: number, entryHeight: number};\n\n constructor(initialFromEntryParams:\n {entryStartX: number, entryStartY: number, entryWidth: number, entryHeight: number}) {\n super();\n this.#render();\n this.#fromEntryData = initialFromEntryParams;\n this.#updateCreateLinkBox();\n const createLinkBox = this.#shadow.querySelector('.create-link-box');\n const createLinkIcon = createLinkBox?.querySelector('.create-link-icon') ?? null;\n createLinkIcon?.addEventListener('click', this.#onClick.bind(this));\n }\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [styles];\n }\n\n set fromEntryData(fromEntryParams:\n {entryStartX: number, entryStartY: number, entryWidth: number, entryHeight: number}) {\n this.#fromEntryData = fromEntryParams;\n this.#updateCreateLinkBox();\n }\n\n #updateCreateLinkBox(): void {\n const createLinkBox = this.#shadow.querySelector('.create-link-box');\n const createLinkIcon = createLinkBox?.querySelector('.create-link-icon') ?? null;\n const entryHighlightWrapper = createLinkBox?.querySelector('.entry-highlight-wrapper') ?? null;\n\n if (!createLinkBox || !createLinkIcon || !entryHighlightWrapper) {\n console.error('creating element is missing.');\n return;\n }\n\n const {entryStartX, entryStartY, entryWidth, entryHeight} = this.#fromEntryData;\n\n createLinkIcon.style.left = `${entryStartX + entryWidth}px`;\n createLinkIcon.style.top = `${entryStartY}px`;\n entryHighlightWrapper.style.left = `${entryStartX}px`;\n entryHighlightWrapper.style.top = `${entryStartY}px`;\n entryHighlightWrapper.style.width = `${entryWidth}px`;\n entryHighlightWrapper.style.height = `${entryHeight}px`;\n }\n\n #onClick(): void {\n this.dispatchEvent(new CreateEntriesLinkRemoveEvent());\n }\n\n #render(): void {\n // clang-format off\n LitHtml.render(\n LitHtml.html`\n \n `,\n this.#shadow, {host: this});\n // clang-format on\n }\n}\n\n// Defines the gap in the border when we are drawing a dashed outline.\n// https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray\nconst DASHED_STROKE_AMOUNT = 4;\nconst OUT_OF_VIEW_STROKE_OPACITY = 0.2;\n\ncustomElements.define('devtools-entries-link-overlay', EntriesLinkOverlay);\ncustomElements.define('devtools-create-entries-link-overlay', CreateEntriesLinkOverlay);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-entries-link-overlay': EntriesLinkOverlay;\n 'devtools-create-entries-link-overlay': CreateEntriesLinkOverlay;\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/overlays/components/EntryLabelOverlay.d.ts b/public/panels/timeline/overlays/components/EntryLabelOverlay.d.ts index 6f7816e1e..e739535f2 100644 --- a/public/panels/timeline/overlays/components/EntryLabelOverlay.d.ts +++ b/public/panels/timeline/overlays/components/EntryLabelOverlay.d.ts @@ -17,6 +17,25 @@ export declare class EntryLabelOverlay extends HTMLElement { static readonly MAX_LABEL_LENGTH = 100; static readonly USER_CREATED_ICON_WIDTH = 16; static readonly litTagName: import("../../../../ui/lit-html/static.js").Static; + /** + * The entry label overlay consists of 3 parts - the label part with the label string inside, + * the line connecting the label to the entry, and a black box around an entry to highlight the entry with a label. + * ________ + * |_label__| <-- label part with the label string inside + * \ + * \ <-- line connecting the label to the entry with a circle at the end + * \ + * _______◯_________ + * |_____entry______| <--- box around an entry + * + * `drawLabel` method below draws the first part. + * `drawConnector` method below draws the second part - the connector line with a circle and the svg container for them. + * `drawEntryHighlightWrapper` draws the third part. + * We only rerender the first part if the label changes and the third part if the size of the entry changes. + * The connector and circle shapes never change so we only draw the second part when the component is created. + * + * Otherwise, the entry label overlay object only gets repositioned. + */ constructor(label: string, entryIsInMainChart: boolean, shouldDrawBelowEntry?: boolean); connectedCallback(): void; set entryLabelParams(entryLabelParams: { @@ -25,6 +44,7 @@ export declare class EntryLabelOverlay extends HTMLElement { cutOffEntryHeight: number; chart: string; }); + setLabelEditabilityAndRemoveEmptyLabel(editable: boolean): void; } declare global { interface HTMLElementTagNameMap { diff --git a/public/panels/timeline/overlays/components/EntryLabelOverlay.js b/public/panels/timeline/overlays/components/EntryLabelOverlay.js index 8e1fb2ee2..ddae8fbe3 100644 --- a/public/panels/timeline/overlays/components/EntryLabelOverlay.js +++ b/public/panels/timeline/overlays/components/EntryLabelOverlay.js @@ -1,10 +1,20 @@ // Copyright 2024 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 * as i18n from '../../../../core/i18n/i18n.js'; import * as ComponentHelpers from '../../../../ui/components/helpers/helpers.js'; import * as IconButton from '../../../../ui/components/icon_button/icon_button.js'; +import * as ThemeSupport from '../../../../ui/legacy/theme_support/theme_support.js'; import * as LitHtml from '../../../../ui/lit-html/lit-html.js'; import styles from './entryLabelOverlay.css.js'; +const UIStrings = { + /** + *@description Accessible label used to explain to a user that they are viewing an entry label. + */ + entryLabel: 'Entry label', +}; +const str_ = i18n.i18n.registerUIStrings('panels/timeline/overlays/components/EntryLabelOverlay.ts', UIStrings); +const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); export class EmptyEntryLabelRemoveEvent extends Event { static eventName = 'emptyentrylabelremoveevent'; constructor() { @@ -30,7 +40,7 @@ export class EntryLabelOverlay extends HTMLElement { static LABEL_AND_CONNECTOR_HEIGHT = EntryLabelOverlay.LABEL_HEIGHT + EntryLabelOverlay.LABEL_PADDING * 2 + EntryLabelOverlay.LABEL_CONNECTOR_HEIGHT; // Set the max label length to avoid labels that could signicantly increase the file size. static MAX_LABEL_LENGTH = 100; - // Width of the icon next to the label input field + // Width of the icon next to the label input field. This is same as the width in CSS. static USER_CREATED_ICON_WIDTH = 16; static litTagName = LitHtml.literal `devtools-entry-label-overlay`; #shadow = this.attachShadow({ mode: 'open' }); @@ -47,25 +57,25 @@ export class EntryLabelOverlay extends HTMLElement { #label; #entryIsInMainChart; #shouldDrawBelowEntry; - /* - The entry label overlay consists of 3 parts - the label part with the label string inside, - the line connecting the label to the entry, and a black box around an entry to highlight the entry with a label. - ________ - |_label__| <-- label part with the label string inside - \ - \ <-- line connecting the label to the entry with a circle at the end - \ - _______◯_________ - |_____entry______| <--- box around an entry - - `drawLabel` method below draws the first part. - `drawConnector` method below draws the second part - the connector line with a circle and the svg container for them. - `drawEntryHighlightWrapper` draws the third part. - We only rerender the first part if the label changes and the third part if the size of the entry changes. - The connector and circle shapes never change so we only draw the second part when the component is created. - - Otherwise, the entry label overlay object only gets repositioned. - */ + /** + * The entry label overlay consists of 3 parts - the label part with the label string inside, + * the line connecting the label to the entry, and a black box around an entry to highlight the entry with a label. + * ________ + * |_label__| <-- label part with the label string inside + * \ + * \ <-- line connecting the label to the entry with a circle at the end + * \ + * _______◯_________ + * |_____entry______| <--- box around an entry + * + * `drawLabel` method below draws the first part. + * `drawConnector` method below draws the second part - the connector line with a circle and the svg container for them. + * `drawEntryHighlightWrapper` draws the third part. + * We only rerender the first part if the label changes and the third part if the size of the entry changes. + * The connector and circle shapes never change so we only draw the second part when the component is created. + * + * Otherwise, the entry label overlay object only gets repositioned. + */ constructor(label, entryIsInMainChart, shouldDrawBelowEntry = false) { super(); this.#render(); @@ -82,7 +92,8 @@ export class EntryLabelOverlay extends HTMLElement { // If the label is not empty, it was loaded from the trace file. // In that case, do not auto-focus it as if the user were creating it for the first time if (label !== '') { - this.#setLabelEditabilityAndRemoveEmptyLabel(false); + this.setLabelEditabilityAndRemoveEmptyLabel(false); + this.#inputField?.setAttribute('aria-label', this.#label); } this.#drawConnector(); } @@ -96,6 +107,7 @@ export class EntryLabelOverlay extends HTMLElement { this.#label = labelBoxTextContent; this.dispatchEvent(new EntryLabelChangeEvent(this.#label)); } + this.#inputField?.setAttribute('aria-label', labelBoxTextContent); } #handleLabelInputKeyDown(event) { if (!this.#inputField) { @@ -154,6 +166,8 @@ export class EntryLabelOverlay extends HTMLElement { if (entryLabelParams.height === this.#entryLabelParams?.height && entryLabelParams.width === this.#entryLabelParams?.width && entryLabelParams.cutOffEntryHeight === this.#entryLabelParams?.cutOffEntryHeight) { + // Even the position is not changed, the theme color might change, so we need to redraw the connector here. + this.#drawConnector(); return; } this.#entryLabelParams = entryLabelParams; @@ -192,13 +206,14 @@ export class EntryLabelOverlay extends HTMLElement { // Finish drawing in middle of the connector container. connector.setAttribute('x2', EntryLabelOverlay.LABEL_AND_CONNECTOR_SHIFT_LENGTH.toString()); connector.setAttribute('y2', EntryLabelOverlay.LABEL_CONNECTOR_HEIGHT.toString()); - connector.setAttribute('stroke', 'black'); + const connectorColor = ThemeSupport.ThemeSupport.instance().getComputedValue('--color-text-primary'); + connector.setAttribute('stroke', connectorColor); connector.setAttribute('stroke-width', '2'); // Draw the circle at the bottom of the connector circle.setAttribute('cx', EntryLabelOverlay.LABEL_AND_CONNECTOR_SHIFT_LENGTH.toString()); circle.setAttribute('cy', EntryLabelOverlay.LABEL_CONNECTOR_HEIGHT.toString()); circle.setAttribute('r', '3'); - circle.setAttribute('fill', 'black'); + circle.setAttribute('fill', connectorColor); } #drawLabel(initialLabel) { if (!this.#inputField || !this.#labelBox) { @@ -274,7 +289,7 @@ export class EntryLabelOverlay extends HTMLElement { } this.#inputField.focus(); } - #setLabelEditabilityAndRemoveEmptyLabel(editable) { + setLabelEditabilityAndRemoveEmptyLabel(editable) { this.#isLabelEditable = editable; this.#render(); // If the label is editable, focus cursor on it @@ -289,19 +304,15 @@ export class EntryLabelOverlay extends HTMLElement { #render() { // clang-format off LitHtml.render(LitHtml.html ` - +
    - <${IconButton.Icon.Icon.litTagName} class="user-created-icon" .data=${{ - iconName: 'profile', - color: 'var(--sys-color-token-variable)', - width: EntryLabelOverlay.USER_CREATED_ICON_WIDTH + 'px', - height: '16px', - }}> - + <${IconButton.Icon.Icon.litTagName} class='user-created-icon' name='profile'> + this.#setLabelEditabilityAndRemoveEmptyLabel(true)} - @blur=${() => this.#setLabelEditabilityAndRemoveEmptyLabel(false)} + role="textbox" + @dblclick=${() => this.setLabelEditabilityAndRemoveEmptyLabel(true)} + @blur=${() => this.setLabelEditabilityAndRemoveEmptyLabel(false)} @keydown=${this.#handleLabelInputKeyDown} @paste=${this.#handleLabelInputPaste} @keyup=${this.#handleLabelInputKeyUp} diff --git a/public/panels/timeline/overlays/components/EntryLabelOverlay.js.map b/public/panels/timeline/overlays/components/EntryLabelOverlay.js.map index 5c5e6e862..84499e1df 100644 --- a/public/panels/timeline/overlays/components/EntryLabelOverlay.js.map +++ b/public/panels/timeline/overlays/components/EntryLabelOverlay.js.map @@ -1 +1 @@ -{"version":3,"file":"EntryLabelOverlay.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as ComponentHelpers from '../../../../ui/components/helpers/helpers.js';\nimport * as IconButton from '../../../../ui/components/icon_button/icon_button.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\n\nimport styles from './entryLabelOverlay.css.js';\n\nexport class EmptyEntryLabelRemoveEvent extends Event {\n static readonly eventName = 'emptyentrylabelremoveevent';\n\n constructor() {\n super(EmptyEntryLabelRemoveEvent.eventName);\n }\n}\n\nexport class EntryLabelChangeEvent extends Event {\n static readonly eventName = 'entrylabelchangeevent';\n\n constructor(public newLabel: string) {\n super(EntryLabelChangeEvent.eventName);\n }\n}\n\nexport class EntryLabelOverlay extends HTMLElement {\n // The label is angled on the left from the centre of the entry it belongs to.\n // `LABEL_AND_CONNECTOR_SHIFT_LENGTH` specifies how many pixels to the left it is shifted.\n static readonly LABEL_AND_CONNECTOR_SHIFT_LENGTH = 8;\n // Length of the line that connects the label to the entry.\n static readonly LABEL_CONNECTOR_HEIGHT = 7;\n static readonly LABEL_HEIGHT = 17;\n static readonly LABEL_PADDING = 4;\n static readonly LABEL_AND_CONNECTOR_HEIGHT =\n EntryLabelOverlay.LABEL_HEIGHT + EntryLabelOverlay.LABEL_PADDING * 2 + EntryLabelOverlay.LABEL_CONNECTOR_HEIGHT;\n // Set the max label length to avoid labels that could signicantly increase the file size.\n static readonly MAX_LABEL_LENGTH = 100;\n // Width of the icon next to the label input field\n static readonly USER_CREATED_ICON_WIDTH = 16;\n\n static readonly litTagName = LitHtml.literal`devtools-entry-label-overlay`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n readonly #boundRender = this.#render.bind(this);\n // The label is set to editable when it is double clicked. If the user clicks away from the label box\n // element, the lable is set to not editable until it double clicked.s\n #isLabelEditable: boolean = true;\n #entryLabelParams: {height: number, width: number, cutOffEntryHeight: number}|null = null;\n\n #labelPartsWrapper: HTMLElement|null = null;\n #inputField: HTMLElement|null = null;\n #labelBox: HTMLElement|null = null;\n #entryHighlightWrapper: HTMLElement|null = null;\n #connectorLineContainer: SVGAElement|null = null;\n #label: string;\n #entryIsInMainChart: boolean;\n #shouldDrawBelowEntry: boolean;\n /*\nThe entry label overlay consists of 3 parts - the label part with the label string inside,\nthe line connecting the label to the entry, and a black box around an entry to highlight the entry with a label.\n________\n|_label__| <-- label part with the label string inside\n \\\n \\ <-- line connecting the label to the entry with a circle at the end\n \\\n_______◯_________\n|_____entry______| <--- box around an entry\n\n`drawLabel` method below draws the first part.\n`drawConnector` method below draws the second part - the connector line with a circle and the svg container for them.\n`drawEntryHighlightWrapper` draws the third part.\nWe only rerender the first part if the label changes and the third part if the size of the entry changes.\nThe connector and circle shapes never change so we only draw the second part when the component is created.\n\nOtherwise, the entry label overlay object only gets repositioned.\n*/\n\n constructor(label: string, entryIsInMainChart: boolean, shouldDrawBelowEntry: boolean = false) {\n super();\n this.#render();\n this.#shouldDrawBelowEntry = shouldDrawBelowEntry;\n this.#labelPartsWrapper = this.#shadow.querySelector('.label-parts-wrapper');\n this.#labelBox = this.#labelPartsWrapper?.querySelector('.label-box') ?? null;\n this.#inputField = this.#labelPartsWrapper?.querySelector('.input-field') ?? null;\n this.#connectorLineContainer = this.#labelPartsWrapper?.querySelector('.connectorContainer') ?? null;\n this.#entryHighlightWrapper =\n this.#labelPartsWrapper?.querySelector('.entry-highlight-wrapper') ?? null;\n this.#label = label;\n this.#entryIsInMainChart = entryIsInMainChart;\n this.#drawLabel(label);\n // If the label is not empty, it was loaded from the trace file.\n // In that case, do not auto-focus it as if the user were creating it for the first time\n if (label !== '') {\n this.#setLabelEditabilityAndRemoveEmptyLabel(false);\n }\n\n this.#drawConnector();\n }\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [styles];\n }\n\n #handleLabelInputKeyUp(): void {\n // If the label changed on key up, dispatch label changed event\n const labelBoxTextContent = this.#inputField?.textContent ?? '';\n if (labelBoxTextContent !== this.#label) {\n this.#label = labelBoxTextContent;\n this.dispatchEvent(new EntryLabelChangeEvent(this.#label));\n }\n }\n\n #handleLabelInputKeyDown(event: KeyboardEvent): boolean {\n if (!this.#inputField) {\n return false;\n }\n\n const allowedKeysAfterReachingLenLimit = [\n 'Backspace',\n 'Delete',\n 'ArrowLeft',\n 'ArrowRight',\n ];\n\n // We do not want to create multi-line labels.\n // Therefore, if the new key is `Enter` key, treat it\n // as the end of the label input and blur the input field.\n if (event.key === 'Enter' || event.key === 'Escape') {\n // In DevTools, the `Escape` button will by default toggle the console\n // drawer, which we don't want here, so we need to call\n // `stopPropagation()`.\n event.stopPropagation();\n this.#inputField.dispatchEvent(new FocusEvent('blur', {bubbles: true}));\n return false;\n }\n\n // If the max limit is not reached, return true\n if (this.#inputField.textContent !== null &&\n this.#inputField.textContent.length <= EntryLabelOverlay.MAX_LABEL_LENGTH) {\n return true;\n }\n\n if (allowedKeysAfterReachingLenLimit.includes(event.key)) {\n return true;\n }\n\n if (event.key.length === 1 && event.ctrlKey /* Ctrl + A for selecting all */) {\n return true;\n }\n\n event.preventDefault();\n return false;\n }\n\n #handleLabelInputPaste(event: ClipboardEvent): void {\n event.preventDefault();\n\n const clipboardData = event.clipboardData;\n if (!clipboardData || !this.#inputField) {\n return;\n }\n\n const pastedText = clipboardData.getData('text');\n\n const newText = this.#inputField.textContent + pastedText;\n const trimmedText = newText.slice(0, EntryLabelOverlay.MAX_LABEL_LENGTH + 1);\n\n this.#inputField.textContent = trimmedText;\n\n // Reset the selection to the end\n const selection = window.getSelection();\n const range = document.createRange();\n range.selectNodeContents(this.#inputField);\n range.collapse(false);\n selection?.removeAllRanges();\n selection?.addRange(range);\n }\n\n set entryLabelParams(entryLabelParams: {height: number, width: number, cutOffEntryHeight: number, chart: string}) {\n if (entryLabelParams.height === this.#entryLabelParams?.height &&\n entryLabelParams.width === this.#entryLabelParams?.width &&\n entryLabelParams.cutOffEntryHeight === this.#entryLabelParams?.cutOffEntryHeight) {\n return;\n }\n\n this.#entryLabelParams = entryLabelParams;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n // We need to redraw the entry wrapper only if the entry dimensions change\n this.#drawEntryHighlightWrapper();\n // The label and connector can move depending on the height of the entry\n this.#drawLabel();\n this.#drawConnector();\n }\n\n #drawConnector(): void {\n if (!this.#connectorLineContainer) {\n console.error('`connectorLineContainer` element is missing.');\n return;\n }\n\n if (this.#shouldDrawBelowEntry && this.#entryLabelParams) {\n const translation = this.#entryLabelParams.height - this.#entryLabelParams.cutOffEntryHeight +\n EntryLabelOverlay.LABEL_CONNECTOR_HEIGHT;\n\n this.#connectorLineContainer.style.transform = `translateY(${translation}px) rotate(180deg)`;\n }\n\n const connector = this.#connectorLineContainer.querySelector('line');\n const circle = this.#connectorLineContainer.querySelector('circle');\n if (!connector || !circle) {\n console.error('Some entry label elements are missing.');\n return;\n }\n // PART 2: draw the connector from label to the entry\n // Set the width of the canvas that draws the connector to be equal to the length of the shift multiplied by two.\n // That way, we can draw the connector from its corner to its middle. Since all elements are alligned in the middle, the connector\n // will end in the middle of the entry.\n this.#connectorLineContainer.setAttribute(\n 'width', (EntryLabelOverlay.LABEL_AND_CONNECTOR_SHIFT_LENGTH * 2).toString());\n this.#connectorLineContainer.setAttribute('height', EntryLabelOverlay.LABEL_CONNECTOR_HEIGHT.toString());\n // Start drawing the top right corner.\n connector.setAttribute('x1', '0');\n connector.setAttribute('y1', '0');\n // Finish drawing in middle of the connector container.\n connector.setAttribute('x2', EntryLabelOverlay.LABEL_AND_CONNECTOR_SHIFT_LENGTH.toString());\n connector.setAttribute('y2', EntryLabelOverlay.LABEL_CONNECTOR_HEIGHT.toString());\n connector.setAttribute('stroke', 'black');\n connector.setAttribute('stroke-width', '2');\n\n // Draw the circle at the bottom of the connector\n circle.setAttribute('cx', EntryLabelOverlay.LABEL_AND_CONNECTOR_SHIFT_LENGTH.toString());\n circle.setAttribute('cy', EntryLabelOverlay.LABEL_CONNECTOR_HEIGHT.toString());\n circle.setAttribute('r', '3');\n circle.setAttribute('fill', 'black');\n }\n\n #drawLabel(initialLabel?: string): void {\n if (!this.#inputField || !this.#labelBox) {\n console.error('`labelBox` or `labelBox` element is missing.');\n return;\n }\n\n if (typeof initialLabel === 'string') {\n this.#inputField.innerText = initialLabel;\n }\n\n let xTranslation: number|null = null;\n let yTranslation: number|null = null;\n // PART 1: draw the label box\n if (this.#shouldDrawBelowEntry) {\n // Label is drawn below and slightly to the right.\n xTranslation = EntryLabelOverlay.LABEL_AND_CONNECTOR_SHIFT_LENGTH - EntryLabelOverlay.USER_CREATED_ICON_WIDTH / 2;\n } else {\n // If the label is drawn above, the connector goes up and to the left, so\n // we pull the label back slightly to align it nicely.\n xTranslation =\n EntryLabelOverlay.LABEL_AND_CONNECTOR_SHIFT_LENGTH * -1 - EntryLabelOverlay.USER_CREATED_ICON_WIDTH / 2;\n }\n\n if (this.#shouldDrawBelowEntry && this.#entryLabelParams) {\n // Move the label down from above the entry to below it. The label is positioned by default quite far above the entry, hence why we add:\n // 1. the height of the entry + of the label (inc its padding)\n // 2. the height of the connector (*2), so we have room to draw it\n // 3. another 4 px, because it looks nicer than if we don't have that :)\n const verticalTransform = this.#entryLabelParams.height - this.#entryLabelParams.cutOffEntryHeight +\n EntryLabelOverlay.LABEL_HEIGHT + EntryLabelOverlay.LABEL_PADDING * 2 +\n EntryLabelOverlay.LABEL_CONNECTOR_HEIGHT * 2;\n\n yTranslation = verticalTransform;\n }\n\n let transformString = '';\n if (xTranslation) {\n transformString += `translateX(${xTranslation}px) `;\n }\n if (yTranslation) {\n transformString += `translateY(${yTranslation}px)`;\n }\n\n if (transformString.length) {\n this.#labelBox.style.transform = transformString;\n }\n }\n\n #drawEntryHighlightWrapper(): void {\n if (!this.#entryHighlightWrapper || !this.#entryLabelParams || !this.#inputField || !this.#connectorLineContainer) {\n console.error('Some elements required to draw `entryHighlightWrapper` are missing.');\n return;\n }\n\n const {height, width, cutOffEntryHeight} = this.#entryLabelParams;\n\n // If part of the entry is hidden by the resizer in the main chart, it is hidden from the top.\n // Therefore, set the bottom border to hidden and hide the label and connector parts of the label.\n // If it's partly hidden in the network chart, it's hidden from the bottom. In that case, hide the bottom border.\n if (this.#entryIsInMainChart) {\n this.#entryHighlightWrapper.style.borderTopWidth = cutOffEntryHeight > 0 ? '0' : '2px';\n } else {\n this.#entryHighlightWrapper.style.borderBottomWidth = cutOffEntryHeight > 0 ? '0' : '2px';\n }\n\n // PART 3: draw the box that highlights the entry with a label\n this.#entryHighlightWrapper.style.height = `${height - cutOffEntryHeight}px`;\n this.#entryHighlightWrapper.style.width = `${width}px`;\n\n // If the label is editable, focus cursor on it.\n // This method needs to be called after rendering the wrapper because it is the last label overlay element to render.\n // By doing this, the cursor focuses when the label is created.\n if (this.#isLabelEditable) {\n this.#focusInputBox();\n }\n }\n\n #focusInputBox(): void {\n if (!this.#inputField) {\n console.error('`labelBox` element is missing.');\n return;\n }\n this.#inputField.focus();\n }\n\n #setLabelEditabilityAndRemoveEmptyLabel(editable: boolean): void {\n this.#isLabelEditable = editable;\n this.#render();\n // If the label is editable, focus cursor on it\n if (editable) {\n this.#focusInputBox();\n }\n // If the label is empty when it is being navigated away from, dispatch an event to remove this entry overlay\n if (!editable && this.#inputField?.innerText.length === 0) {\n this.dispatchEvent(new EmptyEntryLabelRemoveEvent());\n }\n }\n\n #render(): void {\n // clang-format off\n LitHtml.render(\n LitHtml.html`\n \n
    \n <${IconButton.Icon.Icon.litTagName} class=\"user-created-icon\" .data=${{\n iconName: 'profile',\n color: 'var(--sys-color-token-variable)',\n width: EntryLabelOverlay.USER_CREATED_ICON_WIDTH + 'px',\n height: '16px',\n } as IconButton.Icon.IconData}>\n \n this.#setLabelEditabilityAndRemoveEmptyLabel(true)}\n @blur=${() => this.#setLabelEditabilityAndRemoveEmptyLabel(false)}\n @keydown=${this.#handleLabelInputKeyDown}\n @paste=${this.#handleLabelInputPaste}\n @keyup=${this.#handleLabelInputKeyUp}\n contenteditable=${this.#isLabelEditable ? 'plaintext-only' : false}>\n \n
    \n \n \n \n \n
    \n `,\n this.#shadow, {host: this});\n // clang-format on\n }\n}\n\ncustomElements.define('devtools-entry-label-overlay', EntryLabelOverlay);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-entry-label-overlay': EntryLabelOverlay;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"EntryLabelOverlay.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport * as ComponentHelpers from '../../../../ui/components/helpers/helpers.js';\nimport * as IconButton from '../../../../ui/components/icon_button/icon_button.js';\nimport * as ThemeSupport from '../../../../ui/legacy/theme_support/theme_support.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\n\nimport styles from './entryLabelOverlay.css.js';\n\nconst UIStrings = {\n /**\n *@description Accessible label used to explain to a user that they are viewing an entry label.\n */\n entryLabel: 'Entry label',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/overlays/components/EntryLabelOverlay.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport class EmptyEntryLabelRemoveEvent extends Event {\n static readonly eventName = 'emptyentrylabelremoveevent';\n\n constructor() {\n super(EmptyEntryLabelRemoveEvent.eventName);\n }\n}\n\nexport class EntryLabelChangeEvent extends Event {\n static readonly eventName = 'entrylabelchangeevent';\n\n constructor(public newLabel: string) {\n super(EntryLabelChangeEvent.eventName);\n }\n}\n\nexport class EntryLabelOverlay extends HTMLElement {\n // The label is angled on the left from the centre of the entry it belongs to.\n // `LABEL_AND_CONNECTOR_SHIFT_LENGTH` specifies how many pixels to the left it is shifted.\n static readonly LABEL_AND_CONNECTOR_SHIFT_LENGTH = 8;\n // Length of the line that connects the label to the entry.\n static readonly LABEL_CONNECTOR_HEIGHT = 7;\n static readonly LABEL_HEIGHT = 17;\n static readonly LABEL_PADDING = 4;\n static readonly LABEL_AND_CONNECTOR_HEIGHT =\n EntryLabelOverlay.LABEL_HEIGHT + EntryLabelOverlay.LABEL_PADDING * 2 + EntryLabelOverlay.LABEL_CONNECTOR_HEIGHT;\n // Set the max label length to avoid labels that could signicantly increase the file size.\n static readonly MAX_LABEL_LENGTH = 100;\n // Width of the icon next to the label input field. This is same as the width in CSS.\n static readonly USER_CREATED_ICON_WIDTH = 16;\n\n static readonly litTagName = LitHtml.literal`devtools-entry-label-overlay`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n readonly #boundRender = this.#render.bind(this);\n // The label is set to editable when it is double clicked. If the user clicks away from the label box\n // element, the lable is set to not editable until it double clicked.s\n #isLabelEditable: boolean = true;\n #entryLabelParams: {height: number, width: number, cutOffEntryHeight: number}|null = null;\n\n #labelPartsWrapper: HTMLElement|null = null;\n #inputField: HTMLElement|null = null;\n #labelBox: HTMLElement|null = null;\n #entryHighlightWrapper: HTMLElement|null = null;\n #connectorLineContainer: SVGAElement|null = null;\n #label: string;\n #entryIsInMainChart: boolean;\n #shouldDrawBelowEntry: boolean;\n /**\n * The entry label overlay consists of 3 parts - the label part with the label string inside,\n * the line connecting the label to the entry, and a black box around an entry to highlight the entry with a label.\n * ________\n * |_label__| <-- label part with the label string inside\n * \\\n * \\ <-- line connecting the label to the entry with a circle at the end\n * \\\n * _______◯_________\n * |_____entry______| <--- box around an entry\n *\n * `drawLabel` method below draws the first part.\n * `drawConnector` method below draws the second part - the connector line with a circle and the svg container for them.\n * `drawEntryHighlightWrapper` draws the third part.\n * We only rerender the first part if the label changes and the third part if the size of the entry changes.\n * The connector and circle shapes never change so we only draw the second part when the component is created.\n *\n * Otherwise, the entry label overlay object only gets repositioned.\n */\n\n constructor(label: string, entryIsInMainChart: boolean, shouldDrawBelowEntry: boolean = false) {\n super();\n this.#render();\n this.#shouldDrawBelowEntry = shouldDrawBelowEntry;\n this.#labelPartsWrapper = this.#shadow.querySelector('.label-parts-wrapper');\n this.#labelBox = this.#labelPartsWrapper?.querySelector('.label-box') ?? null;\n this.#inputField = this.#labelPartsWrapper?.querySelector('.input-field') ?? null;\n this.#connectorLineContainer = this.#labelPartsWrapper?.querySelector('.connectorContainer') ?? null;\n this.#entryHighlightWrapper =\n this.#labelPartsWrapper?.querySelector('.entry-highlight-wrapper') ?? null;\n this.#label = label;\n this.#entryIsInMainChart = entryIsInMainChart;\n this.#drawLabel(label);\n // If the label is not empty, it was loaded from the trace file.\n // In that case, do not auto-focus it as if the user were creating it for the first time\n if (label !== '') {\n this.setLabelEditabilityAndRemoveEmptyLabel(false);\n this.#inputField?.setAttribute('aria-label', this.#label);\n }\n\n this.#drawConnector();\n }\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [styles];\n }\n\n #handleLabelInputKeyUp(): void {\n // If the label changed on key up, dispatch label changed event\n const labelBoxTextContent = this.#inputField?.textContent ?? '';\n if (labelBoxTextContent !== this.#label) {\n this.#label = labelBoxTextContent;\n this.dispatchEvent(new EntryLabelChangeEvent(this.#label));\n }\n this.#inputField?.setAttribute('aria-label', labelBoxTextContent);\n }\n\n #handleLabelInputKeyDown(event: KeyboardEvent): boolean {\n if (!this.#inputField) {\n return false;\n }\n\n const allowedKeysAfterReachingLenLimit = [\n 'Backspace',\n 'Delete',\n 'ArrowLeft',\n 'ArrowRight',\n ];\n\n // We do not want to create multi-line labels.\n // Therefore, if the new key is `Enter` key, treat it\n // as the end of the label input and blur the input field.\n if (event.key === 'Enter' || event.key === 'Escape') {\n // In DevTools, the `Escape` button will by default toggle the console\n // drawer, which we don't want here, so we need to call\n // `stopPropagation()`.\n event.stopPropagation();\n this.#inputField.dispatchEvent(new FocusEvent('blur', {bubbles: true}));\n return false;\n }\n\n // If the max limit is not reached, return true\n if (this.#inputField.textContent !== null &&\n this.#inputField.textContent.length <= EntryLabelOverlay.MAX_LABEL_LENGTH) {\n return true;\n }\n\n if (allowedKeysAfterReachingLenLimit.includes(event.key)) {\n return true;\n }\n\n if (event.key.length === 1 && event.ctrlKey /* Ctrl + A for selecting all */) {\n return true;\n }\n\n event.preventDefault();\n return false;\n }\n\n #handleLabelInputPaste(event: ClipboardEvent): void {\n event.preventDefault();\n\n const clipboardData = event.clipboardData;\n if (!clipboardData || !this.#inputField) {\n return;\n }\n\n const pastedText = clipboardData.getData('text');\n\n const newText = this.#inputField.textContent + pastedText;\n const trimmedText = newText.slice(0, EntryLabelOverlay.MAX_LABEL_LENGTH + 1);\n\n this.#inputField.textContent = trimmedText;\n\n // Reset the selection to the end\n const selection = window.getSelection();\n const range = document.createRange();\n range.selectNodeContents(this.#inputField);\n range.collapse(false);\n selection?.removeAllRanges();\n selection?.addRange(range);\n }\n\n set entryLabelParams(entryLabelParams: {height: number, width: number, cutOffEntryHeight: number, chart: string}) {\n if (entryLabelParams.height === this.#entryLabelParams?.height &&\n entryLabelParams.width === this.#entryLabelParams?.width &&\n entryLabelParams.cutOffEntryHeight === this.#entryLabelParams?.cutOffEntryHeight) {\n // Even the position is not changed, the theme color might change, so we need to redraw the connector here.\n this.#drawConnector();\n return;\n }\n\n this.#entryLabelParams = entryLabelParams;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n // We need to redraw the entry wrapper only if the entry dimensions change\n this.#drawEntryHighlightWrapper();\n // The label and connector can move depending on the height of the entry\n this.#drawLabel();\n this.#drawConnector();\n }\n\n #drawConnector(): void {\n if (!this.#connectorLineContainer) {\n console.error('`connectorLineContainer` element is missing.');\n return;\n }\n\n if (this.#shouldDrawBelowEntry && this.#entryLabelParams) {\n const translation = this.#entryLabelParams.height - this.#entryLabelParams.cutOffEntryHeight +\n EntryLabelOverlay.LABEL_CONNECTOR_HEIGHT;\n\n this.#connectorLineContainer.style.transform = `translateY(${translation}px) rotate(180deg)`;\n }\n\n const connector = this.#connectorLineContainer.querySelector('line');\n const circle = this.#connectorLineContainer.querySelector('circle');\n if (!connector || !circle) {\n console.error('Some entry label elements are missing.');\n return;\n }\n // PART 2: draw the connector from label to the entry\n // Set the width of the canvas that draws the connector to be equal to the length of the shift multiplied by two.\n // That way, we can draw the connector from its corner to its middle. Since all elements are alligned in the middle, the connector\n // will end in the middle of the entry.\n this.#connectorLineContainer.setAttribute(\n 'width', (EntryLabelOverlay.LABEL_AND_CONNECTOR_SHIFT_LENGTH * 2).toString());\n this.#connectorLineContainer.setAttribute('height', EntryLabelOverlay.LABEL_CONNECTOR_HEIGHT.toString());\n // Start drawing the top right corner.\n connector.setAttribute('x1', '0');\n connector.setAttribute('y1', '0');\n // Finish drawing in middle of the connector container.\n connector.setAttribute('x2', EntryLabelOverlay.LABEL_AND_CONNECTOR_SHIFT_LENGTH.toString());\n connector.setAttribute('y2', EntryLabelOverlay.LABEL_CONNECTOR_HEIGHT.toString());\n const connectorColor = ThemeSupport.ThemeSupport.instance().getComputedValue('--color-text-primary');\n connector.setAttribute('stroke', connectorColor);\n connector.setAttribute('stroke-width', '2');\n\n // Draw the circle at the bottom of the connector\n circle.setAttribute('cx', EntryLabelOverlay.LABEL_AND_CONNECTOR_SHIFT_LENGTH.toString());\n circle.setAttribute('cy', EntryLabelOverlay.LABEL_CONNECTOR_HEIGHT.toString());\n circle.setAttribute('r', '3');\n circle.setAttribute('fill', connectorColor);\n }\n\n #drawLabel(initialLabel?: string): void {\n if (!this.#inputField || !this.#labelBox) {\n console.error('`labelBox` or `labelBox` element is missing.');\n return;\n }\n\n if (typeof initialLabel === 'string') {\n this.#inputField.innerText = initialLabel;\n }\n\n let xTranslation: number|null = null;\n let yTranslation: number|null = null;\n // PART 1: draw the label box\n if (this.#shouldDrawBelowEntry) {\n // Label is drawn below and slightly to the right.\n xTranslation = EntryLabelOverlay.LABEL_AND_CONNECTOR_SHIFT_LENGTH - EntryLabelOverlay.USER_CREATED_ICON_WIDTH / 2;\n } else {\n // If the label is drawn above, the connector goes up and to the left, so\n // we pull the label back slightly to align it nicely.\n xTranslation =\n EntryLabelOverlay.LABEL_AND_CONNECTOR_SHIFT_LENGTH * -1 - EntryLabelOverlay.USER_CREATED_ICON_WIDTH / 2;\n }\n\n if (this.#shouldDrawBelowEntry && this.#entryLabelParams) {\n // Move the label down from above the entry to below it. The label is positioned by default quite far above the entry, hence why we add:\n // 1. the height of the entry + of the label (inc its padding)\n // 2. the height of the connector (*2), so we have room to draw it\n // 3. another 4 px, because it looks nicer than if we don't have that :)\n const verticalTransform = this.#entryLabelParams.height - this.#entryLabelParams.cutOffEntryHeight +\n EntryLabelOverlay.LABEL_HEIGHT + EntryLabelOverlay.LABEL_PADDING * 2 +\n EntryLabelOverlay.LABEL_CONNECTOR_HEIGHT * 2;\n\n yTranslation = verticalTransform;\n }\n\n let transformString = '';\n if (xTranslation) {\n transformString += `translateX(${xTranslation}px) `;\n }\n if (yTranslation) {\n transformString += `translateY(${yTranslation}px)`;\n }\n\n if (transformString.length) {\n this.#labelBox.style.transform = transformString;\n }\n }\n\n #drawEntryHighlightWrapper(): void {\n if (!this.#entryHighlightWrapper || !this.#entryLabelParams || !this.#inputField || !this.#connectorLineContainer) {\n console.error('Some elements required to draw `entryHighlightWrapper` are missing.');\n return;\n }\n\n const {height, width, cutOffEntryHeight} = this.#entryLabelParams;\n\n // If part of the entry is hidden by the resizer in the main chart, it is hidden from the top.\n // Therefore, set the bottom border to hidden and hide the label and connector parts of the label.\n // If it's partly hidden in the network chart, it's hidden from the bottom. In that case, hide the bottom border.\n if (this.#entryIsInMainChart) {\n this.#entryHighlightWrapper.style.borderTopWidth = cutOffEntryHeight > 0 ? '0' : '2px';\n } else {\n this.#entryHighlightWrapper.style.borderBottomWidth = cutOffEntryHeight > 0 ? '0' : '2px';\n }\n\n // PART 3: draw the box that highlights the entry with a label\n this.#entryHighlightWrapper.style.height = `${height - cutOffEntryHeight}px`;\n this.#entryHighlightWrapper.style.width = `${width}px`;\n\n // If the label is editable, focus cursor on it.\n // This method needs to be called after rendering the wrapper because it is the last label overlay element to render.\n // By doing this, the cursor focuses when the label is created.\n if (this.#isLabelEditable) {\n this.#focusInputBox();\n }\n }\n\n #focusInputBox(): void {\n if (!this.#inputField) {\n console.error('`labelBox` element is missing.');\n return;\n }\n this.#inputField.focus();\n }\n\n setLabelEditabilityAndRemoveEmptyLabel(editable: boolean): void {\n this.#isLabelEditable = editable;\n this.#render();\n // If the label is editable, focus cursor on it\n if (editable) {\n this.#focusInputBox();\n }\n // If the label is empty when it is being navigated away from, dispatch an event to remove this entry overlay\n if (!editable && this.#inputField?.innerText.length === 0) {\n this.dispatchEvent(new EmptyEntryLabelRemoveEvent());\n }\n }\n\n #render(): void {\n // clang-format off\n LitHtml.render(\n LitHtml.html`\n \n
    \n <${IconButton.Icon.Icon.litTagName} class='user-created-icon' name='profile'>\n \n this.setLabelEditabilityAndRemoveEmptyLabel(true)}\n @blur=${() => this.setLabelEditabilityAndRemoveEmptyLabel(false)}\n @keydown=${this.#handleLabelInputKeyDown}\n @paste=${this.#handleLabelInputPaste}\n @keyup=${this.#handleLabelInputKeyUp}\n contenteditable=${this.#isLabelEditable ? 'plaintext-only' : false}>\n \n
    \n \n \n \n \n
    \n `,\n this.#shadow, {host: this});\n // clang-format on\n }\n}\n\ncustomElements.define('devtools-entry-label-overlay', EntryLabelOverlay);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-entry-label-overlay': EntryLabelOverlay;\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/overlays/components/TimeRangeOverlay.d.ts b/public/panels/timeline/overlays/components/TimeRangeOverlay.d.ts index 68cab371e..1e7296d5b 100644 --- a/public/panels/timeline/overlays/components/TimeRangeOverlay.d.ts +++ b/public/panels/timeline/overlays/components/TimeRangeOverlay.d.ts @@ -1,4 +1,4 @@ -import type * as TraceEngine from '../../../../models/trace/trace.js'; +import type * as Trace from '../../../../models/trace/trace.js'; export declare class TimeRangeLabelChangeEvent extends Event { newLabel: string; static readonly eventName = "timerangelabelchange"; @@ -14,14 +14,14 @@ export declare class TimeRangeOverlay extends HTMLElement { connectedCallback(): void; constructor(initialLabel: string); set canvasRect(rect: DOMRect | null); - set duration(duration: TraceEngine.Types.Timing.MicroSeconds | null); + set duration(duration: Trace.Types.Timing.MicroSeconds | null); /** * We use this method after the overlay has been positioned in order to move * the label as required to keep it on screen. * If the label is off to the left or right, we fix it to that corner and * align the text so the label is visible as long as possible. */ - afterOverlayUpdate(): void; + updateLabelPositioning(): void; } declare global { interface HTMLElementTagNameMap { diff --git a/public/panels/timeline/overlays/components/TimeRangeOverlay.js b/public/panels/timeline/overlays/components/TimeRangeOverlay.js index 1178cd9dc..e0146592f 100644 --- a/public/panels/timeline/overlays/components/TimeRangeOverlay.js +++ b/public/panels/timeline/overlays/components/TimeRangeOverlay.js @@ -6,6 +6,14 @@ import * as ComponentHelpers from '../../../../ui/components/helpers/helpers.js' import * as IconButton from '../../../../ui/components/icon_button/icon_button.js'; import * as LitHtml from '../../../../ui/lit-html/lit-html.js'; import styles from './timeRangeOverlay.css.js'; +const UIStrings = { + /** + *@description Accessible label used to explain to a user that they are viewing an entry label. + */ + timeRange: 'Time range', +}; +const str_ = i18n.i18n.registerUIStrings('panels/timeline/overlays/components/TimeRangeOverlay.ts', UIStrings); +const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); export class TimeRangeLabelChangeEvent extends Event { newLabel; static eventName = 'timerangelabelchange'; @@ -46,8 +54,21 @@ export class TimeRangeOverlay extends HTMLElement { return; } this.#labelBox.innerText = initialLabel; + if (initialLabel) { + this.#labelBox?.setAttribute('aria-label', initialLabel); + // To construct a time range with a predefined label, it must have been + // loaded from the trace file. In this case we do not want it to default + // to editable. + this.#setLabelEditability(false); + } } set canvasRect(rect) { + if (rect === null) { + return; + } + if (this.#canvasRect && this.#canvasRect.width === rect.width && this.#canvasRect.height === rect.height) { + return; + } this.#canvasRect = rect; void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender); } @@ -81,7 +102,7 @@ export class TimeRangeOverlay extends HTMLElement { * If the label is off to the left or right, we fix it to that corner and * align the text so the label is visible as long as possible. */ - afterOverlayUpdate() { + updateLabelPositioning() { if (!this.#rangeContainer) { return; } @@ -171,6 +192,7 @@ export class TimeRangeOverlay extends HTMLElement { if (labelBoxTextContent !== this.#label) { this.#label = labelBoxTextContent; this.dispatchEvent(new TimeRangeLabelChangeEvent(this.#label)); + this.#labelBox?.setAttribute('aria-label', labelBoxTextContent); } } #handleLabelInputKeyDown(event) { @@ -195,28 +217,26 @@ export class TimeRangeOverlay extends HTMLElement { const durationText = this.#duration ? i18n.TimeUtilities.formatMicroSecondsTime(this.#duration) : ''; // clang-format off LitHtml.render(LitHtml.html ` - - <${IconButton.Icon.Icon.litTagName} class="user-created-icon" .data=${{ - iconName: 'profile', - color: 'var(--ref-palette-pink55)', - width: '16px', - height: '17px', - }}> - + + <${IconButton.Icon.Icon.litTagName} class="user-created-icon" name='profile'}> + this.#setLabelEditability(false)} @dblclick=${() => this.#setLabelEditability(true)} @keydown=${this.#handleLabelInputKeyDown} @keyup=${this.#handleLabelInputKeyUp} - contenteditable=${this.#isLabelEditable}> + contenteditable=${this.#isLabelEditable ? 'plaintext-only' : false}> ${durationText} `, this.#shadow, { host: this }); // clang-format on + // Now we have rendered, we need to re-run the code to tweak the margin & + // positioning of the label. + this.updateLabelPositioning(); } } customElements.define('devtools-time-range-overlay', TimeRangeOverlay); diff --git a/public/panels/timeline/overlays/components/TimeRangeOverlay.js.map b/public/panels/timeline/overlays/components/TimeRangeOverlay.js.map index 8f0935962..cde302069 100644 --- a/public/panels/timeline/overlays/components/TimeRangeOverlay.js.map +++ b/public/panels/timeline/overlays/components/TimeRangeOverlay.js.map @@ -1 +1 @@ -{"version":3,"file":"TimeRangeOverlay.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/overlays/components/TimeRangeOverlay.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport type * as TraceEngine from '../../../../models/trace/trace.js';\nimport * as ComponentHelpers from '../../../../ui/components/helpers/helpers.js';\nimport * as IconButton from '../../../../ui/components/icon_button/icon_button.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\n\nimport styles from './timeRangeOverlay.css.js';\n\nexport class TimeRangeLabelChangeEvent extends Event {\n static readonly eventName = 'timerangelabelchange';\n\n constructor(public newLabel: string) {\n super(TimeRangeLabelChangeEvent.eventName);\n }\n}\n\nexport class TimeRangeRemoveEvent extends Event {\n static readonly eventName = 'timerangeremoveevent';\n\n constructor() {\n super(TimeRangeRemoveEvent.eventName);\n }\n}\n\nexport class TimeRangeOverlay extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-time-range-overlay`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n readonly #boundRender = this.#render.bind(this);\n #duration: TraceEngine.Types.Timing.MicroSeconds|null = null;\n #canvasRect: DOMRect|null = null;\n #label: string;\n\n // The label is set to editable and in focus anytime the label is empty and when the label it is double clicked.\n // If the user clicks away from the selected range element and the label is not empty, the lable is set to not editable until it is double clicked.\n #isLabelEditable: boolean = true;\n\n #rangeContainer: HTMLElement|null = null;\n #labelBox: HTMLElement|null = null;\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [styles];\n }\n\n constructor(initialLabel: string) {\n super();\n this.#render();\n this.#rangeContainer = this.#shadow.querySelector('.range-container');\n this.#labelBox = this.#rangeContainer?.querySelector('.label-text') ?? null;\n this.#label = initialLabel;\n if (!this.#labelBox) {\n console.error('`labelBox` element is missing.');\n return;\n }\n this.#labelBox.innerText = initialLabel;\n }\n\n set canvasRect(rect: DOMRect|null) {\n this.#canvasRect = rect;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n set duration(duration: TraceEngine.Types.Timing.MicroSeconds|null) {\n if (duration === this.#duration) {\n return;\n }\n this.#duration = duration;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n /**\n * This calculates how much of the time range is in the user's view. This is\n * used to determine how much of the label can fit into the view, and if we\n * should even show the label.\n */\n #visibleOverlayWidth(overlayRect: DOMRect): number {\n if (!this.#canvasRect) {\n return 0;\n }\n\n const {x: overlayStartX, width} = overlayRect;\n const overlayEndX = overlayStartX + width;\n\n const canvasStartX = this.#canvasRect.x;\n const canvasEndX = this.#canvasRect.x + this.#canvasRect.width;\n\n const leftVisible = Math.max(canvasStartX, overlayStartX);\n const rightVisible = Math.min(canvasEndX, overlayEndX);\n return rightVisible - leftVisible;\n }\n\n /**\n * We use this method after the overlay has been positioned in order to move\n * the label as required to keep it on screen.\n * If the label is off to the left or right, we fix it to that corner and\n * align the text so the label is visible as long as possible.\n */\n afterOverlayUpdate(): void {\n if (!this.#rangeContainer) {\n return;\n }\n\n if (!this.#canvasRect) {\n return;\n }\n\n // On the RHS of the panel a scrollbar can be shown which means the canvas\n // has a 9px gap on the right hand edge. We use this value when calculating\n // values and label positioning from the left hand side in order to be\n // consistent on both edges of the UI.\n const paddingForScrollbar = 9;\n\n const overlayRect = this.getBoundingClientRect();\n const labelRect = this.#rangeContainer.getBoundingClientRect();\n const visibleOverlayWidth = this.#visibleOverlayWidth(overlayRect) - paddingForScrollbar;\n const overlayTooNarrow = visibleOverlayWidth <= labelRect.width - paddingForScrollbar;\n this.#rangeContainer.classList.toggle('labelHidden', overlayTooNarrow);\n\n if (overlayTooNarrow) {\n // Label is invisible, no need to do all the layout.\n return;\n }\n\n // Check if label is off the LHS of the screen.\n const labelLeftMarginToCenter = (overlayRect.width - labelRect.width) / 2;\n const newLabelX = overlayRect.x + labelLeftMarginToCenter;\n\n const labelOffLeftOfScreen = newLabelX < this.#canvasRect.x;\n this.#rangeContainer.classList.toggle('offScreenLeft', labelOffLeftOfScreen);\n\n // Check if label is off the RHS of the screen\n const rightBound = this.#canvasRect.x + this.#canvasRect.width;\n // The label's right hand edge is the gap from the left of the range to the\n // label, and then the width of the label.\n const labelRightEdge = overlayRect.x + labelLeftMarginToCenter + labelRect.width;\n const labelOffRightOfScreen = labelRightEdge > rightBound;\n this.#rangeContainer.classList.toggle('offScreenRight', labelOffRightOfScreen);\n\n if (labelOffLeftOfScreen) {\n // If the label is off the left of the screen, we adjust by the\n // difference between the X that represents the start of the cavnas, and\n // the X that represents the start of the overlay.\n // We then take the absolute value of this - because if the canvas starts\n // at 0, and the overlay is -200px, we have to adjust the label by +200.\n // Add on 9 pixels to pad from the left; this is the width of the sidebar\n // on the RHS so we match it so the label is equally padded on either\n // side.\n this.#rangeContainer.style.marginLeft = `${Math.abs(this.#canvasRect.x - overlayRect.x) + paddingForScrollbar}px`;\n } else if (labelOffRightOfScreen) {\n // To calculate how far left to push the label, we take the right hand\n // bound (the canvas width and subtract the label's width).\n // Finally, we subtract the X position of the overlay (if the overlay is\n // 200px within the view, we don't need to push the label that 200px too\n // otherwise it will be off-screen)\n const leftMargin = rightBound - labelRect.width - overlayRect.x;\n\n this.#rangeContainer.style.marginLeft = `${leftMargin}px`;\n\n } else {\n // Keep the label central.\n this.#rangeContainer.style.marginLeft = `${labelLeftMarginToCenter}px`;\n }\n\n // If the text is empty, set the label editibility to true.\n // Only allow to remove the focus and save the range as annotation if the label is not empty.\n if (this.#labelBox?.innerText === '') {\n this.#setLabelEditability(true);\n }\n }\n\n #focusInputBox(): void {\n if (!this.#labelBox) {\n console.error('`labelBox` element is missing.');\n return;\n }\n this.#labelBox.focus();\n }\n\n #setLabelEditability(editable: boolean): void {\n // Always keep focus on the label input field if the label is empty.\n // TODO: Do not remove a range that is being navigated away from if the label is not empty\n if (this.#labelBox?.innerText === '') {\n this.#focusInputBox();\n return;\n }\n this.#isLabelEditable = editable;\n this.#render();\n // If the label is editable, focus cursor on it\n if (editable) {\n this.#focusInputBox();\n }\n }\n\n #handleLabelInputKeyUp(): void {\n // If the label changed on key up, dispatch label changed event\n const labelBoxTextContent = this.#labelBox?.textContent ?? '';\n if (labelBoxTextContent !== this.#label) {\n this.#label = labelBoxTextContent;\n this.dispatchEvent(new TimeRangeLabelChangeEvent(this.#label));\n }\n }\n\n #handleLabelInputKeyDown(event: KeyboardEvent): boolean {\n // If the new key is `Enter` or `Escape` key, treat it\n // as the end of the label input and blur the input field.\n // If the text field is empty when `Enter` or `Escape` are pressed,\n // dispatch an event to remove the time range.\n if (event.key === 'Enter' || event.key === 'Escape') {\n // In DevTools, the `Escape` button will by default toggle the console\n // drawer, which we don't want here, so we need to call\n // `stopPropagation()`.\n event.stopPropagation();\n if (this.#label === '') {\n this.dispatchEvent(new TimeRangeRemoveEvent());\n }\n this.#labelBox?.blur();\n return false;\n }\n\n return true;\n }\n\n #render(): void {\n const durationText = this.#duration ? i18n.TimeUtilities.formatMicroSecondsTime(this.#duration) : '';\n // clang-format off\n LitHtml.render(\n LitHtml.html`\n \n <${IconButton.Icon.Icon.litTagName} class=\"user-created-icon\" .data=${{\n iconName: 'profile',\n color: 'var(--ref-palette-pink55)',\n width: '16px',\n height: '17px',\n } as IconButton.Icon.IconData}>\n \n this.#setLabelEditability(false)}\n @dblclick=${() => this.#setLabelEditability(true)}\n @keydown=${this.#handleLabelInputKeyDown}\n @keyup=${this.#handleLabelInputKeyUp}\n contenteditable=${this.#isLabelEditable}>\n \n ${durationText}\n \n `,\n this.#shadow, {host: this});\n // clang-format on\n }\n}\n\ncustomElements.define('devtools-time-range-overlay', TimeRangeOverlay);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-time-range-overlay': TimeRangeOverlay;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"TimeRangeOverlay.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/overlays/components/TimeRangeOverlay.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAC7B,OAAO,KAAK,IAAI,MAAM,+BAA+B,CAAC;AAEtD,OAAO,KAAK,gBAAgB,MAAM,8CAA8C,CAAC;AACjF,OAAO,KAAK,UAAU,MAAM,sDAAsD,CAAC;AACnF,OAAO,KAAK,OAAO,MAAM,qCAAqC,CAAC;AAE/D,OAAO,MAAM,MAAM,2BAA2B,CAAC;AAE/C,MAAM,SAAS,GAAG;IAChB;;OAEG;IACH,SAAS,EAAE,YAAY;CACxB,CAAC;AACF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,yDAAyD,EAAE,SAAS,CAAC,CAAC;AAC/G,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAEtE,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IAG/B;IAFnB,MAAM,CAAU,SAAS,GAAG,sBAAsB,CAAC;IAEnD,YAAmB,QAAgB;QACjC,KAAK,CAAC,yBAAyB,CAAC,SAAS,CAAC,CAAC;QAD1B,aAAQ,GAAR,QAAQ,CAAQ;IAEnC,CAAC;;AAGH,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAC7C,MAAM,CAAU,SAAS,GAAG,sBAAsB,CAAC;IAEnD;QACE,KAAK,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC;IACxC,CAAC;;AAGH,MAAM,OAAO,gBAAiB,SAAQ,WAAW;IAC/C,MAAM,CAAU,UAAU,GAAG,OAAO,CAAC,OAAO,CAAA,6BAA6B,CAAC;IACjE,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,EAAC,IAAI,EAAE,MAAM,EAAC,CAAC,CAAC;IAC5C,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChD,SAAS,GAAyC,IAAI,CAAC;IACvD,WAAW,GAAiB,IAAI,CAAC;IACjC,MAAM,CAAS;IAEf,gHAAgH;IAChH,mJAAmJ;IACnJ,gBAAgB,GAAY,IAAI,CAAC;IAEjC,eAAe,GAAqB,IAAI,CAAC;IACzC,SAAS,GAAqB,IAAI,CAAC;IAEnC,iBAAiB;QACf,IAAI,CAAC,OAAO,CAAC,kBAAkB,GAAG,CAAC,MAAM,CAAC,CAAC;IAC7C,CAAC;IAED,YAAY,YAAoB;QAC9B,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAc,kBAAkB,CAAC,CAAC;QACnF,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,eAAe,EAAE,aAAa,CAAc,aAAa,CAAC,IAAI,IAAI,CAAC;QACzF,IAAI,CAAC,MAAM,GAAG,YAAY,CAAC;QAC3B,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;YAChD,OAAO;QACT,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,SAAS,GAAG,YAAY,CAAC;QACxC,IAAI,YAAY,EAAE,CAAC;YACjB,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;YACzD,uEAAuE;YACvE,wEAAwE;YACxE,eAAe;YACf,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC;QACnC,CAAC;IACH,CAAC;IAED,IAAI,UAAU,CAAC,IAAkB;QAC/B,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,OAAO;QACT,CAAC;QACD,IAAI,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,WAAW,CAAC,KAAK,KAAK,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;YACzG,OAAO;QACT,CAAC;QACD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QACxB,KAAK,gBAAgB,CAAC,eAAe,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IAChF,CAAC;IAED,IAAI,QAAQ,CAAC,QAA8C;QACzD,IAAI,QAAQ,KAAK,IAAI,CAAC,SAAS,EAAE,CAAC;YAChC,OAAO;QACT,CAAC;QACD,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;QAC1B,KAAK,gBAAgB,CAAC,eAAe,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IAChF,CAAC;IAED;;;;OAIG;IACH,oBAAoB,CAAC,WAAoB;QACvC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,OAAO,CAAC,CAAC;QACX,CAAC;QAED,MAAM,EAAC,CAAC,EAAE,aAAa,EAAE,KAAK,EAAC,GAAG,WAAW,CAAC;QAC9C,MAAM,WAAW,GAAG,aAAa,GAAG,KAAK,CAAC;QAE1C,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;QACxC,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;QAE/D,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC;QAC1D,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;QACvD,OAAO,YAAY,GAAG,WAAW,CAAC;IACpC,CAAC;IAED;;;;;OAKG;IACH,sBAAsB;QACpB,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;YAC1B,OAAO;QACT,CAAC;QAED,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QAED,0EAA0E;QAC1E,2EAA2E;QAC3E,sEAAsE;QACtE,sCAAsC;QACtC,MAAM,mBAAmB,GAAG,CAAC,CAAC;QAE9B,MAAM,WAAW,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAC;QACjD,MAAM,SAAS,GAAG,IAAI,CAAC,eAAe,CAAC,qBAAqB,EAAE,CAAC;QAC/D,MAAM,mBAAmB,GAAG,IAAI,CAAC,oBAAoB,CAAC,WAAW,CAAC,GAAG,mBAAmB,CAAC;QACzF,MAAM,gBAAgB,GAAG,mBAAmB,IAAI,SAAS,CAAC,KAAK,GAAG,mBAAmB,CAAC;QACtF,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;QAEvE,IAAI,gBAAgB,EAAE,CAAC;YACrB,oDAAoD;YACpD,OAAO;QACT,CAAC;QAED,+CAA+C;QAC/C,MAAM,uBAAuB,GAAG,CAAC,WAAW,CAAC,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC1E,MAAM,SAAS,GAAG,WAAW,CAAC,CAAC,GAAG,uBAAuB,CAAC;QAE1D,MAAM,oBAAoB,GAAG,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;QAC5D,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,MAAM,CAAC,eAAe,EAAE,oBAAoB,CAAC,CAAC;QAE7E,8CAA8C;QAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;QAC/D,2EAA2E;QAC3E,0CAA0C;QAC1C,MAAM,cAAc,GAAG,WAAW,CAAC,CAAC,GAAG,uBAAuB,GAAG,SAAS,CAAC,KAAK,CAAC;QACjF,MAAM,qBAAqB,GAAG,cAAc,GAAG,UAAU,CAAC;QAC1D,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,MAAM,CAAC,gBAAgB,EAAE,qBAAqB,CAAC,CAAC;QAE/E,IAAI,oBAAoB,EAAE,CAAC;YACzB,+DAA+D;YAC/D,wEAAwE;YACxE,kDAAkD;YAClD,yEAAyE;YACzE,wEAAwE;YACxE,yEAAyE;YACzE,qEAAqE;YACrE,QAAQ;YACR,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,UAAU,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,mBAAmB,IAAI,CAAC;QACpH,CAAC;aAAM,IAAI,qBAAqB,EAAE,CAAC;YACjC,sEAAsE;YACtE,2DAA2D;YAC3D,wEAAwE;YACxE,wEAAwE;YACxE,mCAAmC;YACnC,MAAM,UAAU,GAAG,UAAU,GAAG,SAAS,CAAC,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC;YAEhE,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,UAAU,GAAG,GAAG,UAAU,IAAI,CAAC;QAE5D,CAAC;aAAM,CAAC;YACN,0BAA0B;YAC1B,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,UAAU,GAAG,GAAG,uBAAuB,IAAI,CAAC;QACzE,CAAC;QAED,2DAA2D;QAC3D,6FAA6F;QAC7F,IAAI,IAAI,CAAC,SAAS,EAAE,SAAS,KAAK,EAAE,EAAE,CAAC;YACrC,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC;IACH,CAAC;IAED,cAAc;QACZ,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;YAChD,OAAO;QACT,CAAC;QACD,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;IACzB,CAAC;IAED,oBAAoB,CAAC,QAAiB;QACpC,oEAAoE;QACpE,0FAA0F;QAC1F,IAAI,IAAI,CAAC,SAAS,EAAE,SAAS,KAAK,EAAE,EAAE,CAAC;YACrC,IAAI,CAAC,cAAc,EAAE,CAAC;YACtB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,gBAAgB,GAAG,QAAQ,CAAC;QACjC,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,+CAA+C;QAC/C,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,CAAC,cAAc,EAAE,CAAC;QACxB,CAAC;IACH,CAAC;IAED,sBAAsB;QACpB,+DAA+D;QAC/D,MAAM,mBAAmB,GAAG,IAAI,CAAC,SAAS,EAAE,WAAW,IAAI,EAAE,CAAC;QAC9D,IAAI,mBAAmB,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;YACxC,IAAI,CAAC,MAAM,GAAG,mBAAmB,CAAC;YAClC,IAAI,CAAC,aAAa,CAAC,IAAI,yBAAyB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;YAC/D,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,YAAY,EAAE,mBAAmB,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;IAED,wBAAwB,CAAC,KAAoB;QAC3C,sDAAsD;QACtD,0DAA0D;QAC1D,mEAAmE;QACnE,8CAA8C;QAC9C,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;YACpD,sEAAsE;YACtE,uDAAuD;YACvD,uBAAuB;YACvB,KAAK,CAAC,eAAe,EAAE,CAAC;YACxB,IAAI,IAAI,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;gBACvB,IAAI,CAAC,aAAa,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC;YACjD,CAAC;YACD,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC;YACvB,OAAO,KAAK,CAAC;QACf,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,sBAAsB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACrG,mBAAmB;QACnB,OAAO,CAAC,MAAM,CACV,OAAO,CAAC,IAAI,CAAA;mEAC+C,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC;eACnF,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU;gBAC9B,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU;;;;yBAItB,GAAG,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,KAAK,CAAC;yBACtC,GAAG,EAAE,CAAC,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC;wBACtC,IAAI,CAAC,wBAAwB;sBAC/B,IAAI,CAAC,sBAAsB;+BAClB,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,KAAK;;;+BAGhD,YAAY;;WAEhC,EACH,IAAI,CAAC,OAAO,EAAE,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC,CAAC;QAChC,kBAAkB;QAElB,yEAAyE;QACzE,4BAA4B;QAC5B,IAAI,CAAC,sBAAsB,EAAE,CAAC;IAChC,CAAC;;AAGH,cAAc,CAAC,MAAM,CAAC,6BAA6B,EAAE,gBAAgB,CAAC,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport type * as Trace from '../../../../models/trace/trace.js';\nimport * as ComponentHelpers from '../../../../ui/components/helpers/helpers.js';\nimport * as IconButton from '../../../../ui/components/icon_button/icon_button.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\n\nimport styles from './timeRangeOverlay.css.js';\n\nconst UIStrings = {\n /**\n *@description Accessible label used to explain to a user that they are viewing an entry label.\n */\n timeRange: 'Time range',\n};\nconst str_ = i18n.i18n.registerUIStrings('panels/timeline/overlays/components/TimeRangeOverlay.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport class TimeRangeLabelChangeEvent extends Event {\n static readonly eventName = 'timerangelabelchange';\n\n constructor(public newLabel: string) {\n super(TimeRangeLabelChangeEvent.eventName);\n }\n}\n\nexport class TimeRangeRemoveEvent extends Event {\n static readonly eventName = 'timerangeremoveevent';\n\n constructor() {\n super(TimeRangeRemoveEvent.eventName);\n }\n}\n\nexport class TimeRangeOverlay extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-time-range-overlay`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n readonly #boundRender = this.#render.bind(this);\n #duration: Trace.Types.Timing.MicroSeconds|null = null;\n #canvasRect: DOMRect|null = null;\n #label: string;\n\n // The label is set to editable and in focus anytime the label is empty and when the label it is double clicked.\n // If the user clicks away from the selected range element and the label is not empty, the lable is set to not editable until it is double clicked.\n #isLabelEditable: boolean = true;\n\n #rangeContainer: HTMLElement|null = null;\n #labelBox: HTMLElement|null = null;\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [styles];\n }\n\n constructor(initialLabel: string) {\n super();\n this.#render();\n this.#rangeContainer = this.#shadow.querySelector('.range-container');\n this.#labelBox = this.#rangeContainer?.querySelector('.label-text') ?? null;\n this.#label = initialLabel;\n if (!this.#labelBox) {\n console.error('`labelBox` element is missing.');\n return;\n }\n this.#labelBox.innerText = initialLabel;\n if (initialLabel) {\n this.#labelBox?.setAttribute('aria-label', initialLabel);\n // To construct a time range with a predefined label, it must have been\n // loaded from the trace file. In this case we do not want it to default\n // to editable.\n this.#setLabelEditability(false);\n }\n }\n\n set canvasRect(rect: DOMRect|null) {\n if (rect === null) {\n return;\n }\n if (this.#canvasRect && this.#canvasRect.width === rect.width && this.#canvasRect.height === rect.height) {\n return;\n }\n this.#canvasRect = rect;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n set duration(duration: Trace.Types.Timing.MicroSeconds|null) {\n if (duration === this.#duration) {\n return;\n }\n this.#duration = duration;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n /**\n * This calculates how much of the time range is in the user's view. This is\n * used to determine how much of the label can fit into the view, and if we\n * should even show the label.\n */\n #visibleOverlayWidth(overlayRect: DOMRect): number {\n if (!this.#canvasRect) {\n return 0;\n }\n\n const {x: overlayStartX, width} = overlayRect;\n const overlayEndX = overlayStartX + width;\n\n const canvasStartX = this.#canvasRect.x;\n const canvasEndX = this.#canvasRect.x + this.#canvasRect.width;\n\n const leftVisible = Math.max(canvasStartX, overlayStartX);\n const rightVisible = Math.min(canvasEndX, overlayEndX);\n return rightVisible - leftVisible;\n }\n\n /**\n * We use this method after the overlay has been positioned in order to move\n * the label as required to keep it on screen.\n * If the label is off to the left or right, we fix it to that corner and\n * align the text so the label is visible as long as possible.\n */\n updateLabelPositioning(): void {\n if (!this.#rangeContainer) {\n return;\n }\n\n if (!this.#canvasRect) {\n return;\n }\n\n // On the RHS of the panel a scrollbar can be shown which means the canvas\n // has a 9px gap on the right hand edge. We use this value when calculating\n // values and label positioning from the left hand side in order to be\n // consistent on both edges of the UI.\n const paddingForScrollbar = 9;\n\n const overlayRect = this.getBoundingClientRect();\n const labelRect = this.#rangeContainer.getBoundingClientRect();\n const visibleOverlayWidth = this.#visibleOverlayWidth(overlayRect) - paddingForScrollbar;\n const overlayTooNarrow = visibleOverlayWidth <= labelRect.width - paddingForScrollbar;\n this.#rangeContainer.classList.toggle('labelHidden', overlayTooNarrow);\n\n if (overlayTooNarrow) {\n // Label is invisible, no need to do all the layout.\n return;\n }\n\n // Check if label is off the LHS of the screen.\n const labelLeftMarginToCenter = (overlayRect.width - labelRect.width) / 2;\n const newLabelX = overlayRect.x + labelLeftMarginToCenter;\n\n const labelOffLeftOfScreen = newLabelX < this.#canvasRect.x;\n this.#rangeContainer.classList.toggle('offScreenLeft', labelOffLeftOfScreen);\n\n // Check if label is off the RHS of the screen\n const rightBound = this.#canvasRect.x + this.#canvasRect.width;\n // The label's right hand edge is the gap from the left of the range to the\n // label, and then the width of the label.\n const labelRightEdge = overlayRect.x + labelLeftMarginToCenter + labelRect.width;\n const labelOffRightOfScreen = labelRightEdge > rightBound;\n this.#rangeContainer.classList.toggle('offScreenRight', labelOffRightOfScreen);\n\n if (labelOffLeftOfScreen) {\n // If the label is off the left of the screen, we adjust by the\n // difference between the X that represents the start of the cavnas, and\n // the X that represents the start of the overlay.\n // We then take the absolute value of this - because if the canvas starts\n // at 0, and the overlay is -200px, we have to adjust the label by +200.\n // Add on 9 pixels to pad from the left; this is the width of the sidebar\n // on the RHS so we match it so the label is equally padded on either\n // side.\n this.#rangeContainer.style.marginLeft = `${Math.abs(this.#canvasRect.x - overlayRect.x) + paddingForScrollbar}px`;\n } else if (labelOffRightOfScreen) {\n // To calculate how far left to push the label, we take the right hand\n // bound (the canvas width and subtract the label's width).\n // Finally, we subtract the X position of the overlay (if the overlay is\n // 200px within the view, we don't need to push the label that 200px too\n // otherwise it will be off-screen)\n const leftMargin = rightBound - labelRect.width - overlayRect.x;\n\n this.#rangeContainer.style.marginLeft = `${leftMargin}px`;\n\n } else {\n // Keep the label central.\n this.#rangeContainer.style.marginLeft = `${labelLeftMarginToCenter}px`;\n }\n\n // If the text is empty, set the label editibility to true.\n // Only allow to remove the focus and save the range as annotation if the label is not empty.\n if (this.#labelBox?.innerText === '') {\n this.#setLabelEditability(true);\n }\n }\n\n #focusInputBox(): void {\n if (!this.#labelBox) {\n console.error('`labelBox` element is missing.');\n return;\n }\n this.#labelBox.focus();\n }\n\n #setLabelEditability(editable: boolean): void {\n // Always keep focus on the label input field if the label is empty.\n // TODO: Do not remove a range that is being navigated away from if the label is not empty\n if (this.#labelBox?.innerText === '') {\n this.#focusInputBox();\n return;\n }\n this.#isLabelEditable = editable;\n this.#render();\n // If the label is editable, focus cursor on it\n if (editable) {\n this.#focusInputBox();\n }\n }\n\n #handleLabelInputKeyUp(): void {\n // If the label changed on key up, dispatch label changed event\n const labelBoxTextContent = this.#labelBox?.textContent ?? '';\n if (labelBoxTextContent !== this.#label) {\n this.#label = labelBoxTextContent;\n this.dispatchEvent(new TimeRangeLabelChangeEvent(this.#label));\n this.#labelBox?.setAttribute('aria-label', labelBoxTextContent);\n }\n }\n\n #handleLabelInputKeyDown(event: KeyboardEvent): boolean {\n // If the new key is `Enter` or `Escape` key, treat it\n // as the end of the label input and blur the input field.\n // If the text field is empty when `Enter` or `Escape` are pressed,\n // dispatch an event to remove the time range.\n if (event.key === 'Enter' || event.key === 'Escape') {\n // In DevTools, the `Escape` button will by default toggle the console\n // drawer, which we don't want here, so we need to call\n // `stopPropagation()`.\n event.stopPropagation();\n if (this.#label === '') {\n this.dispatchEvent(new TimeRangeRemoveEvent());\n }\n this.#labelBox?.blur();\n return false;\n }\n\n return true;\n }\n\n #render(): void {\n const durationText = this.#duration ? i18n.TimeUtilities.formatMicroSecondsTime(this.#duration) : '';\n // clang-format off\n LitHtml.render(\n LitHtml.html`\n \n <${IconButton.Icon.Icon.litTagName} class=\"user-created-icon\" name='profile'}>\n \n this.#setLabelEditability(false)}\n @dblclick=${() => this.#setLabelEditability(true)}\n @keydown=${this.#handleLabelInputKeyDown}\n @keyup=${this.#handleLabelInputKeyUp}\n contenteditable=${this.#isLabelEditable ? 'plaintext-only' : false}>\n \n ${durationText}\n \n `,\n this.#shadow, {host: this});\n // clang-format on\n\n // Now we have rendered, we need to re-run the code to tweak the margin &\n // positioning of the label.\n this.updateLabelPositioning();\n }\n}\n\ncustomElements.define('devtools-time-range-overlay', TimeRangeOverlay);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-time-range-overlay': TimeRangeOverlay;\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/overlays/components/TimespanBreakdownOverlay.d.ts b/public/panels/timeline/overlays/components/TimespanBreakdownOverlay.d.ts index ebd35fc91..aa1fa5e2e 100644 --- a/public/panels/timeline/overlays/components/TimespanBreakdownOverlay.d.ts +++ b/public/panels/timeline/overlays/components/TimespanBreakdownOverlay.d.ts @@ -1,10 +1,10 @@ -import * as TraceEngine from '../../../../models/trace/trace.js'; +import * as Trace from '../../../../models/trace/trace.js'; import * as LitHtml from '../../../../ui/lit-html/lit-html.js'; /** * An EntryBreakdown, or section, that makes up a TimespanBreakdown. */ export type EntryBreakdown = { - bounds: TraceEngine.Types.Timing.TraceWindowMicroSeconds; + bounds: Trace.Types.Timing.TraceWindowMicroSeconds; label: string | LitHtml.LitTemplate; showDuration: boolean; }; @@ -24,7 +24,7 @@ export declare class TimespanBreakdownOverlay extends HTMLElement { * If the label is off to the left or right, we fix it to that corner and * align the text so the label is visible as long as possible. */ - afterOverlayUpdate(): void; + checkSectionLabelPositioning(): void; renderSection(section: EntryBreakdown): LitHtml.TemplateResult; } declare global { diff --git a/public/panels/timeline/overlays/components/TimespanBreakdownOverlay.js b/public/panels/timeline/overlays/components/TimespanBreakdownOverlay.js index e655733a5..8b268d0a0 100644 --- a/public/panels/timeline/overlays/components/TimespanBreakdownOverlay.js +++ b/public/panels/timeline/overlays/components/TimespanBreakdownOverlay.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as i18n from '../../../../core/i18n/i18n.js'; -import * as TraceEngine from '../../../../models/trace/trace.js'; +import * as Trace from '../../../../models/trace/trace.js'; import * as ComponentHelpers from '../../../../ui/components/helpers/helpers.js'; import * as LitHtml from '../../../../ui/lit-html/lit-html.js'; import styles from './timespanBreakdownOverlay.css.js'; @@ -21,6 +21,9 @@ export class TimespanBreakdownOverlay extends HTMLElement { this.#render(); } set canvasRect(rect) { + if (this.#canvasRect && rect && this.#canvasRect.width === rect.width && this.#canvasRect.height === rect.height) { + return; + } this.#canvasRect = rect; void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender); } @@ -37,7 +40,7 @@ export class TimespanBreakdownOverlay extends HTMLElement { * If the label is off to the left or right, we fix it to that corner and * align the text so the label is visible as long as possible. */ - afterOverlayUpdate() { + checkSectionLabelPositioning() { const sections = this.#shadow.querySelectorAll('.timespan-breakdown-overlay-section'); if (!sections) { return; @@ -122,7 +125,7 @@ export class TimespanBreakdownOverlay extends HTMLElement { } } renderSection(section) { - const sectionRange = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(section.bounds.range); + const sectionRange = Trace.Helpers.Timing.microSecondsToMilliseconds(section.bounds.range); // clang-format off return LitHtml.html `
    @@ -138,6 +141,7 @@ export class TimespanBreakdownOverlay extends HTMLElement { } #render() { LitHtml.render(LitHtml.html `${this.#sections?.map(this.renderSection)}`, this.#shadow, { host: this }); + this.checkSectionLabelPositioning(); } } customElements.define('devtools-timespan-breakdown-overlay', TimespanBreakdownOverlay); diff --git a/public/panels/timeline/overlays/components/TimespanBreakdownOverlay.js.map b/public/panels/timeline/overlays/components/TimespanBreakdownOverlay.js.map index 7ba9f964a..a93d49498 100644 --- a/public/panels/timeline/overlays/components/TimespanBreakdownOverlay.js.map +++ b/public/panels/timeline/overlays/components/TimespanBreakdownOverlay.js.map @@ -1 +1 @@ -{"version":3,"file":"TimespanBreakdownOverlay.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/overlays/components/TimespanBreakdownOverlay.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport * as TraceEngine from '../../../../models/trace/trace.js';\nimport * as ComponentHelpers from '../../../../ui/components/helpers/helpers.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\n\nimport styles from './timespanBreakdownOverlay.css.js';\n\n/**\n * An EntryBreakdown, or section, that makes up a TimespanBreakdown.\n */\nexport type EntryBreakdown = {\n bounds: TraceEngine.Types.Timing.TraceWindowMicroSeconds,\n label: string|LitHtml.LitTemplate,\n showDuration: boolean,\n};\n\nexport class TimespanBreakdownOverlay extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-timespan-breakdown-overlay`;\n /**\n * Size to stagger sections of a TimespanBreakdownOverlay.\n */\n static readonly TIMESPAN_BREAKDOWN_OVERLAY_STAGGER_PX = 5;\n\n readonly #shadow = this.attachShadow({mode: 'open'});\n readonly #boundRender = this.#render.bind(this);\n #canvasRect: DOMRect|null = null;\n #sections: Array|null = null;\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [styles];\n this.#render();\n }\n\n set canvasRect(rect: DOMRect|null) {\n this.#canvasRect = rect;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n set sections(sections: Array|null) {\n if (sections === this.#sections) {\n return;\n }\n this.#sections = sections;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n /**\n * We use this method after the overlay has been positioned in order to move\n * the section label as required to keep it on screen.\n * If the label is off to the left or right, we fix it to that corner and\n * align the text so the label is visible as long as possible.\n */\n afterOverlayUpdate(): void {\n const sections = this.#shadow.querySelectorAll('.timespan-breakdown-overlay-section');\n if (!sections) {\n return;\n }\n\n if (!this.#canvasRect) {\n return;\n }\n\n // On the RHS of the panel a scrollbar can be shown which means the canvas\n // has a 9px gap on the right hand edge. We use this value when calculating\n // values and label positioning from the left hand side in order to be\n // consistent on both edges of the UI.\n const paddingForScrollbar = 9;\n\n // Fetch the rects for each section and label now, rather than in the loop,\n // to avoid causing a bunch of recalcStyles\n const sectionLayoutData = new Map();\n for (const section of sections) {\n const label = section.querySelector('.timespan-breakdown-overlay-label');\n if (!label) {\n continue;\n }\n const sectionRect = section.getBoundingClientRect();\n const labelRect = label.getBoundingClientRect();\n sectionLayoutData.set(section, {sectionRect, labelRect, label});\n }\n\n const minSectionWidthToShowAnyLabel = 30;\n\n // Align the labels for all the breakdown sections.\n for (const section of sections) {\n const layoutData = sectionLayoutData.get(section);\n if (!layoutData) {\n break;\n }\n const {labelRect, sectionRect, label} = layoutData;\n\n const labelHidden = sectionRect.width < minSectionWidthToShowAnyLabel;\n // Subtract 5 from the section width to allow a tiny bit of padding.\n const labelTruncated = sectionRect.width - 5 <= labelRect.width;\n // We differentiate between hidden + truncated; if it is truncated we\n // will show the text with ellipsis for overflow, but if the section is\n // really small we just hide the label entirely.\n label.classList.toggle('labelHidden', labelHidden);\n label.classList.toggle('labelTruncated', labelTruncated);\n\n if (labelHidden || labelTruncated) {\n // Label is hidden or doesn't fully fit, so we don't need to do the\n // logic to left/right align if it needs it.\n continue;\n }\n\n // Check if label is off the LHS of the screen.\n const labelLeftMarginToCenter = (sectionRect.width - labelRect.width) / 2;\n const newLabelX = sectionRect.x + labelLeftMarginToCenter;\n\n const labelOffLeftOfScreen = newLabelX < this.#canvasRect.x;\n label.classList.toggle('offScreenLeft', labelOffLeftOfScreen);\n\n // Check if label is off the RHS of the screen\n const rightBound = this.#canvasRect.x + this.#canvasRect.width;\n // The label's right hand edge is the gap from the left of the range to the\n // label, and then the width of the label.\n const labelRightEdge = sectionRect.x + labelLeftMarginToCenter + labelRect.width;\n const labelOffRightOfScreen = labelRightEdge > rightBound;\n label.classList.toggle('offScreenRight', labelOffRightOfScreen);\n\n if (labelOffLeftOfScreen) {\n // If the label is off the left of the screen, we adjust by the\n // difference between the X that represents the start of the cavnas, and\n // the X that represents the start of the overlay.\n // We then take the absolute value of this - because if the canvas starts\n // at 0, and the overlay is -200px, we have to adjust the label by +200.\n // Add on 9 pixels to pad from the left; this is the width of the sidebar\n // on the RHS so we match it so the label is equally padded on either\n // side.\n label.style.marginLeft = `${Math.abs(this.#canvasRect.x - sectionRect.x) + paddingForScrollbar}px`;\n\n } else if (labelOffRightOfScreen) {\n // To calculate how far left to push the label, we take the right hand\n // bound (the canvas width and subtract the label's width).\n // Finally, we subtract the X position of the overlay (if the overlay is\n // 200px within the view, we don't need to push the label that 200px too\n // otherwise it will be off-screen)\n const leftMargin = rightBound - labelRect.width - sectionRect.x;\n\n label.style.marginLeft = `${leftMargin}px`;\n\n } else {\n // Keep the label central.\n label.style.marginLeft = `${labelLeftMarginToCenter}px`;\n }\n }\n }\n\n renderSection(section: EntryBreakdown): LitHtml.TemplateResult {\n const sectionRange = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(section.bounds.range);\n // clang-format off\n return LitHtml.html`\n
    \n
    \n ${section.showDuration ?\n LitHtml.html`\n ${i18n.TimeUtilities.preciseMillisToString(sectionRange, 2)}\n ` : LitHtml.nothing}\n ${section.label}\n
    \n
    `;\n // clang-format on\n }\n\n #render(): void {\n LitHtml.render(LitHtml.html`${this.#sections?.map(this.renderSection)}`, this.#shadow, {host: this});\n }\n}\n\ncustomElements.define('devtools-timespan-breakdown-overlay', TimespanBreakdownOverlay);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-timespan-breakdown-overlay': TimespanBreakdownOverlay;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"TimespanBreakdownOverlay.js","sourceRoot":"","sources":["../../../../../../../../front_end/panels/timeline/overlays/components/TimespanBreakdownOverlay.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport * as Trace from '../../../../models/trace/trace.js';\nimport * as ComponentHelpers from '../../../../ui/components/helpers/helpers.js';\nimport * as LitHtml from '../../../../ui/lit-html/lit-html.js';\n\nimport styles from './timespanBreakdownOverlay.css.js';\n\n/**\n * An EntryBreakdown, or section, that makes up a TimespanBreakdown.\n */\nexport type EntryBreakdown = {\n bounds: Trace.Types.Timing.TraceWindowMicroSeconds,\n label: string|LitHtml.LitTemplate,\n showDuration: boolean,\n};\n\nexport class TimespanBreakdownOverlay extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-timespan-breakdown-overlay`;\n /**\n * Size to stagger sections of a TimespanBreakdownOverlay.\n */\n static readonly TIMESPAN_BREAKDOWN_OVERLAY_STAGGER_PX = 5;\n\n readonly #shadow = this.attachShadow({mode: 'open'});\n readonly #boundRender = this.#render.bind(this);\n #canvasRect: DOMRect|null = null;\n #sections: Array|null = null;\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [styles];\n this.#render();\n }\n\n set canvasRect(rect: DOMRect|null) {\n if (this.#canvasRect && rect && this.#canvasRect.width === rect.width && this.#canvasRect.height === rect.height) {\n return;\n }\n this.#canvasRect = rect;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n set sections(sections: Array|null) {\n if (sections === this.#sections) {\n return;\n }\n this.#sections = sections;\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#boundRender);\n }\n\n /**\n * We use this method after the overlay has been positioned in order to move\n * the section label as required to keep it on screen.\n * If the label is off to the left or right, we fix it to that corner and\n * align the text so the label is visible as long as possible.\n */\n checkSectionLabelPositioning(): void {\n const sections = this.#shadow.querySelectorAll('.timespan-breakdown-overlay-section');\n if (!sections) {\n return;\n }\n\n if (!this.#canvasRect) {\n return;\n }\n\n // On the RHS of the panel a scrollbar can be shown which means the canvas\n // has a 9px gap on the right hand edge. We use this value when calculating\n // values and label positioning from the left hand side in order to be\n // consistent on both edges of the UI.\n const paddingForScrollbar = 9;\n\n // Fetch the rects for each section and label now, rather than in the loop,\n // to avoid causing a bunch of recalcStyles\n const sectionLayoutData = new Map();\n for (const section of sections) {\n const label = section.querySelector('.timespan-breakdown-overlay-label');\n if (!label) {\n continue;\n }\n const sectionRect = section.getBoundingClientRect();\n const labelRect = label.getBoundingClientRect();\n sectionLayoutData.set(section, {sectionRect, labelRect, label});\n }\n\n const minSectionWidthToShowAnyLabel = 30;\n\n // Align the labels for all the breakdown sections.\n for (const section of sections) {\n const layoutData = sectionLayoutData.get(section);\n if (!layoutData) {\n break;\n }\n const {labelRect, sectionRect, label} = layoutData;\n\n const labelHidden = sectionRect.width < minSectionWidthToShowAnyLabel;\n // Subtract 5 from the section width to allow a tiny bit of padding.\n const labelTruncated = sectionRect.width - 5 <= labelRect.width;\n // We differentiate between hidden + truncated; if it is truncated we\n // will show the text with ellipsis for overflow, but if the section is\n // really small we just hide the label entirely.\n label.classList.toggle('labelHidden', labelHidden);\n label.classList.toggle('labelTruncated', labelTruncated);\n\n if (labelHidden || labelTruncated) {\n // Label is hidden or doesn't fully fit, so we don't need to do the\n // logic to left/right align if it needs it.\n continue;\n }\n\n // Check if label is off the LHS of the screen.\n const labelLeftMarginToCenter = (sectionRect.width - labelRect.width) / 2;\n const newLabelX = sectionRect.x + labelLeftMarginToCenter;\n\n const labelOffLeftOfScreen = newLabelX < this.#canvasRect.x;\n label.classList.toggle('offScreenLeft', labelOffLeftOfScreen);\n\n // Check if label is off the RHS of the screen\n const rightBound = this.#canvasRect.x + this.#canvasRect.width;\n // The label's right hand edge is the gap from the left of the range to the\n // label, and then the width of the label.\n const labelRightEdge = sectionRect.x + labelLeftMarginToCenter + labelRect.width;\n const labelOffRightOfScreen = labelRightEdge > rightBound;\n label.classList.toggle('offScreenRight', labelOffRightOfScreen);\n\n if (labelOffLeftOfScreen) {\n // If the label is off the left of the screen, we adjust by the\n // difference between the X that represents the start of the cavnas, and\n // the X that represents the start of the overlay.\n // We then take the absolute value of this - because if the canvas starts\n // at 0, and the overlay is -200px, we have to adjust the label by +200.\n // Add on 9 pixels to pad from the left; this is the width of the sidebar\n // on the RHS so we match it so the label is equally padded on either\n // side.\n label.style.marginLeft = `${Math.abs(this.#canvasRect.x - sectionRect.x) + paddingForScrollbar}px`;\n\n } else if (labelOffRightOfScreen) {\n // To calculate how far left to push the label, we take the right hand\n // bound (the canvas width and subtract the label's width).\n // Finally, we subtract the X position of the overlay (if the overlay is\n // 200px within the view, we don't need to push the label that 200px too\n // otherwise it will be off-screen)\n const leftMargin = rightBound - labelRect.width - sectionRect.x;\n\n label.style.marginLeft = `${leftMargin}px`;\n\n } else {\n // Keep the label central.\n label.style.marginLeft = `${labelLeftMarginToCenter}px`;\n }\n }\n }\n\n renderSection(section: EntryBreakdown): LitHtml.TemplateResult {\n const sectionRange = Trace.Helpers.Timing.microSecondsToMilliseconds(section.bounds.range);\n // clang-format off\n return LitHtml.html`\n
    \n
    \n ${section.showDuration ?\n LitHtml.html`\n ${i18n.TimeUtilities.preciseMillisToString(sectionRange, 2)}\n ` : LitHtml.nothing}\n ${section.label}\n
    \n
    `;\n // clang-format on\n }\n\n #render(): void {\n LitHtml.render(LitHtml.html`${this.#sections?.map(this.renderSection)}`, this.#shadow, {host: this});\n this.checkSectionLabelPositioning();\n }\n}\n\ncustomElements.define('devtools-timespan-breakdown-overlay', TimespanBreakdownOverlay);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-timespan-breakdown-overlay': TimespanBreakdownOverlay;\n }\n}\n"]} \ No newline at end of file diff --git a/public/panels/timeline/overlays/components/entriesLinkOverlay.css.js b/public/panels/timeline/overlays/components/entriesLinkOverlay.css.js index eab8b63e6..6117937b6 100644 --- a/public/panels/timeline/overlays/components/entriesLinkOverlay.css.js +++ b/public/panels/timeline/overlays/components/entriesLinkOverlay.css.js @@ -17,6 +17,21 @@ styles.replaceSync( height: 100%; } +.entry-highlight-wrapper { + box-sizing: border-box; + border: 2px solid var(--sys-color-on-surface); + position: absolute; +} + +.create-link-icon { + pointer-events: auto; + cursor: pointer; + color: var(--sys-color-on-surface); + width: 16px; + height: 16px; + position: absolute; +} + /*# sourceURL=entriesLinkOverlay.css */ `); diff --git a/public/panels/timeline/overlays/components/entryLabelOverlay.css.js b/public/panels/timeline/overlays/components/entryLabelOverlay.css.js index 26d164e2f..b2fec0352 100644 --- a/public/panels/timeline/overlays/components/entryLabelOverlay.css.js +++ b/public/panels/timeline/overlays/components/entryLabelOverlay.css.js @@ -19,13 +19,13 @@ styles.replaceSync( transform: translate(-50%); display: flex; flex-direction: column; - color: var(--color-selected-option); align-items: center; } .input-field { + background-color: var(--color-background-inverted); + color: var(--color-background); pointer-events: auto; - background-color: var(--sys-color-token-variable); border-radius: var(--sys-shape-corner-extra-small); white-space: nowrap; padding: var(--sys-size-3) var(--sys-size-4); @@ -35,8 +35,9 @@ styles.replaceSync( } .input-field:focus { - background-color: var(--color-selected-option); - color: var(--sys-color-token-variable); + background-color: var(--color-background); + color: var(--color-background-inverted); + outline: 2px solid var(--color-background-inverted); } .connectorContainer { @@ -56,6 +57,10 @@ styles.replaceSync( .user-created-icon { margin: var(--sys-size-3); + color: var(--color-background-inverted); + /* USER_CREATED_ICON_WIDTH */ + width: 16px; + height: 16px; } /*# sourceURL=entryLabelOverlay.css */ diff --git a/public/panels/timeline/overlays/components/timeRangeOverlay.css.js b/public/panels/timeline/overlays/components/timeRangeOverlay.css.js index e5ecbf915..421d3a766 100644 --- a/public/panels/timeline/overlays/components/timeRangeOverlay.css.js +++ b/public/panels/timeline/overlays/components/timeRangeOverlay.css.js @@ -75,6 +75,9 @@ styles.replaceSync( position: absolute; left: 4px; bottom: 5px; + color: var(--ref-palette-pink55); + width: 16px; + height: 17px; } /*# sourceURL=timeRangeOverlay.css */ diff --git a/public/panels/timeline/timeline-tsconfig.json b/public/panels/timeline/timeline-tsconfig.json index 4de6fde1f..f4a8226e8 100644 --- a/public/panels/timeline/timeline-tsconfig.json +++ b/public/panels/timeline/timeline-tsconfig.json @@ -31,6 +31,7 @@ "files": [ "../../../../../../front_end/panels/timeline/ActiveFilters.ts", "../../../../../../front_end/panels/timeline/AnimationsTrackAppender.ts", + "../../../../../../front_end/panels/timeline/AnnotationHelpers.ts", "../../../../../../front_end/panels/timeline/AppenderUtils.ts", "../../../../../../front_end/panels/timeline/BenchmarkEvents.ts", "../../../../../../front_end/panels/timeline/CLSLinkifier.ts", diff --git a/public/panels/timeline/timeline.d.ts b/public/panels/timeline/timeline.d.ts index b846f0dfa..2515edc9f 100644 --- a/public/panels/timeline/timeline.d.ts +++ b/public/panels/timeline/timeline.d.ts @@ -1,4 +1,5 @@ import * as AnimationsTrackAppender from './AnimationsTrackAppender.js'; +import * as AnnotationHelpers from './AnnotationHelpers.js'; import * as AppenderUtils from './AppenderUtils.js'; import * as BenchmarkEvents from './BenchmarkEvents.js'; import * as CLSLinkifier from './CLSLinkifier.js'; @@ -40,4 +41,4 @@ import * as TimelineUIUtils from './TimelineUIUtils.js'; import * as TimingsTrackAppender from './TimingsTrackAppender.js'; import * as UIDevtoolsController from './UIDevtoolsController.js'; import * as UIDevtoolsUtils from './UIDevtoolsUtils.js'; -export { AnimationsTrackAppender, AppenderUtils, BenchmarkEvents, CLSLinkifier, CompatibilityTracksAppender, CountersGraph, EntriesFilter, EventsSerializer, EventsTimelineTreeView, ExtensionDataGatherer, ExtensionTrackAppender, FreshRecording, GPUTrackAppender, Initiators, InteractionsTrackAppender, LayoutShiftsTrackAppender, ModificationsManager, NetworkTrackAppender, SaveFileFormatter, ServerTimingsTrackAppender, SourceMapsResolver, TargetForEvent, ThreadAppender, TimelineController, TimelineDetailsView, TimelineEventOverview, TimelineFilters, TimelineFlameChartDataProvider, TimelineFlameChartNetworkDataProvider, TimelineFlameChartView, TimelineHistoryManager, TimelineLayersView, TimelineLoader, TimelineMiniMap, TimelinePaintProfilerView, TimelinePanel, TimelineSelection, TimelineTreeView, TimelineUIUtils, TimingsTrackAppender, UIDevtoolsController, UIDevtoolsUtils, }; +export { AnimationsTrackAppender, AnnotationHelpers, AppenderUtils, BenchmarkEvents, CLSLinkifier, CompatibilityTracksAppender, CountersGraph, EntriesFilter, EventsSerializer, EventsTimelineTreeView, ExtensionDataGatherer, ExtensionTrackAppender, FreshRecording, GPUTrackAppender, Initiators, InteractionsTrackAppender, LayoutShiftsTrackAppender, ModificationsManager, NetworkTrackAppender, SaveFileFormatter, ServerTimingsTrackAppender, SourceMapsResolver, TargetForEvent, ThreadAppender, TimelineController, TimelineDetailsView, TimelineEventOverview, TimelineFilters, TimelineFlameChartDataProvider, TimelineFlameChartNetworkDataProvider, TimelineFlameChartView, TimelineHistoryManager, TimelineLayersView, TimelineLoader, TimelineMiniMap, TimelinePaintProfilerView, TimelinePanel, TimelineSelection, TimelineTreeView, TimelineUIUtils, TimingsTrackAppender, UIDevtoolsController, UIDevtoolsUtils, }; diff --git a/public/panels/timeline/timeline.js b/public/panels/timeline/timeline.js index 9a2c2953e..0007559b9 100644 --- a/public/panels/timeline/timeline.js +++ b/public/panels/timeline/timeline.js @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as AnimationsTrackAppender from './AnimationsTrackAppender.js'; +import * as AnnotationHelpers from './AnnotationHelpers.js'; import * as AppenderUtils from './AppenderUtils.js'; import * as BenchmarkEvents from './BenchmarkEvents.js'; import * as CLSLinkifier from './CLSLinkifier.js'; @@ -43,5 +44,5 @@ import * as TimelineUIUtils from './TimelineUIUtils.js'; import * as TimingsTrackAppender from './TimingsTrackAppender.js'; import * as UIDevtoolsController from './UIDevtoolsController.js'; import * as UIDevtoolsUtils from './UIDevtoolsUtils.js'; -export { AnimationsTrackAppender, AppenderUtils, BenchmarkEvents, CLSLinkifier, CompatibilityTracksAppender, CountersGraph, EntriesFilter, EventsSerializer, EventsTimelineTreeView, ExtensionDataGatherer, ExtensionTrackAppender, FreshRecording, GPUTrackAppender, Initiators, InteractionsTrackAppender, LayoutShiftsTrackAppender, ModificationsManager, NetworkTrackAppender, SaveFileFormatter, ServerTimingsTrackAppender, SourceMapsResolver, TargetForEvent, ThreadAppender, TimelineController, TimelineDetailsView, TimelineEventOverview, TimelineFilters, TimelineFlameChartDataProvider, TimelineFlameChartNetworkDataProvider, TimelineFlameChartView, TimelineHistoryManager, TimelineLayersView, TimelineLoader, TimelineMiniMap, TimelinePaintProfilerView, TimelinePanel, TimelineSelection, TimelineTreeView, TimelineUIUtils, TimingsTrackAppender, UIDevtoolsController, UIDevtoolsUtils, }; +export { AnimationsTrackAppender, AnnotationHelpers, AppenderUtils, BenchmarkEvents, CLSLinkifier, CompatibilityTracksAppender, CountersGraph, EntriesFilter, EventsSerializer, EventsTimelineTreeView, ExtensionDataGatherer, ExtensionTrackAppender, FreshRecording, GPUTrackAppender, Initiators, InteractionsTrackAppender, LayoutShiftsTrackAppender, ModificationsManager, NetworkTrackAppender, SaveFileFormatter, ServerTimingsTrackAppender, SourceMapsResolver, TargetForEvent, ThreadAppender, TimelineController, TimelineDetailsView, TimelineEventOverview, TimelineFilters, TimelineFlameChartDataProvider, TimelineFlameChartNetworkDataProvider, TimelineFlameChartView, TimelineHistoryManager, TimelineLayersView, TimelineLoader, TimelineMiniMap, TimelinePaintProfilerView, TimelinePanel, TimelineSelection, TimelineTreeView, TimelineUIUtils, TimingsTrackAppender, UIDevtoolsController, UIDevtoolsUtils, }; //# sourceMappingURL=timeline.js.map \ No newline at end of file diff --git a/public/panels/timeline/timeline.js.map b/public/panels/timeline/timeline.js.map index d0b270893..ed18961ac 100644 --- a/public/panels/timeline/timeline.js.map +++ b/public/panels/timeline/timeline.js.map @@ -1 +1 @@ -{"version":3,"file":"timeline.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/timeline.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2019 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as AnimationsTrackAppender from './AnimationsTrackAppender.js';\nimport * as AppenderUtils from './AppenderUtils.js';\nimport * as BenchmarkEvents from './BenchmarkEvents.js';\nimport * as CLSLinkifier from './CLSLinkifier.js';\nimport * as CompatibilityTracksAppender from './CompatibilityTracksAppender.js';\nimport * as CountersGraph from './CountersGraph.js';\nimport * as EntriesFilter from './EntriesFilter.js';\nimport * as EventsSerializer from './EventsSerializer.js';\nimport * as EventsTimelineTreeView from './EventsTimelineTreeView.js';\nimport * as ExtensionDataGatherer from './ExtensionDataGatherer.js';\nimport * as ExtensionTrackAppender from './ExtensionTrackAppender.js';\nimport * as FreshRecording from './FreshRecording.js';\nimport * as GPUTrackAppender from './GPUTrackAppender.js';\nimport * as Initiators from './Initiators.js';\nimport * as InteractionsTrackAppender from './InteractionsTrackAppender.js';\nimport * as LayoutShiftsTrackAppender from './LayoutShiftsTrackAppender.js';\nimport * as ModificationsManager from './ModificationsManager.js';\nimport * as NetworkTrackAppender from './NetworkTrackAppender.js';\nimport * as SaveFileFormatter from './SaveFileFormatter.js';\nimport * as ServerTimingsTrackAppender from './ServerTimingsTrackAppender.js';\nimport * as SourceMapsResolver from './SourceMapsResolver.js';\nimport * as TargetForEvent from './TargetForEvent.js';\nimport * as ThreadAppender from './ThreadAppender.js';\nimport * as TimelineController from './TimelineController.js';\nimport * as TimelineDetailsView from './TimelineDetailsView.js';\nimport * as TimelineEventOverview from './TimelineEventOverview.js';\nimport * as TimelineFilters from './TimelineFilters.js';\nimport * as TimelineFlameChartDataProvider from './TimelineFlameChartDataProvider.js';\nimport * as TimelineFlameChartNetworkDataProvider from './TimelineFlameChartNetworkDataProvider.js';\nimport * as TimelineFlameChartView from './TimelineFlameChartView.js';\nimport * as TimelineHistoryManager from './TimelineHistoryManager.js';\nimport * as TimelineLayersView from './TimelineLayersView.js';\nimport * as TimelineLoader from './TimelineLoader.js';\nimport * as TimelineMiniMap from './TimelineMiniMap.js';\nimport * as TimelinePaintProfilerView from './TimelinePaintProfilerView.js';\nimport * as TimelinePanel from './TimelinePanel.js';\nimport * as TimelineSelection from './TimelineSelection.js';\nimport * as TimelineTreeView from './TimelineTreeView.js';\nimport * as TimelineUIUtils from './TimelineUIUtils.js';\nimport * as TimingsTrackAppender from './TimingsTrackAppender.js';\nimport * as UIDevtoolsController from './UIDevtoolsController.js';\nimport * as UIDevtoolsUtils from './UIDevtoolsUtils.js';\n\nexport {\n AnimationsTrackAppender,\n AppenderUtils,\n BenchmarkEvents,\n CLSLinkifier,\n CompatibilityTracksAppender,\n CountersGraph,\n EntriesFilter,\n EventsSerializer,\n EventsTimelineTreeView,\n ExtensionDataGatherer,\n ExtensionTrackAppender,\n FreshRecording,\n GPUTrackAppender,\n Initiators,\n InteractionsTrackAppender,\n LayoutShiftsTrackAppender,\n ModificationsManager,\n NetworkTrackAppender,\n SaveFileFormatter,\n ServerTimingsTrackAppender,\n SourceMapsResolver,\n TargetForEvent,\n ThreadAppender,\n TimelineController,\n TimelineDetailsView,\n TimelineEventOverview,\n TimelineFilters,\n TimelineFlameChartDataProvider,\n TimelineFlameChartNetworkDataProvider,\n TimelineFlameChartView,\n TimelineHistoryManager,\n TimelineLayersView,\n TimelineLoader,\n TimelineMiniMap,\n TimelinePaintProfilerView,\n TimelinePanel,\n TimelineSelection,\n TimelineTreeView,\n TimelineUIUtils,\n TimingsTrackAppender,\n UIDevtoolsController,\n UIDevtoolsUtils,\n};\n"]} \ No newline at end of file +{"version":3,"file":"timeline.js","sourceRoot":"","sources":["../../../../../../front_end/panels/timeline/timeline.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2019 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as AnimationsTrackAppender from './AnimationsTrackAppender.js';\nimport * as AnnotationHelpers from './AnnotationHelpers.js';\nimport * as AppenderUtils from './AppenderUtils.js';\nimport * as BenchmarkEvents from './BenchmarkEvents.js';\nimport * as CLSLinkifier from './CLSLinkifier.js';\nimport * as CompatibilityTracksAppender from './CompatibilityTracksAppender.js';\nimport * as CountersGraph from './CountersGraph.js';\nimport * as EntriesFilter from './EntriesFilter.js';\nimport * as EventsSerializer from './EventsSerializer.js';\nimport * as EventsTimelineTreeView from './EventsTimelineTreeView.js';\nimport * as ExtensionDataGatherer from './ExtensionDataGatherer.js';\nimport * as ExtensionTrackAppender from './ExtensionTrackAppender.js';\nimport * as FreshRecording from './FreshRecording.js';\nimport * as GPUTrackAppender from './GPUTrackAppender.js';\nimport * as Initiators from './Initiators.js';\nimport * as InteractionsTrackAppender from './InteractionsTrackAppender.js';\nimport * as LayoutShiftsTrackAppender from './LayoutShiftsTrackAppender.js';\nimport * as ModificationsManager from './ModificationsManager.js';\nimport * as NetworkTrackAppender from './NetworkTrackAppender.js';\nimport * as SaveFileFormatter from './SaveFileFormatter.js';\nimport * as ServerTimingsTrackAppender from './ServerTimingsTrackAppender.js';\nimport * as SourceMapsResolver from './SourceMapsResolver.js';\nimport * as TargetForEvent from './TargetForEvent.js';\nimport * as ThreadAppender from './ThreadAppender.js';\nimport * as TimelineController from './TimelineController.js';\nimport * as TimelineDetailsView from './TimelineDetailsView.js';\nimport * as TimelineEventOverview from './TimelineEventOverview.js';\nimport * as TimelineFilters from './TimelineFilters.js';\nimport * as TimelineFlameChartDataProvider from './TimelineFlameChartDataProvider.js';\nimport * as TimelineFlameChartNetworkDataProvider from './TimelineFlameChartNetworkDataProvider.js';\nimport * as TimelineFlameChartView from './TimelineFlameChartView.js';\nimport * as TimelineHistoryManager from './TimelineHistoryManager.js';\nimport * as TimelineLayersView from './TimelineLayersView.js';\nimport * as TimelineLoader from './TimelineLoader.js';\nimport * as TimelineMiniMap from './TimelineMiniMap.js';\nimport * as TimelinePaintProfilerView from './TimelinePaintProfilerView.js';\nimport * as TimelinePanel from './TimelinePanel.js';\nimport * as TimelineSelection from './TimelineSelection.js';\nimport * as TimelineTreeView from './TimelineTreeView.js';\nimport * as TimelineUIUtils from './TimelineUIUtils.js';\nimport * as TimingsTrackAppender from './TimingsTrackAppender.js';\nimport * as UIDevtoolsController from './UIDevtoolsController.js';\nimport * as UIDevtoolsUtils from './UIDevtoolsUtils.js';\n\nexport {\n AnimationsTrackAppender,\n AnnotationHelpers,\n AppenderUtils,\n BenchmarkEvents,\n CLSLinkifier,\n CompatibilityTracksAppender,\n CountersGraph,\n EntriesFilter,\n EventsSerializer,\n EventsTimelineTreeView,\n ExtensionDataGatherer,\n ExtensionTrackAppender,\n FreshRecording,\n GPUTrackAppender,\n Initiators,\n InteractionsTrackAppender,\n LayoutShiftsTrackAppender,\n ModificationsManager,\n NetworkTrackAppender,\n SaveFileFormatter,\n ServerTimingsTrackAppender,\n SourceMapsResolver,\n TargetForEvent,\n ThreadAppender,\n TimelineController,\n TimelineDetailsView,\n TimelineEventOverview,\n TimelineFilters,\n TimelineFlameChartDataProvider,\n TimelineFlameChartNetworkDataProvider,\n TimelineFlameChartView,\n TimelineHistoryManager,\n TimelineLayersView,\n TimelineLoader,\n TimelineMiniMap,\n TimelinePaintProfilerView,\n TimelinePanel,\n TimelineSelection,\n TimelineTreeView,\n TimelineUIUtils,\n TimingsTrackAppender,\n UIDevtoolsController,\n UIDevtoolsUtils,\n};\n"]} \ No newline at end of file diff --git a/public/panels/timeline/timelineFlameChartView.css.js b/public/panels/timeline/timelineFlameChartView.css.js index dac0c86c7..671edff7c 100644 --- a/public/panels/timeline/timelineFlameChartView.css.js +++ b/public/panels/timeline/timelineFlameChartView.css.js @@ -29,6 +29,11 @@ styles.replaceSync( left: 0; } +.overlay-type-ENTRY_LABEL { + /* keep these above the selected entry overline, else they can become hard to read */ + z-index: 2; +} + .overlay-type-ENTRY_SELECTED, .overlay-type-ENTRY_OUTLINE { pointer-events: none; diff --git a/public/panels/timeline/timelineMiniMap.css.js b/public/panels/timeline/timelineMiniMap.css.js index 2ecd5dcc6..56ad62d47 100644 --- a/public/panels/timeline/timelineMiniMap.css.js +++ b/public/panels/timeline/timelineMiniMap.css.js @@ -108,6 +108,12 @@ styles.replaceSync( height: 100%; } +.timeline-minimap-dim-highlight-svg { + width: 100%; + position: absolute; + height: 100%; +} + .timeline-minimap .memory-graph-label { position: absolute; right: 0; diff --git a/public/panels/timeline/track_appenders/AnimationsTrackAppender.test.js b/public/panels/timeline/track_appenders/AnimationsTrackAppender.test.js index bfc1b75b0..8b61e3c2d 100644 --- a/public/panels/timeline/track_appenders/AnimationsTrackAppender.test.js +++ b/public/panels/timeline/track_appenders/AnimationsTrackAppender.test.js @@ -1,25 +1,25 @@ // 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 * as TraceEngine from '../../../models/trace/trace.js'; +import * as Trace from '../../../models/trace/trace.js'; import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; import * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js'; import * as ThemeSupport from '../../../ui/legacy/theme_support/theme_support.js'; import * as Timeline from '../timeline.js'; -function initTrackAppender(flameChartData, traceParsedData, entryData, entryTypeByLevel) { - const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(flameChartData, traceParsedData, entryData, entryTypeByLevel); +function initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel) { + const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel); return compatibilityTracksAppender.animationsTrackAppender(); } describeWithEnvironment('AnimationsTrackAppender', function () { - let traceData; + let parsedTrace; let animationsTrackAppender; let entryData = []; let flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty(); let entryTypeByLevel = []; beforeEach(async function () { - ({ traceData } = await TraceLoader.traceEngine(this, 'animation.json.gz')); - animationsTrackAppender = initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel); + ({ parsedTrace } = await TraceLoader.traceEngine(this, 'animation.json.gz')); + animationsTrackAppender = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel); animationsTrackAppender.appendTrackAtLevel(0); }); afterEach(() => { @@ -33,22 +33,22 @@ describeWithEnvironment('AnimationsTrackAppender', function () { assert.strictEqual(flameChartData.groups[0].name, 'Animations'); }); it('adds start times correctly', function () { - const animationsRequests = traceData.Animations.animations; + const animationsRequests = parsedTrace.Animations.animations; for (let i = 0; i < animationsRequests.length; ++i) { const event = animationsRequests[i]; - assert.strictEqual(flameChartData.entryStartTimes[i], TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.ts)); + assert.strictEqual(flameChartData.entryStartTimes[i], Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts)); } }); it('adds total times correctly', function () { - const animationsRequests = traceData.Animations.animations; + const animationsRequests = parsedTrace.Animations.animations; for (let i = 0; i < animationsRequests.length; i++) { const event = animationsRequests[i]; - if (TraceEngine.Types.TraceEvents.isTraceEventMarkerEvent(event)) { + if (Trace.Types.Events.isMarkerEvent(event)) { assert.isNaN(flameChartData.entryTotalTimes[i]); continue; } const expectedTotalTimeForEvent = event.dur ? - TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.dur) : + Trace.Helpers.Timing.microSecondsToMilliseconds(event.dur) : Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs; assert.strictEqual(flameChartData.entryTotalTimes[i], expectedTotalTimeForEvent); } diff --git a/public/panels/timeline/track_appenders/AnimationsTrackAppender.test.js.map b/public/panels/timeline/track_appenders/AnimationsTrackAppender.test.js.map index 1147a0077..6bd498675 100644 --- a/public/panels/timeline/track_appenders/AnimationsTrackAppender.test.js.map +++ b/public/panels/timeline/track_appenders/AnimationsTrackAppender.test.js.map @@ -1 +1 @@ -{"version":3,"file":"AnimationsTrackAppender.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/track_appenders/AnimationsTrackAppender.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as TraceModel from '../../../models/trace/trace.js';\nimport * as TraceEngine from '../../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as ThemeSupport from '../../../ui/legacy/theme_support/theme_support.js';\nimport * as Timeline from '../timeline.js';\n\nfunction initTrackAppender(\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData, traceParsedData: TraceModel.Handlers.Types.TraceParseData,\n entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[],\n entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[]):\n Timeline.AnimationsTrackAppender.AnimationsTrackAppender {\n const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(\n flameChartData, traceParsedData, entryData, entryTypeByLevel);\n return compatibilityTracksAppender.animationsTrackAppender();\n}\n\ndescribeWithEnvironment('AnimationsTrackAppender', function() {\n let traceData: TraceModel.Handlers.Types.TraceParseData;\n let animationsTrackAppender: Timeline.AnimationsTrackAppender.AnimationsTrackAppender;\n let entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[] = [];\n let flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n let entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[] = [];\n\n beforeEach(async function() {\n ({traceData} = await TraceLoader.traceEngine(this, 'animation.json.gz'));\n animationsTrackAppender = initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel);\n animationsTrackAppender.appendTrackAtLevel(0);\n });\n\n afterEach(() => {\n entryData = [];\n flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n entryTypeByLevel = [];\n });\n\n describe('appendTrackAtLevel', function() {\n it('creates a flamechart group for the Animations track', function() {\n assert.strictEqual(flameChartData.groups.length, 1);\n assert.strictEqual(flameChartData.groups[0].name, 'Animations');\n });\n\n it('adds start times correctly', function() {\n const animationsRequests = traceData.Animations.animations;\n for (let i = 0; i < animationsRequests.length; ++i) {\n const event = animationsRequests[i];\n assert.strictEqual(\n flameChartData.entryStartTimes[i], TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.ts));\n }\n });\n\n it('adds total times correctly', function() {\n const animationsRequests = traceData.Animations.animations;\n for (let i = 0; i < animationsRequests.length; i++) {\n const event = animationsRequests[i];\n if (TraceEngine.Types.TraceEvents.isTraceEventMarkerEvent(event)) {\n assert.isNaN(flameChartData.entryTotalTimes[i]);\n continue;\n }\n const expectedTotalTimeForEvent = event.dur ?\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.dur) :\n Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs;\n assert.strictEqual(flameChartData.entryTotalTimes[i], expectedTotalTimeForEvent);\n }\n });\n });\n\n describe('colorForEvent and titleForEvent', function() {\n before(() => {\n // Rather than use the real colours here and burden the test with having to\n // inject loads of CSS, we fake out the colours. this is fine for our tests as\n // the exact value of the colours is not important; we just make sure that it\n // parses them out correctly. Each variable is given a different rgb() value to\n // ensure we know the code is working and using the right one.\n const styleElement = document.createElement('style');\n styleElement.id = 'fake-perf-panel-colors';\n styleElement.textContent = `\n :root {\n --app-color-rendering: rgb(4 4 4);\n }\n `;\n document.documentElement.appendChild(styleElement);\n ThemeSupport.ThemeSupport.clearThemeCache();\n });\n\n after(() => {\n const styleElementToRemove = document.documentElement.querySelector('#fake-perf-panel-colors');\n if (styleElementToRemove) {\n document.documentElement.removeChild(styleElementToRemove);\n }\n ThemeSupport.ThemeSupport.clearThemeCache();\n });\n\n it('returns the correct color GPU tasks', function() {\n assert.strictEqual(animationsTrackAppender.colorForEvent(), 'rgb(4 4 4)');\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"AnimationsTrackAppender.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/track_appenders/AnimationsTrackAppender.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as ThemeSupport from '../../../ui/legacy/theme_support/theme_support.js';\nimport * as Timeline from '../timeline.js';\n\nfunction initTrackAppender(\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData, parsedTrace: Trace.Handlers.Types.ParsedTrace,\n entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[],\n entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[]):\n Timeline.AnimationsTrackAppender.AnimationsTrackAppender {\n const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(\n flameChartData, parsedTrace, entryData, entryTypeByLevel);\n return compatibilityTracksAppender.animationsTrackAppender();\n}\n\ndescribeWithEnvironment('AnimationsTrackAppender', function() {\n let parsedTrace: Trace.Handlers.Types.ParsedTrace;\n let animationsTrackAppender: Timeline.AnimationsTrackAppender.AnimationsTrackAppender;\n let entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[] = [];\n let flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n let entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[] = [];\n\n beforeEach(async function() {\n ({parsedTrace} = await TraceLoader.traceEngine(this, 'animation.json.gz'));\n animationsTrackAppender = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel);\n animationsTrackAppender.appendTrackAtLevel(0);\n });\n\n afterEach(() => {\n entryData = [];\n flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n entryTypeByLevel = [];\n });\n\n describe('appendTrackAtLevel', function() {\n it('creates a flamechart group for the Animations track', function() {\n assert.strictEqual(flameChartData.groups.length, 1);\n assert.strictEqual(flameChartData.groups[0].name, 'Animations');\n });\n\n it('adds start times correctly', function() {\n const animationsRequests = parsedTrace.Animations.animations;\n for (let i = 0; i < animationsRequests.length; ++i) {\n const event = animationsRequests[i];\n assert.strictEqual(\n flameChartData.entryStartTimes[i], Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts));\n }\n });\n\n it('adds total times correctly', function() {\n const animationsRequests = parsedTrace.Animations.animations;\n for (let i = 0; i < animationsRequests.length; i++) {\n const event = animationsRequests[i];\n if (Trace.Types.Events.isMarkerEvent(event)) {\n assert.isNaN(flameChartData.entryTotalTimes[i]);\n continue;\n }\n const expectedTotalTimeForEvent = event.dur ?\n Trace.Helpers.Timing.microSecondsToMilliseconds(event.dur) :\n Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs;\n assert.strictEqual(flameChartData.entryTotalTimes[i], expectedTotalTimeForEvent);\n }\n });\n });\n\n describe('colorForEvent and titleForEvent', function() {\n before(() => {\n // Rather than use the real colours here and burden the test with having to\n // inject loads of CSS, we fake out the colours. this is fine for our tests as\n // the exact value of the colours is not important; we just make sure that it\n // parses them out correctly. Each variable is given a different rgb() value to\n // ensure we know the code is working and using the right one.\n const styleElement = document.createElement('style');\n styleElement.id = 'fake-perf-panel-colors';\n styleElement.textContent = `\n :root {\n --app-color-rendering: rgb(4 4 4);\n }\n `;\n document.documentElement.appendChild(styleElement);\n ThemeSupport.ThemeSupport.clearThemeCache();\n });\n\n after(() => {\n const styleElementToRemove = document.documentElement.querySelector('#fake-perf-panel-colors');\n if (styleElementToRemove) {\n document.documentElement.removeChild(styleElementToRemove);\n }\n ThemeSupport.ThemeSupport.clearThemeCache();\n });\n\n it('returns the correct color GPU tasks', function() {\n assert.strictEqual(animationsTrackAppender.colorForEvent(), 'rgb(4 4 4)');\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/track_appenders/AppenderUtils.test.js b/public/panels/timeline/track_appenders/AppenderUtils.test.js index 847834df1..ddcae967c 100644 --- a/public/panels/timeline/track_appenders/AppenderUtils.test.js +++ b/public/panels/timeline/track_appenders/AppenderUtils.test.js @@ -1,7 +1,7 @@ // 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 * as TraceEngine from '../../../models/trace/trace.js'; +import * as Trace from '../../../models/trace/trace.js'; import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; import { defaultTraceEvent } from '../../../testing/TraceHelpers.js'; import * as Timeline from '../timeline.js'; @@ -52,48 +52,79 @@ describeWithEnvironment('AppenderUtils', () => { }); }); describe('getFormattedTime', () => { + // Helper method. Treat input as milliseconds + const getFormattedTime = (tot, self) => { + const totalTime = Trace.Helpers.Timing.millisecondsToMicroseconds(Trace.Types.Timing.MilliSeconds(tot)); + const selfTime = Trace.Helpers.Timing.millisecondsToMicroseconds(Trace.Types.Timing.MilliSeconds(self)); + return Timeline.AppenderUtils.getFormattedTime(totalTime, selfTime); + }; it('returns the time info for a entry with no duration correctly', async () => { - const formattedTime = Timeline.AppenderUtils.getFormattedTime(defaultTraceEvent.dur); + const totalTime = Trace.Types.Timing.MicroSeconds(0); + const formattedTime = Timeline.AppenderUtils.getFormattedTime(totalTime); assert.strictEqual(formattedTime, ''); + const formattedTime2 = Timeline.AppenderUtils.getFormattedTime(undefined); + assert.strictEqual(formattedTime2, ''); }); it('returns the time info for given total time correctly', async () => { - const totalTime = TraceEngine.Types.Timing.MicroSeconds(10000); + const totalTime = Trace.Types.Timing.MicroSeconds(10000); const formattedTime = Timeline.AppenderUtils.getFormattedTime(totalTime); // The i18n encodes spaces using the u00A0 unicode character. assert.strictEqual(formattedTime, '10.00\u00A0ms'); }); it('returns the time info for given total time and self time correctly', async () => { - const totalTime = TraceEngine.Types.Timing.MicroSeconds(10000); - const selfTime = TraceEngine.Types.Timing.MicroSeconds(1000); + const totalTime = Trace.Types.Timing.MicroSeconds(10000); + const selfTime = Trace.Types.Timing.MicroSeconds(1000); const formattedTime = Timeline.AppenderUtils.getFormattedTime(totalTime, selfTime); // The i18n encodes spaces using the u00A0 unicode character. assert.strictEqual(formattedTime, '10.00\u00A0ms (self 1.00\u00A0ms)'); }); it('returns the time info for same total time and self time correctly', async () => { - const totalTime = TraceEngine.Types.Timing.MicroSeconds(10000); - const selfTime = TraceEngine.Types.Timing.MicroSeconds(10000); + const totalTime = Trace.Types.Timing.MicroSeconds(10000); + const selfTime = Trace.Types.Timing.MicroSeconds(10000); const formattedTime = Timeline.AppenderUtils.getFormattedTime(totalTime, selfTime); // The i18n encodes spaces using the u00A0 unicode character. assert.strictEqual(formattedTime, '10.00\u00A0ms'); }); + it('has appropriate rounding', () => { + assert.strictEqual(getFormattedTime(10, 9), '10.00\u00A0ms (self 9.00\u00A0ms)'); + assert.strictEqual(getFormattedTime(10, 9.99), '10.00\u00A0ms (self 9.99\u00A0ms)'); + assert.strictEqual(getFormattedTime(10, 9.999), '10.00\u00A0ms (self 10.00\u00A0ms)'); + assert.strictEqual(getFormattedTime(10, 9.9999), '10.00\u00A0ms (self 10.00\u00A0ms)'); + assert.strictEqual(getFormattedTime(8.9, 7), '8.90\u00A0ms (self 7.00\u00A0ms)'); + assert.strictEqual(getFormattedTime(8.99, 7), '8.99\u00A0ms (self 7.00\u00A0ms)'); + assert.strictEqual(getFormattedTime(8.999, 7), '9.00\u00A0ms (self 7.00\u00A0ms)'); + }); + it('selfTime is omitted if we hit minSignificance', async () => { + // Total and self are really close + assert.strictEqual(getFormattedTime(5, 5.00001), '5.00\u00A0ms (self 5.00\u00A0ms)'); + assert.strictEqual(getFormattedTime(5, 5.000001), '5.00\u00A0ms (self 5.00\u00A0ms)'); + assert.strictEqual(getFormattedTime(5, 5.0000001), '5.00\u00A0ms'); // minSignificance hit! + // The self is almost zero + assert.strictEqual(getFormattedTime(10, 0.1), '10.00\u00A0ms (self 0.10\u00A0ms)'); + assert.strictEqual(getFormattedTime(10, 0.01), '10.00\u00A0ms (self 10\u00A0μs)'); + assert.strictEqual(getFormattedTime(10, 0.001), '10.00\u00A0ms (self 1\u00A0μs)'); + assert.strictEqual(getFormattedTime(10, 0.0001), '10.00\u00A0ms (self 0\u00A0μs)'); + assert.strictEqual(getFormattedTime(10, 0.00001), '10.00\u00A0ms (self 0\u00A0μs)'); + assert.strictEqual(getFormattedTime(10, 0.000001), '10.00\u00A0ms'); // minSignificance hit! + }); }); describe('getEventLevel', () => { it('returns the level for async events correctly', async () => { const lastTimestampByLevel = []; const eventOne = { ...defaultTraceEvent, - ts: TraceEngine.Types.Timing.MicroSeconds(0), - dur: TraceEngine.Types.Timing.MicroSeconds(10), + ts: Trace.Types.Timing.MicroSeconds(0), + dur: Trace.Types.Timing.MicroSeconds(10), }; const eventTwo = { ...defaultTraceEvent, - ts: TraceEngine.Types.Timing.MicroSeconds(5), - dur: TraceEngine.Types.Timing.MicroSeconds(10), + ts: Trace.Types.Timing.MicroSeconds(5), + dur: Trace.Types.Timing.MicroSeconds(10), }; const eventThree = { ...defaultTraceEvent, - ts: TraceEngine.Types.Timing.MicroSeconds(20), - dur: TraceEngine.Types.Timing.MicroSeconds(10), + ts: Trace.Types.Timing.MicroSeconds(20), + dur: Trace.Types.Timing.MicroSeconds(10), }; let level = Timeline.AppenderUtils.getEventLevel(eventOne, lastTimestampByLevel); // For first event, the track is empty, so it always returns 0. @@ -109,23 +140,23 @@ describeWithEnvironment('AppenderUtils', () => { const lastTimestampByLevel = []; const eventOne = { ...defaultTraceEvent, - ts: TraceEngine.Types.Timing.MicroSeconds(0), - dur: TraceEngine.Types.Timing.MicroSeconds(30), + ts: Trace.Types.Timing.MicroSeconds(0), + dur: Trace.Types.Timing.MicroSeconds(30), }; const eventTwo = { ...defaultTraceEvent, - ts: TraceEngine.Types.Timing.MicroSeconds(5), - dur: TraceEngine.Types.Timing.MicroSeconds(10), + ts: Trace.Types.Timing.MicroSeconds(5), + dur: Trace.Types.Timing.MicroSeconds(10), }; const eventThree = { ...defaultTraceEvent, - ts: TraceEngine.Types.Timing.MicroSeconds(10), - dur: TraceEngine.Types.Timing.MicroSeconds(2), + ts: Trace.Types.Timing.MicroSeconds(10), + dur: Trace.Types.Timing.MicroSeconds(2), }; const eventFour = { ...defaultTraceEvent, - ts: TraceEngine.Types.Timing.MicroSeconds(20), - dur: TraceEngine.Types.Timing.MicroSeconds(10), + ts: Trace.Types.Timing.MicroSeconds(20), + dur: Trace.Types.Timing.MicroSeconds(10), }; let level = Timeline.AppenderUtils.getEventLevel(eventOne, lastTimestampByLevel); // For first event, the track is empty, so it always returns 0. diff --git a/public/panels/timeline/track_appenders/AppenderUtils.test.js.map b/public/panels/timeline/track_appenders/AppenderUtils.test.js.map index cdc10e71a..818f0da85 100644 --- a/public/panels/timeline/track_appenders/AppenderUtils.test.js.map +++ b/public/panels/timeline/track_appenders/AppenderUtils.test.js.map @@ -1 +1 @@ -{"version":3,"file":"AppenderUtils.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/track_appenders/AppenderUtils.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceEngine from '../../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {defaultTraceEvent} from '../../../testing/TraceHelpers.js';\nimport type * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as Timeline from '../timeline.js';\n\ndescribeWithEnvironment('AppenderUtils', () => {\n const defaultGroupStyle = {\n padding: 4,\n height: 17,\n collapsible: true,\n // This color is same as --sys-color-on-surface in themeColors.css\n color: 'rgb(31 31 31 / 100%)',\n // This color is same as --sys-color-cdt-base-container in themeColors.css\n backgroundColor: 'rgb(253 252 251 / 100%)',\n nestingLevel: 0,\n shareHeaderLine: true,\n };\n\n describe('buildGroupStyle', () => {\n it('builds default GroupStyle correctly', () => {\n const builtGroupStyle = Timeline.AppenderUtils.buildGroupStyle();\n assert.deepEqual(builtGroupStyle, defaultGroupStyle);\n });\n\n it('builds GroupStyle with customized fields correctly', () => {\n const gpuGroupStyle = {...defaultGroupStyle};\n gpuGroupStyle.shareHeaderLine = false;\n\n const builtGroupStyle = Timeline.AppenderUtils.buildGroupStyle({shareHeaderLine: false});\n assert.deepEqual(builtGroupStyle, gpuGroupStyle);\n });\n });\n\n describe('buildTrackHeader', () => {\n const legends: PerfUI.FlameChart.Legend[] = [{\n color: 'yellow',\n category: 'test',\n }];\n const trackHeader = {\n startLevel: 0,\n name: 'Header Name',\n style: defaultGroupStyle,\n selectable: true,\n expanded: true,\n showStackContextMenu: true,\n legends,\n jslogContext: 'animations',\n } as PerfUI.FlameChart.Group;\n\n it('builds a track header correctly', () => {\n const builtHeader = Timeline.AppenderUtils.buildTrackHeader(\n Timeline.CompatibilityTracksAppender.VisualLoggingTrackName.ANIMATIONS,\n /* startLevel= */ 0, 'Header Name', Timeline.AppenderUtils.buildGroupStyle(), /* selectable= */ true,\n /* expanded= */ true, /* showStackContextMenu= */ true, legends);\n assert.deepEqual(builtHeader, trackHeader);\n });\n });\n\n describe('getFormattedTime', () => {\n it('returns the time info for a entry with no duration correctly', async () => {\n const formattedTime = Timeline.AppenderUtils.getFormattedTime(defaultTraceEvent.dur);\n assert.strictEqual(formattedTime, '');\n });\n\n it('returns the time info for given total time correctly', async () => {\n const totalTime = TraceEngine.Types.Timing.MicroSeconds(10000);\n const formattedTime = Timeline.AppenderUtils.getFormattedTime(totalTime);\n // The i18n encodes spaces using the u00A0 unicode character.\n assert.strictEqual(formattedTime, '10.00\\u00A0ms');\n });\n\n it('returns the time info for given total time and self time correctly', async () => {\n const totalTime = TraceEngine.Types.Timing.MicroSeconds(10000);\n const selfTime = TraceEngine.Types.Timing.MicroSeconds(1000);\n const formattedTime = Timeline.AppenderUtils.getFormattedTime(totalTime, selfTime);\n // The i18n encodes spaces using the u00A0 unicode character.\n assert.strictEqual(formattedTime, '10.00\\u00A0ms (self 1.00\\u00A0ms)');\n });\n\n it('returns the time info for same total time and self time correctly', async () => {\n const totalTime = TraceEngine.Types.Timing.MicroSeconds(10000);\n const selfTime = TraceEngine.Types.Timing.MicroSeconds(10000);\n const formattedTime = Timeline.AppenderUtils.getFormattedTime(totalTime, selfTime);\n // The i18n encodes spaces using the u00A0 unicode character.\n assert.strictEqual(formattedTime, '10.00\\u00A0ms');\n });\n });\n\n describe('getEventLevel', () => {\n it('returns the level for async events correctly', async () => {\n const lastTimestampByLevel: Timeline.AppenderUtils.LastTimestampByLevel = [];\n const eventOne = {\n ...defaultTraceEvent,\n ts: TraceEngine.Types.Timing.MicroSeconds(0),\n dur: TraceEngine.Types.Timing.MicroSeconds(10),\n };\n const eventTwo = {\n ...defaultTraceEvent,\n ts: TraceEngine.Types.Timing.MicroSeconds(5),\n dur: TraceEngine.Types.Timing.MicroSeconds(10),\n };\n const eventThree = {\n ...defaultTraceEvent,\n ts: TraceEngine.Types.Timing.MicroSeconds(20),\n dur: TraceEngine.Types.Timing.MicroSeconds(10),\n };\n\n let level = Timeline.AppenderUtils.getEventLevel(eventOne, lastTimestampByLevel);\n // For first event, the track is empty, so it always returns 0.\n assert.strictEqual(level, 0);\n\n level = Timeline.AppenderUtils.getEventLevel(eventTwo, lastTimestampByLevel);\n // For eventTwo, its start time is smaller than eventOne's end time, so it should be appended to level 1.\n assert.strictEqual(level, 1);\n\n level = Timeline.AppenderUtils.getEventLevel(eventThree, lastTimestampByLevel);\n // For eventThree, it doesn't overlap with eventOne, so it can fit in level 0.\n assert.strictEqual(level, 0);\n });\n\n it('returns the level for sync events correctly', async () => {\n const lastTimestampByLevel: Timeline.AppenderUtils.LastTimestampByLevel = [];\n const eventOne = {\n ...defaultTraceEvent,\n ts: TraceEngine.Types.Timing.MicroSeconds(0),\n dur: TraceEngine.Types.Timing.MicroSeconds(30),\n };\n const eventTwo = {\n ...defaultTraceEvent,\n ts: TraceEngine.Types.Timing.MicroSeconds(5),\n dur: TraceEngine.Types.Timing.MicroSeconds(10),\n };\n const eventThree = {\n ...defaultTraceEvent,\n ts: TraceEngine.Types.Timing.MicroSeconds(10),\n dur: TraceEngine.Types.Timing.MicroSeconds(2),\n };\n const eventFour = {\n ...defaultTraceEvent,\n ts: TraceEngine.Types.Timing.MicroSeconds(20),\n dur: TraceEngine.Types.Timing.MicroSeconds(10),\n };\n\n let level = Timeline.AppenderUtils.getEventLevel(eventOne, lastTimestampByLevel);\n // For first event, the track is empty, so it always returns 0.\n assert.strictEqual(level, 0);\n\n level = Timeline.AppenderUtils.getEventLevel(eventTwo, lastTimestampByLevel);\n // For eventTwo, its time is a subset of the eventOne, so it will be append as eventOne's child.\n assert.strictEqual(level, 1);\n\n level = Timeline.AppenderUtils.getEventLevel(eventThree, lastTimestampByLevel);\n // For eventTwo, its time is a subset of the eventTwo, so it will be append as eventTwo's child.\n assert.strictEqual(level, 2);\n\n level = Timeline.AppenderUtils.getEventLevel(eventFour, lastTimestampByLevel);\n // For eventFour, its time is a subset of eventOne but not eventTwo, so it will be append as eventTwo's child.\n assert.strictEqual(level, 1);\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"AppenderUtils.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/track_appenders/AppenderUtils.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {defaultTraceEvent} from '../../../testing/TraceHelpers.js';\nimport type * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as Timeline from '../timeline.js';\n\ndescribeWithEnvironment('AppenderUtils', () => {\n const defaultGroupStyle = {\n padding: 4,\n height: 17,\n collapsible: true,\n // This color is same as --sys-color-on-surface in themeColors.css\n color: 'rgb(31 31 31 / 100%)',\n // This color is same as --sys-color-cdt-base-container in themeColors.css\n backgroundColor: 'rgb(253 252 251 / 100%)',\n nestingLevel: 0,\n shareHeaderLine: true,\n };\n\n describe('buildGroupStyle', () => {\n it('builds default GroupStyle correctly', () => {\n const builtGroupStyle = Timeline.AppenderUtils.buildGroupStyle();\n assert.deepEqual(builtGroupStyle, defaultGroupStyle);\n });\n\n it('builds GroupStyle with customized fields correctly', () => {\n const gpuGroupStyle = {...defaultGroupStyle};\n gpuGroupStyle.shareHeaderLine = false;\n\n const builtGroupStyle = Timeline.AppenderUtils.buildGroupStyle({shareHeaderLine: false});\n assert.deepEqual(builtGroupStyle, gpuGroupStyle);\n });\n });\n\n describe('buildTrackHeader', () => {\n const legends: PerfUI.FlameChart.Legend[] = [{\n color: 'yellow',\n category: 'test',\n }];\n const trackHeader = {\n startLevel: 0,\n name: 'Header Name',\n style: defaultGroupStyle,\n selectable: true,\n expanded: true,\n showStackContextMenu: true,\n legends,\n jslogContext: 'animations',\n } as PerfUI.FlameChart.Group;\n\n it('builds a track header correctly', () => {\n const builtHeader = Timeline.AppenderUtils.buildTrackHeader(\n Timeline.CompatibilityTracksAppender.VisualLoggingTrackName.ANIMATIONS,\n /* startLevel= */ 0, 'Header Name', Timeline.AppenderUtils.buildGroupStyle(), /* selectable= */ true,\n /* expanded= */ true, /* showStackContextMenu= */ true, legends);\n assert.deepEqual(builtHeader, trackHeader);\n });\n });\n\n describe('getFormattedTime', () => {\n // Helper method. Treat input as milliseconds\n const getFormattedTime = (tot: number, self: number): string => {\n const totalTime = Trace.Helpers.Timing.millisecondsToMicroseconds(Trace.Types.Timing.MilliSeconds(tot));\n const selfTime = Trace.Helpers.Timing.millisecondsToMicroseconds(Trace.Types.Timing.MilliSeconds(self));\n return Timeline.AppenderUtils.getFormattedTime(totalTime, selfTime);\n };\n\n it('returns the time info for a entry with no duration correctly', async () => {\n const totalTime = Trace.Types.Timing.MicroSeconds(0);\n const formattedTime = Timeline.AppenderUtils.getFormattedTime(totalTime);\n assert.strictEqual(formattedTime, '');\n\n const formattedTime2 = Timeline.AppenderUtils.getFormattedTime(undefined);\n assert.strictEqual(formattedTime2, '');\n });\n\n it('returns the time info for given total time correctly', async () => {\n const totalTime = Trace.Types.Timing.MicroSeconds(10000);\n const formattedTime = Timeline.AppenderUtils.getFormattedTime(totalTime);\n // The i18n encodes spaces using the u00A0 unicode character.\n assert.strictEqual(formattedTime, '10.00\\u00A0ms');\n });\n\n it('returns the time info for given total time and self time correctly', async () => {\n const totalTime = Trace.Types.Timing.MicroSeconds(10000);\n const selfTime = Trace.Types.Timing.MicroSeconds(1000);\n const formattedTime = Timeline.AppenderUtils.getFormattedTime(totalTime, selfTime);\n // The i18n encodes spaces using the u00A0 unicode character.\n assert.strictEqual(formattedTime, '10.00\\u00A0ms (self 1.00\\u00A0ms)');\n });\n\n it('returns the time info for same total time and self time correctly', async () => {\n const totalTime = Trace.Types.Timing.MicroSeconds(10000);\n const selfTime = Trace.Types.Timing.MicroSeconds(10000);\n const formattedTime = Timeline.AppenderUtils.getFormattedTime(totalTime, selfTime);\n // The i18n encodes spaces using the u00A0 unicode character.\n assert.strictEqual(formattedTime, '10.00\\u00A0ms');\n });\n\n it('has appropriate rounding', () => {\n assert.strictEqual(getFormattedTime(10, 9), '10.00\\u00A0ms (self 9.00\\u00A0ms)');\n assert.strictEqual(getFormattedTime(10, 9.99), '10.00\\u00A0ms (self 9.99\\u00A0ms)');\n assert.strictEqual(getFormattedTime(10, 9.999), '10.00\\u00A0ms (self 10.00\\u00A0ms)');\n assert.strictEqual(getFormattedTime(10, 9.9999), '10.00\\u00A0ms (self 10.00\\u00A0ms)');\n\n assert.strictEqual(getFormattedTime(8.9, 7), '8.90\\u00A0ms (self 7.00\\u00A0ms)');\n assert.strictEqual(getFormattedTime(8.99, 7), '8.99\\u00A0ms (self 7.00\\u00A0ms)');\n assert.strictEqual(getFormattedTime(8.999, 7), '9.00\\u00A0ms (self 7.00\\u00A0ms)');\n });\n\n it('selfTime is omitted if we hit minSignificance', async () => {\n // Total and self are really close\n assert.strictEqual(getFormattedTime(5, 5.00001), '5.00\\u00A0ms (self 5.00\\u00A0ms)');\n assert.strictEqual(getFormattedTime(5, 5.000001), '5.00\\u00A0ms (self 5.00\\u00A0ms)');\n assert.strictEqual(getFormattedTime(5, 5.0000001), '5.00\\u00A0ms'); // minSignificance hit!\n\n // The self is almost zero\n assert.strictEqual(getFormattedTime(10, 0.1), '10.00\\u00A0ms (self 0.10\\u00A0ms)');\n assert.strictEqual(getFormattedTime(10, 0.01), '10.00\\u00A0ms (self 10\\u00A0μs)');\n assert.strictEqual(getFormattedTime(10, 0.001), '10.00\\u00A0ms (self 1\\u00A0μs)');\n assert.strictEqual(getFormattedTime(10, 0.0001), '10.00\\u00A0ms (self 0\\u00A0μs)');\n assert.strictEqual(getFormattedTime(10, 0.00001), '10.00\\u00A0ms (self 0\\u00A0μs)');\n assert.strictEqual(getFormattedTime(10, 0.000001), '10.00\\u00A0ms'); // minSignificance hit!\n });\n });\n\n describe('getEventLevel', () => {\n it('returns the level for async events correctly', async () => {\n const lastTimestampByLevel: Timeline.AppenderUtils.LastTimestampByLevel = [];\n const eventOne = {\n ...defaultTraceEvent,\n ts: Trace.Types.Timing.MicroSeconds(0),\n dur: Trace.Types.Timing.MicroSeconds(10),\n };\n const eventTwo = {\n ...defaultTraceEvent,\n ts: Trace.Types.Timing.MicroSeconds(5),\n dur: Trace.Types.Timing.MicroSeconds(10),\n };\n const eventThree = {\n ...defaultTraceEvent,\n ts: Trace.Types.Timing.MicroSeconds(20),\n dur: Trace.Types.Timing.MicroSeconds(10),\n };\n\n let level = Timeline.AppenderUtils.getEventLevel(eventOne, lastTimestampByLevel);\n // For first event, the track is empty, so it always returns 0.\n assert.strictEqual(level, 0);\n\n level = Timeline.AppenderUtils.getEventLevel(eventTwo, lastTimestampByLevel);\n // For eventTwo, its start time is smaller than eventOne's end time, so it should be appended to level 1.\n assert.strictEqual(level, 1);\n\n level = Timeline.AppenderUtils.getEventLevel(eventThree, lastTimestampByLevel);\n // For eventThree, it doesn't overlap with eventOne, so it can fit in level 0.\n assert.strictEqual(level, 0);\n });\n\n it('returns the level for sync events correctly', async () => {\n const lastTimestampByLevel: Timeline.AppenderUtils.LastTimestampByLevel = [];\n const eventOne = {\n ...defaultTraceEvent,\n ts: Trace.Types.Timing.MicroSeconds(0),\n dur: Trace.Types.Timing.MicroSeconds(30),\n };\n const eventTwo = {\n ...defaultTraceEvent,\n ts: Trace.Types.Timing.MicroSeconds(5),\n dur: Trace.Types.Timing.MicroSeconds(10),\n };\n const eventThree = {\n ...defaultTraceEvent,\n ts: Trace.Types.Timing.MicroSeconds(10),\n dur: Trace.Types.Timing.MicroSeconds(2),\n };\n const eventFour = {\n ...defaultTraceEvent,\n ts: Trace.Types.Timing.MicroSeconds(20),\n dur: Trace.Types.Timing.MicroSeconds(10),\n };\n\n let level = Timeline.AppenderUtils.getEventLevel(eventOne, lastTimestampByLevel);\n // For first event, the track is empty, so it always returns 0.\n assert.strictEqual(level, 0);\n\n level = Timeline.AppenderUtils.getEventLevel(eventTwo, lastTimestampByLevel);\n // For eventTwo, its time is a subset of the eventOne, so it will be append as eventOne's child.\n assert.strictEqual(level, 1);\n\n level = Timeline.AppenderUtils.getEventLevel(eventThree, lastTimestampByLevel);\n // For eventTwo, its time is a subset of the eventTwo, so it will be append as eventTwo's child.\n assert.strictEqual(level, 2);\n\n level = Timeline.AppenderUtils.getEventLevel(eventFour, lastTimestampByLevel);\n // For eventFour, its time is a subset of eventOne but not eventTwo, so it will be append as eventTwo's child.\n assert.strictEqual(level, 1);\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/track_appenders/CompatibilityTracksAppender.test.js b/public/panels/timeline/track_appenders/CompatibilityTracksAppender.test.js index 45e86dc39..4819bc0ac 100644 --- a/public/panels/timeline/track_appenders/CompatibilityTracksAppender.test.js +++ b/public/panels/timeline/track_appenders/CompatibilityTracksAppender.test.js @@ -1,14 +1,14 @@ // 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 * as TraceModel from '../../../models/trace/trace.js'; +import * as Trace from '../../../models/trace/trace.js'; import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; import { setupIgnoreListManagerEnvironment } from '../../../testing/TraceHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; import * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js'; import * as Timeline from '../timeline.js'; describeWithEnvironment('CompatibilityTracksAppender', function () { - let traceData; + let parsedTrace; let tracksAppender; let entryData = []; let flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty(); @@ -17,8 +17,8 @@ describeWithEnvironment('CompatibilityTracksAppender', function () { entryData = []; flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty(); entryTypeByLevel = []; - ({ traceData } = await TraceLoader.traceEngine(context, fixture)); - tracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(flameChartData, traceData, entryData, entryTypeByLevel); + ({ parsedTrace } = await TraceLoader.traceEngine(context, fixture)); + tracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel); const timingsTrack = tracksAppender.timingsTrackAppender(); const gpuTrack = tracksAppender.gpuTrackAppender(); const threadAppenders = tracksAppender.threadAppenders(); @@ -38,11 +38,11 @@ describeWithEnvironment('CompatibilityTracksAppender', function () { const timingsTrack = tracksAppender.timingsTrackAppender(); const timingsTrackEvents = tracksAppender.eventsInTrack(timingsTrack); const allTimingEvents = [ - ...traceData.UserTimings.consoleTimings, - ...traceData.UserTimings.timestampEvents, - ...traceData.UserTimings.performanceMarks, - ...traceData.UserTimings.performanceMeasures, - ...traceData.PageLoadMetrics.allMarkerEvents.toSorted((m1, m2) => { + ...parsedTrace.UserTimings.consoleTimings, + ...parsedTrace.UserTimings.timestampEvents, + ...parsedTrace.UserTimings.performanceMarks, + ...parsedTrace.UserTimings.performanceMeasures, + ...parsedTrace.PageLoadMetrics.allMarkerEvents.toSorted((m1, m2) => { // These get sorted based on the metric so we have to replicate // that for this assertion. return Timeline.TimingsTrackAppender.SORT_ORDER_PAGE_LOAD_MARKERS[m1.name] - @@ -54,16 +54,16 @@ describeWithEnvironment('CompatibilityTracksAppender', function () { it('returns all the events appended by a track with one level', () => { const gpuTrack = tracksAppender.gpuTrackAppender(); const gpuTrackEvents = tracksAppender.eventsInTrack(gpuTrack); - assert.deepEqual(gpuTrackEvents, traceData.GPU.mainGPUThreadTasks); + assert.deepEqual(gpuTrackEvents, parsedTrace.GPU.mainGPUThreadTasks); }); }); describe('eventsForTreeView', () => { it('returns only sync events if using async events means a tree cannot be built', () => { const timingsTrack = tracksAppender.timingsTrackAppender(); const timingsEvents = tracksAppender.eventsInTrack(timingsTrack); - assert.isFalse(TraceModel.Helpers.TreeHelpers.canBuildTreesFromEvents(timingsEvents)); + assert.isFalse(Trace.Helpers.TreeHelpers.canBuildTreesFromEvents(timingsEvents)); const treeEvents = tracksAppender.eventsForTreeView(timingsTrack); - const allEventsAreSync = treeEvents.every(event => !TraceModel.Types.TraceEvents.isAsyncPhase(event.ph)); + const allEventsAreSync = treeEvents.every(event => !Trace.Types.Events.isPhaseAsync(event.ph)); assert.isTrue(allEventsAreSync); }); it('returns both sync and async events if a tree can be built with them', async () => { @@ -71,7 +71,7 @@ describeWithEnvironment('CompatibilityTracksAppender', function () { await initTrackAppender(this, 'sync-like-timings.json.gz'); const timingsTrack = tracksAppender.timingsTrackAppender(); const timingsEvents = tracksAppender.eventsInTrack(timingsTrack); - assert.isTrue(TraceModel.Helpers.TreeHelpers.canBuildTreesFromEvents(timingsEvents)); + assert.isTrue(Trace.Helpers.TreeHelpers.canBuildTreesFromEvents(timingsEvents)); const treeEvents = tracksAppender.eventsForTreeView(timingsTrack); assert.deepEqual(treeEvents, timingsEvents); }); @@ -79,16 +79,16 @@ describeWithEnvironment('CompatibilityTracksAppender', function () { // This file contains two rasterizer threads which should be // nested inside the same header. await initTrackAppender(this, 'lcp-images-rasterizer.json.gz'); - const rasterTracks = tracksAppender.threadAppenders().filter(threadAppender => threadAppender.threadType === "RASTERIZER" /* TraceModel.Handlers.Threads.ThreadType.RASTERIZER */); + const rasterTracks = tracksAppender.threadAppenders().filter(threadAppender => threadAppender.threadType === "RASTERIZER" /* Trace.Handlers.Threads.ThreadType.RASTERIZER */); assert.strictEqual(rasterTracks.length, 2); const raster1Events = tracksAppender.eventsInTrack(rasterTracks[0]); assert.strictEqual(raster1Events.length, 6); - assert.isTrue(TraceModel.Helpers.TreeHelpers.canBuildTreesFromEvents(raster1Events)); + assert.isTrue(Trace.Helpers.TreeHelpers.canBuildTreesFromEvents(raster1Events)); const raster1TreeEvents = tracksAppender.eventsForTreeView(rasterTracks[0]); assert.deepEqual(raster1TreeEvents, raster1Events); const raster2Events = tracksAppender.eventsInTrack(rasterTracks[1]); assert.strictEqual(raster2Events.length, 1); - assert.isTrue(TraceModel.Helpers.TreeHelpers.canBuildTreesFromEvents(raster2Events)); + assert.isTrue(Trace.Helpers.TreeHelpers.canBuildTreesFromEvents(raster2Events)); const raster2TreeEvents = tracksAppender.eventsForTreeView(rasterTracks[1]); assert.deepEqual(raster2TreeEvents, raster2Events); }); @@ -102,11 +102,11 @@ describeWithEnvironment('CompatibilityTracksAppender', function () { assert.fail('Could not find events for group'); } const allTimingEvents = [ - ...traceData.UserTimings.consoleTimings, - ...traceData.UserTimings.timestampEvents, - ...traceData.UserTimings.performanceMarks, - ...traceData.UserTimings.performanceMeasures, - ...traceData.PageLoadMetrics.allMarkerEvents.toSorted((m1, m2) => { + ...parsedTrace.UserTimings.consoleTimings, + ...parsedTrace.UserTimings.timestampEvents, + ...parsedTrace.UserTimings.performanceMarks, + ...parsedTrace.UserTimings.performanceMeasures, + ...parsedTrace.PageLoadMetrics.allMarkerEvents.toSorted((m1, m2) => { // These get sorted based on the metric so we have to replicate // that for this assertion. return Timeline.TimingsTrackAppender.SORT_ORDER_PAGE_LOAD_MARKERS[m1.name] - @@ -120,14 +120,14 @@ describeWithEnvironment('CompatibilityTracksAppender', function () { if (!gpuGroupEvents) { assert.fail('Could not find events for group'); } - assert.deepEqual(gpuGroupEvents, traceData.GPU.mainGPUThreadTasks); + assert.deepEqual(gpuGroupEvents, parsedTrace.GPU.mainGPUThreadTasks); }); }); }); describe('highlightedEntryInfo', () => { it('shows the correct warning for a long task when hovered', async function () { await initTrackAppender(this, 'simple-js-program.json.gz'); - const events = traceData.Renderer?.allTraceEntries; + const events = parsedTrace.Renderer?.allTraceEntries; if (!events) { throw new Error('Could not find renderer events'); } @@ -145,7 +145,7 @@ describeWithEnvironment('CompatibilityTracksAppender', function () { }); it('shows the correct warning for a forced recalc styles when hovered', async function () { await initTrackAppender(this, 'large-layout-small-recalc.json.gz'); - const events = traceData.Warnings.perWarning.get('FORCED_REFLOW') || []; + const events = parsedTrace.Warnings.perWarning.get('FORCED_REFLOW') || []; if (!events) { throw new Error('Could not find forced reflows events'); } @@ -163,7 +163,7 @@ describeWithEnvironment('CompatibilityTracksAppender', function () { }); it('shows the correct warning for a forced layout when hovered', async function () { await initTrackAppender(this, 'large-layout-small-recalc.json.gz'); - const events = traceData.Warnings.perWarning.get('FORCED_REFLOW') || []; + const events = parsedTrace.Warnings.perWarning.get('FORCED_REFLOW') || []; if (!events) { throw new Error('Could not find forced reflows events'); } @@ -181,13 +181,13 @@ describeWithEnvironment('CompatibilityTracksAppender', function () { }); it('shows the correct warning for slow idle callbacks', async function () { await initTrackAppender(this, 'idle-callback.json.gz'); - const events = traceData.Renderer?.allTraceEntries; + const events = parsedTrace.Renderer?.allTraceEntries; if (!events) { throw new Error('Could not find renderer events'); } const idleCallback = events.find(event => { - const { duration } = TraceModel.Helpers.Timing.eventTimingsMilliSeconds(event); - if (!TraceModel.Types.TraceEvents.isTraceEventFireIdleCallback(event)) { + const { duration } = Trace.Helpers.Timing.eventTimingsMilliSeconds(event); + if (!Trace.Types.Events.isFireIdleCallback(event)) { return false; } if (duration <= event.args.data.allottedMilliseconds) { diff --git a/public/panels/timeline/track_appenders/CompatibilityTracksAppender.test.js.map b/public/panels/timeline/track_appenders/CompatibilityTracksAppender.test.js.map index a255022bb..a4454f5c9 100644 --- a/public/panels/timeline/track_appenders/CompatibilityTracksAppender.test.js.map +++ b/public/panels/timeline/track_appenders/CompatibilityTracksAppender.test.js.map @@ -1 +1 @@ -{"version":3,"file":"CompatibilityTracksAppender.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/track_appenders/CompatibilityTracksAppender.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceModel from '../../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {setupIgnoreListManagerEnvironment} from '../../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as Timeline from '../timeline.js';\n\ndescribeWithEnvironment('CompatibilityTracksAppender', function() {\n let traceData: TraceModel.Handlers.Types.TraceParseData;\n let tracksAppender: Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender;\n let entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[] = [];\n let flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n let entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[] = [];\n\n async function initTrackAppender(\n context: Mocha.Suite|Mocha.Context, fixture = 'timings-track.json.gz'): Promise {\n entryData = [];\n flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n entryTypeByLevel = [];\n ({traceData} = await TraceLoader.traceEngine(context, fixture));\n tracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(\n flameChartData, traceData, entryData, entryTypeByLevel);\n const timingsTrack = tracksAppender.timingsTrackAppender();\n const gpuTrack = tracksAppender.gpuTrackAppender();\n const threadAppenders = tracksAppender.threadAppenders();\n let currentLevel = timingsTrack.appendTrackAtLevel(0);\n currentLevel = gpuTrack.appendTrackAtLevel(currentLevel);\n for (const threadAppender of threadAppenders) {\n currentLevel = threadAppender.appendTrackAtLevel(currentLevel);\n }\n }\n\n beforeEach(async () => {\n setupIgnoreListManagerEnvironment();\n await initTrackAppender(this);\n });\n\n describe('Tree view data', () => {\n describe('eventsInTrack', () => {\n it('returns all the events appended by a track with multiple levels', () => {\n const timingsTrack = tracksAppender.timingsTrackAppender();\n const timingsTrackEvents = tracksAppender.eventsInTrack(timingsTrack);\n const allTimingEvents = [\n ...traceData.UserTimings.consoleTimings,\n ...traceData.UserTimings.timestampEvents,\n ...traceData.UserTimings.performanceMarks,\n ...traceData.UserTimings.performanceMeasures,\n ...traceData.PageLoadMetrics.allMarkerEvents.toSorted((m1, m2) => {\n // These get sorted based on the metric so we have to replicate\n // that for this assertion.\n return Timeline.TimingsTrackAppender.SORT_ORDER_PAGE_LOAD_MARKERS[m1.name] -\n Timeline.TimingsTrackAppender.SORT_ORDER_PAGE_LOAD_MARKERS[m2.name];\n }),\n ].sort((a, b) => a.ts - b.ts);\n assert.deepEqual(timingsTrackEvents, allTimingEvents);\n });\n\n it('returns all the events appended by a track with one level', () => {\n const gpuTrack = tracksAppender.gpuTrackAppender();\n const gpuTrackEvents =\n tracksAppender.eventsInTrack(gpuTrack) as readonly TraceModel.Types.TraceEvents.TraceEventData[];\n assert.deepEqual(gpuTrackEvents, traceData.GPU.mainGPUThreadTasks);\n });\n });\n describe('eventsForTreeView', () => {\n it('returns only sync events if using async events means a tree cannot be built', () => {\n const timingsTrack = tracksAppender.timingsTrackAppender();\n const timingsEvents = tracksAppender.eventsInTrack(timingsTrack);\n assert.isFalse(TraceModel.Helpers.TreeHelpers.canBuildTreesFromEvents(timingsEvents));\n const treeEvents = tracksAppender.eventsForTreeView(timingsTrack);\n const allEventsAreSync = treeEvents.every(event => !TraceModel.Types.TraceEvents.isAsyncPhase(event.ph));\n assert.isTrue(allEventsAreSync);\n });\n it('returns both sync and async events if a tree can be built with them', async () => {\n // This file contains events in the timings track that can be assembled as a tree\n await initTrackAppender(this, 'sync-like-timings.json.gz');\n const timingsTrack = tracksAppender.timingsTrackAppender();\n const timingsEvents = tracksAppender.eventsInTrack(timingsTrack);\n assert.isTrue(TraceModel.Helpers.TreeHelpers.canBuildTreesFromEvents(timingsEvents));\n const treeEvents = tracksAppender.eventsForTreeView(timingsTrack);\n assert.deepEqual(treeEvents, timingsEvents);\n });\n\n it('returns events for tree view for nested tracks', async () => {\n // This file contains two rasterizer threads which should be\n // nested inside the same header.\n await initTrackAppender(this, 'lcp-images-rasterizer.json.gz');\n const rasterTracks = tracksAppender.threadAppenders().filter(\n threadAppender => threadAppender.threadType === TraceModel.Handlers.Threads.ThreadType.RASTERIZER);\n assert.strictEqual(rasterTracks.length, 2);\n\n const raster1Events = tracksAppender.eventsInTrack(rasterTracks[0]);\n assert.strictEqual(raster1Events.length, 6);\n assert.isTrue(TraceModel.Helpers.TreeHelpers.canBuildTreesFromEvents(raster1Events));\n const raster1TreeEvents = tracksAppender.eventsForTreeView(rasterTracks[0]);\n assert.deepEqual(raster1TreeEvents, raster1Events);\n\n const raster2Events = tracksAppender.eventsInTrack(rasterTracks[1]);\n assert.strictEqual(raster2Events.length, 1);\n assert.isTrue(TraceModel.Helpers.TreeHelpers.canBuildTreesFromEvents(raster2Events));\n const raster2TreeEvents = tracksAppender.eventsForTreeView(rasterTracks[1]);\n assert.deepEqual(raster2TreeEvents, raster2Events);\n });\n });\n describe('groupEventsForTreeView', () => {\n it('returns all the events of a flame chart group with multiple levels', async () => {\n // This file contains events in the timings track that can be assembled as a tree\n await initTrackAppender(this, 'sync-like-timings.json.gz');\n const timingsGroupEvents = tracksAppender.groupEventsForTreeView(flameChartData.groups[0]);\n if (!timingsGroupEvents) {\n assert.fail('Could not find events for group');\n }\n const allTimingEvents = [\n ...traceData.UserTimings.consoleTimings,\n ...traceData.UserTimings.timestampEvents,\n ...traceData.UserTimings.performanceMarks,\n ...traceData.UserTimings.performanceMeasures,\n ...traceData.PageLoadMetrics.allMarkerEvents.toSorted((m1, m2) => {\n // These get sorted based on the metric so we have to replicate\n // that for this assertion.\n return Timeline.TimingsTrackAppender.SORT_ORDER_PAGE_LOAD_MARKERS[m1.name] -\n Timeline.TimingsTrackAppender.SORT_ORDER_PAGE_LOAD_MARKERS[m2.name];\n }),\n ].sort((a, b) => a.ts - b.ts);\n assert.deepEqual(timingsGroupEvents, allTimingEvents);\n });\n it('returns all the events of a flame chart group with one level', () => {\n const gpuGroupEvents = tracksAppender.groupEventsForTreeView(flameChartData.groups[1]) as\n readonly TraceModel.Types.TraceEvents.TraceEventData[];\n if (!gpuGroupEvents) {\n assert.fail('Could not find events for group');\n }\n assert.deepEqual(gpuGroupEvents, traceData.GPU.mainGPUThreadTasks);\n });\n });\n });\n\n describe('highlightedEntryInfo', () => {\n it('shows the correct warning for a long task when hovered', async function() {\n await initTrackAppender(this, 'simple-js-program.json.gz');\n const events = traceData.Renderer?.allTraceEntries;\n if (!events) {\n throw new Error('Could not find renderer events');\n }\n const longTask = events.find(e => (e.dur || 0) > 1_000_000);\n if (!longTask) {\n throw new Error('Could not find long task');\n }\n const info = tracksAppender.highlightedEntryInfo(longTask, 2);\n assert.strictEqual(info.warningElements?.length, 1);\n const warning = info.warningElements?.[0];\n if (!(warning instanceof HTMLSpanElement)) {\n throw new Error('Found unexpected warning');\n }\n assert.strictEqual(warning?.innerText, 'Long task took 1.30\\u00A0s.');\n });\n\n it('shows the correct warning for a forced recalc styles when hovered', async function() {\n await initTrackAppender(this, 'large-layout-small-recalc.json.gz');\n const events = traceData.Warnings.perWarning.get('FORCED_REFLOW') || [];\n\n if (!events) {\n throw new Error('Could not find forced reflows events');\n }\n const recalcStyles = events[0];\n if (!recalcStyles) {\n throw new Error('Could not find recalc styles');\n }\n const info = tracksAppender.highlightedEntryInfo(recalcStyles, 2);\n assert.strictEqual(info.warningElements?.length, 1);\n const warning = info.warningElements?.[0];\n if (!(warning instanceof HTMLSpanElement)) {\n throw new Error('Found unexpected warning');\n }\n assert.strictEqual(warning?.innerText, 'Forced reflow is a likely performance bottleneck.');\n });\n\n it('shows the correct warning for a forced layout when hovered', async function() {\n await initTrackAppender(this, 'large-layout-small-recalc.json.gz');\n const events = traceData.Warnings.perWarning.get('FORCED_REFLOW') || [];\n\n if (!events) {\n throw new Error('Could not find forced reflows events');\n }\n const layout = events[1];\n if (!layout) {\n throw new Error('Could not find layout');\n }\n const info = tracksAppender.highlightedEntryInfo(layout, 2);\n assert.strictEqual(info.warningElements?.length, 1);\n const warning = info.warningElements?.[0];\n if (!(warning instanceof HTMLSpanElement)) {\n throw new Error('Found unexpected warning');\n }\n assert.strictEqual(warning?.innerText, 'Forced reflow is a likely performance bottleneck.');\n });\n\n it('shows the correct warning for slow idle callbacks', async function() {\n await initTrackAppender(this, 'idle-callback.json.gz');\n const events = traceData.Renderer?.allTraceEntries;\n if (!events) {\n throw new Error('Could not find renderer events');\n }\n const idleCallback = events.find(event => {\n const {duration} = TraceModel.Helpers.Timing.eventTimingsMilliSeconds(event);\n if (!TraceModel.Types.TraceEvents.isTraceEventFireIdleCallback(event)) {\n return false;\n }\n if (duration <= event.args.data.allottedMilliseconds) {\n false;\n }\n return true;\n });\n if (!idleCallback) {\n throw new Error('Could not find idle callback');\n }\n const info = tracksAppender.highlightedEntryInfo(idleCallback, 2);\n assert.strictEqual(info.warningElements?.length, 1);\n const warning = info.warningElements?.[0];\n if (!(warning instanceof HTMLSpanElement)) {\n throw new Error('Found unexpected warning');\n }\n assert.strictEqual(warning?.innerText, 'Idle callback execution extended beyond deadline by 79.56\\u00A0ms');\n });\n });\n\n it('can return the group for a given level', async () => {\n await initTrackAppender(this, 'web-dev-with-commit.json.gz');\n // The order of these groups might seem odd, but it's based on the setup in\n // the initTrackAppender function which does Timings, GPU and then threads.\n const groupForLevel0 = tracksAppender.groupForLevel(0);\n assert.strictEqual(groupForLevel0?.name, 'Timings');\n const groupForLevel1 = tracksAppender.groupForLevel(1);\n assert.strictEqual(groupForLevel1?.name, 'GPU');\n const groupForLevel2 = tracksAppender.groupForLevel(2);\n assert.strictEqual(groupForLevel2?.name, 'Main — https://web.dev/');\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"CompatibilityTracksAppender.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/track_appenders/CompatibilityTracksAppender.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {setupIgnoreListManagerEnvironment} from '../../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as Timeline from '../timeline.js';\n\ndescribeWithEnvironment('CompatibilityTracksAppender', function() {\n let parsedTrace: Trace.Handlers.Types.ParsedTrace;\n let tracksAppender: Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender;\n let entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[] = [];\n let flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n let entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[] = [];\n\n async function initTrackAppender(\n context: Mocha.Suite|Mocha.Context, fixture = 'timings-track.json.gz'): Promise {\n entryData = [];\n flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n entryTypeByLevel = [];\n ({parsedTrace} = await TraceLoader.traceEngine(context, fixture));\n tracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(\n flameChartData, parsedTrace, entryData, entryTypeByLevel);\n const timingsTrack = tracksAppender.timingsTrackAppender();\n const gpuTrack = tracksAppender.gpuTrackAppender();\n const threadAppenders = tracksAppender.threadAppenders();\n let currentLevel = timingsTrack.appendTrackAtLevel(0);\n currentLevel = gpuTrack.appendTrackAtLevel(currentLevel);\n for (const threadAppender of threadAppenders) {\n currentLevel = threadAppender.appendTrackAtLevel(currentLevel);\n }\n }\n\n beforeEach(async () => {\n setupIgnoreListManagerEnvironment();\n await initTrackAppender(this);\n });\n\n describe('Tree view data', () => {\n describe('eventsInTrack', () => {\n it('returns all the events appended by a track with multiple levels', () => {\n const timingsTrack = tracksAppender.timingsTrackAppender();\n const timingsTrackEvents = tracksAppender.eventsInTrack(timingsTrack);\n const allTimingEvents = [\n ...parsedTrace.UserTimings.consoleTimings,\n ...parsedTrace.UserTimings.timestampEvents,\n ...parsedTrace.UserTimings.performanceMarks,\n ...parsedTrace.UserTimings.performanceMeasures,\n ...parsedTrace.PageLoadMetrics.allMarkerEvents.toSorted((m1, m2) => {\n // These get sorted based on the metric so we have to replicate\n // that for this assertion.\n return Timeline.TimingsTrackAppender.SORT_ORDER_PAGE_LOAD_MARKERS[m1.name] -\n Timeline.TimingsTrackAppender.SORT_ORDER_PAGE_LOAD_MARKERS[m2.name];\n }),\n ].sort((a, b) => a.ts - b.ts);\n assert.deepEqual(timingsTrackEvents, allTimingEvents);\n });\n\n it('returns all the events appended by a track with one level', () => {\n const gpuTrack = tracksAppender.gpuTrackAppender();\n const gpuTrackEvents = tracksAppender.eventsInTrack(gpuTrack) as readonly Trace.Types.Events.Event[];\n assert.deepEqual(gpuTrackEvents, parsedTrace.GPU.mainGPUThreadTasks);\n });\n });\n describe('eventsForTreeView', () => {\n it('returns only sync events if using async events means a tree cannot be built', () => {\n const timingsTrack = tracksAppender.timingsTrackAppender();\n const timingsEvents = tracksAppender.eventsInTrack(timingsTrack);\n assert.isFalse(Trace.Helpers.TreeHelpers.canBuildTreesFromEvents(timingsEvents));\n const treeEvents = tracksAppender.eventsForTreeView(timingsTrack);\n const allEventsAreSync = treeEvents.every(event => !Trace.Types.Events.isPhaseAsync(event.ph));\n assert.isTrue(allEventsAreSync);\n });\n it('returns both sync and async events if a tree can be built with them', async () => {\n // This file contains events in the timings track that can be assembled as a tree\n await initTrackAppender(this, 'sync-like-timings.json.gz');\n const timingsTrack = tracksAppender.timingsTrackAppender();\n const timingsEvents = tracksAppender.eventsInTrack(timingsTrack);\n assert.isTrue(Trace.Helpers.TreeHelpers.canBuildTreesFromEvents(timingsEvents));\n const treeEvents = tracksAppender.eventsForTreeView(timingsTrack);\n assert.deepEqual(treeEvents, timingsEvents);\n });\n\n it('returns events for tree view for nested tracks', async () => {\n // This file contains two rasterizer threads which should be\n // nested inside the same header.\n await initTrackAppender(this, 'lcp-images-rasterizer.json.gz');\n const rasterTracks = tracksAppender.threadAppenders().filter(\n threadAppender => threadAppender.threadType === Trace.Handlers.Threads.ThreadType.RASTERIZER);\n assert.strictEqual(rasterTracks.length, 2);\n\n const raster1Events = tracksAppender.eventsInTrack(rasterTracks[0]);\n assert.strictEqual(raster1Events.length, 6);\n assert.isTrue(Trace.Helpers.TreeHelpers.canBuildTreesFromEvents(raster1Events));\n const raster1TreeEvents = tracksAppender.eventsForTreeView(rasterTracks[0]);\n assert.deepEqual(raster1TreeEvents, raster1Events);\n\n const raster2Events = tracksAppender.eventsInTrack(rasterTracks[1]);\n assert.strictEqual(raster2Events.length, 1);\n assert.isTrue(Trace.Helpers.TreeHelpers.canBuildTreesFromEvents(raster2Events));\n const raster2TreeEvents = tracksAppender.eventsForTreeView(rasterTracks[1]);\n assert.deepEqual(raster2TreeEvents, raster2Events);\n });\n });\n describe('groupEventsForTreeView', () => {\n it('returns all the events of a flame chart group with multiple levels', async () => {\n // This file contains events in the timings track that can be assembled as a tree\n await initTrackAppender(this, 'sync-like-timings.json.gz');\n const timingsGroupEvents = tracksAppender.groupEventsForTreeView(flameChartData.groups[0]);\n if (!timingsGroupEvents) {\n assert.fail('Could not find events for group');\n }\n const allTimingEvents = [\n ...parsedTrace.UserTimings.consoleTimings,\n ...parsedTrace.UserTimings.timestampEvents,\n ...parsedTrace.UserTimings.performanceMarks,\n ...parsedTrace.UserTimings.performanceMeasures,\n ...parsedTrace.PageLoadMetrics.allMarkerEvents.toSorted((m1, m2) => {\n // These get sorted based on the metric so we have to replicate\n // that for this assertion.\n return Timeline.TimingsTrackAppender.SORT_ORDER_PAGE_LOAD_MARKERS[m1.name] -\n Timeline.TimingsTrackAppender.SORT_ORDER_PAGE_LOAD_MARKERS[m2.name];\n }),\n ].sort((a, b) => a.ts - b.ts);\n assert.deepEqual(timingsGroupEvents, allTimingEvents);\n });\n it('returns all the events of a flame chart group with one level', () => {\n const gpuGroupEvents =\n tracksAppender.groupEventsForTreeView(flameChartData.groups[1]) as readonly Trace.Types.Events.Event[];\n if (!gpuGroupEvents) {\n assert.fail('Could not find events for group');\n }\n assert.deepEqual(gpuGroupEvents, parsedTrace.GPU.mainGPUThreadTasks);\n });\n });\n });\n\n describe('highlightedEntryInfo', () => {\n it('shows the correct warning for a long task when hovered', async function() {\n await initTrackAppender(this, 'simple-js-program.json.gz');\n const events = parsedTrace.Renderer?.allTraceEntries;\n if (!events) {\n throw new Error('Could not find renderer events');\n }\n const longTask = events.find(e => (e.dur || 0) > 1_000_000);\n if (!longTask) {\n throw new Error('Could not find long task');\n }\n const info = tracksAppender.highlightedEntryInfo(longTask, 2);\n assert.strictEqual(info.warningElements?.length, 1);\n const warning = info.warningElements?.[0];\n if (!(warning instanceof HTMLSpanElement)) {\n throw new Error('Found unexpected warning');\n }\n assert.strictEqual(warning?.innerText, 'Long task took 1.30\\u00A0s.');\n });\n\n it('shows the correct warning for a forced recalc styles when hovered', async function() {\n await initTrackAppender(this, 'large-layout-small-recalc.json.gz');\n const events = parsedTrace.Warnings.perWarning.get('FORCED_REFLOW') || [];\n\n if (!events) {\n throw new Error('Could not find forced reflows events');\n }\n const recalcStyles = events[0];\n if (!recalcStyles) {\n throw new Error('Could not find recalc styles');\n }\n const info = tracksAppender.highlightedEntryInfo(recalcStyles, 2);\n assert.strictEqual(info.warningElements?.length, 1);\n const warning = info.warningElements?.[0];\n if (!(warning instanceof HTMLSpanElement)) {\n throw new Error('Found unexpected warning');\n }\n assert.strictEqual(warning?.innerText, 'Forced reflow is a likely performance bottleneck.');\n });\n\n it('shows the correct warning for a forced layout when hovered', async function() {\n await initTrackAppender(this, 'large-layout-small-recalc.json.gz');\n const events = parsedTrace.Warnings.perWarning.get('FORCED_REFLOW') || [];\n\n if (!events) {\n throw new Error('Could not find forced reflows events');\n }\n const layout = events[1];\n if (!layout) {\n throw new Error('Could not find layout');\n }\n const info = tracksAppender.highlightedEntryInfo(layout, 2);\n assert.strictEqual(info.warningElements?.length, 1);\n const warning = info.warningElements?.[0];\n if (!(warning instanceof HTMLSpanElement)) {\n throw new Error('Found unexpected warning');\n }\n assert.strictEqual(warning?.innerText, 'Forced reflow is a likely performance bottleneck.');\n });\n\n it('shows the correct warning for slow idle callbacks', async function() {\n await initTrackAppender(this, 'idle-callback.json.gz');\n const events = parsedTrace.Renderer?.allTraceEntries;\n if (!events) {\n throw new Error('Could not find renderer events');\n }\n const idleCallback = events.find(event => {\n const {duration} = Trace.Helpers.Timing.eventTimingsMilliSeconds(event);\n if (!Trace.Types.Events.isFireIdleCallback(event)) {\n return false;\n }\n if (duration <= event.args.data.allottedMilliseconds) {\n false;\n }\n return true;\n });\n if (!idleCallback) {\n throw new Error('Could not find idle callback');\n }\n const info = tracksAppender.highlightedEntryInfo(idleCallback, 2);\n assert.strictEqual(info.warningElements?.length, 1);\n const warning = info.warningElements?.[0];\n if (!(warning instanceof HTMLSpanElement)) {\n throw new Error('Found unexpected warning');\n }\n assert.strictEqual(warning?.innerText, 'Idle callback execution extended beyond deadline by 79.56\\u00A0ms');\n });\n });\n\n it('can return the group for a given level', async () => {\n await initTrackAppender(this, 'web-dev-with-commit.json.gz');\n // The order of these groups might seem odd, but it's based on the setup in\n // the initTrackAppender function which does Timings, GPU and then threads.\n const groupForLevel0 = tracksAppender.groupForLevel(0);\n assert.strictEqual(groupForLevel0?.name, 'Timings');\n const groupForLevel1 = tracksAppender.groupForLevel(1);\n assert.strictEqual(groupForLevel1?.name, 'GPU');\n const groupForLevel2 = tracksAppender.groupForLevel(2);\n assert.strictEqual(groupForLevel2?.name, 'Main — https://web.dev/');\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/track_appenders/ExtensionTrackAppender.test.js b/public/panels/timeline/track_appenders/ExtensionTrackAppender.test.js index 604c786c3..4c8af76fd 100644 --- a/public/panels/timeline/track_appenders/ExtensionTrackAppender.test.js +++ b/public/panels/timeline/track_appenders/ExtensionTrackAppender.test.js @@ -1,27 +1,27 @@ // Copyright 2024 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 * as TraceEngine from '../../../models/trace/trace.js'; +import * as Trace from '../../../models/trace/trace.js'; import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; import * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js'; import * as ThemeSupport from '../../../ui/legacy/theme_support/theme_support.js'; import * as Timeline from '../timeline.js'; -function initTrackAppender(flameChartData, traceParsedData, entryData, entryTypeByLevel) { - Timeline.ExtensionDataGatherer.ExtensionDataGatherer.instance().modelChanged(traceParsedData); - const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(flameChartData, traceParsedData, entryData, entryTypeByLevel); +function initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel) { + Timeline.ExtensionDataGatherer.ExtensionDataGatherer.instance().modelChanged(parsedTrace); + const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel); return compatibilityTracksAppender.allVisibleTrackAppenders().filter(track => track.appenderName === 'Extension'); } describeWithEnvironment('ExtensionTrackAppender', function () { - let traceData; + let parsedTrace; let extensionTrackAppenders; let entryData = []; let flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty(); let entryTypeByLevel = []; beforeEach(async function () { Timeline.ExtensionDataGatherer.ExtensionDataGatherer.removeInstance(); - ({ traceData } = await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz')); - extensionTrackAppenders = initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel); + ({ parsedTrace } = await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz')); + extensionTrackAppenders = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel); let level = 0; extensionTrackAppenders.forEach(appender => { level = appender.appendTrackAtLevel(level); @@ -46,22 +46,22 @@ describeWithEnvironment('ExtensionTrackAppender', function () { assert.strictEqual(flameChartData.groups[2].style.nestingLevel, 0); }); it('adds start times correctly', function () { - const allExtensionTrackEntries = traceData.ExtensionTraceData.extensionTrackData.map(track => Object.values(track.entriesByTrack)).flat(2); + const allExtensionTrackEntries = parsedTrace.ExtensionTraceData.extensionTrackData.map(track => Object.values(track.entriesByTrack)).flat(2); for (let i = 0; i < allExtensionTrackEntries.length; ++i) { const event = allExtensionTrackEntries[i]; - assert.strictEqual(flameChartData.entryStartTimes[i], TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.ts)); + assert.strictEqual(flameChartData.entryStartTimes[i], Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts)); } }); it('adds total times correctly', function () { - const allExtensionTrackEntries = traceData.ExtensionTraceData.extensionTrackData.map(track => Object.values(track.entriesByTrack)).flat(2); + const allExtensionTrackEntries = parsedTrace.ExtensionTraceData.extensionTrackData.map(track => Object.values(track.entriesByTrack)).flat(2); for (let i = 0; i < allExtensionTrackEntries.length; i++) { const event = allExtensionTrackEntries[i]; - if (TraceEngine.Types.TraceEvents.isTraceEventMarkerEvent(event)) { + if (Trace.Types.Events.isMarkerEvent(event)) { assert.isNaN(flameChartData.entryTotalTimes[i]); continue; } const expectedTotalTimeForEvent = event.dur ? - TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.dur) : + Trace.Helpers.Timing.microSecondsToMilliseconds(event.dur) : Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs; assert.strictEqual(flameChartData.entryTotalTimes[i], expectedTotalTimeForEvent); } @@ -93,7 +93,7 @@ describeWithEnvironment('ExtensionTrackAppender', function () { ThemeSupport.ThemeSupport.clearThemeCache(); }); it('returns the correct color and title for extension entries', function () { - const allExtensionTrackEntries = traceData.ExtensionTraceData.extensionTrackData.map(track => Object.values(track.entriesByTrack)).flat(2); + const allExtensionTrackEntries = parsedTrace.ExtensionTraceData.extensionTrackData.map(track => Object.values(track.entriesByTrack)).flat(2); for (const event of allExtensionTrackEntries) { assert.strictEqual(extensionTrackAppenders[0].titleForEvent(event), event.name); if (event.args.color === 'tertiary') { @@ -138,8 +138,8 @@ describeWithEnvironment('ExtensionTrackAppender', function () { flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty(); entryTypeByLevel = []; Timeline.TimelinePanel.TimelinePanel.extensionDataVisibilitySetting().set(false); - traceData = (await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz')).traceData; - extensionTrackAppenders = initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel); + parsedTrace = (await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz')).parsedTrace; + extensionTrackAppenders = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel); let level = 0; extensionTrackAppenders.forEach(appender => { level = appender.appendTrackAtLevel(level); @@ -150,7 +150,7 @@ describeWithEnvironment('ExtensionTrackAppender', function () { }); describe('highlightedEntryInfo', function () { it('returns the info for an entry correctly', function () { - const allExtensionTrackEntries = traceData.ExtensionTraceData.extensionTrackData.map(track => Object.values(track.entriesByTrack)).flat(2); + const allExtensionTrackEntries = parsedTrace.ExtensionTraceData.extensionTrackData.map(track => Object.values(track.entriesByTrack)).flat(2); const highlightedEntryInfo = extensionTrackAppenders[0].highlightedEntryInfo(allExtensionTrackEntries[0]); // The i18n encodes spaces using the u00A0 unicode character. assert.strictEqual(highlightedEntryInfo.formattedTime, '1.00\u00A0s'); diff --git a/public/panels/timeline/track_appenders/ExtensionTrackAppender.test.js.map b/public/panels/timeline/track_appenders/ExtensionTrackAppender.test.js.map index 3abb2e789..057fa531f 100644 --- a/public/panels/timeline/track_appenders/ExtensionTrackAppender.test.js.map +++ b/public/panels/timeline/track_appenders/ExtensionTrackAppender.test.js.map @@ -1 +1 @@ -{"version":3,"file":"ExtensionTrackAppender.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/track_appenders/ExtensionTrackAppender.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as TraceModel from '../../../models/trace/trace.js';\nimport * as TraceEngine from '../../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as ThemeSupport from '../../../ui/legacy/theme_support/theme_support.js';\nimport * as Timeline from '../timeline.js';\n\nfunction initTrackAppender(\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData, traceParsedData: TraceModel.Handlers.Types.TraceParseData,\n entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[],\n entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[]):\n Timeline.ExtensionTrackAppender.ExtensionTrackAppender[] {\n Timeline.ExtensionDataGatherer.ExtensionDataGatherer.instance().modelChanged(traceParsedData);\n const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(\n flameChartData, traceParsedData, entryData, entryTypeByLevel);\n\n return compatibilityTracksAppender.allVisibleTrackAppenders().filter(track => track.appenderName === 'Extension') as\n Timeline.ExtensionTrackAppender.ExtensionTrackAppender[];\n}\n\ndescribeWithEnvironment('ExtensionTrackAppender', function() {\n let traceData: TraceModel.Handlers.Types.TraceParseData;\n let extensionTrackAppenders: Timeline.ExtensionTrackAppender.ExtensionTrackAppender[];\n let entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[] = [];\n let flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n let entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[] = [];\n\n beforeEach(async function() {\n Timeline.ExtensionDataGatherer.ExtensionDataGatherer.removeInstance();\n ({traceData} = await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz'));\n extensionTrackAppenders = initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel);\n let level = 0;\n extensionTrackAppenders.forEach(appender => {\n level = appender.appendTrackAtLevel(level);\n });\n });\n\n afterEach(() => {\n entryData = [];\n flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n entryTypeByLevel = [];\n });\n\n describe('appendTrackAtLevel', function() {\n it('creates flamechart groups for the Extension tracks properly', function() {\n assert.strictEqual(flameChartData.groups.length, 3);\n assert.strictEqual(flameChartData.groups[0].name, 'A track group — Custom track');\n assert.strictEqual(flameChartData.groups[0].startLevel, 0);\n assert.strictEqual(flameChartData.groups[0].style.nestingLevel, 0);\n assert.strictEqual(flameChartData.groups[1].name, 'Another Extension Track');\n assert.strictEqual(flameChartData.groups[1].startLevel, 0);\n assert.strictEqual(flameChartData.groups[1].style.nestingLevel, 1);\n assert.strictEqual(flameChartData.groups[2].name, 'An Extension Track — Custom track');\n assert.strictEqual(flameChartData.groups[2].startLevel, 1);\n assert.strictEqual(flameChartData.groups[2].style.nestingLevel, 0);\n });\n\n it('adds start times correctly', function() {\n const allExtensionTrackEntries =\n traceData.ExtensionTraceData.extensionTrackData.map(track => Object.values(track.entriesByTrack)).flat(2);\n for (let i = 0; i < allExtensionTrackEntries.length; ++i) {\n const event = allExtensionTrackEntries[i];\n assert.strictEqual(\n flameChartData.entryStartTimes[i], TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.ts));\n }\n });\n\n it('adds total times correctly', function() {\n const allExtensionTrackEntries =\n traceData.ExtensionTraceData.extensionTrackData.map(track => Object.values(track.entriesByTrack)).flat(2);\n for (let i = 0; i < allExtensionTrackEntries.length; i++) {\n const event = allExtensionTrackEntries[i];\n if (TraceEngine.Types.TraceEvents.isTraceEventMarkerEvent(event)) {\n assert.isNaN(flameChartData.entryTotalTimes[i]);\n continue;\n }\n const expectedTotalTimeForEvent = event.dur ?\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.dur) :\n Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs;\n assert.strictEqual(flameChartData.entryTotalTimes[i], expectedTotalTimeForEvent);\n }\n });\n });\n\n describe('colorForEvent and titleForEvent', function() {\n before(() => {\n // Rather than use the real colours here and burden the test with having to\n // inject loads of CSS, we fake out the colours. this is fine for our tests as\n // the exact value of the colours is not important; we just make sure that it\n // parses them out correctly. Each variable is given a different rgb() value to\n // ensure we know the code is working and using the right one.\n const styleElement = document.createElement('style');\n styleElement.id = 'fake-perf-panel-colors';\n styleElement.textContent = `\n :root {\n --ref-palette-primary70: rgb(4 4 4);\n --ref-palette-tertiary70: rgb(10 10 10);\n }\n `;\n document.documentElement.appendChild(styleElement);\n ThemeSupport.ThemeSupport.clearThemeCache();\n });\n\n after(() => {\n const styleElementToRemove = document.documentElement.querySelector('#fake-perf-panel-colors');\n if (styleElementToRemove) {\n document.documentElement.removeChild(styleElementToRemove);\n }\n ThemeSupport.ThemeSupport.clearThemeCache();\n });\n it('returns the correct color and title for extension entries', function() {\n const allExtensionTrackEntries =\n traceData.ExtensionTraceData.extensionTrackData.map(track => Object.values(track.entriesByTrack)).flat(2);\n for (const event of allExtensionTrackEntries) {\n assert.strictEqual(extensionTrackAppenders[0].titleForEvent(event), event.name);\n if (event.args.color === 'tertiary') {\n // \"tertiary\" color category is mapped to --ref-palette-tertiary70\n // which is faked out to 10, 10, 10\n assert.strictEqual(extensionTrackAppenders[0].colorForEvent(event), 'rgb(10 10 10)');\n } else {\n // Unknown colors are mapped to \"primary\" by default, and\n // \"primary\" color category is mapped to --ref-palette-primary70\n // which is faked out to 4, 4, 4\n assert.strictEqual(extensionTrackAppenders[0].colorForEvent(event), 'rgb(4 4 4)');\n }\n }\n });\n\n it('sets a default value when a color is not set or is set an unknown value', function() {\n const mockExtensionEntryNoColor = {\n args: {\n metadata: {dataType: 'track-entry', extensionName: 'Extension'},\n track: 'A track',\n },\n cat: 'devtools.extension',\n } as unknown as TraceEngine.Types.TraceEvents.TraceEventData;\n\n const mockExtensionEntryUnknownColor = {\n args: {\n metadata: {dataType: 'track-entry', extensionName: 'Extension'},\n track: 'A track',\n color: 'anUnknownColor',\n },\n cat: 'devtools.extension',\n } as unknown as TraceEngine.Types.TraceEvents.TraceEventData;\n // \"primary\" color category is mapped to --ref-palette-primary70\n // which is faked out to 4, 4, 4\n assert.strictEqual(extensionTrackAppenders[0].colorForEvent(mockExtensionEntryNoColor), 'rgb(4 4 4)');\n assert.strictEqual(extensionTrackAppenders[0].colorForEvent(mockExtensionEntryUnknownColor), 'rgb(4 4 4)');\n });\n });\n\n describe('toggling', function() {\n it('Does not append extension data when the configuration is set to disabled', async function() {\n Timeline.ExtensionDataGatherer.ExtensionDataGatherer.removeInstance();\n entryData = [];\n flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n entryTypeByLevel = [];\n Timeline.TimelinePanel.TimelinePanel.extensionDataVisibilitySetting().set(false);\n traceData = (await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz')).traceData;\n extensionTrackAppenders = initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel);\n let level = 0;\n extensionTrackAppenders.forEach(appender => {\n level = appender.appendTrackAtLevel(level);\n });\n assert.strictEqual(flameChartData.groups.length, 0);\n Timeline.TimelinePanel.TimelinePanel.extensionDataVisibilitySetting().set(true);\n });\n });\n\n describe('highlightedEntryInfo', function() {\n it('returns the info for an entry correctly', function() {\n const allExtensionTrackEntries =\n traceData.ExtensionTraceData.extensionTrackData.map(track => Object.values(track.entriesByTrack)).flat(2);\n const highlightedEntryInfo = extensionTrackAppenders[0].highlightedEntryInfo(allExtensionTrackEntries[0]);\n // The i18n encodes spaces using the u00A0 unicode character.\n assert.strictEqual(highlightedEntryInfo.formattedTime, '1.00\\u00A0s');\n assert.strictEqual(highlightedEntryInfo.title, 'A hint if needed');\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"ExtensionTrackAppender.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/track_appenders/ExtensionTrackAppender.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as ThemeSupport from '../../../ui/legacy/theme_support/theme_support.js';\nimport * as Timeline from '../timeline.js';\n\nfunction initTrackAppender(\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData, parsedTrace: Trace.Handlers.Types.ParsedTrace,\n entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[],\n entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[]):\n Timeline.ExtensionTrackAppender.ExtensionTrackAppender[] {\n Timeline.ExtensionDataGatherer.ExtensionDataGatherer.instance().modelChanged(parsedTrace);\n const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(\n flameChartData, parsedTrace, entryData, entryTypeByLevel);\n\n return compatibilityTracksAppender.allVisibleTrackAppenders().filter(track => track.appenderName === 'Extension') as\n Timeline.ExtensionTrackAppender.ExtensionTrackAppender[];\n}\n\ndescribeWithEnvironment('ExtensionTrackAppender', function() {\n let parsedTrace: Trace.Handlers.Types.ParsedTrace;\n let extensionTrackAppenders: Timeline.ExtensionTrackAppender.ExtensionTrackAppender[];\n let entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[] = [];\n let flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n let entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[] = [];\n\n beforeEach(async function() {\n Timeline.ExtensionDataGatherer.ExtensionDataGatherer.removeInstance();\n ({parsedTrace} = await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz'));\n extensionTrackAppenders = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel);\n let level = 0;\n extensionTrackAppenders.forEach(appender => {\n level = appender.appendTrackAtLevel(level);\n });\n });\n\n afterEach(() => {\n entryData = [];\n flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n entryTypeByLevel = [];\n });\n\n describe('appendTrackAtLevel', function() {\n it('creates flamechart groups for the Extension tracks properly', function() {\n assert.strictEqual(flameChartData.groups.length, 3);\n assert.strictEqual(flameChartData.groups[0].name, 'A track group — Custom track');\n assert.strictEqual(flameChartData.groups[0].startLevel, 0);\n assert.strictEqual(flameChartData.groups[0].style.nestingLevel, 0);\n assert.strictEqual(flameChartData.groups[1].name, 'Another Extension Track');\n assert.strictEqual(flameChartData.groups[1].startLevel, 0);\n assert.strictEqual(flameChartData.groups[1].style.nestingLevel, 1);\n assert.strictEqual(flameChartData.groups[2].name, 'An Extension Track — Custom track');\n assert.strictEqual(flameChartData.groups[2].startLevel, 1);\n assert.strictEqual(flameChartData.groups[2].style.nestingLevel, 0);\n });\n\n it('adds start times correctly', function() {\n const allExtensionTrackEntries =\n parsedTrace.ExtensionTraceData.extensionTrackData.map(track => Object.values(track.entriesByTrack)).flat(2);\n for (let i = 0; i < allExtensionTrackEntries.length; ++i) {\n const event = allExtensionTrackEntries[i];\n assert.strictEqual(\n flameChartData.entryStartTimes[i], Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts));\n }\n });\n\n it('adds total times correctly', function() {\n const allExtensionTrackEntries =\n parsedTrace.ExtensionTraceData.extensionTrackData.map(track => Object.values(track.entriesByTrack)).flat(2);\n for (let i = 0; i < allExtensionTrackEntries.length; i++) {\n const event = allExtensionTrackEntries[i];\n if (Trace.Types.Events.isMarkerEvent(event)) {\n assert.isNaN(flameChartData.entryTotalTimes[i]);\n continue;\n }\n const expectedTotalTimeForEvent = event.dur ?\n Trace.Helpers.Timing.microSecondsToMilliseconds(event.dur) :\n Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs;\n assert.strictEqual(flameChartData.entryTotalTimes[i], expectedTotalTimeForEvent);\n }\n });\n });\n\n describe('colorForEvent and titleForEvent', function() {\n before(() => {\n // Rather than use the real colours here and burden the test with having to\n // inject loads of CSS, we fake out the colours. this is fine for our tests as\n // the exact value of the colours is not important; we just make sure that it\n // parses them out correctly. Each variable is given a different rgb() value to\n // ensure we know the code is working and using the right one.\n const styleElement = document.createElement('style');\n styleElement.id = 'fake-perf-panel-colors';\n styleElement.textContent = `\n :root {\n --ref-palette-primary70: rgb(4 4 4);\n --ref-palette-tertiary70: rgb(10 10 10);\n }\n `;\n document.documentElement.appendChild(styleElement);\n ThemeSupport.ThemeSupport.clearThemeCache();\n });\n\n after(() => {\n const styleElementToRemove = document.documentElement.querySelector('#fake-perf-panel-colors');\n if (styleElementToRemove) {\n document.documentElement.removeChild(styleElementToRemove);\n }\n ThemeSupport.ThemeSupport.clearThemeCache();\n });\n it('returns the correct color and title for extension entries', function() {\n const allExtensionTrackEntries =\n parsedTrace.ExtensionTraceData.extensionTrackData.map(track => Object.values(track.entriesByTrack)).flat(2);\n for (const event of allExtensionTrackEntries) {\n assert.strictEqual(extensionTrackAppenders[0].titleForEvent(event), event.name);\n if (event.args.color === 'tertiary') {\n // \"tertiary\" color category is mapped to --ref-palette-tertiary70\n // which is faked out to 10, 10, 10\n assert.strictEqual(extensionTrackAppenders[0].colorForEvent(event), 'rgb(10 10 10)');\n } else {\n // Unknown colors are mapped to \"primary\" by default, and\n // \"primary\" color category is mapped to --ref-palette-primary70\n // which is faked out to 4, 4, 4\n assert.strictEqual(extensionTrackAppenders[0].colorForEvent(event), 'rgb(4 4 4)');\n }\n }\n });\n\n it('sets a default value when a color is not set or is set an unknown value', function() {\n const mockExtensionEntryNoColor = {\n args: {\n metadata: {dataType: 'track-entry', extensionName: 'Extension'},\n track: 'A track',\n },\n cat: 'devtools.extension',\n } as unknown as Trace.Types.Events.Event;\n\n const mockExtensionEntryUnknownColor = {\n args: {\n metadata: {dataType: 'track-entry', extensionName: 'Extension'},\n track: 'A track',\n color: 'anUnknownColor',\n },\n cat: 'devtools.extension',\n } as unknown as Trace.Types.Events.Event;\n // \"primary\" color category is mapped to --ref-palette-primary70\n // which is faked out to 4, 4, 4\n assert.strictEqual(extensionTrackAppenders[0].colorForEvent(mockExtensionEntryNoColor), 'rgb(4 4 4)');\n assert.strictEqual(extensionTrackAppenders[0].colorForEvent(mockExtensionEntryUnknownColor), 'rgb(4 4 4)');\n });\n });\n\n describe('toggling', function() {\n it('Does not append extension data when the configuration is set to disabled', async function() {\n Timeline.ExtensionDataGatherer.ExtensionDataGatherer.removeInstance();\n entryData = [];\n flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n entryTypeByLevel = [];\n Timeline.TimelinePanel.TimelinePanel.extensionDataVisibilitySetting().set(false);\n parsedTrace = (await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz')).parsedTrace;\n extensionTrackAppenders = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel);\n let level = 0;\n extensionTrackAppenders.forEach(appender => {\n level = appender.appendTrackAtLevel(level);\n });\n assert.strictEqual(flameChartData.groups.length, 0);\n Timeline.TimelinePanel.TimelinePanel.extensionDataVisibilitySetting().set(true);\n });\n });\n\n describe('highlightedEntryInfo', function() {\n it('returns the info for an entry correctly', function() {\n const allExtensionTrackEntries =\n parsedTrace.ExtensionTraceData.extensionTrackData.map(track => Object.values(track.entriesByTrack)).flat(2);\n const highlightedEntryInfo = extensionTrackAppenders[0].highlightedEntryInfo(allExtensionTrackEntries[0]);\n // The i18n encodes spaces using the u00A0 unicode character.\n assert.strictEqual(highlightedEntryInfo.formattedTime, '1.00\\u00A0s');\n assert.strictEqual(highlightedEntryInfo.title, 'A hint if needed');\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/track_appenders/GPUTrackAppender.test.js b/public/panels/timeline/track_appenders/GPUTrackAppender.test.js index c16677b53..1efd7019e 100644 --- a/public/panels/timeline/track_appenders/GPUTrackAppender.test.js +++ b/public/panels/timeline/track_appenders/GPUTrackAppender.test.js @@ -1,25 +1,25 @@ // 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 * as TraceEngine from '../../../models/trace/trace.js'; +import * as Trace from '../../../models/trace/trace.js'; import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; import * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js'; import * as ThemeSupport from '../../../ui/legacy/theme_support/theme_support.js'; import * as Timeline from '../timeline.js'; -function initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel) { - const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(flameChartData, traceData, entryData, entryTypeByLevel); +function initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel) { + const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel); return compatibilityTracksAppender.gpuTrackAppender(); } describeWithEnvironment('GPUTrackAppender', function () { - let traceData; + let parsedTrace; let gpuTrackAppender; let entryData = []; let flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty(); let entryTypeByLevel = []; beforeEach(async function () { - ({ traceData } = await TraceLoader.traceEngine(this, 'threejs-gpu.json.gz')); - gpuTrackAppender = initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel); + ({ parsedTrace } = await TraceLoader.traceEngine(this, 'threejs-gpu.json.gz')); + gpuTrackAppender = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel); gpuTrackAppender.appendTrackAtLevel(0); }); afterEach(() => { @@ -40,24 +40,24 @@ describeWithEnvironment('GPUTrackAppender', function () { assert.strictEqual(flameChartData.groups[0].name, 'GPU'); }); it('adds start times correctly', () => { - const gpuEvents = traceData.GPU.mainGPUThreadTasks; + const gpuEvents = parsedTrace.GPU.mainGPUThreadTasks; for (const event of gpuEvents) { const index = entryData.indexOf(event); assert.exists(index); - assert.strictEqual(flameChartData.entryStartTimes[index], TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.ts)); + assert.strictEqual(flameChartData.entryStartTimes[index], Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts)); } }); it('adds total times correctly', () => { - const gpuEvents = traceData.GPU.mainGPUThreadTasks; + const gpuEvents = parsedTrace.GPU.mainGPUThreadTasks; for (const event of gpuEvents) { const index = entryData.indexOf(event); assert.exists(index); - if (TraceEngine.Types.TraceEvents.isTraceEventMarkerEvent(event)) { + if (Trace.Types.Events.isMarkerEvent(event)) { assert.isNaN(flameChartData.entryTotalTimes[index]); continue; } const expectedTotalTimeForEvent = event.dur ? - TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.dur) : + Trace.Helpers.Timing.microSecondsToMilliseconds(event.dur) : Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs; assert.strictEqual(flameChartData.entryTotalTimes[index], expectedTotalTimeForEvent); } @@ -88,7 +88,7 @@ describeWithEnvironment('GPUTrackAppender', function () { ThemeSupport.ThemeSupport.clearThemeCache(); }); it('returns the correct color and title for GPU tasks', () => { - const gpuEvents = traceData.GPU.mainGPUThreadTasks; + const gpuEvents = parsedTrace.GPU.mainGPUThreadTasks; for (const event of gpuEvents) { assert.strictEqual(gpuTrackAppender.colorForEvent(event), 'rgb(6 6 6)'); } diff --git a/public/panels/timeline/track_appenders/GPUTrackAppender.test.js.map b/public/panels/timeline/track_appenders/GPUTrackAppender.test.js.map index 99844159e..6f246a6e8 100644 --- a/public/panels/timeline/track_appenders/GPUTrackAppender.test.js.map +++ b/public/panels/timeline/track_appenders/GPUTrackAppender.test.js.map @@ -1 +1 @@ -{"version":3,"file":"GPUTrackAppender.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/track_appenders/GPUTrackAppender.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceEngine from '../../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as ThemeSupport from '../../../ui/legacy/theme_support/theme_support.js';\nimport * as Timeline from '../timeline.js';\n\nfunction initTrackAppender(\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData,\n traceData: TraceEngine.Handlers.Types.TraceParseData,\n entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[],\n entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[],\n ): Timeline.GPUTrackAppender.GPUTrackAppender {\n const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(\n flameChartData, traceData, entryData, entryTypeByLevel);\n return compatibilityTracksAppender.gpuTrackAppender();\n}\n\ndescribeWithEnvironment('GPUTrackAppender', function() {\n let traceData: TraceEngine.Handlers.Types.TraceParseData;\n let gpuTrackAppender: Timeline.GPUTrackAppender.GPUTrackAppender;\n let entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[] = [];\n let flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n let entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[] = [];\n\n beforeEach(async function() {\n ({traceData} = await TraceLoader.traceEngine(this, 'threejs-gpu.json.gz'));\n gpuTrackAppender = initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel);\n gpuTrackAppender.appendTrackAtLevel(0);\n });\n\n afterEach(() => {\n entryData = [];\n flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n entryTypeByLevel = [];\n });\n\n describe('appendTrackAtLevel', () => {\n it('marks all levels used by the track with the `TrackAppender` type', () => {\n // One levels should be taken: 1 for the GPU tasks.\n const levelCount = 1;\n assert.strictEqual(entryTypeByLevel.length, levelCount);\n const allEntriesAreTrackAppender =\n entryTypeByLevel.every(type => type === Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER);\n assert.isTrue(allEntriesAreTrackAppender);\n });\n\n it('creates a flamechart group for the GPU track', () => {\n assert.strictEqual(flameChartData.groups.length, 1);\n assert.strictEqual(flameChartData.groups[0].name, 'GPU');\n });\n\n it('adds start times correctly', () => {\n const gpuEvents = traceData.GPU.mainGPUThreadTasks;\n for (const event of gpuEvents) {\n const index = entryData.indexOf(event);\n assert.exists(index);\n assert.strictEqual(\n flameChartData.entryStartTimes[index], TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.ts));\n }\n });\n\n it('adds total times correctly', () => {\n const gpuEvents = traceData.GPU.mainGPUThreadTasks;\n for (const event of gpuEvents) {\n const index = entryData.indexOf(event);\n assert.exists(index);\n if (TraceEngine.Types.TraceEvents.isTraceEventMarkerEvent(event)) {\n assert.isNaN(flameChartData.entryTotalTimes[index]);\n continue;\n }\n const expectedTotalTimeForEvent = event.dur ?\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.dur) :\n Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs;\n assert.strictEqual(flameChartData.entryTotalTimes[index], expectedTotalTimeForEvent);\n }\n });\n });\n\n describe('colorForEvent and titleForEvent', () => {\n before(() => {\n // Rather than use the real colours here and burden the test with having to\n // inject loads of CSS, we fake out the colours. this is fine for our tests as\n // the exact value of the colours is not important; we just make sure that it\n // parses them out correctly. Each variable is given a different rgb() value to\n // ensure we know the code is working and using the right one.\n const styleElement = document.createElement('style');\n styleElement.id = 'fake-perf-panel-colors';\n styleElement.textContent = `\n :root {\n --app-color-painting: rgb(6 6 6);\n }\n `;\n document.documentElement.appendChild(styleElement);\n ThemeSupport.ThemeSupport.clearThemeCache();\n });\n\n after(() => {\n const styleElementToRemove = document.documentElement.querySelector('#fake-perf-panel-colors');\n if (styleElementToRemove) {\n document.documentElement.removeChild(styleElementToRemove);\n }\n ThemeSupport.ThemeSupport.clearThemeCache();\n });\n it('returns the correct color and title for GPU tasks', () => {\n const gpuEvents = traceData.GPU.mainGPUThreadTasks;\n for (const event of gpuEvents) {\n assert.strictEqual(gpuTrackAppender.colorForEvent(event), 'rgb(6 6 6)');\n }\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"GPUTrackAppender.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/track_appenders/GPUTrackAppender.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as ThemeSupport from '../../../ui/legacy/theme_support/theme_support.js';\nimport * as Timeline from '../timeline.js';\n\nfunction initTrackAppender(\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData,\n parsedTrace: Trace.Handlers.Types.ParsedTrace,\n entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[],\n entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[],\n ): Timeline.GPUTrackAppender.GPUTrackAppender {\n const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(\n flameChartData, parsedTrace, entryData, entryTypeByLevel);\n return compatibilityTracksAppender.gpuTrackAppender();\n}\n\ndescribeWithEnvironment('GPUTrackAppender', function() {\n let parsedTrace: Trace.Handlers.Types.ParsedTrace;\n let gpuTrackAppender: Timeline.GPUTrackAppender.GPUTrackAppender;\n let entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[] = [];\n let flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n let entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[] = [];\n\n beforeEach(async function() {\n ({parsedTrace} = await TraceLoader.traceEngine(this, 'threejs-gpu.json.gz'));\n gpuTrackAppender = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel);\n gpuTrackAppender.appendTrackAtLevel(0);\n });\n\n afterEach(() => {\n entryData = [];\n flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n entryTypeByLevel = [];\n });\n\n describe('appendTrackAtLevel', () => {\n it('marks all levels used by the track with the `TrackAppender` type', () => {\n // One levels should be taken: 1 for the GPU tasks.\n const levelCount = 1;\n assert.strictEqual(entryTypeByLevel.length, levelCount);\n const allEntriesAreTrackAppender =\n entryTypeByLevel.every(type => type === Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER);\n assert.isTrue(allEntriesAreTrackAppender);\n });\n\n it('creates a flamechart group for the GPU track', () => {\n assert.strictEqual(flameChartData.groups.length, 1);\n assert.strictEqual(flameChartData.groups[0].name, 'GPU');\n });\n\n it('adds start times correctly', () => {\n const gpuEvents = parsedTrace.GPU.mainGPUThreadTasks;\n for (const event of gpuEvents) {\n const index = entryData.indexOf(event);\n assert.exists(index);\n assert.strictEqual(\n flameChartData.entryStartTimes[index], Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts));\n }\n });\n\n it('adds total times correctly', () => {\n const gpuEvents = parsedTrace.GPU.mainGPUThreadTasks;\n for (const event of gpuEvents) {\n const index = entryData.indexOf(event);\n assert.exists(index);\n if (Trace.Types.Events.isMarkerEvent(event)) {\n assert.isNaN(flameChartData.entryTotalTimes[index]);\n continue;\n }\n const expectedTotalTimeForEvent = event.dur ?\n Trace.Helpers.Timing.microSecondsToMilliseconds(event.dur) :\n Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs;\n assert.strictEqual(flameChartData.entryTotalTimes[index], expectedTotalTimeForEvent);\n }\n });\n });\n\n describe('colorForEvent and titleForEvent', () => {\n before(() => {\n // Rather than use the real colours here and burden the test with having to\n // inject loads of CSS, we fake out the colours. this is fine for our tests as\n // the exact value of the colours is not important; we just make sure that it\n // parses them out correctly. Each variable is given a different rgb() value to\n // ensure we know the code is working and using the right one.\n const styleElement = document.createElement('style');\n styleElement.id = 'fake-perf-panel-colors';\n styleElement.textContent = `\n :root {\n --app-color-painting: rgb(6 6 6);\n }\n `;\n document.documentElement.appendChild(styleElement);\n ThemeSupport.ThemeSupport.clearThemeCache();\n });\n\n after(() => {\n const styleElementToRemove = document.documentElement.querySelector('#fake-perf-panel-colors');\n if (styleElementToRemove) {\n document.documentElement.removeChild(styleElementToRemove);\n }\n ThemeSupport.ThemeSupport.clearThemeCache();\n });\n it('returns the correct color and title for GPU tasks', () => {\n const gpuEvents = parsedTrace.GPU.mainGPUThreadTasks;\n for (const event of gpuEvents) {\n assert.strictEqual(gpuTrackAppender.colorForEvent(event), 'rgb(6 6 6)');\n }\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/track_appenders/InteractionsTrackAppender.test.js b/public/panels/timeline/track_appenders/InteractionsTrackAppender.test.js index 7efcc397f..8de88e77e 100644 --- a/public/panels/timeline/track_appenders/InteractionsTrackAppender.test.js +++ b/public/panels/timeline/track_appenders/InteractionsTrackAppender.test.js @@ -1,13 +1,13 @@ // 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 * as TraceEngine from '../../../models/trace/trace.js'; +import * as Trace from '../../../models/trace/trace.js'; import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; import * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js'; import * as Timeline from '../timeline.js'; -function initTrackAppender(flameChartData, traceParsedData, entryData, entryTypeByLevel) { - const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(flameChartData, traceParsedData, entryData, entryTypeByLevel); +function initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel) { + const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel); return compatibilityTracksAppender.interactionsTrackAppender(); } describeWithEnvironment('InteractionsTrackAppender', function () { @@ -15,12 +15,12 @@ describeWithEnvironment('InteractionsTrackAppender', function () { const entryTypeByLevel = []; const entryData = []; const flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty(); - const { traceData } = await TraceLoader.traceEngine(context, trace); - const interactionsTrackAppender = initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel); + const { parsedTrace } = await TraceLoader.traceEngine(context, trace); + const interactionsTrackAppender = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel); interactionsTrackAppender.appendTrackAtLevel(0); return { entryTypeByLevel, - traceParsedData: traceData, + parsedTrace, flameChartData, interactionsTrackAppender, entryData, @@ -41,8 +41,8 @@ describeWithEnvironment('InteractionsTrackAppender', function () { assert.strictEqual(entryTypeByLevel.length, 0); }); it('only shows the top level interactions', async function () { - const { entryData, traceParsedData } = await renderTrackAppender(this, 'nested-interactions.json.gz'); - assert.strictEqual(entryData.length, traceParsedData.UserInteractions.interactionEventsWithNoNesting.length); + const { entryData, parsedTrace } = await renderTrackAppender(this, 'nested-interactions.json.gz'); + assert.strictEqual(entryData.length, parsedTrace.UserInteractions.interactionEventsWithNoNesting.length); }); it('creates a flamechart group', async function () { const { flameChartData } = await renderTrackAppender(this, 'slow-interaction-button-click.json.gz'); @@ -50,28 +50,28 @@ describeWithEnvironment('InteractionsTrackAppender', function () { assert.strictEqual(flameChartData.groups[0].name, 'Interactions'); }); it('adds all interactions with the correct start times', async function () { - const { flameChartData, traceParsedData, entryData } = await renderTrackAppender(this, 'slow-interaction-button-click.json.gz'); - const events = traceParsedData.UserInteractions.interactionEventsWithNoNesting; + const { flameChartData, parsedTrace, entryData } = await renderTrackAppender(this, 'slow-interaction-button-click.json.gz'); + const events = parsedTrace.UserInteractions.interactionEventsWithNoNesting; for (const event of events) { const markerIndex = entryData.indexOf(event); assert.exists(markerIndex); - assert.strictEqual(flameChartData.entryStartTimes[markerIndex], TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.ts)); + assert.strictEqual(flameChartData.entryStartTimes[markerIndex], Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts)); } }); it('adds total times correctly', async function () { - const { flameChartData, traceParsedData, entryData } = await renderTrackAppender(this, 'slow-interaction-button-click.json.gz'); - const events = traceParsedData.UserInteractions.interactionEventsWithNoNesting; + const { flameChartData, parsedTrace, entryData } = await renderTrackAppender(this, 'slow-interaction-button-click.json.gz'); + const events = parsedTrace.UserInteractions.interactionEventsWithNoNesting; for (const event of events) { const markerIndex = entryData.indexOf(event); assert.exists(markerIndex); - const expectedTotalTimeForEvent = TraceEngine.Helpers.Timing.microSecondsToMilliseconds((event.dur || 0)); + const expectedTotalTimeForEvent = Trace.Helpers.Timing.microSecondsToMilliseconds((event.dur || 0)); assert.strictEqual(flameChartData.entryTotalTimes[markerIndex], expectedTotalTimeForEvent); } }); }); it('candy-stripes and adds warning triangles to long interactions', async function () { - const { traceParsedData, flameChartData, entryData } = await renderTrackAppender(this, 'one-second-interaction.json.gz'); - const longInteraction = traceParsedData.UserInteractions.longestInteractionEvent; + const { parsedTrace, flameChartData, entryData } = await renderTrackAppender(this, 'one-second-interaction.json.gz'); + const longInteraction = parsedTrace.UserInteractions.longestInteractionEvent; if (!longInteraction) { throw new Error('Could not find longest interaction'); } @@ -80,7 +80,7 @@ describeWithEnvironment('InteractionsTrackAppender', function () { assert.deepEqual(decorationsForEntry, [ { type: "CANDY" /* PerfUI.FlameChart.FlameChartDecorationType.CANDY */, - startAtTime: TraceEngine.Types.Timing.MicroSeconds(200_000), + startAtTime: Trace.Types.Timing.MicroSeconds(200_000), endAtTime: longInteraction.processingEnd, }, { diff --git a/public/panels/timeline/track_appenders/InteractionsTrackAppender.test.js.map b/public/panels/timeline/track_appenders/InteractionsTrackAppender.test.js.map index b30c8e9ce..8f43238f4 100644 --- a/public/panels/timeline/track_appenders/InteractionsTrackAppender.test.js.map +++ b/public/panels/timeline/track_appenders/InteractionsTrackAppender.test.js.map @@ -1 +1 @@ -{"version":3,"file":"InteractionsTrackAppender.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/track_appenders/InteractionsTrackAppender.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceEngine from '../../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as Timeline from '../timeline.js';\n\nfunction initTrackAppender(\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData,\n traceParsedData: TraceEngine.Handlers.Types.TraceParseData,\n entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[],\n entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[],\n ): Timeline.InteractionsTrackAppender.InteractionsTrackAppender {\n const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(\n flameChartData, traceParsedData, entryData, entryTypeByLevel);\n return compatibilityTracksAppender.interactionsTrackAppender();\n}\n\ndescribeWithEnvironment('InteractionsTrackAppender', function() {\n async function renderTrackAppender(context: Mocha.Suite|Mocha.Context, trace: string): Promise<{\n entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[],\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData,\n interactionsTrackAppender: Timeline.InteractionsTrackAppender.InteractionsTrackAppender,\n entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[],\n traceParsedData: Readonly,\n }> {\n const entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[] = [];\n const entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[] = [];\n const flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n const {traceData} = await TraceLoader.traceEngine(context, trace);\n const interactionsTrackAppender = initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel);\n interactionsTrackAppender.appendTrackAtLevel(0);\n\n return {\n entryTypeByLevel,\n traceParsedData: traceData,\n flameChartData,\n interactionsTrackAppender,\n entryData,\n };\n }\n\n describe('appendTrackAtLevel', function() {\n it('marks all levels used by the track with the `TrackAppender` type', async function() {\n const {entryTypeByLevel} = await renderTrackAppender(this, 'slow-interaction-button-click.json.gz');\n // All events fit on the top level\n assert.strictEqual(entryTypeByLevel.length, 1);\n assert.deepEqual(entryTypeByLevel, [\n Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER,\n ]);\n });\n\n it('takes over no levels if there are no interactions', async function() {\n // animation trace has no interactions in it.\n const {entryTypeByLevel} = await renderTrackAppender(this, 'animation.json.gz');\n assert.strictEqual(entryTypeByLevel.length, 0);\n });\n\n it('only shows the top level interactions', async function() {\n const {entryData, traceParsedData} = await renderTrackAppender(this, 'nested-interactions.json.gz');\n assert.strictEqual(entryData.length, traceParsedData.UserInteractions.interactionEventsWithNoNesting.length);\n });\n\n it('creates a flamechart group', async function() {\n const {flameChartData} = await renderTrackAppender(this, 'slow-interaction-button-click.json.gz');\n assert.strictEqual(flameChartData.groups.length, 1);\n assert.strictEqual(flameChartData.groups[0].name, 'Interactions');\n });\n\n it('adds all interactions with the correct start times', async function() {\n const {flameChartData, traceParsedData, entryData} =\n await renderTrackAppender(this, 'slow-interaction-button-click.json.gz');\n const events = traceParsedData.UserInteractions.interactionEventsWithNoNesting;\n for (const event of events) {\n const markerIndex = entryData.indexOf(event);\n assert.exists(markerIndex);\n assert.strictEqual(\n flameChartData.entryStartTimes[markerIndex],\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.ts));\n }\n });\n\n it('adds total times correctly', async function() {\n const {flameChartData, traceParsedData, entryData} =\n await renderTrackAppender(this, 'slow-interaction-button-click.json.gz');\n const events = traceParsedData.UserInteractions.interactionEventsWithNoNesting;\n for (const event of events) {\n const markerIndex = entryData.indexOf(event);\n assert.exists(markerIndex);\n const expectedTotalTimeForEvent = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(\n (event.dur || 0) as TraceEngine.Types.Timing.MicroSeconds);\n assert.strictEqual(flameChartData.entryTotalTimes[markerIndex], expectedTotalTimeForEvent);\n }\n });\n });\n\n it('candy-stripes and adds warning triangles to long interactions', async function() {\n const {traceParsedData, flameChartData, entryData} =\n await renderTrackAppender(this, 'one-second-interaction.json.gz');\n const longInteraction = traceParsedData.UserInteractions.longestInteractionEvent;\n if (!longInteraction) {\n throw new Error('Could not find longest interaction');\n }\n const entryIndex = entryData.indexOf(longInteraction);\n const decorationsForEntry = flameChartData.entryDecorations[entryIndex];\n assert.deepEqual(decorationsForEntry, [\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,\n startAtTime: TraceEngine.Types.Timing.MicroSeconds(200_000),\n endAtTime: longInteraction.processingEnd,\n },\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE,\n customEndTime: longInteraction.processingEnd,\n },\n ]);\n });\n\n it('does not candy-stripe interactions less than 200ms', async function() {\n const {flameChartData} = await renderTrackAppender(this, 'slow-interaction-button-click.json.gz');\n // None of the interactions are over 200ms, so we do not expect to see any decorations\n assert.lengthOf(flameChartData.entryDecorations, 0);\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"InteractionsTrackAppender.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/track_appenders/InteractionsTrackAppender.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as Timeline from '../timeline.js';\n\nfunction initTrackAppender(\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData,\n parsedTrace: Trace.Handlers.Types.ParsedTrace,\n entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[],\n entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[],\n ): Timeline.InteractionsTrackAppender.InteractionsTrackAppender {\n const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(\n flameChartData, parsedTrace, entryData, entryTypeByLevel);\n return compatibilityTracksAppender.interactionsTrackAppender();\n}\n\ndescribeWithEnvironment('InteractionsTrackAppender', function() {\n async function renderTrackAppender(context: Mocha.Suite|Mocha.Context, trace: string): Promise<{\n entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[],\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData,\n interactionsTrackAppender: Timeline.InteractionsTrackAppender.InteractionsTrackAppender,\n entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[],\n parsedTrace: Readonly,\n }> {\n const entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[] = [];\n const entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[] = [];\n const flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n const {parsedTrace} = await TraceLoader.traceEngine(context, trace);\n const interactionsTrackAppender = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel);\n interactionsTrackAppender.appendTrackAtLevel(0);\n\n return {\n entryTypeByLevel,\n parsedTrace,\n flameChartData,\n interactionsTrackAppender,\n entryData,\n };\n }\n\n describe('appendTrackAtLevel', function() {\n it('marks all levels used by the track with the `TrackAppender` type', async function() {\n const {entryTypeByLevel} = await renderTrackAppender(this, 'slow-interaction-button-click.json.gz');\n // All events fit on the top level\n assert.strictEqual(entryTypeByLevel.length, 1);\n assert.deepEqual(entryTypeByLevel, [\n Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER,\n ]);\n });\n\n it('takes over no levels if there are no interactions', async function() {\n // animation trace has no interactions in it.\n const {entryTypeByLevel} = await renderTrackAppender(this, 'animation.json.gz');\n assert.strictEqual(entryTypeByLevel.length, 0);\n });\n\n it('only shows the top level interactions', async function() {\n const {entryData, parsedTrace} = await renderTrackAppender(this, 'nested-interactions.json.gz');\n assert.strictEqual(entryData.length, parsedTrace.UserInteractions.interactionEventsWithNoNesting.length);\n });\n\n it('creates a flamechart group', async function() {\n const {flameChartData} = await renderTrackAppender(this, 'slow-interaction-button-click.json.gz');\n assert.strictEqual(flameChartData.groups.length, 1);\n assert.strictEqual(flameChartData.groups[0].name, 'Interactions');\n });\n\n it('adds all interactions with the correct start times', async function() {\n const {flameChartData, parsedTrace, entryData} =\n await renderTrackAppender(this, 'slow-interaction-button-click.json.gz');\n const events = parsedTrace.UserInteractions.interactionEventsWithNoNesting;\n for (const event of events) {\n const markerIndex = entryData.indexOf(event);\n assert.exists(markerIndex);\n assert.strictEqual(\n flameChartData.entryStartTimes[markerIndex], Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts));\n }\n });\n\n it('adds total times correctly', async function() {\n const {flameChartData, parsedTrace, entryData} =\n await renderTrackAppender(this, 'slow-interaction-button-click.json.gz');\n const events = parsedTrace.UserInteractions.interactionEventsWithNoNesting;\n for (const event of events) {\n const markerIndex = entryData.indexOf(event);\n assert.exists(markerIndex);\n const expectedTotalTimeForEvent =\n Trace.Helpers.Timing.microSecondsToMilliseconds((event.dur || 0) as Trace.Types.Timing.MicroSeconds);\n assert.strictEqual(flameChartData.entryTotalTimes[markerIndex], expectedTotalTimeForEvent);\n }\n });\n });\n\n it('candy-stripes and adds warning triangles to long interactions', async function() {\n const {parsedTrace, flameChartData, entryData} = await renderTrackAppender(this, 'one-second-interaction.json.gz');\n const longInteraction = parsedTrace.UserInteractions.longestInteractionEvent;\n if (!longInteraction) {\n throw new Error('Could not find longest interaction');\n }\n const entryIndex = entryData.indexOf(longInteraction);\n const decorationsForEntry = flameChartData.entryDecorations[entryIndex];\n assert.deepEqual(decorationsForEntry, [\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,\n startAtTime: Trace.Types.Timing.MicroSeconds(200_000),\n endAtTime: longInteraction.processingEnd,\n },\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE,\n customEndTime: longInteraction.processingEnd,\n },\n ]);\n });\n\n it('does not candy-stripe interactions less than 200ms', async function() {\n const {flameChartData} = await renderTrackAppender(this, 'slow-interaction-button-click.json.gz');\n // None of the interactions are over 200ms, so we do not expect to see any decorations\n assert.lengthOf(flameChartData.entryDecorations, 0);\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/track_appenders/LayoutShiftsTrackAppender.test.js b/public/panels/timeline/track_appenders/LayoutShiftsTrackAppender.test.js index 1f5ad01d4..828494291 100644 --- a/public/panels/timeline/track_appenders/LayoutShiftsTrackAppender.test.js +++ b/public/panels/timeline/track_appenders/LayoutShiftsTrackAppender.test.js @@ -1,13 +1,13 @@ // 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 * as TraceModel from '../../../models/trace/trace.js'; +import * as Trace from '../../../models/trace/trace.js'; import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; import * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js'; import * as Timeline from '../timeline.js'; -function initTrackAppender(flameChartData, traceParsedData, entryData, entryTypeByLevel) { - const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(flameChartData, traceParsedData, entryData, entryTypeByLevel); +function initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel) { + const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel); return compatibilityTracksAppender.layoutShiftsTrackAppender(); } describeWithEnvironment('LayoutShiftsTrackAppender', function () { @@ -15,12 +15,12 @@ describeWithEnvironment('LayoutShiftsTrackAppender', function () { const entryTypeByLevel = []; const entryData = []; const flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty(); - const { traceData } = await TraceLoader.traceEngine(context, trace); - const layoutShiftsTrackAppender = initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel); + const { parsedTrace } = await TraceLoader.traceEngine(context, trace); + const layoutShiftsTrackAppender = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel); layoutShiftsTrackAppender.appendTrackAtLevel(0); return { entryTypeByLevel, - traceParsedData: traceData, + parsedTrace, flameChartData, layoutShiftsTrackAppender, entryData, @@ -45,17 +45,17 @@ describeWithEnvironment('LayoutShiftsTrackAppender', function () { assert.strictEqual(flameChartData.groups[0].name, 'Layout shifts'); }); it('adds all layout shifts with the correct start times', async function () { - const { flameChartData, traceParsedData, entryData } = await renderTrackAppender(this, 'cls-single-frame.json.gz'); - const events = traceParsedData.LayoutShifts.clusters.flatMap(c => c.events); + const { flameChartData, parsedTrace, entryData } = await renderTrackAppender(this, 'cls-single-frame.json.gz'); + const events = parsedTrace.LayoutShifts.clusters.flatMap(c => c.events); for (const event of events) { const markerIndex = entryData.indexOf(event); assert.exists(markerIndex); - assert.strictEqual(flameChartData.entryStartTimes[markerIndex], TraceModel.Helpers.Timing.microSecondsToMilliseconds(event.ts)); + assert.strictEqual(flameChartData.entryStartTimes[markerIndex], Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts)); } }); it('sets all layout shifts to be 5ms in duration', async function () { - const { flameChartData, traceParsedData, entryData } = await renderTrackAppender(this, 'cls-single-frame.json.gz'); - const events = traceParsedData.LayoutShifts.clusters.flatMap(c => c.events); + const { flameChartData, parsedTrace, entryData } = await renderTrackAppender(this, 'cls-single-frame.json.gz'); + const events = parsedTrace.LayoutShifts.clusters.flatMap(c => c.events); for (const event of events) { const markerIndex = entryData.indexOf(event); assert.exists(markerIndex); @@ -63,14 +63,14 @@ describeWithEnvironment('LayoutShiftsTrackAppender', function () { } }); it('returns the correct title for a layout shift', async function () { - const { layoutShiftsTrackAppender, traceParsedData } = await renderTrackAppender(this, 'cls-single-frame.json.gz'); - const shifts = traceParsedData.LayoutShifts.clusters.flatMap(c => c.events); + const { layoutShiftsTrackAppender, parsedTrace } = await renderTrackAppender(this, 'cls-single-frame.json.gz'); + const shifts = parsedTrace.LayoutShifts.clusters.flatMap(c => c.events); const title = layoutShiftsTrackAppender.titleForEvent(shifts[0]); assert.strictEqual(title, 'Layout shift'); }); it('shows "Layout shift" text on hover', async function () { - const { layoutShiftsTrackAppender, traceParsedData } = await renderTrackAppender(this, 'cls-single-frame.json.gz'); - const shifts = traceParsedData.LayoutShifts.clusters.flatMap(c => c.events); + const { layoutShiftsTrackAppender, parsedTrace } = await renderTrackAppender(this, 'cls-single-frame.json.gz'); + const shifts = parsedTrace.LayoutShifts.clusters.flatMap(c => c.events); const info = layoutShiftsTrackAppender.highlightedEntryInfo(shifts[0]); assert.deepEqual(info, { title: 'Layout shift', diff --git a/public/panels/timeline/track_appenders/LayoutShiftsTrackAppender.test.js.map b/public/panels/timeline/track_appenders/LayoutShiftsTrackAppender.test.js.map index 780e7fcfe..902f85c73 100644 --- a/public/panels/timeline/track_appenders/LayoutShiftsTrackAppender.test.js.map +++ b/public/panels/timeline/track_appenders/LayoutShiftsTrackAppender.test.js.map @@ -1 +1 @@ -{"version":3,"file":"LayoutShiftsTrackAppender.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/track_appenders/LayoutShiftsTrackAppender.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceModel from '../../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as Timeline from '../timeline.js';\n\nfunction initTrackAppender(\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData, traceParsedData: TraceModel.Handlers.Types.TraceParseData,\n entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[],\n entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[]):\n Timeline.LayoutShiftsTrackAppender.LayoutShiftsTrackAppender {\n const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(\n flameChartData, traceParsedData, entryData, entryTypeByLevel);\n return compatibilityTracksAppender.layoutShiftsTrackAppender();\n}\n\ndescribeWithEnvironment('LayoutShiftsTrackAppender', function() {\n async function renderTrackAppender(context: Mocha.Context|Mocha.Suite, trace: string): Promise<{\n entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[],\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData,\n layoutShiftsTrackAppender: Timeline.LayoutShiftsTrackAppender.LayoutShiftsTrackAppender,\n entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[],\n traceParsedData: Readonly,\n }> {\n const entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[] = [];\n const entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[] = [];\n const flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n const {traceData} = await TraceLoader.traceEngine(context, trace);\n const layoutShiftsTrackAppender = initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel);\n layoutShiftsTrackAppender.appendTrackAtLevel(0);\n\n return {\n entryTypeByLevel,\n traceParsedData: traceData,\n flameChartData,\n layoutShiftsTrackAppender,\n entryData,\n };\n }\n\n it('marks all levels used by the track with the TrackAppender type', async function() {\n const {entryTypeByLevel} = await renderTrackAppender(this, 'cls-single-frame.json.gz');\n // Only one row of layout shifts.\n assert.strictEqual(entryTypeByLevel.length, 1);\n assert.deepEqual(entryTypeByLevel, [\n Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER,\n ]);\n });\n\n it('does not append anything if there are no layout shifts', async function() {\n // No layout shifts.\n const {entryTypeByLevel} = await renderTrackAppender(this, 'animation.json.gz');\n assert.lengthOf(entryTypeByLevel, 0);\n });\n\n it('creates a flamechart group', async function() {\n const {flameChartData} = await renderTrackAppender(this, 'cls-single-frame.json.gz');\n assert.strictEqual(flameChartData.groups.length, 1);\n assert.strictEqual(flameChartData.groups[0].name, 'Layout shifts');\n });\n\n it('adds all layout shifts with the correct start times', async function() {\n const {flameChartData, traceParsedData, entryData} = await renderTrackAppender(this, 'cls-single-frame.json.gz');\n const events = traceParsedData.LayoutShifts.clusters.flatMap(c => c.events);\n for (const event of events) {\n const markerIndex = entryData.indexOf(event);\n assert.exists(markerIndex);\n assert.strictEqual(\n flameChartData.entryStartTimes[markerIndex], TraceModel.Helpers.Timing.microSecondsToMilliseconds(event.ts));\n }\n });\n\n it('sets all layout shifts to be 5ms in duration', async function() {\n const {flameChartData, traceParsedData, entryData} = await renderTrackAppender(this, 'cls-single-frame.json.gz');\n const events = traceParsedData.LayoutShifts.clusters.flatMap(c => c.events);\n for (const event of events) {\n const markerIndex = entryData.indexOf(event);\n assert.exists(markerIndex);\n assert.strictEqual(flameChartData.entryTotalTimes[markerIndex], 5);\n }\n });\n\n it('returns the correct title for a layout shift', async function() {\n const {layoutShiftsTrackAppender, traceParsedData} = await renderTrackAppender(this, 'cls-single-frame.json.gz');\n const shifts = traceParsedData.LayoutShifts.clusters.flatMap(c => c.events);\n const title = layoutShiftsTrackAppender.titleForEvent(shifts[0]);\n assert.strictEqual(title, 'Layout shift');\n });\n\n it('shows \"Layout shift\" text on hover', async function() {\n const {layoutShiftsTrackAppender, traceParsedData} = await renderTrackAppender(this, 'cls-single-frame.json.gz');\n const shifts = traceParsedData.LayoutShifts.clusters.flatMap(c => c.events);\n const info = layoutShiftsTrackAppender.highlightedEntryInfo(shifts[0]);\n assert.deepEqual(info, {\n title: 'Layout shift',\n formattedTime: '',\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"LayoutShiftsTrackAppender.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/track_appenders/LayoutShiftsTrackAppender.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as Timeline from '../timeline.js';\n\nfunction initTrackAppender(\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData, parsedTrace: Trace.Handlers.Types.ParsedTrace,\n entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[],\n entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[]):\n Timeline.LayoutShiftsTrackAppender.LayoutShiftsTrackAppender {\n const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(\n flameChartData, parsedTrace, entryData, entryTypeByLevel);\n return compatibilityTracksAppender.layoutShiftsTrackAppender();\n}\n\ndescribeWithEnvironment('LayoutShiftsTrackAppender', function() {\n async function renderTrackAppender(context: Mocha.Context|Mocha.Suite, trace: string): Promise<{\n entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[],\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData,\n layoutShiftsTrackAppender: Timeline.LayoutShiftsTrackAppender.LayoutShiftsTrackAppender,\n entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[],\n parsedTrace: Readonly,\n }> {\n const entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[] = [];\n const entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[] = [];\n const flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n const {parsedTrace} = await TraceLoader.traceEngine(context, trace);\n const layoutShiftsTrackAppender = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel);\n layoutShiftsTrackAppender.appendTrackAtLevel(0);\n\n return {\n entryTypeByLevel,\n parsedTrace,\n flameChartData,\n layoutShiftsTrackAppender,\n entryData,\n };\n }\n\n it('marks all levels used by the track with the TrackAppender type', async function() {\n const {entryTypeByLevel} = await renderTrackAppender(this, 'cls-single-frame.json.gz');\n // Only one row of layout shifts.\n assert.strictEqual(entryTypeByLevel.length, 1);\n assert.deepEqual(entryTypeByLevel, [\n Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER,\n ]);\n });\n\n it('does not append anything if there are no layout shifts', async function() {\n // No layout shifts.\n const {entryTypeByLevel} = await renderTrackAppender(this, 'animation.json.gz');\n assert.lengthOf(entryTypeByLevel, 0);\n });\n\n it('creates a flamechart group', async function() {\n const {flameChartData} = await renderTrackAppender(this, 'cls-single-frame.json.gz');\n assert.strictEqual(flameChartData.groups.length, 1);\n assert.strictEqual(flameChartData.groups[0].name, 'Layout shifts');\n });\n\n it('adds all layout shifts with the correct start times', async function() {\n const {flameChartData, parsedTrace, entryData} = await renderTrackAppender(this, 'cls-single-frame.json.gz');\n const events = parsedTrace.LayoutShifts.clusters.flatMap(c => c.events);\n for (const event of events) {\n const markerIndex = entryData.indexOf(event);\n assert.exists(markerIndex);\n assert.strictEqual(\n flameChartData.entryStartTimes[markerIndex], Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts));\n }\n });\n\n it('sets all layout shifts to be 5ms in duration', async function() {\n const {flameChartData, parsedTrace, entryData} = await renderTrackAppender(this, 'cls-single-frame.json.gz');\n const events = parsedTrace.LayoutShifts.clusters.flatMap(c => c.events);\n for (const event of events) {\n const markerIndex = entryData.indexOf(event);\n assert.exists(markerIndex);\n assert.strictEqual(flameChartData.entryTotalTimes[markerIndex], 5);\n }\n });\n\n it('returns the correct title for a layout shift', async function() {\n const {layoutShiftsTrackAppender, parsedTrace} = await renderTrackAppender(this, 'cls-single-frame.json.gz');\n const shifts = parsedTrace.LayoutShifts.clusters.flatMap(c => c.events);\n const title = layoutShiftsTrackAppender.titleForEvent(shifts[0]);\n assert.strictEqual(title, 'Layout shift');\n });\n\n it('shows \"Layout shift\" text on hover', async function() {\n const {layoutShiftsTrackAppender, parsedTrace} = await renderTrackAppender(this, 'cls-single-frame.json.gz');\n const shifts = parsedTrace.LayoutShifts.clusters.flatMap(c => c.events);\n const info = layoutShiftsTrackAppender.highlightedEntryInfo(shifts[0]);\n assert.deepEqual(info, {\n title: 'Layout shift',\n formattedTime: '',\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/track_appenders/NetworkTrackAppender.test.js b/public/panels/timeline/track_appenders/NetworkTrackAppender.test.js index c1d1adf9e..df09363a3 100644 --- a/public/panels/timeline/track_appenders/NetworkTrackAppender.test.js +++ b/public/panels/timeline/track_appenders/NetworkTrackAppender.test.js @@ -1,20 +1,20 @@ // 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 * as TraceEngine from '../../../models/trace/trace.js'; +import * as Trace from '../../../models/trace/trace.js'; import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; import * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js'; import * as TimelineComponents from '../components/components.js'; import * as Timeline from '../timeline.js'; describeWithEnvironment('NetworkTrackAppender', function () { - let traceData; + let parsedTrace; let networkTrackAppender; let flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty(); beforeEach(async function () { - ({ traceData } = await TraceLoader.traceEngine(this, 'cls-cluster-max-timeout.json.gz')); + ({ parsedTrace } = await TraceLoader.traceEngine(this, 'cls-cluster-max-timeout.json.gz')); networkTrackAppender = - new Timeline.NetworkTrackAppender.NetworkTrackAppender(flameChartData, traceData.NetworkRequests.byTime); + new Timeline.NetworkTrackAppender.NetworkTrackAppender(flameChartData, parsedTrace.NetworkRequests.byTime); networkTrackAppender.appendTrackAtLevel(0); }); afterEach(() => { @@ -26,29 +26,29 @@ describeWithEnvironment('NetworkTrackAppender', function () { assert.strictEqual(flameChartData.groups[0].name, 'Network'); }); it('adds start times correctly', function () { - const networkRequests = traceData.NetworkRequests.byTime; + const networkRequests = parsedTrace.NetworkRequests.byTime; for (let i = 0; i < networkRequests.length; ++i) { const event = networkRequests[i]; - assert.strictEqual(flameChartData.entryStartTimes[i], TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.ts)); + assert.strictEqual(flameChartData.entryStartTimes[i], Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts)); } }); it('adds total times correctly', function () { - const networkRequests = traceData.NetworkRequests.byTime; + const networkRequests = parsedTrace.NetworkRequests.byTime; for (let i = 0; i < networkRequests.length; i++) { const event = networkRequests[i]; - if (TraceEngine.Types.TraceEvents.isTraceEventMarkerEvent(event)) { + if (Trace.Types.Events.isMarkerEvent(event)) { assert.isNaN(flameChartData.entryTotalTimes[i]); continue; } const expectedTotalTimeForEvent = event.dur ? - TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.dur) : + Trace.Helpers.Timing.microSecondsToMilliseconds(event.dur) : Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs; assert.strictEqual(flameChartData.entryTotalTimes[i], expectedTotalTimeForEvent); } }); }); it('returns the correct color for network events', function () { - const networkRequests = traceData.NetworkRequests.byTime; + const networkRequests = parsedTrace.NetworkRequests.byTime; for (const event of networkRequests) { const color = TimelineComponents.Utils.colorForNetworkRequest(event); assert.strictEqual(networkTrackAppender.colorForEvent(event), color); diff --git a/public/panels/timeline/track_appenders/NetworkTrackAppender.test.js.map b/public/panels/timeline/track_appenders/NetworkTrackAppender.test.js.map index e3b0bac77..41f902f55 100644 --- a/public/panels/timeline/track_appenders/NetworkTrackAppender.test.js.map +++ b/public/panels/timeline/track_appenders/NetworkTrackAppender.test.js.map @@ -1 +1 @@ -{"version":3,"file":"NetworkTrackAppender.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/track_appenders/NetworkTrackAppender.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceEngine from '../../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as TimelineComponents from '../components/components.js';\nimport * as Timeline from '../timeline.js';\n\ndescribeWithEnvironment('NetworkTrackAppender', function() {\n let traceData: TraceEngine.Handlers.Types.TraceParseData;\n let networkTrackAppender: Timeline.NetworkTrackAppender.NetworkTrackAppender;\n let flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n\n beforeEach(async function() {\n ({traceData} = await TraceLoader.traceEngine(this, 'cls-cluster-max-timeout.json.gz'));\n networkTrackAppender =\n new Timeline.NetworkTrackAppender.NetworkTrackAppender(flameChartData, traceData.NetworkRequests.byTime);\n networkTrackAppender.appendTrackAtLevel(0);\n });\n\n afterEach(() => {\n flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n });\n\n describe('appendTrackAtLevel', function() {\n it('creates a flamechart group for the Network track', function() {\n assert.strictEqual(flameChartData.groups.length, 1);\n assert.strictEqual(flameChartData.groups[0].name, 'Network');\n });\n\n it('adds start times correctly', function() {\n const networkRequests = traceData.NetworkRequests.byTime;\n for (let i = 0; i < networkRequests.length; ++i) {\n const event = networkRequests[i];\n assert.strictEqual(\n flameChartData.entryStartTimes[i], TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.ts));\n }\n });\n\n it('adds total times correctly', function() {\n const networkRequests = traceData.NetworkRequests.byTime;\n for (let i = 0; i < networkRequests.length; i++) {\n const event = networkRequests[i];\n if (TraceEngine.Types.TraceEvents.isTraceEventMarkerEvent(event)) {\n assert.isNaN(flameChartData.entryTotalTimes[i]);\n continue;\n }\n const expectedTotalTimeForEvent = event.dur ?\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.dur) :\n Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs;\n assert.strictEqual(flameChartData.entryTotalTimes[i], expectedTotalTimeForEvent);\n }\n });\n });\n\n it('returns the correct color for network events', function() {\n const networkRequests = traceData.NetworkRequests.byTime;\n for (const event of networkRequests) {\n const color = TimelineComponents.Utils.colorForNetworkRequest(event);\n assert.strictEqual(networkTrackAppender.colorForEvent(event), color);\n }\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"NetworkTrackAppender.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/track_appenders/NetworkTrackAppender.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as TimelineComponents from '../components/components.js';\nimport * as Timeline from '../timeline.js';\n\ndescribeWithEnvironment('NetworkTrackAppender', function() {\n let parsedTrace: Trace.Handlers.Types.ParsedTrace;\n let networkTrackAppender: Timeline.NetworkTrackAppender.NetworkTrackAppender;\n let flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n\n beforeEach(async function() {\n ({parsedTrace} = await TraceLoader.traceEngine(this, 'cls-cluster-max-timeout.json.gz'));\n networkTrackAppender =\n new Timeline.NetworkTrackAppender.NetworkTrackAppender(flameChartData, parsedTrace.NetworkRequests.byTime);\n networkTrackAppender.appendTrackAtLevel(0);\n });\n\n afterEach(() => {\n flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n });\n\n describe('appendTrackAtLevel', function() {\n it('creates a flamechart group for the Network track', function() {\n assert.strictEqual(flameChartData.groups.length, 1);\n assert.strictEqual(flameChartData.groups[0].name, 'Network');\n });\n\n it('adds start times correctly', function() {\n const networkRequests = parsedTrace.NetworkRequests.byTime;\n for (let i = 0; i < networkRequests.length; ++i) {\n const event = networkRequests[i];\n assert.strictEqual(\n flameChartData.entryStartTimes[i], Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts));\n }\n });\n\n it('adds total times correctly', function() {\n const networkRequests = parsedTrace.NetworkRequests.byTime;\n for (let i = 0; i < networkRequests.length; i++) {\n const event = networkRequests[i];\n if (Trace.Types.Events.isMarkerEvent(event)) {\n assert.isNaN(flameChartData.entryTotalTimes[i]);\n continue;\n }\n const expectedTotalTimeForEvent = event.dur ?\n Trace.Helpers.Timing.microSecondsToMilliseconds(event.dur) :\n Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs;\n assert.strictEqual(flameChartData.entryTotalTimes[i], expectedTotalTimeForEvent);\n }\n });\n });\n\n it('returns the correct color for network events', function() {\n const networkRequests = parsedTrace.NetworkRequests.byTime;\n for (const event of networkRequests) {\n const color = TimelineComponents.Utils.colorForNetworkRequest(event);\n assert.strictEqual(networkTrackAppender.colorForEvent(event), color);\n }\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/track_appenders/ServerTimingsTrackAppender.test.js b/public/panels/timeline/track_appenders/ServerTimingsTrackAppender.test.js index 6d7f8392c..0b5bc1eb9 100644 --- a/public/panels/timeline/track_appenders/ServerTimingsTrackAppender.test.js +++ b/public/panels/timeline/track_appenders/ServerTimingsTrackAppender.test.js @@ -2,26 +2,26 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as Root from '../../../core/root/root.js'; -import * as TraceEngine from '../../../models/trace/trace.js'; +import * as Trace from '../../../models/trace/trace.js'; import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; import * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js'; import * as ThemeSupport from '../../../ui/legacy/theme_support/theme_support.js'; import * as Timeline from '../timeline.js'; -function initTrackAppender(flameChartData, traceParsedData, entryData, entryTypeByLevel) { - const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(flameChartData, traceParsedData, entryData, entryTypeByLevel); +function initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel) { + const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel); return compatibilityTracksAppender.serverTimingsTrackAppender(); } describeWithEnvironment('ServerTimingsTrackAppender', function () { - let traceData; + let parsedTrace; let serverTimingsTrackAppender; let entryData = []; let flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty(); let entryTypeByLevel = []; beforeEach(async function () { Root.Runtime.experiments.enableForTest("timeline-server-timings" /* Root.Runtime.ExperimentName.TIMELINE_SERVER_TIMINGS */); - ({ traceData } = await TraceLoader.traceEngine(this, 'server-timings.json.gz')); - serverTimingsTrackAppender = initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel); + ({ parsedTrace } = await TraceLoader.traceEngine(this, 'server-timings.json.gz')); + serverTimingsTrackAppender = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel); serverTimingsTrackAppender.appendTrackAtLevel(0); }); afterEach(() => { @@ -40,22 +40,22 @@ describeWithEnvironment('ServerTimingsTrackAppender', function () { assert.strictEqual(flameChartData.groups[0].description, 'This track contains timings taken from Server-Timing network response headers. Their respective start times are only estimated and may not be accurate.'); }); it('adds start times correctly', function () { - const animationsRequests = traceData.Animations.animations; + const animationsRequests = parsedTrace.Animations.animations; for (let i = 0; i < animationsRequests.length; ++i) { const event = animationsRequests[i]; - assert.strictEqual(flameChartData.entryStartTimes[i], TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.ts)); + assert.strictEqual(flameChartData.entryStartTimes[i], Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts)); } }); it('adds total times correctly', function () { - const animationsRequests = traceData.Animations.animations; + const animationsRequests = parsedTrace.Animations.animations; for (let i = 0; i < animationsRequests.length; i++) { const event = animationsRequests[i]; - if (TraceEngine.Types.TraceEvents.isTraceEventMarkerEvent(event)) { + if (Trace.Types.Events.isMarkerEvent(event)) { assert.isNaN(flameChartData.entryTotalTimes[i]); continue; } const expectedTotalTimeForEvent = event.dur ? - TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.dur) : + Trace.Helpers.Timing.microSecondsToMilliseconds(event.dur) : Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs; assert.strictEqual(flameChartData.entryTotalTimes[i], expectedTotalTimeForEvent); } @@ -86,7 +86,7 @@ describeWithEnvironment('ServerTimingsTrackAppender', function () { ThemeSupport.ThemeSupport.clearThemeCache(); }); it('returns the correct color and title for server timing events', function () { - const serverTimings = traceData.ServerTimings.serverTimings; + const serverTimings = parsedTrace.ServerTimings.serverTimings; for (const event of serverTimings) { assert.strictEqual(serverTimingsTrackAppender.titleForEvent(event), event.name); assert.strictEqual(serverTimingsTrackAppender.colorForEvent(), 'rgb(4 4 4)'); @@ -95,7 +95,7 @@ describeWithEnvironment('ServerTimingsTrackAppender', function () { }); describe('highlightedEntryInfo', function () { it('returns the info for an entry correctly', function () { - const serverTimings = traceData.ServerTimings.serverTimings; + const serverTimings = parsedTrace.ServerTimings.serverTimings; const highlightedEntryInfo = serverTimingsTrackAppender.highlightedEntryInfo(serverTimings[0]); // The i18n encodes spaces using the u00A0 unicode character. assert.strictEqual(highlightedEntryInfo.formattedTime, '1.00\u00A0s'); diff --git a/public/panels/timeline/track_appenders/ServerTimingsTrackAppender.test.js.map b/public/panels/timeline/track_appenders/ServerTimingsTrackAppender.test.js.map index e97a0c926..8799ab5bd 100644 --- a/public/panels/timeline/track_appenders/ServerTimingsTrackAppender.test.js.map +++ b/public/panels/timeline/track_appenders/ServerTimingsTrackAppender.test.js.map @@ -1 +1 @@ -{"version":3,"file":"ServerTimingsTrackAppender.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/track_appenders/ServerTimingsTrackAppender.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Root from '../../../core/root/root.js';\nimport type * as TraceModel from '../../../models/trace/trace.js';\nimport * as TraceEngine from '../../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as ThemeSupport from '../../../ui/legacy/theme_support/theme_support.js';\nimport * as Timeline from '../timeline.js';\n\nfunction initTrackAppender(\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData, traceParsedData: TraceModel.Handlers.Types.TraceParseData,\n entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[],\n entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[]):\n Timeline.ServerTimingsTrackAppender.ServerTimingsTrackAppender {\n const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(\n flameChartData, traceParsedData, entryData, entryTypeByLevel);\n return compatibilityTracksAppender.serverTimingsTrackAppender();\n}\n\ndescribeWithEnvironment('ServerTimingsTrackAppender', function() {\n let traceData: TraceModel.Handlers.Types.TraceParseData;\n let serverTimingsTrackAppender: Timeline.ServerTimingsTrackAppender.ServerTimingsTrackAppender;\n let entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[] = [];\n let flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n let entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[] = [];\n\n beforeEach(async function() {\n Root.Runtime.experiments.enableForTest(Root.Runtime.ExperimentName.TIMELINE_SERVER_TIMINGS);\n\n ({traceData} = await TraceLoader.traceEngine(this, 'server-timings.json.gz'));\n serverTimingsTrackAppender = initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel);\n serverTimingsTrackAppender.appendTrackAtLevel(0);\n });\n\n afterEach(() => {\n Root.Runtime.experiments.disableForTest(Root.Runtime.ExperimentName.TIMELINE_SERVER_TIMINGS);\n\n entryData = [];\n flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n entryTypeByLevel = [];\n });\n\n describe('appendTrackAtLevel', function() {\n it('creates a flamechart group for the Server timings track', function() {\n assert.strictEqual(flameChartData.groups.length, 1);\n assert.strictEqual(flameChartData.groups[0].name, 'Server Timings — https://node-server-tan.vercel.app');\n });\n\n it('Adds a description to server timings tracks', function() {\n assert.strictEqual(flameChartData.groups.length, 1);\n assert.strictEqual(\n flameChartData.groups[0].description,\n 'This track contains timings taken from Server-Timing network response headers. Their respective start times are only estimated and may not be accurate.');\n });\n\n it('adds start times correctly', function() {\n const animationsRequests = traceData.Animations.animations;\n for (let i = 0; i < animationsRequests.length; ++i) {\n const event = animationsRequests[i];\n assert.strictEqual(\n flameChartData.entryStartTimes[i], TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.ts));\n }\n });\n\n it('adds total times correctly', function() {\n const animationsRequests = traceData.Animations.animations;\n for (let i = 0; i < animationsRequests.length; i++) {\n const event = animationsRequests[i];\n if (TraceEngine.Types.TraceEvents.isTraceEventMarkerEvent(event)) {\n assert.isNaN(flameChartData.entryTotalTimes[i]);\n continue;\n }\n const expectedTotalTimeForEvent = event.dur ?\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds(event.dur) :\n Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs;\n assert.strictEqual(flameChartData.entryTotalTimes[i], expectedTotalTimeForEvent);\n }\n });\n });\n\n describe('colorForEvent and titleForEvent', function() {\n before(() => {\n // Rather than use the real colours here and burden the test with having to\n // inject loads of CSS, we fake out the colours. this is fine for our tests as\n // the exact value of the colours is not important; we just make sure that it\n // parses them out correctly. Each variable is given a different rgb() value to\n // ensure we know the code is working and using the right one.\n const styleElement = document.createElement('style');\n styleElement.id = 'fake-perf-panel-colors';\n styleElement.textContent = `\n :root {\n --ref-palette-primary70: rgb(4 4 4);\n }\n `;\n document.documentElement.appendChild(styleElement);\n ThemeSupport.ThemeSupport.clearThemeCache();\n });\n\n after(() => {\n const styleElementToRemove = document.documentElement.querySelector('#fake-perf-panel-colors');\n if (styleElementToRemove) {\n document.documentElement.removeChild(styleElementToRemove);\n }\n ThemeSupport.ThemeSupport.clearThemeCache();\n });\n it('returns the correct color and title for server timing events', function() {\n const serverTimings = traceData.ServerTimings.serverTimings;\n for (const event of serverTimings) {\n assert.strictEqual(serverTimingsTrackAppender.titleForEvent(event), event.name);\n assert.strictEqual(serverTimingsTrackAppender.colorForEvent(), 'rgb(4 4 4)');\n }\n });\n });\n\n describe('highlightedEntryInfo', function() {\n it('returns the info for an entry correctly', function() {\n const serverTimings = traceData.ServerTimings.serverTimings;\n const highlightedEntryInfo = serverTimingsTrackAppender.highlightedEntryInfo(serverTimings[0]);\n // The i18n encodes spaces using the u00A0 unicode character.\n assert.strictEqual(highlightedEntryInfo.formattedTime, '1.00\\u00A0s');\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"ServerTimingsTrackAppender.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/track_appenders/ServerTimingsTrackAppender.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Root from '../../../core/root/root.js';\nimport * as Trace from '../../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as ThemeSupport from '../../../ui/legacy/theme_support/theme_support.js';\nimport * as Timeline from '../timeline.js';\n\nfunction initTrackAppender(\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData, parsedTrace: Trace.Handlers.Types.ParsedTrace,\n entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[],\n entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[]):\n Timeline.ServerTimingsTrackAppender.ServerTimingsTrackAppender {\n const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(\n flameChartData, parsedTrace, entryData, entryTypeByLevel);\n return compatibilityTracksAppender.serverTimingsTrackAppender();\n}\n\ndescribeWithEnvironment('ServerTimingsTrackAppender', function() {\n let parsedTrace: Trace.Handlers.Types.ParsedTrace;\n let serverTimingsTrackAppender: Timeline.ServerTimingsTrackAppender.ServerTimingsTrackAppender;\n let entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[] = [];\n let flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n let entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[] = [];\n\n beforeEach(async function() {\n Root.Runtime.experiments.enableForTest(Root.Runtime.ExperimentName.TIMELINE_SERVER_TIMINGS);\n\n ({parsedTrace} = await TraceLoader.traceEngine(this, 'server-timings.json.gz'));\n serverTimingsTrackAppender = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel);\n serverTimingsTrackAppender.appendTrackAtLevel(0);\n });\n\n afterEach(() => {\n Root.Runtime.experiments.disableForTest(Root.Runtime.ExperimentName.TIMELINE_SERVER_TIMINGS);\n\n entryData = [];\n flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n entryTypeByLevel = [];\n });\n\n describe('appendTrackAtLevel', function() {\n it('creates a flamechart group for the Server timings track', function() {\n assert.strictEqual(flameChartData.groups.length, 1);\n assert.strictEqual(flameChartData.groups[0].name, 'Server Timings — https://node-server-tan.vercel.app');\n });\n\n it('Adds a description to server timings tracks', function() {\n assert.strictEqual(flameChartData.groups.length, 1);\n assert.strictEqual(\n flameChartData.groups[0].description,\n 'This track contains timings taken from Server-Timing network response headers. Their respective start times are only estimated and may not be accurate.');\n });\n\n it('adds start times correctly', function() {\n const animationsRequests = parsedTrace.Animations.animations;\n for (let i = 0; i < animationsRequests.length; ++i) {\n const event = animationsRequests[i];\n assert.strictEqual(\n flameChartData.entryStartTimes[i], Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts));\n }\n });\n\n it('adds total times correctly', function() {\n const animationsRequests = parsedTrace.Animations.animations;\n for (let i = 0; i < animationsRequests.length; i++) {\n const event = animationsRequests[i];\n if (Trace.Types.Events.isMarkerEvent(event)) {\n assert.isNaN(flameChartData.entryTotalTimes[i]);\n continue;\n }\n const expectedTotalTimeForEvent = event.dur ?\n Trace.Helpers.Timing.microSecondsToMilliseconds(event.dur) :\n Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs;\n assert.strictEqual(flameChartData.entryTotalTimes[i], expectedTotalTimeForEvent);\n }\n });\n });\n\n describe('colorForEvent and titleForEvent', function() {\n before(() => {\n // Rather than use the real colours here and burden the test with having to\n // inject loads of CSS, we fake out the colours. this is fine for our tests as\n // the exact value of the colours is not important; we just make sure that it\n // parses them out correctly. Each variable is given a different rgb() value to\n // ensure we know the code is working and using the right one.\n const styleElement = document.createElement('style');\n styleElement.id = 'fake-perf-panel-colors';\n styleElement.textContent = `\n :root {\n --ref-palette-primary70: rgb(4 4 4);\n }\n `;\n document.documentElement.appendChild(styleElement);\n ThemeSupport.ThemeSupport.clearThemeCache();\n });\n\n after(() => {\n const styleElementToRemove = document.documentElement.querySelector('#fake-perf-panel-colors');\n if (styleElementToRemove) {\n document.documentElement.removeChild(styleElementToRemove);\n }\n ThemeSupport.ThemeSupport.clearThemeCache();\n });\n it('returns the correct color and title for server timing events', function() {\n const serverTimings = parsedTrace.ServerTimings.serverTimings;\n for (const event of serverTimings) {\n assert.strictEqual(serverTimingsTrackAppender.titleForEvent(event), event.name);\n assert.strictEqual(serverTimingsTrackAppender.colorForEvent(), 'rgb(4 4 4)');\n }\n });\n });\n\n describe('highlightedEntryInfo', function() {\n it('returns the info for an entry correctly', function() {\n const serverTimings = parsedTrace.ServerTimings.serverTimings;\n const highlightedEntryInfo = serverTimingsTrackAppender.highlightedEntryInfo(serverTimings[0]);\n // The i18n encodes spaces using the u00A0 unicode character.\n assert.strictEqual(highlightedEntryInfo.formattedTime, '1.00\\u00A0s');\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/track_appenders/ThreadAppender.test.js b/public/panels/timeline/track_appenders/ThreadAppender.test.js index 7f8b5702a..7ce8c56ca 100644 --- a/public/panels/timeline/track_appenders/ThreadAppender.test.js +++ b/public/panels/timeline/track_appenders/ThreadAppender.test.js @@ -4,41 +4,41 @@ import * as Root from '../../../core/root/root.js'; import * as SDK from '../../../core/sdk/sdk.js'; import * as Bindings from '../../../models/bindings/bindings.js'; -import * as TraceModel from '../../../models/trace/trace.js'; +import * as Trace from '../../../models/trace/trace.js'; import * as Workspace from '../../../models/workspace/workspace.js'; import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; import { makeMockRendererHandlerData as makeRendererHandlerData, makeProfileCall, setupIgnoreListManagerEnvironment, } from '../../../testing/TraceHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; import * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js'; import * as Timeline from '../timeline.js'; -function initTrackAppender(flameChartData, traceParsedData, entryData, entryTypeByLevel) { +function initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel) { setupIgnoreListManagerEnvironment(); - const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(flameChartData, traceParsedData, entryData, entryTypeByLevel); + const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel); return compatibilityTracksAppender.threadAppenders(); } async function renderThreadAppendersFromTrace(context, trace) { const entryTypeByLevel = []; const entryData = []; const flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty(); - const { traceData } = await TraceLoader.traceEngine(context, trace); - const threadAppenders = initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel); + const { parsedTrace } = await TraceLoader.traceEngine(context, trace); + const threadAppenders = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel); let level = 0; for (const appender of threadAppenders) { level = appender.appendTrackAtLevel(level); } return { entryTypeByLevel, - traceParsedData: traceData, + parsedTrace, flameChartData, threadAppenders, entryData, }; } -function renderThreadAppendersFromParsedData(traceParseData) { +function renderThreadAppendersFromParsedData(parsedTrace) { const entryTypeByLevel = []; const entryData = []; const flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty(); - const threadAppenders = initTrackAppender(flameChartData, traceParseData, entryData, entryTypeByLevel); + const threadAppenders = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel); let level = 0; for (const appender of threadAppenders) { level = appender.appendTrackAtLevel(level); @@ -137,8 +137,8 @@ describeWithEnvironment('ThreadAppender', function () { .includes('CrBrowserMain (1213787)')); }); it('assigns the right color for events when the trace is generic', async () => { - const { threadAppenders, traceParsedData } = await renderThreadAppendersFromTrace(this, 'generic-about-tracing.json.gz'); - const event = traceParsedData.Renderer.allTraceEntries.find(entry => { + const { threadAppenders, parsedTrace } = await renderThreadAppendersFromTrace(this, 'generic-about-tracing.json.gz'); + const event = parsedTrace.Renderer.allTraceEntries.find(entry => { return entry.name === 'ThreadControllerImpl::RunTask'; }); if (!event) { @@ -159,8 +159,8 @@ describeWithEnvironment('ThreadAppender', function () { assert.deepStrictEqual(flameChartData.groups.map(g => g.name), expectedTrackNames); }); it('returns the correct title for a renderer event', async function () { - const { threadAppenders, traceParsedData } = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz'); - const events = traceParsedData.Renderer?.allTraceEntries; + const { threadAppenders, parsedTrace } = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz'); + const events = parsedTrace.Renderer?.allTraceEntries; if (!events) { throw new Error('Could not find renderer events'); } @@ -168,13 +168,13 @@ describeWithEnvironment('ThreadAppender', function () { assert.strictEqual(title, 'Task'); }); it('adds the type for EventDispatch events to the title', async function () { - const { threadAppenders, traceParsedData } = await renderThreadAppendersFromTrace(this, 'one-second-interaction.json.gz'); - const events = traceParsedData.Renderer?.allTraceEntries; + const { threadAppenders, parsedTrace } = await renderThreadAppendersFromTrace(this, 'one-second-interaction.json.gz'); + const events = parsedTrace.Renderer?.allTraceEntries; if (!events) { throw new Error('Could not find renderer events'); } const clickEvent = events.find(event => { - return TraceModel.Types.TraceEvents.isTraceEventDispatch(event) && event.args.data.type === 'click'; + return Trace.Types.Events.isDispatch(event) && event.args.data.type === 'click'; }); if (!clickEvent) { throw new Error('Could not find expected click event'); @@ -183,14 +183,14 @@ describeWithEnvironment('ThreadAppender', function () { assert.strictEqual(title, 'Event: click'); }); it('returns the correct title for a profile call', async function () { - const { threadAppenders, traceParsedData } = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz'); - const rendererHandler = traceParsedData.Renderer; + const { threadAppenders, parsedTrace } = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz'); + const rendererHandler = parsedTrace.Renderer; if (!rendererHandler) { throw new Error('RendererHandler is undefined'); } const [process] = rendererHandler.processes.values(); const [thread] = process.threads.values(); - const profileCalls = thread.entries.filter(entry => TraceModel.Types.TraceEvents.isProfileCall(entry)); + const profileCalls = thread.entries.filter(entry => Trace.Types.Events.isProfileCall(entry)); if (!profileCalls) { throw new Error('Could not find renderer events'); } @@ -200,11 +200,11 @@ describeWithEnvironment('ThreadAppender', function () { assert.strictEqual(n, 'n'); }); it('will use the function name from the CPUProfile if it has been set', async function () { - const { threadAppenders, traceParsedData } = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz'); - const { Renderer, Samples } = traceParsedData; + const { threadAppenders, parsedTrace } = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz'); + const { Renderer, Samples } = parsedTrace; const [process] = Renderer.processes.values(); const [thread] = process.threads.values(); - const profileCalls = thread.entries.filter(TraceModel.Types.TraceEvents.isProfileCall); + const profileCalls = thread.entries.filter(Trace.Types.Events.isProfileCall); if (!profileCalls || profileCalls.length === 0) { throw new Error('Could not find renderer events'); } @@ -222,8 +222,8 @@ describeWithEnvironment('ThreadAppender', function () { cpuProfileNode.setFunctionName(originalName); }); it('shows the correct title for a trace event when hovered', async function () { - const { threadAppenders, traceParsedData } = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz'); - const events = traceParsedData.Renderer?.allTraceEntries; + const { threadAppenders, parsedTrace } = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz'); + const events = parsedTrace.Renderer?.allTraceEntries; if (!events) { throw new Error('Could not find renderer events'); } @@ -232,8 +232,8 @@ describeWithEnvironment('ThreadAppender', function () { assert.strictEqual(info.formattedTime, '0.27\u00A0ms'); }); it('shows self time only for events with self time above the threshold when hovered', async function () { - const { threadAppenders, traceParsedData } = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz'); - const events = traceParsedData.Renderer?.allTraceEntries; + const { threadAppenders, parsedTrace } = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz'); + const events = parsedTrace.Renderer?.allTraceEntries; if (!events) { throw new Error('Could not find renderer events'); } @@ -247,8 +247,8 @@ describeWithEnvironment('ThreadAppender', function () { assert.strictEqual(infoForLongEvent.formattedTime, '1.30\u00A0s (self 47\u00A0μs)'); }); it('shows the correct title for a ParseHTML event', async function () { - const { threadAppenders, traceParsedData } = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz'); - const events = traceParsedData.Renderer?.allTraceEntries; + const { threadAppenders, parsedTrace } = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz'); + const events = parsedTrace.Renderer?.allTraceEntries; if (!events) { throw new Error('Could not find renderer events'); } @@ -262,14 +262,14 @@ describeWithEnvironment('ThreadAppender', function () { assert.strictEqual(infoForLongEvent.formattedTime, '1.30\u00A0s (self 47\u00A0μs)'); }); it('shows the correct title for a profile call when hovered', async function () { - const { threadAppenders, traceParsedData } = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz'); - const rendererHandler = traceParsedData.Renderer; + const { threadAppenders, parsedTrace } = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz'); + const rendererHandler = parsedTrace.Renderer; if (!rendererHandler) { throw new Error('RendererHandler is undefined'); } const [process] = rendererHandler.processes.values(); const [thread] = process.threads.values(); - const profileCalls = thread.entries.filter(entry => TraceModel.Types.TraceEvents.isProfileCall(entry)); + const profileCalls = thread.entries.filter(entry => Trace.Types.Events.isProfileCall(entry)); if (!profileCalls) { throw new Error('Could not find renderer events'); } @@ -278,8 +278,8 @@ describeWithEnvironment('ThreadAppender', function () { assert.strictEqual(info.formattedTime, '15\u00A0μs'); }); it('candy-stripes long tasks', async function () { - const { traceParsedData, flameChartData, entryData } = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz'); - const events = traceParsedData.Renderer?.allTraceEntries; + const { parsedTrace, flameChartData, entryData } = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz'); + const events = parsedTrace.Renderer?.allTraceEntries; if (!events) { throw new Error('Could not find renderer events'); } @@ -293,13 +293,13 @@ describeWithEnvironment('ThreadAppender', function () { { type: "WARNING_TRIANGLE" /* PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE */ }, { type: "CANDY" /* PerfUI.FlameChart.FlameChartDecorationType.CANDY */, - startAtTime: TraceModel.Types.Timing.MicroSeconds(50_000), + startAtTime: Trace.Types.Timing.MicroSeconds(50_000), }, ]); }); it('does not candy-stripe tasks below the long task threshold', async function () { - const { traceParsedData, flameChartData, entryData } = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz'); - const events = traceParsedData.Renderer?.allTraceEntries; + const { parsedTrace, flameChartData, entryData } = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz'); + const events = parsedTrace.Renderer?.allTraceEntries; if (!events) { throw new Error('Could not find renderer events'); } @@ -399,7 +399,7 @@ describeWithEnvironment('ThreadAppender', function () { perEvent: new Map(), }; // This only includes data used in the thread appender - const mockTraceParseData = { + const mockParsedTrace = { Renderer: rendererData, Workers: workersData, Warnings: warningsData, @@ -410,13 +410,13 @@ describeWithEnvironment('ThreadAppender', function () { }; // Add the script to ignore list and then append the flamechart data ignoreListManager.ignoreListURL(SCRIPT_TO_IGNORE); - const { entryData, flameChartData, threadAppenders } = renderThreadAppendersFromParsedData(mockTraceParseData); + const { entryData, flameChartData, threadAppenders } = renderThreadAppendersFromParsedData(mockParsedTrace); const entryDataNames = entryData.map(entry => { const regularEvent = Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider.timelineEntryIsTraceEvent(entry); if (!regularEvent) { return 'Unknown type'; } - if (TraceModel.Types.TraceEvents.isProfileCall(entry)) { + if (Trace.Types.Events.isProfileCall(entry)) { return entry.callFrame.functionName; } return entry.name; diff --git a/public/panels/timeline/track_appenders/ThreadAppender.test.js.map b/public/panels/timeline/track_appenders/ThreadAppender.test.js.map index 7cde1002a..1d504eb5b 100644 --- a/public/panels/timeline/track_appenders/ThreadAppender.test.js.map +++ b/public/panels/timeline/track_appenders/ThreadAppender.test.js.map @@ -1 +1 @@ -{"version":3,"file":"ThreadAppender.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/track_appenders/ThreadAppender.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Platform from '../../../core/platform/platform.js';\nimport * as Root from '../../../core/root/root.js';\nimport * as SDK from '../../../core/sdk/sdk.js';\nimport * as Bindings from '../../../models/bindings/bindings.js';\nimport * as TraceModel from '../../../models/trace/trace.js';\nimport * as Workspace from '../../../models/workspace/workspace.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {\n makeMockRendererHandlerData as makeRendererHandlerData,\n makeProfileCall,\n setupIgnoreListManagerEnvironment,\n} from '../../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as Timeline from '../timeline.js';\n\nfunction initTrackAppender(\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData,\n traceParsedData: TraceModel.Handlers.Types.TraceParseData,\n entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[],\n entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[],\n ): Timeline.ThreadAppender.ThreadAppender[] {\n setupIgnoreListManagerEnvironment();\n const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(\n flameChartData, traceParsedData, entryData, entryTypeByLevel);\n return compatibilityTracksAppender.threadAppenders();\n}\nasync function renderThreadAppendersFromTrace(context: Mocha.Context|Mocha.Suite, trace: string): Promise<{\n entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[],\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData,\n threadAppenders: Timeline.ThreadAppender.ThreadAppender[],\n entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[],\n traceParsedData: Readonly,\n}> {\n const entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[] = [];\n const entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[] = [];\n const flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n const {traceData} = await TraceLoader.traceEngine(context, trace);\n const threadAppenders = initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel);\n let level = 0;\n for (const appender of threadAppenders) {\n level = appender.appendTrackAtLevel(level);\n }\n return {\n entryTypeByLevel,\n traceParsedData: traceData,\n flameChartData,\n threadAppenders,\n entryData,\n };\n}\n\nfunction renderThreadAppendersFromParsedData(traceParseData: TraceModel.Handlers.Types.TraceParseData): {\n entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[],\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData,\n threadAppenders: Timeline.ThreadAppender.ThreadAppender[],\n entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[],\n} {\n const entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[] = [];\n const entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[] = [];\n const flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n\n const threadAppenders = initTrackAppender(flameChartData, traceParseData, entryData, entryTypeByLevel);\n let level = 0;\n for (const appender of threadAppenders) {\n level = appender.appendTrackAtLevel(level);\n }\n\n return {\n entryTypeByLevel,\n flameChartData,\n threadAppenders,\n entryData,\n };\n}\n\ndescribeWithEnvironment('ThreadAppender', function() {\n it('creates a thread appender for each thread in a trace', async function() {\n const {threadAppenders} = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz');\n const expectedAppenderNames = [\n 'Thread',\n 'Thread',\n 'Thread',\n ];\n assert.deepStrictEqual(threadAppenders.map(g => g.appenderName), expectedAppenderNames);\n });\n\n it('renders tracks for threads in correct order', async function() {\n const {flameChartData} = await renderThreadAppendersFromTrace(this, 'multiple-navigations-with-iframes.json.gz');\n assert.strictEqual(flameChartData.groups[0].name, 'Main — http://localhost:5000/');\n assert.strictEqual(flameChartData.groups[1].name, 'Frame — https://www.example.com/');\n });\n\n it('renders tracks for threads in correct order when a process url is about:blank', async function() {\n const {flameChartData} = await renderThreadAppendersFromTrace(this, 'about-blank-first.json.gz');\n const groupNames = flameChartData.groups.map(g => g.name.replace(/(new-tab-page\\/).*/, '$1'));\n assert.deepStrictEqual(groupNames.slice(0, 3), [\n 'Frame — chrome-untrusted://new-tab-page/',\n 'Main — chrome://new-tab-page/',\n 'Main — about:blank',\n ]);\n });\n\n it('marks all levels used by the track with the TrackAppender type', async function() {\n const {entryTypeByLevel} = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz');\n // This includes all tracks rendered by the ThreadAppender.\n const execptedLevelTypes = [\n Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER,\n Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER,\n Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER,\n Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER,\n Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER,\n Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER,\n Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER,\n Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER,\n Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER,\n Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER,\n ];\n assert.deepStrictEqual(entryTypeByLevel, execptedLevelTypes);\n });\n\n it('creates a flamechart groups for track headers and titles', async function() {\n const {flameChartData} = await renderThreadAppendersFromTrace(this, 'cls-single-frame.json.gz');\n const expectedTrackNames = [\n 'Main — https://output.jsbin.com/zajamil/quiet',\n 'Raster',\n 'Rasterizer thread 1',\n 'Rasterizer thread 2',\n 'Thread pool',\n 'Thread pool worker 1',\n ];\n assert.deepStrictEqual(flameChartData.groups.map(g => g.name), expectedTrackNames);\n });\n\n it('builds flamechart groups for nested tracks correctly', async function() {\n const {flameChartData} = await renderThreadAppendersFromTrace(this, 'cls-single-frame.json.gz');\n // This group corresponds to the header that wraps the raster tracks\n // together. It isn't selectable and isn't nested\n assert.strictEqual(flameChartData.groups[1].name, 'Raster');\n assert.strictEqual(flameChartData.groups[1].selectable, false);\n assert.strictEqual(flameChartData.groups[1].style.nestingLevel, 0);\n\n // These groups correspond to the raster tracks titles, or the\n // individual raster tracks themselves. They are selectable and\n // nested\n assert.strictEqual(flameChartData.groups[2].name, 'Rasterizer thread 1');\n assert.strictEqual(flameChartData.groups[2].selectable, true);\n assert.strictEqual(flameChartData.groups[2].style.nestingLevel, 1);\n\n assert.strictEqual(flameChartData.groups[3].name, 'Rasterizer thread 2');\n assert.strictEqual(flameChartData.groups[3].selectable, true);\n assert.strictEqual(flameChartData.groups[3].style.nestingLevel, 1);\n });\n\n it('assigns correct names to multiple types of threads', async function() {\n const {flameChartData} = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz');\n const expectedTrackNames = [\n 'Main — https://www.google.com',\n 'Thread pool',\n 'Thread pool worker 1',\n 'Thread pool worker 2',\n ];\n assert.deepStrictEqual(flameChartData.groups.map(g => g.name), expectedTrackNames);\n });\n\n it('adds thread IDs onto tracks when the trace is generic', async () => {\n const {flameChartData} = await renderThreadAppendersFromTrace(this, 'generic-about-tracing.json.gz');\n // This trace has a lot of tracks, so just test one.\n assert.isTrue(flameChartData.groups.map(g => g.name)\n .includes('CrBrowserMain (1213787)' as Platform.UIString.LocalizedString));\n });\n\n it('assigns the right color for events when the trace is generic', async () => {\n const {threadAppenders, traceParsedData} =\n await renderThreadAppendersFromTrace(this, 'generic-about-tracing.json.gz');\n const event = traceParsedData.Renderer.allTraceEntries.find(entry => {\n return entry.name === 'ThreadControllerImpl::RunTask';\n });\n if (!event) {\n throw new Error('Could not find event.');\n }\n assert.strictEqual(threadAppenders[0].colorForEvent(event), 'hsl(278, 40%, 70%)');\n });\n\n it('assigns correct names to worker threads', async function() {\n const {flameChartData} = await renderThreadAppendersFromTrace(this, 'two-workers.json.gz');\n const expectedTrackNames = [\n 'Main — https://chromedevtools.github.io/performance-stories/two-workers/index.html',\n 'Worker — https://chromedevtools.github.io/performance-stories/two-workers/fib-worker.js',\n 'Worker — https://chromedevtools.github.io/performance-stories/two-workers/fib-worker.js',\n 'Thread pool',\n 'Thread pool worker 1',\n 'Thread pool worker 2',\n ];\n assert.deepStrictEqual(flameChartData.groups.map(g => g.name), expectedTrackNames);\n });\n\n it('returns the correct title for a renderer event', async function() {\n const {threadAppenders, traceParsedData} = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz');\n const events = traceParsedData.Renderer?.allTraceEntries;\n if (!events) {\n throw new Error('Could not find renderer events');\n }\n const title = threadAppenders[0].titleForEvent(events[0]);\n assert.strictEqual(title, 'Task');\n });\n\n it('adds the type for EventDispatch events to the title', async function() {\n const {threadAppenders, traceParsedData} =\n await renderThreadAppendersFromTrace(this, 'one-second-interaction.json.gz');\n const events = traceParsedData.Renderer?.allTraceEntries;\n if (!events) {\n throw new Error('Could not find renderer events');\n }\n const clickEvent = events.find(event => {\n return TraceModel.Types.TraceEvents.isTraceEventDispatch(event) && event.args.data.type === 'click';\n });\n if (!clickEvent) {\n throw new Error('Could not find expected click event');\n }\n const title = threadAppenders[0].titleForEvent(clickEvent);\n assert.strictEqual(title, 'Event: click');\n });\n\n it('returns the correct title for a profile call', async function() {\n const {threadAppenders, traceParsedData} = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz');\n const rendererHandler = traceParsedData.Renderer;\n if (!rendererHandler) {\n throw new Error('RendererHandler is undefined');\n }\n const [process] = rendererHandler.processes.values();\n const [thread] = process.threads.values();\n const profileCalls = thread.entries.filter(entry => TraceModel.Types.TraceEvents.isProfileCall(entry));\n\n if (!profileCalls) {\n throw new Error('Could not find renderer events');\n }\n const anonymousCall = threadAppenders[0].titleForEvent(profileCalls[0]);\n assert.strictEqual(anonymousCall, '(anonymous)');\n const n = threadAppenders[0].titleForEvent(profileCalls[7]);\n assert.strictEqual(n, 'n');\n });\n\n it('will use the function name from the CPUProfile if it has been set', async function() {\n const {threadAppenders, traceParsedData} = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz');\n const {Renderer, Samples} = traceParsedData;\n const [process] = Renderer.processes.values();\n const [thread] = process.threads.values();\n const profileCalls = thread.entries.filter(TraceModel.Types.TraceEvents.isProfileCall);\n\n if (!profileCalls || profileCalls.length === 0) {\n throw new Error('Could not find renderer events');\n }\n const entry = profileCalls[0];\n const cpuProfileNode =\n Samples.profilesInProcess.get(entry.pid)?.get(entry.tid)?.parsedProfile.nodeById(entry.nodeId);\n if (!cpuProfileNode) {\n throw new Error('Could not find CPU Profile Node');\n }\n const anonymousCall = threadAppenders[0].titleForEvent(entry);\n assert.strictEqual(anonymousCall, '(anonymous)');\n const originalName = cpuProfileNode.functionName;\n cpuProfileNode.setFunctionName('new-resolved-function-name');\n assert.strictEqual(threadAppenders[0].titleForEvent(entry), 'new-resolved-function-name');\n // Reset the value for future tests.\n cpuProfileNode.setFunctionName(originalName);\n });\n\n it('shows the correct title for a trace event when hovered', async function() {\n const {threadAppenders, traceParsedData} = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz');\n const events = traceParsedData.Renderer?.allTraceEntries;\n if (!events) {\n throw new Error('Could not find renderer events');\n }\n const info = threadAppenders[0].highlightedEntryInfo(events[0]);\n assert.strictEqual(info.title, 'Task');\n assert.strictEqual(info.formattedTime, '0.27\\u00A0ms');\n });\n\n it('shows self time only for events with self time above the threshold when hovered', async function() {\n const {threadAppenders, traceParsedData} = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz');\n const events = traceParsedData.Renderer?.allTraceEntries;\n if (!events) {\n throw new Error('Could not find renderer events');\n }\n const infoForShortEvent = threadAppenders[0].highlightedEntryInfo(events[0]);\n assert.strictEqual(infoForShortEvent.formattedTime, '0.27\\u00A0ms');\n\n const longTask = events.find(e => (e.dur || 0) > 1_000_000);\n if (!longTask) {\n throw new Error('Could not find long task');\n }\n const infoForLongEvent = threadAppenders[0].highlightedEntryInfo(longTask);\n assert.strictEqual(infoForLongEvent.formattedTime, '1.30\\u00A0s (self 47\\u00A0μs)');\n });\n\n it('shows the correct title for a ParseHTML event', async function() {\n const {threadAppenders, traceParsedData} = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz');\n const events = traceParsedData.Renderer?.allTraceEntries;\n if (!events) {\n throw new Error('Could not find renderer events');\n }\n const infoForShortEvent = threadAppenders[0].highlightedEntryInfo(events[0]);\n assert.strictEqual(infoForShortEvent.formattedTime, '0.27\\u00A0ms');\n\n const longTask = events.find(e => (e.dur || 0) > 1_000_000);\n if (!longTask) {\n throw new Error('Could not find long task');\n }\n const infoForLongEvent = threadAppenders[0].highlightedEntryInfo(longTask);\n assert.strictEqual(infoForLongEvent.formattedTime, '1.30\\u00A0s (self 47\\u00A0μs)');\n });\n\n it('shows the correct title for a profile call when hovered', async function() {\n const {threadAppenders, traceParsedData} = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz');\n const rendererHandler = traceParsedData.Renderer;\n if (!rendererHandler) {\n throw new Error('RendererHandler is undefined');\n }\n const [process] = rendererHandler.processes.values();\n const [thread] = process.threads.values();\n const profileCalls = thread.entries.filter(entry => TraceModel.Types.TraceEvents.isProfileCall(entry));\n\n if (!profileCalls) {\n throw new Error('Could not find renderer events');\n }\n\n const info = threadAppenders[0].highlightedEntryInfo(profileCalls[0]);\n assert.strictEqual(info.title, '(anonymous)');\n assert.strictEqual(info.formattedTime, '15\\u00A0μs');\n });\n it('candy-stripes long tasks', async function() {\n const {traceParsedData, flameChartData, entryData} =\n await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz');\n const events = traceParsedData.Renderer?.allTraceEntries;\n if (!events) {\n throw new Error('Could not find renderer events');\n }\n const longTask = events.find(e => (e.dur || 0) > 1_000_000);\n if (!longTask) {\n throw new Error('Could not find long task');\n }\n const entryIndex = entryData.indexOf(longTask);\n const decorationsForEntry = flameChartData.entryDecorations[entryIndex];\n assert.deepEqual(decorationsForEntry, [\n {type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE},\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,\n startAtTime: TraceModel.Types.Timing.MicroSeconds(50_000),\n },\n ]);\n });\n\n it('does not candy-stripe tasks below the long task threshold', async function() {\n const {traceParsedData, flameChartData, entryData} =\n await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz');\n const events = traceParsedData.Renderer?.allTraceEntries;\n if (!events) {\n throw new Error('Could not find renderer events');\n }\n const entryIndex = entryData.indexOf(events[0]);\n const decorationsForEntry = flameChartData.entryDecorations[entryIndex];\n assert.isUndefined(decorationsForEntry);\n });\n\n it('does not append a track if there are no visible events on it', async function() {\n const {flameChartData} = await renderThreadAppendersFromTrace(this, 'one-second-interaction.json.gz');\n const expectedTrackNames = [\n 'Main — https://chromedevtools.github.io/performance-stories/long-interaction/index.html?x=40',\n 'Thread pool',\n // There are multiple ThreadPoolForegroundWorker threads present in\n // the trace, but only one of these has trace events we deem as\n // \"visible\".\n 'Thread pool worker 1',\n // This second \"worker\" is the ThreadPoolServiceThread. TODO: perhaps hide ThreadPoolServiceThread completely?\n 'Thread pool worker 2',\n ];\n assert.deepStrictEqual(flameChartData.groups.map(g => g.name), expectedTrackNames);\n });\n\n describe('ignore listing', () => {\n let ignoreListManager: Bindings.IgnoreListManager.IgnoreListManager;\n beforeEach(() => {\n const targetManager = SDK.TargetManager.TargetManager.instance({forceNew: true});\n const workspace = Workspace.Workspace.WorkspaceImpl.instance({forceNew: true});\n const resourceMapping = new Bindings.ResourceMapping.ResourceMapping(targetManager, workspace);\n const debuggerWorkspaceBinding = Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance({\n forceNew: true,\n resourceMapping,\n targetManager,\n });\n ignoreListManager = Bindings.IgnoreListManager.IgnoreListManager.instance({\n forceNew: true,\n debuggerWorkspaceBinding,\n });\n });\n afterEach(() => {\n SDK.TargetManager.TargetManager.removeInstance();\n Workspace.Workspace.WorkspaceImpl.removeInstance();\n Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.removeInstance();\n Bindings.IgnoreListManager.IgnoreListManager.removeInstance();\n });\n it('removes entries from the data that match the ignored URL', async function() {\n const initialTimelineData = await renderThreadAppendersFromTrace(this, 'react-hello-world.json.gz');\n const initialFlamechartData = initialTimelineData.flameChartData;\n const eventCountBeforeIgnoreList = initialFlamechartData.entryStartTimes.length;\n const SCRIPT_TO_IGNORE =\n 'https://unpkg.com/react@18.2.0/umd/react.development.js' as Platform.DevToolsPath.UrlString;\n // Clear the data provider cache and add the React script to the ignore list.\n ignoreListManager.ignoreListURL(SCRIPT_TO_IGNORE);\n const finalTimelineData = await renderThreadAppendersFromTrace(this, 'react-hello-world.json.gz');\n const finalFlamechartData = finalTimelineData.flameChartData;\n const eventCountAfterIgnoreList = finalFlamechartData.entryStartTimes.length;\n // Ensure that the amount of events we show on the flame chart is less\n // than before, now we have added the React URL to the ignore list.\n assert.isBelow(eventCountAfterIgnoreList, eventCountBeforeIgnoreList);\n\n // // Clear the data provider cache and unignore the script again\n ignoreListManager.unIgnoreListURL(SCRIPT_TO_IGNORE);\n const finalTimelineData2 = await renderThreadAppendersFromTrace(this, 'react-hello-world.json.gz');\n const finalFlamechartData2 = finalTimelineData2.flameChartData;\n const eventCountAfterIgnoreList2 = finalFlamechartData2.entryStartTimes.length;\n // // Ensure that now we have un-ignored the URL that we get the full set of events again.\n assert.strictEqual(eventCountAfterIgnoreList2, eventCountBeforeIgnoreList);\n });\n\n it('appends a tree that contains ignore listed entries correctly', async function() {\n const SCRIPT_TO_IGNORE = 'https://some-framework/bundled.js' as Platform.DevToolsPath.UrlString;\n\n // Create the following hierarchy with profile calls. Events marked\n // with \\\\\\\\ represent ignored listed events.\n // |----------A-----------|\n // |\\\\\\\\\\B\\\\\\\\\\||----F----|\n // |\\\\C\\\\||\\D\\|\n // |--E--|\n //\n // Applying ignore listing in the appender, should yield the\n // following flame chart:\n // |----------A-----------|\n // |\\\\\\\\\\B\\\\\\\\||----F----|\n // |--E--|\n const callFrameA = makeProfileCall('A', 100, 200);\n const callFrameB = makeProfileCall('IgnoreListedB', 100, 100);\n callFrameB.callFrame.url = SCRIPT_TO_IGNORE;\n const callFrameC = makeProfileCall('IgnoreListedC', 100, 50);\n callFrameC.callFrame.url = SCRIPT_TO_IGNORE;\n const callFrameD = makeProfileCall('IgnoreListedD', 151, 49);\n callFrameD.callFrame.url = SCRIPT_TO_IGNORE;\n const callFrameE = makeProfileCall('E', 100, 25);\n const callFrameF = makeProfileCall('F', 200, 100);\n\n const allEntries = [callFrameA, callFrameB, callFrameC, callFrameE, callFrameD, callFrameF];\n const rendererData = makeRendererHandlerData(allEntries);\n const workersData: TraceModel.Handlers.ModelHandlers.Workers.WorkersData = {\n workerSessionIdEvents: [],\n workerIdByThread: new Map(),\n workerURLById: new Map(),\n };\n const warningsData: TraceModel.Handlers.ModelHandlers.Warnings.WarningsData = {\n perWarning: new Map(),\n perEvent: new Map(),\n };\n // This only includes data used in the thread appender\n const mockTraceParseData = {\n Renderer: rendererData,\n Workers: workersData,\n Warnings: warningsData,\n AuctionWorklets: {worklets: new Map()},\n Meta: {\n traceIsGeneric: false,\n },\n } as TraceModel.Handlers.Types.TraceParseData;\n\n // Add the script to ignore list and then append the flamechart data\n ignoreListManager.ignoreListURL(SCRIPT_TO_IGNORE);\n const {entryData, flameChartData, threadAppenders} = renderThreadAppendersFromParsedData(mockTraceParseData);\n const entryDataNames = entryData.map(entry => {\n const regularEvent =\n Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider.timelineEntryIsTraceEvent(entry);\n if (!regularEvent) {\n return 'Unknown type';\n }\n if (TraceModel.Types.TraceEvents.isProfileCall(entry)) {\n return entry.callFrame.functionName;\n }\n return entry.name;\n });\n\n assert.deepEqual(entryDataNames, ['A', 'IgnoreListedB', 'E', 'F']);\n assert.deepEqual(flameChartData.entryLevels, [0, 1, 2, 1]);\n assert.deepEqual(flameChartData.entryStartTimes, [0.1, 0.1, 0.1, 0.2]);\n assert.deepEqual(flameChartData.entryTotalTimes, [0.2, 0.1, 0.025, 0.1]);\n assert.strictEqual(threadAppenders.length, 1);\n assert.strictEqual(threadAppenders[0].titleForEvent(callFrameB), 'On ignore list');\n });\n });\n describe('showAllEvents', () => {\n beforeEach(() => {\n const targetManager = SDK.TargetManager.TargetManager.instance({forceNew: true});\n const workspace = Workspace.Workspace.WorkspaceImpl.instance({forceNew: true});\n const resourceMapping = new Bindings.ResourceMapping.ResourceMapping(targetManager, workspace);\n const debuggerWorkspaceBinding = Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance({\n forceNew: true,\n resourceMapping,\n targetManager,\n });\n Bindings.IgnoreListManager.IgnoreListManager.instance({\n forceNew: true,\n debuggerWorkspaceBinding,\n });\n });\n afterEach(() => {\n SDK.TargetManager.TargetManager.removeInstance();\n Workspace.Workspace.WorkspaceImpl.removeInstance();\n Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.removeInstance();\n Bindings.IgnoreListManager.IgnoreListManager.removeInstance();\n });\n it('appends unknown events to the flame chart data only when the experiment is enabled', async function() {\n const fileName = 'react-hello-world.json.gz';\n const bizarreName = 'BackForwardCacheBufferLimitTracker::DidRemoveFrameOrWorkerFromBackForwardCache';\n // Look up a trace event with an name we are not tracking anywhere and make sure it's not\n // appended to the timeline data.\n const initialTimelineData = await renderThreadAppendersFromTrace(this, fileName);\n let unknownEventIndex = initialTimelineData.entryData.findIndex(entry => {\n const event = entry as TraceModel.Types.TraceEvents.TraceEventData;\n return event.name === bizarreName;\n });\n assert.strictEqual(unknownEventIndex, -1);\n\n // Now enable the experiment and make sure the event is appended to the timeline data this time\n Root.Runtime.experiments.enableForTest('timeline-show-all-events');\n const finalTimelineData = await renderThreadAppendersFromTrace(this, fileName);\n const finalFlamechartData = finalTimelineData.flameChartData;\n unknownEventIndex = finalTimelineData.entryData.findIndex(entry => {\n const event = entry as TraceModel.Types.TraceEvents.TraceEventData;\n return event.name === bizarreName;\n });\n assert.isAbove(unknownEventIndex, -1);\n assert.exists(finalFlamechartData.entryStartTimes);\n assert.exists(finalFlamechartData.entryTotalTimes);\n Root.Runtime.experiments.disableForTest('timeline-show-all-events');\n });\n });\n describe('AuctionWorklet threads', () => {\n // We have to set these up because the ThreadAppender includes logic for\n // ignoring events that relies on the IgnoreListManager.\n beforeEach(() => {\n const targetManager = SDK.TargetManager.TargetManager.instance({forceNew: true});\n const workspace = Workspace.Workspace.WorkspaceImpl.instance({forceNew: true});\n const resourceMapping = new Bindings.ResourceMapping.ResourceMapping(targetManager, workspace);\n const debuggerWorkspaceBinding = Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance({\n forceNew: true,\n resourceMapping,\n targetManager,\n });\n Bindings.IgnoreListManager.IgnoreListManager.instance({\n forceNew: true,\n debuggerWorkspaceBinding,\n });\n });\n\n afterEach(() => {\n SDK.TargetManager.TargetManager.removeInstance();\n Workspace.Workspace.WorkspaceImpl.removeInstance();\n Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.removeInstance();\n Bindings.IgnoreListManager.IgnoreListManager.removeInstance();\n });\n\n it('finds all the worklet threads', async function() {\n const {threadAppenders} = await renderThreadAppendersFromTrace(this, 'fenced-frame-fledge.json.gz');\n const workletAppenders = threadAppenders.filter(threadAppender => {\n return threadAppender.trackName().includes('Worklet');\n });\n assert.lengthOf(workletAppenders, 6);\n });\n\n it('sets the title correctly for an Auction Worklet service', async function() {\n const UTILITY_THREAD_PID = 776435 as TraceModel.Types.TraceEvents.ProcessID;\n const UTILITY_THREAD_TID = 1 as TraceModel.Types.TraceEvents.ThreadID;\n const {threadAppenders} = await renderThreadAppendersFromTrace(this, 'fenced-frame-fledge.json.gz');\n const appender = threadAppenders.find(threadAppender => {\n return threadAppender.processId() === UTILITY_THREAD_PID && threadAppender.threadId() === UTILITY_THREAD_TID;\n });\n if (!appender) {\n throw new Error('Could not find expected thread appender');\n }\n assert.strictEqual(appender.trackName(), 'Auction Worklet service — https://ssp-fledge-demo.glitch.me');\n });\n\n it('sets the title correctly for an Auction Worklet seller service', async function() {\n const SELLER_THREAD_PID = 776435 as TraceModel.Types.TraceEvents.ProcessID;\n const SELLER_THREAD_TID = 6 as TraceModel.Types.TraceEvents.ThreadID;\n const {threadAppenders} = await renderThreadAppendersFromTrace(this, 'fenced-frame-fledge.json.gz');\n const appender = threadAppenders.find(threadAppender => {\n return threadAppender.processId() === SELLER_THREAD_PID && threadAppender.threadId() === SELLER_THREAD_TID;\n });\n if (!appender) {\n throw new Error('Could not find expected thread appender');\n }\n assert.strictEqual(appender.trackName(), 'Seller Worklet — https://ssp-fledge-demo.glitch.me');\n });\n\n it('sets the title correctly for an Auction Worklet bidder service', async function() {\n const BIDDER_THREAD_PID = 776436 as TraceModel.Types.TraceEvents.ProcessID;\n const BIDDER_THREAD_TID = 6 as TraceModel.Types.TraceEvents.ThreadID;\n const {threadAppenders} = await renderThreadAppendersFromTrace(this, 'fenced-frame-fledge.json.gz');\n const appender = threadAppenders.find(threadAppender => {\n return threadAppender.processId() === BIDDER_THREAD_PID && threadAppender.threadId() === BIDDER_THREAD_TID;\n });\n if (!appender) {\n throw new Error('Could not find expected thread appender');\n }\n assert.strictEqual(appender.trackName(), 'Bidder Worklet — https://dsp-fledge-demo.glitch.me');\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"ThreadAppender.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/track_appenders/ThreadAppender.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Platform from '../../../core/platform/platform.js';\nimport * as Root from '../../../core/root/root.js';\nimport * as SDK from '../../../core/sdk/sdk.js';\nimport * as Bindings from '../../../models/bindings/bindings.js';\nimport * as Trace from '../../../models/trace/trace.js';\nimport * as Workspace from '../../../models/workspace/workspace.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {\n makeMockRendererHandlerData as makeRendererHandlerData,\n makeProfileCall,\n setupIgnoreListManagerEnvironment,\n} from '../../../testing/TraceHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as Timeline from '../timeline.js';\n\nfunction initTrackAppender(\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData,\n parsedTrace: Trace.Handlers.Types.ParsedTrace,\n entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[],\n entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[],\n ): Timeline.ThreadAppender.ThreadAppender[] {\n setupIgnoreListManagerEnvironment();\n const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(\n flameChartData, parsedTrace, entryData, entryTypeByLevel);\n return compatibilityTracksAppender.threadAppenders();\n}\nasync function renderThreadAppendersFromTrace(context: Mocha.Context|Mocha.Suite, trace: string): Promise<{\n entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[],\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData,\n threadAppenders: Timeline.ThreadAppender.ThreadAppender[],\n entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[],\n parsedTrace: Readonly,\n}> {\n const entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[] = [];\n const entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[] = [];\n const flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n const {parsedTrace} = await TraceLoader.traceEngine(context, trace);\n const threadAppenders = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel);\n let level = 0;\n for (const appender of threadAppenders) {\n level = appender.appendTrackAtLevel(level);\n }\n return {\n entryTypeByLevel,\n parsedTrace,\n flameChartData,\n threadAppenders,\n entryData,\n };\n}\n\nfunction renderThreadAppendersFromParsedData(parsedTrace: Trace.Handlers.Types.ParsedTrace): {\n entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[],\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData,\n threadAppenders: Timeline.ThreadAppender.ThreadAppender[],\n entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[],\n} {\n const entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[] = [];\n const entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[] = [];\n const flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n\n const threadAppenders = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel);\n let level = 0;\n for (const appender of threadAppenders) {\n level = appender.appendTrackAtLevel(level);\n }\n\n return {\n entryTypeByLevel,\n flameChartData,\n threadAppenders,\n entryData,\n };\n}\n\ndescribeWithEnvironment('ThreadAppender', function() {\n it('creates a thread appender for each thread in a trace', async function() {\n const {threadAppenders} = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz');\n const expectedAppenderNames = [\n 'Thread',\n 'Thread',\n 'Thread',\n ];\n assert.deepStrictEqual(threadAppenders.map(g => g.appenderName), expectedAppenderNames);\n });\n\n it('renders tracks for threads in correct order', async function() {\n const {flameChartData} = await renderThreadAppendersFromTrace(this, 'multiple-navigations-with-iframes.json.gz');\n assert.strictEqual(flameChartData.groups[0].name, 'Main — http://localhost:5000/');\n assert.strictEqual(flameChartData.groups[1].name, 'Frame — https://www.example.com/');\n });\n\n it('renders tracks for threads in correct order when a process url is about:blank', async function() {\n const {flameChartData} = await renderThreadAppendersFromTrace(this, 'about-blank-first.json.gz');\n const groupNames = flameChartData.groups.map(g => g.name.replace(/(new-tab-page\\/).*/, '$1'));\n assert.deepStrictEqual(groupNames.slice(0, 3), [\n 'Frame — chrome-untrusted://new-tab-page/',\n 'Main — chrome://new-tab-page/',\n 'Main — about:blank',\n ]);\n });\n\n it('marks all levels used by the track with the TrackAppender type', async function() {\n const {entryTypeByLevel} = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz');\n // This includes all tracks rendered by the ThreadAppender.\n const execptedLevelTypes = [\n Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER,\n Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER,\n Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER,\n Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER,\n Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER,\n Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER,\n Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER,\n Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER,\n Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER,\n Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER,\n ];\n assert.deepStrictEqual(entryTypeByLevel, execptedLevelTypes);\n });\n\n it('creates a flamechart groups for track headers and titles', async function() {\n const {flameChartData} = await renderThreadAppendersFromTrace(this, 'cls-single-frame.json.gz');\n const expectedTrackNames = [\n 'Main — https://output.jsbin.com/zajamil/quiet',\n 'Raster',\n 'Rasterizer thread 1',\n 'Rasterizer thread 2',\n 'Thread pool',\n 'Thread pool worker 1',\n ];\n assert.deepStrictEqual(flameChartData.groups.map(g => g.name), expectedTrackNames);\n });\n\n it('builds flamechart groups for nested tracks correctly', async function() {\n const {flameChartData} = await renderThreadAppendersFromTrace(this, 'cls-single-frame.json.gz');\n // This group corresponds to the header that wraps the raster tracks\n // together. It isn't selectable and isn't nested\n assert.strictEqual(flameChartData.groups[1].name, 'Raster');\n assert.strictEqual(flameChartData.groups[1].selectable, false);\n assert.strictEqual(flameChartData.groups[1].style.nestingLevel, 0);\n\n // These groups correspond to the raster tracks titles, or the\n // individual raster tracks themselves. They are selectable and\n // nested\n assert.strictEqual(flameChartData.groups[2].name, 'Rasterizer thread 1');\n assert.strictEqual(flameChartData.groups[2].selectable, true);\n assert.strictEqual(flameChartData.groups[2].style.nestingLevel, 1);\n\n assert.strictEqual(flameChartData.groups[3].name, 'Rasterizer thread 2');\n assert.strictEqual(flameChartData.groups[3].selectable, true);\n assert.strictEqual(flameChartData.groups[3].style.nestingLevel, 1);\n });\n\n it('assigns correct names to multiple types of threads', async function() {\n const {flameChartData} = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz');\n const expectedTrackNames = [\n 'Main — https://www.google.com',\n 'Thread pool',\n 'Thread pool worker 1',\n 'Thread pool worker 2',\n ];\n assert.deepStrictEqual(flameChartData.groups.map(g => g.name), expectedTrackNames);\n });\n\n it('adds thread IDs onto tracks when the trace is generic', async () => {\n const {flameChartData} = await renderThreadAppendersFromTrace(this, 'generic-about-tracing.json.gz');\n // This trace has a lot of tracks, so just test one.\n assert.isTrue(flameChartData.groups.map(g => g.name)\n .includes('CrBrowserMain (1213787)' as Platform.UIString.LocalizedString));\n });\n\n it('assigns the right color for events when the trace is generic', async () => {\n const {threadAppenders, parsedTrace} = await renderThreadAppendersFromTrace(this, 'generic-about-tracing.json.gz');\n const event = parsedTrace.Renderer.allTraceEntries.find(entry => {\n return entry.name === 'ThreadControllerImpl::RunTask';\n });\n if (!event) {\n throw new Error('Could not find event.');\n }\n assert.strictEqual(threadAppenders[0].colorForEvent(event), 'hsl(278, 40%, 70%)');\n });\n\n it('assigns correct names to worker threads', async function() {\n const {flameChartData} = await renderThreadAppendersFromTrace(this, 'two-workers.json.gz');\n const expectedTrackNames = [\n 'Main — https://chromedevtools.github.io/performance-stories/two-workers/index.html',\n 'Worker — https://chromedevtools.github.io/performance-stories/two-workers/fib-worker.js',\n 'Worker — https://chromedevtools.github.io/performance-stories/two-workers/fib-worker.js',\n 'Thread pool',\n 'Thread pool worker 1',\n 'Thread pool worker 2',\n ];\n assert.deepStrictEqual(flameChartData.groups.map(g => g.name), expectedTrackNames);\n });\n\n it('returns the correct title for a renderer event', async function() {\n const {threadAppenders, parsedTrace} = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz');\n const events = parsedTrace.Renderer?.allTraceEntries;\n if (!events) {\n throw new Error('Could not find renderer events');\n }\n const title = threadAppenders[0].titleForEvent(events[0]);\n assert.strictEqual(title, 'Task');\n });\n\n it('adds the type for EventDispatch events to the title', async function() {\n const {threadAppenders, parsedTrace} = await renderThreadAppendersFromTrace(this, 'one-second-interaction.json.gz');\n const events = parsedTrace.Renderer?.allTraceEntries;\n if (!events) {\n throw new Error('Could not find renderer events');\n }\n const clickEvent = events.find(event => {\n return Trace.Types.Events.isDispatch(event) && event.args.data.type === 'click';\n });\n if (!clickEvent) {\n throw new Error('Could not find expected click event');\n }\n const title = threadAppenders[0].titleForEvent(clickEvent);\n assert.strictEqual(title, 'Event: click');\n });\n\n it('returns the correct title for a profile call', async function() {\n const {threadAppenders, parsedTrace} = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz');\n const rendererHandler = parsedTrace.Renderer;\n if (!rendererHandler) {\n throw new Error('RendererHandler is undefined');\n }\n const [process] = rendererHandler.processes.values();\n const [thread] = process.threads.values();\n const profileCalls = thread.entries.filter(entry => Trace.Types.Events.isProfileCall(entry));\n\n if (!profileCalls) {\n throw new Error('Could not find renderer events');\n }\n const anonymousCall = threadAppenders[0].titleForEvent(profileCalls[0]);\n assert.strictEqual(anonymousCall, '(anonymous)');\n const n = threadAppenders[0].titleForEvent(profileCalls[7]);\n assert.strictEqual(n, 'n');\n });\n\n it('will use the function name from the CPUProfile if it has been set', async function() {\n const {threadAppenders, parsedTrace} = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz');\n const {Renderer, Samples} = parsedTrace;\n const [process] = Renderer.processes.values();\n const [thread] = process.threads.values();\n const profileCalls = thread.entries.filter(Trace.Types.Events.isProfileCall);\n\n if (!profileCalls || profileCalls.length === 0) {\n throw new Error('Could not find renderer events');\n }\n const entry = profileCalls[0];\n const cpuProfileNode =\n Samples.profilesInProcess.get(entry.pid)?.get(entry.tid)?.parsedProfile.nodeById(entry.nodeId);\n if (!cpuProfileNode) {\n throw new Error('Could not find CPU Profile Node');\n }\n const anonymousCall = threadAppenders[0].titleForEvent(entry);\n assert.strictEqual(anonymousCall, '(anonymous)');\n const originalName = cpuProfileNode.functionName;\n cpuProfileNode.setFunctionName('new-resolved-function-name');\n assert.strictEqual(threadAppenders[0].titleForEvent(entry), 'new-resolved-function-name');\n // Reset the value for future tests.\n cpuProfileNode.setFunctionName(originalName);\n });\n\n it('shows the correct title for a trace event when hovered', async function() {\n const {threadAppenders, parsedTrace} = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz');\n const events = parsedTrace.Renderer?.allTraceEntries;\n if (!events) {\n throw new Error('Could not find renderer events');\n }\n const info = threadAppenders[0].highlightedEntryInfo(events[0]);\n assert.strictEqual(info.title, 'Task');\n assert.strictEqual(info.formattedTime, '0.27\\u00A0ms');\n });\n\n it('shows self time only for events with self time above the threshold when hovered', async function() {\n const {threadAppenders, parsedTrace} = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz');\n const events = parsedTrace.Renderer?.allTraceEntries;\n if (!events) {\n throw new Error('Could not find renderer events');\n }\n const infoForShortEvent = threadAppenders[0].highlightedEntryInfo(events[0]);\n assert.strictEqual(infoForShortEvent.formattedTime, '0.27\\u00A0ms');\n\n const longTask = events.find(e => (e.dur || 0) > 1_000_000);\n if (!longTask) {\n throw new Error('Could not find long task');\n }\n const infoForLongEvent = threadAppenders[0].highlightedEntryInfo(longTask);\n assert.strictEqual(infoForLongEvent.formattedTime, '1.30\\u00A0s (self 47\\u00A0μs)');\n });\n\n it('shows the correct title for a ParseHTML event', async function() {\n const {threadAppenders, parsedTrace} = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz');\n const events = parsedTrace.Renderer?.allTraceEntries;\n if (!events) {\n throw new Error('Could not find renderer events');\n }\n const infoForShortEvent = threadAppenders[0].highlightedEntryInfo(events[0]);\n assert.strictEqual(infoForShortEvent.formattedTime, '0.27\\u00A0ms');\n\n const longTask = events.find(e => (e.dur || 0) > 1_000_000);\n if (!longTask) {\n throw new Error('Could not find long task');\n }\n const infoForLongEvent = threadAppenders[0].highlightedEntryInfo(longTask);\n assert.strictEqual(infoForLongEvent.formattedTime, '1.30\\u00A0s (self 47\\u00A0μs)');\n });\n\n it('shows the correct title for a profile call when hovered', async function() {\n const {threadAppenders, parsedTrace} = await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz');\n const rendererHandler = parsedTrace.Renderer;\n if (!rendererHandler) {\n throw new Error('RendererHandler is undefined');\n }\n const [process] = rendererHandler.processes.values();\n const [thread] = process.threads.values();\n const profileCalls = thread.entries.filter(entry => Trace.Types.Events.isProfileCall(entry));\n\n if (!profileCalls) {\n throw new Error('Could not find renderer events');\n }\n\n const info = threadAppenders[0].highlightedEntryInfo(profileCalls[0]);\n assert.strictEqual(info.title, '(anonymous)');\n assert.strictEqual(info.formattedTime, '15\\u00A0μs');\n });\n it('candy-stripes long tasks', async function() {\n const {parsedTrace, flameChartData, entryData} =\n await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz');\n const events = parsedTrace.Renderer?.allTraceEntries;\n if (!events) {\n throw new Error('Could not find renderer events');\n }\n const longTask = events.find(e => (e.dur || 0) > 1_000_000);\n if (!longTask) {\n throw new Error('Could not find long task');\n }\n const entryIndex = entryData.indexOf(longTask);\n const decorationsForEntry = flameChartData.entryDecorations[entryIndex];\n assert.deepEqual(decorationsForEntry, [\n {type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE},\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,\n startAtTime: Trace.Types.Timing.MicroSeconds(50_000),\n },\n ]);\n });\n\n it('does not candy-stripe tasks below the long task threshold', async function() {\n const {parsedTrace, flameChartData, entryData} =\n await renderThreadAppendersFromTrace(this, 'simple-js-program.json.gz');\n const events = parsedTrace.Renderer?.allTraceEntries;\n if (!events) {\n throw new Error('Could not find renderer events');\n }\n const entryIndex = entryData.indexOf(events[0]);\n const decorationsForEntry = flameChartData.entryDecorations[entryIndex];\n assert.isUndefined(decorationsForEntry);\n });\n\n it('does not append a track if there are no visible events on it', async function() {\n const {flameChartData} = await renderThreadAppendersFromTrace(this, 'one-second-interaction.json.gz');\n const expectedTrackNames = [\n 'Main — https://chromedevtools.github.io/performance-stories/long-interaction/index.html?x=40',\n 'Thread pool',\n // There are multiple ThreadPoolForegroundWorker threads present in\n // the trace, but only one of these has trace events we deem as\n // \"visible\".\n 'Thread pool worker 1',\n // This second \"worker\" is the ThreadPoolServiceThread. TODO: perhaps hide ThreadPoolServiceThread completely?\n 'Thread pool worker 2',\n ];\n assert.deepStrictEqual(flameChartData.groups.map(g => g.name), expectedTrackNames);\n });\n\n describe('ignore listing', () => {\n let ignoreListManager: Bindings.IgnoreListManager.IgnoreListManager;\n beforeEach(() => {\n const targetManager = SDK.TargetManager.TargetManager.instance({forceNew: true});\n const workspace = Workspace.Workspace.WorkspaceImpl.instance({forceNew: true});\n const resourceMapping = new Bindings.ResourceMapping.ResourceMapping(targetManager, workspace);\n const debuggerWorkspaceBinding = Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance({\n forceNew: true,\n resourceMapping,\n targetManager,\n });\n ignoreListManager = Bindings.IgnoreListManager.IgnoreListManager.instance({\n forceNew: true,\n debuggerWorkspaceBinding,\n });\n });\n afterEach(() => {\n SDK.TargetManager.TargetManager.removeInstance();\n Workspace.Workspace.WorkspaceImpl.removeInstance();\n Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.removeInstance();\n Bindings.IgnoreListManager.IgnoreListManager.removeInstance();\n });\n it('removes entries from the data that match the ignored URL', async function() {\n const initialTimelineData = await renderThreadAppendersFromTrace(this, 'react-hello-world.json.gz');\n const initialFlamechartData = initialTimelineData.flameChartData;\n const eventCountBeforeIgnoreList = initialFlamechartData.entryStartTimes.length;\n const SCRIPT_TO_IGNORE =\n 'https://unpkg.com/react@18.2.0/umd/react.development.js' as Platform.DevToolsPath.UrlString;\n // Clear the data provider cache and add the React script to the ignore list.\n ignoreListManager.ignoreListURL(SCRIPT_TO_IGNORE);\n const finalTimelineData = await renderThreadAppendersFromTrace(this, 'react-hello-world.json.gz');\n const finalFlamechartData = finalTimelineData.flameChartData;\n const eventCountAfterIgnoreList = finalFlamechartData.entryStartTimes.length;\n // Ensure that the amount of events we show on the flame chart is less\n // than before, now we have added the React URL to the ignore list.\n assert.isBelow(eventCountAfterIgnoreList, eventCountBeforeIgnoreList);\n\n // // Clear the data provider cache and unignore the script again\n ignoreListManager.unIgnoreListURL(SCRIPT_TO_IGNORE);\n const finalTimelineData2 = await renderThreadAppendersFromTrace(this, 'react-hello-world.json.gz');\n const finalFlamechartData2 = finalTimelineData2.flameChartData;\n const eventCountAfterIgnoreList2 = finalFlamechartData2.entryStartTimes.length;\n // // Ensure that now we have un-ignored the URL that we get the full set of events again.\n assert.strictEqual(eventCountAfterIgnoreList2, eventCountBeforeIgnoreList);\n });\n\n it('appends a tree that contains ignore listed entries correctly', async function() {\n const SCRIPT_TO_IGNORE = 'https://some-framework/bundled.js' as Platform.DevToolsPath.UrlString;\n\n // Create the following hierarchy with profile calls. Events marked\n // with \\\\\\\\ represent ignored listed events.\n // |----------A-----------|\n // |\\\\\\\\\\B\\\\\\\\\\||----F----|\n // |\\\\C\\\\||\\D\\|\n // |--E--|\n //\n // Applying ignore listing in the appender, should yield the\n // following flame chart:\n // |----------A-----------|\n // |\\\\\\\\\\B\\\\\\\\||----F----|\n // |--E--|\n const callFrameA = makeProfileCall('A', 100, 200);\n const callFrameB = makeProfileCall('IgnoreListedB', 100, 100);\n callFrameB.callFrame.url = SCRIPT_TO_IGNORE;\n const callFrameC = makeProfileCall('IgnoreListedC', 100, 50);\n callFrameC.callFrame.url = SCRIPT_TO_IGNORE;\n const callFrameD = makeProfileCall('IgnoreListedD', 151, 49);\n callFrameD.callFrame.url = SCRIPT_TO_IGNORE;\n const callFrameE = makeProfileCall('E', 100, 25);\n const callFrameF = makeProfileCall('F', 200, 100);\n\n const allEntries = [callFrameA, callFrameB, callFrameC, callFrameE, callFrameD, callFrameF];\n const rendererData = makeRendererHandlerData(allEntries);\n const workersData: Trace.Handlers.ModelHandlers.Workers.WorkersData = {\n workerSessionIdEvents: [],\n workerIdByThread: new Map(),\n workerURLById: new Map(),\n };\n const warningsData: Trace.Handlers.ModelHandlers.Warnings.WarningsData = {\n perWarning: new Map(),\n perEvent: new Map(),\n };\n // This only includes data used in the thread appender\n const mockParsedTrace = {\n Renderer: rendererData,\n Workers: workersData,\n Warnings: warningsData,\n AuctionWorklets: {worklets: new Map()},\n Meta: {\n traceIsGeneric: false,\n },\n } as Trace.Handlers.Types.ParsedTrace;\n\n // Add the script to ignore list and then append the flamechart data\n ignoreListManager.ignoreListURL(SCRIPT_TO_IGNORE);\n const {entryData, flameChartData, threadAppenders} = renderThreadAppendersFromParsedData(mockParsedTrace);\n const entryDataNames = entryData.map(entry => {\n const regularEvent =\n Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider.timelineEntryIsTraceEvent(entry);\n if (!regularEvent) {\n return 'Unknown type';\n }\n if (Trace.Types.Events.isProfileCall(entry)) {\n return entry.callFrame.functionName;\n }\n return entry.name;\n });\n\n assert.deepEqual(entryDataNames, ['A', 'IgnoreListedB', 'E', 'F']);\n assert.deepEqual(flameChartData.entryLevels, [0, 1, 2, 1]);\n assert.deepEqual(flameChartData.entryStartTimes, [0.1, 0.1, 0.1, 0.2]);\n assert.deepEqual(flameChartData.entryTotalTimes, [0.2, 0.1, 0.025, 0.1]);\n assert.strictEqual(threadAppenders.length, 1);\n assert.strictEqual(threadAppenders[0].titleForEvent(callFrameB), 'On ignore list');\n });\n });\n describe('showAllEvents', () => {\n beforeEach(() => {\n const targetManager = SDK.TargetManager.TargetManager.instance({forceNew: true});\n const workspace = Workspace.Workspace.WorkspaceImpl.instance({forceNew: true});\n const resourceMapping = new Bindings.ResourceMapping.ResourceMapping(targetManager, workspace);\n const debuggerWorkspaceBinding = Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance({\n forceNew: true,\n resourceMapping,\n targetManager,\n });\n Bindings.IgnoreListManager.IgnoreListManager.instance({\n forceNew: true,\n debuggerWorkspaceBinding,\n });\n });\n afterEach(() => {\n SDK.TargetManager.TargetManager.removeInstance();\n Workspace.Workspace.WorkspaceImpl.removeInstance();\n Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.removeInstance();\n Bindings.IgnoreListManager.IgnoreListManager.removeInstance();\n });\n it('appends unknown events to the flame chart data only when the experiment is enabled', async function() {\n const fileName = 'react-hello-world.json.gz';\n const bizarreName = 'BackForwardCacheBufferLimitTracker::DidRemoveFrameOrWorkerFromBackForwardCache';\n // Look up a trace event with an name we are not tracking anywhere and make sure it's not\n // appended to the timeline data.\n const initialTimelineData = await renderThreadAppendersFromTrace(this, fileName);\n let unknownEventIndex = initialTimelineData.entryData.findIndex(entry => {\n const event = entry as Trace.Types.Events.Event;\n return event.name === bizarreName;\n });\n assert.strictEqual(unknownEventIndex, -1);\n\n // Now enable the experiment and make sure the event is appended to the timeline data this time\n Root.Runtime.experiments.enableForTest('timeline-show-all-events');\n const finalTimelineData = await renderThreadAppendersFromTrace(this, fileName);\n const finalFlamechartData = finalTimelineData.flameChartData;\n unknownEventIndex = finalTimelineData.entryData.findIndex(entry => {\n const event = entry as Trace.Types.Events.Event;\n return event.name === bizarreName;\n });\n assert.isAbove(unknownEventIndex, -1);\n assert.exists(finalFlamechartData.entryStartTimes);\n assert.exists(finalFlamechartData.entryTotalTimes);\n Root.Runtime.experiments.disableForTest('timeline-show-all-events');\n });\n });\n describe('AuctionWorklet threads', () => {\n // We have to set these up because the ThreadAppender includes logic for\n // ignoring events that relies on the IgnoreListManager.\n beforeEach(() => {\n const targetManager = SDK.TargetManager.TargetManager.instance({forceNew: true});\n const workspace = Workspace.Workspace.WorkspaceImpl.instance({forceNew: true});\n const resourceMapping = new Bindings.ResourceMapping.ResourceMapping(targetManager, workspace);\n const debuggerWorkspaceBinding = Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance({\n forceNew: true,\n resourceMapping,\n targetManager,\n });\n Bindings.IgnoreListManager.IgnoreListManager.instance({\n forceNew: true,\n debuggerWorkspaceBinding,\n });\n });\n\n afterEach(() => {\n SDK.TargetManager.TargetManager.removeInstance();\n Workspace.Workspace.WorkspaceImpl.removeInstance();\n Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.removeInstance();\n Bindings.IgnoreListManager.IgnoreListManager.removeInstance();\n });\n\n it('finds all the worklet threads', async function() {\n const {threadAppenders} = await renderThreadAppendersFromTrace(this, 'fenced-frame-fledge.json.gz');\n const workletAppenders = threadAppenders.filter(threadAppender => {\n return threadAppender.trackName().includes('Worklet');\n });\n assert.lengthOf(workletAppenders, 6);\n });\n\n it('sets the title correctly for an Auction Worklet service', async function() {\n const UTILITY_THREAD_PID = 776435 as Trace.Types.Events.ProcessID;\n const UTILITY_THREAD_TID = 1 as Trace.Types.Events.ThreadID;\n const {threadAppenders} = await renderThreadAppendersFromTrace(this, 'fenced-frame-fledge.json.gz');\n const appender = threadAppenders.find(threadAppender => {\n return threadAppender.processId() === UTILITY_THREAD_PID && threadAppender.threadId() === UTILITY_THREAD_TID;\n });\n if (!appender) {\n throw new Error('Could not find expected thread appender');\n }\n assert.strictEqual(appender.trackName(), 'Auction Worklet service — https://ssp-fledge-demo.glitch.me');\n });\n\n it('sets the title correctly for an Auction Worklet seller service', async function() {\n const SELLER_THREAD_PID = 776435 as Trace.Types.Events.ProcessID;\n const SELLER_THREAD_TID = 6 as Trace.Types.Events.ThreadID;\n const {threadAppenders} = await renderThreadAppendersFromTrace(this, 'fenced-frame-fledge.json.gz');\n const appender = threadAppenders.find(threadAppender => {\n return threadAppender.processId() === SELLER_THREAD_PID && threadAppender.threadId() === SELLER_THREAD_TID;\n });\n if (!appender) {\n throw new Error('Could not find expected thread appender');\n }\n assert.strictEqual(appender.trackName(), 'Seller Worklet — https://ssp-fledge-demo.glitch.me');\n });\n\n it('sets the title correctly for an Auction Worklet bidder service', async function() {\n const BIDDER_THREAD_PID = 776436 as Trace.Types.Events.ProcessID;\n const BIDDER_THREAD_TID = 6 as Trace.Types.Events.ThreadID;\n const {threadAppenders} = await renderThreadAppendersFromTrace(this, 'fenced-frame-fledge.json.gz');\n const appender = threadAppenders.find(threadAppender => {\n return threadAppender.processId() === BIDDER_THREAD_PID && threadAppender.threadId() === BIDDER_THREAD_TID;\n });\n if (!appender) {\n throw new Error('Could not find expected thread appender');\n }\n assert.strictEqual(appender.trackName(), 'Bidder Worklet — https://dsp-fledge-demo.glitch.me');\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/track_appenders/TimingsTrackAppender.test.js b/public/panels/timeline/track_appenders/TimingsTrackAppender.test.js index 4e9dc3c0b..7011e55ea 100644 --- a/public/panels/timeline/track_appenders/TimingsTrackAppender.test.js +++ b/public/panels/timeline/track_appenders/TimingsTrackAppender.test.js @@ -1,26 +1,26 @@ // 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 * as TraceModel from '../../../models/trace/trace.js'; +import * as Trace from '../../../models/trace/trace.js'; import { describeWithEnvironment } from '../../../testing/EnvironmentHelpers.js'; import { TraceLoader } from '../../../testing/TraceLoader.js'; import * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js'; import * as ThemeSupport from '../../../ui/legacy/theme_support/theme_support.js'; import * as Timeline from '../timeline.js'; -function initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel) { - Timeline.ExtensionDataGatherer.ExtensionDataGatherer.instance().modelChanged(traceData); - const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(flameChartData, traceData, entryData, entryTypeByLevel); +function initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel) { + Timeline.ExtensionDataGatherer.ExtensionDataGatherer.instance().modelChanged(parsedTrace); + const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel); return compatibilityTracksAppender.timingsTrackAppender(); } describeWithEnvironment('TimingTrackAppender', function () { - let traceData; + let parsedTrace; let timingsTrackAppender; let entryData = []; let flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty(); let entryTypeByLevel = []; beforeEach(async function () { - ({ traceData } = await TraceLoader.traceEngine(this, 'timings-track.json.gz')); - timingsTrackAppender = initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel); + ({ parsedTrace } = await TraceLoader.traceEngine(this, 'timings-track.json.gz')); + timingsTrackAppender = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel); timingsTrackAppender.appendTrackAtLevel(0); }); afterEach(() => { @@ -46,51 +46,51 @@ describeWithEnvironment('TimingTrackAppender', function () { assert.strictEqual(flameChartData.groups[0].name, 'Timings'); }); it('populates the markers array in ascendent order', () => { - const traceMarkers = traceData.PageLoadMetrics.allMarkerEvents; + const traceMarkers = parsedTrace.PageLoadMetrics.allMarkerEvents; assert.strictEqual(flameChartData.markers.length, traceMarkers.length); for (let i = 1; i < flameChartData.markers.length; i++) { assert.isAtLeast(flameChartData.markers[i].startTime(), flameChartData.markers[i - 1].startTime()); } }); it('creates a TimelineFlameChartMarker for each page load marker event in a trace', () => { - const traceMarkers = traceData.PageLoadMetrics.allMarkerEvents; + const traceMarkers = parsedTrace.PageLoadMetrics.allMarkerEvents; assert.strictEqual(flameChartData.markers.length, traceMarkers.length); for (const traceMarker of traceMarkers) { - const markerTimeMs = TraceModel.Helpers.Timing.microSecondsToMilliseconds(traceMarker.ts); + const markerTimeMs = Trace.Helpers.Timing.microSecondsToMilliseconds(traceMarker.ts); const flameChartMarker = flameChartData.markers.find(flameChartMarker => flameChartMarker.startTime() === markerTimeMs); assert.exists(flameChartMarker); } assert.strictEqual(flameChartData.markers.length, traceMarkers.length); }); it('adds start times correctly', () => { - const traceMarkers = traceData.PageLoadMetrics.allMarkerEvents; - const performanceMarks = traceData.UserTimings.performanceMarks; - const performanceMeasures = traceData.UserTimings.performanceMeasures; - const consoleTimings = traceData.UserTimings.consoleTimings; - const consoleTimestamps = traceData.UserTimings.timestampEvents; + const traceMarkers = parsedTrace.PageLoadMetrics.allMarkerEvents; + const performanceMarks = parsedTrace.UserTimings.performanceMarks; + const performanceMeasures = parsedTrace.UserTimings.performanceMeasures; + const consoleTimings = parsedTrace.UserTimings.consoleTimings; + const consoleTimestamps = parsedTrace.UserTimings.timestampEvents; for (const event of [...traceMarkers, ...performanceMarks, ...performanceMeasures, ...consoleTimings, ...consoleTimestamps]) { const markerIndex = entryData.indexOf(event); assert.exists(markerIndex); - assert.strictEqual(flameChartData.entryStartTimes[markerIndex], TraceModel.Helpers.Timing.microSecondsToMilliseconds(event.ts)); + assert.strictEqual(flameChartData.entryStartTimes[markerIndex], Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts)); } }); it('adds total times correctly', () => { - const traceMarkers = traceData.PageLoadMetrics.allMarkerEvents; - const performanceMarks = traceData.UserTimings.performanceMarks; - const performanceMeasures = traceData.UserTimings.performanceMeasures; - const consoleTimings = traceData.UserTimings.consoleTimings; - const consoleTimestamps = traceData.UserTimings.timestampEvents; + const traceMarkers = parsedTrace.PageLoadMetrics.allMarkerEvents; + const performanceMarks = parsedTrace.UserTimings.performanceMarks; + const performanceMeasures = parsedTrace.UserTimings.performanceMeasures; + const consoleTimings = parsedTrace.UserTimings.consoleTimings; + const consoleTimestamps = parsedTrace.UserTimings.timestampEvents; for (const event of [...traceMarkers, ...performanceMarks, ...performanceMeasures, ...consoleTimings, ...consoleTimestamps]) { const markerIndex = entryData.indexOf(event); assert.exists(markerIndex); - if (TraceModel.Types.TraceEvents.isTraceEventMarkerEvent(event)) { + if (Trace.Types.Events.isMarkerEvent(event)) { assert.isNaN(flameChartData.entryTotalTimes[markerIndex]); continue; } const expectedTotalTimeForEvent = event.dur ? - TraceModel.Helpers.Timing.microSecondsToMilliseconds(event.dur) : + Trace.Helpers.Timing.microSecondsToMilliseconds(event.dur) : Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs; assert.strictEqual(flameChartData.entryTotalTimes[markerIndex], expectedTotalTimeForEvent); } @@ -102,13 +102,13 @@ describeWithEnvironment('TimingTrackAppender', function () { entryTypeByLevel = []; // animation.json.gz has FP, FCP and LCP at the same timestamp, and we want // to make sure visually the markers are ordered [FP][FCP][LCP]. - const { traceData } = await TraceLoader.traceEngine(this, 'animation.json.gz'); - timingsTrackAppender = initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'animation.json.gz'); + timingsTrackAppender = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel); timingsTrackAppender.appendTrackAtLevel(0); - const { allMarkerEvents } = traceData.PageLoadMetrics; - const firstPaint = allMarkerEvents.find(TraceModel.Types.TraceEvents.isTraceEventFirstPaint); - const fcp = allMarkerEvents.find(TraceModel.Types.TraceEvents.isTraceEventFirstContentfulPaint); - const lcp = allMarkerEvents.find(TraceModel.Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate); + const { allMarkerEvents } = parsedTrace.PageLoadMetrics; + const firstPaint = allMarkerEvents.find(Trace.Types.Events.isFirstPaint); + const fcp = allMarkerEvents.find(Trace.Types.Events.isFirstContentfulPaint); + const lcp = allMarkerEvents.find(Trace.Types.Events.isLargestContentfulPaintCandidate); assert.isOk(firstPaint); assert.isOk(fcp); assert.isOk(lcp); @@ -122,7 +122,7 @@ describeWithEnvironment('TimingTrackAppender', function () { }); describe('colorForEvent and titleForEvent', () => { it('returns the correct color and title for page load markers', () => { - const traceMarkers = traceData.PageLoadMetrics.allMarkerEvents; + const traceMarkers = parsedTrace.PageLoadMetrics.allMarkerEvents; const firstContentfulPaint = traceMarkers.find(marker => marker.name === 'firstContentfulPaint'); const markLoad = traceMarkers.find(marker => marker.name === 'MarkLoad'); const markDOMContent = traceMarkers.find(marker => marker.name === 'MarkDOMContent'); @@ -133,36 +133,36 @@ describeWithEnvironment('TimingTrackAppender', function () { throw new Error('A metric was not found'); } assert.strictEqual(timingsTrackAppender.colorForEvent(firstContentfulPaint), '#1A6937'); - assert.strictEqual(timingsTrackAppender.titleForEvent(firstContentfulPaint), "FCP" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP */); + assert.strictEqual(timingsTrackAppender.titleForEvent(firstContentfulPaint), "FCP" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP */); assert.strictEqual(timingsTrackAppender.colorForEvent(markLoad), '#B31412'); - assert.strictEqual(timingsTrackAppender.titleForEvent(markLoad), "L" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.L */); + assert.strictEqual(timingsTrackAppender.titleForEvent(markLoad), "L" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.L */); assert.strictEqual(timingsTrackAppender.colorForEvent(markDOMContent), '#0867CB'); - assert.strictEqual(timingsTrackAppender.titleForEvent(markDOMContent), "DCL" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.DCL */); + assert.strictEqual(timingsTrackAppender.titleForEvent(markDOMContent), "DCL" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.DCL */); assert.strictEqual(timingsTrackAppender.colorForEvent(firstPaint), '#228847'); - assert.strictEqual(timingsTrackAppender.titleForEvent(firstPaint), "FP" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FP */); + assert.strictEqual(timingsTrackAppender.titleForEvent(firstPaint), "FP" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FP */); assert.strictEqual(timingsTrackAppender.colorForEvent(largestContentfulPaint), '#1A3422'); - assert.strictEqual(timingsTrackAppender.titleForEvent(largestContentfulPaint), "LCP" /* TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP */); + assert.strictEqual(timingsTrackAppender.titleForEvent(largestContentfulPaint), "LCP" /* Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP */); }); it('returns the correct title for performance measures', () => { - const performanceMeasures = traceData.UserTimings.performanceMeasures; + const performanceMeasures = parsedTrace.UserTimings.performanceMeasures; for (const measure of performanceMeasures) { assert.strictEqual(timingsTrackAppender.titleForEvent(measure), measure.name); } }); it('returns the correct title for console timings', () => { - const traceMarkers = traceData.UserTimings.consoleTimings; + const traceMarkers = parsedTrace.UserTimings.consoleTimings; for (const mark of traceMarkers) { assert.strictEqual(timingsTrackAppender.titleForEvent(mark), mark.name); } }); it('returns the correct title for performance marks', () => { - const traceMarkers = traceData.UserTimings.performanceMarks; + const traceMarkers = parsedTrace.UserTimings.performanceMarks; for (const mark of traceMarkers) { assert.strictEqual(timingsTrackAppender.titleForEvent(mark), `[mark]: ${mark.name}`); } }); it('returns the correct title for console timestamps', () => { - const traceMarkers = traceData.UserTimings.timestampEvents; + const traceMarkers = parsedTrace.UserTimings.timestampEvents; for (const mark of traceMarkers) { assert.strictEqual(timingsTrackAppender.titleForEvent(mark), `TimeStamp: ${mark.args.data.message}`); } @@ -170,7 +170,7 @@ describeWithEnvironment('TimingTrackAppender', function () { }); describe('highlightedEntryInfo', () => { it('shows the time of the mark, not the duration, if the event is a performance mark', () => { - const firstMark = traceData.UserTimings.performanceMarks[0]; + const firstMark = parsedTrace.UserTimings.performanceMarks[0]; const highlightedEntryInfo = timingsTrackAppender.highlightedEntryInfo(firstMark); assert.deepEqual(highlightedEntryInfo, { title: '[mark]: myMark', @@ -178,7 +178,7 @@ describeWithEnvironment('TimingTrackAppender', function () { }); }); it('shows the time of the mark for an LCP event', () => { - const largestContentfulPaint = traceData.PageLoadMetrics.allMarkerEvents.find(marker => marker.name === 'largestContentfulPaint::Candidate'); + const largestContentfulPaint = parsedTrace.PageLoadMetrics.allMarkerEvents.find(marker => marker.name === 'largestContentfulPaint::Candidate'); if (!largestContentfulPaint) { throw new Error('Could not find LCP event'); } @@ -189,7 +189,7 @@ describeWithEnvironment('TimingTrackAppender', function () { }); }); it('shows the time of the mark for an FCP event', () => { - const firstContentfulPaint = traceData.PageLoadMetrics.allMarkerEvents.find(marker => marker.name === 'firstContentfulPaint'); + const firstContentfulPaint = parsedTrace.PageLoadMetrics.allMarkerEvents.find(marker => marker.name === 'firstContentfulPaint'); if (!firstContentfulPaint) { throw new Error('Could not find FCP event'); } @@ -200,7 +200,7 @@ describeWithEnvironment('TimingTrackAppender', function () { }); }); it('shows the time of the mark for a DCL event', () => { - const dclEvent = traceData.PageLoadMetrics.allMarkerEvents.find(marker => marker.name === 'MarkDOMContent'); + const dclEvent = parsedTrace.PageLoadMetrics.allMarkerEvents.find(marker => marker.name === 'MarkDOMContent'); if (!dclEvent) { throw new Error('Could not find DCL event'); } @@ -211,7 +211,7 @@ describeWithEnvironment('TimingTrackAppender', function () { }); }); it('shows the time of a console.timestamp event in the hover info', () => { - const timestampEvent = traceData.UserTimings.timestampEvents[0]; + const timestampEvent = parsedTrace.UserTimings.timestampEvents[0]; const highlightedEntryInfo = timingsTrackAppender.highlightedEntryInfo(timestampEvent); assert.deepEqual(highlightedEntryInfo, { title: 'TimeStamp: a timestamp', @@ -219,13 +219,13 @@ describeWithEnvironment('TimingTrackAppender', function () { }); }); it('returns the info for a performance.measure calls correctly', () => { - const performanceMeasures = traceData.UserTimings.performanceMeasures; + const performanceMeasures = parsedTrace.UserTimings.performanceMeasures; const highlightedEntryInfo = timingsTrackAppender.highlightedEntryInfo(performanceMeasures[0]); // The i18n encodes spaces using the u00A0 unicode character. assert.strictEqual(highlightedEntryInfo.formattedTime, ('500.07\u00A0ms')); }); it('returns the info for a console.time calls correctly', () => { - const consoleTimings = traceData.UserTimings.consoleTimings; + const consoleTimings = parsedTrace.UserTimings.consoleTimings; const highlightedEntryInfo = timingsTrackAppender.highlightedEntryInfo(consoleTimings[0]); // The i18n encodes spaces using the u00A0 unicode character. assert.strictEqual(highlightedEntryInfo.formattedTime, ('1.60\u00A0s')); @@ -236,8 +236,8 @@ describeWithEnvironment('TimingTrackAppender', function () { entryData = []; flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty(); entryTypeByLevel = []; - ({ traceData } = await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz')); - timingsTrackAppender = initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel); + ({ parsedTrace } = await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz')); + timingsTrackAppender = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel); timingsTrackAppender.appendTrackAtLevel(0); // Rather than use the real colours here and burden the test with having to // inject loads of CSS, we fake out the colours. this is fine for our tests as @@ -266,15 +266,15 @@ describeWithEnvironment('TimingTrackAppender', function () { ThemeSupport.ThemeSupport.clearThemeCache(); }); it('creates a TimelineFlameChartMarker for each extension marker event in a trace', () => { - const extensionMarkers = traceData.ExtensionTraceData.extensionMarkers; + const extensionMarkers = parsedTrace.ExtensionTraceData.extensionMarkers; for (const traceMarker of extensionMarkers) { - const markerTimeMs = TraceModel.Helpers.Timing.microSecondsToMilliseconds(traceMarker.ts); + const markerTimeMs = Trace.Helpers.Timing.microSecondsToMilliseconds(traceMarker.ts); const flameChartMarker = flameChartData.markers.find(flameChartMarker => flameChartMarker.startTime() === markerTimeMs); assert.exists(flameChartMarker); } }); it('returns the correct color and title for extension markers', function () { - const extensionMarkers = traceData.ExtensionTraceData.extensionMarkers; + const extensionMarkers = parsedTrace.ExtensionTraceData.extensionMarkers; for (const event of extensionMarkers) { assert.strictEqual(timingsTrackAppender.titleForEvent(event), event.name); if (event.args.color === 'error') { @@ -310,7 +310,7 @@ describeWithEnvironment('TimingTrackAppender', function () { assert.strictEqual(timingsTrackAppender.colorForEvent(mockExtensionEntryUnknownColor), 'rgb(4 4 4)'); }); it('returns the tool tip info for an entry correctly', function () { - const extensionMarker = traceData.ExtensionTraceData.extensionMarkers.at(0); + const extensionMarker = parsedTrace.ExtensionTraceData.extensionMarkers.at(0); assert.isOk(extensionMarker, 'did not find any extension markers'); const highlightedEntryInfo = timingsTrackAppender.highlightedEntryInfo(extensionMarker); assert.strictEqual(highlightedEntryInfo.title, 'A mark'); @@ -322,12 +322,12 @@ describeWithEnvironment('TimingTrackAppender', function () { flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty(); entryTypeByLevel = []; Timeline.TimelinePanel.TimelinePanel.extensionDataVisibilitySetting().set(false); - traceData = (await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz')).traceData; - timingsTrackAppender = initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel); + parsedTrace = (await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz')).parsedTrace; + timingsTrackAppender = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel); timingsTrackAppender.appendTrackAtLevel(0); - const extensionMarkers = traceData.ExtensionTraceData.extensionMarkers; + const extensionMarkers = parsedTrace.ExtensionTraceData.extensionMarkers; for (const traceMarker of extensionMarkers) { - const markerTimeMs = TraceModel.Helpers.Timing.microSecondsToMilliseconds(traceMarker.ts); + const markerTimeMs = Trace.Helpers.Timing.microSecondsToMilliseconds(traceMarker.ts); const flameChartMarker = flameChartData.markers.find(flameChartMarker => flameChartMarker.startTime() === markerTimeMs); assert.isUndefined(flameChartMarker); } diff --git a/public/panels/timeline/track_appenders/TimingsTrackAppender.test.js.map b/public/panels/timeline/track_appenders/TimingsTrackAppender.test.js.map index 6c18deecb..be7ef83e6 100644 --- a/public/panels/timeline/track_appenders/TimingsTrackAppender.test.js.map +++ b/public/panels/timeline/track_appenders/TimingsTrackAppender.test.js.map @@ -1 +1 @@ -{"version":3,"file":"TimingsTrackAppender.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/track_appenders/TimingsTrackAppender.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceModel from '../../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as ThemeSupport from '../../../ui/legacy/theme_support/theme_support.js';\nimport * as Timeline from '../timeline.js';\n\nfunction initTrackAppender(\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData,\n traceData: TraceModel.Handlers.Types.TraceParseData,\n entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[],\n entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[],\n ): Timeline.TimingsTrackAppender.TimingsTrackAppender {\n Timeline.ExtensionDataGatherer.ExtensionDataGatherer.instance().modelChanged(traceData);\n const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(\n flameChartData, traceData, entryData, entryTypeByLevel);\n return compatibilityTracksAppender.timingsTrackAppender();\n}\n\ndescribeWithEnvironment('TimingTrackAppender', function() {\n let traceData: TraceModel.Handlers.Types.TraceParseData;\n let timingsTrackAppender: Timeline.TimingsTrackAppender.TimingsTrackAppender;\n let entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[] = [];\n let flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n let entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[] = [];\n beforeEach(async function() {\n ({traceData} = await TraceLoader.traceEngine(this, 'timings-track.json.gz'));\n timingsTrackAppender = initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel);\n timingsTrackAppender.appendTrackAtLevel(0);\n });\n afterEach(() => {\n entryData = [];\n flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n entryTypeByLevel = [];\n });\n\n describe('appendTrackAtLevel', () => {\n it('marks all levels used by the track with the `TrackAppender` type', () => {\n // 8 levels should be taken:\n // * 1 for page load marks.\n // * 1 performance.marks.\n // * 3 used by performance.measures.\n // * 1 used by console timestamps.\n // * 1 used by console.time calls.\n const levelCount = 7;\n assert.strictEqual(entryTypeByLevel.length, levelCount);\n const allEntriesAreTrackAppender =\n entryTypeByLevel.every(type => type === Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER);\n assert.isTrue(allEntriesAreTrackAppender);\n });\n it('creates a flamechart group for the timings track', () => {\n assert.strictEqual(flameChartData.groups.length, 1);\n assert.strictEqual(flameChartData.groups[0].name, 'Timings');\n });\n it('populates the markers array in ascendent order', () => {\n const traceMarkers = traceData.PageLoadMetrics.allMarkerEvents;\n assert.strictEqual(flameChartData.markers.length, traceMarkers.length);\n for (let i = 1; i < flameChartData.markers.length; i++) {\n assert.isAtLeast(flameChartData.markers[i].startTime(), flameChartData.markers[i - 1].startTime());\n }\n });\n it('creates a TimelineFlameChartMarker for each page load marker event in a trace', () => {\n const traceMarkers = traceData.PageLoadMetrics.allMarkerEvents;\n assert.strictEqual(flameChartData.markers.length, traceMarkers.length);\n for (const traceMarker of traceMarkers) {\n const markerTimeMs = TraceModel.Helpers.Timing.microSecondsToMilliseconds(traceMarker.ts);\n const flameChartMarker =\n flameChartData.markers.find(flameChartMarker => flameChartMarker.startTime() === markerTimeMs);\n assert.exists(flameChartMarker);\n }\n assert.strictEqual(flameChartData.markers.length, traceMarkers.length);\n });\n it('adds start times correctly', () => {\n const traceMarkers = traceData.PageLoadMetrics.allMarkerEvents;\n const performanceMarks = traceData.UserTimings.performanceMarks;\n const performanceMeasures = traceData.UserTimings.performanceMeasures;\n const consoleTimings = traceData.UserTimings.consoleTimings;\n const consoleTimestamps = traceData.UserTimings.timestampEvents;\n for (const event\n of [...traceMarkers, ...performanceMarks, ...performanceMeasures, ...consoleTimings,\n ...consoleTimestamps]) {\n const markerIndex = entryData.indexOf(event);\n assert.exists(markerIndex);\n assert.strictEqual(\n flameChartData.entryStartTimes[markerIndex],\n TraceModel.Helpers.Timing.microSecondsToMilliseconds(event.ts));\n }\n });\n it('adds total times correctly', () => {\n const traceMarkers = traceData.PageLoadMetrics.allMarkerEvents;\n const performanceMarks = traceData.UserTimings.performanceMarks;\n const performanceMeasures = traceData.UserTimings.performanceMeasures;\n const consoleTimings = traceData.UserTimings.consoleTimings;\n const consoleTimestamps = traceData.UserTimings.timestampEvents;\n for (const event\n of [...traceMarkers, ...performanceMarks, ...performanceMeasures, ...consoleTimings,\n ...consoleTimestamps]) {\n const markerIndex = entryData.indexOf(event);\n assert.exists(markerIndex);\n if (TraceModel.Types.TraceEvents.isTraceEventMarkerEvent(event)) {\n assert.isNaN(flameChartData.entryTotalTimes[markerIndex]);\n continue;\n }\n const expectedTotalTimeForEvent = event.dur ?\n TraceModel.Helpers.Timing.microSecondsToMilliseconds(event.dur) :\n Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs;\n assert.strictEqual(flameChartData.entryTotalTimes[markerIndex], expectedTotalTimeForEvent);\n }\n });\n });\n\n it('orders page load metrics that have the same timestamp', async function() {\n entryData = [];\n flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n entryTypeByLevel = [];\n // animation.json.gz has FP, FCP and LCP at the same timestamp, and we want\n // to make sure visually the markers are ordered [FP][FCP][LCP].\n const {traceData} = await TraceLoader.traceEngine(this, 'animation.json.gz');\n timingsTrackAppender = initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel);\n timingsTrackAppender.appendTrackAtLevel(0);\n const {allMarkerEvents} = traceData.PageLoadMetrics;\n\n const firstPaint = allMarkerEvents.find(TraceModel.Types.TraceEvents.isTraceEventFirstPaint);\n const fcp = allMarkerEvents.find(TraceModel.Types.TraceEvents.isTraceEventFirstContentfulPaint);\n const lcp = allMarkerEvents.find(TraceModel.Types.TraceEvents.isTraceEventLargestContentfulPaintCandidate);\n\n assert.isOk(firstPaint);\n assert.isOk(fcp);\n assert.isOk(lcp);\n\n // Prevent against the trace changing by ensuring all these events have the same timestamp.\n assert.isTrue(firstPaint.ts === fcp.ts && fcp.ts === lcp.ts);\n\n const indexes = [firstPaint, fcp, lcp].map(entry => entryData.indexOf(entry));\n // Because of how we order page markers, we expect the indexes to be in\n // this order which represents the visual order they are represented.\n // (0, 1, 2) are this traces navigation start, DCL and Load event.\n assert.deepEqual(indexes, [3, 4, 5]);\n });\n\n describe('colorForEvent and titleForEvent', () => {\n it('returns the correct color and title for page load markers', () => {\n const traceMarkers = traceData.PageLoadMetrics.allMarkerEvents;\n const firstContentfulPaint = traceMarkers.find(marker => marker.name === 'firstContentfulPaint');\n const markLoad = traceMarkers.find(marker => marker.name === 'MarkLoad');\n const markDOMContent = traceMarkers.find(marker => marker.name === 'MarkDOMContent');\n const firstPaint = traceMarkers.find(marker => marker.name === 'firstPaint');\n const largestContentfulPaint = traceMarkers.find(marker => marker.name === 'largestContentfulPaint::Candidate');\n\n if (firstContentfulPaint === undefined || markLoad === undefined || markDOMContent === undefined ||\n firstPaint === undefined || largestContentfulPaint === undefined) {\n throw new Error('A metric was not found');\n }\n\n assert.strictEqual(timingsTrackAppender.colorForEvent(firstContentfulPaint), '#1A6937');\n assert.strictEqual(\n timingsTrackAppender.titleForEvent(firstContentfulPaint),\n TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP);\n\n assert.strictEqual(timingsTrackAppender.colorForEvent(markLoad), '#B31412');\n assert.strictEqual(\n timingsTrackAppender.titleForEvent(markLoad), TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.L);\n\n assert.strictEqual(timingsTrackAppender.colorForEvent(markDOMContent), '#0867CB');\n assert.strictEqual(\n timingsTrackAppender.titleForEvent(markDOMContent),\n TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.DCL);\n\n assert.strictEqual(timingsTrackAppender.colorForEvent(firstPaint), '#228847');\n assert.strictEqual(\n timingsTrackAppender.titleForEvent(firstPaint),\n TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FP);\n\n assert.strictEqual(timingsTrackAppender.colorForEvent(largestContentfulPaint), '#1A3422');\n assert.strictEqual(\n timingsTrackAppender.titleForEvent(largestContentfulPaint),\n TraceModel.Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP);\n });\n\n it('returns the correct title for performance measures', () => {\n const performanceMeasures = traceData.UserTimings.performanceMeasures;\n for (const measure of performanceMeasures) {\n assert.strictEqual(timingsTrackAppender.titleForEvent(measure), measure.name);\n }\n });\n\n it('returns the correct title for console timings', () => {\n const traceMarkers = traceData.UserTimings.consoleTimings;\n for (const mark of traceMarkers) {\n assert.strictEqual(timingsTrackAppender.titleForEvent(mark), mark.name);\n }\n });\n\n it('returns the correct title for performance marks', () => {\n const traceMarkers = traceData.UserTimings.performanceMarks;\n for (const mark of traceMarkers) {\n assert.strictEqual(timingsTrackAppender.titleForEvent(mark), `[mark]: ${mark.name}`);\n }\n });\n\n it('returns the correct title for console timestamps', () => {\n const traceMarkers = traceData.UserTimings.timestampEvents;\n for (const mark of traceMarkers) {\n assert.strictEqual(timingsTrackAppender.titleForEvent(mark), `TimeStamp: ${mark.args.data.message}`);\n }\n });\n });\n\n describe('highlightedEntryInfo', () => {\n it('shows the time of the mark, not the duration, if the event is a performance mark', () => {\n const firstMark = traceData.UserTimings.performanceMarks[0];\n const highlightedEntryInfo = timingsTrackAppender.highlightedEntryInfo(firstMark);\n assert.deepEqual(highlightedEntryInfo, {\n title: '[mark]: myMark',\n formattedTime: '1.12\\u00A0s',\n });\n });\n\n it('shows the time of the mark for an LCP event', () => {\n const largestContentfulPaint =\n traceData.PageLoadMetrics.allMarkerEvents.find(marker => marker.name === 'largestContentfulPaint::Candidate');\n if (!largestContentfulPaint) {\n throw new Error('Could not find LCP event');\n }\n const highlightedEntryInfo = timingsTrackAppender.highlightedEntryInfo(largestContentfulPaint);\n assert.deepEqual(highlightedEntryInfo, {\n title: 'LCP',\n formattedTime: '2.42\\u00A0s',\n });\n });\n\n it('shows the time of the mark for an FCP event', () => {\n const firstContentfulPaint =\n traceData.PageLoadMetrics.allMarkerEvents.find(marker => marker.name === 'firstContentfulPaint');\n if (!firstContentfulPaint) {\n throw new Error('Could not find FCP event');\n }\n const highlightedEntryInfo = timingsTrackAppender.highlightedEntryInfo(firstContentfulPaint);\n assert.deepEqual(highlightedEntryInfo, {\n title: 'FCP',\n formattedTime: '2.42\\u00A0s',\n });\n });\n\n it('shows the time of the mark for a DCL event', () => {\n const dclEvent = traceData.PageLoadMetrics.allMarkerEvents.find(marker => marker.name === 'MarkDOMContent');\n if (!dclEvent) {\n throw new Error('Could not find DCL event');\n }\n const highlightedEntryInfo = timingsTrackAppender.highlightedEntryInfo(dclEvent);\n assert.deepEqual(highlightedEntryInfo, {\n title: 'DCL',\n formattedTime: '2.42\\u00A0s',\n });\n });\n\n it('shows the time of a console.timestamp event in the hover info', () => {\n const timestampEvent = traceData.UserTimings.timestampEvents[0];\n const highlightedEntryInfo = timingsTrackAppender.highlightedEntryInfo(timestampEvent);\n\n assert.deepEqual(highlightedEntryInfo, {\n title: 'TimeStamp: a timestamp',\n formattedTime: '615.25\\u00A0ms',\n });\n });\n\n it('returns the info for a performance.measure calls correctly', () => {\n const performanceMeasures = traceData.UserTimings.performanceMeasures;\n const highlightedEntryInfo = timingsTrackAppender.highlightedEntryInfo(performanceMeasures[0]);\n // The i18n encodes spaces using the u00A0 unicode character.\n assert.strictEqual(highlightedEntryInfo.formattedTime, ('500.07\\u00A0ms'));\n });\n\n it('returns the info for a console.time calls correctly', () => {\n const consoleTimings = traceData.UserTimings.consoleTimings;\n const highlightedEntryInfo = timingsTrackAppender.highlightedEntryInfo(consoleTimings[0]);\n // The i18n encodes spaces using the u00A0 unicode character.\n assert.strictEqual(highlightedEntryInfo.formattedTime, ('1.60\\u00A0s'));\n });\n });\n\n describe('extension markers', () => {\n beforeEach(async function() {\n entryData = [];\n flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n entryTypeByLevel = [];\n ({traceData} = await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz'));\n timingsTrackAppender = initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel);\n timingsTrackAppender.appendTrackAtLevel(0);\n // Rather than use the real colours here and burden the test with having to\n // inject loads of CSS, we fake out the colours. this is fine for our tests as\n // the exact value of the colours is not important; we just make sure that it\n // parses them out correctly. Each variable is given a different rgb() value to\n // ensure we know the code is working and using the right one.\n const styleElement = document.createElement('style');\n styleElement.id = 'fake-perf-panel-colors';\n styleElement.textContent = `\n :root {\n --ref-palette-primary70: rgb(4 4 4);\n --ref-palette-error50: rgb(10 10 10);\n }\n `;\n document.documentElement.appendChild(styleElement);\n ThemeSupport.ThemeSupport.clearThemeCache();\n });\n afterEach(() => {\n entryData = [];\n flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n entryTypeByLevel = [];\n const styleElementToRemove = document.documentElement.querySelector('#fake-perf-panel-colors');\n if (styleElementToRemove) {\n document.documentElement.removeChild(styleElementToRemove);\n }\n ThemeSupport.ThemeSupport.clearThemeCache();\n });\n\n it('creates a TimelineFlameChartMarker for each extension marker event in a trace', () => {\n const extensionMarkers = traceData.ExtensionTraceData.extensionMarkers;\n for (const traceMarker of extensionMarkers) {\n const markerTimeMs = TraceModel.Helpers.Timing.microSecondsToMilliseconds(traceMarker.ts);\n const flameChartMarker =\n flameChartData.markers.find(flameChartMarker => flameChartMarker.startTime() === markerTimeMs);\n assert.exists(flameChartMarker);\n }\n });\n\n it('returns the correct color and title for extension markers', function() {\n const extensionMarkers = traceData.ExtensionTraceData.extensionMarkers;\n for (const event of extensionMarkers) {\n assert.strictEqual(timingsTrackAppender.titleForEvent(event), event.name);\n if (event.args.color === 'error') {\n // \"error\" color category is mapped to --ref-palette-error50\n // which is faked out to 10, 10, 10\n assert.strictEqual(timingsTrackAppender.colorForEvent(event), 'rgb(10 10 10)');\n } else {\n // Unknown colors are mapped to \"primary\" by default, and\n // \"primary\" color category is mapped to --ref-palette-primary70\n // which is faked out to 4, 4, 4\n assert.strictEqual(timingsTrackAppender.colorForEvent(event), 'rgb(4 4 4)');\n }\n }\n });\n it('sets a default value when a color is not set or is set an unknown value', function() {\n const mockExtensionEntryNoColor = {\n args: {\n dataType: 'marker',\n },\n cat: 'devtools.extension',\n } as unknown as TraceModel.Types.TraceEvents.TraceEventData;\n\n const mockExtensionEntryUnknownColor = {\n args: {\n color: 'anUnknownColor',\n dataType: 'marker',\n },\n cat: 'devtools.extension',\n } as unknown as TraceModel.Types.TraceEvents.TraceEventData;\n // \"primary\" color category is mapped to --ref-palette-primary70\n // which is faked out to 4, 4, 4\n assert.strictEqual(timingsTrackAppender.colorForEvent(mockExtensionEntryNoColor), 'rgb(4 4 4)');\n assert.strictEqual(timingsTrackAppender.colorForEvent(mockExtensionEntryUnknownColor), 'rgb(4 4 4)');\n });\n it('returns the tool tip info for an entry correctly', function() {\n const extensionMarker = traceData.ExtensionTraceData.extensionMarkers.at(0);\n assert.isOk(extensionMarker, 'did not find any extension markers');\n\n const highlightedEntryInfo = timingsTrackAppender.highlightedEntryInfo(extensionMarker);\n assert.strictEqual(highlightedEntryInfo.title, 'A mark');\n });\n describe('toggling', function() {\n it('Does not append extension data when the configuration is set to disabled', async function() {\n Timeline.ExtensionDataGatherer.ExtensionDataGatherer.removeInstance();\n entryData = [];\n flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n entryTypeByLevel = [];\n Timeline.TimelinePanel.TimelinePanel.extensionDataVisibilitySetting().set(false);\n traceData = (await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz')).traceData;\n timingsTrackAppender = initTrackAppender(flameChartData, traceData, entryData, entryTypeByLevel);\n timingsTrackAppender.appendTrackAtLevel(0);\n\n const extensionMarkers = traceData.ExtensionTraceData.extensionMarkers;\n for (const traceMarker of extensionMarkers) {\n const markerTimeMs = TraceModel.Helpers.Timing.microSecondsToMilliseconds(traceMarker.ts);\n const flameChartMarker =\n flameChartData.markers.find(flameChartMarker => flameChartMarker.startTime() === markerTimeMs);\n assert.isUndefined(flameChartMarker);\n }\n });\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"TimingsTrackAppender.test.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/track_appenders/TimingsTrackAppender.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../../models/trace/trace.js';\nimport {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../testing/TraceLoader.js';\nimport * as PerfUI from '../../../ui/legacy/components/perf_ui/perf_ui.js';\nimport * as ThemeSupport from '../../../ui/legacy/theme_support/theme_support.js';\nimport * as Timeline from '../timeline.js';\n\nfunction initTrackAppender(\n flameChartData: PerfUI.FlameChart.FlameChartTimelineData,\n parsedTrace: Trace.Handlers.Types.ParsedTrace,\n entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[],\n entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[],\n ): Timeline.TimingsTrackAppender.TimingsTrackAppender {\n Timeline.ExtensionDataGatherer.ExtensionDataGatherer.instance().modelChanged(parsedTrace);\n const compatibilityTracksAppender = new Timeline.CompatibilityTracksAppender.CompatibilityTracksAppender(\n flameChartData, parsedTrace, entryData, entryTypeByLevel);\n return compatibilityTracksAppender.timingsTrackAppender();\n}\n\ndescribeWithEnvironment('TimingTrackAppender', function() {\n let parsedTrace: Trace.Handlers.Types.ParsedTrace;\n let timingsTrackAppender: Timeline.TimingsTrackAppender.TimingsTrackAppender;\n let entryData: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartEntry[] = [];\n let flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n let entryTypeByLevel: Timeline.TimelineFlameChartDataProvider.EntryType[] = [];\n beforeEach(async function() {\n ({parsedTrace} = await TraceLoader.traceEngine(this, 'timings-track.json.gz'));\n timingsTrackAppender = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel);\n timingsTrackAppender.appendTrackAtLevel(0);\n });\n afterEach(() => {\n entryData = [];\n flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n entryTypeByLevel = [];\n });\n\n describe('appendTrackAtLevel', () => {\n it('marks all levels used by the track with the `TrackAppender` type', () => {\n // 8 levels should be taken:\n // * 1 for page load marks.\n // * 1 performance.marks.\n // * 3 used by performance.measures.\n // * 1 used by console timestamps.\n // * 1 used by console.time calls.\n const levelCount = 7;\n assert.strictEqual(entryTypeByLevel.length, levelCount);\n const allEntriesAreTrackAppender =\n entryTypeByLevel.every(type => type === Timeline.TimelineFlameChartDataProvider.EntryType.TRACK_APPENDER);\n assert.isTrue(allEntriesAreTrackAppender);\n });\n it('creates a flamechart group for the timings track', () => {\n assert.strictEqual(flameChartData.groups.length, 1);\n assert.strictEqual(flameChartData.groups[0].name, 'Timings');\n });\n it('populates the markers array in ascendent order', () => {\n const traceMarkers = parsedTrace.PageLoadMetrics.allMarkerEvents;\n assert.strictEqual(flameChartData.markers.length, traceMarkers.length);\n for (let i = 1; i < flameChartData.markers.length; i++) {\n assert.isAtLeast(flameChartData.markers[i].startTime(), flameChartData.markers[i - 1].startTime());\n }\n });\n it('creates a TimelineFlameChartMarker for each page load marker event in a trace', () => {\n const traceMarkers = parsedTrace.PageLoadMetrics.allMarkerEvents;\n assert.strictEqual(flameChartData.markers.length, traceMarkers.length);\n for (const traceMarker of traceMarkers) {\n const markerTimeMs = Trace.Helpers.Timing.microSecondsToMilliseconds(traceMarker.ts);\n const flameChartMarker =\n flameChartData.markers.find(flameChartMarker => flameChartMarker.startTime() === markerTimeMs);\n assert.exists(flameChartMarker);\n }\n assert.strictEqual(flameChartData.markers.length, traceMarkers.length);\n });\n it('adds start times correctly', () => {\n const traceMarkers = parsedTrace.PageLoadMetrics.allMarkerEvents;\n const performanceMarks = parsedTrace.UserTimings.performanceMarks;\n const performanceMeasures = parsedTrace.UserTimings.performanceMeasures;\n const consoleTimings = parsedTrace.UserTimings.consoleTimings;\n const consoleTimestamps = parsedTrace.UserTimings.timestampEvents;\n for (const event\n of [...traceMarkers, ...performanceMarks, ...performanceMeasures, ...consoleTimings,\n ...consoleTimestamps]) {\n const markerIndex = entryData.indexOf(event);\n assert.exists(markerIndex);\n assert.strictEqual(\n flameChartData.entryStartTimes[markerIndex], Trace.Helpers.Timing.microSecondsToMilliseconds(event.ts));\n }\n });\n it('adds total times correctly', () => {\n const traceMarkers = parsedTrace.PageLoadMetrics.allMarkerEvents;\n const performanceMarks = parsedTrace.UserTimings.performanceMarks;\n const performanceMeasures = parsedTrace.UserTimings.performanceMeasures;\n const consoleTimings = parsedTrace.UserTimings.consoleTimings;\n const consoleTimestamps = parsedTrace.UserTimings.timestampEvents;\n for (const event\n of [...traceMarkers, ...performanceMarks, ...performanceMeasures, ...consoleTimings,\n ...consoleTimestamps]) {\n const markerIndex = entryData.indexOf(event);\n assert.exists(markerIndex);\n if (Trace.Types.Events.isMarkerEvent(event)) {\n assert.isNaN(flameChartData.entryTotalTimes[markerIndex]);\n continue;\n }\n const expectedTotalTimeForEvent = event.dur ?\n Trace.Helpers.Timing.microSecondsToMilliseconds(event.dur) :\n Timeline.TimelineFlameChartDataProvider.InstantEventVisibleDurationMs;\n assert.strictEqual(flameChartData.entryTotalTimes[markerIndex], expectedTotalTimeForEvent);\n }\n });\n });\n\n it('orders page load metrics that have the same timestamp', async function() {\n entryData = [];\n flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n entryTypeByLevel = [];\n // animation.json.gz has FP, FCP and LCP at the same timestamp, and we want\n // to make sure visually the markers are ordered [FP][FCP][LCP].\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'animation.json.gz');\n timingsTrackAppender = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel);\n timingsTrackAppender.appendTrackAtLevel(0);\n const {allMarkerEvents} = parsedTrace.PageLoadMetrics;\n\n const firstPaint = allMarkerEvents.find(Trace.Types.Events.isFirstPaint);\n const fcp = allMarkerEvents.find(Trace.Types.Events.isFirstContentfulPaint);\n const lcp = allMarkerEvents.find(Trace.Types.Events.isLargestContentfulPaintCandidate);\n\n assert.isOk(firstPaint);\n assert.isOk(fcp);\n assert.isOk(lcp);\n\n // Prevent against the trace changing by ensuring all these events have the same timestamp.\n assert.isTrue(firstPaint.ts === fcp.ts && fcp.ts === lcp.ts);\n\n const indexes = [firstPaint, fcp, lcp].map(entry => entryData.indexOf(entry));\n // Because of how we order page markers, we expect the indexes to be in\n // this order which represents the visual order they are represented.\n // (0, 1, 2) are this traces navigation start, DCL and Load event.\n assert.deepEqual(indexes, [3, 4, 5]);\n });\n\n describe('colorForEvent and titleForEvent', () => {\n it('returns the correct color and title for page load markers', () => {\n const traceMarkers = parsedTrace.PageLoadMetrics.allMarkerEvents;\n const firstContentfulPaint = traceMarkers.find(marker => marker.name === 'firstContentfulPaint');\n const markLoad = traceMarkers.find(marker => marker.name === 'MarkLoad');\n const markDOMContent = traceMarkers.find(marker => marker.name === 'MarkDOMContent');\n const firstPaint = traceMarkers.find(marker => marker.name === 'firstPaint');\n const largestContentfulPaint = traceMarkers.find(marker => marker.name === 'largestContentfulPaint::Candidate');\n\n if (firstContentfulPaint === undefined || markLoad === undefined || markDOMContent === undefined ||\n firstPaint === undefined || largestContentfulPaint === undefined) {\n throw new Error('A metric was not found');\n }\n\n assert.strictEqual(timingsTrackAppender.colorForEvent(firstContentfulPaint), '#1A6937');\n assert.strictEqual(\n timingsTrackAppender.titleForEvent(firstContentfulPaint),\n Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FCP);\n\n assert.strictEqual(timingsTrackAppender.colorForEvent(markLoad), '#B31412');\n assert.strictEqual(\n timingsTrackAppender.titleForEvent(markLoad), Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.L);\n\n assert.strictEqual(timingsTrackAppender.colorForEvent(markDOMContent), '#0867CB');\n assert.strictEqual(\n timingsTrackAppender.titleForEvent(markDOMContent),\n Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.DCL);\n\n assert.strictEqual(timingsTrackAppender.colorForEvent(firstPaint), '#228847');\n assert.strictEqual(\n timingsTrackAppender.titleForEvent(firstPaint), Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.FP);\n\n assert.strictEqual(timingsTrackAppender.colorForEvent(largestContentfulPaint), '#1A3422');\n assert.strictEqual(\n timingsTrackAppender.titleForEvent(largestContentfulPaint),\n Trace.Handlers.ModelHandlers.PageLoadMetrics.MetricName.LCP);\n });\n\n it('returns the correct title for performance measures', () => {\n const performanceMeasures = parsedTrace.UserTimings.performanceMeasures;\n for (const measure of performanceMeasures) {\n assert.strictEqual(timingsTrackAppender.titleForEvent(measure), measure.name);\n }\n });\n\n it('returns the correct title for console timings', () => {\n const traceMarkers = parsedTrace.UserTimings.consoleTimings;\n for (const mark of traceMarkers) {\n assert.strictEqual(timingsTrackAppender.titleForEvent(mark), mark.name);\n }\n });\n\n it('returns the correct title for performance marks', () => {\n const traceMarkers = parsedTrace.UserTimings.performanceMarks;\n for (const mark of traceMarkers) {\n assert.strictEqual(timingsTrackAppender.titleForEvent(mark), `[mark]: ${mark.name}`);\n }\n });\n\n it('returns the correct title for console timestamps', () => {\n const traceMarkers = parsedTrace.UserTimings.timestampEvents;\n for (const mark of traceMarkers) {\n assert.strictEqual(timingsTrackAppender.titleForEvent(mark), `TimeStamp: ${mark.args.data.message}`);\n }\n });\n });\n\n describe('highlightedEntryInfo', () => {\n it('shows the time of the mark, not the duration, if the event is a performance mark', () => {\n const firstMark = parsedTrace.UserTimings.performanceMarks[0];\n const highlightedEntryInfo = timingsTrackAppender.highlightedEntryInfo(firstMark);\n assert.deepEqual(highlightedEntryInfo, {\n title: '[mark]: myMark',\n formattedTime: '1.12\\u00A0s',\n });\n });\n\n it('shows the time of the mark for an LCP event', () => {\n const largestContentfulPaint = parsedTrace.PageLoadMetrics.allMarkerEvents.find(\n marker => marker.name === 'largestContentfulPaint::Candidate');\n if (!largestContentfulPaint) {\n throw new Error('Could not find LCP event');\n }\n const highlightedEntryInfo = timingsTrackAppender.highlightedEntryInfo(largestContentfulPaint);\n assert.deepEqual(highlightedEntryInfo, {\n title: 'LCP',\n formattedTime: '2.42\\u00A0s',\n });\n });\n\n it('shows the time of the mark for an FCP event', () => {\n const firstContentfulPaint =\n parsedTrace.PageLoadMetrics.allMarkerEvents.find(marker => marker.name === 'firstContentfulPaint');\n if (!firstContentfulPaint) {\n throw new Error('Could not find FCP event');\n }\n const highlightedEntryInfo = timingsTrackAppender.highlightedEntryInfo(firstContentfulPaint);\n assert.deepEqual(highlightedEntryInfo, {\n title: 'FCP',\n formattedTime: '2.42\\u00A0s',\n });\n });\n\n it('shows the time of the mark for a DCL event', () => {\n const dclEvent = parsedTrace.PageLoadMetrics.allMarkerEvents.find(marker => marker.name === 'MarkDOMContent');\n if (!dclEvent) {\n throw new Error('Could not find DCL event');\n }\n const highlightedEntryInfo = timingsTrackAppender.highlightedEntryInfo(dclEvent);\n assert.deepEqual(highlightedEntryInfo, {\n title: 'DCL',\n formattedTime: '2.42\\u00A0s',\n });\n });\n\n it('shows the time of a console.timestamp event in the hover info', () => {\n const timestampEvent = parsedTrace.UserTimings.timestampEvents[0];\n const highlightedEntryInfo = timingsTrackAppender.highlightedEntryInfo(timestampEvent);\n\n assert.deepEqual(highlightedEntryInfo, {\n title: 'TimeStamp: a timestamp',\n formattedTime: '615.25\\u00A0ms',\n });\n });\n\n it('returns the info for a performance.measure calls correctly', () => {\n const performanceMeasures = parsedTrace.UserTimings.performanceMeasures;\n const highlightedEntryInfo = timingsTrackAppender.highlightedEntryInfo(performanceMeasures[0]);\n // The i18n encodes spaces using the u00A0 unicode character.\n assert.strictEqual(highlightedEntryInfo.formattedTime, ('500.07\\u00A0ms'));\n });\n\n it('returns the info for a console.time calls correctly', () => {\n const consoleTimings = parsedTrace.UserTimings.consoleTimings;\n const highlightedEntryInfo = timingsTrackAppender.highlightedEntryInfo(consoleTimings[0]);\n // The i18n encodes spaces using the u00A0 unicode character.\n assert.strictEqual(highlightedEntryInfo.formattedTime, ('1.60\\u00A0s'));\n });\n });\n\n describe('extension markers', () => {\n beforeEach(async function() {\n entryData = [];\n flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n entryTypeByLevel = [];\n ({parsedTrace} = await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz'));\n timingsTrackAppender = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel);\n timingsTrackAppender.appendTrackAtLevel(0);\n // Rather than use the real colours here and burden the test with having to\n // inject loads of CSS, we fake out the colours. this is fine for our tests as\n // the exact value of the colours is not important; we just make sure that it\n // parses them out correctly. Each variable is given a different rgb() value to\n // ensure we know the code is working and using the right one.\n const styleElement = document.createElement('style');\n styleElement.id = 'fake-perf-panel-colors';\n styleElement.textContent = `\n :root {\n --ref-palette-primary70: rgb(4 4 4);\n --ref-palette-error50: rgb(10 10 10);\n }\n `;\n document.documentElement.appendChild(styleElement);\n ThemeSupport.ThemeSupport.clearThemeCache();\n });\n afterEach(() => {\n entryData = [];\n flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n entryTypeByLevel = [];\n const styleElementToRemove = document.documentElement.querySelector('#fake-perf-panel-colors');\n if (styleElementToRemove) {\n document.documentElement.removeChild(styleElementToRemove);\n }\n ThemeSupport.ThemeSupport.clearThemeCache();\n });\n\n it('creates a TimelineFlameChartMarker for each extension marker event in a trace', () => {\n const extensionMarkers = parsedTrace.ExtensionTraceData.extensionMarkers;\n for (const traceMarker of extensionMarkers) {\n const markerTimeMs = Trace.Helpers.Timing.microSecondsToMilliseconds(traceMarker.ts);\n const flameChartMarker =\n flameChartData.markers.find(flameChartMarker => flameChartMarker.startTime() === markerTimeMs);\n assert.exists(flameChartMarker);\n }\n });\n\n it('returns the correct color and title for extension markers', function() {\n const extensionMarkers = parsedTrace.ExtensionTraceData.extensionMarkers;\n for (const event of extensionMarkers) {\n assert.strictEqual(timingsTrackAppender.titleForEvent(event), event.name);\n if (event.args.color === 'error') {\n // \"error\" color category is mapped to --ref-palette-error50\n // which is faked out to 10, 10, 10\n assert.strictEqual(timingsTrackAppender.colorForEvent(event), 'rgb(10 10 10)');\n } else {\n // Unknown colors are mapped to \"primary\" by default, and\n // \"primary\" color category is mapped to --ref-palette-primary70\n // which is faked out to 4, 4, 4\n assert.strictEqual(timingsTrackAppender.colorForEvent(event), 'rgb(4 4 4)');\n }\n }\n });\n it('sets a default value when a color is not set or is set an unknown value', function() {\n const mockExtensionEntryNoColor = {\n args: {\n dataType: 'marker',\n },\n cat: 'devtools.extension',\n } as unknown as Trace.Types.Events.Event;\n\n const mockExtensionEntryUnknownColor = {\n args: {\n color: 'anUnknownColor',\n dataType: 'marker',\n },\n cat: 'devtools.extension',\n } as unknown as Trace.Types.Events.Event;\n // \"primary\" color category is mapped to --ref-palette-primary70\n // which is faked out to 4, 4, 4\n assert.strictEqual(timingsTrackAppender.colorForEvent(mockExtensionEntryNoColor), 'rgb(4 4 4)');\n assert.strictEqual(timingsTrackAppender.colorForEvent(mockExtensionEntryUnknownColor), 'rgb(4 4 4)');\n });\n it('returns the tool tip info for an entry correctly', function() {\n const extensionMarker = parsedTrace.ExtensionTraceData.extensionMarkers.at(0);\n assert.isOk(extensionMarker, 'did not find any extension markers');\n\n const highlightedEntryInfo = timingsTrackAppender.highlightedEntryInfo(extensionMarker);\n assert.strictEqual(highlightedEntryInfo.title, 'A mark');\n });\n describe('toggling', function() {\n it('Does not append extension data when the configuration is set to disabled', async function() {\n Timeline.ExtensionDataGatherer.ExtensionDataGatherer.removeInstance();\n entryData = [];\n flameChartData = PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n entryTypeByLevel = [];\n Timeline.TimelinePanel.TimelinePanel.extensionDataVisibilitySetting().set(false);\n parsedTrace = (await TraceLoader.traceEngine(this, 'extension-tracks-and-marks.json.gz')).parsedTrace;\n timingsTrackAppender = initTrackAppender(flameChartData, parsedTrace, entryData, entryTypeByLevel);\n timingsTrackAppender.appendTrackAtLevel(0);\n\n const extensionMarkers = parsedTrace.ExtensionTraceData.extensionMarkers;\n for (const traceMarker of extensionMarkers) {\n const markerTimeMs = Trace.Helpers.Timing.microSecondsToMilliseconds(traceMarker.ts);\n const flameChartMarker =\n flameChartData.markers.find(flameChartMarker => flameChartMarker.startTime() === markerTimeMs);\n assert.isUndefined(flameChartMarker);\n }\n });\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/panels/timeline/unittests-tsconfig.json b/public/panels/timeline/unittests-tsconfig.json index 2bed592bd..26a5d9834 100644 --- a/public/panels/timeline/unittests-tsconfig.json +++ b/public/panels/timeline/unittests-tsconfig.json @@ -38,6 +38,7 @@ "useUnknownInCatchVariables": false }, "files": [ + "../../../../../../front_end/panels/timeline/AnnotationHelpers.test.ts", "../../../../../../front_end/panels/timeline/Breadcrumbs.test.ts", "../../../../../../front_end/panels/timeline/EntriesFilter.test.ts", "../../../../../../front_end/panels/timeline/EventsSerializer.test.ts", diff --git a/public/panels/timeline/utils/NetworkRequest.d.ts b/public/panels/timeline/utils/NetworkRequest.d.ts index cadd44d2a..c32f0ddfe 100644 --- a/public/panels/timeline/utils/NetworkRequest.d.ts +++ b/public/panels/timeline/utils/NetworkRequest.d.ts @@ -1,7 +1,7 @@ import type * as SDK from '../../../core/sdk/sdk.js'; -import type * as TraceEngine from '../../../models/trace/trace.js'; -export declare function getNetworkRequest(syntheticNetworkRequest: TraceEngine.Types.TraceEvents.SyntheticNetworkRequest): SDK.NetworkRequest.NetworkRequest | undefined | null; -export declare function createTimelineNetworkRequest(syntheticNetworkRequest: TraceEngine.Types.TraceEvents.SyntheticNetworkRequest): TimelineNetworkRequest | null; +import type * as Trace from '../../../models/trace/trace.js'; +export declare function getNetworkRequest(syntheticNetworkRequest: Trace.Types.Events.SyntheticNetworkRequest): SDK.NetworkRequest.NetworkRequest | undefined | null; +export declare function createTimelineNetworkRequest(syntheticNetworkRequest: Trace.Types.Events.SyntheticNetworkRequest): TimelineNetworkRequest | null; export declare class TimelineNetworkRequest { #private; constructor(request: SDK.NetworkRequest.NetworkRequest); diff --git a/public/panels/timeline/utils/NetworkRequest.js.map b/public/panels/timeline/utils/NetworkRequest.js.map index d72d43785..aaf316f47 100644 --- a/public/panels/timeline/utils/NetworkRequest.js.map +++ b/public/panels/timeline/utils/NetworkRequest.js.map @@ -1 +1 @@ -{"version":3,"file":"NetworkRequest.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/utils/NetworkRequest.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAC7B,OAAO,KAAK,MAAM,MAAM,gCAAgC,CAAC;AAGzD,OAAO,KAAK,QAAQ,MAAM,sCAAsC,CAAC;AAGjE,MAAM,UAAU,iBAAiB,CAAC,uBAA8E;IAE9G,MAAM,GAAG,GAAG,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAsC,CAAC;IACrF,MAAM,cAAc,GAAG,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,cAAc,CAAC,GAAG,CAAoC,CAAC;IACzG,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,aAAa,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;IACrH,OAAO,QAAQ,EAAE,OAAO,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,4BAA4B,CACxC,uBAA8E;IAChF,MAAM,OAAO,GAAG,iBAAiB,CAAC,uBAAuB,CAAC,CAAC;IAC3D,OAAO,OAAO,CAAC,CAAC,CAAC,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9D,CAAC;AAED,4BAA4B;AAC5B,kHAAkH;AAClH,8FAA8F;AAC9F,qHAAqH;AACrH,wHAAwH;AACxH,oHAAoH;AACpH,yBAAyB;AACzB,MAAM,OAAO,sBAAsB;IACjC,QAAQ,CAAoC;IAC5C,YAAY,OAA0C;QACpD,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;IAC1B,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as Common from '../../../core/common/common.js';\nimport type * as Platform from '../../../core/platform/platform.js';\nimport type * as SDK from '../../../core/sdk/sdk.js';\nimport * as Bindings from '../../../models/bindings/bindings.js';\nimport type * as TraceEngine from '../../../models/trace/trace.js';\n\nexport function getNetworkRequest(syntheticNetworkRequest: TraceEngine.Types.TraceEvents.SyntheticNetworkRequest):\n SDK.NetworkRequest.NetworkRequest|undefined|null {\n const url = syntheticNetworkRequest.args.data.url as Platform.DevToolsPath.UrlString;\n const urlWithoutHash = Common.ParsedURL.ParsedURL.urlWithoutHash(url) as Platform.DevToolsPath.UrlString;\n const resource = Bindings.ResourceUtils.resourceForURL(url) || Bindings.ResourceUtils.resourceForURL(urlWithoutHash);\n return resource?.request;\n}\n\nexport function createTimelineNetworkRequest(\n syntheticNetworkRequest: TraceEngine.Types.TraceEvents.SyntheticNetworkRequest): TimelineNetworkRequest|null {\n const request = getNetworkRequest(syntheticNetworkRequest);\n return request ? new TimelineNetworkRequest(request) : null;\n}\n\n// Add a wrapper class here.\n// The reason is the `Reveal in Network panel` option is handled by the context menu provider, which will add this\n// option for all supporting types. And there are a lot of context menu providers that support\n// `SDK.NetworkRequest.NetworkRequest`, for example `Override content` by PersistenceActions, but we so far just want\n// the one to reveal in network panel, so add a new class which will only be supported by Network panel. Also we want to\n// have a different behavior(select the network request) from the `SDK.NetworkRequest.NetworkRequest` (highlight the\n// network request once).\nexport class TimelineNetworkRequest {\n #request: SDK.NetworkRequest.NetworkRequest;\n constructor(request: SDK.NetworkRequest.NetworkRequest) {\n this.#request = request;\n }\n\n get request(): SDK.NetworkRequest.NetworkRequest {\n return this.#request;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"NetworkRequest.js","sourceRoot":"","sources":["../../../../../../../front_end/panels/timeline/utils/NetworkRequest.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAC7B,OAAO,KAAK,MAAM,MAAM,gCAAgC,CAAC;AAGzD,OAAO,KAAK,QAAQ,MAAM,sCAAsC,CAAC;AAGjE,MAAM,UAAU,iBAAiB,CAAC,uBAAmE;IAEnG,MAAM,GAAG,GAAG,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAsC,CAAC;IACrF,MAAM,cAAc,GAAG,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,cAAc,CAAC,GAAG,CAAoC,CAAC;IACzG,MAAM,QAAQ,GAAG,QAAQ,CAAC,aAAa,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,aAAa,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;IACrH,OAAO,QAAQ,EAAE,OAAO,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,4BAA4B,CAAC,uBAAmE;IAE9G,MAAM,OAAO,GAAG,iBAAiB,CAAC,uBAAuB,CAAC,CAAC;IAC3D,OAAO,OAAO,CAAC,CAAC,CAAC,IAAI,sBAAsB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC9D,CAAC;AAED,4BAA4B;AAC5B,kHAAkH;AAClH,8FAA8F;AAC9F,qHAAqH;AACrH,wHAAwH;AACxH,oHAAoH;AACpH,yBAAyB;AACzB,MAAM,OAAO,sBAAsB;IACjC,QAAQ,CAAoC;IAC5C,YAAY,OAA0C;QACpD,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC;IAC1B,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;CACF","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as Common from '../../../core/common/common.js';\nimport type * as Platform from '../../../core/platform/platform.js';\nimport type * as SDK from '../../../core/sdk/sdk.js';\nimport * as Bindings from '../../../models/bindings/bindings.js';\nimport type * as Trace from '../../../models/trace/trace.js';\n\nexport function getNetworkRequest(syntheticNetworkRequest: Trace.Types.Events.SyntheticNetworkRequest):\n SDK.NetworkRequest.NetworkRequest|undefined|null {\n const url = syntheticNetworkRequest.args.data.url as Platform.DevToolsPath.UrlString;\n const urlWithoutHash = Common.ParsedURL.ParsedURL.urlWithoutHash(url) as Platform.DevToolsPath.UrlString;\n const resource = Bindings.ResourceUtils.resourceForURL(url) || Bindings.ResourceUtils.resourceForURL(urlWithoutHash);\n return resource?.request;\n}\n\nexport function createTimelineNetworkRequest(syntheticNetworkRequest: Trace.Types.Events.SyntheticNetworkRequest):\n TimelineNetworkRequest|null {\n const request = getNetworkRequest(syntheticNetworkRequest);\n return request ? new TimelineNetworkRequest(request) : null;\n}\n\n// Add a wrapper class here.\n// The reason is the `Reveal in Network panel` option is handled by the context menu provider, which will add this\n// option for all supporting types. And there are a lot of context menu providers that support\n// `SDK.NetworkRequest.NetworkRequest`, for example `Override content` by PersistenceActions, but we so far just want\n// the one to reveal in network panel, so add a new class which will only be supported by Network panel. Also we want to\n// have a different behavior(select the network request) from the `SDK.NetworkRequest.NetworkRequest` (highlight the\n// network request once).\nexport class TimelineNetworkRequest {\n #request: SDK.NetworkRequest.NetworkRequest;\n constructor(request: SDK.NetworkRequest.NetworkRequest) {\n this.#request = request;\n }\n\n get request(): SDK.NetworkRequest.NetworkRequest {\n return this.#request;\n }\n}\n"]} \ No newline at end of file diff --git a/public/services/trace_bounds/TraceBounds.d.ts b/public/services/trace_bounds/TraceBounds.d.ts index 03cc86a69..53caae9e6 100644 --- a/public/services/trace_bounds/TraceBounds.d.ts +++ b/public/services/trace_bounds/TraceBounds.d.ts @@ -1,4 +1,4 @@ -import * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; export declare class StateChangedEvent extends Event { state: Readonly; updateType: 'RESET' | 'MINIMAP_BOUNDS' | 'VISIBLE_WINDOW'; @@ -13,15 +13,15 @@ export declare class StateChangedEvent extends Event { export declare function onChange(cb: (event: StateChangedEvent) => void): void; export declare function removeListener(cb: (event: StateChangedEvent) => void): void; export interface State { - readonly micro: Readonly>; - readonly milli: Readonly>; + readonly micro: Readonly>; + readonly milli: Readonly>; } -export interface TraceWindows { +export interface TraceWindows { /** * This is the bounds of the entire trace. Once a trace is imported/recorded * and this is set, it cannot be changed. */ - readonly entireTraceBounds: TraceEngine.Types.Timing.TraceWindow; + readonly entireTraceBounds: Trace.Types.Timing.TraceWindow; /** * This is the bounds of the minimap and represents the left and right bound * being shown by the minimap. It can be changed by a user action: for @@ -31,7 +31,7 @@ export interface TraceWindows; + minimapTraceBounds: Trace.Types.Timing.TraceWindow; /** * This represents the trace window that is being shown on the main timeline. * The reason this is called a "Window" rather than "Bounds" is because the @@ -41,7 +41,7 @@ export interface TraceWindows; + timelineTraceWindow: Trace.Types.Timing.TraceWindow; } export declare class BoundsManager extends EventTarget { #private; @@ -50,9 +50,9 @@ export declare class BoundsManager extends EventTarget { }): BoundsManager; static removeInstance(): void; private constructor(); - resetWithNewBounds(initialBounds: TraceEngine.Types.Timing.TraceWindowMicroSeconds): this; + resetWithNewBounds(initialBounds: Trace.Types.Timing.TraceWindowMicroSeconds): this; state(): Readonly | null; - setMiniMapBounds(newBounds: TraceEngine.Types.Timing.TraceWindowMicroSeconds): void; + setMiniMapBounds(newBounds: Trace.Types.Timing.TraceWindowMicroSeconds): void; /** * Updates the visible part of the trace that the user can see. * @param options.ignoreMiniMapBounds - by default the visible window will be @@ -61,7 +61,7 @@ export declare class BoundsManager extends EventTarget { * with this! Unless you deal with this situation, the UI of the performance * panel will break. */ - setTimelineVisibleWindow(newWindow: TraceEngine.Types.Timing.TraceWindowMicroSeconds, options?: { + setTimelineVisibleWindow(newWindow: Trace.Types.Timing.TraceWindowMicroSeconds, options?: { shouldAnimate?: boolean; ignoreMiniMapBounds?: boolean; }): void; diff --git a/public/services/trace_bounds/TraceBounds.js b/public/services/trace_bounds/TraceBounds.js index 89bea4c28..970281dd6 100644 --- a/public/services/trace_bounds/TraceBounds.js +++ b/public/services/trace_bounds/TraceBounds.js @@ -1,7 +1,7 @@ // 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 * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; let instance = null; export class StateChangedEvent extends Event { state; @@ -55,9 +55,9 @@ export class BoundsManager extends EventTarget { if (this.#currentState === null) { return null; } - const entireBoundsMilli = TraceEngine.Helpers.Timing.traceWindowMilliSeconds(this.#currentState.entireTraceBounds); - const minimapBoundsMilli = TraceEngine.Helpers.Timing.traceWindowMilliSeconds(this.#currentState.minimapTraceBounds); - const timelineTraceWindowMilli = TraceEngine.Helpers.Timing.traceWindowMilliSeconds(this.#currentState.timelineTraceWindow); + const entireBoundsMilli = Trace.Helpers.Timing.traceWindowMilliSeconds(this.#currentState.entireTraceBounds); + const minimapBoundsMilli = Trace.Helpers.Timing.traceWindowMilliSeconds(this.#currentState.minimapTraceBounds); + const timelineTraceWindowMilli = Trace.Helpers.Timing.traceWindowMilliSeconds(this.#currentState.timelineTraceWindow); return { micro: this.#currentState, milli: { @@ -118,9 +118,9 @@ export class BoundsManager extends EventTarget { if (!options.ignoreMiniMapBounds) { // Ensure that the setTimelineVisibleWindow can never go outside the bounds of the minimap bounds. newWindow.min = - TraceEngine.Types.Timing.MicroSeconds(Math.max(this.#currentState.minimapTraceBounds.min, newWindow.min)); + Trace.Types.Timing.MicroSeconds(Math.max(this.#currentState.minimapTraceBounds.min, newWindow.min)); newWindow.max = - TraceEngine.Types.Timing.MicroSeconds(Math.min(this.#currentState.minimapTraceBounds.max, newWindow.max)); + Trace.Types.Timing.MicroSeconds(Math.min(this.#currentState.minimapTraceBounds.max, newWindow.max)); } this.#currentState.timelineTraceWindow = newWindow; this.dispatchEvent(new StateChangedEvent(this.state(), 'VISIBLE_WINDOW', { shouldAnimate: options.shouldAnimate })); diff --git a/public/services/trace_bounds/TraceBounds.js.map b/public/services/trace_bounds/TraceBounds.js.map index 8f271604a..10dd56def 100644 --- a/public/services/trace_bounds/TraceBounds.js.map +++ b/public/services/trace_bounds/TraceBounds.js.map @@ -1 +1 @@ -{"version":3,"file":"TraceBounds.js","sourceRoot":"","sources":["../../../../../../front_end/services/trace_bounds/TraceBounds.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceEngine from '../../models/trace/trace.js';\n\nlet instance: BoundsManager|null = null;\n\nexport class StateChangedEvent extends Event {\n static readonly eventName = 'traceboundsstatechanged';\n constructor(\n public state: Readonly,\n public updateType: 'RESET'|'MINIMAP_BOUNDS'|'VISIBLE_WINDOW',\n public options: {\n shouldAnimate?: boolean,\n } = {shouldAnimate: false},\n ) {\n super(StateChangedEvent.eventName, {composed: true, bubbles: true});\n }\n}\n\n// Exposed as a shortcut to BoundsManager.instance().addEventListener, which\n// also takes care of type-casting the event to StateChangedEvent.\nexport function onChange(cb: (event: StateChangedEvent) => void): void {\n BoundsManager.instance().addEventListener(\n StateChangedEvent.eventName,\n // Cast the callback as TS doesn't know that these events will emit\n // StateChangedEvent types.\n cb as (event: Event) => void);\n}\n\nexport function removeListener(cb: (event: StateChangedEvent) => void): void {\n BoundsManager.instance().removeEventListener(StateChangedEvent.eventName, cb as (event: Event) => void);\n}\n\nexport interface State {\n readonly micro: Readonly>;\n readonly milli: Readonly>;\n}\n\nexport interface TraceWindows {\n /**\n * This is the bounds of the entire trace. Once a trace is imported/recorded\n * and this is set, it cannot be changed.\n */\n readonly entireTraceBounds: TraceEngine.Types.Timing.TraceWindow;\n /**\n * This is the bounds of the minimap and represents the left and right bound\n * being shown by the minimap. It can be changed by a user action: for\n * example, when a user creates a breadcrumb, that breadcrumb becomes the\n * minimap trace bounds. By default, and when a trace is first loaded, the\n * minimapTraceBounds are equivalent to the entireTraceBounds.\n * Note that this is NOT the active time window that the user has dragged\n * the minimap handles to; this is the min/max being shown by the minimap.\n */\n minimapTraceBounds: TraceEngine.Types.Timing.TraceWindow;\n /**\n * This represents the trace window that is being shown on the main timeline.\n * The reason this is called a \"Window\" rather than \"Bounds\" is because the\n * user is not bound by this value - they can use their mouse to pan/zoom\n * in/out beyond the limits of this window (the limit is the\n * minimapTraceBounds). Another way to think of this value is that the\n * min/max of this value is what is represented by the two drag handles on\n * the TimelineMiniMap that the user can drag to change their current window.\n */\n timelineTraceWindow: TraceEngine.Types.Timing.TraceWindow;\n}\n\nexport class BoundsManager extends EventTarget {\n static instance(opts: {\n forceNew: boolean|null,\n } = {forceNew: null}): BoundsManager {\n const forceNew = Boolean(opts.forceNew);\n if (!instance || forceNew) {\n instance = new BoundsManager();\n }\n return instance;\n }\n\n static removeInstance(): void {\n instance = null;\n }\n\n #currentState: TraceWindows|null = null;\n\n private constructor() {\n // Defined to enable us to mark it as Private.\n super();\n }\n\n resetWithNewBounds(initialBounds: TraceEngine.Types.Timing.TraceWindowMicroSeconds): this {\n this.#currentState = {\n entireTraceBounds: initialBounds,\n minimapTraceBounds: initialBounds,\n timelineTraceWindow: initialBounds,\n };\n this.dispatchEvent(new StateChangedEvent(this.state() as State, 'RESET'));\n return this;\n }\n\n state(): Readonly|null {\n if (this.#currentState === null) {\n return null;\n }\n const entireBoundsMilli = TraceEngine.Helpers.Timing.traceWindowMilliSeconds(this.#currentState.entireTraceBounds);\n const minimapBoundsMilli =\n TraceEngine.Helpers.Timing.traceWindowMilliSeconds(this.#currentState.minimapTraceBounds);\n const timelineTraceWindowMilli =\n TraceEngine.Helpers.Timing.traceWindowMilliSeconds(this.#currentState.timelineTraceWindow);\n\n return {\n micro: this.#currentState,\n milli: {\n entireTraceBounds: entireBoundsMilli,\n minimapTraceBounds: minimapBoundsMilli,\n timelineTraceWindow: timelineTraceWindowMilli,\n },\n };\n }\n\n setMiniMapBounds(newBounds: TraceEngine.Types.Timing.TraceWindowMicroSeconds): void {\n if (!this.#currentState) {\n // If we don't have the existing state and know the trace bounds, we\n // cannot set the minimap bounds.\n console.error('TraceBounds.setMiniMapBounds could not set bounds because there is no existing trace window set.');\n return;\n }\n const existingBounds = this.#currentState.minimapTraceBounds;\n if (newBounds.min === existingBounds.min && newBounds.max === existingBounds.max) {\n // New bounds are identical to the old ones so no action required.\n return;\n }\n\n if (newBounds.range < 1_000) {\n // Minimum minimap bounds range is 1 millisecond.\n return;\n }\n\n this.#currentState.minimapTraceBounds = newBounds;\n // this.state() cannot be null here.\n this.dispatchEvent(new StateChangedEvent(this.state() as State, 'MINIMAP_BOUNDS'));\n }\n\n /**\n * Updates the visible part of the trace that the user can see.\n * @param options.ignoreMiniMapBounds - by default the visible window will be\n * bound by the minimap bounds. If you set this to `true` then the timeline\n * visible window will not be constrained by the minimap bounds. Be careful\n * with this! Unless you deal with this situation, the UI of the performance\n * panel will break.\n */\n setTimelineVisibleWindow(newWindow: TraceEngine.Types.Timing.TraceWindowMicroSeconds, options: {\n shouldAnimate?: boolean,\n ignoreMiniMapBounds?: boolean,\n } = {\n shouldAnimate: false,\n ignoreMiniMapBounds: false,\n }): void {\n if (!this.#currentState) {\n // This is a weird state to be in: we can't change the visible timeline\n // window if we don't alreayd have an existing state with the trace\n // bounds set.\n console.error(\n 'TraceBounds.setTimelineVisibleWindow could not set bounds because there is no existing trace window set.');\n return;\n }\n const existingWindow = this.#currentState.timelineTraceWindow;\n if (newWindow.min === existingWindow.min && newWindow.max === existingWindow.max) {\n // New bounds are identical to the old ones so no action required.\n return;\n }\n\n if (newWindow.range < 1_000) {\n // Minimum timeline visible window range is 1 millisecond.\n return;\n }\n\n if (!options.ignoreMiniMapBounds) {\n // Ensure that the setTimelineVisibleWindow can never go outside the bounds of the minimap bounds.\n newWindow.min =\n TraceEngine.Types.Timing.MicroSeconds(Math.max(this.#currentState.minimapTraceBounds.min, newWindow.min));\n newWindow.max =\n TraceEngine.Types.Timing.MicroSeconds(Math.min(this.#currentState.minimapTraceBounds.max, newWindow.max));\n }\n\n this.#currentState.timelineTraceWindow = newWindow;\n this.dispatchEvent(\n new StateChangedEvent(this.state() as State, 'VISIBLE_WINDOW', {shouldAnimate: options.shouldAnimate}));\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"TraceBounds.js","sourceRoot":"","sources":["../../../../../../front_end/services/trace_bounds/TraceBounds.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../models/trace/trace.js';\n\nlet instance: BoundsManager|null = null;\n\nexport class StateChangedEvent extends Event {\n static readonly eventName = 'traceboundsstatechanged';\n constructor(\n public state: Readonly,\n public updateType: 'RESET'|'MINIMAP_BOUNDS'|'VISIBLE_WINDOW',\n public options: {\n shouldAnimate?: boolean,\n } = {shouldAnimate: false},\n ) {\n super(StateChangedEvent.eventName, {composed: true, bubbles: true});\n }\n}\n\n// Exposed as a shortcut to BoundsManager.instance().addEventListener, which\n// also takes care of type-casting the event to StateChangedEvent.\nexport function onChange(cb: (event: StateChangedEvent) => void): void {\n BoundsManager.instance().addEventListener(\n StateChangedEvent.eventName,\n // Cast the callback as TS doesn't know that these events will emit\n // StateChangedEvent types.\n cb as (event: Event) => void);\n}\n\nexport function removeListener(cb: (event: StateChangedEvent) => void): void {\n BoundsManager.instance().removeEventListener(StateChangedEvent.eventName, cb as (event: Event) => void);\n}\n\nexport interface State {\n readonly micro: Readonly>;\n readonly milli: Readonly>;\n}\n\nexport interface TraceWindows {\n /**\n * This is the bounds of the entire trace. Once a trace is imported/recorded\n * and this is set, it cannot be changed.\n */\n readonly entireTraceBounds: Trace.Types.Timing.TraceWindow;\n /**\n * This is the bounds of the minimap and represents the left and right bound\n * being shown by the minimap. It can be changed by a user action: for\n * example, when a user creates a breadcrumb, that breadcrumb becomes the\n * minimap trace bounds. By default, and when a trace is first loaded, the\n * minimapTraceBounds are equivalent to the entireTraceBounds.\n * Note that this is NOT the active time window that the user has dragged\n * the minimap handles to; this is the min/max being shown by the minimap.\n */\n minimapTraceBounds: Trace.Types.Timing.TraceWindow;\n /**\n * This represents the trace window that is being shown on the main timeline.\n * The reason this is called a \"Window\" rather than \"Bounds\" is because the\n * user is not bound by this value - they can use their mouse to pan/zoom\n * in/out beyond the limits of this window (the limit is the\n * minimapTraceBounds). Another way to think of this value is that the\n * min/max of this value is what is represented by the two drag handles on\n * the TimelineMiniMap that the user can drag to change their current window.\n */\n timelineTraceWindow: Trace.Types.Timing.TraceWindow;\n}\n\nexport class BoundsManager extends EventTarget {\n static instance(opts: {\n forceNew: boolean|null,\n } = {forceNew: null}): BoundsManager {\n const forceNew = Boolean(opts.forceNew);\n if (!instance || forceNew) {\n instance = new BoundsManager();\n }\n return instance;\n }\n\n static removeInstance(): void {\n instance = null;\n }\n\n #currentState: TraceWindows|null = null;\n\n private constructor() {\n // Defined to enable us to mark it as Private.\n super();\n }\n\n resetWithNewBounds(initialBounds: Trace.Types.Timing.TraceWindowMicroSeconds): this {\n this.#currentState = {\n entireTraceBounds: initialBounds,\n minimapTraceBounds: initialBounds,\n timelineTraceWindow: initialBounds,\n };\n this.dispatchEvent(new StateChangedEvent(this.state() as State, 'RESET'));\n return this;\n }\n\n state(): Readonly|null {\n if (this.#currentState === null) {\n return null;\n }\n const entireBoundsMilli = Trace.Helpers.Timing.traceWindowMilliSeconds(this.#currentState.entireTraceBounds);\n const minimapBoundsMilli = Trace.Helpers.Timing.traceWindowMilliSeconds(this.#currentState.minimapTraceBounds);\n const timelineTraceWindowMilli =\n Trace.Helpers.Timing.traceWindowMilliSeconds(this.#currentState.timelineTraceWindow);\n\n return {\n micro: this.#currentState,\n milli: {\n entireTraceBounds: entireBoundsMilli,\n minimapTraceBounds: minimapBoundsMilli,\n timelineTraceWindow: timelineTraceWindowMilli,\n },\n };\n }\n\n setMiniMapBounds(newBounds: Trace.Types.Timing.TraceWindowMicroSeconds): void {\n if (!this.#currentState) {\n // If we don't have the existing state and know the trace bounds, we\n // cannot set the minimap bounds.\n console.error('TraceBounds.setMiniMapBounds could not set bounds because there is no existing trace window set.');\n return;\n }\n const existingBounds = this.#currentState.minimapTraceBounds;\n if (newBounds.min === existingBounds.min && newBounds.max === existingBounds.max) {\n // New bounds are identical to the old ones so no action required.\n return;\n }\n\n if (newBounds.range < 1_000) {\n // Minimum minimap bounds range is 1 millisecond.\n return;\n }\n\n this.#currentState.minimapTraceBounds = newBounds;\n // this.state() cannot be null here.\n this.dispatchEvent(new StateChangedEvent(this.state() as State, 'MINIMAP_BOUNDS'));\n }\n\n /**\n * Updates the visible part of the trace that the user can see.\n * @param options.ignoreMiniMapBounds - by default the visible window will be\n * bound by the minimap bounds. If you set this to `true` then the timeline\n * visible window will not be constrained by the minimap bounds. Be careful\n * with this! Unless you deal with this situation, the UI of the performance\n * panel will break.\n */\n setTimelineVisibleWindow(newWindow: Trace.Types.Timing.TraceWindowMicroSeconds, options: {\n shouldAnimate?: boolean,\n ignoreMiniMapBounds?: boolean,\n } = {\n shouldAnimate: false,\n ignoreMiniMapBounds: false,\n }): void {\n if (!this.#currentState) {\n // This is a weird state to be in: we can't change the visible timeline\n // window if we don't alreayd have an existing state with the trace\n // bounds set.\n console.error(\n 'TraceBounds.setTimelineVisibleWindow could not set bounds because there is no existing trace window set.');\n return;\n }\n const existingWindow = this.#currentState.timelineTraceWindow;\n if (newWindow.min === existingWindow.min && newWindow.max === existingWindow.max) {\n // New bounds are identical to the old ones so no action required.\n return;\n }\n\n if (newWindow.range < 1_000) {\n // Minimum timeline visible window range is 1 millisecond.\n return;\n }\n\n if (!options.ignoreMiniMapBounds) {\n // Ensure that the setTimelineVisibleWindow can never go outside the bounds of the minimap bounds.\n newWindow.min =\n Trace.Types.Timing.MicroSeconds(Math.max(this.#currentState.minimapTraceBounds.min, newWindow.min));\n newWindow.max =\n Trace.Types.Timing.MicroSeconds(Math.min(this.#currentState.minimapTraceBounds.max, newWindow.max));\n }\n\n this.#currentState.timelineTraceWindow = newWindow;\n this.dispatchEvent(\n new StateChangedEvent(this.state() as State, 'VISIBLE_WINDOW', {shouldAnimate: options.shouldAnimate}));\n }\n}\n"]} \ No newline at end of file diff --git a/public/services/trace_bounds/TraceBounds.test.js b/public/services/trace_bounds/TraceBounds.test.js index 7e15dc18f..e760047d7 100644 --- a/public/services/trace_bounds/TraceBounds.test.js +++ b/public/services/trace_bounds/TraceBounds.test.js @@ -1,14 +1,14 @@ // 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 * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; import * as TraceBounds from './trace_bounds.js'; const baseTraceWindow = { - min: TraceEngine.Types.Timing.MicroSeconds(0), - max: TraceEngine.Types.Timing.MicroSeconds(10_000), - range: TraceEngine.Types.Timing.MicroSeconds(10_000), + min: Trace.Types.Timing.MicroSeconds(0), + max: Trace.Types.Timing.MicroSeconds(10_000), + range: Trace.Types.Timing.MicroSeconds(10_000), }; -const baseTraceWindowMilli = TraceEngine.Helpers.Timing.traceWindowMilliSeconds(baseTraceWindow); +const baseTraceWindowMilli = Trace.Helpers.Timing.traceWindowMilliSeconds(baseTraceWindow); describe('TraceBounds', () => { it('is initialized with the entire trace window and sets the state accordingly', async () => { const manager = TraceBounds.TraceBounds.BoundsManager.instance({ forceNew: true }).resetWithNewBounds(baseTraceWindow); @@ -30,9 +30,9 @@ describe('TraceBounds', () => { const onStateChange = sinon.spy(); manager.addEventListener(TraceBounds.TraceBounds.StateChangedEvent.eventName, onStateChange); const newMiniMapBounds = { - min: TraceEngine.Types.Timing.MicroSeconds(10_000), - max: TraceEngine.Types.Timing.MicroSeconds(20_000), - range: TraceEngine.Types.Timing.MicroSeconds(10_000), + min: Trace.Types.Timing.MicroSeconds(10_000), + max: Trace.Types.Timing.MicroSeconds(20_000), + range: Trace.Types.Timing.MicroSeconds(10_000), }; manager.setMiniMapBounds(newMiniMapBounds); assert.strictEqual(onStateChange.callCount, 1); @@ -49,11 +49,11 @@ describe('TraceBounds', () => { const onStateChange = sinon.spy(); manager.addEventListener(TraceBounds.TraceBounds.StateChangedEvent.eventName, onStateChange); const newBounds = { - min: TraceEngine.Types.Timing.MicroSeconds(1_000), - max: TraceEngine.Types.Timing.MicroSeconds(5_000), - range: TraceEngine.Types.Timing.MicroSeconds(4_000), + min: Trace.Types.Timing.MicroSeconds(1_000), + max: Trace.Types.Timing.MicroSeconds(5_000), + range: Trace.Types.Timing.MicroSeconds(4_000), }; - const newBoundsMilli = TraceEngine.Helpers.Timing.traceWindowMilliSeconds(newBounds); + const newBoundsMilli = Trace.Helpers.Timing.traceWindowMilliSeconds(newBounds); manager.resetWithNewBounds(newBounds); assert.strictEqual(onStateChange.callCount, 1); const dataFromEvent = onStateChange.firstCall.args[0]; @@ -76,9 +76,9 @@ describe('TraceBounds', () => { const onStateChange = sinon.spy(); manager.addEventListener(TraceBounds.TraceBounds.StateChangedEvent.eventName, onStateChange); const newVisibleWindow = { - min: TraceEngine.Types.Timing.MicroSeconds(10_000), - max: TraceEngine.Types.Timing.MicroSeconds(20_000), - range: TraceEngine.Types.Timing.MicroSeconds(10_000), + min: Trace.Types.Timing.MicroSeconds(10_000), + max: Trace.Types.Timing.MicroSeconds(20_000), + range: Trace.Types.Timing.MicroSeconds(10_000), }; manager.setTimelineVisibleWindow(newVisibleWindow); assert.strictEqual(onStateChange.callCount, 1); @@ -95,9 +95,9 @@ describe('TraceBounds', () => { const onStateChange = sinon.spy(); manager.addEventListener(TraceBounds.TraceBounds.StateChangedEvent.eventName, onStateChange); const newVisibleWindow = { - min: TraceEngine.Types.Timing.MicroSeconds(10_000), - max: TraceEngine.Types.Timing.MicroSeconds(10_500), - range: TraceEngine.Types.Timing.MicroSeconds(500), + min: Trace.Types.Timing.MicroSeconds(10_000), + max: Trace.Types.Timing.MicroSeconds(10_500), + range: Trace.Types.Timing.MicroSeconds(500), }; manager.setTimelineVisibleWindow(newVisibleWindow); assert.strictEqual(onStateChange.callCount, 0); @@ -112,9 +112,9 @@ describe('TraceBounds', () => { const onStateChange = sinon.spy(); manager.addEventListener(TraceBounds.TraceBounds.StateChangedEvent.eventName, onStateChange); const newMiniMapBounds = { - min: TraceEngine.Types.Timing.MicroSeconds(10_000), - max: TraceEngine.Types.Timing.MicroSeconds(10_500), - range: TraceEngine.Types.Timing.MicroSeconds(500), + min: Trace.Types.Timing.MicroSeconds(10_000), + max: Trace.Types.Timing.MicroSeconds(10_500), + range: Trace.Types.Timing.MicroSeconds(500), }; manager.setMiniMapBounds(newMiniMapBounds); assert.strictEqual(onStateChange.callCount, 0); diff --git a/public/services/trace_bounds/TraceBounds.test.js.map b/public/services/trace_bounds/TraceBounds.test.js.map index 8834b023c..a21ac862c 100644 --- a/public/services/trace_bounds/TraceBounds.test.js.map +++ b/public/services/trace_bounds/TraceBounds.test.js.map @@ -1 +1 @@ -{"version":3,"file":"TraceBounds.test.js","sourceRoot":"","sources":["../../../../../../front_end/services/trace_bounds/TraceBounds.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceEngine from '../../models/trace/trace.js';\nimport * as TraceBounds from './trace_bounds.js';\n\nconst baseTraceWindow: TraceEngine.Types.Timing.TraceWindowMicroSeconds = {\n min: TraceEngine.Types.Timing.MicroSeconds(0),\n max: TraceEngine.Types.Timing.MicroSeconds(10_000),\n range: TraceEngine.Types.Timing.MicroSeconds(10_000),\n};\nconst baseTraceWindowMilli: TraceEngine.Types.Timing.TraceWindowMilliSeconds =\n TraceEngine.Helpers.Timing.traceWindowMilliSeconds(baseTraceWindow);\n\ndescribe('TraceBounds', () => {\n it('is initialized with the entire trace window and sets the state accordingly', async () => {\n const manager =\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(baseTraceWindow);\n assert.deepEqual(manager.state(), {\n micro: {\n entireTraceBounds: baseTraceWindow,\n minimapTraceBounds: baseTraceWindow,\n timelineTraceWindow: baseTraceWindow,\n },\n milli: {\n entireTraceBounds: baseTraceWindowMilli,\n minimapTraceBounds: baseTraceWindowMilli,\n timelineTraceWindow: baseTraceWindowMilli,\n },\n });\n });\n\n it('can update the minimap bounds and dispatches a state change event', async () => {\n const manager =\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(baseTraceWindow);\n const onStateChange = sinon.spy();\n manager.addEventListener(TraceBounds.TraceBounds.StateChangedEvent.eventName, onStateChange);\n\n const newMiniMapBounds = {\n min: TraceEngine.Types.Timing.MicroSeconds(10_000),\n max: TraceEngine.Types.Timing.MicroSeconds(20_000),\n range: TraceEngine.Types.Timing.MicroSeconds(10_000),\n };\n\n manager.setMiniMapBounds(newMiniMapBounds);\n assert.strictEqual(onStateChange.callCount, 1);\n const dataFromEvent = onStateChange.firstCall.args[0] as TraceBounds.TraceBounds.StateChangedEvent;\n assert.strictEqual(dataFromEvent.updateType, 'MINIMAP_BOUNDS');\n assert.deepEqual(dataFromEvent.state.micro, {\n entireTraceBounds: baseTraceWindow,\n minimapTraceBounds: newMiniMapBounds,\n timelineTraceWindow: baseTraceWindow,\n });\n });\n\n it('dispatches an event when the bounds are completely reset', async () => {\n const manager =\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(baseTraceWindow);\n\n const onStateChange = sinon.spy();\n manager.addEventListener(TraceBounds.TraceBounds.StateChangedEvent.eventName, onStateChange);\n\n const newBounds = {\n min: TraceEngine.Types.Timing.MicroSeconds(1_000),\n max: TraceEngine.Types.Timing.MicroSeconds(5_000),\n range: TraceEngine.Types.Timing.MicroSeconds(4_000),\n };\n const newBoundsMilli = TraceEngine.Helpers.Timing.traceWindowMilliSeconds(newBounds);\n manager.resetWithNewBounds(newBounds);\n\n assert.strictEqual(onStateChange.callCount, 1);\n const dataFromEvent = onStateChange.firstCall.args[0] as TraceBounds.TraceBounds.StateChangedEvent;\n assert.strictEqual(dataFromEvent.updateType, 'RESET');\n assert.deepEqual(dataFromEvent.state, {\n micro: {\n entireTraceBounds: newBounds,\n minimapTraceBounds: newBounds,\n timelineTraceWindow: newBounds,\n },\n milli: {\n entireTraceBounds: newBoundsMilli,\n minimapTraceBounds: newBoundsMilli,\n timelineTraceWindow: newBoundsMilli,\n },\n });\n });\n\n it('can update the visible timeline window and dispatch an event', async () => {\n const manager =\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(baseTraceWindow);\n const onStateChange = sinon.spy();\n manager.addEventListener(TraceBounds.TraceBounds.StateChangedEvent.eventName, onStateChange);\n\n const newVisibleWindow = {\n min: TraceEngine.Types.Timing.MicroSeconds(10_000),\n max: TraceEngine.Types.Timing.MicroSeconds(20_000),\n range: TraceEngine.Types.Timing.MicroSeconds(10_000),\n };\n\n manager.setTimelineVisibleWindow(newVisibleWindow);\n\n assert.strictEqual(onStateChange.callCount, 1);\n const dataFromEvent = onStateChange.firstCall.args[0] as TraceBounds.TraceBounds.StateChangedEvent;\n assert.strictEqual(dataFromEvent.updateType, 'VISIBLE_WINDOW');\n assert.deepEqual(dataFromEvent.state.micro, {\n entireTraceBounds: baseTraceWindow,\n minimapTraceBounds: baseTraceWindow,\n timelineTraceWindow: newVisibleWindow,\n });\n });\n\n it('does not update or dispatch if the range of the new trace window is less than 1ms', async () => {\n const manager =\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(baseTraceWindow);\n const onStateChange = sinon.spy();\n manager.addEventListener(TraceBounds.TraceBounds.StateChangedEvent.eventName, onStateChange);\n\n const newVisibleWindow = {\n min: TraceEngine.Types.Timing.MicroSeconds(10_000),\n max: TraceEngine.Types.Timing.MicroSeconds(10_500),\n range: TraceEngine.Types.Timing.MicroSeconds(500),\n };\n\n manager.setTimelineVisibleWindow(newVisibleWindow);\n assert.strictEqual(onStateChange.callCount, 0);\n assert.deepEqual(manager.state()?.micro, {\n entireTraceBounds: baseTraceWindow,\n minimapTraceBounds: baseTraceWindow,\n timelineTraceWindow: baseTraceWindow,\n });\n });\n\n it('does not update or dispatch if the range of the new minimap bounds is less than 1ms', async () => {\n const manager =\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(baseTraceWindow);\n const onStateChange = sinon.spy();\n manager.addEventListener(TraceBounds.TraceBounds.StateChangedEvent.eventName, onStateChange);\n\n const newMiniMapBounds = {\n min: TraceEngine.Types.Timing.MicroSeconds(10_000),\n max: TraceEngine.Types.Timing.MicroSeconds(10_500),\n range: TraceEngine.Types.Timing.MicroSeconds(500),\n };\n\n manager.setMiniMapBounds(newMiniMapBounds);\n assert.strictEqual(onStateChange.callCount, 0);\n assert.deepEqual(manager.state()?.micro, {\n entireTraceBounds: baseTraceWindow,\n minimapTraceBounds: baseTraceWindow,\n timelineTraceWindow: baseTraceWindow,\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"TraceBounds.test.js","sourceRoot":"","sources":["../../../../../../front_end/services/trace_bounds/TraceBounds.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../models/trace/trace.js';\n\nimport * as TraceBounds from './trace_bounds.js';\n\nconst baseTraceWindow: Trace.Types.Timing.TraceWindowMicroSeconds = {\n min: Trace.Types.Timing.MicroSeconds(0),\n max: Trace.Types.Timing.MicroSeconds(10_000),\n range: Trace.Types.Timing.MicroSeconds(10_000),\n};\nconst baseTraceWindowMilli: Trace.Types.Timing.TraceWindowMilliSeconds =\n Trace.Helpers.Timing.traceWindowMilliSeconds(baseTraceWindow);\n\ndescribe('TraceBounds', () => {\n it('is initialized with the entire trace window and sets the state accordingly', async () => {\n const manager =\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(baseTraceWindow);\n assert.deepEqual(manager.state(), {\n micro: {\n entireTraceBounds: baseTraceWindow,\n minimapTraceBounds: baseTraceWindow,\n timelineTraceWindow: baseTraceWindow,\n },\n milli: {\n entireTraceBounds: baseTraceWindowMilli,\n minimapTraceBounds: baseTraceWindowMilli,\n timelineTraceWindow: baseTraceWindowMilli,\n },\n });\n });\n\n it('can update the minimap bounds and dispatches a state change event', async () => {\n const manager =\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(baseTraceWindow);\n const onStateChange = sinon.spy();\n manager.addEventListener(TraceBounds.TraceBounds.StateChangedEvent.eventName, onStateChange);\n\n const newMiniMapBounds = {\n min: Trace.Types.Timing.MicroSeconds(10_000),\n max: Trace.Types.Timing.MicroSeconds(20_000),\n range: Trace.Types.Timing.MicroSeconds(10_000),\n };\n\n manager.setMiniMapBounds(newMiniMapBounds);\n assert.strictEqual(onStateChange.callCount, 1);\n const dataFromEvent = onStateChange.firstCall.args[0] as TraceBounds.TraceBounds.StateChangedEvent;\n assert.strictEqual(dataFromEvent.updateType, 'MINIMAP_BOUNDS');\n assert.deepEqual(dataFromEvent.state.micro, {\n entireTraceBounds: baseTraceWindow,\n minimapTraceBounds: newMiniMapBounds,\n timelineTraceWindow: baseTraceWindow,\n });\n });\n\n it('dispatches an event when the bounds are completely reset', async () => {\n const manager =\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(baseTraceWindow);\n\n const onStateChange = sinon.spy();\n manager.addEventListener(TraceBounds.TraceBounds.StateChangedEvent.eventName, onStateChange);\n\n const newBounds = {\n min: Trace.Types.Timing.MicroSeconds(1_000),\n max: Trace.Types.Timing.MicroSeconds(5_000),\n range: Trace.Types.Timing.MicroSeconds(4_000),\n };\n const newBoundsMilli = Trace.Helpers.Timing.traceWindowMilliSeconds(newBounds);\n manager.resetWithNewBounds(newBounds);\n\n assert.strictEqual(onStateChange.callCount, 1);\n const dataFromEvent = onStateChange.firstCall.args[0] as TraceBounds.TraceBounds.StateChangedEvent;\n assert.strictEqual(dataFromEvent.updateType, 'RESET');\n assert.deepEqual(dataFromEvent.state, {\n micro: {\n entireTraceBounds: newBounds,\n minimapTraceBounds: newBounds,\n timelineTraceWindow: newBounds,\n },\n milli: {\n entireTraceBounds: newBoundsMilli,\n minimapTraceBounds: newBoundsMilli,\n timelineTraceWindow: newBoundsMilli,\n },\n });\n });\n\n it('can update the visible timeline window and dispatch an event', async () => {\n const manager =\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(baseTraceWindow);\n const onStateChange = sinon.spy();\n manager.addEventListener(TraceBounds.TraceBounds.StateChangedEvent.eventName, onStateChange);\n\n const newVisibleWindow = {\n min: Trace.Types.Timing.MicroSeconds(10_000),\n max: Trace.Types.Timing.MicroSeconds(20_000),\n range: Trace.Types.Timing.MicroSeconds(10_000),\n };\n\n manager.setTimelineVisibleWindow(newVisibleWindow);\n\n assert.strictEqual(onStateChange.callCount, 1);\n const dataFromEvent = onStateChange.firstCall.args[0] as TraceBounds.TraceBounds.StateChangedEvent;\n assert.strictEqual(dataFromEvent.updateType, 'VISIBLE_WINDOW');\n assert.deepEqual(dataFromEvent.state.micro, {\n entireTraceBounds: baseTraceWindow,\n minimapTraceBounds: baseTraceWindow,\n timelineTraceWindow: newVisibleWindow,\n });\n });\n\n it('does not update or dispatch if the range of the new trace window is less than 1ms', async () => {\n const manager =\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(baseTraceWindow);\n const onStateChange = sinon.spy();\n manager.addEventListener(TraceBounds.TraceBounds.StateChangedEvent.eventName, onStateChange);\n\n const newVisibleWindow = {\n min: Trace.Types.Timing.MicroSeconds(10_000),\n max: Trace.Types.Timing.MicroSeconds(10_500),\n range: Trace.Types.Timing.MicroSeconds(500),\n };\n\n manager.setTimelineVisibleWindow(newVisibleWindow);\n assert.strictEqual(onStateChange.callCount, 0);\n assert.deepEqual(manager.state()?.micro, {\n entireTraceBounds: baseTraceWindow,\n minimapTraceBounds: baseTraceWindow,\n timelineTraceWindow: baseTraceWindow,\n });\n });\n\n it('does not update or dispatch if the range of the new minimap bounds is less than 1ms', async () => {\n const manager =\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true}).resetWithNewBounds(baseTraceWindow);\n const onStateChange = sinon.spy();\n manager.addEventListener(TraceBounds.TraceBounds.StateChangedEvent.eventName, onStateChange);\n\n const newMiniMapBounds = {\n min: Trace.Types.Timing.MicroSeconds(10_000),\n max: Trace.Types.Timing.MicroSeconds(10_500),\n range: Trace.Types.Timing.MicroSeconds(500),\n };\n\n manager.setMiniMapBounds(newMiniMapBounds);\n assert.strictEqual(onStateChange.callCount, 0);\n assert.deepEqual(manager.state()?.micro, {\n entireTraceBounds: baseTraceWindow,\n minimapTraceBounds: baseTraceWindow,\n timelineTraceWindow: baseTraceWindow,\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/services/tracing/PerformanceTracing.d.ts b/public/services/tracing/PerformanceTracing.d.ts index 15d936716..b9627322d 100644 --- a/public/services/tracing/PerformanceTracing.d.ts +++ b/public/services/tracing/PerformanceTracing.d.ts @@ -1,6 +1,6 @@ import type * as SDK from '../../core/sdk/sdk.js'; -import * as TraceEngine from '../../models/trace/trace.js'; -export declare class PerformanceTracing implements TraceEngine.TracingManager.TracingManagerClient { +import * as Trace from '../../models/trace/trace.js'; +export declare class PerformanceTracing implements Trace.TracingManager.TracingManagerClient { #private; constructor(target: SDK.Target.Target, delegate: Delegate); start(): Promise; diff --git a/public/services/tracing/PerformanceTracing.js b/public/services/tracing/PerformanceTracing.js index c7825a1bd..4284fa326 100644 --- a/public/services/tracing/PerformanceTracing.js +++ b/public/services/tracing/PerformanceTracing.js @@ -1,13 +1,13 @@ // 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 * as TraceEngine from '../../models/trace/trace.js'; +import * as Trace from '../../models/trace/trace.js'; export class PerformanceTracing { #traceEvents = []; #tracingManager = null; #delegate; constructor(target, delegate) { - this.#tracingManager = target.model(TraceEngine.TracingManager.TracingManager); + this.#tracingManager = target.model(Trace.TracingManager.TracingManager); this.#delegate = delegate; } async start() { diff --git a/public/services/tracing/PerformanceTracing.js.map b/public/services/tracing/PerformanceTracing.js.map index b228969f2..26e0a0dcf 100644 --- a/public/services/tracing/PerformanceTracing.js.map +++ b/public/services/tracing/PerformanceTracing.js.map @@ -1 +1 @@ -{"version":3,"file":"PerformanceTracing.js","sourceRoot":"","sources":["../../../../../../front_end/services/tracing/PerformanceTracing.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAG7B,OAAO,KAAK,WAAW,MAAM,6BAA6B,CAAC;AAE3D,MAAM,OAAO,kBAAkB;IACpB,YAAY,GAAa,EAAE,CAAC;IACrC,eAAe,GAAmD,IAAI,CAAC;IACvE,SAAS,CAAW;IAEpB,YAAY,MAAyB,EAAE,QAAkB;QACvD,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;QAC/E,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;QAE7B,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACxC,CAAC;QAED,oEAAoE;QACpE,8CAA8C;QAC9C,6IAA6I;QAC7I,mGAAmG;QACnG,MAAM,UAAU,GAAG;YACjB,IAAI;YACJ,eAAe;YACf,mBAAmB;YACnB,mBAAmB;YACnB,yCAAyC;YACzC,uCAAuC;YACvC,4DAA4D;YAC5D,6CAA6C;YAC7C,6CAA6C;YAC7C,qCAAqC;YACrC,2CAA2C;YAC3C,aAAa;YACb,SAAS;YACT,gCAAgC;YAChC,YAAY;YACZ,IAAI;SACL,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEZ,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;QAEvE,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI;QACR,OAAO,IAAI,CAAC,eAAe,EAAE,IAAI,EAAE,CAAC;IACtC,CAAC;IAED,qEAAqE;IACrE,cAAc;QACZ,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,oBAAoB,CAAC,MAAgB;QACnC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;IACpC,CAAC;IAED,kBAAkB,CAAC,KAAa;QAC9B,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED,uBAAuB,CAAC,QAAgB;QACtC,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IACnD,CAAC;IAED,eAAe;QACb,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACpD,CAAC;CAEF;AAQD,4GAA4G;AAC5G,MAAM,OAAO,cAAc;IACL;IAApB,YAAoB,MAAgB;QAAhB,WAAM,GAAN,MAAM,CAAU;IACpC,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;CACF","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as SDK from '../../core/sdk/sdk.js';\nimport * as TraceEngine from '../../models/trace/trace.js';\n\nexport class PerformanceTracing implements TraceEngine.TracingManager.TracingManagerClient {\n readonly #traceEvents: Object[] = [];\n #tracingManager: TraceEngine.TracingManager.TracingManager|null = null;\n #delegate: Delegate;\n\n constructor(target: SDK.Target.Target, delegate: Delegate) {\n this.#tracingManager = target.model(TraceEngine.TracingManager.TracingManager);\n this.#delegate = delegate;\n }\n\n async start(): Promise {\n this.#traceEvents.length = 0;\n\n if (!this.#tracingManager) {\n throw new Error('No tracing manager');\n }\n\n // This panel may be opened with trace data recorded in other tools.\n // Keep in sync with the categories arrays in:\n // https://source.chromium.org/chromium/chromium/src/+/main:third_party/devtools-frontend/src/front_end/panels/timeline/TimelineController.ts\n // https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/gather/gatherers/trace.js\n const categories = [\n '-*',\n 'blink.console',\n 'blink.user_timing',\n 'devtools.timeline',\n 'disabled-by-default-devtools.screenshot',\n 'disabled-by-default-devtools.timeline',\n 'disabled-by-default-devtools.timeline.invalidationTracking',\n 'disabled-by-default-devtools.timeline.frame',\n 'disabled-by-default-devtools.timeline.stack',\n 'disabled-by-default-v8.cpu_profiler',\n 'disabled-by-default-v8.cpu_profiler.hires',\n 'latencyInfo',\n 'loading',\n 'disabled-by-default-lighthouse',\n 'v8.execute',\n 'v8',\n ].join(',');\n\n const started = await this.#tracingManager.start(this, categories, '');\n\n if (!started) {\n throw new Error('Unable to start tracing.');\n }\n }\n\n async stop(): Promise {\n return this.#tracingManager?.stop();\n }\n\n // Start of implementation of SDK.TracingManager.TracingManagerClient\n getTraceEvents(): Object[] {\n return this.#traceEvents;\n }\n\n traceEventsCollected(events: Object[]): void {\n this.#traceEvents.push(...events);\n }\n\n tracingBufferUsage(usage: number): void {\n this.#delegate.tracingBufferUsage(usage);\n }\n\n eventsRetrievalProgress(progress: number): void {\n this.#delegate.eventsRetrievalProgress(progress);\n }\n\n tracingComplete(): void {\n this.#delegate.tracingComplete(this.#traceEvents);\n }\n // End of implementation of SDK.TracingManager.TracingManagerClient\n}\n\ninterface Delegate {\n tracingBufferUsage(usage: number): void;\n eventsRetrievalProgress(progress: number): void;\n tracingComplete(events: Object[]): void;\n}\n\n// Used by an implementation of Common.Revealer to transfer data from the recorder to the performance panel.\nexport class RawTraceEvents {\n constructor(private events: Object[]) {\n }\n\n getEvents(): Object[] {\n return this.events;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"PerformanceTracing.js","sourceRoot":"","sources":["../../../../../../front_end/services/tracing/PerformanceTracing.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAG7B,OAAO,KAAK,KAAK,MAAM,6BAA6B,CAAC;AAErD,MAAM,OAAO,kBAAkB;IACpB,YAAY,GAAa,EAAE,CAAC;IACrC,eAAe,GAA6C,IAAI,CAAC;IACjE,SAAS,CAAW;IAEpB,YAAY,MAAyB,EAAE,QAAkB;QACvD,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,CAAC;QACzE,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;IAC5B,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;QAE7B,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACxC,CAAC;QAED,oEAAoE;QACpE,8CAA8C;QAC9C,6IAA6I;QAC7I,mGAAmG;QACnG,MAAM,UAAU,GAAG;YACjB,IAAI;YACJ,eAAe;YACf,mBAAmB;YACnB,mBAAmB;YACnB,yCAAyC;YACzC,uCAAuC;YACvC,4DAA4D;YAC5D,6CAA6C;YAC7C,6CAA6C;YAC7C,qCAAqC;YACrC,2CAA2C;YAC3C,aAAa;YACb,SAAS;YACT,gCAAgC;YAChC,YAAY;YACZ,IAAI;SACL,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEZ,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,CAAC;QAEvE,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI;QACR,OAAO,IAAI,CAAC,eAAe,EAAE,IAAI,EAAE,CAAC;IACtC,CAAC;IAED,qEAAqE;IACrE,cAAc;QACZ,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,oBAAoB,CAAC,MAAgB;QACnC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;IACpC,CAAC;IAED,kBAAkB,CAAC,KAAa;QAC9B,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAC3C,CAAC;IAED,uBAAuB,CAAC,QAAgB;QACtC,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IACnD,CAAC;IAED,eAAe;QACb,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACpD,CAAC;CAEF;AAQD,4GAA4G;AAC5G,MAAM,OAAO,cAAc;IACL;IAApB,YAAoB,MAAgB;QAAhB,WAAM,GAAN,MAAM,CAAU;IACpC,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;CACF","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as SDK from '../../core/sdk/sdk.js';\nimport * as Trace from '../../models/trace/trace.js';\n\nexport class PerformanceTracing implements Trace.TracingManager.TracingManagerClient {\n readonly #traceEvents: Object[] = [];\n #tracingManager: Trace.TracingManager.TracingManager|null = null;\n #delegate: Delegate;\n\n constructor(target: SDK.Target.Target, delegate: Delegate) {\n this.#tracingManager = target.model(Trace.TracingManager.TracingManager);\n this.#delegate = delegate;\n }\n\n async start(): Promise {\n this.#traceEvents.length = 0;\n\n if (!this.#tracingManager) {\n throw new Error('No tracing manager');\n }\n\n // This panel may be opened with trace data recorded in other tools.\n // Keep in sync with the categories arrays in:\n // https://source.chromium.org/chromium/chromium/src/+/main:third_party/devtools-frontend/src/front_end/panels/timeline/TimelineController.ts\n // https://github.com/GoogleChrome/lighthouse/blob/master/lighthouse-core/gather/gatherers/trace.js\n const categories = [\n '-*',\n 'blink.console',\n 'blink.user_timing',\n 'devtools.timeline',\n 'disabled-by-default-devtools.screenshot',\n 'disabled-by-default-devtools.timeline',\n 'disabled-by-default-devtools.timeline.invalidationTracking',\n 'disabled-by-default-devtools.timeline.frame',\n 'disabled-by-default-devtools.timeline.stack',\n 'disabled-by-default-v8.cpu_profiler',\n 'disabled-by-default-v8.cpu_profiler.hires',\n 'latencyInfo',\n 'loading',\n 'disabled-by-default-lighthouse',\n 'v8.execute',\n 'v8',\n ].join(',');\n\n const started = await this.#tracingManager.start(this, categories, '');\n\n if (!started) {\n throw new Error('Unable to start tracing.');\n }\n }\n\n async stop(): Promise {\n return this.#tracingManager?.stop();\n }\n\n // Start of implementation of SDK.TracingManager.TracingManagerClient\n getTraceEvents(): Object[] {\n return this.#traceEvents;\n }\n\n traceEventsCollected(events: Object[]): void {\n this.#traceEvents.push(...events);\n }\n\n tracingBufferUsage(usage: number): void {\n this.#delegate.tracingBufferUsage(usage);\n }\n\n eventsRetrievalProgress(progress: number): void {\n this.#delegate.eventsRetrievalProgress(progress);\n }\n\n tracingComplete(): void {\n this.#delegate.tracingComplete(this.#traceEvents);\n }\n // End of implementation of SDK.TracingManager.TracingManagerClient\n}\n\ninterface Delegate {\n tracingBufferUsage(usage: number): void;\n eventsRetrievalProgress(progress: number): void;\n tracingComplete(events: Object[]): void;\n}\n\n// Used by an implementation of Common.Revealer to transfer data from the recorder to the performance panel.\nexport class RawTraceEvents {\n constructor(private events: Object[]) {\n }\n\n getEvents(): Object[] {\n return this.events;\n }\n}\n"]} \ No newline at end of file diff --git a/public/testing/EnvironmentHelpers.js b/public/testing/EnvironmentHelpers.js index 642250013..66beb7d5d 100644 --- a/public/testing/EnvironmentHelpers.js +++ b/public/testing/EnvironmentHelpers.js @@ -112,6 +112,7 @@ const REGISTERED_EXPERIMENTS = [ "timeline-enhanced-traces" /* Root.Runtime.ExperimentName.TIMELINE_ENHANCED_TRACES */, "gen-ai-settings-panel" /* Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL */, "timeline-layout-shift-details" /* Root.Runtime.ExperimentName.TIMELINE_LAYOUT_SHIFT_DETAILS */, + "extension-storage-viewer" /* Root.Runtime.ExperimentName.EXTENSION_STORAGE_VIEWER */, ]; export async function initializeGlobalVars({ reset = true } = {}) { await initializeGlobalLocaleVars(); @@ -155,7 +156,6 @@ export async function initializeGlobalVars({ reset = true } = {}) { createSettingValue("RENDERING" /* Common.Settings.SettingCategory.RENDERING */, 'show-debug-borders', false), createSettingValue("RENDERING" /* Common.Settings.SettingCategory.RENDERING */, 'show-fps-counter', false), createSettingValue("RENDERING" /* Common.Settings.SettingCategory.RENDERING */, 'show-scroll-bottleneck-rects', false), - createSettingValue("RENDERING" /* Common.Settings.SettingCategory.RENDERING */, 'show-web-vitals', false), createSettingValue("RENDERING" /* Common.Settings.SettingCategory.RENDERING */, 'webp-format-disabled', false), createSettingValue("SOURCES" /* Common.Settings.SettingCategory.SOURCES */, 'allow-scroll-past-eof', true), createSettingValue("SOURCES" /* Common.Settings.SettingCategory.SOURCES */, 'css-source-maps-enabled', true), diff --git a/public/testing/EnvironmentHelpers.js.map b/public/testing/EnvironmentHelpers.js.map index 8e085d0f2..7b39807bb 100644 --- a/public/testing/EnvironmentHelpers.js.map +++ b/public/testing/EnvironmentHelpers.js.map @@ -1 +1 @@ -{"version":3,"file":"EnvironmentHelpers.js","sourceRoot":"","sources":["../../../../../front_end/testing/EnvironmentHelpers.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../core/common/common.js';\nimport * as Host from '../core/host/host.js';\nimport * as i18n from '../core/i18n/i18n.js';\nimport type * as Platform from '../core/platform/platform.js';\nimport * as Root from '../core/root/root.js';\nimport * as SDK from '../core/sdk/sdk.js';\nimport type * as Protocol from '../generated/protocol.js';\nimport * as Bindings from '../models/bindings/bindings.js';\nimport * as IssuesManager from '../models/issues_manager/issues_manager.js';\nimport * as Logs from '../models/logs/logs.js';\nimport * as Persistence from '../models/persistence/persistence.js';\nimport * as Workspace from '../models/workspace/workspace.js';\nimport type * as UIModule from '../ui/legacy/legacy.js';\n\n// Don't import UI at this stage because it will fail without\n// the environment. Instead we do the import at the end of the\n// initialization phase.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nlet UI: typeof UIModule;\n\nlet uniqueTargetId = 0;\n\nexport function createTarget(\n {id, name, type = SDK.Target.Type.FRAME, parentTarget, subtype, url = 'http://example.com'}: {\n id?: Protocol.Target.TargetID,\n name?: string,\n type?: SDK.Target.Type,\n parentTarget?: SDK.Target.Target,\n subtype?: string,\n url?: string,\n } = {}) {\n if (!id) {\n if (!uniqueTargetId++) {\n id = 'test' as Protocol.Target.TargetID;\n } else {\n id = ('test' + uniqueTargetId) as Protocol.Target.TargetID;\n }\n }\n const targetManager = SDK.TargetManager.TargetManager.instance();\n return targetManager.createTarget(\n id, name ?? id, type, parentTarget ? parentTarget : null, /* sessionId=*/ parentTarget ? id : undefined,\n /* suspended=*/ false,\n /* connection=*/ undefined, {targetId: id, url, subtype} as Protocol.Target.TargetInfo);\n}\n\nfunction createSettingValue(\n category: Common.Settings.SettingCategory, settingName: string, defaultValue: unknown,\n settingType = Common.Settings.SettingType.BOOLEAN): Common.Settings.SettingRegistration {\n return {category, settingName, defaultValue, settingType};\n}\n\nexport function stubNoopSettings() {\n sinon.stub(Common.Settings.Settings, 'instance').returns({\n createSetting: () => ({\n get: () => [],\n set: () => {},\n addChangeListener: () => {},\n removeChangeListener: () => {},\n setDisabled: () => {},\n setTitle: () => {},\n title: () => {},\n asRegExp: () => {},\n type: () => Common.Settings.SettingType.BOOLEAN,\n getAsArray: () => [],\n }),\n moduleSetting: () => ({\n get: () => [],\n set: () => {},\n addChangeListener: () => {},\n removeChangeListener: () => {},\n setDisabled: () => {},\n setTitle: () => {},\n title: () => {},\n asRegExp: () => {},\n type: () => Common.Settings.SettingType.BOOLEAN,\n getAsArray: () => [],\n }),\n createLocalSetting: () => ({\n get: () => [],\n set: () => {},\n addChangeListener: () => {},\n removeChangeListener: () => {},\n setDisabled: () => {},\n setTitle: () => {},\n title: () => {},\n asRegExp: () => {},\n type: () => Common.Settings.SettingType.BOOLEAN,\n getAsArray: () => [],\n }),\n getHostConfig: () => {},\n } as unknown as Common.Settings.Settings);\n}\n\nexport function registerNoopActions(actionIds: string[]): void {\n for (const actionId of actionIds) {\n UI.ActionRegistration.maybeRemoveActionExtension(actionId);\n UI.ActionRegistration.registerActionExtension({\n actionId,\n category: UI.ActionRegistration.ActionCategory.NONE,\n title: () => 'mock' as Platform.UIString.LocalizedString,\n });\n }\n const actionRegistryInstance = UI.ActionRegistry.ActionRegistry.instance({forceNew: true});\n UI.ShortcutRegistry.ShortcutRegistry.instance({forceNew: true, actionRegistry: actionRegistryInstance});\n}\n\nconst REGISTERED_EXPERIMENTS = [\n Root.Runtime.ExperimentName.CAPTURE_NODE_CREATION_STACKS,\n Root.Runtime.ExperimentName.PROTOCOL_MONITOR,\n 'timeline-show-all-events',\n 'timeline-v8-runtime-call-stats',\n 'timeline-invalidation-tracking',\n Root.Runtime.ExperimentName.INSTRUMENTATION_BREAKPOINTS,\n 'css-type-component-length-deprecate',\n Root.Runtime.ExperimentName.STYLES_PANE_CSS_CHANGES,\n Root.Runtime.ExperimentName.HEADER_OVERRIDES,\n Root.Runtime.ExperimentName.HIGHLIGHT_ERRORS_ELEMENTS_PANEL,\n Root.Runtime.ExperimentName.USE_SOURCE_MAP_SCOPES,\n 'font-editor',\n Root.Runtime.ExperimentName.NETWORK_PANEL_FILTER_BAR_REDESIGN,\n Root.Runtime.ExperimentName.AUTOFILL_VIEW,\n Root.Runtime.ExperimentName.TIMELINE_ANNOTATIONS,\n Root.Runtime.ExperimentName.TIMELINE_INSIGHTS,\n Root.Runtime.ExperimentName.TIMELINE_DEBUG_MODE,\n Root.Runtime.ExperimentName.TIMELINE_OBSERVATIONS,\n Root.Runtime.ExperimentName.TIMELINE_SERVER_TIMINGS,\n Root.Runtime.ExperimentName.FULL_ACCESSIBILITY_TREE,\n Root.Runtime.ExperimentName.TIMELINE_SHOW_POST_MESSAGE_EVENTS,\n Root.Runtime.ExperimentName.TIMELINE_ENHANCED_TRACES,\n Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL,\n Root.Runtime.ExperimentName.TIMELINE_LAYOUT_SHIFT_DETAILS,\n];\n\nexport async function initializeGlobalVars({reset = true} = {}) {\n await initializeGlobalLocaleVars();\n\n // Create the appropriate settings needed to boot.\n const settings = [\n createSettingValue(\n Common.Settings.SettingCategory.ADORNER, 'adorner-settings', [], Common.Settings.SettingType.ARRAY),\n createSettingValue(Common.Settings.SettingCategory.APPEARANCE, 'disable-paused-state-overlay', false),\n createSettingValue(\n Common.Settings.SettingCategory.APPEARANCE, 'sidebar-position', 'auto', Common.Settings.SettingType.ENUM),\n createSettingValue(Common.Settings.SettingCategory.CONSOLE, 'custom-formatters', false),\n createSettingValue(Common.Settings.SettingCategory.DEBUGGER, 'pause-on-exception-enabled', false),\n createSettingValue(Common.Settings.SettingCategory.DEBUGGER, 'pause-on-caught-exception', false),\n createSettingValue(Common.Settings.SettingCategory.DEBUGGER, 'pause-on-uncaught-exception', false),\n createSettingValue(Common.Settings.SettingCategory.DEBUGGER, 'disable-async-stack-traces', false),\n createSettingValue(Common.Settings.SettingCategory.DEBUGGER, 'breakpoints-active', true),\n createSettingValue(Common.Settings.SettingCategory.DEBUGGER, 'java-script-disabled', false),\n createSettingValue(Common.Settings.SettingCategory.DEBUGGER, 'skip-content-scripts', true),\n createSettingValue(\n Common.Settings.SettingCategory.DEBUGGER, 'automatically-ignore-list-known-third-party-scripts', true),\n createSettingValue(Common.Settings.SettingCategory.DEBUGGER, 'enable-ignore-listing', true),\n createSettingValue(\n Common.Settings.SettingCategory.DEBUGGER, 'skip-stack-frames-pattern', '/node_modules/|/bower_components/',\n Common.Settings.SettingType.REGEX),\n createSettingValue(Common.Settings.SettingCategory.DEBUGGER, 'navigator-group-by-folder', true),\n createSettingValue(Common.Settings.SettingCategory.ELEMENTS, 'show-detailed-inspect-tooltip', true),\n createSettingValue(Common.Settings.SettingCategory.ELEMENTS, 'show-html-comments', true),\n createSettingValue(Common.Settings.SettingCategory.ELEMENTS, 'show-ua-shadow-dom', false),\n createSettingValue(Common.Settings.SettingCategory.PERFORMANCE, 'annotations-hidden', false),\n createSettingValue(Common.Settings.SettingCategory.NETWORK, 'cache-disabled', false),\n createSettingValue(Common.Settings.SettingCategory.RENDERING, 'avif-format-disabled', false),\n createSettingValue(\n Common.Settings.SettingCategory.RENDERING, 'emulated-css-media', '', Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.RENDERING, 'emulated-css-media-feature-prefers-color-scheme', '',\n Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.RENDERING, 'emulated-css-media-feature-forced-colors', '',\n Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.RENDERING, 'emulated-css-media-feature-prefers-reduced-motion', '',\n Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.RENDERING, 'emulated-css-media-feature-prefers-contrast', '',\n Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.RENDERING, 'emulated-css-media-feature-prefers-reduced-data', '',\n Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.RENDERING, 'emulated-css-media-feature-prefers-reduced-transparency', '',\n Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.RENDERING, 'emulated-css-media-feature-color-gamut', '',\n Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.RENDERING, 'emulated-vision-deficiency', '', Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.RENDERING, 'emulate-auto-dark-mode', '', Common.Settings.SettingType.ENUM),\n createSettingValue(Common.Settings.SettingCategory.RENDERING, 'local-fonts-disabled', false),\n createSettingValue(Common.Settings.SettingCategory.RENDERING, 'show-paint-rects', false),\n createSettingValue(Common.Settings.SettingCategory.RENDERING, 'show-layout-shift-regions', false),\n createSettingValue(Common.Settings.SettingCategory.RENDERING, 'show-ad-highlights', false),\n createSettingValue(Common.Settings.SettingCategory.RENDERING, 'show-debug-borders', false),\n createSettingValue(Common.Settings.SettingCategory.RENDERING, 'show-fps-counter', false),\n createSettingValue(Common.Settings.SettingCategory.RENDERING, 'show-scroll-bottleneck-rects', false),\n createSettingValue(Common.Settings.SettingCategory.RENDERING, 'show-web-vitals', false),\n createSettingValue(Common.Settings.SettingCategory.RENDERING, 'webp-format-disabled', false),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'allow-scroll-past-eof', true),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'css-source-maps-enabled', true),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'inline-variable-values', true),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'auto-pretty-print-minified', true),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'js-source-maps-enabled', true),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'show-whitespaces-in-editor', 'none'),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'text-editor-autocompletion', true),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'text-editor-auto-detect-indent', false),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'text-editor-bracket-closing', true),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'text-editor-bracket-matching', true),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'text-editor-code-folding', true),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'text-editor-indent', ' '),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'text-editor-tab-moves-focus', false),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'dom-word-wrap', true),\n createSettingValue(\n Common.Settings.SettingCategory.EMULATION, 'emulation.touch', '', Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.EMULATION, 'emulation.idle-detection', '', Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.GRID, 'show-grid-line-labels', 'none', Common.Settings.SettingType.ENUM),\n createSettingValue(Common.Settings.SettingCategory.GRID, 'extend-grid-lines', true),\n createSettingValue(Common.Settings.SettingCategory.GRID, 'show-grid-areas', true),\n createSettingValue(Common.Settings.SettingCategory.GRID, 'show-grid-track-sizes', true),\n createSettingValue(\n Common.Settings.SettingCategory.NONE, 'active-keybind-set', '', Common.Settings.SettingType.ENUM),\n createSettingValue(Common.Settings.SettingCategory.NONE, 'user-shortcuts', [], Common.Settings.SettingType.ARRAY),\n createSettingValue(\n Common.Settings.SettingCategory.APPEARANCE, 'help.show-release-note', true,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(Common.Settings.SettingCategory.NETWORK, 'request-blocking-enabled', false),\n createSettingValue(Common.Settings.SettingCategory.CONSOLE, 'monitoring-xhr-enabled', false),\n createSettingValue(\n Common.Settings.SettingCategory.NONE, 'custom-network-conditions', [], Common.Settings.SettingType.ARRAY),\n createSettingValue(\n Common.Settings.SettingCategory.APPEARANCE, 'ui-theme', 'systemPreferred', Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.APPEARANCE, 'language', 'en-US', Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.PERSISTENCE, 'persistence-network-overrides-enabled', true,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.NETWORK, 'network-log.preserve-log', true, Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.NETWORK, 'network-log.record-log', true, Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.SOURCES, 'network.enable-remote-file-loading', false,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'hide-network-messages', false, Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'selected-context-filter-enabled', false,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'console-group-similar', false, Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'console-shows-cors-errors', false,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'console-timestamps-enabled', false,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'console-insights-enabled', false,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'console-insights-onboarding-finished', false,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'console-history-autocomplete', false,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'console-autocomplete-on-enter', false,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'preserve-console-log', false, Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'console-eager-eval', false, Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'console-user-activation-eval', false,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'console-trace-expand', false, Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.PERFORMANCE, 'flamechart-mouse-wheel-action', false,\n Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.ELEMENTS, 'show-css-property-documentation-on-hover', false,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.NONE, 'freestyler-dogfood-consent-onboarding-finished', false,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'freestyler-enabled', false, Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.MOBILE, 'emulation.show-device-outline', false,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.APPEARANCE, 'chrome-theme-colors', true, Common.Settings.SettingType.BOOLEAN),\n ];\n\n Common.Settings.registerSettingsForTest(settings, reset);\n\n // Instantiate the storage.\n const storage = new Common.Settings.SettingsStorage({}, Common.Settings.NOOP_STORAGE, 'test');\n Common.Settings.Settings.instance(\n {forceNew: reset, syncedStorage: storage, globalStorage: storage, localStorage: storage});\n\n Root.Runtime.experiments.clearForTest();\n for (const experimentName of REGISTERED_EXPERIMENTS) {\n Root.Runtime.experiments.register(experimentName, '');\n }\n\n // Dynamically import UI after the rest of the environment is set up, otherwise it will fail.\n UI = await import('../ui/legacy/legacy.js');\n UI.ZoomManager.ZoomManager.instance(\n {forceNew: true, win: window, frontendHost: Host.InspectorFrontendHost.InspectorFrontendHostInstance});\n\n // Initialize theme support and context menus.\n Common.Settings.Settings.instance().createSetting('uiTheme', 'systemPreferred');\n UI.UIUtils.initializeUIUtils(document);\n}\n\nexport async function deinitializeGlobalVars() {\n // Remove the global SDK.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n const globalObject = (globalThis as unknown as {SDK?: {}, ls?: {}});\n delete globalObject.SDK;\n delete globalObject.ls;\n\n for (const target of SDK.TargetManager.TargetManager.instance().targets()) {\n target.dispose('deinitializeGlobalVars');\n }\n\n // Remove instances.\n await deinitializeGlobalLocaleVars();\n Logs.NetworkLog.NetworkLog.removeInstance();\n SDK.TargetManager.TargetManager.removeInstance();\n Root.Runtime.Runtime.removeInstance();\n Common.Settings.Settings.removeInstance();\n Common.Revealer.RevealerRegistry.removeInstance();\n Common.Console.Console.removeInstance();\n Workspace.Workspace.WorkspaceImpl.removeInstance();\n Bindings.IgnoreListManager.IgnoreListManager.removeInstance();\n Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.removeInstance();\n Bindings.CSSWorkspaceBinding.CSSWorkspaceBinding.removeInstance();\n IssuesManager.IssuesManager.IssuesManager.removeInstance();\n Persistence.IsolatedFileSystemManager.IsolatedFileSystemManager.removeInstance();\n\n Common.Settings.resetSettings();\n\n // Protect against the dynamic import not having happened.\n if (UI) {\n UI.ZoomManager.ZoomManager.removeInstance();\n UI.ViewManager.ViewManager.removeInstance();\n UI.ViewManager.resetViewRegistration();\n UI.Context.Context.removeInstance();\n UI.InspectorView.InspectorView.removeInstance();\n UI.ActionRegistry.ActionRegistry.reset();\n }\n\n Root.Runtime.experiments.clearForTest();\n}\n\nexport function describeWithEnvironment(title: string, fn: (this: Mocha.Suite) => void, opts: {reset: boolean} = {\n reset: true,\n}) {\n return describe(title, function() {\n before(async () => await initializeGlobalVars(opts));\n fn.call(this);\n after(async () => await deinitializeGlobalVars());\n });\n}\n\ndescribeWithEnvironment.only = function(title: string, fn: (this: Mocha.Suite) => void, opts: {reset: boolean} = {\n reset: true,\n}) {\n // eslint-disable-next-line mocha/no-exclusive-tests\n return describe.only(title, function() {\n before(async () => await initializeGlobalVars(opts));\n fn.call(this);\n after(async () => await deinitializeGlobalVars());\n });\n};\n\nexport async function initializeGlobalLocaleVars() {\n // Expose the locale.\n i18n.DevToolsLocale.DevToolsLocale.instance({\n create: true,\n data: {\n navigatorLanguage: 'en-US',\n settingLanguage: 'en-US',\n lookupClosestDevToolsLocale: () => 'en-US',\n },\n });\n\n if (i18n.i18n.hasLocaleDataForTest('en-US')) {\n return;\n }\n\n // Load the strings from the resource file.\n try {\n await i18n.i18n.fetchAndRegisterLocaleData('en-US');\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn('EnvironmentHelper: Loading en-US locale failed', error.message);\n }\n}\n\nexport function deinitializeGlobalLocaleVars() {\n i18n.DevToolsLocale.DevToolsLocale.removeInstance();\n}\n\nexport function describeWithLocale(title: string, fn: (this: Mocha.Suite) => void) {\n return describe(title, function() {\n before(async () => await initializeGlobalLocaleVars());\n fn.call(this);\n after(deinitializeGlobalLocaleVars);\n });\n}\ndescribeWithLocale.only = function(title: string, fn: (this: Mocha.Suite) => void) {\n // eslint-disable-next-line mocha/no-exclusive-tests\n return describe.only(title, function() {\n before(async () => await initializeGlobalLocaleVars());\n fn.call(this);\n after(deinitializeGlobalLocaleVars);\n });\n};\ndescribeWithLocale.skip = function(title: string, fn: (this: Mocha.Suite) => void) {\n // eslint-disable-next-line rulesdir/check_test_definitions\n return describe.skip(title, function() {\n fn.call(this);\n });\n};\n\nexport function createFakeSetting(name: string, defaultValue: T): Common.Settings.Setting {\n const storage = new Common.Settings.SettingsStorage({}, Common.Settings.NOOP_STORAGE, 'test');\n return new Common.Settings.Setting(name, defaultValue, new Common.ObjectWrapper.ObjectWrapper(), storage);\n}\n\nexport function enableFeatureForTest(feature: string): void {\n Root.Runtime.experiments.enableForTest(feature);\n}\n\nexport function setupActionRegistry() {\n before(function() {\n const actionRegistry = UI.ActionRegistry.ActionRegistry.instance();\n UI.ShortcutRegistry.ShortcutRegistry.instance({\n forceNew: true,\n actionRegistry,\n });\n });\n after(function() {\n if (UI) {\n UI.ShortcutRegistry.ShortcutRegistry.removeInstance();\n UI.ActionRegistry.ActionRegistry.removeInstance();\n }\n });\n}\n\nexport function expectConsoleLogs(expectedLogs: {warn?: string[], log?: string[], error?: string[]}) {\n const {error, warn, log} = console;\n before(() => {\n if (expectedLogs.log) {\n // eslint-disable-next-line no-console\n console.log = (...data: unknown[]) => {\n if (!expectedLogs.log?.includes(data.join(' '))) {\n log(...data);\n }\n };\n }\n if (expectedLogs.warn) {\n console.warn = (...data: unknown[]) => {\n if (!expectedLogs.warn?.includes(data.join(' '))) {\n warn(...data);\n }\n };\n }\n if (expectedLogs.error) {\n console.error = (...data: unknown[]) => {\n if (!expectedLogs.error?.includes(data.join(' '))) {\n error(...data);\n }\n };\n }\n });\n after(() => {\n if (expectedLogs.log) {\n // eslint-disable-next-line no-console\n console.log = log;\n }\n if (expectedLogs.warn) {\n console.warn = warn;\n }\n if (expectedLogs.error) {\n console.error = error;\n }\n });\n}\n\nexport function getGetHostConfigStub(config: Root.Runtime.HostConfig): sinon.SinonStub {\n const settings = Common.Settings.Settings.instance();\n return sinon.stub(settings, 'getHostConfig').returns({\n aidaAvailability: {\n disallowLogging: false,\n ...config.aidaAvailability,\n },\n devToolsConsoleInsights: {\n enabled: false,\n modelId: '',\n temperature: 0.2,\n ...config.devToolsConsoleInsights,\n } as Root.Runtime.HostConfigConsoleInsights,\n devToolsFreestylerDogfood: {\n modelId: '',\n temperature: 0,\n enabled: false,\n ...config.devToolsFreestylerDogfood,\n } as Root.Runtime.HostConfigFreestylerDogfood,\n devToolsVeLogging: {\n enabled: true,\n testing: false,\n },\n devToolsPrivacyUI: {\n enabled: false,\n ...config.devToolsPrivacyUI,\n } as Root.Runtime.HostConfigPrivacyUI,\n isOffTheRecord: false,\n });\n}\n"]} \ No newline at end of file +{"version":3,"file":"EnvironmentHelpers.js","sourceRoot":"","sources":["../../../../../front_end/testing/EnvironmentHelpers.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../core/common/common.js';\nimport * as Host from '../core/host/host.js';\nimport * as i18n from '../core/i18n/i18n.js';\nimport type * as Platform from '../core/platform/platform.js';\nimport * as Root from '../core/root/root.js';\nimport * as SDK from '../core/sdk/sdk.js';\nimport type * as Protocol from '../generated/protocol.js';\nimport * as Bindings from '../models/bindings/bindings.js';\nimport * as IssuesManager from '../models/issues_manager/issues_manager.js';\nimport * as Logs from '../models/logs/logs.js';\nimport * as Persistence from '../models/persistence/persistence.js';\nimport * as Workspace from '../models/workspace/workspace.js';\nimport type * as UIModule from '../ui/legacy/legacy.js';\n\n// Don't import UI at this stage because it will fail without\n// the environment. Instead we do the import at the end of the\n// initialization phase.\n// eslint-disable-next-line @typescript-eslint/naming-convention\nlet UI: typeof UIModule;\n\nlet uniqueTargetId = 0;\n\nexport function createTarget(\n {id, name, type = SDK.Target.Type.FRAME, parentTarget, subtype, url = 'http://example.com'}: {\n id?: Protocol.Target.TargetID,\n name?: string,\n type?: SDK.Target.Type,\n parentTarget?: SDK.Target.Target,\n subtype?: string,\n url?: string,\n } = {}) {\n if (!id) {\n if (!uniqueTargetId++) {\n id = 'test' as Protocol.Target.TargetID;\n } else {\n id = ('test' + uniqueTargetId) as Protocol.Target.TargetID;\n }\n }\n const targetManager = SDK.TargetManager.TargetManager.instance();\n return targetManager.createTarget(\n id, name ?? id, type, parentTarget ? parentTarget : null, /* sessionId=*/ parentTarget ? id : undefined,\n /* suspended=*/ false,\n /* connection=*/ undefined, {targetId: id, url, subtype} as Protocol.Target.TargetInfo);\n}\n\nfunction createSettingValue(\n category: Common.Settings.SettingCategory, settingName: string, defaultValue: unknown,\n settingType = Common.Settings.SettingType.BOOLEAN): Common.Settings.SettingRegistration {\n return {category, settingName, defaultValue, settingType};\n}\n\nexport function stubNoopSettings() {\n sinon.stub(Common.Settings.Settings, 'instance').returns({\n createSetting: () => ({\n get: () => [],\n set: () => {},\n addChangeListener: () => {},\n removeChangeListener: () => {},\n setDisabled: () => {},\n setTitle: () => {},\n title: () => {},\n asRegExp: () => {},\n type: () => Common.Settings.SettingType.BOOLEAN,\n getAsArray: () => [],\n }),\n moduleSetting: () => ({\n get: () => [],\n set: () => {},\n addChangeListener: () => {},\n removeChangeListener: () => {},\n setDisabled: () => {},\n setTitle: () => {},\n title: () => {},\n asRegExp: () => {},\n type: () => Common.Settings.SettingType.BOOLEAN,\n getAsArray: () => [],\n }),\n createLocalSetting: () => ({\n get: () => [],\n set: () => {},\n addChangeListener: () => {},\n removeChangeListener: () => {},\n setDisabled: () => {},\n setTitle: () => {},\n title: () => {},\n asRegExp: () => {},\n type: () => Common.Settings.SettingType.BOOLEAN,\n getAsArray: () => [],\n }),\n getHostConfig: () => {},\n } as unknown as Common.Settings.Settings);\n}\n\nexport function registerNoopActions(actionIds: string[]): void {\n for (const actionId of actionIds) {\n UI.ActionRegistration.maybeRemoveActionExtension(actionId);\n UI.ActionRegistration.registerActionExtension({\n actionId,\n category: UI.ActionRegistration.ActionCategory.NONE,\n title: () => 'mock' as Platform.UIString.LocalizedString,\n });\n }\n const actionRegistryInstance = UI.ActionRegistry.ActionRegistry.instance({forceNew: true});\n UI.ShortcutRegistry.ShortcutRegistry.instance({forceNew: true, actionRegistry: actionRegistryInstance});\n}\n\nconst REGISTERED_EXPERIMENTS = [\n Root.Runtime.ExperimentName.CAPTURE_NODE_CREATION_STACKS,\n Root.Runtime.ExperimentName.PROTOCOL_MONITOR,\n 'timeline-show-all-events',\n 'timeline-v8-runtime-call-stats',\n 'timeline-invalidation-tracking',\n Root.Runtime.ExperimentName.INSTRUMENTATION_BREAKPOINTS,\n 'css-type-component-length-deprecate',\n Root.Runtime.ExperimentName.STYLES_PANE_CSS_CHANGES,\n Root.Runtime.ExperimentName.HEADER_OVERRIDES,\n Root.Runtime.ExperimentName.HIGHLIGHT_ERRORS_ELEMENTS_PANEL,\n Root.Runtime.ExperimentName.USE_SOURCE_MAP_SCOPES,\n 'font-editor',\n Root.Runtime.ExperimentName.NETWORK_PANEL_FILTER_BAR_REDESIGN,\n Root.Runtime.ExperimentName.AUTOFILL_VIEW,\n Root.Runtime.ExperimentName.TIMELINE_ANNOTATIONS,\n Root.Runtime.ExperimentName.TIMELINE_INSIGHTS,\n Root.Runtime.ExperimentName.TIMELINE_DEBUG_MODE,\n Root.Runtime.ExperimentName.TIMELINE_OBSERVATIONS,\n Root.Runtime.ExperimentName.TIMELINE_SERVER_TIMINGS,\n Root.Runtime.ExperimentName.FULL_ACCESSIBILITY_TREE,\n Root.Runtime.ExperimentName.TIMELINE_SHOW_POST_MESSAGE_EVENTS,\n Root.Runtime.ExperimentName.TIMELINE_ENHANCED_TRACES,\n Root.Runtime.ExperimentName.GEN_AI_SETTINGS_PANEL,\n Root.Runtime.ExperimentName.TIMELINE_LAYOUT_SHIFT_DETAILS,\n Root.Runtime.ExperimentName.EXTENSION_STORAGE_VIEWER,\n];\n\nexport async function initializeGlobalVars({reset = true} = {}) {\n await initializeGlobalLocaleVars();\n\n // Create the appropriate settings needed to boot.\n const settings = [\n createSettingValue(\n Common.Settings.SettingCategory.ADORNER, 'adorner-settings', [], Common.Settings.SettingType.ARRAY),\n createSettingValue(Common.Settings.SettingCategory.APPEARANCE, 'disable-paused-state-overlay', false),\n createSettingValue(\n Common.Settings.SettingCategory.APPEARANCE, 'sidebar-position', 'auto', Common.Settings.SettingType.ENUM),\n createSettingValue(Common.Settings.SettingCategory.CONSOLE, 'custom-formatters', false),\n createSettingValue(Common.Settings.SettingCategory.DEBUGGER, 'pause-on-exception-enabled', false),\n createSettingValue(Common.Settings.SettingCategory.DEBUGGER, 'pause-on-caught-exception', false),\n createSettingValue(Common.Settings.SettingCategory.DEBUGGER, 'pause-on-uncaught-exception', false),\n createSettingValue(Common.Settings.SettingCategory.DEBUGGER, 'disable-async-stack-traces', false),\n createSettingValue(Common.Settings.SettingCategory.DEBUGGER, 'breakpoints-active', true),\n createSettingValue(Common.Settings.SettingCategory.DEBUGGER, 'java-script-disabled', false),\n createSettingValue(Common.Settings.SettingCategory.DEBUGGER, 'skip-content-scripts', true),\n createSettingValue(\n Common.Settings.SettingCategory.DEBUGGER, 'automatically-ignore-list-known-third-party-scripts', true),\n createSettingValue(Common.Settings.SettingCategory.DEBUGGER, 'enable-ignore-listing', true),\n createSettingValue(\n Common.Settings.SettingCategory.DEBUGGER, 'skip-stack-frames-pattern', '/node_modules/|/bower_components/',\n Common.Settings.SettingType.REGEX),\n createSettingValue(Common.Settings.SettingCategory.DEBUGGER, 'navigator-group-by-folder', true),\n createSettingValue(Common.Settings.SettingCategory.ELEMENTS, 'show-detailed-inspect-tooltip', true),\n createSettingValue(Common.Settings.SettingCategory.ELEMENTS, 'show-html-comments', true),\n createSettingValue(Common.Settings.SettingCategory.ELEMENTS, 'show-ua-shadow-dom', false),\n createSettingValue(Common.Settings.SettingCategory.PERFORMANCE, 'annotations-hidden', false),\n createSettingValue(Common.Settings.SettingCategory.NETWORK, 'cache-disabled', false),\n createSettingValue(Common.Settings.SettingCategory.RENDERING, 'avif-format-disabled', false),\n createSettingValue(\n Common.Settings.SettingCategory.RENDERING, 'emulated-css-media', '', Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.RENDERING, 'emulated-css-media-feature-prefers-color-scheme', '',\n Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.RENDERING, 'emulated-css-media-feature-forced-colors', '',\n Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.RENDERING, 'emulated-css-media-feature-prefers-reduced-motion', '',\n Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.RENDERING, 'emulated-css-media-feature-prefers-contrast', '',\n Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.RENDERING, 'emulated-css-media-feature-prefers-reduced-data', '',\n Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.RENDERING, 'emulated-css-media-feature-prefers-reduced-transparency', '',\n Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.RENDERING, 'emulated-css-media-feature-color-gamut', '',\n Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.RENDERING, 'emulated-vision-deficiency', '', Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.RENDERING, 'emulate-auto-dark-mode', '', Common.Settings.SettingType.ENUM),\n createSettingValue(Common.Settings.SettingCategory.RENDERING, 'local-fonts-disabled', false),\n createSettingValue(Common.Settings.SettingCategory.RENDERING, 'show-paint-rects', false),\n createSettingValue(Common.Settings.SettingCategory.RENDERING, 'show-layout-shift-regions', false),\n createSettingValue(Common.Settings.SettingCategory.RENDERING, 'show-ad-highlights', false),\n createSettingValue(Common.Settings.SettingCategory.RENDERING, 'show-debug-borders', false),\n createSettingValue(Common.Settings.SettingCategory.RENDERING, 'show-fps-counter', false),\n createSettingValue(Common.Settings.SettingCategory.RENDERING, 'show-scroll-bottleneck-rects', false),\n createSettingValue(Common.Settings.SettingCategory.RENDERING, 'webp-format-disabled', false),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'allow-scroll-past-eof', true),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'css-source-maps-enabled', true),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'inline-variable-values', true),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'auto-pretty-print-minified', true),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'js-source-maps-enabled', true),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'show-whitespaces-in-editor', 'none'),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'text-editor-autocompletion', true),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'text-editor-auto-detect-indent', false),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'text-editor-bracket-closing', true),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'text-editor-bracket-matching', true),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'text-editor-code-folding', true),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'text-editor-indent', ' '),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'text-editor-tab-moves-focus', false),\n createSettingValue(Common.Settings.SettingCategory.SOURCES, 'dom-word-wrap', true),\n createSettingValue(\n Common.Settings.SettingCategory.EMULATION, 'emulation.touch', '', Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.EMULATION, 'emulation.idle-detection', '', Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.GRID, 'show-grid-line-labels', 'none', Common.Settings.SettingType.ENUM),\n createSettingValue(Common.Settings.SettingCategory.GRID, 'extend-grid-lines', true),\n createSettingValue(Common.Settings.SettingCategory.GRID, 'show-grid-areas', true),\n createSettingValue(Common.Settings.SettingCategory.GRID, 'show-grid-track-sizes', true),\n createSettingValue(\n Common.Settings.SettingCategory.NONE, 'active-keybind-set', '', Common.Settings.SettingType.ENUM),\n createSettingValue(Common.Settings.SettingCategory.NONE, 'user-shortcuts', [], Common.Settings.SettingType.ARRAY),\n createSettingValue(\n Common.Settings.SettingCategory.APPEARANCE, 'help.show-release-note', true,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(Common.Settings.SettingCategory.NETWORK, 'request-blocking-enabled', false),\n createSettingValue(Common.Settings.SettingCategory.CONSOLE, 'monitoring-xhr-enabled', false),\n createSettingValue(\n Common.Settings.SettingCategory.NONE, 'custom-network-conditions', [], Common.Settings.SettingType.ARRAY),\n createSettingValue(\n Common.Settings.SettingCategory.APPEARANCE, 'ui-theme', 'systemPreferred', Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.APPEARANCE, 'language', 'en-US', Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.PERSISTENCE, 'persistence-network-overrides-enabled', true,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.NETWORK, 'network-log.preserve-log', true, Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.NETWORK, 'network-log.record-log', true, Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.SOURCES, 'network.enable-remote-file-loading', false,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'hide-network-messages', false, Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'selected-context-filter-enabled', false,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'console-group-similar', false, Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'console-shows-cors-errors', false,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'console-timestamps-enabled', false,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'console-insights-enabled', false,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'console-insights-onboarding-finished', false,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'console-history-autocomplete', false,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'console-autocomplete-on-enter', false,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'preserve-console-log', false, Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'console-eager-eval', false, Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'console-user-activation-eval', false,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'console-trace-expand', false, Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.PERFORMANCE, 'flamechart-mouse-wheel-action', false,\n Common.Settings.SettingType.ENUM),\n createSettingValue(\n Common.Settings.SettingCategory.ELEMENTS, 'show-css-property-documentation-on-hover', false,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.NONE, 'freestyler-dogfood-consent-onboarding-finished', false,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.CONSOLE, 'freestyler-enabled', false, Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.MOBILE, 'emulation.show-device-outline', false,\n Common.Settings.SettingType.BOOLEAN),\n createSettingValue(\n Common.Settings.SettingCategory.APPEARANCE, 'chrome-theme-colors', true, Common.Settings.SettingType.BOOLEAN),\n ];\n\n Common.Settings.registerSettingsForTest(settings, reset);\n\n // Instantiate the storage.\n const storage = new Common.Settings.SettingsStorage({}, Common.Settings.NOOP_STORAGE, 'test');\n Common.Settings.Settings.instance(\n {forceNew: reset, syncedStorage: storage, globalStorage: storage, localStorage: storage});\n\n Root.Runtime.experiments.clearForTest();\n for (const experimentName of REGISTERED_EXPERIMENTS) {\n Root.Runtime.experiments.register(experimentName, '');\n }\n\n // Dynamically import UI after the rest of the environment is set up, otherwise it will fail.\n UI = await import('../ui/legacy/legacy.js');\n UI.ZoomManager.ZoomManager.instance(\n {forceNew: true, win: window, frontendHost: Host.InspectorFrontendHost.InspectorFrontendHostInstance});\n\n // Initialize theme support and context menus.\n Common.Settings.Settings.instance().createSetting('uiTheme', 'systemPreferred');\n UI.UIUtils.initializeUIUtils(document);\n}\n\nexport async function deinitializeGlobalVars() {\n // Remove the global SDK.\n // eslint-disable-next-line @typescript-eslint/naming-convention\n const globalObject = (globalThis as unknown as {SDK?: {}, ls?: {}});\n delete globalObject.SDK;\n delete globalObject.ls;\n\n for (const target of SDK.TargetManager.TargetManager.instance().targets()) {\n target.dispose('deinitializeGlobalVars');\n }\n\n // Remove instances.\n await deinitializeGlobalLocaleVars();\n Logs.NetworkLog.NetworkLog.removeInstance();\n SDK.TargetManager.TargetManager.removeInstance();\n Root.Runtime.Runtime.removeInstance();\n Common.Settings.Settings.removeInstance();\n Common.Revealer.RevealerRegistry.removeInstance();\n Common.Console.Console.removeInstance();\n Workspace.Workspace.WorkspaceImpl.removeInstance();\n Bindings.IgnoreListManager.IgnoreListManager.removeInstance();\n Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.removeInstance();\n Bindings.CSSWorkspaceBinding.CSSWorkspaceBinding.removeInstance();\n IssuesManager.IssuesManager.IssuesManager.removeInstance();\n Persistence.IsolatedFileSystemManager.IsolatedFileSystemManager.removeInstance();\n\n Common.Settings.resetSettings();\n\n // Protect against the dynamic import not having happened.\n if (UI) {\n UI.ZoomManager.ZoomManager.removeInstance();\n UI.ViewManager.ViewManager.removeInstance();\n UI.ViewManager.resetViewRegistration();\n UI.Context.Context.removeInstance();\n UI.InspectorView.InspectorView.removeInstance();\n UI.ActionRegistry.ActionRegistry.reset();\n }\n\n Root.Runtime.experiments.clearForTest();\n}\n\nexport function describeWithEnvironment(title: string, fn: (this: Mocha.Suite) => void, opts: {reset: boolean} = {\n reset: true,\n}) {\n return describe(title, function() {\n before(async () => await initializeGlobalVars(opts));\n fn.call(this);\n after(async () => await deinitializeGlobalVars());\n });\n}\n\ndescribeWithEnvironment.only = function(title: string, fn: (this: Mocha.Suite) => void, opts: {reset: boolean} = {\n reset: true,\n}) {\n // eslint-disable-next-line mocha/no-exclusive-tests\n return describe.only(title, function() {\n before(async () => await initializeGlobalVars(opts));\n fn.call(this);\n after(async () => await deinitializeGlobalVars());\n });\n};\n\nexport async function initializeGlobalLocaleVars() {\n // Expose the locale.\n i18n.DevToolsLocale.DevToolsLocale.instance({\n create: true,\n data: {\n navigatorLanguage: 'en-US',\n settingLanguage: 'en-US',\n lookupClosestDevToolsLocale: () => 'en-US',\n },\n });\n\n if (i18n.i18n.hasLocaleDataForTest('en-US')) {\n return;\n }\n\n // Load the strings from the resource file.\n try {\n await i18n.i18n.fetchAndRegisterLocaleData('en-US');\n } catch (error) {\n // eslint-disable-next-line no-console\n console.warn('EnvironmentHelper: Loading en-US locale failed', error.message);\n }\n}\n\nexport function deinitializeGlobalLocaleVars() {\n i18n.DevToolsLocale.DevToolsLocale.removeInstance();\n}\n\nexport function describeWithLocale(title: string, fn: (this: Mocha.Suite) => void) {\n return describe(title, function() {\n before(async () => await initializeGlobalLocaleVars());\n fn.call(this);\n after(deinitializeGlobalLocaleVars);\n });\n}\ndescribeWithLocale.only = function(title: string, fn: (this: Mocha.Suite) => void) {\n // eslint-disable-next-line mocha/no-exclusive-tests\n return describe.only(title, function() {\n before(async () => await initializeGlobalLocaleVars());\n fn.call(this);\n after(deinitializeGlobalLocaleVars);\n });\n};\ndescribeWithLocale.skip = function(title: string, fn: (this: Mocha.Suite) => void) {\n // eslint-disable-next-line rulesdir/check_test_definitions\n return describe.skip(title, function() {\n fn.call(this);\n });\n};\n\nexport function createFakeSetting(name: string, defaultValue: T): Common.Settings.Setting {\n const storage = new Common.Settings.SettingsStorage({}, Common.Settings.NOOP_STORAGE, 'test');\n return new Common.Settings.Setting(name, defaultValue, new Common.ObjectWrapper.ObjectWrapper(), storage);\n}\n\nexport function enableFeatureForTest(feature: string): void {\n Root.Runtime.experiments.enableForTest(feature);\n}\n\nexport function setupActionRegistry() {\n before(function() {\n const actionRegistry = UI.ActionRegistry.ActionRegistry.instance();\n UI.ShortcutRegistry.ShortcutRegistry.instance({\n forceNew: true,\n actionRegistry,\n });\n });\n after(function() {\n if (UI) {\n UI.ShortcutRegistry.ShortcutRegistry.removeInstance();\n UI.ActionRegistry.ActionRegistry.removeInstance();\n }\n });\n}\n\nexport function expectConsoleLogs(expectedLogs: {warn?: string[], log?: string[], error?: string[]}) {\n const {error, warn, log} = console;\n before(() => {\n if (expectedLogs.log) {\n // eslint-disable-next-line no-console\n console.log = (...data: unknown[]) => {\n if (!expectedLogs.log?.includes(data.join(' '))) {\n log(...data);\n }\n };\n }\n if (expectedLogs.warn) {\n console.warn = (...data: unknown[]) => {\n if (!expectedLogs.warn?.includes(data.join(' '))) {\n warn(...data);\n }\n };\n }\n if (expectedLogs.error) {\n console.error = (...data: unknown[]) => {\n if (!expectedLogs.error?.includes(data.join(' '))) {\n error(...data);\n }\n };\n }\n });\n after(() => {\n if (expectedLogs.log) {\n // eslint-disable-next-line no-console\n console.log = log;\n }\n if (expectedLogs.warn) {\n console.warn = warn;\n }\n if (expectedLogs.error) {\n console.error = error;\n }\n });\n}\n\nexport function getGetHostConfigStub(config: Root.Runtime.HostConfig): sinon.SinonStub {\n const settings = Common.Settings.Settings.instance();\n return sinon.stub(settings, 'getHostConfig').returns({\n aidaAvailability: {\n disallowLogging: false,\n ...config.aidaAvailability,\n },\n devToolsConsoleInsights: {\n enabled: false,\n modelId: '',\n temperature: 0.2,\n ...config.devToolsConsoleInsights,\n } as Root.Runtime.HostConfigConsoleInsights,\n devToolsFreestylerDogfood: {\n modelId: '',\n temperature: 0,\n enabled: false,\n ...config.devToolsFreestylerDogfood,\n } as Root.Runtime.HostConfigFreestylerDogfood,\n devToolsVeLogging: {\n enabled: true,\n testing: false,\n },\n devToolsPrivacyUI: {\n enabled: false,\n ...config.devToolsPrivacyUI,\n } as Root.Runtime.HostConfigPrivacyUI,\n isOffTheRecord: false,\n });\n}\n"]} \ No newline at end of file diff --git a/public/testing/InsightHelpers.d.ts b/public/testing/InsightHelpers.d.ts new file mode 100644 index 000000000..5f74e7dec --- /dev/null +++ b/public/testing/InsightHelpers.d.ts @@ -0,0 +1,5 @@ +import * as Trace from '../models/trace/trace.js'; +export declare function createContextForNavigation(navigation: Trace.Types.Events.NavigationStart, frameId: string): Trace.Insights.Types.InsightSetContextWithNavigation; +export declare function getInsight(insightKey: Key, insights: Trace.Insights.Types.TraceInsightSets, navigation?: Trace.Types.Events.NavigationStart): Trace.Insights.Types.InsightResults[Key]; +export declare function getFirstOrError(iterator: IterableIterator): T; +export declare function getFirst(iterator: IterableIterator): T | undefined; diff --git a/public/testing/InsightHelpers.js b/public/testing/InsightHelpers.js new file mode 100644 index 000000000..6355cd6e1 --- /dev/null +++ b/public/testing/InsightHelpers.js @@ -0,0 +1,51 @@ +// Copyright 2024 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 * as Trace from '../models/trace/trace.js'; +export function createContextForNavigation(navigation, frameId) { + if (!navigation.args.data?.navigationId) { + throw new Error('expected navigationId'); + } + const min = navigation.ts; + const max = (navigation.ts + (navigation?.dur ?? 0)); + const bounds = Trace.Helpers.Timing.traceWindowFromMicroSeconds(min, max); + return { + bounds, + frameId, + navigation, + navigationId: navigation.args.data?.navigationId, + }; +} +export function getInsight(insightKey, insights, navigation) { + let key; + if (navigation) { + if (!navigation.args.data?.navigationId) { + throw new Error('expected navigationId'); + } + key = navigation.args.data.navigationId; + } + else { + key = Trace.Insights.Types.NO_NAVIGATION; + } + const insightSets = insights.get(key); + if (!insightSets) { + throw new Error('missing navInsights'); + } + const insight = insightSets.data[insightKey]; + if (insight instanceof Error) { + throw insight; + } + // For some reason typescript won't narrow the type by removing Error, so do it manually. + return insight; +} +export function getFirstOrError(iterator) { + const result = iterator.next(); + if (result.done || result.value === undefined) { + throw new Error('iterator has zero values'); + } + return result.value; +} +export function getFirst(iterator) { + return iterator.next().value; +} +//# sourceMappingURL=InsightHelpers.js.map \ No newline at end of file diff --git a/public/testing/InsightHelpers.js.map b/public/testing/InsightHelpers.js.map new file mode 100644 index 000000000..e202a86f6 --- /dev/null +++ b/public/testing/InsightHelpers.js.map @@ -0,0 +1 @@ +{"version":3,"file":"InsightHelpers.js","sourceRoot":"","sources":["../../../../../front_end/testing/InsightHelpers.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,KAAK,MAAM,0BAA0B,CAAC;AAElD,MAAM,UAAU,0BAA0B,CAAC,UAA8C,EAAE,OAAe;IAExG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,GAAG,GAAG,UAAU,CAAC,EAAE,CAAC;IAC1B,MAAM,GAAG,GAAG,CAAC,UAAU,CAAC,EAAE,GAAG,CAAC,UAAU,EAAE,GAAG,IAAI,CAAC,CAAC,CAAoC,CAAC;IACxF,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,2BAA2B,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;IAE1E,OAAO;QACL,MAAM;QACN,OAAO;QACP,UAAU;QACV,YAAY,EAAE,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY;KACjD,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CACtB,UAAe,EAAE,QAA+C,EAChE,UAA+C;IACjD,IAAI,GAAG,CAAC;IACR,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,EAAE,CAAC;YACxC,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAC3C,CAAC;QACD,GAAG,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC;IAC1C,CAAC;SAAM,CAAC;QACN,GAAG,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,aAAa,CAAC;IAC3C,CAAC;IAED,MAAM,WAAW,GAAG,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACzC,CAAC;IAED,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC7C,IAAI,OAAO,YAAY,KAAK,EAAE,CAAC;QAC7B,MAAM,OAAO,CAAC;IAChB,CAAC;IAED,yFAAyF;IACzF,OAAO,OAAmD,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,eAAe,CAAI,QAA6B;IAC9D,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC/B,IAAI,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,MAAM,CAAC,KAAK,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,QAAQ,CAAI,QAA6B;IACvD,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC;AAC/B,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../models/trace/trace.js';\n\nexport function createContextForNavigation(navigation: Trace.Types.Events.NavigationStart, frameId: string):\n Trace.Insights.Types.InsightSetContextWithNavigation {\n if (!navigation.args.data?.navigationId) {\n throw new Error('expected navigationId');\n }\n\n const min = navigation.ts;\n const max = (navigation.ts + (navigation?.dur ?? 0)) as Trace.Types.Timing.MicroSeconds;\n const bounds = Trace.Helpers.Timing.traceWindowFromMicroSeconds(min, max);\n\n return {\n bounds,\n frameId,\n navigation,\n navigationId: navigation.args.data?.navigationId,\n };\n}\n\nexport function getInsight(\n insightKey: Key, insights: Trace.Insights.Types.TraceInsightSets,\n navigation?: Trace.Types.Events.NavigationStart): Trace.Insights.Types.InsightResults[Key] {\n let key;\n if (navigation) {\n if (!navigation.args.data?.navigationId) {\n throw new Error('expected navigationId');\n }\n key = navigation.args.data.navigationId;\n } else {\n key = Trace.Insights.Types.NO_NAVIGATION;\n }\n\n const insightSets = insights.get(key);\n if (!insightSets) {\n throw new Error('missing navInsights');\n }\n\n const insight = insightSets.data[insightKey];\n if (insight instanceof Error) {\n throw insight;\n }\n\n // For some reason typescript won't narrow the type by removing Error, so do it manually.\n return insight as Trace.Insights.Types.InsightResults[Key];\n}\n\nexport function getFirstOrError(iterator: IterableIterator): T {\n const result = iterator.next();\n if (result.done || result.value === undefined) {\n throw new Error('iterator has zero values');\n }\n\n return result.value;\n}\n\nexport function getFirst(iterator: IterableIterator): T|undefined {\n return iterator.next().value;\n}\n"]} \ No newline at end of file diff --git a/public/testing/TraceHelpers.d.ts b/public/testing/TraceHelpers.d.ts index eaa37da5b..e4762692f 100644 --- a/public/testing/TraceHelpers.d.ts +++ b/public/testing/TraceHelpers.d.ts @@ -1,5 +1,5 @@ import * as Bindings from '../models/bindings/bindings.js'; -import * as TraceEngine from '../models/trace/trace.js'; +import * as Trace from '../models/trace/trace.js'; import * as Timeline from '../panels/timeline/timeline.js'; import * as PerfUI from '../ui/legacy/components/perf_ui/perf_ui.js'; export declare class MockFlameChartDelegate implements PerfUI.FlameChart.FlameChartDelegate { @@ -37,65 +37,65 @@ export declare function getNetworkFlameChart(traceFileName: string, expanded: bo flameChart: PerfUI.FlameChart.FlameChart; dataProvider: Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider; }>; -export declare const defaultTraceEvent: TraceEngine.Types.TraceEvents.TraceEventData; +export declare const defaultTraceEvent: Trace.Types.Events.Event; /** * Gets the tree in a thread. * @see RendererHandler.ts */ -export declare function getTree(thread: TraceEngine.Handlers.ModelHandlers.Renderer.RendererThread): TraceEngine.Helpers.TreeHelpers.TraceEntryTree; +export declare function getTree(thread: Trace.Handlers.ModelHandlers.Renderer.RendererThread): Trace.Helpers.TreeHelpers.TraceEntryTree; /** * Gets the n-th root from a tree in a thread. * @see RendererHandler.ts */ -export declare function getRootAt(thread: TraceEngine.Handlers.ModelHandlers.Renderer.RendererThread, index: number): TraceEngine.Helpers.TreeHelpers.TraceEntryNode; +export declare function getRootAt(thread: Trace.Handlers.ModelHandlers.Renderer.RendererThread, index: number): Trace.Helpers.TreeHelpers.TraceEntryNode; /** * Gets all nodes in a thread. To finish this task, we Walk through all the nodes, starting from the root node. */ -export declare function getAllNodes(roots: Set): TraceEngine.Helpers.TreeHelpers.TraceEntryNode[]; +export declare function getAllNodes(roots: Set): Trace.Helpers.TreeHelpers.TraceEntryNode[]; /** * Gets the node with an id from a tree in a thread. * @see RendererHandler.ts */ -export declare function getNodeFor(thread: TraceEngine.Handlers.ModelHandlers.Renderer.RendererThread, nodeId: TraceEngine.Helpers.TreeHelpers.TraceEntryNodeId): TraceEngine.Helpers.TreeHelpers.TraceEntryNode; +export declare function getNodeFor(thread: Trace.Handlers.ModelHandlers.Renderer.RendererThread, nodeId: Trace.Helpers.TreeHelpers.TraceEntryNodeId): Trace.Helpers.TreeHelpers.TraceEntryNode; /** * Gets all the `events` for the `nodes`. */ -export declare function getEventsIn(nodes: IterableIterator): TraceEngine.Types.TraceEvents.TraceEventData[]; +export declare function getEventsIn(nodes: IterableIterator): Trace.Types.Events.Event[]; /** * Pretty-prints a tree. */ -export declare function prettyPrint(tree: TraceEngine.Helpers.TreeHelpers.TraceEntryTree, predicate?: (node: TraceEngine.Helpers.TreeHelpers.TraceEntryNode, event: TraceEngine.Types.TraceEvents.TraceEventData) => boolean, indentation?: number, delimiter?: string, prefix?: string, newline?: string, out?: string): string; +export declare function prettyPrint(tree: Trace.Helpers.TreeHelpers.TraceEntryTree, predicate?: (node: Trace.Helpers.TreeHelpers.TraceEntryNode, event: Trace.Types.Events.Event) => boolean, indentation?: number, delimiter?: string, prefix?: string, newline?: string, out?: string): string; /** - * Builds a mock TraceEventComplete. + * Builds a mock Complete. */ -export declare function makeCompleteEvent(name: string, ts: number, dur: number, cat?: string, pid?: number, tid?: number): TraceEngine.Types.TraceEvents.TraceEventComplete; -export declare function makeAsyncStartEvent(name: string, ts: number, pid?: number, tid?: number): TraceEngine.Types.TraceEvents.TraceEventAsync; -export declare function makeAsyncEndEvent(name: string, ts: number, pid?: number, tid?: number): TraceEngine.Types.TraceEvents.TraceEventAsync; -export declare function makeCompleteEventInMilliseconds(name: string, tsMillis: number, durMillis: number, cat?: string, pid?: number, tid?: number): TraceEngine.Types.TraceEvents.TraceEventComplete; +export declare function makeCompleteEvent(name: string, ts: number, dur: number, cat?: string, pid?: number, tid?: number): Trace.Types.Events.Complete; +export declare function makeAsyncStartEvent(name: string, ts: number, pid?: number, tid?: number): Trace.Types.Events.Async; +export declare function makeAsyncEndEvent(name: string, ts: number, pid?: number, tid?: number): Trace.Types.Events.Async; +export declare function makeCompleteEventInMilliseconds(name: string, tsMillis: number, durMillis: number, cat?: string, pid?: number, tid?: number): Trace.Types.Events.Complete; /** - * Builds a mock TraceEventInstant. + * Builds a mock Instant. */ -export declare function makeInstantEvent(name: string, tsMicroseconds: number, cat?: string, pid?: number, tid?: number, s?: TraceEngine.Types.TraceEvents.TraceEventScope): TraceEngine.Types.TraceEvents.TraceEventInstant; +export declare function makeInstantEvent(name: string, tsMicroseconds: number, cat?: string, pid?: number, tid?: number, s?: Trace.Types.Events.Scope): Trace.Types.Events.Instant; /** - * Builds a mock TraceEventBegin. + * Builds a mock Begin. */ -export declare function makeBeginEvent(name: string, ts: number, cat?: string, pid?: number, tid?: number): TraceEngine.Types.TraceEvents.TraceEventBegin; +export declare function makeBeginEvent(name: string, ts: number, cat?: string, pid?: number, tid?: number): Trace.Types.Events.Begin; /** - * Builds a mock TraceEventEnd. + * Builds a mock End. */ -export declare function makeEndEvent(name: string, ts: number, cat?: string, pid?: number, tid?: number): TraceEngine.Types.TraceEvents.TraceEventEnd; -export declare function makeProfileCall(functionName: string, tsMs: number, durMs: number, pid?: TraceEngine.Types.TraceEvents.ProcessID, tid?: TraceEngine.Types.TraceEvents.ThreadID, nodeId?: number, url?: string): TraceEngine.Types.TraceEvents.SyntheticProfileCall; +export declare function makeEndEvent(name: string, ts: number, cat?: string, pid?: number, tid?: number): Trace.Types.Events.End; +export declare function makeProfileCall(functionName: string, tsMs: number, durMs: number, pid?: Trace.Types.Events.ProcessID, tid?: Trace.Types.Events.ThreadID, nodeId?: number, url?: string): Trace.Types.Events.SyntheticProfileCall; export declare const DevToolsTimelineCategory = "disabled-by-default-devtools.timeline"; /** * Mocks an object compatible with the return type of the * RendererHandler using only an array of ordered entries. */ -export declare function makeMockRendererHandlerData(entries: TraceEngine.Types.TraceEvents.TraceEventData[]): TraceEngine.Handlers.ModelHandlers.Renderer.RendererHandlerData; +export declare function makeMockRendererHandlerData(entries: Trace.Types.Events.Event[]): Trace.Handlers.ModelHandlers.Renderer.RendererHandlerData; /** * Mocks an object compatible with the return type of the * SamplesHandler using only an array of ordered profile calls. */ -export declare function makeMockSamplesHandlerData(profileCalls: TraceEngine.Types.TraceEvents.SyntheticProfileCall[]): TraceEngine.Handlers.ModelHandlers.Samples.SamplesHandlerData; +export declare function makeMockSamplesHandlerData(profileCalls: Trace.Types.Events.SyntheticProfileCall[]): Trace.Handlers.ModelHandlers.Samples.SamplesHandlerData; export declare class FakeFlameChartProvider implements PerfUI.FlameChart.FlameChartDataProvider { minimumBoundary(): number; hasTrackConfigurationMode(): boolean; @@ -112,15 +112,15 @@ export declare class FakeFlameChartProvider implements PerfUI.FlameChart.FlameCh textColor(_entryIndex: number): string; timelineData(): PerfUI.FlameChart.FlameChartTimelineData | null; } -export declare function getMainThread(data: TraceEngine.Handlers.ModelHandlers.Renderer.RendererHandlerData): TraceEngine.Handlers.ModelHandlers.Renderer.RendererThread; -type TraceParseData = TraceEngine.Handlers.Types.TraceParseData; -export declare function getBaseTraceParseModelData(overrides?: Partial): TraceParseData; +export declare function getMainThread(data: Trace.Handlers.ModelHandlers.Renderer.RendererHandlerData): Trace.Handlers.ModelHandlers.Renderer.RendererThread; +type ParsedTrace = Trace.Handlers.Types.ParsedTrace; +export declare function getBaseTraceParseModelData(overrides?: Partial): ParsedTrace; /** * A helper that will query the given array of events and find the first event * matching the predicate. It will also assert that a match is found, which * saves the need to do that for every test. */ -export declare function getEventOfType(events: TraceEngine.Types.TraceEvents.TraceEventData[], predicate: (e: TraceEngine.Types.TraceEvents.TraceEventData) => e is T): T; +export declare function getEventOfType(events: Trace.Types.Events.Event[], predicate: (e: Trace.Types.Events.Event) => e is T): T; /** * The Performance Panel is integrated with the IgnoreListManager so in tests * that render a flame chart or a track appender, it needs to be setup to avoid diff --git a/public/testing/TraceHelpers.js b/public/testing/TraceHelpers.js index cc6d00acb..5520e9179 100644 --- a/public/testing/TraceHelpers.js +++ b/public/testing/TraceHelpers.js @@ -4,7 +4,7 @@ import * as SDK from '../core/sdk/sdk.js'; import * as Bindings from '../models/bindings/bindings.js'; import * as CPUProfile from '../models/cpu_profile/cpu_profile.js'; -import * as TraceEngine from '../models/trace/trace.js'; +import * as Trace from '../models/trace/trace.js'; import * as Workspace from '../models/workspace/workspace.js'; import * as Timeline from '../panels/timeline/timeline.js'; import * as PerfUI from '../ui/legacy/components/perf_ui/perf_ui.js'; @@ -38,18 +38,18 @@ export class MockFlameChartDelegate { export async function getMainFlameChartWithTracks(traceFileName, trackAppenderNames, expanded, trackName) { await initializeGlobalVars(); // This function is used to load a component example. - const { traceData } = await TraceLoader.traceEngine(/* context= */ null, traceFileName); + const { parsedTrace } = await TraceLoader.traceEngine(/* context= */ null, traceFileName); const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider(); // The data provider still needs a reference to the legacy model to // work properly. - dataProvider.setModel(traceData); + dataProvider.setModel(parsedTrace); const tracksAppender = dataProvider.compatibilityTracksAppenderInstance(); tracksAppender.setVisibleTracks(trackAppenderNames); dataProvider.buildFromTrackAppenders({ filterThreadsByName: trackName, expandedTracks: expanded ? trackAppenderNames : undefined }); const delegate = new MockFlameChartDelegate(); const flameChart = new PerfUI.FlameChart.FlameChart(dataProvider, delegate); - const minTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min); - const maxTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max); + const minTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min); + const maxTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max); flameChart.setWindowTimes(minTime, maxTime); flameChart.markAsRoot(); flameChart.update(); @@ -65,11 +65,11 @@ export async function getMainFlameChartWithTracks(traceFileName, trackAppenderNa */ export async function getNetworkFlameChart(traceFileName, expanded) { await initializeGlobalVars(); - const { traceData } = await TraceLoader.traceEngine(/* context= */ null, traceFileName); - const minTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min); - const maxTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max); + const { parsedTrace } = await TraceLoader.traceEngine(/* context= */ null, traceFileName); + const minTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min); + const maxTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max); const dataProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider(); - dataProvider.setModel(traceData); + dataProvider.setModel(parsedTrace); dataProvider.setWindowTimes(minTime, maxTime); dataProvider.timelineData().groups.forEach(group => { group.expanded = expanded; @@ -85,11 +85,11 @@ export async function getNetworkFlameChart(traceFileName, expanded) { // test will import this default event and copy-override properties at will. export const defaultTraceEvent = { name: 'process_name', - tid: TraceEngine.Types.TraceEvents.ThreadID(0), - pid: TraceEngine.Types.TraceEvents.ProcessID(0), - ts: TraceEngine.Types.Timing.MicroSeconds(0), + tid: Trace.Types.Events.ThreadID(0), + pid: Trace.Types.Events.ProcessID(0), + ts: Trace.Types.Timing.MicroSeconds(0), cat: 'test', - ph: "M" /* TraceEngine.Types.TraceEvents.Phase.METADATA */, + ph: "M" /* Trace.Types.Events.Phase.METADATA */, }; /** * Gets the tree in a thread. @@ -138,7 +138,7 @@ export function getNodeFor(thread, nodeId) { function findNode(nodes, nodeId) { for (const node of nodes) { const event = node.entry; - if (TraceEngine.Types.TraceEvents.isProfileCall(event) && event.nodeId === nodeId) { + if (Trace.Types.Events.isProfileCall(event) && event.nodeId === nodeId) { return node; } return findNode(node.children, nodeId); @@ -173,10 +173,8 @@ export function prettyPrint(tree, predicate = () => true, indentation = 2, delim } skipped = false; const spacing = new Array(node.depth * indentation).fill(delimiter).join(''); - const eventType = TraceEngine.Types.TraceEvents.isTraceEventDispatch(event) ? `(${event.args.data?.type})` : false; - const jsFunctionName = TraceEngine.Types.TraceEvents.isProfileCall(event) ? - `(${event.callFrame.functionName || 'anonymous'})` : - false; + const eventType = Trace.Types.Events.isDispatch(event) ? `(${event.args.data?.type})` : false; + const jsFunctionName = Trace.Types.Events.isProfileCall(event) ? `(${event.callFrame.functionName || 'anonymous'})` : false; const duration = `[${(event.dur || 0) / 1000}ms]`; const info = [jsFunctionName, eventType, duration].filter(Boolean); out += `${newline}${spacing}${prefix}${event.name} ${info.join(' ')}`; @@ -186,18 +184,18 @@ export function prettyPrint(tree, predicate = () => true, indentation = 2, delim } } /** - * Builds a mock TraceEventComplete. + * Builds a mock Complete. */ export function makeCompleteEvent(name, ts, dur, cat = '*', pid = 0, tid = 0) { return { args: {}, cat, name, - ph: "X" /* TraceEngine.Types.TraceEvents.Phase.COMPLETE */, - pid: TraceEngine.Types.TraceEvents.ProcessID(pid), - tid: TraceEngine.Types.TraceEvents.ThreadID(tid), - ts: TraceEngine.Types.Timing.MicroSeconds(ts), - dur: TraceEngine.Types.Timing.MicroSeconds(dur), + ph: "X" /* Trace.Types.Events.Phase.COMPLETE */, + pid: Trace.Types.Events.ProcessID(pid), + tid: Trace.Types.Events.ThreadID(tid), + ts: Trace.Types.Timing.MicroSeconds(ts), + dur: Trace.Types.Timing.MicroSeconds(dur), }; } export function makeAsyncStartEvent(name, ts, pid = 0, tid = 0) { @@ -205,10 +203,10 @@ export function makeAsyncStartEvent(name, ts, pid = 0, tid = 0) { args: {}, cat: '*', name, - ph: "b" /* TraceEngine.Types.TraceEvents.Phase.ASYNC_NESTABLE_START */, - pid: TraceEngine.Types.TraceEvents.ProcessID(pid), - tid: TraceEngine.Types.TraceEvents.ThreadID(tid), - ts: TraceEngine.Types.Timing.MicroSeconds(ts), + ph: "b" /* Trace.Types.Events.Phase.ASYNC_NESTABLE_START */, + pid: Trace.Types.Events.ProcessID(pid), + tid: Trace.Types.Events.ThreadID(tid), + ts: Trace.Types.Timing.MicroSeconds(ts), }; } export function makeAsyncEndEvent(name, ts, pid = 0, tid = 0) { @@ -216,70 +214,70 @@ export function makeAsyncEndEvent(name, ts, pid = 0, tid = 0) { args: {}, cat: '*', name, - ph: "e" /* TraceEngine.Types.TraceEvents.Phase.ASYNC_NESTABLE_END */, - pid: TraceEngine.Types.TraceEvents.ProcessID(pid), - tid: TraceEngine.Types.TraceEvents.ThreadID(tid), - ts: TraceEngine.Types.Timing.MicroSeconds(ts), + ph: "e" /* Trace.Types.Events.Phase.ASYNC_NESTABLE_END */, + pid: Trace.Types.Events.ProcessID(pid), + tid: Trace.Types.Events.ThreadID(tid), + ts: Trace.Types.Timing.MicroSeconds(ts), }; } export function makeCompleteEventInMilliseconds(name, tsMillis, durMillis, cat = '*', pid = 0, tid = 0) { - return makeCompleteEvent(name, TraceEngine.Helpers.Timing.millisecondsToMicroseconds(TraceEngine.Types.Timing.MilliSeconds(tsMillis)), TraceEngine.Helpers.Timing.millisecondsToMicroseconds(TraceEngine.Types.Timing.MilliSeconds(durMillis)), cat, pid, tid); + return makeCompleteEvent(name, Trace.Helpers.Timing.millisecondsToMicroseconds(Trace.Types.Timing.MilliSeconds(tsMillis)), Trace.Helpers.Timing.millisecondsToMicroseconds(Trace.Types.Timing.MilliSeconds(durMillis)), cat, pid, tid); } /** - * Builds a mock TraceEventInstant. + * Builds a mock Instant. */ -export function makeInstantEvent(name, tsMicroseconds, cat = '', pid = 0, tid = 0, s = "t" /* TraceEngine.Types.TraceEvents.TraceEventScope.THREAD */) { +export function makeInstantEvent(name, tsMicroseconds, cat = '', pid = 0, tid = 0, s = "t" /* Trace.Types.Events.Scope.THREAD */) { return { args: {}, cat, name, - ph: "I" /* TraceEngine.Types.TraceEvents.Phase.INSTANT */, - pid: TraceEngine.Types.TraceEvents.ProcessID(pid), - tid: TraceEngine.Types.TraceEvents.ThreadID(tid), - ts: TraceEngine.Types.Timing.MicroSeconds(tsMicroseconds), + ph: "I" /* Trace.Types.Events.Phase.INSTANT */, + pid: Trace.Types.Events.ProcessID(pid), + tid: Trace.Types.Events.ThreadID(tid), + ts: Trace.Types.Timing.MicroSeconds(tsMicroseconds), s, }; } /** - * Builds a mock TraceEventBegin. + * Builds a mock Begin. */ export function makeBeginEvent(name, ts, cat = '*', pid = 0, tid = 0) { return { args: {}, cat, name, - ph: "B" /* TraceEngine.Types.TraceEvents.Phase.BEGIN */, - pid: TraceEngine.Types.TraceEvents.ProcessID(pid), - tid: TraceEngine.Types.TraceEvents.ThreadID(tid), - ts: TraceEngine.Types.Timing.MicroSeconds(ts), + ph: "B" /* Trace.Types.Events.Phase.BEGIN */, + pid: Trace.Types.Events.ProcessID(pid), + tid: Trace.Types.Events.ThreadID(tid), + ts: Trace.Types.Timing.MicroSeconds(ts), }; } /** - * Builds a mock TraceEventEnd. + * Builds a mock End. */ export function makeEndEvent(name, ts, cat = '*', pid = 0, tid = 0) { return { args: {}, cat, name, - ph: "E" /* TraceEngine.Types.TraceEvents.Phase.END */, - pid: TraceEngine.Types.TraceEvents.ProcessID(pid), - tid: TraceEngine.Types.TraceEvents.ThreadID(tid), - ts: TraceEngine.Types.Timing.MicroSeconds(ts), + ph: "E" /* Trace.Types.Events.Phase.END */, + pid: Trace.Types.Events.ProcessID(pid), + tid: Trace.Types.Events.ThreadID(tid), + ts: Trace.Types.Timing.MicroSeconds(ts), }; } -export function makeProfileCall(functionName, tsMs, durMs, pid = TraceEngine.Types.TraceEvents.ProcessID(0), tid = TraceEngine.Types.TraceEvents.ThreadID(0), nodeId = 0, url = '') { +export function makeProfileCall(functionName, tsMs, durMs, pid = Trace.Types.Events.ProcessID(0), tid = Trace.Types.Events.ThreadID(0), nodeId = 0, url = '') { return { cat: '', name: 'ProfileCall', nodeId, sampleIndex: 0, - profileId: TraceEngine.Types.TraceEvents.ProfileID('fake-profile-id'), - ph: "X" /* TraceEngine.Types.TraceEvents.Phase.COMPLETE */, + profileId: Trace.Types.Events.ProfileID('fake-profile-id'), + ph: "X" /* Trace.Types.Events.Phase.COMPLETE */, pid, tid, - ts: TraceEngine.Types.Timing.MicroSeconds(tsMs), - dur: TraceEngine.Types.Timing.MicroSeconds(durMs), + ts: Trace.Types.Timing.MicroSeconds(tsMs), + dur: Trace.Types.Timing.MicroSeconds(durMs), callFrame: { functionName, scriptId: '', @@ -296,12 +294,12 @@ export const DevToolsTimelineCategory = 'disabled-by-default-devtools.timeline'; * RendererHandler using only an array of ordered entries. */ export function makeMockRendererHandlerData(entries) { - const { tree, entryToNode } = TraceEngine.Helpers.TreeHelpers.treify(entries, { filter: { has: () => true } }); + const { tree, entryToNode } = Trace.Helpers.TreeHelpers.treify(entries, { filter: { has: () => true } }); const mockThread = { tree, name: 'thread', entries, - profileCalls: entries.filter(TraceEngine.Types.TraceEvents.isProfileCall), + profileCalls: entries.filter(Trace.Types.Events.isProfileCall), }; const mockProcess = { url: 'url', @@ -310,7 +308,7 @@ export function makeMockRendererHandlerData(entries) { }; const renderereEvents = []; for (const entry of entries) { - if (TraceEngine.Types.TraceEvents.isTraceEventRendererEvent(entry)) { + if (Trace.Types.Events.isRendererEvent(entry)) { renderereEvents.push(entry); } } @@ -326,11 +324,11 @@ export function makeMockRendererHandlerData(entries) { * SamplesHandler using only an array of ordered profile calls. */ export function makeMockSamplesHandlerData(profileCalls) { - const { tree, entryToNode } = TraceEngine.Helpers.TreeHelpers.treify(profileCalls, { filter: { has: () => true } }); + const { tree, entryToNode } = Trace.Helpers.TreeHelpers.treify(profileCalls, { filter: { has: () => true } }); const profile = { nodes: [], - startTime: profileCalls.at(0)?.ts || TraceEngine.Types.Timing.MicroSeconds(0), - endTime: profileCalls.at(-1)?.ts || TraceEngine.Types.Timing.MicroSeconds(10e5), + startTime: profileCalls.at(0)?.ts || Trace.Types.Timing.MicroSeconds(0), + endTime: profileCalls.at(-1)?.ts || Trace.Types.Timing.MicroSeconds(10e5), samples: [], timeDeltas: [], }; @@ -355,7 +353,7 @@ export function makeMockSamplesHandlerData(profileCalls) { parsedProfile: new CPUProfile.CPUProfileDataModel.CPUProfileDataModel(profile), profileCalls, profileTree: tree, - profileId: TraceEngine.Types.TraceEvents.ProfileID('fake-profile-id'), + profileId: Trace.Types.Events.ProfileID('fake-profile-id'), }; const profilesInThread = new Map([[1, profileData]]); return { @@ -446,14 +444,14 @@ export function getBaseTraceParseModelData(overrides = {}) { }, Meta: { traceBounds: { - min: TraceEngine.Types.Timing.MicroSeconds(0), - max: TraceEngine.Types.Timing.MicroSeconds(100), - range: TraceEngine.Types.Timing.MicroSeconds(100), + min: Trace.Types.Timing.MicroSeconds(0), + max: Trace.Types.Timing.MicroSeconds(100), + range: Trace.Types.Timing.MicroSeconds(100), }, - browserProcessId: TraceEngine.Types.TraceEvents.ProcessID(-1), - browserThreadId: TraceEngine.Types.TraceEvents.ThreadID(-1), - gpuProcessId: TraceEngine.Types.TraceEvents.ProcessID(-1), - gpuThreadId: TraceEngine.Types.TraceEvents.ThreadID(-1), + browserProcessId: Trace.Types.Events.ProcessID(-1), + browserThreadId: Trace.Types.Events.ThreadID(-1), + gpuProcessId: Trace.Types.Events.ProcessID(-1), + gpuThreadId: Trace.Types.Events.ThreadID(-1), threadsInProcess: new Map(), navigationsByFrameId: new Map(), navigationsByNavigationId: new Map(), diff --git a/public/testing/TraceHelpers.js.map b/public/testing/TraceHelpers.js.map index c1bfdc456..d83e68be4 100644 --- a/public/testing/TraceHelpers.js.map +++ b/public/testing/TraceHelpers.js.map @@ -1 +1 @@ -{"version":3,"file":"TraceHelpers.js","sourceRoot":"","sources":["../../../../../front_end/testing/TraceHelpers.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as SDK from '../core/sdk/sdk.js';\nimport type * as Protocol from '../generated/protocol.js';\nimport * as Bindings from '../models/bindings/bindings.js';\nimport * as CPUProfile from '../models/cpu_profile/cpu_profile.js';\nimport * as TraceEngine from '../models/trace/trace.js';\nimport * as Workspace from '../models/workspace/workspace.js';\nimport * as Timeline from '../panels/timeline/timeline.js';\nimport * as PerfUI from '../ui/legacy/components/perf_ui/perf_ui.js';\n\nimport {initializeGlobalVars} from './EnvironmentHelpers.js';\nimport {TraceLoader} from './TraceLoader.js';\n\n// This mock class is used for instancing a flame chart in the helpers.\n// Its implementation is empty because the methods aren't used by the\n// helpers, only the mere definition.\nexport class MockFlameChartDelegate implements PerfUI.FlameChart.FlameChartDelegate {\n windowChanged(_startTime: number, _endTime: number, _animate: boolean): void {\n }\n updateRangeSelection(_startTime: number, _endTime: number): void {\n }\n updateSelectedGroup(_flameChart: PerfUI.FlameChart.FlameChart, _group: PerfUI.FlameChart.Group|null): void {\n }\n}\n\n/**\n * Draws a set of tracks track in the flame chart using the new system.\n * For this to work, every track that will be rendered must have a\n * corresponding track appender registered in the\n * CompatibilityTracksAppender.\n *\n * @param traceFileName The name of the trace file to be loaded into the\n * flame chart.\n * @param trackAppenderNames A Set with the names of the tracks to be\n * rendered. For example, Set(\"Timings\").\n * @param expanded whether the track should be expanded\n * @param trackName optional param to filter tracks by their name.\n * @returns a flame chart element and its corresponding data provider.\n */\nexport async function getMainFlameChartWithTracks(\n traceFileName: string, trackAppenderNames: Set,\n expanded: boolean, trackName?: string): Promise<{\n flameChart: PerfUI.FlameChart.FlameChart,\n dataProvider: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider,\n}> {\n await initializeGlobalVars();\n\n // This function is used to load a component example.\n const {traceData} = await TraceLoader.traceEngine(/* context= */ null, traceFileName);\n\n const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();\n // The data provider still needs a reference to the legacy model to\n // work properly.\n dataProvider.setModel(traceData);\n const tracksAppender = dataProvider.compatibilityTracksAppenderInstance();\n tracksAppender.setVisibleTracks(trackAppenderNames);\n dataProvider.buildFromTrackAppenders(\n {filterThreadsByName: trackName, expandedTracks: expanded ? trackAppenderNames : undefined});\n const delegate = new MockFlameChartDelegate();\n const flameChart = new PerfUI.FlameChart.FlameChart(dataProvider, delegate);\n const minTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min);\n const maxTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max);\n flameChart.setWindowTimes(minTime, maxTime);\n flameChart.markAsRoot();\n flameChart.update();\n return {flameChart, dataProvider};\n}\n\n/**\n * Draws the network track in the flame chart using the legacy system.\n *\n * @param traceFileName The name of the trace file to be loaded to the flame\n * chart.\n * @param expanded if the track is expanded\n * @returns a flame chart element and its corresponding data provider.\n */\nexport async function getNetworkFlameChart(traceFileName: string, expanded: boolean): Promise<{\n flameChart: PerfUI.FlameChart.FlameChart,\n dataProvider: Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider,\n}> {\n await initializeGlobalVars();\n\n const {traceData} = await TraceLoader.traceEngine(/* context= */ null, traceFileName);\n const minTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.min);\n const maxTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(traceData.Meta.traceBounds.max);\n const dataProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider();\n dataProvider.setModel(traceData);\n dataProvider.setWindowTimes(minTime, maxTime);\n dataProvider.timelineData().groups.forEach(group => {\n group.expanded = expanded;\n });\n\n const delegate = new MockFlameChartDelegate();\n const flameChart = new PerfUI.FlameChart.FlameChart(dataProvider, delegate);\n flameChart.setWindowTimes(minTime, maxTime);\n flameChart.markAsRoot();\n flameChart.update();\n return {flameChart, dataProvider};\n}\n\n// We create here a cross-test base trace event. It is assumed that each\n// test will import this default event and copy-override properties at will.\nexport const defaultTraceEvent: TraceEngine.Types.TraceEvents.TraceEventData = {\n name: 'process_name',\n tid: TraceEngine.Types.TraceEvents.ThreadID(0),\n pid: TraceEngine.Types.TraceEvents.ProcessID(0),\n ts: TraceEngine.Types.Timing.MicroSeconds(0),\n cat: 'test',\n ph: TraceEngine.Types.TraceEvents.Phase.METADATA,\n};\n\n/**\n * Gets the tree in a thread.\n * @see RendererHandler.ts\n */\nexport function getTree(thread: TraceEngine.Handlers.ModelHandlers.Renderer.RendererThread):\n TraceEngine.Helpers.TreeHelpers.TraceEntryTree {\n const tree = thread.tree;\n if (!tree) {\n assert(false, `Couldn't get tree in thread ${thread.name}`);\n }\n return tree;\n}\n\n/**\n * Gets the n-th root from a tree in a thread.\n * @see RendererHandler.ts\n */\nexport function getRootAt(thread: TraceEngine.Handlers.ModelHandlers.Renderer.RendererThread, index: number):\n TraceEngine.Helpers.TreeHelpers.TraceEntryNode {\n const tree = getTree(thread);\n const node = [...tree.roots][index];\n if (node === undefined) {\n assert(false, `Couldn't get the id of the root at index ${index} in thread ${thread.name}`);\n }\n return node;\n}\n\n/**\n * Gets all nodes in a thread. To finish this task, we Walk through all the nodes, starting from the root node.\n */\nexport function getAllNodes(roots: Set):\n TraceEngine.Helpers.TreeHelpers.TraceEntryNode[] {\n const allNodes: TraceEngine.Helpers.TreeHelpers.TraceEntryNode[] = [];\n\n const children: TraceEngine.Helpers.TreeHelpers.TraceEntryNode[] = Array.from(roots);\n while (children.length > 0) {\n const childNode = children.shift();\n if (childNode) {\n allNodes.push(childNode);\n children.push(...childNode.children);\n }\n }\n return allNodes;\n}\n\n/**\n * Gets the node with an id from a tree in a thread.\n * @see RendererHandler.ts\n */\nexport function getNodeFor(\n thread: TraceEngine.Handlers.ModelHandlers.Renderer.RendererThread,\n nodeId: TraceEngine.Helpers.TreeHelpers.TraceEntryNodeId): TraceEngine.Helpers.TreeHelpers.TraceEntryNode {\n const tree = getTree(thread);\n\n function findNode(\n nodes: Set|TraceEngine.Helpers.TreeHelpers.TraceEntryNode[],\n nodeId: TraceEngine.Helpers.TreeHelpers.TraceEntryNodeId): TraceEngine.Helpers.TreeHelpers.TraceEntryNode|\n undefined {\n for (const node of nodes) {\n const event = node.entry;\n if (TraceEngine.Types.TraceEvents.isProfileCall(event) && event.nodeId === nodeId) {\n return node;\n }\n return findNode(node.children, nodeId);\n }\n return undefined;\n }\n const node = findNode(tree.roots, nodeId);\n if (!node) {\n assert(false, `Couldn't get the node with id ${nodeId} in thread ${thread.name}`);\n }\n return node;\n}\n\n/**\n * Gets all the `events` for the `nodes`.\n */\nexport function getEventsIn(nodes: IterableIterator):\n TraceEngine.Types.TraceEvents.TraceEventData[] {\n return [...nodes].flatMap(node => node ? node.entry : []);\n}\n/**\n * Pretty-prints a tree.\n */\nexport function prettyPrint(\n tree: TraceEngine.Helpers.TreeHelpers.TraceEntryTree,\n predicate:\n (node: TraceEngine.Helpers.TreeHelpers.TraceEntryNode, event: TraceEngine.Types.TraceEvents.TraceEventData) =>\n boolean = () => true,\n indentation: number = 2, delimiter: string = ' ', prefix: string = '-', newline: string = '\\n',\n out: string = ''): string {\n let skipped = false;\n return printNodes(tree.roots);\n function printNodes(nodes: Set|\n TraceEngine.Helpers.TreeHelpers.TraceEntryNode[]): string {\n for (const node of nodes) {\n const event = node.entry;\n if (!predicate(node, event)) {\n out += `${!skipped ? newline : ''}.`;\n skipped = true;\n continue;\n }\n skipped = false;\n const spacing = new Array(node.depth * indentation).fill(delimiter).join('');\n const eventType =\n TraceEngine.Types.TraceEvents.isTraceEventDispatch(event) ? `(${event.args.data?.type})` : false;\n const jsFunctionName = TraceEngine.Types.TraceEvents.isProfileCall(event) ?\n `(${event.callFrame.functionName || 'anonymous'})` :\n false;\n const duration = `[${(event.dur || 0) / 1000}ms]`;\n const info = [jsFunctionName, eventType, duration].filter(Boolean);\n out += `${newline}${spacing}${prefix}${event.name} ${info.join(' ')}`;\n out = printNodes(node.children);\n }\n return out;\n }\n}\n\n/**\n * Builds a mock TraceEventComplete.\n */\nexport function makeCompleteEvent(\n name: string, ts: number, dur: number, cat: string = '*', pid: number = 0,\n tid: number = 0): TraceEngine.Types.TraceEvents.TraceEventComplete {\n return {\n args: {},\n cat,\n name,\n ph: TraceEngine.Types.TraceEvents.Phase.COMPLETE,\n pid: TraceEngine.Types.TraceEvents.ProcessID(pid),\n tid: TraceEngine.Types.TraceEvents.ThreadID(tid),\n ts: TraceEngine.Types.Timing.MicroSeconds(ts),\n dur: TraceEngine.Types.Timing.MicroSeconds(dur),\n };\n}\n\nexport function makeAsyncStartEvent(\n name: string,\n ts: number,\n pid: number = 0,\n tid: number = 0,\n ): TraceEngine.Types.TraceEvents.TraceEventAsync {\n return {\n args: {},\n cat: '*',\n name,\n ph: TraceEngine.Types.TraceEvents.Phase.ASYNC_NESTABLE_START,\n pid: TraceEngine.Types.TraceEvents.ProcessID(pid),\n tid: TraceEngine.Types.TraceEvents.ThreadID(tid),\n ts: TraceEngine.Types.Timing.MicroSeconds(ts),\n };\n}\nexport function makeAsyncEndEvent(\n name: string,\n ts: number,\n pid: number = 0,\n tid: number = 0,\n ): TraceEngine.Types.TraceEvents.TraceEventAsync {\n return {\n args: {},\n cat: '*',\n name,\n ph: TraceEngine.Types.TraceEvents.Phase.ASYNC_NESTABLE_END,\n pid: TraceEngine.Types.TraceEvents.ProcessID(pid),\n tid: TraceEngine.Types.TraceEvents.ThreadID(tid),\n ts: TraceEngine.Types.Timing.MicroSeconds(ts),\n };\n}\n\nexport function makeCompleteEventInMilliseconds(\n name: string, tsMillis: number, durMillis: number, cat: string = '*', pid: number = 0,\n tid: number = 0): TraceEngine.Types.TraceEvents.TraceEventComplete {\n return makeCompleteEvent(\n name, TraceEngine.Helpers.Timing.millisecondsToMicroseconds(TraceEngine.Types.Timing.MilliSeconds(tsMillis)),\n TraceEngine.Helpers.Timing.millisecondsToMicroseconds(TraceEngine.Types.Timing.MilliSeconds(durMillis)), cat, pid,\n tid);\n}\n\n/**\n * Builds a mock TraceEventInstant.\n */\nexport function makeInstantEvent(\n name: string, tsMicroseconds: number, cat: string = '', pid: number = 0, tid: number = 0,\n s: TraceEngine.Types.TraceEvents.TraceEventScope =\n TraceEngine.Types.TraceEvents.TraceEventScope.THREAD): TraceEngine.Types.TraceEvents.TraceEventInstant {\n return {\n args: {},\n cat,\n name,\n ph: TraceEngine.Types.TraceEvents.Phase.INSTANT,\n pid: TraceEngine.Types.TraceEvents.ProcessID(pid),\n tid: TraceEngine.Types.TraceEvents.ThreadID(tid),\n ts: TraceEngine.Types.Timing.MicroSeconds(tsMicroseconds),\n s,\n };\n}\n\n/**\n * Builds a mock TraceEventBegin.\n */\nexport function makeBeginEvent(name: string, ts: number, cat: string = '*', pid: number = 0, tid: number = 0):\n TraceEngine.Types.TraceEvents.TraceEventBegin {\n return {\n args: {},\n cat,\n name,\n ph: TraceEngine.Types.TraceEvents.Phase.BEGIN,\n pid: TraceEngine.Types.TraceEvents.ProcessID(pid),\n tid: TraceEngine.Types.TraceEvents.ThreadID(tid),\n ts: TraceEngine.Types.Timing.MicroSeconds(ts),\n };\n}\n\n/**\n * Builds a mock TraceEventEnd.\n */\nexport function makeEndEvent(name: string, ts: number, cat: string = '*', pid: number = 0, tid: number = 0):\n TraceEngine.Types.TraceEvents.TraceEventEnd {\n return {\n args: {},\n cat,\n name,\n ph: TraceEngine.Types.TraceEvents.Phase.END,\n pid: TraceEngine.Types.TraceEvents.ProcessID(pid),\n tid: TraceEngine.Types.TraceEvents.ThreadID(tid),\n ts: TraceEngine.Types.Timing.MicroSeconds(ts),\n };\n}\n\nexport function makeProfileCall(\n functionName: string, tsMs: number, durMs: number,\n pid: TraceEngine.Types.TraceEvents.ProcessID = TraceEngine.Types.TraceEvents.ProcessID(0),\n tid: TraceEngine.Types.TraceEvents.ThreadID = TraceEngine.Types.TraceEvents.ThreadID(0), nodeId: number = 0,\n url: string = ''): TraceEngine.Types.TraceEvents.SyntheticProfileCall {\n return {\n cat: '',\n name: 'ProfileCall',\n nodeId,\n sampleIndex: 0,\n profileId: TraceEngine.Types.TraceEvents.ProfileID('fake-profile-id'),\n ph: TraceEngine.Types.TraceEvents.Phase.COMPLETE,\n pid,\n tid,\n ts: TraceEngine.Types.Timing.MicroSeconds(tsMs),\n dur: TraceEngine.Types.Timing.MicroSeconds(durMs),\n callFrame: {\n functionName,\n scriptId: '' as Protocol.Runtime.ScriptId,\n url,\n lineNumber: -1,\n columnNumber: -1,\n },\n args: {},\n };\n}\nexport const DevToolsTimelineCategory = 'disabled-by-default-devtools.timeline';\n\n/**\n * Mocks an object compatible with the return type of the\n * RendererHandler using only an array of ordered entries.\n */\nexport function makeMockRendererHandlerData(entries: TraceEngine.Types.TraceEvents.TraceEventData[]):\n TraceEngine.Handlers.ModelHandlers.Renderer.RendererHandlerData {\n const {tree, entryToNode} = TraceEngine.Helpers.TreeHelpers.treify(entries, {filter: {has: () => true}});\n const mockThread: TraceEngine.Handlers.ModelHandlers.Renderer.RendererThread = {\n tree,\n name: 'thread',\n entries,\n profileCalls: entries.filter(TraceEngine.Types.TraceEvents.isProfileCall),\n };\n\n const mockProcess: TraceEngine.Handlers.ModelHandlers.Renderer.RendererProcess = {\n url: 'url',\n isOnMainFrame: true,\n threads: new Map([[1 as TraceEngine.Types.TraceEvents.ThreadID, mockThread]]),\n };\n\n const renderereEvents: TraceEngine.Types.TraceEvents.TraceEventRendererEvent[] = [];\n for (const entry of entries) {\n if (TraceEngine.Types.TraceEvents.isTraceEventRendererEvent(entry)) {\n renderereEvents.push(entry);\n }\n }\n\n return {\n processes: new Map([[1 as TraceEngine.Types.TraceEvents.ProcessID, mockProcess]]),\n compositorTileWorkers: new Map(),\n entryToNode,\n allTraceEntries: renderereEvents,\n };\n}\n\n/**\n * Mocks an object compatible with the return type of the\n * SamplesHandler using only an array of ordered profile calls.\n */\nexport function makeMockSamplesHandlerData(profileCalls: TraceEngine.Types.TraceEvents.SyntheticProfileCall[]):\n TraceEngine.Handlers.ModelHandlers.Samples.SamplesHandlerData {\n const {tree, entryToNode} = TraceEngine.Helpers.TreeHelpers.treify(profileCalls, {filter: {has: () => true}});\n const profile: Protocol.Profiler.Profile = {\n nodes: [],\n startTime: profileCalls.at(0)?.ts || TraceEngine.Types.Timing.MicroSeconds(0),\n endTime: profileCalls.at(-1)?.ts || TraceEngine.Types.Timing.MicroSeconds(10e5),\n samples: [],\n timeDeltas: [],\n };\n\n const nodesIds = new Map();\n const lastTimestamp = profile.startTime;\n for (const profileCall of profileCalls) {\n let node = nodesIds.get(profileCall.nodeId);\n if (!node) {\n node = {\n id: profileCall.nodeId,\n callFrame: profileCall.callFrame,\n };\n profile.nodes.push(node);\n nodesIds.set(profileCall.nodeId, node);\n }\n profile.samples?.push(node.id);\n const timeDelta = profileCall.ts - lastTimestamp;\n profile.timeDeltas?.push(timeDelta);\n }\n const profileData = {\n rawProfile: profile,\n parsedProfile: new CPUProfile.CPUProfileDataModel.CPUProfileDataModel(profile),\n profileCalls,\n profileTree: tree,\n profileId: TraceEngine.Types.TraceEvents.ProfileID('fake-profile-id'),\n };\n const profilesInThread = new Map([[1 as TraceEngine.Types.TraceEvents.ThreadID, profileData]]);\n return {\n profilesInProcess: new Map([[1 as TraceEngine.Types.TraceEvents.ProcessID, profilesInThread]]),\n entryToNode,\n };\n}\n\nexport class FakeFlameChartProvider implements PerfUI.FlameChart.FlameChartDataProvider {\n minimumBoundary(): number {\n return 0;\n }\n\n hasTrackConfigurationMode(): boolean {\n return false;\n }\n\n totalTime(): number {\n return 100;\n }\n\n formatValue(value: number): string {\n return value.toString();\n }\n\n maxStackDepth(): number {\n return 3;\n }\n\n prepareHighlightedEntryInfo(_entryIndex: number): Element|null {\n return null;\n }\n\n canJumpToEntry(_entryIndex: number): boolean {\n return false;\n }\n\n entryTitle(entryIndex: number): string|null {\n return `Entry ${entryIndex}`;\n }\n\n entryFont(_entryIndex: number): string|null {\n return null;\n }\n\n entryColor(entryIndex: number): string {\n return [\n 'lightblue',\n 'lightpink',\n 'yellow',\n 'lightgray',\n 'lightgreen',\n 'lightsalmon',\n 'orange',\n 'pink',\n ][entryIndex % 8];\n }\n\n decorateEntry(): boolean {\n return false;\n }\n\n forceDecoration(_entryIndex: number): boolean {\n return false;\n }\n\n textColor(_entryIndex: number): string {\n return 'black';\n }\n\n timelineData(): PerfUI.FlameChart.FlameChartTimelineData|null {\n return PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n }\n}\n\nexport function getMainThread(data: TraceEngine.Handlers.ModelHandlers.Renderer.RendererHandlerData):\n TraceEngine.Handlers.ModelHandlers.Renderer.RendererThread {\n let mainThread: TraceEngine.Handlers.ModelHandlers.Renderer.RendererThread|null = null;\n for (const [, process] of data.processes) {\n for (const [, thread] of process.threads) {\n if (thread.name === 'CrRendererMain') {\n mainThread = thread;\n break;\n }\n }\n }\n if (!mainThread) {\n throw new Error('Could not find main thread.');\n }\n return mainThread;\n}\n\ntype TraceParseData = TraceEngine.Handlers.Types.TraceParseData;\n\nexport function getBaseTraceParseModelData(overrides: Partial = {}): TraceParseData {\n return {\n Animations: [],\n LayoutShifts: {\n clusters: [],\n sessionMaxScore: 0,\n clsWindowID: 0,\n prePaintEvents: [],\n layoutInvalidationEvents: [],\n styleRecalcInvalidationEvents: [],\n backendNodeIds: [],\n scoreRecords: [],\n },\n Meta: {\n traceBounds: {\n min: TraceEngine.Types.Timing.MicroSeconds(0),\n max: TraceEngine.Types.Timing.MicroSeconds(100),\n range: TraceEngine.Types.Timing.MicroSeconds(100),\n },\n browserProcessId: TraceEngine.Types.TraceEvents.ProcessID(-1),\n browserThreadId: TraceEngine.Types.TraceEvents.ThreadID(-1),\n gpuProcessId: TraceEngine.Types.TraceEvents.ProcessID(-1),\n gpuThreadId: TraceEngine.Types.TraceEvents.ThreadID(-1),\n threadsInProcess: new Map(),\n navigationsByFrameId: new Map(),\n navigationsByNavigationId: new Map(),\n mainFrameId: '',\n mainFrameURL: '',\n rendererProcessesByFrame: new Map(),\n topLevelRendererIds: new Set(),\n frameByProcessId: new Map(),\n mainFrameNavigations: [],\n },\n Renderer: {\n processes: new Map(),\n compositorTileWorkers: new Map(),\n entryToNode: new Map(),\n allTraceEntries: [],\n },\n Screenshots: [],\n Samples: {\n profiles: new Map(),\n processes: new Map(),\n },\n PageLoadMetrics: {metricScoresByFrameId: new Map(), lcpEventNodeIdToDOMNodeMap: new Map()},\n UserInteractions: {allEvents: [], interactionEvents: []},\n NetworkRequests: {\n byOrigin: new Map(),\n byTime: [],\n },\n GPU: {\n mainGPUThreadTasks: [],\n errorsByUseCase: new Map(),\n },\n UserTimings: {\n timings: [],\n },\n LargestImagePaint: new Map(),\n LargestTextPaint: new Map(),\n ...overrides,\n } as Partialas TraceParseData;\n}\n\n/**\n * A helper that will query the given array of events and find the first event\n * matching the predicate. It will also assert that a match is found, which\n * saves the need to do that for every test.\n */\nexport function getEventOfType(\n events: TraceEngine.Types.TraceEvents.TraceEventData[],\n predicate: (e: TraceEngine.Types.TraceEvents.TraceEventData) => e is T): T {\n const match = events.find(predicate);\n if (!match) {\n throw new Error('Failed to find matching event of type.');\n }\n return match;\n}\n\n/**\n * The Performance Panel is integrated with the IgnoreListManager so in tests\n * that render a flame chart or a track appender, it needs to be setup to avoid\n * errors.\n */\nexport function setupIgnoreListManagerEnvironment(): {\n ignoreListManager: Bindings.IgnoreListManager.IgnoreListManager,\n} {\n const targetManager = SDK.TargetManager.TargetManager.instance({forceNew: true});\n const workspace = Workspace.Workspace.WorkspaceImpl.instance({forceNew: true});\n const resourceMapping = new Bindings.ResourceMapping.ResourceMapping(targetManager, workspace);\n\n const debuggerWorkspaceBinding = Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance({\n forceNew: true,\n resourceMapping,\n targetManager,\n });\n\n const ignoreListManager = Bindings.IgnoreListManager.IgnoreListManager.instance({\n forceNew: true,\n debuggerWorkspaceBinding,\n });\n\n return {ignoreListManager};\n}\n"]} \ No newline at end of file +{"version":3,"file":"TraceHelpers.js","sourceRoot":"","sources":["../../../../../front_end/testing/TraceHelpers.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2022 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\nimport * as SDK from '../core/sdk/sdk.js';\nimport type * as Protocol from '../generated/protocol.js';\nimport * as Bindings from '../models/bindings/bindings.js';\nimport * as CPUProfile from '../models/cpu_profile/cpu_profile.js';\nimport * as Trace from '../models/trace/trace.js';\nimport * as Workspace from '../models/workspace/workspace.js';\nimport * as Timeline from '../panels/timeline/timeline.js';\nimport * as PerfUI from '../ui/legacy/components/perf_ui/perf_ui.js';\n\nimport {initializeGlobalVars} from './EnvironmentHelpers.js';\nimport {TraceLoader} from './TraceLoader.js';\n\n// This mock class is used for instancing a flame chart in the helpers.\n// Its implementation is empty because the methods aren't used by the\n// helpers, only the mere definition.\nexport class MockFlameChartDelegate implements PerfUI.FlameChart.FlameChartDelegate {\n windowChanged(_startTime: number, _endTime: number, _animate: boolean): void {\n }\n updateRangeSelection(_startTime: number, _endTime: number): void {\n }\n updateSelectedGroup(_flameChart: PerfUI.FlameChart.FlameChart, _group: PerfUI.FlameChart.Group|null): void {\n }\n}\n\n/**\n * Draws a set of tracks track in the flame chart using the new system.\n * For this to work, every track that will be rendered must have a\n * corresponding track appender registered in the\n * CompatibilityTracksAppender.\n *\n * @param traceFileName The name of the trace file to be loaded into the\n * flame chart.\n * @param trackAppenderNames A Set with the names of the tracks to be\n * rendered. For example, Set(\"Timings\").\n * @param expanded whether the track should be expanded\n * @param trackName optional param to filter tracks by their name.\n * @returns a flame chart element and its corresponding data provider.\n */\nexport async function getMainFlameChartWithTracks(\n traceFileName: string, trackAppenderNames: Set,\n expanded: boolean, trackName?: string): Promise<{\n flameChart: PerfUI.FlameChart.FlameChart,\n dataProvider: Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider,\n}> {\n await initializeGlobalVars();\n\n // This function is used to load a component example.\n const {parsedTrace} = await TraceLoader.traceEngine(/* context= */ null, traceFileName);\n\n const dataProvider = new Timeline.TimelineFlameChartDataProvider.TimelineFlameChartDataProvider();\n // The data provider still needs a reference to the legacy model to\n // work properly.\n dataProvider.setModel(parsedTrace);\n const tracksAppender = dataProvider.compatibilityTracksAppenderInstance();\n tracksAppender.setVisibleTracks(trackAppenderNames);\n dataProvider.buildFromTrackAppenders(\n {filterThreadsByName: trackName, expandedTracks: expanded ? trackAppenderNames : undefined});\n const delegate = new MockFlameChartDelegate();\n const flameChart = new PerfUI.FlameChart.FlameChart(dataProvider, delegate);\n const minTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min);\n const maxTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max);\n flameChart.setWindowTimes(minTime, maxTime);\n flameChart.markAsRoot();\n flameChart.update();\n return {flameChart, dataProvider};\n}\n\n/**\n * Draws the network track in the flame chart using the legacy system.\n *\n * @param traceFileName The name of the trace file to be loaded to the flame\n * chart.\n * @param expanded if the track is expanded\n * @returns a flame chart element and its corresponding data provider.\n */\nexport async function getNetworkFlameChart(traceFileName: string, expanded: boolean): Promise<{\n flameChart: PerfUI.FlameChart.FlameChart,\n dataProvider: Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider,\n}> {\n await initializeGlobalVars();\n\n const {parsedTrace} = await TraceLoader.traceEngine(/* context= */ null, traceFileName);\n const minTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.min);\n const maxTime = Trace.Helpers.Timing.microSecondsToMilliseconds(parsedTrace.Meta.traceBounds.max);\n const dataProvider = new Timeline.TimelineFlameChartNetworkDataProvider.TimelineFlameChartNetworkDataProvider();\n dataProvider.setModel(parsedTrace);\n dataProvider.setWindowTimes(minTime, maxTime);\n dataProvider.timelineData().groups.forEach(group => {\n group.expanded = expanded;\n });\n\n const delegate = new MockFlameChartDelegate();\n const flameChart = new PerfUI.FlameChart.FlameChart(dataProvider, delegate);\n flameChart.setWindowTimes(minTime, maxTime);\n flameChart.markAsRoot();\n flameChart.update();\n return {flameChart, dataProvider};\n}\n\n// We create here a cross-test base trace event. It is assumed that each\n// test will import this default event and copy-override properties at will.\nexport const defaultTraceEvent: Trace.Types.Events.Event = {\n name: 'process_name',\n tid: Trace.Types.Events.ThreadID(0),\n pid: Trace.Types.Events.ProcessID(0),\n ts: Trace.Types.Timing.MicroSeconds(0),\n cat: 'test',\n ph: Trace.Types.Events.Phase.METADATA,\n};\n\n/**\n * Gets the tree in a thread.\n * @see RendererHandler.ts\n */\nexport function getTree(thread: Trace.Handlers.ModelHandlers.Renderer.RendererThread):\n Trace.Helpers.TreeHelpers.TraceEntryTree {\n const tree = thread.tree;\n if (!tree) {\n assert(false, `Couldn't get tree in thread ${thread.name}`);\n }\n return tree;\n}\n\n/**\n * Gets the n-th root from a tree in a thread.\n * @see RendererHandler.ts\n */\nexport function getRootAt(thread: Trace.Handlers.ModelHandlers.Renderer.RendererThread, index: number):\n Trace.Helpers.TreeHelpers.TraceEntryNode {\n const tree = getTree(thread);\n const node = [...tree.roots][index];\n if (node === undefined) {\n assert(false, `Couldn't get the id of the root at index ${index} in thread ${thread.name}`);\n }\n return node;\n}\n\n/**\n * Gets all nodes in a thread. To finish this task, we Walk through all the nodes, starting from the root node.\n */\nexport function getAllNodes(roots: Set):\n Trace.Helpers.TreeHelpers.TraceEntryNode[] {\n const allNodes: Trace.Helpers.TreeHelpers.TraceEntryNode[] = [];\n\n const children: Trace.Helpers.TreeHelpers.TraceEntryNode[] = Array.from(roots);\n while (children.length > 0) {\n const childNode = children.shift();\n if (childNode) {\n allNodes.push(childNode);\n children.push(...childNode.children);\n }\n }\n return allNodes;\n}\n\n/**\n * Gets the node with an id from a tree in a thread.\n * @see RendererHandler.ts\n */\nexport function getNodeFor(\n thread: Trace.Handlers.ModelHandlers.Renderer.RendererThread,\n nodeId: Trace.Helpers.TreeHelpers.TraceEntryNodeId): Trace.Helpers.TreeHelpers.TraceEntryNode {\n const tree = getTree(thread);\n\n function findNode(\n nodes: Set|Trace.Helpers.TreeHelpers.TraceEntryNode[],\n nodeId: Trace.Helpers.TreeHelpers.TraceEntryNodeId): Trace.Helpers.TreeHelpers.TraceEntryNode|undefined {\n for (const node of nodes) {\n const event = node.entry;\n if (Trace.Types.Events.isProfileCall(event) && event.nodeId === nodeId) {\n return node;\n }\n return findNode(node.children, nodeId);\n }\n return undefined;\n }\n const node = findNode(tree.roots, nodeId);\n if (!node) {\n assert(false, `Couldn't get the node with id ${nodeId} in thread ${thread.name}`);\n }\n return node;\n}\n\n/**\n * Gets all the `events` for the `nodes`.\n */\nexport function getEventsIn(nodes: IterableIterator):\n Trace.Types.Events.Event[] {\n return [...nodes].flatMap(node => node ? node.entry : []);\n}\n/**\n * Pretty-prints a tree.\n */\nexport function prettyPrint(\n tree: Trace.Helpers.TreeHelpers.TraceEntryTree,\n predicate: (node: Trace.Helpers.TreeHelpers.TraceEntryNode, event: Trace.Types.Events.Event) => boolean = () =>\n true,\n indentation: number = 2, delimiter: string = ' ', prefix: string = '-', newline: string = '\\n',\n out: string = ''): string {\n let skipped = false;\n return printNodes(tree.roots);\n function printNodes(nodes: Set|\n Trace.Helpers.TreeHelpers.TraceEntryNode[]): string {\n for (const node of nodes) {\n const event = node.entry;\n if (!predicate(node, event)) {\n out += `${!skipped ? newline : ''}.`;\n skipped = true;\n continue;\n }\n skipped = false;\n const spacing = new Array(node.depth * indentation).fill(delimiter).join('');\n const eventType = Trace.Types.Events.isDispatch(event) ? `(${event.args.data?.type})` : false;\n const jsFunctionName =\n Trace.Types.Events.isProfileCall(event) ? `(${event.callFrame.functionName || 'anonymous'})` : false;\n const duration = `[${(event.dur || 0) / 1000}ms]`;\n const info = [jsFunctionName, eventType, duration].filter(Boolean);\n out += `${newline}${spacing}${prefix}${event.name} ${info.join(' ')}`;\n out = printNodes(node.children);\n }\n return out;\n }\n}\n\n/**\n * Builds a mock Complete.\n */\nexport function makeCompleteEvent(\n name: string, ts: number, dur: number, cat: string = '*', pid: number = 0,\n tid: number = 0): Trace.Types.Events.Complete {\n return {\n args: {},\n cat,\n name,\n ph: Trace.Types.Events.Phase.COMPLETE,\n pid: Trace.Types.Events.ProcessID(pid),\n tid: Trace.Types.Events.ThreadID(tid),\n ts: Trace.Types.Timing.MicroSeconds(ts),\n dur: Trace.Types.Timing.MicroSeconds(dur),\n };\n}\n\nexport function makeAsyncStartEvent(\n name: string,\n ts: number,\n pid: number = 0,\n tid: number = 0,\n ): Trace.Types.Events.Async {\n return {\n args: {},\n cat: '*',\n name,\n ph: Trace.Types.Events.Phase.ASYNC_NESTABLE_START,\n pid: Trace.Types.Events.ProcessID(pid),\n tid: Trace.Types.Events.ThreadID(tid),\n ts: Trace.Types.Timing.MicroSeconds(ts),\n };\n}\nexport function makeAsyncEndEvent(\n name: string,\n ts: number,\n pid: number = 0,\n tid: number = 0,\n ): Trace.Types.Events.Async {\n return {\n args: {},\n cat: '*',\n name,\n ph: Trace.Types.Events.Phase.ASYNC_NESTABLE_END,\n pid: Trace.Types.Events.ProcessID(pid),\n tid: Trace.Types.Events.ThreadID(tid),\n ts: Trace.Types.Timing.MicroSeconds(ts),\n };\n}\n\nexport function makeCompleteEventInMilliseconds(\n name: string, tsMillis: number, durMillis: number, cat: string = '*', pid: number = 0,\n tid: number = 0): Trace.Types.Events.Complete {\n return makeCompleteEvent(\n name, Trace.Helpers.Timing.millisecondsToMicroseconds(Trace.Types.Timing.MilliSeconds(tsMillis)),\n Trace.Helpers.Timing.millisecondsToMicroseconds(Trace.Types.Timing.MilliSeconds(durMillis)), cat, pid, tid);\n}\n\n/**\n * Builds a mock Instant.\n */\nexport function makeInstantEvent(\n name: string, tsMicroseconds: number, cat: string = '', pid: number = 0, tid: number = 0,\n s: Trace.Types.Events.Scope = Trace.Types.Events.Scope.THREAD): Trace.Types.Events.Instant {\n return {\n args: {},\n cat,\n name,\n ph: Trace.Types.Events.Phase.INSTANT,\n pid: Trace.Types.Events.ProcessID(pid),\n tid: Trace.Types.Events.ThreadID(tid),\n ts: Trace.Types.Timing.MicroSeconds(tsMicroseconds),\n s,\n };\n}\n\n/**\n * Builds a mock Begin.\n */\nexport function makeBeginEvent(\n name: string, ts: number, cat: string = '*', pid: number = 0, tid: number = 0): Trace.Types.Events.Begin {\n return {\n args: {},\n cat,\n name,\n ph: Trace.Types.Events.Phase.BEGIN,\n pid: Trace.Types.Events.ProcessID(pid),\n tid: Trace.Types.Events.ThreadID(tid),\n ts: Trace.Types.Timing.MicroSeconds(ts),\n };\n}\n\n/**\n * Builds a mock End.\n */\nexport function makeEndEvent(\n name: string, ts: number, cat: string = '*', pid: number = 0, tid: number = 0): Trace.Types.Events.End {\n return {\n args: {},\n cat,\n name,\n ph: Trace.Types.Events.Phase.END,\n pid: Trace.Types.Events.ProcessID(pid),\n tid: Trace.Types.Events.ThreadID(tid),\n ts: Trace.Types.Timing.MicroSeconds(ts),\n };\n}\n\nexport function makeProfileCall(\n functionName: string, tsMs: number, durMs: number,\n pid: Trace.Types.Events.ProcessID = Trace.Types.Events.ProcessID(0),\n tid: Trace.Types.Events.ThreadID = Trace.Types.Events.ThreadID(0), nodeId: number = 0,\n url: string = ''): Trace.Types.Events.SyntheticProfileCall {\n return {\n cat: '',\n name: 'ProfileCall',\n nodeId,\n sampleIndex: 0,\n profileId: Trace.Types.Events.ProfileID('fake-profile-id'),\n ph: Trace.Types.Events.Phase.COMPLETE,\n pid,\n tid,\n ts: Trace.Types.Timing.MicroSeconds(tsMs),\n dur: Trace.Types.Timing.MicroSeconds(durMs),\n callFrame: {\n functionName,\n scriptId: '' as Protocol.Runtime.ScriptId,\n url,\n lineNumber: -1,\n columnNumber: -1,\n },\n args: {},\n };\n}\nexport const DevToolsTimelineCategory = 'disabled-by-default-devtools.timeline';\n\n/**\n * Mocks an object compatible with the return type of the\n * RendererHandler using only an array of ordered entries.\n */\nexport function makeMockRendererHandlerData(entries: Trace.Types.Events.Event[]):\n Trace.Handlers.ModelHandlers.Renderer.RendererHandlerData {\n const {tree, entryToNode} = Trace.Helpers.TreeHelpers.treify(entries, {filter: {has: () => true}});\n const mockThread: Trace.Handlers.ModelHandlers.Renderer.RendererThread = {\n tree,\n name: 'thread',\n entries,\n profileCalls: entries.filter(Trace.Types.Events.isProfileCall),\n };\n\n const mockProcess: Trace.Handlers.ModelHandlers.Renderer.RendererProcess = {\n url: 'url',\n isOnMainFrame: true,\n threads: new Map([[1 as Trace.Types.Events.ThreadID, mockThread]]),\n };\n\n const renderereEvents: Trace.Types.Events.RendererEvent[] = [];\n for (const entry of entries) {\n if (Trace.Types.Events.isRendererEvent(entry)) {\n renderereEvents.push(entry);\n }\n }\n\n return {\n processes: new Map([[1 as Trace.Types.Events.ProcessID, mockProcess]]),\n compositorTileWorkers: new Map(),\n entryToNode,\n allTraceEntries: renderereEvents,\n };\n}\n\n/**\n * Mocks an object compatible with the return type of the\n * SamplesHandler using only an array of ordered profile calls.\n */\nexport function makeMockSamplesHandlerData(profileCalls: Trace.Types.Events.SyntheticProfileCall[]):\n Trace.Handlers.ModelHandlers.Samples.SamplesHandlerData {\n const {tree, entryToNode} = Trace.Helpers.TreeHelpers.treify(profileCalls, {filter: {has: () => true}});\n const profile: Protocol.Profiler.Profile = {\n nodes: [],\n startTime: profileCalls.at(0)?.ts || Trace.Types.Timing.MicroSeconds(0),\n endTime: profileCalls.at(-1)?.ts || Trace.Types.Timing.MicroSeconds(10e5),\n samples: [],\n timeDeltas: [],\n };\n\n const nodesIds = new Map();\n const lastTimestamp = profile.startTime;\n for (const profileCall of profileCalls) {\n let node = nodesIds.get(profileCall.nodeId);\n if (!node) {\n node = {\n id: profileCall.nodeId,\n callFrame: profileCall.callFrame,\n };\n profile.nodes.push(node);\n nodesIds.set(profileCall.nodeId, node);\n }\n profile.samples?.push(node.id);\n const timeDelta = profileCall.ts - lastTimestamp;\n profile.timeDeltas?.push(timeDelta);\n }\n const profileData = {\n rawProfile: profile,\n parsedProfile: new CPUProfile.CPUProfileDataModel.CPUProfileDataModel(profile),\n profileCalls,\n profileTree: tree,\n profileId: Trace.Types.Events.ProfileID('fake-profile-id'),\n };\n const profilesInThread = new Map([[1 as Trace.Types.Events.ThreadID, profileData]]);\n return {\n profilesInProcess: new Map([[1 as Trace.Types.Events.ProcessID, profilesInThread]]),\n entryToNode,\n };\n}\n\nexport class FakeFlameChartProvider implements PerfUI.FlameChart.FlameChartDataProvider {\n minimumBoundary(): number {\n return 0;\n }\n\n hasTrackConfigurationMode(): boolean {\n return false;\n }\n\n totalTime(): number {\n return 100;\n }\n\n formatValue(value: number): string {\n return value.toString();\n }\n\n maxStackDepth(): number {\n return 3;\n }\n\n prepareHighlightedEntryInfo(_entryIndex: number): Element|null {\n return null;\n }\n\n canJumpToEntry(_entryIndex: number): boolean {\n return false;\n }\n\n entryTitle(entryIndex: number): string|null {\n return `Entry ${entryIndex}`;\n }\n\n entryFont(_entryIndex: number): string|null {\n return null;\n }\n\n entryColor(entryIndex: number): string {\n return [\n 'lightblue',\n 'lightpink',\n 'yellow',\n 'lightgray',\n 'lightgreen',\n 'lightsalmon',\n 'orange',\n 'pink',\n ][entryIndex % 8];\n }\n\n decorateEntry(): boolean {\n return false;\n }\n\n forceDecoration(_entryIndex: number): boolean {\n return false;\n }\n\n textColor(_entryIndex: number): string {\n return 'black';\n }\n\n timelineData(): PerfUI.FlameChart.FlameChartTimelineData|null {\n return PerfUI.FlameChart.FlameChartTimelineData.createEmpty();\n }\n}\n\nexport function getMainThread(data: Trace.Handlers.ModelHandlers.Renderer.RendererHandlerData):\n Trace.Handlers.ModelHandlers.Renderer.RendererThread {\n let mainThread: Trace.Handlers.ModelHandlers.Renderer.RendererThread|null = null;\n for (const [, process] of data.processes) {\n for (const [, thread] of process.threads) {\n if (thread.name === 'CrRendererMain') {\n mainThread = thread;\n break;\n }\n }\n }\n if (!mainThread) {\n throw new Error('Could not find main thread.');\n }\n return mainThread;\n}\n\ntype ParsedTrace = Trace.Handlers.Types.ParsedTrace;\n\nexport function getBaseTraceParseModelData(overrides: Partial = {}): ParsedTrace {\n return {\n Animations: [],\n LayoutShifts: {\n clusters: [],\n sessionMaxScore: 0,\n clsWindowID: 0,\n prePaintEvents: [],\n layoutInvalidationEvents: [],\n styleRecalcInvalidationEvents: [],\n backendNodeIds: [],\n scoreRecords: [],\n },\n Meta: {\n traceBounds: {\n min: Trace.Types.Timing.MicroSeconds(0),\n max: Trace.Types.Timing.MicroSeconds(100),\n range: Trace.Types.Timing.MicroSeconds(100),\n },\n browserProcessId: Trace.Types.Events.ProcessID(-1),\n browserThreadId: Trace.Types.Events.ThreadID(-1),\n gpuProcessId: Trace.Types.Events.ProcessID(-1),\n gpuThreadId: Trace.Types.Events.ThreadID(-1),\n threadsInProcess: new Map(),\n navigationsByFrameId: new Map(),\n navigationsByNavigationId: new Map(),\n mainFrameId: '',\n mainFrameURL: '',\n rendererProcessesByFrame: new Map(),\n topLevelRendererIds: new Set(),\n frameByProcessId: new Map(),\n mainFrameNavigations: [],\n },\n Renderer: {\n processes: new Map(),\n compositorTileWorkers: new Map(),\n entryToNode: new Map(),\n allTraceEntries: [],\n },\n Screenshots: [],\n Samples: {\n profiles: new Map(),\n processes: new Map(),\n },\n PageLoadMetrics: {metricScoresByFrameId: new Map(), lcpEventNodeIdToDOMNodeMap: new Map()},\n UserInteractions: {allEvents: [], interactionEvents: []},\n NetworkRequests: {\n byOrigin: new Map(),\n byTime: [],\n },\n GPU: {\n mainGPUThreadTasks: [],\n errorsByUseCase: new Map(),\n },\n UserTimings: {\n timings: [],\n },\n LargestImagePaint: new Map(),\n LargestTextPaint: new Map(),\n ...overrides,\n } as Partialas ParsedTrace;\n}\n\n/**\n * A helper that will query the given array of events and find the first event\n * matching the predicate. It will also assert that a match is found, which\n * saves the need to do that for every test.\n */\nexport function getEventOfType(\n events: Trace.Types.Events.Event[], predicate: (e: Trace.Types.Events.Event) => e is T): T {\n const match = events.find(predicate);\n if (!match) {\n throw new Error('Failed to find matching event of type.');\n }\n return match;\n}\n\n/**\n * The Performance Panel is integrated with the IgnoreListManager so in tests\n * that render a flame chart or a track appender, it needs to be setup to avoid\n * errors.\n */\nexport function setupIgnoreListManagerEnvironment(): {\n ignoreListManager: Bindings.IgnoreListManager.IgnoreListManager,\n} {\n const targetManager = SDK.TargetManager.TargetManager.instance({forceNew: true});\n const workspace = Workspace.Workspace.WorkspaceImpl.instance({forceNew: true});\n const resourceMapping = new Bindings.ResourceMapping.ResourceMapping(targetManager, workspace);\n\n const debuggerWorkspaceBinding = Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance({\n forceNew: true,\n resourceMapping,\n targetManager,\n });\n\n const ignoreListManager = Bindings.IgnoreListManager.IgnoreListManager.instance({\n forceNew: true,\n debuggerWorkspaceBinding,\n });\n\n return {ignoreListManager};\n}\n"]} \ No newline at end of file diff --git a/public/testing/TraceLoader.d.ts b/public/testing/TraceLoader.d.ts index db80f46d3..589605857 100644 --- a/public/testing/TraceLoader.d.ts +++ b/public/testing/TraceLoader.d.ts @@ -1,5 +1,5 @@ import type * as Protocol from '../generated/protocol.js'; -import * as TraceEngine from '../models/trace/trace.js'; +import * as Trace from '../models/trace/trace.js'; export interface TraceEngineLoaderOptions { initTraceBounds: boolean; } @@ -23,14 +23,14 @@ export declare class TraceLoader { * JSON.parse-ing them * **/ - static fixtureContents(context: Mocha.Context | Mocha.Suite | null, name: string): Promise; + static fixtureContents(context: Mocha.Context | Mocha.Suite | null, name: string): Promise; /** * Load an array of raw events from the trace file. **/ - static rawEvents(context: Mocha.Context | Mocha.Suite | null, name: string): Promise; + static rawEvents(context: Mocha.Context | Mocha.Suite | null, name: string): Promise; /** * Load an array of raw events from the trace file. - * Will default to typing those events using the types from TraceEngine, but + * Will default to typing those events using the types from Trace Engine, but * can be overriden by passing the legacy EventPayload type as the generic. **/ static rawCPUProfile(context: Mocha.Context | Mocha.Suite | null, name: string): Promise; @@ -53,9 +53,9 @@ export declare class TraceLoader { * @param config The config the new trace engine should run with. Optional, * will fall back to the Default config if not provided. */ - static traceEngine(context: Mocha.Context | Mocha.Suite | null, name: string, config?: TraceEngine.Types.Configuration.Configuration): Promise<{ - traceData: TraceEngine.Handlers.Types.TraceParseData; - insights: TraceEngine.Insights.Types.TraceInsightData | null; + static traceEngine(context: Mocha.Context | Mocha.Suite | null, name: string, config?: Trace.Types.Configuration.Configuration): Promise<{ + parsedTrace: Trace.Handlers.Types.ParsedTrace; + insights: Trace.Insights.Types.TraceInsightSets | null; }>; /** * Initialise the BoundsManager with the bounds from a trace. @@ -63,11 +63,11 @@ export declare class TraceLoader { * level - rely on this being set. This is always set in the actual panel, but * parsing a trace in a test does not automatically set it. **/ - static initTraceBoundsManager(data: TraceEngine.Handlers.Types.TraceParseData): void; - static executeTraceEngineOnFileContents(contents: TraceEngine.Types.File.Contents, emulateFreshRecording?: boolean, traceEngineConfig?: TraceEngine.Types.Configuration.Configuration): Promise<{ - model: TraceEngine.TraceModel.Model; - metadata: TraceEngine.Types.File.MetaData; - traceData: TraceEngine.Handlers.Types.TraceParseData; - insights: TraceEngine.Insights.Types.TraceInsightData | null; + static initTraceBoundsManager(data: Trace.Handlers.Types.ParsedTrace): void; + static executeTraceEngineOnFileContents(contents: Trace.Types.File.Contents, emulateFreshRecording?: boolean, traceEngineConfig?: Trace.Types.Configuration.Configuration): Promise<{ + model: Trace.TraceModel.Model; + metadata: Trace.Types.File.MetaData; + parsedTrace: Trace.Handlers.Types.ParsedTrace; + insights: Trace.Insights.Types.TraceInsightSets | null; }>; } diff --git a/public/testing/TraceLoader.js b/public/testing/TraceLoader.js index cb3a02c71..027701044 100644 --- a/public/testing/TraceLoader.js +++ b/public/testing/TraceLoader.js @@ -1,7 +1,7 @@ // 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 * as TraceEngine from '../models/trace/trace.js'; +import * as Trace from '../models/trace/trace.js'; import * as Timeline from '../panels/timeline/timeline.js'; import * as TraceBounds from '../services/trace_bounds/trace_bounds.js'; // We maintain two caches: @@ -72,7 +72,7 @@ export class TraceLoader { } /** * Load an array of raw events from the trace file. - * Will default to typing those events using the types from TraceEngine, but + * Will default to typing those events using the types from Trace Engine, but * can be overriden by passing the legacy EventPayload type as the generic. **/ static async rawCPUProfile(context, name) { @@ -98,12 +98,12 @@ export class TraceLoader { * @param config The config the new trace engine should run with. Optional, * will fall back to the Default config if not provided. */ - static async traceEngine(context, name, config = TraceEngine.Types.Configuration.defaults()) { + static async traceEngine(context, name, config = Trace.Types.Configuration.defaults()) { // Force the TraceBounds to be reset to empty. This ensures that in // tests where we are using the new engine data we don't accidentally // rely on the fact that a previous test has set the BoundsManager. TraceBounds.TraceBounds.BoundsManager.instance({ forceNew: true }); - const configCacheKey = TraceEngine.Types.Configuration.configToCacheKey(config); + const configCacheKey = Trace.Types.Configuration.configToCacheKey(config); const fromCache = traceEngineCache.get(name)?.get(configCacheKey); // If we have results from the cache, we use those to ensure we keep the // tests speedy and don't re-parse trace files over and over again. @@ -112,23 +112,23 @@ export class TraceLoader { if (!syntheticEventsManager) { throw new Error('Cached trace engine result did not have a synthetic events manager instance'); } - TraceEngine.Helpers.SyntheticEvents.SyntheticEventsManager.activate(syntheticEventsManager); - TraceLoader.initTraceBoundsManager(fromCache.traceData); + Trace.Helpers.SyntheticEvents.SyntheticEventsManager.activate(syntheticEventsManager); + TraceLoader.initTraceBoundsManager(fromCache.parsedTrace); Timeline.ModificationsManager.ModificationsManager.reset(); Timeline.ModificationsManager.ModificationsManager.initAndActivateModificationsManager(fromCache.model, 0); - return { traceData: fromCache.traceData, insights: fromCache.insights }; + return { parsedTrace: fromCache.parsedTrace, insights: fromCache.insights }; } const fileContents = await TraceLoader.fixtureContents(context, name); - const traceEngineData = await TraceLoader.executeTraceEngineOnFileContents(fileContents, /* emulate fresh recording */ false, config); + const parsedTraceData = await TraceLoader.executeTraceEngineOnFileContents(fileContents, /* emulate fresh recording */ false, config); const cacheByName = traceEngineCache.get(name) || new Map(); - cacheByName.set(configCacheKey, traceEngineData); + cacheByName.set(configCacheKey, parsedTraceData); traceEngineCache.set(name, cacheByName); - TraceLoader.initTraceBoundsManager(traceEngineData.traceData); + TraceLoader.initTraceBoundsManager(parsedTraceData.parsedTrace); Timeline.ModificationsManager.ModificationsManager.reset(); - Timeline.ModificationsManager.ModificationsManager.initAndActivateModificationsManager(traceEngineData.model, 0); + Timeline.ModificationsManager.ModificationsManager.initAndActivateModificationsManager(parsedTraceData.model, 0); return { - traceData: traceEngineData.traceData, - insights: traceEngineData.insights, + parsedTrace: parsedTraceData.parsedTrace, + insights: parsedTraceData.insights, }; } /** @@ -148,20 +148,20 @@ export class TraceLoader { const events = 'traceEvents' in contents ? contents.traceEvents : contents; const metadata = 'metadata' in contents ? contents.metadata : {}; return new Promise((resolve, reject) => { - const model = TraceEngine.TraceModel.Model.createWithAllHandlers(traceEngineConfig); - model.addEventListener(TraceEngine.TraceModel.ModelUpdateEvent.eventName, (event) => { + const model = Trace.TraceModel.Model.createWithAllHandlers(traceEngineConfig); + model.addEventListener(Trace.TraceModel.ModelUpdateEvent.eventName, (event) => { const { data } = event; // When we receive the final update from the model, update the recording // state back to waiting. - if (TraceEngine.TraceModel.isModelUpdateDataComplete(data)) { + if (Trace.TraceModel.isModelUpdateDataComplete(data)) { const metadata = model.metadata(0); - const traceData = model.traceParsedData(0); + const parsedTrace = model.parsedTrace(0); const insights = model.traceInsights(0); - if (metadata && traceData) { + if (metadata && parsedTrace) { resolve({ model, metadata, - traceData, + parsedTrace, insights, }); } diff --git a/public/testing/TraceLoader.js.map b/public/testing/TraceLoader.js.map index 4c75e878a..b685dadf2 100644 --- a/public/testing/TraceLoader.js.map +++ b/public/testing/TraceLoader.js.map @@ -1 +1 @@ -{"version":3,"file":"TraceLoader.js","sourceRoot":"","sources":["../../../../../front_end/testing/TraceLoader.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Protocol from '../generated/protocol.js';\nimport * as TraceEngine from '../models/trace/trace.js';\nimport * as Timeline from '../panels/timeline/timeline.js';\nimport * as TraceBounds from '../services/trace_bounds/trace_bounds.js';\n\n// We maintain two caches:\n// 1. The file contents JSON.parsed for a given trace file.\n// 2. The trace engine models for a given file (used by the traceEngine function)\n// Both the file contents and the model data are not expected to change during\n// the lifetime of an instance of DevTools, so they are safe to cache and\n// re-use across tests to avoid extra time spent loading and parsing the same\n// inputs.\n// In the future once the data layer migration is complete, we can hopefully\n// simplify this into one method that loads the new engine and none of the old\n// ones.\nconst fileContentsCache = new Map();\n\n// The new engine cache is a map of maps of:\n// trace file name => trace engine configuration => trace data\n//\n// The first map is a Map of string (which is the name of the trace file) to a\n// new map, where the key is the trace engine configuration stringified.\n// This ensures that we cache as much as we can, but if you load the same trace\n// file with different trace engine configurations, we will not use the cache\n// and will reparse. This is required as some of the settings and experiments\n// change if events are kept and dropped.\nconst traceEngineCache = new Map>();\n\nexport interface TraceEngineLoaderOptions {\n initTraceBounds: boolean;\n}\n\n/**\n * Loads trace files defined as fixtures in front_end/panels/timeline/fixtures/traces.\n *\n * Will automatically cache the results to save time processing the same trace\n * multiple times in a run of the test suite.\n **/\nexport class TraceLoader {\n /**\n * Parsing some trace files easily takes up more than our default Mocha timeout\n * which is 2seconds. So for most tests that include parsing a trace, we have to\n * increase the timeout. We use this function to ensure we set a consistent\n * timeout across all trace model tests.\n * The context might be null when we only render a component example.\n **/\n static setTestTimeout(context: Mocha.Context|Mocha.Suite|null): void {\n if (!context || context.timeout() >= 10_000) {\n return;\n }\n context?.timeout(10_000);\n }\n\n /**\n * Loads a trace file into memory and returns its contents after\n * JSON.parse-ing them\n *\n **/\n static async fixtureContents(context: Mocha.Context|Mocha.Suite|null, name: string):\n Promise {\n TraceLoader.setTestTimeout(context);\n const cached = fileContentsCache.get(name);\n if (cached) {\n return cached;\n }\n // Required URLs differ across the component server and the unit tests, so try both.\n const urlForTest = new URL(`../panels/timeline/fixtures/traces/${name}`, import.meta.url);\n\n const contents = await loadTraceFileFromURL(urlForTest);\n fileContentsCache.set(name, contents);\n return contents;\n }\n\n /**\n * Load an array of raw events from the trace file.\n **/\n static async rawEvents(context: Mocha.Context|Mocha.Suite|null, name: string):\n Promise {\n const contents = await TraceLoader.fixtureContents(context, name);\n\n const events = 'traceEvents' in contents ? contents.traceEvents : contents;\n return events;\n }\n\n /**\n * Load an array of raw events from the trace file.\n * Will default to typing those events using the types from TraceEngine, but\n * can be overriden by passing the legacy EventPayload type as the generic.\n **/\n static async rawCPUProfile(context: Mocha.Context|Mocha.Suite|null, name: string):\n Promise {\n const contents = await TraceLoader.fixtureContents(context, name) as unknown as Protocol.Profiler.Profile;\n return contents;\n }\n\n /**\n * Executes only the new trace engine on the fixture and returns the resulting parsed data.\n *\n * @param context The Mocha test context. |allModelsFromFile| function easily\n * takes up more than our default Mocha timeout, which is 2s. So we have to\n * increase this test's timeout. It might be null when we only render a\n * component example.\n *\n * @param file The name of the trace file to be loaded.\n * The trace file should be in ../panels/timeline/fixtures/traces folder.\n *\n * @param options Additional trace options.\n * @param options.initTraceBounds (defaults to `true`) after the trace is\n * loaded, the TraceBounds manager will automatically be initialised using\n * the bounds from the trace.\n *\n * @param config The config the new trace engine should run with. Optional,\n * will fall back to the Default config if not provided.\n */\n static async traceEngine(\n context: Mocha.Context|Mocha.Suite|null, name: string,\n config: TraceEngine.Types.Configuration.Configuration = TraceEngine.Types.Configuration.defaults()): Promise<{\n traceData: TraceEngine.Handlers.Types.TraceParseData,\n insights: TraceEngine.Insights.Types.TraceInsightData|null,\n }> {\n // Force the TraceBounds to be reset to empty. This ensures that in\n // tests where we are using the new engine data we don't accidentally\n // rely on the fact that a previous test has set the BoundsManager.\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true});\n\n const configCacheKey = TraceEngine.Types.Configuration.configToCacheKey(config);\n\n const fromCache = traceEngineCache.get(name)?.get(configCacheKey);\n\n // If we have results from the cache, we use those to ensure we keep the\n // tests speedy and don't re-parse trace files over and over again.\n if (fromCache) {\n const syntheticEventsManager = fromCache.model.syntheticTraceEventsManager(0);\n if (!syntheticEventsManager) {\n throw new Error('Cached trace engine result did not have a synthetic events manager instance');\n }\n TraceEngine.Helpers.SyntheticEvents.SyntheticEventsManager.activate(syntheticEventsManager);\n TraceLoader.initTraceBoundsManager(fromCache.traceData);\n Timeline.ModificationsManager.ModificationsManager.reset();\n Timeline.ModificationsManager.ModificationsManager.initAndActivateModificationsManager(fromCache.model, 0);\n return {traceData: fromCache.traceData, insights: fromCache.insights};\n }\n\n const fileContents = await TraceLoader.fixtureContents(context, name);\n const traceEngineData =\n await TraceLoader.executeTraceEngineOnFileContents(fileContents, /* emulate fresh recording */ false, config);\n\n const cacheByName = traceEngineCache.get(name) || new Map();\n cacheByName.set(configCacheKey, traceEngineData);\n traceEngineCache.set(name, cacheByName);\n\n TraceLoader.initTraceBoundsManager(traceEngineData.traceData);\n Timeline.ModificationsManager.ModificationsManager.reset();\n Timeline.ModificationsManager.ModificationsManager.initAndActivateModificationsManager(traceEngineData.model, 0);\n return {\n traceData: traceEngineData.traceData,\n insights: traceEngineData.insights,\n };\n }\n\n /**\n * Initialise the BoundsManager with the bounds from a trace.\n * This isn't always required, but some of our code - particularly at the UI\n * level - rely on this being set. This is always set in the actual panel, but\n * parsing a trace in a test does not automatically set it.\n **/\n static initTraceBoundsManager(data: TraceEngine.Handlers.Types.TraceParseData): void {\n TraceBounds.TraceBounds.BoundsManager\n .instance({\n forceNew: true,\n })\n .resetWithNewBounds(data.Meta.traceBounds);\n }\n\n static async executeTraceEngineOnFileContents(\n contents: TraceEngine.Types.File.Contents, emulateFreshRecording = false,\n traceEngineConfig?: TraceEngine.Types.Configuration.Configuration): Promise<{\n model: TraceEngine.TraceModel.Model,\n metadata: TraceEngine.Types.File.MetaData,\n traceData: TraceEngine.Handlers.Types.TraceParseData,\n insights: TraceEngine.Insights.Types.TraceInsightData|null,\n }> {\n const events = 'traceEvents' in contents ? contents.traceEvents : contents;\n const metadata = 'metadata' in contents ? contents.metadata : {};\n return new Promise((resolve, reject) => {\n const model = TraceEngine.TraceModel.Model.createWithAllHandlers(traceEngineConfig);\n model.addEventListener(TraceEngine.TraceModel.ModelUpdateEvent.eventName, (event: Event) => {\n const {data} = event as TraceEngine.TraceModel.ModelUpdateEvent;\n\n // When we receive the final update from the model, update the recording\n // state back to waiting.\n if (TraceEngine.TraceModel.isModelUpdateDataComplete(data)) {\n const metadata = model.metadata(0);\n const traceData = model.traceParsedData(0);\n const insights = model.traceInsights(0);\n if (metadata && traceData) {\n resolve({\n model,\n metadata,\n traceData,\n insights,\n });\n } else {\n reject(new Error('Unable to load trace'));\n }\n }\n });\n\n void model.parse(events, {metadata, isFreshRecording: emulateFreshRecording}).catch(e => console.error(e));\n });\n }\n}\n\n// Below this point are private methods used in the TraceLoader class. These\n// are purposefully not exported, you should use one of the static methods\n// defined above.\n\nasync function loadTraceFileFromURL(url: URL): Promise {\n const response = await fetch(url);\n if (response.status !== 200) {\n throw new Error(`Unable to load ${url}`);\n }\n\n const contentType = response.headers.get('content-type');\n const isGzipEncoded = contentType !== null && contentType.includes('gzip');\n let buffer = await response.arrayBuffer();\n if (isGzipEncoded) {\n buffer = await decodeGzipBuffer(buffer);\n }\n const decoder = new TextDecoder('utf-8');\n const contents = JSON.parse(decoder.decode(buffer)) as TraceEngine.Types.File.Contents;\n return contents;\n}\n\ninterface CompressionStream extends ReadableWritablePair {}\ninterface DecompressionStream extends ReadableWritablePair {}\ndeclare const CompressionStream: {\n prototype: CompressionStream,\n new (type: string): CompressionStream,\n};\n\ndeclare const DecompressionStream: {\n prototype: DecompressionStream,\n new (type: string): DecompressionStream,\n};\n\nfunction codec(buffer: ArrayBuffer, codecStream: CompressionStream|DecompressionStream): Promise {\n const {readable, writable} = new TransformStream();\n const codecReadable = readable.pipeThrough(codecStream);\n\n const writer = writable.getWriter();\n void writer.write(buffer);\n void writer.close();\n\n // Wrap in a response for convenience.\n const response = new Response(codecReadable);\n return response.arrayBuffer();\n}\n\nfunction decodeGzipBuffer(buffer: ArrayBuffer): Promise {\n return codec(buffer, new DecompressionStream('gzip'));\n}\n"]} \ No newline at end of file +{"version":3,"file":"TraceLoader.js","sourceRoot":"","sources":["../../../../../front_end/testing/TraceLoader.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Protocol from '../generated/protocol.js';\nimport * as Trace from '../models/trace/trace.js';\nimport * as Timeline from '../panels/timeline/timeline.js';\nimport * as TraceBounds from '../services/trace_bounds/trace_bounds.js';\n\n// We maintain two caches:\n// 1. The file contents JSON.parsed for a given trace file.\n// 2. The trace engine models for a given file (used by the traceEngine function)\n// Both the file contents and the model data are not expected to change during\n// the lifetime of an instance of DevTools, so they are safe to cache and\n// re-use across tests to avoid extra time spent loading and parsing the same\n// inputs.\n// In the future once the data layer migration is complete, we can hopefully\n// simplify this into one method that loads the new engine and none of the old\n// ones.\nconst fileContentsCache = new Map();\n\n// The new engine cache is a map of maps of:\n// trace file name => trace engine configuration => trace data\n//\n// The first map is a Map of string (which is the name of the trace file) to a\n// new map, where the key is the trace engine configuration stringified.\n// This ensures that we cache as much as we can, but if you load the same trace\n// file with different trace engine configurations, we will not use the cache\n// and will reparse. This is required as some of the settings and experiments\n// change if events are kept and dropped.\nconst traceEngineCache = new Map>();\n\nexport interface TraceEngineLoaderOptions {\n initTraceBounds: boolean;\n}\n\n/**\n * Loads trace files defined as fixtures in front_end/panels/timeline/fixtures/traces.\n *\n * Will automatically cache the results to save time processing the same trace\n * multiple times in a run of the test suite.\n **/\nexport class TraceLoader {\n /**\n * Parsing some trace files easily takes up more than our default Mocha timeout\n * which is 2seconds. So for most tests that include parsing a trace, we have to\n * increase the timeout. We use this function to ensure we set a consistent\n * timeout across all trace model tests.\n * The context might be null when we only render a component example.\n **/\n static setTestTimeout(context: Mocha.Context|Mocha.Suite|null): void {\n if (!context || context.timeout() >= 10_000) {\n return;\n }\n context?.timeout(10_000);\n }\n\n /**\n * Loads a trace file into memory and returns its contents after\n * JSON.parse-ing them\n *\n **/\n static async fixtureContents(context: Mocha.Context|Mocha.Suite|null, name: string):\n Promise {\n TraceLoader.setTestTimeout(context);\n const cached = fileContentsCache.get(name);\n if (cached) {\n return cached;\n }\n // Required URLs differ across the component server and the unit tests, so try both.\n const urlForTest = new URL(`../panels/timeline/fixtures/traces/${name}`, import.meta.url);\n\n const contents = await loadTraceFileFromURL(urlForTest);\n fileContentsCache.set(name, contents);\n return contents;\n }\n\n /**\n * Load an array of raw events from the trace file.\n **/\n static async rawEvents(context: Mocha.Context|Mocha.Suite|null, name: string):\n Promise {\n const contents = await TraceLoader.fixtureContents(context, name);\n\n const events = 'traceEvents' in contents ? contents.traceEvents : contents;\n return events;\n }\n\n /**\n * Load an array of raw events from the trace file.\n * Will default to typing those events using the types from Trace Engine, but\n * can be overriden by passing the legacy EventPayload type as the generic.\n **/\n static async rawCPUProfile(context: Mocha.Context|Mocha.Suite|null, name: string):\n Promise {\n const contents = await TraceLoader.fixtureContents(context, name) as unknown as Protocol.Profiler.Profile;\n return contents;\n }\n\n /**\n * Executes only the new trace engine on the fixture and returns the resulting parsed data.\n *\n * @param context The Mocha test context. |allModelsFromFile| function easily\n * takes up more than our default Mocha timeout, which is 2s. So we have to\n * increase this test's timeout. It might be null when we only render a\n * component example.\n *\n * @param file The name of the trace file to be loaded.\n * The trace file should be in ../panels/timeline/fixtures/traces folder.\n *\n * @param options Additional trace options.\n * @param options.initTraceBounds (defaults to `true`) after the trace is\n * loaded, the TraceBounds manager will automatically be initialised using\n * the bounds from the trace.\n *\n * @param config The config the new trace engine should run with. Optional,\n * will fall back to the Default config if not provided.\n */\n static async traceEngine(\n context: Mocha.Context|Mocha.Suite|null, name: string,\n config: Trace.Types.Configuration.Configuration = Trace.Types.Configuration.defaults()): Promise<{\n parsedTrace: Trace.Handlers.Types.ParsedTrace,\n insights: Trace.Insights.Types.TraceInsightSets|null,\n }> {\n // Force the TraceBounds to be reset to empty. This ensures that in\n // tests where we are using the new engine data we don't accidentally\n // rely on the fact that a previous test has set the BoundsManager.\n TraceBounds.TraceBounds.BoundsManager.instance({forceNew: true});\n\n const configCacheKey = Trace.Types.Configuration.configToCacheKey(config);\n\n const fromCache = traceEngineCache.get(name)?.get(configCacheKey);\n\n // If we have results from the cache, we use those to ensure we keep the\n // tests speedy and don't re-parse trace files over and over again.\n if (fromCache) {\n const syntheticEventsManager = fromCache.model.syntheticTraceEventsManager(0);\n if (!syntheticEventsManager) {\n throw new Error('Cached trace engine result did not have a synthetic events manager instance');\n }\n Trace.Helpers.SyntheticEvents.SyntheticEventsManager.activate(syntheticEventsManager);\n TraceLoader.initTraceBoundsManager(fromCache.parsedTrace);\n Timeline.ModificationsManager.ModificationsManager.reset();\n Timeline.ModificationsManager.ModificationsManager.initAndActivateModificationsManager(fromCache.model, 0);\n return {parsedTrace: fromCache.parsedTrace, insights: fromCache.insights};\n }\n\n const fileContents = await TraceLoader.fixtureContents(context, name);\n const parsedTraceData =\n await TraceLoader.executeTraceEngineOnFileContents(fileContents, /* emulate fresh recording */ false, config);\n\n const cacheByName = traceEngineCache.get(name) || new Map();\n cacheByName.set(configCacheKey, parsedTraceData);\n traceEngineCache.set(name, cacheByName);\n\n TraceLoader.initTraceBoundsManager(parsedTraceData.parsedTrace);\n Timeline.ModificationsManager.ModificationsManager.reset();\n Timeline.ModificationsManager.ModificationsManager.initAndActivateModificationsManager(parsedTraceData.model, 0);\n return {\n parsedTrace: parsedTraceData.parsedTrace,\n insights: parsedTraceData.insights,\n };\n }\n\n /**\n * Initialise the BoundsManager with the bounds from a trace.\n * This isn't always required, but some of our code - particularly at the UI\n * level - rely on this being set. This is always set in the actual panel, but\n * parsing a trace in a test does not automatically set it.\n **/\n static initTraceBoundsManager(data: Trace.Handlers.Types.ParsedTrace): void {\n TraceBounds.TraceBounds.BoundsManager\n .instance({\n forceNew: true,\n })\n .resetWithNewBounds(data.Meta.traceBounds);\n }\n\n static async executeTraceEngineOnFileContents(\n contents: Trace.Types.File.Contents, emulateFreshRecording = false,\n traceEngineConfig?: Trace.Types.Configuration.Configuration): Promise<{\n model: Trace.TraceModel.Model,\n metadata: Trace.Types.File.MetaData,\n parsedTrace: Trace.Handlers.Types.ParsedTrace,\n insights: Trace.Insights.Types.TraceInsightSets|null,\n }> {\n const events = 'traceEvents' in contents ? contents.traceEvents : contents;\n const metadata = 'metadata' in contents ? contents.metadata : {};\n return new Promise((resolve, reject) => {\n const model = Trace.TraceModel.Model.createWithAllHandlers(traceEngineConfig);\n model.addEventListener(Trace.TraceModel.ModelUpdateEvent.eventName, (event: Event) => {\n const {data} = event as Trace.TraceModel.ModelUpdateEvent;\n\n // When we receive the final update from the model, update the recording\n // state back to waiting.\n if (Trace.TraceModel.isModelUpdateDataComplete(data)) {\n const metadata = model.metadata(0);\n const parsedTrace = model.parsedTrace(0);\n const insights = model.traceInsights(0);\n if (metadata && parsedTrace) {\n resolve({\n model,\n metadata,\n parsedTrace,\n insights,\n });\n } else {\n reject(new Error('Unable to load trace'));\n }\n }\n });\n\n void model.parse(events, {metadata, isFreshRecording: emulateFreshRecording}).catch(e => console.error(e));\n });\n }\n}\n\n// Below this point are private methods used in the TraceLoader class. These\n// are purposefully not exported, you should use one of the static methods\n// defined above.\n\nasync function loadTraceFileFromURL(url: URL): Promise {\n const response = await fetch(url);\n if (response.status !== 200) {\n throw new Error(`Unable to load ${url}`);\n }\n\n const contentType = response.headers.get('content-type');\n const isGzipEncoded = contentType !== null && contentType.includes('gzip');\n let buffer = await response.arrayBuffer();\n if (isGzipEncoded) {\n buffer = await decodeGzipBuffer(buffer);\n }\n const decoder = new TextDecoder('utf-8');\n const contents = JSON.parse(decoder.decode(buffer)) as Trace.Types.File.Contents;\n return contents;\n}\n\ninterface CompressionStream extends ReadableWritablePair {}\ninterface DecompressionStream extends ReadableWritablePair {}\ndeclare const CompressionStream: {\n prototype: CompressionStream,\n new (type: string): CompressionStream,\n};\n\ndeclare const DecompressionStream: {\n prototype: DecompressionStream,\n new (type: string): DecompressionStream,\n};\n\nfunction codec(buffer: ArrayBuffer, codecStream: CompressionStream|DecompressionStream): Promise {\n const {readable, writable} = new TransformStream();\n const codecReadable = readable.pipeThrough(codecStream);\n\n const writer = writable.getWriter();\n void writer.write(buffer);\n void writer.close();\n\n // Wrap in a response for convenience.\n const response = new Response(codecReadable);\n return response.arrayBuffer();\n}\n\nfunction decodeGzipBuffer(buffer: ArrayBuffer): Promise {\n return codec(buffer, new DecompressionStream('gzip'));\n}\n"]} \ No newline at end of file diff --git a/public/testing/test_setup.js b/public/testing/test_setup.js index 14e655543..ca428381b 100644 --- a/public/testing/test_setup.js +++ b/public/testing/test_setup.js @@ -7,7 +7,7 @@ */ import * as Common from '../core/common/common.js'; import * as Host from '../core/host/host.js'; -import * as TraceEngine from '../models/trace/trace.js'; +import * as Trace from '../models/trace/trace.js'; import * as Timeline from '../panels/timeline/timeline.js'; import * as ThemeSupport from '../ui/legacy/theme_support/theme_support.js'; import { resetTestDOM } from './DOMHelpers.js'; @@ -16,10 +16,10 @@ import { checkForPendingActivity, startTrackingAsyncActivity, stopTrackingAsyncA beforeEach(() => { resetTestDOM(); // Ensure that no trace data leaks between tests when testing the trace engine. - for (const handler of Object.values(TraceEngine.Handlers.ModelHandlers)) { + for (const handler of Object.values(Trace.Handlers.ModelHandlers)) { handler.reset(); } - TraceEngine.Helpers.SyntheticEvents.SyntheticEventsManager.reset(); + Trace.Helpers.SyntheticEvents.SyntheticEventsManager.reset(); Timeline.SourceMapsResolver.SourceMapsResolver.clearResolvedNodeNames(); // Don't retain host binding listeners across tests. Set this up before initializing ThemeSupport as // ThemeSupport adds a host binding listener. diff --git a/public/testing/test_setup.js.map b/public/testing/test_setup.js.map index 980cf96ab..87d355057 100644 --- a/public/testing/test_setup.js.map +++ b/public/testing/test_setup.js.map @@ -1 +1 @@ -{"version":3,"file":"test_setup.js","sourceRoot":"","sources":["../../../../../front_end/testing/test_setup.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B;;;GAGG;AACH,OAAO,KAAK,MAAM,MAAM,0BAA0B,CAAC;AACnD,OAAO,KAAK,IAAI,MAAM,sBAAsB,CAAC;AAC7C,OAAO,KAAK,WAAW,MAAM,0BAA0B,CAAC;AACxD,OAAO,KAAK,QAAQ,MAAM,gCAAgC,CAAC;AAC3D,OAAO,KAAK,YAAY,MAAM,6CAA6C,CAAC;AAE5E,OAAO,EAAC,YAAY,EAAC,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAC,iBAAiB,EAAC,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EACL,uBAAuB,EACvB,0BAA0B,EAC1B,yBAAyB,GAC1B,MAAM,2BAA2B,CAAC;AAEnC,UAAU,CAAC,GAAG,EAAE;IACd,YAAY,EAAE,CAAC;IACf,+EAA+E;IAC/E,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QACxE,OAAO,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC;IACD,WAAW,CAAC,OAAO,CAAC,eAAe,CAAC,sBAAsB,CAAC,KAAK,EAAE,CAAC;IACnE,QAAQ,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,sBAAsB,EAAE,CAAC;IAExE,oGAAoG;IACpG,6CAA6C;IAC7C,IAAI,CAAC,qBAAqB,CAAC,6BAA6B,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC;IAE3G,mFAAmF;IACnF,oEAAoE;IACpE,MAAM,OAAO,GAAG,iBAAiB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACtD,YAAY,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAC,CAAC,CAAC;IAE9D,0BAA0B,EAAE,CAAC;AAC/B,CAAC,CAAC,CAAC;AAEH,SAAS,CAAC,KAAK,IAAI,EAAE;IACnB,MAAM,uBAAuB,EAAE,CAAC;IAChC,KAAK,CAAC,OAAO,EAAE,CAAC;IAChB,yBAAyB,EAAE,CAAC;IAC5B,+DAA+D;AACjE,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2020 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/*\n * This file is automatically loaded and run by Karma because it automatically\n * loads and injects all *.js files it finds.\n */\nimport * as Common from '../core/common/common.js';\nimport * as Host from '../core/host/host.js';\nimport * as TraceEngine from '../models/trace/trace.js';\nimport * as Timeline from '../panels/timeline/timeline.js';\nimport * as ThemeSupport from '../ui/legacy/theme_support/theme_support.js';\n\nimport {resetTestDOM} from './DOMHelpers.js';\nimport {createFakeSetting} from './EnvironmentHelpers.js';\nimport {\n checkForPendingActivity,\n startTrackingAsyncActivity,\n stopTrackingAsyncActivity,\n} from './TrackAsyncOperations.js';\n\nbeforeEach(() => {\n resetTestDOM();\n // Ensure that no trace data leaks between tests when testing the trace engine.\n for (const handler of Object.values(TraceEngine.Handlers.ModelHandlers)) {\n handler.reset();\n }\n TraceEngine.Helpers.SyntheticEvents.SyntheticEventsManager.reset();\n Timeline.SourceMapsResolver.SourceMapsResolver.clearResolvedNodeNames();\n\n // Don't retain host binding listeners across tests. Set this up before initializing ThemeSupport as\n // ThemeSupport adds a host binding listener.\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.events = new Common.ObjectWrapper.ObjectWrapper();\n\n // Some unit tests exercise code that assumes a ThemeSupport instance is available.\n // Run this in a beforeEach in case an individual test overrides it.\n const setting = createFakeSetting('theme', 'default');\n ThemeSupport.ThemeSupport.instance({forceNew: true, setting});\n\n startTrackingAsyncActivity();\n});\n\nafterEach(async () => {\n await checkForPendingActivity();\n sinon.restore();\n stopTrackingAsyncActivity();\n // Clear out any Sinon stubs or spies between individual tests.\n});\n"]} \ No newline at end of file +{"version":3,"file":"test_setup.js","sourceRoot":"","sources":["../../../../../front_end/testing/test_setup.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B;;;GAGG;AACH,OAAO,KAAK,MAAM,MAAM,0BAA0B,CAAC;AACnD,OAAO,KAAK,IAAI,MAAM,sBAAsB,CAAC;AAC7C,OAAO,KAAK,KAAK,MAAM,0BAA0B,CAAC;AAClD,OAAO,KAAK,QAAQ,MAAM,gCAAgC,CAAC;AAC3D,OAAO,KAAK,YAAY,MAAM,6CAA6C,CAAC;AAE5E,OAAO,EAAC,YAAY,EAAC,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAC,iBAAiB,EAAC,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EACL,uBAAuB,EACvB,0BAA0B,EAC1B,yBAAyB,GAC1B,MAAM,2BAA2B,CAAC;AAEnC,UAAU,CAAC,GAAG,EAAE;IACd,YAAY,EAAE,CAAC;IACf,+EAA+E;IAC/E,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QAClE,OAAO,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC;IACD,KAAK,CAAC,OAAO,CAAC,eAAe,CAAC,sBAAsB,CAAC,KAAK,EAAE,CAAC;IAC7D,QAAQ,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,sBAAsB,EAAE,CAAC;IAExE,oGAAoG;IACpG,6CAA6C;IAC7C,IAAI,CAAC,qBAAqB,CAAC,6BAA6B,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC;IAE3G,mFAAmF;IACnF,oEAAoE;IACpE,MAAM,OAAO,GAAG,iBAAiB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;IACtD,YAAY,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAC,CAAC,CAAC;IAE9D,0BAA0B,EAAE,CAAC;AAC/B,CAAC,CAAC,CAAC;AAEH,SAAS,CAAC,KAAK,IAAI,EAAE;IACnB,MAAM,uBAAuB,EAAE,CAAC;IAChC,KAAK,CAAC,OAAO,EAAE,CAAC;IAChB,yBAAyB,EAAE,CAAC;IAC5B,+DAA+D;AACjE,CAAC,CAAC,CAAC","sourcesContent":["// Copyright 2020 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\n/*\n * This file is automatically loaded and run by Karma because it automatically\n * loads and injects all *.js files it finds.\n */\nimport * as Common from '../core/common/common.js';\nimport * as Host from '../core/host/host.js';\nimport * as Trace from '../models/trace/trace.js';\nimport * as Timeline from '../panels/timeline/timeline.js';\nimport * as ThemeSupport from '../ui/legacy/theme_support/theme_support.js';\n\nimport {resetTestDOM} from './DOMHelpers.js';\nimport {createFakeSetting} from './EnvironmentHelpers.js';\nimport {\n checkForPendingActivity,\n startTrackingAsyncActivity,\n stopTrackingAsyncActivity,\n} from './TrackAsyncOperations.js';\n\nbeforeEach(() => {\n resetTestDOM();\n // Ensure that no trace data leaks between tests when testing the trace engine.\n for (const handler of Object.values(Trace.Handlers.ModelHandlers)) {\n handler.reset();\n }\n Trace.Helpers.SyntheticEvents.SyntheticEventsManager.reset();\n Timeline.SourceMapsResolver.SourceMapsResolver.clearResolvedNodeNames();\n\n // Don't retain host binding listeners across tests. Set this up before initializing ThemeSupport as\n // ThemeSupport adds a host binding listener.\n Host.InspectorFrontendHost.InspectorFrontendHostInstance.events = new Common.ObjectWrapper.ObjectWrapper();\n\n // Some unit tests exercise code that assumes a ThemeSupport instance is available.\n // Run this in a beforeEach in case an individual test overrides it.\n const setting = createFakeSetting('theme', 'default');\n ThemeSupport.ThemeSupport.instance({forceNew: true, setting});\n\n startTrackingAsyncActivity();\n});\n\nafterEach(async () => {\n await checkForPendingActivity();\n sinon.restore();\n stopTrackingAsyncActivity();\n // Clear out any Sinon stubs or spies between individual tests.\n});\n"]} \ No newline at end of file diff --git a/public/testing/testing-tsconfig.json b/public/testing/testing-tsconfig.json index dccb96265..c206e9798 100644 --- a/public/testing/testing-tsconfig.json +++ b/public/testing/testing-tsconfig.json @@ -47,6 +47,7 @@ "../../../../../front_end/testing/ExpectStubCall.ts", "../../../../../front_end/testing/ExtensionHelpers.ts", "../../../../../front_end/testing/FileManagerHelpers.ts", + "../../../../../front_end/testing/InsightHelpers.ts", "../../../../../front_end/testing/LanguagePluginHelpers.ts", "../../../../../front_end/testing/MockConnection.ts", "../../../../../front_end/testing/MockExecutionContext.ts", diff --git a/public/tests.txt b/public/tests.txt index e317e761d..bfc2d6e13 100644 --- a/public/tests.txt +++ b/public/tests.txt @@ -60,6 +60,7 @@ core/sdk/CookieParser.test.js core/sdk/DOMModel.test.js core/sdk/DebuggerModel.test.js core/sdk/EmulationModel.test.js +core/sdk/EnhancedTracesParser.test.js core/sdk/FrameManager.test.js core/sdk/NetworkManager.test.js core/sdk/NetworkRequest.test.js @@ -169,7 +170,6 @@ models/trace/extras/Metadata.test.js models/trace/extras/URLForEntry.test.js models/trace/handlers/AnimationHandler.test.js models/trace/handlers/AuctionWorkletsHandler.test.js -models/trace/handlers/EnhancedTracesHandler.test.js models/trace/handlers/ExtensionTraceDataHandler.test.js models/trace/handlers/FramesHandler.test.js models/trace/handlers/GPUHandler.test.js @@ -202,6 +202,7 @@ models/trace/helpers/Trace.test.js models/trace/helpers/TreeHelpers.test.js models/trace/insights/CumulativeLayoutShift.test.js models/trace/insights/DocumentLatency.test.js +models/trace/insights/FontDisplay.test.js models/trace/insights/InteractionToNextPaint.test.js models/trace/insights/LargestContentfulPaint.test.js models/trace/insights/RenderBlocking.test.js @@ -234,6 +235,7 @@ panels/application/AppManifestView.test.js panels/application/ApplicationPanelSidebar.test.js panels/application/BackgroundServiceView.test.js panels/application/DOMStorageModel.test.js +panels/application/ExtensionStorageModel.test.js panels/application/IndexedDBModel.test.js panels/application/IndexedDBViews.test.js panels/application/InterestGroupStorageView.test.js @@ -421,6 +423,7 @@ panels/sources/TabbedEditorContainer.test.js panels/sources/components/BreakpointsView.test.js panels/sources/components/BreakpointsViewUtils.test.js panels/sources/components/HeadersView.test.js +panels/timeline/AnnotationHelpers.test.js panels/timeline/Breadcrumbs.test.js panels/timeline/EntriesFilter.test.js panels/timeline/EventsSerializer.test.js diff --git a/public/third_party/puppeteer/package/lib/esm/puppeteer/api/Browser.d.ts b/public/third_party/puppeteer/package/lib/esm/puppeteer/api/Browser.d.ts index 2aacc158f..6204eff0c 100644 --- a/public/third_party/puppeteer/package/lib/esm/puppeteer/api/Browser.d.ts +++ b/public/third_party/puppeteer/package/lib/esm/puppeteer/api/Browser.d.ts @@ -265,7 +265,7 @@ export declare abstract class Browser extends EventEmitter { /** * Gets a list of all open {@link Page | pages} inside this {@link Browser}. * - * If there ar multiple {@link BrowserContext | browser contexts}, this + * If there are multiple {@link BrowserContext | browser contexts}, this * returns all {@link Page | pages} in all * {@link BrowserContext | browser contexts}. * diff --git a/public/third_party/puppeteer/package/lib/esm/puppeteer/api/Browser.js b/public/third_party/puppeteer/package/lib/esm/puppeteer/api/Browser.js index 83edf5dfd..c1df6226f 100644 --- a/public/third_party/puppeteer/package/lib/esm/puppeteer/api/Browser.js +++ b/public/third_party/puppeteer/package/lib/esm/puppeteer/api/Browser.js @@ -101,7 +101,7 @@ export class Browser extends EventEmitter { /** * Gets a list of all open {@link Page | pages} inside this {@link Browser}. * - * If there ar multiple {@link BrowserContext | browser contexts}, this + * If there are multiple {@link BrowserContext | browser contexts}, this * returns all {@link Page | pages} in all * {@link BrowserContext | browser contexts}. * diff --git a/public/third_party/puppeteer/package/lib/esm/puppeteer/cdp/ExtensionTransport.js b/public/third_party/puppeteer/package/lib/esm/puppeteer/cdp/ExtensionTransport.js index 7ffdaf654..4927704b6 100644 --- a/public/third_party/puppeteer/package/lib/esm/puppeteer/cdp/ExtensionTransport.js +++ b/public/third_party/puppeteer/package/lib/esm/puppeteer/cdp/ExtensionTransport.js @@ -111,6 +111,13 @@ export class ExtensionTransport { sessionId: 'pageTargetSessionId', }, }); + this.#dispatchResponse({ + id: parsed.id, + sessionId: parsed.sessionId, + method: parsed.method, + result: {}, + }); + return; } else if (!parsed.sessionId) { this.#dispatchResponse({ @@ -120,14 +127,14 @@ export class ExtensionTransport { sessionId: 'tabTargetSessionId', }, }); + this.#dispatchResponse({ + id: parsed.id, + sessionId: parsed.sessionId, + method: parsed.method, + result: {}, + }); + return; } - this.#dispatchResponse({ - id: parsed.id, - sessionId: parsed.sessionId, - method: parsed.method, - result: {}, - }); - return; } } if (parsed.sessionId === 'pageTargetSessionId') { diff --git a/public/third_party/puppeteer/package/lib/esm/puppeteer/common/PDFOptions.d.ts b/public/third_party/puppeteer/package/lib/esm/puppeteer/common/PDFOptions.d.ts index d514b19fe..be2325d0f 100644 --- a/public/third_party/puppeteer/package/lib/esm/puppeteer/common/PDFOptions.d.ts +++ b/public/third_party/puppeteer/package/lib/esm/puppeteer/common/PDFOptions.d.ts @@ -31,19 +31,19 @@ export type LowerCasePaperFormat = 'letter' | 'legal' | 'tabloid' | 'ledger' | ' * * - `Ledger`: 17in x 11in * - * - `A0`: 33.1in x 46.8in + * - `A0`: 33.1102in x 46.811in * - * - `A1`: 23.4in x 33.1in + * - `A1`: 23.3858in x 33.1102in * - * - `A2`: 16.54in x 23.4in + * - `A2`: 16.5354in x 23.3858in * - * - `A3`: 11.7in x 16.54in + * - `A3`: 11.6929in x 16.5354in * - * - `A4`: 8.27in x 11.7in + * - `A4`: 8.2677in x 11.6929in * - * - `A5`: 5.83in x 8.27in + * - `A5`: 5.8268in x 8.2677in * - * - `A6`: 4.13in x 5.83in + * - `A6`: 4.1339in x 5.8268in * * @public */ diff --git a/public/third_party/puppeteer/package/lib/esm/puppeteer/common/PDFOptions.js b/public/third_party/puppeteer/package/lib/esm/puppeteer/common/PDFOptions.js index 4ecd3dbd6..7ff5136b5 100644 --- a/public/third_party/puppeteer/package/lib/esm/puppeteer/common/PDFOptions.js +++ b/public/third_party/puppeteer/package/lib/esm/puppeteer/common/PDFOptions.js @@ -11,12 +11,12 @@ export const paperFormats = { legal: { width: 8.5, height: 14 }, tabloid: { width: 11, height: 17 }, ledger: { width: 17, height: 11 }, - a0: { width: 33.1, height: 46.8 }, - a1: { width: 23.4, height: 33.1 }, - a2: { width: 16.54, height: 23.4 }, - a3: { width: 11.7, height: 16.54 }, - a4: { width: 8.27, height: 11.7 }, - a5: { width: 5.83, height: 8.27 }, - a6: { width: 4.13, height: 5.83 }, + a0: { width: 33.1102, height: 46.811 }, + a1: { width: 23.3858, height: 33.1102 }, + a2: { width: 16.5354, height: 23.3858 }, + a3: { width: 11.6929, height: 16.5354 }, + a4: { width: 8.2677, height: 11.6929 }, + a5: { width: 5.8268, height: 8.2677 }, + a6: { width: 4.1339, height: 5.8268 }, }; //# sourceMappingURL=PDFOptions.js.map \ No newline at end of file diff --git a/public/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.d.ts b/public/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.d.ts index 3673a6393..3e23f01b3 100644 --- a/public/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.d.ts +++ b/public/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.d.ts @@ -1,5 +1,5 @@ /** * @internal */ -export declare const packageVersion = "23.3.0"; +export declare const packageVersion = "23.4.0"; //# sourceMappingURL=version.d.ts.map \ No newline at end of file diff --git a/public/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.js b/public/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.js index 299b34505..05100ef5a 100644 --- a/public/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.js +++ b/public/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.js @@ -1,5 +1,5 @@ /** * @internal */ -export const packageVersion = '23.3.0'; +export const packageVersion = '23.4.0'; //# sourceMappingURL=version.js.map \ No newline at end of file diff --git a/public/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts b/public/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts index 1babfa5ad..770fca28d 100644 --- a/public/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +++ b/public/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts @@ -7,8 +7,8 @@ * @internal */ export declare const PUPPETEER_REVISIONS: Readonly<{ - chrome: "128.0.6613.119"; - 'chrome-headless-shell': "128.0.6613.119"; - firefox: "stable_130.0"; + chrome: "129.0.6668.58"; + 'chrome-headless-shell': "129.0.6668.58"; + firefox: "stable_130.0.1"; }>; //# sourceMappingURL=revisions.d.ts.map \ No newline at end of file diff --git a/public/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js b/public/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js index 5ddb0e1f4..129bc38b3 100644 --- a/public/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +++ b/public/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js @@ -7,8 +7,8 @@ * @internal */ export const PUPPETEER_REVISIONS = Object.freeze({ - chrome: '128.0.6613.119', - 'chrome-headless-shell': '128.0.6613.119', - firefox: 'stable_130.0', + chrome: '129.0.6668.58', + 'chrome-headless-shell': '129.0.6668.58', + firefox: 'stable_130.0.1', }); //# sourceMappingURL=revisions.js.map \ No newline at end of file diff --git a/public/ui/components/buttons/Button.js b/public/ui/components/buttons/Button.js index 012f3f1e2..e62319fbc 100644 --- a/public/ui/components/buttons/Button.js +++ b/public/ui/components/buttons/Button.js @@ -219,14 +219,14 @@ export class Button extends HTMLElement { 'text-with-icon': hasIcon && !isEmpty, 'only-icon': hasIcon && isEmpty, micro: this.#props.size === "MICRO" /* Size.MICRO */, - small: Boolean(this.#props.size === "SMALL" /* Size.SMALL */), + small: this.#props.size === "SMALL" /* Size.SMALL */, 'reduced-focus-ring': Boolean(this.#props.reducedFocusRing), active: this.#props.active, }; const spinnerClasses = { primary: this.#props.variant === "primary" /* Variant.PRIMARY */, outlined: this.#props.variant === "outlined" /* Variant.OUTLINED */, - disabled: Boolean(this.#props.disabled), + disabled: this.#props.disabled, spinner: true, }; const jslog = this.#props.jslogContext && VisualLogging.action().track({ click: true }).context(this.#props.jslogContext); diff --git a/public/ui/components/buttons/Button.js.map b/public/ui/components/buttons/Button.js.map index a35e581c1..7c5e4d386 100644 --- a/public/ui/components/buttons/Button.js.map +++ b/public/ui/components/buttons/Button.js.map @@ -1 +1 @@ -{"version":3,"file":"Button.js","sourceRoot":"","sources":["../../../../../../../front_end/ui/components/buttons/Button.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2021 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as LitHtml from '../../lit-html/lit-html.js';\nimport * as VisualLogging from '../../visual_logging/visual_logging.js';\nimport * as IconButton from '../icon_button/icon_button.js';\n\nimport buttonStyles from './button.css.legacy.js';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-button': Button;\n }\n}\n\nexport const enum Variant {\n PRIMARY = 'primary',\n TONAL = 'tonal',\n OUTLINED = 'outlined',\n TEXT = 'text',\n TOOLBAR = 'toolbar',\n // Just like toolbar but has a style similar to a primary button.\n PRIMARY_TOOLBAR = 'primary_toolbar',\n ICON = 'icon',\n ICON_TOGGLE = 'icon_toggle',\n ADORNER_ICON = 'adorner_icon',\n}\n\nexport const enum Size {\n MICRO = 'MICRO',\n SMALL = 'SMALL',\n REGULAR = 'REGULAR',\n}\n\nexport const enum ToggleType {\n PRIMARY = 'primary-toggle',\n RED = 'red-toggle',\n}\n\ntype ButtonType = 'button'|'submit'|'reset';\n\ninterface ButtonState {\n iconUrl?: string;\n variant: Variant;\n size?: Size;\n reducedFocusRing?: boolean;\n disabled: boolean;\n toggled?: boolean;\n toggleOnClick?: boolean;\n checked?: boolean;\n pressed?: boolean;\n active: boolean;\n spinner?: boolean;\n type: ButtonType;\n value?: string;\n title?: string;\n iconName?: string;\n toggledIconName?: string;\n toggleType?: ToggleType;\n jslogContext?: string;\n longClickable?: boolean;\n}\n\ninterface CommonButtonData {\n variant: Variant;\n iconUrl?: string;\n iconName?: string;\n toggledIconName?: string;\n toggleType?: ToggleType;\n toggleOnClick?: boolean;\n size?: Size;\n reducedFocusRing?: boolean;\n disabled?: boolean;\n toggled?: boolean;\n checked?: boolean;\n active?: boolean;\n spinner?: boolean;\n type?: ButtonType;\n value?: string;\n title?: string;\n jslogContext?: string;\n longClickable?: boolean;\n}\n\nexport type ButtonData = CommonButtonData&(|{\n variant: Variant.PRIMARY_TOOLBAR | Variant.TOOLBAR | Variant.ICON,\n iconUrl: string,\n}|{\n variant: Variant.PRIMARY_TOOLBAR | Variant.TOOLBAR | Variant.ICON,\n iconName: string,\n}|{\n variant: Variant.PRIMARY | Variant.OUTLINED | Variant.TONAL | Variant.TEXT | Variant.ADORNER_ICON,\n}|{\n variant: Variant.ICON_TOGGLE,\n iconName: string,\n toggledIconName: string,\n toggleType: ToggleType,\n toggled: boolean,\n});\n\nexport class Button extends HTMLElement {\n static formAssociated = true;\n static readonly litTagName = LitHtml.literal`devtools-button`;\n readonly #shadow = this.attachShadow({mode: 'open', delegatesFocus: true});\n readonly #boundOnClick = this.#onClick.bind(this);\n readonly #props: ButtonState = {\n size: Size.REGULAR,\n variant: Variant.PRIMARY,\n toggleOnClick: true,\n disabled: false,\n active: false,\n spinner: false,\n type: 'button',\n longClickable: false,\n };\n #internals = this.attachInternals();\n #slotRef = LitHtml.Directives.createRef();\n\n constructor() {\n super();\n this.setAttribute('role', 'presentation');\n this.addEventListener('click', this.#boundOnClick, true);\n\n // TODO(crbug.com/359141904): Ideally we would be using\n // adopted style sheets for installing css styles, but this\n // currently throws an error when sharing the styles across\n // multiple documents. This is a workaround.\n const styleElement = document.createElement('style');\n styleElement.textContent = buttonStyles.cssContent;\n this.#shadow.appendChild(styleElement);\n }\n\n /**\n * Perfer using the .data= setter instead of setting the individual properties\n * for increased type-safety.\n */\n set data(data: ButtonData) {\n this.#props.variant = data.variant;\n this.#props.iconUrl = data.iconUrl;\n this.#props.iconName = data.iconName;\n this.#props.toggledIconName = data.toggledIconName;\n this.#props.toggleOnClick = data.toggleOnClick !== undefined ? data.toggleOnClick : true;\n this.#props.size = Size.REGULAR;\n\n if ('size' in data && data.size) {\n this.#props.size = data.size;\n }\n\n this.#props.active = Boolean(data.active);\n this.#props.spinner = Boolean('spinner' in data ? data.spinner : false);\n\n this.#props.type = 'button';\n if ('type' in data && data.type) {\n this.#props.type = data.type;\n }\n this.#props.toggled = data.toggled;\n this.#props.toggleType = data.toggleType;\n this.#props.checked = data.checked;\n this.#props.disabled = Boolean(data.disabled);\n this.#props.title = data.title;\n this.#props.jslogContext = data.jslogContext;\n this.#props.longClickable = data.longClickable;\n this.#render();\n }\n\n set iconUrl(iconUrl: string|undefined) {\n this.#props.iconUrl = iconUrl;\n this.#render();\n }\n\n set iconName(iconName: string|undefined) {\n this.#props.iconName = iconName;\n this.#render();\n }\n\n set toggledIconName(toggledIconName: string) {\n this.#props.toggledIconName = toggledIconName;\n this.#render();\n }\n\n set toggleType(toggleType: ToggleType) {\n this.#props.toggleType = toggleType;\n this.#render();\n }\n\n set variant(variant: Variant) {\n this.#props.variant = variant;\n this.#render();\n }\n\n set size(size: Size) {\n this.#props.size = size;\n this.#render();\n }\n\n set reducedFocusRing(reducedFocusRing: boolean) {\n this.#props.reducedFocusRing = reducedFocusRing;\n this.#render();\n }\n\n set type(type: ButtonType) {\n this.#props.type = type;\n this.#render();\n }\n\n override set title(title: string) {\n this.#props.title = title;\n this.#render();\n }\n\n set disabled(disabled: boolean) {\n this.#setDisabledProperty(disabled);\n this.#render();\n }\n\n set toggleOnClick(toggleOnClick: boolean) {\n this.#props.toggleOnClick = toggleOnClick;\n this.#render();\n }\n\n set toggled(toggled: boolean) {\n this.#props.toggled = toggled;\n this.#render();\n }\n\n get toggled(): boolean {\n return Boolean(this.#props.toggled);\n }\n\n set checked(checked: boolean) {\n this.#props.checked = checked;\n this.#render();\n }\n\n set pressed(pressed: boolean) {\n this.#props.pressed = pressed;\n this.#render();\n }\n\n set active(active: boolean) {\n this.#props.active = active;\n this.#render();\n }\n\n get active(): boolean {\n return this.#props.active;\n }\n\n set spinner(spinner: boolean) {\n this.#props.spinner = spinner;\n this.#render();\n }\n\n get jslogContext(): string|undefined {\n return this.#props.jslogContext;\n }\n\n set jslogContext(jslogContext: string|undefined) {\n this.#props.jslogContext = jslogContext;\n this.#render();\n }\n\n set longClickable(longClickable: boolean) {\n this.#props.longClickable = longClickable;\n this.#render();\n }\n\n #setDisabledProperty(disabled: boolean): void {\n this.#props.disabled = disabled;\n this.#render();\n }\n\n override focus(): void {\n this.#shadow.querySelector('button')?.focus();\n }\n\n connectedCallback(): void {\n this.#render();\n }\n\n #onClick(event: Event): void {\n if (this.#props.disabled) {\n event.stopPropagation();\n event.preventDefault();\n return;\n }\n if (this.form && this.#props.type === 'submit') {\n event.preventDefault();\n this.form.dispatchEvent(new SubmitEvent('submit', {\n submitter: this,\n }));\n }\n if (this.form && this.#props.type === 'reset') {\n event.preventDefault();\n this.form.reset();\n }\n if (this.#props.toggleOnClick && this.#props.variant === Variant.ICON_TOGGLE && this.#props.iconName) {\n this.toggled = !this.#props.toggled;\n }\n }\n\n #isToolbarVariant(): boolean {\n return this.#props.variant === Variant.TOOLBAR || this.#props.variant === Variant.PRIMARY_TOOLBAR;\n }\n\n #render(): void {\n const nodes = (this.#slotRef.value as HTMLSlotElement | undefined)?.assignedNodes();\n const isEmpty = !Boolean(nodes?.length);\n if (!this.#props.variant) {\n throw new Error('Button requires a variant to be defined');\n }\n if (this.#isToolbarVariant()) {\n if (!this.#props.iconUrl && !this.#props.iconName) {\n throw new Error('Toolbar button requires an icon');\n }\n if (!isEmpty) {\n throw new Error('Toolbar button does not accept children');\n }\n }\n if (this.#props.variant === Variant.ICON) {\n if (!this.#props.iconUrl && !this.#props.iconName) {\n throw new Error('Icon button requires an icon');\n }\n if (!isEmpty) {\n throw new Error('Icon button does not accept children');\n }\n }\n if (this.#props.iconName && this.#props.iconUrl) {\n throw new Error('Both iconName and iconUrl are provided.');\n }\n const hasIcon = Boolean(this.#props.iconUrl) || Boolean(this.#props.iconName);\n const classes = {\n primary: this.#props.variant === Variant.PRIMARY,\n tonal: this.#props.variant === Variant.TONAL,\n outlined: this.#props.variant === Variant.OUTLINED,\n text: this.#props.variant === Variant.TEXT,\n toolbar: this.#isToolbarVariant(),\n 'primary-toolbar': this.#props.variant === Variant.PRIMARY_TOOLBAR,\n icon: this.#props.variant === Variant.ICON || this.#props.variant === Variant.ICON_TOGGLE ||\n this.#props.variant === Variant.ADORNER_ICON,\n 'primary-toggle': this.#props.toggleType === ToggleType.PRIMARY,\n 'red-toggle': this.#props.toggleType === ToggleType.RED,\n toggled: Boolean(this.#props.toggled),\n checked: Boolean(this.#props.checked),\n 'text-with-icon': hasIcon && !isEmpty,\n 'only-icon': hasIcon && isEmpty,\n micro: this.#props.size === Size.MICRO,\n small: Boolean(this.#props.size === Size.SMALL),\n 'reduced-focus-ring': Boolean(this.#props.reducedFocusRing),\n active: this.#props.active,\n };\n const spinnerClasses = {\n primary: this.#props.variant === Variant.PRIMARY,\n outlined: this.#props.variant === Variant.OUTLINED,\n disabled: Boolean(this.#props.disabled),\n spinner: true,\n };\n const jslog =\n this.#props.jslogContext && VisualLogging.action().track({click: true}).context(this.#props.jslogContext);\n // clang-format off\n LitHtml.render(\n LitHtml.html`\n \n `, this.#shadow, {host: this});\n // clang-format on\n }\n\n // Based on https://web.dev/more-capable-form-controls/ to make custom elements form-friendly.\n // Form controls usually expose a \"value\" property.\n get value(): string {\n return this.#props.value || '';\n }\n set value(value: string) {\n this.#props.value = value;\n }\n\n // The following properties and methods aren't strictly required,\n // but browser-level form controls provide them. Providing them helps\n // ensure consistency with browser-provided controls.\n get form(): HTMLFormElement|null {\n return this.#internals.form;\n }\n get name(): string|null {\n return this.getAttribute('name');\n }\n get type(): ButtonType {\n return this.#props.type;\n }\n get validity(): ValidityState {\n return this.#internals.validity;\n }\n get validationMessage(): string {\n return this.#internals.validationMessage;\n }\n get willValidate(): boolean {\n return this.#internals.willValidate;\n }\n checkValidity(): boolean {\n return this.#internals.checkValidity();\n }\n reportValidity(): boolean {\n return this.#internals.reportValidity();\n }\n}\n\ncustomElements.define('devtools-button', Button);\n"]} \ No newline at end of file +{"version":3,"file":"Button.js","sourceRoot":"","sources":["../../../../../../../front_end/ui/components/buttons/Button.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,OAAO,MAAM,4BAA4B,CAAC;AACtD,OAAO,KAAK,aAAa,MAAM,wCAAwC,CAAC;AACxE,OAAO,KAAK,UAAU,MAAM,+BAA+B,CAAC;AAE5D,OAAO,YAAY,MAAM,wBAAwB,CAAC;AA6FlD,MAAM,OAAO,MAAO,SAAQ,WAAW;IACrC,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC;IAC7B,MAAM,CAAU,UAAU,GAAG,OAAO,CAAC,OAAO,CAAA,iBAAiB,CAAC;IACrD,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,EAAC,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAC,CAAC,CAAC;IAClE,aAAa,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzC,MAAM,GAAgB;QAC7B,IAAI,8BAAc;QAClB,OAAO,iCAAiB;QACxB,aAAa,EAAE,IAAI;QACnB,QAAQ,EAAE,KAAK;QACf,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,KAAK;QACd,IAAI,EAAE,QAAQ;QACd,aAAa,EAAE,KAAK;KACrB,CAAC;IACF,UAAU,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;IACpC,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC;IAE1C;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;QAC1C,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;QAEzD,uDAAuD;QACvD,2DAA2D;QAC3D,2DAA2D;QAC3D,4CAA4C;QAC5C,MAAM,YAAY,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QACrD,YAAY,CAAC,WAAW,GAAG,YAAY,CAAC,UAAU,CAAC;QACnD,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,CAAC;IACzC,CAAC;IAED;;;OAGG;IACH,IAAI,IAAI,CAAC,IAAgB;QACvB,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QACnC,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QACnC,IAAI,CAAC,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QACrC,IAAI,CAAC,MAAM,CAAC,eAAe,GAAG,IAAI,CAAC,eAAe,CAAC;QACnD,IAAI,CAAC,MAAM,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC;QACzF,IAAI,CAAC,MAAM,CAAC,IAAI,+BAAe,CAAC;QAEhC,IAAI,MAAM,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAChC,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QAC/B,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAExE,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,QAAQ,CAAC;QAC5B,IAAI,MAAM,IAAI,IAAI,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAChC,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QAC/B,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QACnC,IAAI,CAAC,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;QACzC,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QACnC,IAAI,CAAC,MAAM,CAAC,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QAC/B,IAAI,CAAC,MAAM,CAAC,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;QAC7C,IAAI,CAAC,MAAM,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC;QAC/C,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,IAAI,OAAO,CAAC,OAAyB;QACnC,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;QAC9B,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,IAAI,QAAQ,CAAC,QAA0B;QACrC,IAAI,CAAC,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAChC,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,IAAI,eAAe,CAAC,eAAuB;QACzC,IAAI,CAAC,MAAM,CAAC,eAAe,GAAG,eAAe,CAAC;QAC9C,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,IAAI,UAAU,CAAC,UAAsB;QACnC,IAAI,CAAC,MAAM,CAAC,UAAU,GAAG,UAAU,CAAC;QACpC,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,IAAI,OAAO,CAAC,OAAgB;QAC1B,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;QAC9B,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,IAAI,IAAI,CAAC,IAAU;QACjB,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,IAAI,gBAAgB,CAAC,gBAAyB;QAC5C,IAAI,CAAC,MAAM,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;QAChD,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,IAAI,IAAI,CAAC,IAAgB;QACvB,IAAI,CAAC,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC;QACxB,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,IAAa,KAAK,CAAC,KAAa;QAC9B,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;QAC1B,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,IAAI,QAAQ,CAAC,QAAiB;QAC5B,IAAI,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC;QACpC,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,IAAI,aAAa,CAAC,aAAsB;QACtC,IAAI,CAAC,MAAM,CAAC,aAAa,GAAG,aAAa,CAAC;QAC1C,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,IAAI,OAAO,CAAC,OAAgB;QAC1B,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;QAC9B,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,IAAI,OAAO;QACT,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,OAAO,CAAC,OAAgB;QAC1B,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;QAC9B,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,IAAI,OAAO,CAAC,OAAgB;QAC1B,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;QAC9B,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,IAAI,MAAM,CAAC,MAAe;QACxB,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;QAC5B,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,IAAI,MAAM;QACR,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;IAC5B,CAAC;IAED,IAAI,OAAO,CAAC,OAAgB;QAC1B,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;QAC9B,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC;IAClC,CAAC;IAED,IAAI,YAAY,CAAC,YAA8B;QAC7C,IAAI,CAAC,MAAM,CAAC,YAAY,GAAG,YAAY,CAAC;QACxC,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,IAAI,aAAa,CAAC,aAAsB;QACtC,IAAI,CAAC,MAAM,CAAC,aAAa,GAAG,aAAa,CAAC;QAC1C,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,oBAAoB,CAAC,QAAiB;QACpC,IAAI,CAAC,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAChC,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAEQ,KAAK;QACZ,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAC;IAChD,CAAC;IAED,iBAAiB;QACf,IAAI,CAAC,OAAO,EAAE,CAAC;IACjB,CAAC;IAED,QAAQ,CAAC,KAAY;QACnB,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YACzB,KAAK,CAAC,eAAe,EAAE,CAAC;YACxB,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,OAAO;QACT,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC/C,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,WAAW,CAAC,QAAQ,EAAE;gBAChD,SAAS,EAAE,IAAI;aAChB,CAAC,CAAC,CAAC;QACN,CAAC;QACD,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;YAC9C,KAAK,CAAC,cAAc,EAAE,CAAC;YACvB,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,CAAC,aAAa,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,4CAAwB,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YACrG,IAAI,CAAC,OAAO,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;QACtC,CAAC;IACH,CAAC;IAED,iBAAiB;QACf,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,oCAAoB,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,oDAA4B,CAAC;IACpG,CAAC;IAED,OAAO;QACL,MAAM,KAAK,GAAI,IAAI,CAAC,QAAQ,CAAC,KAAqC,EAAE,aAAa,EAAE,CAAC;QACpF,MAAM,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;QAC7D,CAAC;QACD,IAAI,IAAI,CAAC,iBAAiB,EAAE,EAAE,CAAC;YAC7B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;gBAClD,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;YACrD,CAAC;YACD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,8BAAiB,EAAE,CAAC;YACzC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;gBAClD,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;YAClD,CAAC;YACD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;YAC1D,CAAC;QACH,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YAChD,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;QAC7D,CAAC;QACD,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC9E,MAAM,OAAO,GAAG;YACd,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,oCAAoB;YAChD,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,gCAAkB;YAC5C,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,sCAAqB;YAClD,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,8BAAiB;YAC1C,OAAO,EAAE,IAAI,CAAC,iBAAiB,EAAE;YACjC,iBAAiB,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,oDAA4B;YAClE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,8BAAiB,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,4CAAwB;gBACrF,IAAI,CAAC,MAAM,CAAC,OAAO,8CAAyB;YAChD,gBAAgB,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,8CAAuB;YAC/D,YAAY,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,sCAAmB;YACvD,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;YACrC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;YACrC,gBAAgB,EAAE,OAAO,IAAI,CAAC,OAAO;YACrC,WAAW,EAAE,OAAO,IAAI,OAAO;YAC/B,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,6BAAe;YACtC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,6BAAe;YACtC,oBAAoB,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC;YAC3D,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,MAAM;SAC3B,CAAC;QACF,MAAM,cAAc,GAAG;YACrB,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,oCAAoB;YAChD,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO,sCAAqB;YAClD,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;YAC9B,OAAO,EAAE,IAAI;SACd,CAAC;QACF,MAAM,KAAK,GACP,IAAI,CAAC,MAAM,CAAC,YAAY,IAAI,aAAa,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,EAAC,KAAK,EAAE,IAAI,EAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAC9G,mBAAmB;QACnB,OAAO,CAAC,MAAM,CACZ,OAAO,CAAC,IAAI,CAAA;wBACM,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,cAAc,IAAI,CAAC,MAAM,CAAC,QAAQ,UAAU,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,iBAAiB,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC;YAC1P,OAAO;YACP,CAAC,CAAC,OAAO,CAAC,IAAI,CAAA;mBACP,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,SAAS,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO;oBACtI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,GAAG;YAC1C,CAAC,CAAC,EAAE;YACJ,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAA,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,SAAS,uBAAuB;cACzG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,GAAG;YAC1C,CAAC,CAAC,EAAE;YACE,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAA,eAAe,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE;8BACzF,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC;;OAE5E,EAAE,IAAI,CAAC,OAAO,EAAE,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC,CAAC;QACjC,kBAAkB;IACpB,CAAC;IAED,8FAA8F;IAC9F,mDAAmD;IACnD,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC;IACjC,CAAC;IACD,IAAI,KAAK,CAAC,KAAa;QACrB,IAAI,CAAC,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC;IAC5B,CAAC;IAED,iEAAiE;IACjE,qEAAqE;IACrE,qDAAqD;IACrD,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;IAC9B,CAAC;IACD,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IACnC,CAAC;IACD,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC;IAC1B,CAAC;IACD,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC;IAClC,CAAC;IACD,IAAI,iBAAiB;QACnB,OAAO,IAAI,CAAC,UAAU,CAAC,iBAAiB,CAAC;IAC3C,CAAC;IACD,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;IACtC,CAAC;IACD,aAAa;QACX,OAAO,IAAI,CAAC,UAAU,CAAC,aAAa,EAAE,CAAC;IACzC,CAAC;IACD,cAAc;QACZ,OAAO,IAAI,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC;IAC1C,CAAC;;AAGH,cAAc,CAAC,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC","sourcesContent":["// Copyright 2021 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as LitHtml from '../../lit-html/lit-html.js';\nimport * as VisualLogging from '../../visual_logging/visual_logging.js';\nimport * as IconButton from '../icon_button/icon_button.js';\n\nimport buttonStyles from './button.css.legacy.js';\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-button': Button;\n }\n}\n\nexport const enum Variant {\n PRIMARY = 'primary',\n TONAL = 'tonal',\n OUTLINED = 'outlined',\n TEXT = 'text',\n TOOLBAR = 'toolbar',\n // Just like toolbar but has a style similar to a primary button.\n PRIMARY_TOOLBAR = 'primary_toolbar',\n ICON = 'icon',\n ICON_TOGGLE = 'icon_toggle',\n ADORNER_ICON = 'adorner_icon',\n}\n\nexport const enum Size {\n MICRO = 'MICRO',\n SMALL = 'SMALL',\n REGULAR = 'REGULAR',\n}\n\nexport const enum ToggleType {\n PRIMARY = 'primary-toggle',\n RED = 'red-toggle',\n}\n\ntype ButtonType = 'button'|'submit'|'reset';\n\ninterface ButtonState {\n iconUrl?: string;\n variant: Variant;\n size?: Size;\n reducedFocusRing?: boolean;\n disabled: boolean;\n toggled?: boolean;\n toggleOnClick?: boolean;\n checked?: boolean;\n pressed?: boolean;\n active: boolean;\n spinner?: boolean;\n type: ButtonType;\n value?: string;\n title?: string;\n iconName?: string;\n toggledIconName?: string;\n toggleType?: ToggleType;\n jslogContext?: string;\n longClickable?: boolean;\n}\n\ninterface CommonButtonData {\n variant: Variant;\n iconUrl?: string;\n iconName?: string;\n toggledIconName?: string;\n toggleType?: ToggleType;\n toggleOnClick?: boolean;\n size?: Size;\n reducedFocusRing?: boolean;\n disabled?: boolean;\n toggled?: boolean;\n checked?: boolean;\n active?: boolean;\n spinner?: boolean;\n type?: ButtonType;\n value?: string;\n title?: string;\n jslogContext?: string;\n longClickable?: boolean;\n}\n\nexport type ButtonData = CommonButtonData&(|{\n variant: Variant.PRIMARY_TOOLBAR | Variant.TOOLBAR | Variant.ICON,\n iconUrl: string,\n}|{\n variant: Variant.PRIMARY_TOOLBAR | Variant.TOOLBAR | Variant.ICON,\n iconName: string,\n}|{\n variant: Variant.PRIMARY | Variant.OUTLINED | Variant.TONAL | Variant.TEXT | Variant.ADORNER_ICON,\n}|{\n variant: Variant.ICON_TOGGLE,\n iconName: string,\n toggledIconName: string,\n toggleType: ToggleType,\n toggled: boolean,\n});\n\nexport class Button extends HTMLElement {\n static formAssociated = true;\n static readonly litTagName = LitHtml.literal`devtools-button`;\n readonly #shadow = this.attachShadow({mode: 'open', delegatesFocus: true});\n readonly #boundOnClick = this.#onClick.bind(this);\n readonly #props: ButtonState = {\n size: Size.REGULAR,\n variant: Variant.PRIMARY,\n toggleOnClick: true,\n disabled: false,\n active: false,\n spinner: false,\n type: 'button',\n longClickable: false,\n };\n #internals = this.attachInternals();\n #slotRef = LitHtml.Directives.createRef();\n\n constructor() {\n super();\n this.setAttribute('role', 'presentation');\n this.addEventListener('click', this.#boundOnClick, true);\n\n // TODO(crbug.com/359141904): Ideally we would be using\n // adopted style sheets for installing css styles, but this\n // currently throws an error when sharing the styles across\n // multiple documents. This is a workaround.\n const styleElement = document.createElement('style');\n styleElement.textContent = buttonStyles.cssContent;\n this.#shadow.appendChild(styleElement);\n }\n\n /**\n * Perfer using the .data= setter instead of setting the individual properties\n * for increased type-safety.\n */\n set data(data: ButtonData) {\n this.#props.variant = data.variant;\n this.#props.iconUrl = data.iconUrl;\n this.#props.iconName = data.iconName;\n this.#props.toggledIconName = data.toggledIconName;\n this.#props.toggleOnClick = data.toggleOnClick !== undefined ? data.toggleOnClick : true;\n this.#props.size = Size.REGULAR;\n\n if ('size' in data && data.size) {\n this.#props.size = data.size;\n }\n\n this.#props.active = Boolean(data.active);\n this.#props.spinner = Boolean('spinner' in data ? data.spinner : false);\n\n this.#props.type = 'button';\n if ('type' in data && data.type) {\n this.#props.type = data.type;\n }\n this.#props.toggled = data.toggled;\n this.#props.toggleType = data.toggleType;\n this.#props.checked = data.checked;\n this.#props.disabled = Boolean(data.disabled);\n this.#props.title = data.title;\n this.#props.jslogContext = data.jslogContext;\n this.#props.longClickable = data.longClickable;\n this.#render();\n }\n\n set iconUrl(iconUrl: string|undefined) {\n this.#props.iconUrl = iconUrl;\n this.#render();\n }\n\n set iconName(iconName: string|undefined) {\n this.#props.iconName = iconName;\n this.#render();\n }\n\n set toggledIconName(toggledIconName: string) {\n this.#props.toggledIconName = toggledIconName;\n this.#render();\n }\n\n set toggleType(toggleType: ToggleType) {\n this.#props.toggleType = toggleType;\n this.#render();\n }\n\n set variant(variant: Variant) {\n this.#props.variant = variant;\n this.#render();\n }\n\n set size(size: Size) {\n this.#props.size = size;\n this.#render();\n }\n\n set reducedFocusRing(reducedFocusRing: boolean) {\n this.#props.reducedFocusRing = reducedFocusRing;\n this.#render();\n }\n\n set type(type: ButtonType) {\n this.#props.type = type;\n this.#render();\n }\n\n override set title(title: string) {\n this.#props.title = title;\n this.#render();\n }\n\n set disabled(disabled: boolean) {\n this.#setDisabledProperty(disabled);\n this.#render();\n }\n\n set toggleOnClick(toggleOnClick: boolean) {\n this.#props.toggleOnClick = toggleOnClick;\n this.#render();\n }\n\n set toggled(toggled: boolean) {\n this.#props.toggled = toggled;\n this.#render();\n }\n\n get toggled(): boolean {\n return Boolean(this.#props.toggled);\n }\n\n set checked(checked: boolean) {\n this.#props.checked = checked;\n this.#render();\n }\n\n set pressed(pressed: boolean) {\n this.#props.pressed = pressed;\n this.#render();\n }\n\n set active(active: boolean) {\n this.#props.active = active;\n this.#render();\n }\n\n get active(): boolean {\n return this.#props.active;\n }\n\n set spinner(spinner: boolean) {\n this.#props.spinner = spinner;\n this.#render();\n }\n\n get jslogContext(): string|undefined {\n return this.#props.jslogContext;\n }\n\n set jslogContext(jslogContext: string|undefined) {\n this.#props.jslogContext = jslogContext;\n this.#render();\n }\n\n set longClickable(longClickable: boolean) {\n this.#props.longClickable = longClickable;\n this.#render();\n }\n\n #setDisabledProperty(disabled: boolean): void {\n this.#props.disabled = disabled;\n this.#render();\n }\n\n override focus(): void {\n this.#shadow.querySelector('button')?.focus();\n }\n\n connectedCallback(): void {\n this.#render();\n }\n\n #onClick(event: Event): void {\n if (this.#props.disabled) {\n event.stopPropagation();\n event.preventDefault();\n return;\n }\n if (this.form && this.#props.type === 'submit') {\n event.preventDefault();\n this.form.dispatchEvent(new SubmitEvent('submit', {\n submitter: this,\n }));\n }\n if (this.form && this.#props.type === 'reset') {\n event.preventDefault();\n this.form.reset();\n }\n if (this.#props.toggleOnClick && this.#props.variant === Variant.ICON_TOGGLE && this.#props.iconName) {\n this.toggled = !this.#props.toggled;\n }\n }\n\n #isToolbarVariant(): boolean {\n return this.#props.variant === Variant.TOOLBAR || this.#props.variant === Variant.PRIMARY_TOOLBAR;\n }\n\n #render(): void {\n const nodes = (this.#slotRef.value as HTMLSlotElement | undefined)?.assignedNodes();\n const isEmpty = !Boolean(nodes?.length);\n if (!this.#props.variant) {\n throw new Error('Button requires a variant to be defined');\n }\n if (this.#isToolbarVariant()) {\n if (!this.#props.iconUrl && !this.#props.iconName) {\n throw new Error('Toolbar button requires an icon');\n }\n if (!isEmpty) {\n throw new Error('Toolbar button does not accept children');\n }\n }\n if (this.#props.variant === Variant.ICON) {\n if (!this.#props.iconUrl && !this.#props.iconName) {\n throw new Error('Icon button requires an icon');\n }\n if (!isEmpty) {\n throw new Error('Icon button does not accept children');\n }\n }\n if (this.#props.iconName && this.#props.iconUrl) {\n throw new Error('Both iconName and iconUrl are provided.');\n }\n const hasIcon = Boolean(this.#props.iconUrl) || Boolean(this.#props.iconName);\n const classes = {\n primary: this.#props.variant === Variant.PRIMARY,\n tonal: this.#props.variant === Variant.TONAL,\n outlined: this.#props.variant === Variant.OUTLINED,\n text: this.#props.variant === Variant.TEXT,\n toolbar: this.#isToolbarVariant(),\n 'primary-toolbar': this.#props.variant === Variant.PRIMARY_TOOLBAR,\n icon: this.#props.variant === Variant.ICON || this.#props.variant === Variant.ICON_TOGGLE ||\n this.#props.variant === Variant.ADORNER_ICON,\n 'primary-toggle': this.#props.toggleType === ToggleType.PRIMARY,\n 'red-toggle': this.#props.toggleType === ToggleType.RED,\n toggled: Boolean(this.#props.toggled),\n checked: Boolean(this.#props.checked),\n 'text-with-icon': hasIcon && !isEmpty,\n 'only-icon': hasIcon && isEmpty,\n micro: this.#props.size === Size.MICRO,\n small: this.#props.size === Size.SMALL,\n 'reduced-focus-ring': Boolean(this.#props.reducedFocusRing),\n active: this.#props.active,\n };\n const spinnerClasses = {\n primary: this.#props.variant === Variant.PRIMARY,\n outlined: this.#props.variant === Variant.OUTLINED,\n disabled: this.#props.disabled,\n spinner: true,\n };\n const jslog =\n this.#props.jslogContext && VisualLogging.action().track({click: true}).context(this.#props.jslogContext);\n // clang-format off\n LitHtml.render(\n LitHtml.html`\n \n `, this.#shadow, {host: this});\n // clang-format on\n }\n\n // Based on https://web.dev/more-capable-form-controls/ to make custom elements form-friendly.\n // Form controls usually expose a \"value\" property.\n get value(): string {\n return this.#props.value || '';\n }\n set value(value: string) {\n this.#props.value = value;\n }\n\n // The following properties and methods aren't strictly required,\n // but browser-level form controls provide them. Providing them helps\n // ensure consistency with browser-provided controls.\n get form(): HTMLFormElement|null {\n return this.#internals.form;\n }\n get name(): string|null {\n return this.getAttribute('name');\n }\n get type(): ButtonType {\n return this.#props.type;\n }\n get validity(): ValidityState {\n return this.#internals.validity;\n }\n get validationMessage(): string {\n return this.#internals.validationMessage;\n }\n get willValidate(): boolean {\n return this.#internals.willValidate;\n }\n checkValidity(): boolean {\n return this.#internals.checkValidity();\n }\n reportValidity(): boolean {\n return this.#internals.reportValidity();\n }\n}\n\ncustomElements.define('devtools-button', Button);\n"]} \ No newline at end of file diff --git a/public/ui/components/dialogs/Dialog.js b/public/ui/components/dialogs/Dialog.js index 786e93849..883a920ef 100644 --- a/public/ui/components/dialogs/Dialog.js +++ b/public/ui/components/dialogs/Dialog.js @@ -15,6 +15,7 @@ const IS_DIALOG_SUPPORTED = 'HTMLDialogElement' in globalThis; // (the visible height is only half of the diamond). export const CONNECTOR_HEIGHT = 10; const CONNECTOR_WIDTH = 2 * CONNECTOR_HEIGHT; +// The offset used by the dialog's animation as it slides in when opened. const DIALOG_ANIMATION_OFFSET = 20; export const DIALOG_SIDE_PADDING = 5; export const DIALOG_VERTICAL_PADDING = 3; @@ -203,9 +204,13 @@ export class Dialog extends HTMLElement { } #mouseEventWasInDialogContent(evt) { const dialogBounds = this.#dialogClientRect; - const animationOffSetValue = this.bestVerticalPosition === "bottom" /* DialogVerticalPosition.BOTTOM */ ? + let animationOffSetValue = this.bestVerticalPosition === "bottom" /* DialogVerticalPosition.BOTTOM */ ? DIALOG_ANIMATION_OFFSET : -1 * DIALOG_ANIMATION_OFFSET; + if (this.#props.origin === MODAL) { + // When shown as a modal, the dialog is not animated + animationOffSetValue = 0; + } const eventWasDialogContentX = evt.pageX >= dialogBounds.left && evt.pageX <= dialogBounds.left + dialogBounds.width; const eventWasDialogContentY = evt.pageY >= dialogBounds.top + animationOffSetValue && evt.pageY <= dialogBounds.top + dialogBounds.height + animationOffSetValue; diff --git a/public/ui/components/dialogs/Dialog.js.map b/public/ui/components/dialogs/Dialog.js.map index 7db1e2053..14ce4cc8c 100644 --- a/public/ui/components/dialogs/Dialog.js.map +++ b/public/ui/components/dialogs/Dialog.js.map @@ -1 +1 @@ -{"version":3,"file":"Dialog.js","sourceRoot":"","sources":["../../../../../../../front_end/ui/components/dialogs/Dialog.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport * as WindowBoundsService from '../../../services/window_bounds/window_bounds.js';\nimport * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';\nimport * as Coordinator from '../../../ui/components/render_coordinator/render_coordinator.js';\nimport * as LitHtml from '../../../ui/lit-html/lit-html.js';\nimport * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';\n\nimport dialogStyles from './dialog.css.js';\n\nconst coordinator = Coordinator.RenderCoordinator.RenderCoordinator.instance();\n\nconst IS_DIALOG_SUPPORTED = 'HTMLDialogElement' in globalThis;\n\n// Height in pixels of the dialog's connector. The connector is represented as\n// as a diamond and the height corresponds to half the height of the diamond.\n// (the visible height is only half of the diamond).\nexport const CONNECTOR_HEIGHT = 10;\nconst CONNECTOR_WIDTH = 2 * CONNECTOR_HEIGHT;\n\nconst DIALOG_ANIMATION_OFFSET = 20;\n\nexport const DIALOG_SIDE_PADDING = 5;\nexport const DIALOG_VERTICAL_PADDING = 3;\n\n// If the content of the dialog cannot be completely shown because otherwise\n// the dialog would overflow the window, the dialog's max width and height are\n// set such that the dialog remains inside the visible bounds. In this cases\n// some extra, determined by this constant, is added so that the dialog's borders\n// remain clearly visible. This constant accounts for the padding of the dialog's\n// content (20 px) and a 5px gap left on each extreme of the dialog from the viewport.\nexport const DIALOG_PADDING_FROM_WINDOW = 3 * CONNECTOR_HEIGHT;\ninterface DialogData {\n /**\n * Position or point the dialog is shown relative to.\n * If the dialog instance will be shown as a modal, set\n * this property to MODAL.\n */\n origin: DialogOrigin;\n position: DialogVerticalPosition;\n /**\n * Horizontal alignment of the dialg with respect to its origin.\n * Center by default.\n */\n horizontalAlignment: DialogHorizontalAlignment;\n /**\n * Whether the connector from the dialog to its origin is shown.\n */\n showConnector: boolean;\n\n /**\n * Optional function used to the determine the x coordinate of the connector's\n * end (tip of the triangle), relative to the viewport. If not defined, the x\n * coordinate of the origin's center is used instead.\n */\n getConnectorCustomXPosition: (() => number)|null;\n\n /**\n * Optional function called when the dialog is shown.\n */\n dialogShownCallback: (() => unknown)|null;\n\n /**\n * Optional. Service that provides the window dimensions used for positioning the Dialog.\n */\n windowBoundsService: WindowBoundsService.WindowBoundsService.WindowBoundsService;\n /**\n * Whether the dialog is closed when the 'Escape' key is pressed. When true, the event is\n * propagation is stopped.\n */\n closeOnESC: boolean;\n /**\n * Whether the dialog is closed when a scroll event is detected outside of the dialog's\n * content. Defaults to true.\n */\n closeOnScroll: boolean;\n /**\n * Specifies a context for the visual element.\n */\n jslogContext: string;\n}\n\ntype DialogAnchor = HTMLElement|DOMRect|DOMPoint;\n\nexport const MODAL = 'MODAL';\n\nexport type DialogOrigin = DialogAnchor|null|(() => DialogAnchor)|typeof MODAL;\nexport class Dialog extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-dialog`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n readonly #renderBound = this.#render.bind(this);\n readonly #forceDialogCloseInDevToolsBound = this.#forceDialogCloseInDevToolsMutation.bind(this);\n readonly #handleScrollAttemptBound = this.#handleScrollAttempt.bind(this);\n readonly #props: DialogData = {\n origin: MODAL,\n position: DialogVerticalPosition.BOTTOM,\n horizontalAlignment: DialogHorizontalAlignment.CENTER,\n showConnector: false,\n getConnectorCustomXPosition: null,\n dialogShownCallback: null,\n windowBoundsService: WindowBoundsService.WindowBoundsService.WindowBoundsServiceImpl.instance(),\n closeOnESC: true,\n closeOnScroll: true,\n jslogContext: '',\n };\n\n #dialog: HTMLDialogElement|null = null;\n #isPendingShowDialog = false;\n #isPendingCloseDialog = false;\n #hitArea = new DOMRect(0, 0, 0, 0);\n #dialogClientRect = new DOMRect(0, 0, 0, 0);\n #bestVerticalPositionInternal: DialogVerticalPosition|null = null;\n #bestHorizontalAlignment: DialogHorizontalAlignment|null = null;\n readonly #devtoolsMutationObserver = new MutationObserver(this.#forceDialogCloseInDevToolsBound);\n readonly #dialogResizeObserver = new ResizeObserver(this.#updateDialogBounds.bind(this));\n #devToolsBoundingElement = this.windowBoundsService.getDevToolsBoundingElement();\n\n // We bind here because we have to listen to keydowns on the entire window,\n // not on the Dialog element itself. This is because if the user has the\n // dialog open, but their focus is elsewhere, and they hit ESC, we should\n // still close the dialog.\n #onKeyDownBound = this.#onKeyDown.bind(this);\n\n get showConnector(): boolean {\n return this.#props.showConnector;\n }\n\n set showConnector(showConnector: boolean) {\n this.#props.showConnector = showConnector;\n this.#onStateChange();\n }\n\n get origin(): DialogOrigin {\n return this.#props.origin;\n }\n\n set origin(origin: DialogOrigin) {\n this.#props.origin = origin;\n this.#onStateChange();\n }\n\n get position(): DialogVerticalPosition {\n return this.#props.position;\n }\n\n set position(position: DialogVerticalPosition) {\n this.#props.position = position;\n this.#onStateChange();\n }\n\n get horizontalAlignment(): DialogHorizontalAlignment {\n return this.#props.horizontalAlignment;\n }\n\n set horizontalAlignment(alignment: DialogHorizontalAlignment) {\n this.#props.horizontalAlignment = alignment;\n this.#onStateChange();\n }\n\n get windowBoundsService(): WindowBoundsService.WindowBoundsService.WindowBoundsService {\n return this.#props.windowBoundsService;\n }\n\n set windowBoundsService(windowBoundsService: WindowBoundsService.WindowBoundsService.WindowBoundsService) {\n this.#props.windowBoundsService = windowBoundsService;\n this.#devToolsBoundingElement = this.windowBoundsService.getDevToolsBoundingElement();\n this.#onStateChange();\n }\n\n get bestVerticalPosition(): DialogVerticalPosition|null {\n return this.#bestVerticalPositionInternal;\n }\n\n get bestHorizontalAlignment(): DialogHorizontalAlignment|null {\n return this.#bestHorizontalAlignment;\n }\n get getConnectorCustomXPosition(): (() => number)|null {\n return this.#props.getConnectorCustomXPosition;\n }\n\n set getConnectorCustomXPosition(connectorXPosition: (() => number)|null) {\n this.#props.getConnectorCustomXPosition = connectorXPosition;\n this.#onStateChange();\n }\n\n get dialogShownCallback(): (() => unknown)|null {\n return this.#props.dialogShownCallback;\n }\n\n get jslogContext(): string {\n return this.#props.jslogContext;\n }\n\n set dialogShownCallback(dialogShownCallback: (() => unknown)|null) {\n this.#props.dialogShownCallback = dialogShownCallback;\n this.#onStateChange();\n }\n\n set closeOnESC(closeOnESC: boolean) {\n this.#props.closeOnESC = closeOnESC;\n this.#onStateChange();\n }\n\n set closeOnScroll(closeOnScroll: boolean) {\n this.#props.closeOnScroll = closeOnScroll;\n this.#onStateChange();\n }\n\n set jslogContext(jslogContext: string) {\n this.#props.jslogContext = jslogContext;\n this.#onStateChange();\n }\n\n #updateDialogBounds(): void {\n this.#dialogClientRect = this.#getDialog().getBoundingClientRect();\n }\n\n #onStateChange(): void {\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#renderBound);\n }\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [dialogStyles];\n\n window.addEventListener('resize', this.#forceDialogCloseInDevToolsBound);\n this.#devtoolsMutationObserver.observe(this.#devToolsBoundingElement, {childList: true, subtree: true});\n this.#devToolsBoundingElement.addEventListener('wheel', this.#handleScrollAttemptBound);\n this.style.setProperty('--dialog-padding', '0');\n this.style.setProperty('--override-content-box-shadow', 'none');\n this.style.setProperty('--dialog-display', IS_DIALOG_SUPPORTED ? 'block' : 'none');\n this.style.setProperty('--override-dialog-content-border', `${CONNECTOR_HEIGHT}px solid transparent`);\n this.style.setProperty('--dialog-padding', `${DIALOG_VERTICAL_PADDING}px ${DIALOG_SIDE_PADDING}px`);\n }\n\n disconnectedCallback(): void {\n window.removeEventListener('resize', this.#forceDialogCloseInDevToolsBound);\n\n this.#devToolsBoundingElement.removeEventListener('wheel', this.#handleScrollAttemptBound);\n this.#devtoolsMutationObserver.disconnect();\n this.#dialogResizeObserver.disconnect();\n }\n\n #getDialog(): HTMLDialogElement {\n if (!this.#dialog) {\n this.#dialog = this.#shadow.querySelector('dialog');\n if (!this.#dialog) {\n throw new Error('Dialog not found');\n }\n this.#dialogResizeObserver.observe(this.#dialog);\n }\n return this.#dialog;\n }\n\n getHitArea(): DOMRect {\n return this.#hitArea;\n }\n\n async setDialogVisible(show: boolean): Promise {\n if (show) {\n await this.#showDialog();\n return;\n }\n this.#closeDialog();\n }\n\n async #handlePointerEvent(evt: MouseEvent|PointerEvent): Promise {\n evt.stopPropagation();\n // If the user uses the keyboard to interact with an element within the\n // dialog, it will trigger a pointer event (for example, the user might use\n // their spacebar to \"click\" on a form input element). In that case the\n // pointerType will be an empty string, rather than `mouse`, `pen` or\n // `touch`. In this instance, we early return, because we only need to\n // worry about clicks outside of the dialog. Once the dialog is open, the\n // user can only use the keyboard to navigate within the dialog; so we\n // don't have to concern ourselves with keyboard events that occur outside\n // the dialog's bounds.\n if (evt instanceof PointerEvent && evt.pointerType === '') {\n return;\n }\n\n const eventWasInDialogContent = this.#mouseEventWasInDialogContent(evt);\n const eventWasInHitArea = this.#mouseEventWasInHitArea(evt);\n if (eventWasInDialogContent) {\n return;\n }\n if (evt.type === 'pointermove') {\n if (eventWasInHitArea) {\n return;\n }\n this.dispatchEvent(new PointerLeftDialogEvent());\n return;\n }\n this.dispatchEvent(new ClickOutsideDialogEvent());\n }\n\n #mouseEventWasInDialogContent(evt: MouseEvent): boolean {\n const dialogBounds = this.#dialogClientRect;\n const animationOffSetValue = this.bestVerticalPosition === DialogVerticalPosition.BOTTOM ?\n DIALOG_ANIMATION_OFFSET :\n -1 * DIALOG_ANIMATION_OFFSET;\n const eventWasDialogContentX =\n evt.pageX >= dialogBounds.left && evt.pageX <= dialogBounds.left + dialogBounds.width;\n const eventWasDialogContentY = evt.pageY >= dialogBounds.top + animationOffSetValue &&\n evt.pageY <= dialogBounds.top + dialogBounds.height + animationOffSetValue;\n\n return eventWasDialogContentX && eventWasDialogContentY;\n }\n\n #mouseEventWasInHitArea(evt: MouseEvent): boolean {\n const hitAreaBounds = this.#hitArea;\n const eventWasInHitAreaX = evt.pageX >= hitAreaBounds.left && evt.pageX <= hitAreaBounds.left + hitAreaBounds.width;\n const eventWasInHitAreaY = evt.pageY >= hitAreaBounds.top && evt.pageY <= hitAreaBounds.top + hitAreaBounds.height;\n\n return eventWasInHitAreaX && eventWasInHitAreaY;\n }\n\n #getCoordinatesFromDialogOrigin(origin: DialogOrigin): AnchorBounds {\n if (!origin || origin === MODAL) {\n throw new Error('Dialog origin is null');\n }\n const anchor = origin instanceof Function ? origin() : origin;\n if (anchor instanceof DOMPoint) {\n return {top: anchor.y, bottom: anchor.y, left: anchor.x, right: anchor.x};\n }\n if (anchor instanceof HTMLElement) {\n return anchor.getBoundingClientRect();\n }\n return anchor;\n }\n\n #getBestHorizontalAlignment(anchorBounds: AnchorBounds, devtoolsBounds: DOMRect): DialogHorizontalAlignment {\n if (devtoolsBounds.right - anchorBounds.left > anchorBounds.right - devtoolsBounds.left) {\n return DialogHorizontalAlignment.LEFT;\n }\n return DialogHorizontalAlignment.RIGHT;\n }\n\n #getBestVerticalPosition(originBounds: AnchorBounds, dialogHeight: number, devtoolsBounds: DOMRect):\n DialogVerticalPosition {\n // If the dialog's full height doesn't fit at the bottom attempt to\n // position it at the top. If it doesn't fit at the top either\n // position it at the bottom and make the overflow scrollable.\n if (originBounds.bottom + dialogHeight > devtoolsBounds.height &&\n originBounds.top - dialogHeight > devtoolsBounds.top) {\n return DialogVerticalPosition.TOP;\n }\n return DialogVerticalPosition.BOTTOM;\n }\n\n #positionDialog(): void {\n if (!this.#props.origin) {\n return;\n }\n\n this.#isPendingShowDialog = true;\n void coordinator.read(() => {\n // Fixed elements are positioned relative to the window, regardless if\n // DevTools is docked. As such, if DevTools is docked we must account for\n // its offset relative to the window when positioning fixed elements.\n // DevTools' effective offset can be determined using\n // this.#devToolsBoundingElement.\n const devtoolsBounds = this.#devToolsBoundingElement.getBoundingClientRect();\n const devToolsWidth = devtoolsBounds.width;\n const devToolsHeight = devtoolsBounds.height;\n const devToolsLeft = devtoolsBounds.left;\n const devToolsTop = devtoolsBounds.top;\n const devToolsRight = devtoolsBounds.right;\n if (this.#props.origin === MODAL) {\n void coordinator.write(() => {\n this.style.setProperty('--dialog-top', `${devToolsTop}px`);\n this.style.setProperty('--dialog-left', `${devToolsLeft}px`);\n this.style.setProperty('--dialog-margin', 'auto');\n this.style.setProperty('--dialog-margin-left', 'auto');\n this.style.setProperty('--dialog-margin-bottom', 'auto');\n this.style.setProperty('--dialog-max-height', `${devToolsHeight - DIALOG_PADDING_FROM_WINDOW}px`);\n this.style.setProperty('--dialog-max-width', `${devToolsWidth - DIALOG_PADDING_FROM_WINDOW}px`);\n this.style.setProperty('--dialog-right', `${document.body.clientWidth - devToolsRight}px`);\n });\n return;\n }\n const anchor = this.#props.origin;\n const absoluteAnchorBounds = this.#getCoordinatesFromDialogOrigin(anchor);\n const {top: anchorTop, right: anchorRight, bottom: anchorBottom, left: anchorLeft} = absoluteAnchorBounds;\n const originCenterX = (anchorLeft + anchorRight) / 2;\n const hitAreaWidth = anchorRight - anchorLeft + CONNECTOR_HEIGHT;\n const windowWidth = document.body.clientWidth;\n const connectorFixedXValue =\n this.#props.getConnectorCustomXPosition ? this.#props.getConnectorCustomXPosition() : originCenterX;\n void coordinator.write(() => {\n this.style.setProperty('--dialog-top', '0');\n\n // Start by showing the dialog hidden to allow measuring its width.\n const dialog = this.#getDialog();\n dialog.style.visibility = 'hidden';\n if (this.#isPendingShowDialog && !dialog.hasAttribute('open')) {\n dialog.showModal();\n this.setAttribute('open', '');\n this.#isPendingShowDialog = false;\n }\n const {width: dialogWidth, height: dialogHeight} = dialog.getBoundingClientRect();\n this.#bestHorizontalAlignment = this.#props.horizontalAlignment === DialogHorizontalAlignment.AUTO ?\n this.#getBestHorizontalAlignment(absoluteAnchorBounds, devtoolsBounds) :\n this.#props.horizontalAlignment;\n\n this.#bestVerticalPositionInternal = this.#props.position === DialogVerticalPosition.AUTO ?\n this.#getBestVerticalPosition(absoluteAnchorBounds, dialogHeight, devtoolsBounds) :\n this.#props.position;\n if (this.#bestHorizontalAlignment === DialogHorizontalAlignment.AUTO ||\n this.#bestVerticalPositionInternal === DialogVerticalPosition.AUTO) {\n return;\n }\n this.#hitArea.height = anchorBottom - anchorTop + (CONNECTOR_HEIGHT * (this.showConnector ? 2 : 1));\n this.#hitArea.width = hitAreaWidth;\n let connectorRelativeXValue = 0;\n // If the connector is to be shown, the dialog needs a minimum width such that it covers\n // the connector's width.\n this.style.setProperty(\n '--content-min-width',\n `${connectorFixedXValue - anchorLeft + CONNECTOR_WIDTH + DIALOG_SIDE_PADDING * 2}px`);\n this.style.setProperty('--dialog-left', 'auto');\n this.style.setProperty('--dialog-right', 'auto');\n this.style.setProperty('--dialog-margin', '0');\n const offsetToCoverConnector = this.showConnector ? CONNECTOR_WIDTH * 3 / 4 : 0;\n switch (this.#bestHorizontalAlignment) {\n case DialogHorizontalAlignment.LEFT: {\n // Position the dialog such that its left border is in line with that of its anchor.\n // If this means the dialog's left border is out of DevTools bounds, move it to the right.\n // Cap its width as needed so that the right border doesn't overflow.\n const dialogLeft = Math.max(anchorLeft - offsetToCoverConnector, devToolsLeft);\n const devtoolsRightBorderToDialogLeft = devToolsRight - dialogLeft;\n const dialogMaxWidth = devtoolsRightBorderToDialogLeft - DIALOG_PADDING_FROM_WINDOW;\n connectorRelativeXValue = connectorFixedXValue - dialogLeft - DIALOG_SIDE_PADDING;\n this.style.setProperty('--dialog-left', `${dialogLeft}px`);\n this.#hitArea.x = anchorLeft;\n this.style.setProperty('--dialog-max-width', `${dialogMaxWidth}px`);\n break;\n }\n case DialogHorizontalAlignment.RIGHT: {\n // Position the dialog such that its right border is in line with that of its anchor.\n // If this means the dialog's right border is out of DevTools bounds, move it to the left.\n // Cap its width as needed so that the left border doesn't overflow.\n const windowRightBorderToAnchorRight = windowWidth - anchorRight;\n const windowRightBorderToDevToolsRight = windowWidth - devToolsRight;\n const windowRightBorderToDialogRight =\n Math.max(windowRightBorderToAnchorRight - offsetToCoverConnector, windowRightBorderToDevToolsRight);\n\n const dialogRight = windowWidth - windowRightBorderToDialogRight;\n const devtoolsLeftBorderToDialogRight = dialogRight - devToolsLeft;\n const dialogMaxWidth = devtoolsLeftBorderToDialogRight - DIALOG_PADDING_FROM_WINDOW;\n const dialogCappedWidth = Math.min(dialogMaxWidth, dialogWidth);\n\n const dialogLeft = dialogRight - dialogCappedWidth;\n connectorRelativeXValue = connectorFixedXValue - dialogLeft;\n\n this.#hitArea.x = windowWidth - windowRightBorderToDialogRight - hitAreaWidth;\n this.style.setProperty('--dialog-right', `${windowRightBorderToDialogRight}px`);\n this.style.setProperty('--dialog-max-width', `${dialogMaxWidth}px`);\n break;\n }\n case DialogHorizontalAlignment.CENTER: {\n // Position the dialog aligned with its anchor's center as long as its borders don't overlap\n // with those of DevTools. In case one border overlaps, move the dialog to the opposite side.\n // In case both borders overlap, reduce its width to that of DevTools.\n const dialogCappedWidth = Math.min(devToolsWidth - DIALOG_PADDING_FROM_WINDOW, dialogWidth);\n\n let dialogLeft = Math.max(originCenterX - dialogCappedWidth * 0.5, devToolsLeft);\n dialogLeft = Math.min(dialogLeft, devToolsRight - dialogCappedWidth);\n connectorRelativeXValue = connectorFixedXValue - dialogLeft - DIALOG_SIDE_PADDING;\n this.style.setProperty('--dialog-left', `${dialogLeft}px`);\n this.#hitArea.x = originCenterX - hitAreaWidth * 0.5;\n this.style.setProperty('--dialog-max-width', `${devToolsWidth - DIALOG_PADDING_FROM_WINDOW}px`);\n break;\n }\n default:\n Platform.assertNever(\n this.#bestHorizontalAlignment, `Unknown alignment type: ${this.#bestHorizontalAlignment}`);\n }\n const visibleConnectorHeight = this.showConnector ? CONNECTOR_HEIGHT : 0;\n const clipPathConnectorStartX = connectorRelativeXValue - CONNECTOR_WIDTH / 2;\n const clipPathConnectorEndX = connectorRelativeXValue + CONNECTOR_WIDTH / 2;\n let [p1, p2, p3, p4, p5, p6, p7, p8, p9] = ['', '', '', '', '', '', '', '', '', ''];\n\n const PSEUDO_BORDER_RADIUS = 2;\n switch (this.#bestVerticalPositionInternal) {\n case DialogVerticalPosition.TOP: {\n // p1 p2\n // *-----------------------------*\n // | |\n // | |\n // p9| |\n // \\__________________p7 p5____/ p3 <-- A pseudo curve is added to the clip path to\n // p8 \\/ p4 imitate a curved boder.\n // p6\n // |-connectorRelativeX--|\n const clipPathBottom = `calc(100% - ${CONNECTOR_HEIGHT}px)`;\n if (this.#props.showConnector) {\n p1 = '0 0';\n p2 = '100% 0';\n p3 = `100% calc(${clipPathBottom} - ${PSEUDO_BORDER_RADIUS}px)`;\n p4 = `calc(100% - ${PSEUDO_BORDER_RADIUS}px) ${clipPathBottom}`;\n p5 = `${clipPathConnectorStartX}px ${clipPathBottom}`;\n p6 = `${connectorRelativeXValue}px 100%`;\n p7 = `${clipPathConnectorEndX}px ${clipPathBottom}`;\n p8 = `${PSEUDO_BORDER_RADIUS}px ${clipPathBottom}`;\n p9 = `0 calc(${clipPathBottom} - ${PSEUDO_BORDER_RADIUS}px)`;\n }\n\n this.style.setProperty(\n '--content-padding-bottom',\n `${CONNECTOR_HEIGHT + (this.#props.showConnector ? CONNECTOR_HEIGHT : 0)}px`);\n this.style.setProperty('--content-padding-top', `${CONNECTOR_HEIGHT}px`);\n this.style.setProperty('--dialog-top', '0');\n this.style.setProperty('--dialog-margin', 'auto');\n this.style.setProperty('--dialog-margin-bottom', `${innerHeight - anchorTop}px`);\n this.#hitArea.y = anchorTop - 2 * CONNECTOR_HEIGHT;\n this.style.setProperty('--dialog-offset-y', `${DIALOG_ANIMATION_OFFSET}px`);\n this.style.setProperty(\n '--dialog-max-height',\n `${\n devToolsHeight - (innerHeight - anchorTop) - DIALOG_PADDING_FROM_WINDOW -\n visibleConnectorHeight}px`);\n break;\n }\n case DialogVerticalPosition.BOTTOM: {\n // p4\n // p2_________/\\_________p6\n // / p3 p5 \\\n // p1 | | p7\n // | |\n // p9 *________________________* p8\n\n if (this.#props.showConnector) {\n p1 = `0 ${CONNECTOR_HEIGHT + PSEUDO_BORDER_RADIUS}px`;\n p2 = `${PSEUDO_BORDER_RADIUS}px ${CONNECTOR_HEIGHT}px`;\n p3 = `${clipPathConnectorStartX}px ${CONNECTOR_HEIGHT}px`;\n p4 = `${connectorRelativeXValue}px 0`;\n p5 = `${clipPathConnectorEndX}px ${CONNECTOR_HEIGHT}px`;\n p6 = `calc(100% - ${PSEUDO_BORDER_RADIUS}px) ${CONNECTOR_HEIGHT}px`;\n p7 = `100% ${CONNECTOR_HEIGHT + PSEUDO_BORDER_RADIUS}px`;\n p8 = '100% 100%';\n p9 = '0 100%';\n }\n this.style.setProperty(\n '--content-padding-top', `${CONNECTOR_HEIGHT + (this.#props.showConnector ? CONNECTOR_HEIGHT : 0)}px`);\n this.style.setProperty('--content-padding-bottom', `${CONNECTOR_HEIGHT}px`);\n this.style.setProperty('--dialog-top', `${anchorBottom}px`);\n this.#hitArea.y = anchorTop;\n this.style.setProperty('--dialog-offset-y', `-${DIALOG_ANIMATION_OFFSET}px`);\n this.style.setProperty(\n '--dialog-max-height',\n `${\n devToolsHeight - (anchorBottom - devToolsTop) - DIALOG_PADDING_FROM_WINDOW -\n visibleConnectorHeight}px`);\n break;\n }\n default:\n Platform.assertNever(\n this.#bestVerticalPositionInternal, `Unknown position type: ${this.#bestVerticalPositionInternal}`);\n }\n\n const clipPath = [p1, p2, p3, p4, p5, p6, p7, p8, p9].join();\n\n this.style.setProperty('--content-clip-path', clipPath);\n dialog.close();\n dialog.style.visibility = '';\n });\n });\n }\n\n async #showDialog(): Promise {\n if (!IS_DIALOG_SUPPORTED) {\n return;\n }\n\n if (this.#isPendingShowDialog || this.hasAttribute('open')) {\n return;\n }\n this.#isPendingShowDialog = true;\n this.#positionDialog();\n // Allow the CSS variables to be set before showing.\n await coordinator.done();\n this.#isPendingShowDialog = false;\n const dialog = this.#getDialog();\n // Make the dialog visible now.\n if (!dialog.hasAttribute('open')) {\n dialog.showModal();\n }\n if (this.#props.dialogShownCallback) {\n await this.#props.dialogShownCallback();\n }\n this.#updateDialogBounds();\n document.body.addEventListener('keydown', this.#onKeyDownBound);\n }\n\n #handleScrollAttempt(event: WheelEvent): void {\n if (this.#mouseEventWasInDialogContent(event) || !this.#props.closeOnScroll ||\n !this.#getDialog().hasAttribute('open')) {\n return;\n }\n this.#closeDialog();\n this.dispatchEvent(new ForcedDialogClose());\n }\n\n #onKeyDown(event: KeyboardEvent): void {\n if (!this.#getDialog().hasAttribute('open') || !this.#props.closeOnESC) {\n return;\n }\n\n if (event.key !== Platform.KeyboardUtilities.ESCAPE_KEY) {\n return;\n }\n event.stopPropagation();\n event.preventDefault();\n this.#closeDialog();\n this.dispatchEvent(new ForcedDialogClose());\n }\n\n #onCancel(event: Event): void {\n event.stopPropagation();\n event.preventDefault();\n if (!this.#getDialog().hasAttribute('open') || !this.#props.closeOnESC) {\n return;\n }\n this.dispatchEvent(new ForcedDialogClose());\n }\n\n #forceDialogCloseInDevToolsMutation(): void {\n if (!this.#dialog?.hasAttribute('open')) {\n return;\n }\n if (this.#devToolsBoundingElement === document.body) {\n // Do not close if running in test environment.\n return;\n }\n this.#closeDialog();\n this.dispatchEvent(new ForcedDialogClose());\n }\n\n #closeDialog(): void {\n if (this.#isPendingCloseDialog || !this.#getDialog().hasAttribute('open')) {\n return;\n }\n this.#isPendingCloseDialog = true;\n void coordinator.write(() => {\n this.#hitArea.width = 0;\n this.removeAttribute('open');\n this.#getDialog().close();\n this.#isPendingCloseDialog = false;\n document.body.removeEventListener('keydown', this.#onKeyDownBound);\n });\n }\n\n getDialogBounds(): DOMRect {\n return this.#dialogClientRect;\n }\n\n #render(): void {\n if (!ComponentHelpers.ScheduledRender.isScheduledRender(this)) {\n throw new Error('Dialog render was not scheduled');\n }\n\n if (!IS_DIALOG_SUPPORTED) {\n // To make sure that light dom content passed into this component doesn't show up,\n // we have to explicitly render a slot and hide it with CSS.\n LitHtml.render(\n // clang-format off\n LitHtml.html`\n \n `, this.#shadow, {host: this});\n // clang-format on\n return;\n }\n\n // clang-format off\n LitHtml.render(LitHtml.html`\n \n
    \n
    \n \n
    \n
    \n
    \n `, this.#shadow, { host: this });\n VisualLogging.setMappedParent(this.#getDialog(), this.parentElementOrShadowHost() as HTMLElement);\n // clang-format on\n }\n}\n\ncustomElements.define('devtools-dialog', Dialog);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-dialog': Dialog;\n }\n}\n\nexport class PointerLeftDialogEvent extends Event {\n static readonly eventName = 'pointerleftdialog';\n\n constructor() {\n super(PointerLeftDialogEvent.eventName, {bubbles: true, composed: true});\n }\n}\n\nexport class ClickOutsideDialogEvent extends Event {\n static readonly eventName = 'clickoutsidedialog';\n\n constructor() {\n super(ClickOutsideDialogEvent.eventName, {bubbles: true, composed: true});\n }\n}\n\nexport class ForcedDialogClose extends Event {\n static readonly eventName = 'forceddialogclose';\n constructor() {\n super(ForcedDialogClose.eventName, {bubbles: true, composed: true});\n }\n}\n\nexport const enum DialogVerticalPosition {\n TOP = 'top',\n BOTTOM = 'bottom',\n AUTO = 'auto',\n}\n\nexport const enum DialogHorizontalAlignment {\n // Dialog and anchor are aligned on their left borders.\n LEFT = 'left',\n // Dialog and anchor are aligned on their right borders.\n RIGHT = 'right',\n CENTER = 'center',\n // This option allows to set the alignment\n // automatically to LEFT or RIGHT depending\n // on whether the dialog overflows the\n // viewport if it's aligned to the left.\n AUTO = 'auto',\n}\n\ntype AnchorBounds = {\n top: number,\n bottom: number,\n left: number,\n right: number,\n};\n"]} \ No newline at end of file +{"version":3,"file":"Dialog.js","sourceRoot":"","sources":["../../../../../../../front_end/ui/components/dialogs/Dialog.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport * as WindowBoundsService from '../../../services/window_bounds/window_bounds.js';\nimport * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';\nimport * as Coordinator from '../../../ui/components/render_coordinator/render_coordinator.js';\nimport * as LitHtml from '../../../ui/lit-html/lit-html.js';\nimport * as VisualLogging from '../../../ui/visual_logging/visual_logging.js';\n\nimport dialogStyles from './dialog.css.js';\n\nconst coordinator = Coordinator.RenderCoordinator.RenderCoordinator.instance();\n\nconst IS_DIALOG_SUPPORTED = 'HTMLDialogElement' in globalThis;\n\n// Height in pixels of the dialog's connector. The connector is represented as\n// as a diamond and the height corresponds to half the height of the diamond.\n// (the visible height is only half of the diamond).\nexport const CONNECTOR_HEIGHT = 10;\nconst CONNECTOR_WIDTH = 2 * CONNECTOR_HEIGHT;\n\n// The offset used by the dialog's animation as it slides in when opened.\nconst DIALOG_ANIMATION_OFFSET = 20;\n\nexport const DIALOG_SIDE_PADDING = 5;\nexport const DIALOG_VERTICAL_PADDING = 3;\n\n// If the content of the dialog cannot be completely shown because otherwise\n// the dialog would overflow the window, the dialog's max width and height are\n// set such that the dialog remains inside the visible bounds. In this cases\n// some extra, determined by this constant, is added so that the dialog's borders\n// remain clearly visible. This constant accounts for the padding of the dialog's\n// content (20 px) and a 5px gap left on each extreme of the dialog from the viewport.\nexport const DIALOG_PADDING_FROM_WINDOW = 3 * CONNECTOR_HEIGHT;\ninterface DialogData {\n /**\n * Position or point the dialog is shown relative to.\n * If the dialog instance will be shown as a modal, set\n * this property to MODAL.\n */\n origin: DialogOrigin;\n position: DialogVerticalPosition;\n /**\n * Horizontal alignment of the dialg with respect to its origin.\n * Center by default.\n */\n horizontalAlignment: DialogHorizontalAlignment;\n /**\n * Whether the connector from the dialog to its origin is shown.\n */\n showConnector: boolean;\n\n /**\n * Optional function used to the determine the x coordinate of the connector's\n * end (tip of the triangle), relative to the viewport. If not defined, the x\n * coordinate of the origin's center is used instead.\n */\n getConnectorCustomXPosition: (() => number)|null;\n\n /**\n * Optional function called when the dialog is shown.\n */\n dialogShownCallback: (() => unknown)|null;\n\n /**\n * Optional. Service that provides the window dimensions used for positioning the Dialog.\n */\n windowBoundsService: WindowBoundsService.WindowBoundsService.WindowBoundsService;\n /**\n * Whether the dialog is closed when the 'Escape' key is pressed. When true, the event is\n * propagation is stopped.\n */\n closeOnESC: boolean;\n /**\n * Whether the dialog is closed when a scroll event is detected outside of the dialog's\n * content. Defaults to true.\n */\n closeOnScroll: boolean;\n /**\n * Specifies a context for the visual element.\n */\n jslogContext: string;\n}\n\ntype DialogAnchor = HTMLElement|DOMRect|DOMPoint;\n\nexport const MODAL = 'MODAL';\n\nexport type DialogOrigin = DialogAnchor|null|(() => DialogAnchor)|typeof MODAL;\nexport class Dialog extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-dialog`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n readonly #renderBound = this.#render.bind(this);\n readonly #forceDialogCloseInDevToolsBound = this.#forceDialogCloseInDevToolsMutation.bind(this);\n readonly #handleScrollAttemptBound = this.#handleScrollAttempt.bind(this);\n readonly #props: DialogData = {\n origin: MODAL,\n position: DialogVerticalPosition.BOTTOM,\n horizontalAlignment: DialogHorizontalAlignment.CENTER,\n showConnector: false,\n getConnectorCustomXPosition: null,\n dialogShownCallback: null,\n windowBoundsService: WindowBoundsService.WindowBoundsService.WindowBoundsServiceImpl.instance(),\n closeOnESC: true,\n closeOnScroll: true,\n jslogContext: '',\n };\n\n #dialog: HTMLDialogElement|null = null;\n #isPendingShowDialog = false;\n #isPendingCloseDialog = false;\n #hitArea = new DOMRect(0, 0, 0, 0);\n #dialogClientRect = new DOMRect(0, 0, 0, 0);\n #bestVerticalPositionInternal: DialogVerticalPosition|null = null;\n #bestHorizontalAlignment: DialogHorizontalAlignment|null = null;\n readonly #devtoolsMutationObserver = new MutationObserver(this.#forceDialogCloseInDevToolsBound);\n readonly #dialogResizeObserver = new ResizeObserver(this.#updateDialogBounds.bind(this));\n #devToolsBoundingElement = this.windowBoundsService.getDevToolsBoundingElement();\n\n // We bind here because we have to listen to keydowns on the entire window,\n // not on the Dialog element itself. This is because if the user has the\n // dialog open, but their focus is elsewhere, and they hit ESC, we should\n // still close the dialog.\n #onKeyDownBound = this.#onKeyDown.bind(this);\n\n get showConnector(): boolean {\n return this.#props.showConnector;\n }\n\n set showConnector(showConnector: boolean) {\n this.#props.showConnector = showConnector;\n this.#onStateChange();\n }\n\n get origin(): DialogOrigin {\n return this.#props.origin;\n }\n\n set origin(origin: DialogOrigin) {\n this.#props.origin = origin;\n this.#onStateChange();\n }\n\n get position(): DialogVerticalPosition {\n return this.#props.position;\n }\n\n set position(position: DialogVerticalPosition) {\n this.#props.position = position;\n this.#onStateChange();\n }\n\n get horizontalAlignment(): DialogHorizontalAlignment {\n return this.#props.horizontalAlignment;\n }\n\n set horizontalAlignment(alignment: DialogHorizontalAlignment) {\n this.#props.horizontalAlignment = alignment;\n this.#onStateChange();\n }\n\n get windowBoundsService(): WindowBoundsService.WindowBoundsService.WindowBoundsService {\n return this.#props.windowBoundsService;\n }\n\n set windowBoundsService(windowBoundsService: WindowBoundsService.WindowBoundsService.WindowBoundsService) {\n this.#props.windowBoundsService = windowBoundsService;\n this.#devToolsBoundingElement = this.windowBoundsService.getDevToolsBoundingElement();\n this.#onStateChange();\n }\n\n get bestVerticalPosition(): DialogVerticalPosition|null {\n return this.#bestVerticalPositionInternal;\n }\n\n get bestHorizontalAlignment(): DialogHorizontalAlignment|null {\n return this.#bestHorizontalAlignment;\n }\n get getConnectorCustomXPosition(): (() => number)|null {\n return this.#props.getConnectorCustomXPosition;\n }\n\n set getConnectorCustomXPosition(connectorXPosition: (() => number)|null) {\n this.#props.getConnectorCustomXPosition = connectorXPosition;\n this.#onStateChange();\n }\n\n get dialogShownCallback(): (() => unknown)|null {\n return this.#props.dialogShownCallback;\n }\n\n get jslogContext(): string {\n return this.#props.jslogContext;\n }\n\n set dialogShownCallback(dialogShownCallback: (() => unknown)|null) {\n this.#props.dialogShownCallback = dialogShownCallback;\n this.#onStateChange();\n }\n\n set closeOnESC(closeOnESC: boolean) {\n this.#props.closeOnESC = closeOnESC;\n this.#onStateChange();\n }\n\n set closeOnScroll(closeOnScroll: boolean) {\n this.#props.closeOnScroll = closeOnScroll;\n this.#onStateChange();\n }\n\n set jslogContext(jslogContext: string) {\n this.#props.jslogContext = jslogContext;\n this.#onStateChange();\n }\n\n #updateDialogBounds(): void {\n this.#dialogClientRect = this.#getDialog().getBoundingClientRect();\n }\n\n #onStateChange(): void {\n void ComponentHelpers.ScheduledRender.scheduleRender(this, this.#renderBound);\n }\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [dialogStyles];\n\n window.addEventListener('resize', this.#forceDialogCloseInDevToolsBound);\n this.#devtoolsMutationObserver.observe(this.#devToolsBoundingElement, {childList: true, subtree: true});\n this.#devToolsBoundingElement.addEventListener('wheel', this.#handleScrollAttemptBound);\n this.style.setProperty('--dialog-padding', '0');\n this.style.setProperty('--override-content-box-shadow', 'none');\n this.style.setProperty('--dialog-display', IS_DIALOG_SUPPORTED ? 'block' : 'none');\n this.style.setProperty('--override-dialog-content-border', `${CONNECTOR_HEIGHT}px solid transparent`);\n this.style.setProperty('--dialog-padding', `${DIALOG_VERTICAL_PADDING}px ${DIALOG_SIDE_PADDING}px`);\n }\n\n disconnectedCallback(): void {\n window.removeEventListener('resize', this.#forceDialogCloseInDevToolsBound);\n\n this.#devToolsBoundingElement.removeEventListener('wheel', this.#handleScrollAttemptBound);\n this.#devtoolsMutationObserver.disconnect();\n this.#dialogResizeObserver.disconnect();\n }\n\n #getDialog(): HTMLDialogElement {\n if (!this.#dialog) {\n this.#dialog = this.#shadow.querySelector('dialog');\n if (!this.#dialog) {\n throw new Error('Dialog not found');\n }\n this.#dialogResizeObserver.observe(this.#dialog);\n }\n return this.#dialog;\n }\n\n getHitArea(): DOMRect {\n return this.#hitArea;\n }\n\n async setDialogVisible(show: boolean): Promise {\n if (show) {\n await this.#showDialog();\n return;\n }\n this.#closeDialog();\n }\n\n async #handlePointerEvent(evt: MouseEvent|PointerEvent): Promise {\n evt.stopPropagation();\n // If the user uses the keyboard to interact with an element within the\n // dialog, it will trigger a pointer event (for example, the user might use\n // their spacebar to \"click\" on a form input element). In that case the\n // pointerType will be an empty string, rather than `mouse`, `pen` or\n // `touch`. In this instance, we early return, because we only need to\n // worry about clicks outside of the dialog. Once the dialog is open, the\n // user can only use the keyboard to navigate within the dialog; so we\n // don't have to concern ourselves with keyboard events that occur outside\n // the dialog's bounds.\n if (evt instanceof PointerEvent && evt.pointerType === '') {\n return;\n }\n\n const eventWasInDialogContent = this.#mouseEventWasInDialogContent(evt);\n const eventWasInHitArea = this.#mouseEventWasInHitArea(evt);\n if (eventWasInDialogContent) {\n return;\n }\n if (evt.type === 'pointermove') {\n if (eventWasInHitArea) {\n return;\n }\n this.dispatchEvent(new PointerLeftDialogEvent());\n return;\n }\n this.dispatchEvent(new ClickOutsideDialogEvent());\n }\n\n #mouseEventWasInDialogContent(evt: MouseEvent): boolean {\n const dialogBounds = this.#dialogClientRect;\n\n let animationOffSetValue = this.bestVerticalPosition === DialogVerticalPosition.BOTTOM ?\n DIALOG_ANIMATION_OFFSET :\n -1 * DIALOG_ANIMATION_OFFSET;\n if (this.#props.origin === MODAL) {\n // When shown as a modal, the dialog is not animated\n animationOffSetValue = 0;\n }\n const eventWasDialogContentX =\n evt.pageX >= dialogBounds.left && evt.pageX <= dialogBounds.left + dialogBounds.width;\n const eventWasDialogContentY = evt.pageY >= dialogBounds.top + animationOffSetValue &&\n evt.pageY <= dialogBounds.top + dialogBounds.height + animationOffSetValue;\n\n return eventWasDialogContentX && eventWasDialogContentY;\n }\n\n #mouseEventWasInHitArea(evt: MouseEvent): boolean {\n const hitAreaBounds = this.#hitArea;\n const eventWasInHitAreaX = evt.pageX >= hitAreaBounds.left && evt.pageX <= hitAreaBounds.left + hitAreaBounds.width;\n const eventWasInHitAreaY = evt.pageY >= hitAreaBounds.top && evt.pageY <= hitAreaBounds.top + hitAreaBounds.height;\n\n return eventWasInHitAreaX && eventWasInHitAreaY;\n }\n\n #getCoordinatesFromDialogOrigin(origin: DialogOrigin): AnchorBounds {\n if (!origin || origin === MODAL) {\n throw new Error('Dialog origin is null');\n }\n const anchor = origin instanceof Function ? origin() : origin;\n if (anchor instanceof DOMPoint) {\n return {top: anchor.y, bottom: anchor.y, left: anchor.x, right: anchor.x};\n }\n if (anchor instanceof HTMLElement) {\n return anchor.getBoundingClientRect();\n }\n return anchor;\n }\n\n #getBestHorizontalAlignment(anchorBounds: AnchorBounds, devtoolsBounds: DOMRect): DialogHorizontalAlignment {\n if (devtoolsBounds.right - anchorBounds.left > anchorBounds.right - devtoolsBounds.left) {\n return DialogHorizontalAlignment.LEFT;\n }\n return DialogHorizontalAlignment.RIGHT;\n }\n\n #getBestVerticalPosition(originBounds: AnchorBounds, dialogHeight: number, devtoolsBounds: DOMRect):\n DialogVerticalPosition {\n // If the dialog's full height doesn't fit at the bottom attempt to\n // position it at the top. If it doesn't fit at the top either\n // position it at the bottom and make the overflow scrollable.\n if (originBounds.bottom + dialogHeight > devtoolsBounds.height &&\n originBounds.top - dialogHeight > devtoolsBounds.top) {\n return DialogVerticalPosition.TOP;\n }\n return DialogVerticalPosition.BOTTOM;\n }\n\n #positionDialog(): void {\n if (!this.#props.origin) {\n return;\n }\n\n this.#isPendingShowDialog = true;\n void coordinator.read(() => {\n // Fixed elements are positioned relative to the window, regardless if\n // DevTools is docked. As such, if DevTools is docked we must account for\n // its offset relative to the window when positioning fixed elements.\n // DevTools' effective offset can be determined using\n // this.#devToolsBoundingElement.\n const devtoolsBounds = this.#devToolsBoundingElement.getBoundingClientRect();\n const devToolsWidth = devtoolsBounds.width;\n const devToolsHeight = devtoolsBounds.height;\n const devToolsLeft = devtoolsBounds.left;\n const devToolsTop = devtoolsBounds.top;\n const devToolsRight = devtoolsBounds.right;\n if (this.#props.origin === MODAL) {\n void coordinator.write(() => {\n this.style.setProperty('--dialog-top', `${devToolsTop}px`);\n this.style.setProperty('--dialog-left', `${devToolsLeft}px`);\n this.style.setProperty('--dialog-margin', 'auto');\n this.style.setProperty('--dialog-margin-left', 'auto');\n this.style.setProperty('--dialog-margin-bottom', 'auto');\n this.style.setProperty('--dialog-max-height', `${devToolsHeight - DIALOG_PADDING_FROM_WINDOW}px`);\n this.style.setProperty('--dialog-max-width', `${devToolsWidth - DIALOG_PADDING_FROM_WINDOW}px`);\n this.style.setProperty('--dialog-right', `${document.body.clientWidth - devToolsRight}px`);\n });\n return;\n }\n const anchor = this.#props.origin;\n const absoluteAnchorBounds = this.#getCoordinatesFromDialogOrigin(anchor);\n const {top: anchorTop, right: anchorRight, bottom: anchorBottom, left: anchorLeft} = absoluteAnchorBounds;\n const originCenterX = (anchorLeft + anchorRight) / 2;\n const hitAreaWidth = anchorRight - anchorLeft + CONNECTOR_HEIGHT;\n const windowWidth = document.body.clientWidth;\n const connectorFixedXValue =\n this.#props.getConnectorCustomXPosition ? this.#props.getConnectorCustomXPosition() : originCenterX;\n void coordinator.write(() => {\n this.style.setProperty('--dialog-top', '0');\n\n // Start by showing the dialog hidden to allow measuring its width.\n const dialog = this.#getDialog();\n dialog.style.visibility = 'hidden';\n if (this.#isPendingShowDialog && !dialog.hasAttribute('open')) {\n dialog.showModal();\n this.setAttribute('open', '');\n this.#isPendingShowDialog = false;\n }\n const {width: dialogWidth, height: dialogHeight} = dialog.getBoundingClientRect();\n this.#bestHorizontalAlignment = this.#props.horizontalAlignment === DialogHorizontalAlignment.AUTO ?\n this.#getBestHorizontalAlignment(absoluteAnchorBounds, devtoolsBounds) :\n this.#props.horizontalAlignment;\n\n this.#bestVerticalPositionInternal = this.#props.position === DialogVerticalPosition.AUTO ?\n this.#getBestVerticalPosition(absoluteAnchorBounds, dialogHeight, devtoolsBounds) :\n this.#props.position;\n if (this.#bestHorizontalAlignment === DialogHorizontalAlignment.AUTO ||\n this.#bestVerticalPositionInternal === DialogVerticalPosition.AUTO) {\n return;\n }\n this.#hitArea.height = anchorBottom - anchorTop + (CONNECTOR_HEIGHT * (this.showConnector ? 2 : 1));\n this.#hitArea.width = hitAreaWidth;\n let connectorRelativeXValue = 0;\n // If the connector is to be shown, the dialog needs a minimum width such that it covers\n // the connector's width.\n this.style.setProperty(\n '--content-min-width',\n `${connectorFixedXValue - anchorLeft + CONNECTOR_WIDTH + DIALOG_SIDE_PADDING * 2}px`);\n this.style.setProperty('--dialog-left', 'auto');\n this.style.setProperty('--dialog-right', 'auto');\n this.style.setProperty('--dialog-margin', '0');\n const offsetToCoverConnector = this.showConnector ? CONNECTOR_WIDTH * 3 / 4 : 0;\n switch (this.#bestHorizontalAlignment) {\n case DialogHorizontalAlignment.LEFT: {\n // Position the dialog such that its left border is in line with that of its anchor.\n // If this means the dialog's left border is out of DevTools bounds, move it to the right.\n // Cap its width as needed so that the right border doesn't overflow.\n const dialogLeft = Math.max(anchorLeft - offsetToCoverConnector, devToolsLeft);\n const devtoolsRightBorderToDialogLeft = devToolsRight - dialogLeft;\n const dialogMaxWidth = devtoolsRightBorderToDialogLeft - DIALOG_PADDING_FROM_WINDOW;\n connectorRelativeXValue = connectorFixedXValue - dialogLeft - DIALOG_SIDE_PADDING;\n this.style.setProperty('--dialog-left', `${dialogLeft}px`);\n this.#hitArea.x = anchorLeft;\n this.style.setProperty('--dialog-max-width', `${dialogMaxWidth}px`);\n break;\n }\n case DialogHorizontalAlignment.RIGHT: {\n // Position the dialog such that its right border is in line with that of its anchor.\n // If this means the dialog's right border is out of DevTools bounds, move it to the left.\n // Cap its width as needed so that the left border doesn't overflow.\n const windowRightBorderToAnchorRight = windowWidth - anchorRight;\n const windowRightBorderToDevToolsRight = windowWidth - devToolsRight;\n const windowRightBorderToDialogRight =\n Math.max(windowRightBorderToAnchorRight - offsetToCoverConnector, windowRightBorderToDevToolsRight);\n\n const dialogRight = windowWidth - windowRightBorderToDialogRight;\n const devtoolsLeftBorderToDialogRight = dialogRight - devToolsLeft;\n const dialogMaxWidth = devtoolsLeftBorderToDialogRight - DIALOG_PADDING_FROM_WINDOW;\n const dialogCappedWidth = Math.min(dialogMaxWidth, dialogWidth);\n\n const dialogLeft = dialogRight - dialogCappedWidth;\n connectorRelativeXValue = connectorFixedXValue - dialogLeft;\n\n this.#hitArea.x = windowWidth - windowRightBorderToDialogRight - hitAreaWidth;\n this.style.setProperty('--dialog-right', `${windowRightBorderToDialogRight}px`);\n this.style.setProperty('--dialog-max-width', `${dialogMaxWidth}px`);\n break;\n }\n case DialogHorizontalAlignment.CENTER: {\n // Position the dialog aligned with its anchor's center as long as its borders don't overlap\n // with those of DevTools. In case one border overlaps, move the dialog to the opposite side.\n // In case both borders overlap, reduce its width to that of DevTools.\n const dialogCappedWidth = Math.min(devToolsWidth - DIALOG_PADDING_FROM_WINDOW, dialogWidth);\n\n let dialogLeft = Math.max(originCenterX - dialogCappedWidth * 0.5, devToolsLeft);\n dialogLeft = Math.min(dialogLeft, devToolsRight - dialogCappedWidth);\n connectorRelativeXValue = connectorFixedXValue - dialogLeft - DIALOG_SIDE_PADDING;\n this.style.setProperty('--dialog-left', `${dialogLeft}px`);\n this.#hitArea.x = originCenterX - hitAreaWidth * 0.5;\n this.style.setProperty('--dialog-max-width', `${devToolsWidth - DIALOG_PADDING_FROM_WINDOW}px`);\n break;\n }\n default:\n Platform.assertNever(\n this.#bestHorizontalAlignment, `Unknown alignment type: ${this.#bestHorizontalAlignment}`);\n }\n const visibleConnectorHeight = this.showConnector ? CONNECTOR_HEIGHT : 0;\n const clipPathConnectorStartX = connectorRelativeXValue - CONNECTOR_WIDTH / 2;\n const clipPathConnectorEndX = connectorRelativeXValue + CONNECTOR_WIDTH / 2;\n let [p1, p2, p3, p4, p5, p6, p7, p8, p9] = ['', '', '', '', '', '', '', '', '', ''];\n\n const PSEUDO_BORDER_RADIUS = 2;\n switch (this.#bestVerticalPositionInternal) {\n case DialogVerticalPosition.TOP: {\n // p1 p2\n // *-----------------------------*\n // | |\n // | |\n // p9| |\n // \\__________________p7 p5____/ p3 <-- A pseudo curve is added to the clip path to\n // p8 \\/ p4 imitate a curved boder.\n // p6\n // |-connectorRelativeX--|\n const clipPathBottom = `calc(100% - ${CONNECTOR_HEIGHT}px)`;\n if (this.#props.showConnector) {\n p1 = '0 0';\n p2 = '100% 0';\n p3 = `100% calc(${clipPathBottom} - ${PSEUDO_BORDER_RADIUS}px)`;\n p4 = `calc(100% - ${PSEUDO_BORDER_RADIUS}px) ${clipPathBottom}`;\n p5 = `${clipPathConnectorStartX}px ${clipPathBottom}`;\n p6 = `${connectorRelativeXValue}px 100%`;\n p7 = `${clipPathConnectorEndX}px ${clipPathBottom}`;\n p8 = `${PSEUDO_BORDER_RADIUS}px ${clipPathBottom}`;\n p9 = `0 calc(${clipPathBottom} - ${PSEUDO_BORDER_RADIUS}px)`;\n }\n\n this.style.setProperty(\n '--content-padding-bottom',\n `${CONNECTOR_HEIGHT + (this.#props.showConnector ? CONNECTOR_HEIGHT : 0)}px`);\n this.style.setProperty('--content-padding-top', `${CONNECTOR_HEIGHT}px`);\n this.style.setProperty('--dialog-top', '0');\n this.style.setProperty('--dialog-margin', 'auto');\n this.style.setProperty('--dialog-margin-bottom', `${innerHeight - anchorTop}px`);\n this.#hitArea.y = anchorTop - 2 * CONNECTOR_HEIGHT;\n this.style.setProperty('--dialog-offset-y', `${DIALOG_ANIMATION_OFFSET}px`);\n this.style.setProperty(\n '--dialog-max-height',\n `${\n devToolsHeight - (innerHeight - anchorTop) - DIALOG_PADDING_FROM_WINDOW -\n visibleConnectorHeight}px`);\n break;\n }\n case DialogVerticalPosition.BOTTOM: {\n // p4\n // p2_________/\\_________p6\n // / p3 p5 \\\n // p1 | | p7\n // | |\n // p9 *________________________* p8\n\n if (this.#props.showConnector) {\n p1 = `0 ${CONNECTOR_HEIGHT + PSEUDO_BORDER_RADIUS}px`;\n p2 = `${PSEUDO_BORDER_RADIUS}px ${CONNECTOR_HEIGHT}px`;\n p3 = `${clipPathConnectorStartX}px ${CONNECTOR_HEIGHT}px`;\n p4 = `${connectorRelativeXValue}px 0`;\n p5 = `${clipPathConnectorEndX}px ${CONNECTOR_HEIGHT}px`;\n p6 = `calc(100% - ${PSEUDO_BORDER_RADIUS}px) ${CONNECTOR_HEIGHT}px`;\n p7 = `100% ${CONNECTOR_HEIGHT + PSEUDO_BORDER_RADIUS}px`;\n p8 = '100% 100%';\n p9 = '0 100%';\n }\n this.style.setProperty(\n '--content-padding-top', `${CONNECTOR_HEIGHT + (this.#props.showConnector ? CONNECTOR_HEIGHT : 0)}px`);\n this.style.setProperty('--content-padding-bottom', `${CONNECTOR_HEIGHT}px`);\n this.style.setProperty('--dialog-top', `${anchorBottom}px`);\n this.#hitArea.y = anchorTop;\n this.style.setProperty('--dialog-offset-y', `-${DIALOG_ANIMATION_OFFSET}px`);\n this.style.setProperty(\n '--dialog-max-height',\n `${\n devToolsHeight - (anchorBottom - devToolsTop) - DIALOG_PADDING_FROM_WINDOW -\n visibleConnectorHeight}px`);\n break;\n }\n default:\n Platform.assertNever(\n this.#bestVerticalPositionInternal, `Unknown position type: ${this.#bestVerticalPositionInternal}`);\n }\n\n const clipPath = [p1, p2, p3, p4, p5, p6, p7, p8, p9].join();\n\n this.style.setProperty('--content-clip-path', clipPath);\n dialog.close();\n dialog.style.visibility = '';\n });\n });\n }\n\n async #showDialog(): Promise {\n if (!IS_DIALOG_SUPPORTED) {\n return;\n }\n\n if (this.#isPendingShowDialog || this.hasAttribute('open')) {\n return;\n }\n this.#isPendingShowDialog = true;\n this.#positionDialog();\n // Allow the CSS variables to be set before showing.\n await coordinator.done();\n this.#isPendingShowDialog = false;\n const dialog = this.#getDialog();\n // Make the dialog visible now.\n if (!dialog.hasAttribute('open')) {\n dialog.showModal();\n }\n if (this.#props.dialogShownCallback) {\n await this.#props.dialogShownCallback();\n }\n this.#updateDialogBounds();\n document.body.addEventListener('keydown', this.#onKeyDownBound);\n }\n\n #handleScrollAttempt(event: WheelEvent): void {\n if (this.#mouseEventWasInDialogContent(event) || !this.#props.closeOnScroll ||\n !this.#getDialog().hasAttribute('open')) {\n return;\n }\n this.#closeDialog();\n this.dispatchEvent(new ForcedDialogClose());\n }\n\n #onKeyDown(event: KeyboardEvent): void {\n if (!this.#getDialog().hasAttribute('open') || !this.#props.closeOnESC) {\n return;\n }\n\n if (event.key !== Platform.KeyboardUtilities.ESCAPE_KEY) {\n return;\n }\n event.stopPropagation();\n event.preventDefault();\n this.#closeDialog();\n this.dispatchEvent(new ForcedDialogClose());\n }\n\n #onCancel(event: Event): void {\n event.stopPropagation();\n event.preventDefault();\n if (!this.#getDialog().hasAttribute('open') || !this.#props.closeOnESC) {\n return;\n }\n this.dispatchEvent(new ForcedDialogClose());\n }\n\n #forceDialogCloseInDevToolsMutation(): void {\n if (!this.#dialog?.hasAttribute('open')) {\n return;\n }\n if (this.#devToolsBoundingElement === document.body) {\n // Do not close if running in test environment.\n return;\n }\n this.#closeDialog();\n this.dispatchEvent(new ForcedDialogClose());\n }\n\n #closeDialog(): void {\n if (this.#isPendingCloseDialog || !this.#getDialog().hasAttribute('open')) {\n return;\n }\n this.#isPendingCloseDialog = true;\n void coordinator.write(() => {\n this.#hitArea.width = 0;\n this.removeAttribute('open');\n this.#getDialog().close();\n this.#isPendingCloseDialog = false;\n document.body.removeEventListener('keydown', this.#onKeyDownBound);\n });\n }\n\n getDialogBounds(): DOMRect {\n return this.#dialogClientRect;\n }\n\n #render(): void {\n if (!ComponentHelpers.ScheduledRender.isScheduledRender(this)) {\n throw new Error('Dialog render was not scheduled');\n }\n\n if (!IS_DIALOG_SUPPORTED) {\n // To make sure that light dom content passed into this component doesn't show up,\n // we have to explicitly render a slot and hide it with CSS.\n LitHtml.render(\n // clang-format off\n LitHtml.html`\n \n `, this.#shadow, {host: this});\n // clang-format on\n return;\n }\n\n // clang-format off\n LitHtml.render(LitHtml.html`\n \n
    \n
    \n \n
    \n
    \n
    \n `, this.#shadow, { host: this });\n VisualLogging.setMappedParent(this.#getDialog(), this.parentElementOrShadowHost() as HTMLElement);\n // clang-format on\n }\n}\n\ncustomElements.define('devtools-dialog', Dialog);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-dialog': Dialog;\n }\n}\n\nexport class PointerLeftDialogEvent extends Event {\n static readonly eventName = 'pointerleftdialog';\n\n constructor() {\n super(PointerLeftDialogEvent.eventName, {bubbles: true, composed: true});\n }\n}\n\nexport class ClickOutsideDialogEvent extends Event {\n static readonly eventName = 'clickoutsidedialog';\n\n constructor() {\n super(ClickOutsideDialogEvent.eventName, {bubbles: true, composed: true});\n }\n}\n\nexport class ForcedDialogClose extends Event {\n static readonly eventName = 'forceddialogclose';\n constructor() {\n super(ForcedDialogClose.eventName, {bubbles: true, composed: true});\n }\n}\n\nexport const enum DialogVerticalPosition {\n TOP = 'top',\n BOTTOM = 'bottom',\n AUTO = 'auto',\n}\n\nexport const enum DialogHorizontalAlignment {\n // Dialog and anchor are aligned on their left borders.\n LEFT = 'left',\n // Dialog and anchor are aligned on their right borders.\n RIGHT = 'right',\n CENTER = 'center',\n // This option allows to set the alignment\n // automatically to LEFT or RIGHT depending\n // on whether the dialog overflows the\n // viewport if it's aligned to the left.\n AUTO = 'auto',\n}\n\ntype AnchorBounds = {\n top: number,\n bottom: number,\n left: number,\n right: number,\n};\n"]} \ No newline at end of file diff --git a/public/ui/components/dialogs/Dialog.test.js b/public/ui/components/dialogs/Dialog.test.js index ed71a9db4..88e18cc39 100644 --- a/public/ui/components/dialogs/Dialog.test.js +++ b/public/ui/components/dialogs/Dialog.test.js @@ -455,4 +455,49 @@ describe('Dialog', () => { }); }); }); +describe('closing the dialog with click', () => { + let devtoolsDialog; + beforeEach(async () => { + devtoolsDialog = new Dialogs.Dialog.Dialog(); + const container = document.createElement('div'); + const host = document.createElement('div'); + const content = document.createElement('div'); + content.innerHTML = 'Hello, World
    I am
    a Dialog!'; + devtoolsDialog.origin = Dialogs.Dialog.MODAL; + host.addEventListener('click', () => devtoolsDialog.setDialogVisible(true)); + devtoolsDialog.addEventListener('clickoutsidedialog', () => devtoolsDialog.setDialogVisible(false)); + container.appendChild(host); + container.appendChild(devtoolsDialog); + Helpers.renderElementIntoDOM(container); + await coordinator.done(); + devtoolsDialog.appendChild(content); + // Open the dialog. + Helpers.dispatchClickEvent(host); + await coordinator.done(); + }); + it('Only closes the dialog if the click falls outside its content', async () => { + let dialog = devtoolsDialog.shadowRoot?.querySelector('dialog[open]'); + if (!dialog) { + assert.fail('Dialog not found'); + return; + } + const { x, width, bottom } = dialog.getBoundingClientRect(); + // Click just inside must not close the dialog. + Helpers.dispatchClickEvent(dialog, { clientX: x + width / 2, clientY: bottom - 1 }); + await coordinator.done(); + dialog = devtoolsDialog.shadowRoot?.querySelector('dialog[open]'); + if (!dialog) { + assert.fail('Dialog closed when it should not'); + return; + } + Helpers.dispatchClickEvent(dialog, { clientX: x + width / 2, clientY: bottom + 1 }); + await coordinator.done(); + // Click just outside must close the dialog. + dialog = devtoolsDialog.shadowRoot?.querySelector('dialog[open]'); + if (dialog) { + assert.fail('Dialog did not close'); + return; + } + }); +}); //# sourceMappingURL=Dialog.test.js.map \ No newline at end of file diff --git a/public/ui/components/dialogs/Dialog.test.js.map b/public/ui/components/dialogs/Dialog.test.js.map index 34b3199ab..f3c05ade2 100644 --- a/public/ui/components/dialogs/Dialog.test.js.map +++ b/public/ui/components/dialogs/Dialog.test.js.map @@ -1 +1 @@ -{"version":3,"file":"Dialog.test.js","sourceRoot":"","sources":["../../../../../../../front_end/ui/components/dialogs/Dialog.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport type * as WindowBoundsService from '../../../services/window_bounds/window_bounds.js';\nimport * as Helpers from '../../../testing/DOMHelpers.js'; // eslint-disable-line rulesdir/es_modules_import\nimport * as Coordinator from '../render_coordinator/render_coordinator.js';\n\nimport * as Dialogs from './dialogs.js';\n\nconst coordinator = Coordinator.RenderCoordinator.RenderCoordinator.instance();\nclass DialogExampleWindowBoundsServiceFactory implements WindowBoundsService.WindowBoundsService.WindowBoundsService {\n constructor(private boundingElement: HTMLElement) {\n }\n getDevToolsBoundingElement(): HTMLElement {\n return this.boundingElement;\n }\n}\n\ndescribe('Dialog', () => {\n describe('positioning', () => {\n let dialog: Dialogs.Dialog.Dialog;\n let container: HTMLDivElement;\n let host: HTMLDivElement;\n beforeEach(() => {\n dialog = new Dialogs.Dialog.Dialog();\n container = document.createElement('div');\n container.style.width = '500px';\n container.style.height = '500px';\n container.style.display = 'flex';\n container.style.alignItems = 'center';\n container.style.justifyContent = 'center';\n\n host = document.createElement('div');\n host.textContent = 'Hover me';\n host.style.width = '100px';\n host.style.height = '100px';\n\n dialog.position = Dialogs.Dialog.DialogVerticalPosition.TOP;\n dialog.showConnector = true;\n dialog.origin = host;\n });\n it('places the Dialog hit area correctly', async () => {\n host.addEventListener('click', () => dialog.setDialogVisible(true));\n dialog.addEventListener('clickoutsidedialog', () => dialog.setDialogVisible(false));\n\n container.appendChild(host);\n container.appendChild(dialog);\n Helpers.renderElementIntoDOM(container);\n await coordinator.done();\n\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n\n const hostBounds = host.getBoundingClientRect();\n const hitAreaBounds = dialog.getHitArea();\n\n // Make sure the hit area contains the host fully.\n assert.isAtMost(hitAreaBounds.top, hostBounds.top);\n assert.isAtLeast(hitAreaBounds.bottom, hostBounds.top + hostBounds.height);\n\n assert.isAtMost(hitAreaBounds.left, hostBounds.left);\n assert.isAtLeast(hitAreaBounds.right, hostBounds.left + hostBounds.width);\n });\n it('sets the automatic horizontal alignment correctly', async () => {\n // Create the container for the dialog and its origin (host).\n // This container will be set as the dialog's \"window\".\n // With the host in the left border of the window, the Dialog\n // should deploy from left to right (left horizontal alignment).\n container.style.display = 'block';\n host.style.position = 'relative';\n host.style.left = '0';\n\n const content = document.createElement('div');\n content.classList.add('dialog-content');\n content.style.padding = '0 1em';\n content.innerHTML = 'Hi';\n\n dialog.horizontalAlignment = Dialogs.Dialog.DialogHorizontalAlignment.AUTO;\n dialog.showConnector = true;\n dialog.origin = host;\n\n // Set the dialog's \"window\" to be the container element we just created.\n dialog.windowBoundsService = new DialogExampleWindowBoundsServiceFactory(container);\n\n host.addEventListener('click', () => dialog.setDialogVisible(true));\n dialog.addEventListener('clickoutsidedialog', () => dialog.setDialogVisible(false));\n\n dialog.appendChild(content);\n container.appendChild(host);\n container.appendChild(dialog);\n Helpers.renderElementIntoDOM(container);\n await coordinator.done();\n\n // Open the dialog and check its position.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n\n // Test the dialog is deployed left to right, since this way there is more space.\n assert.strictEqual(dialog.bestHorizontalAlignment, Dialogs.Dialog.DialogHorizontalAlignment.LEFT);\n\n // Close the dialog\n Helpers.dispatchKeyDownEvent(dialog, {key: Platform.KeyboardUtilities.ESCAPE_KEY, bubbles: true, composed: true});\n await coordinator.done();\n\n // With the host in the right border of the window, the Dialog\n // should deploy from right to left (left horizontal alignment).\n host.style.position = 'relative';\n host.style.left = '450px';\n await coordinator.done();\n\n // Open the dialog and check its position.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n\n // Test the dialog is deployed right to left.\n assert.strictEqual(dialog.bestHorizontalAlignment, Dialogs.Dialog.DialogHorizontalAlignment.RIGHT);\n });\n\n it('sets the automatic vertical position correctly when it fits on top', async () => {\n // Create the container for the dialog and its origin (host), aligning\n // items to the bottom of the container. This container will be set as the\n // dialog's \"window\".\n // By default the dialog is placed at the bottom of its origin, but doing\n // so means it wouldn't fit in its window. Because if shown on top would\n // fit in its window it should be automatically positioned there.\n container.style.width = '150px';\n container.style.height = '300px';\n container.style.display = 'flex';\n container.style.alignItems = 'end';\n container.style.justifyContent = 'center';\n\n // The dialogs content dimensions exceed the viewport's\n const content = document.createElement('div');\n content.classList.add('dialog-content');\n content.style.padding = '0 1em';\n content.innerHTML = 'Hello, World
    I am
    a Dialog!';\n\n dialog.position = Dialogs.Dialog.DialogVerticalPosition.AUTO;\n dialog.showConnector = true;\n dialog.origin = host;\n\n // Set the dialog's \"window\" to be the container element we just created.\n dialog.windowBoundsService = new DialogExampleWindowBoundsServiceFactory(container);\n\n host.addEventListener('click', () => dialog.setDialogVisible(true));\n dialog.addEventListener('clickoutsidedialog', () => dialog.setDialogVisible(false));\n\n dialog.appendChild(content);\n container.appendChild(host);\n container.appendChild(dialog);\n Helpers.renderElementIntoDOM(container);\n await coordinator.done();\n\n // Open the dialog and check its position.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n\n // Test the capped dimensions\n assert.strictEqual(dialog.bestVerticalPosition, Dialogs.Dialog.DialogVerticalPosition.TOP);\n });\n\n it('sets the automatic vertical position correctly when it does not fit on top', async () => {\n // Create the container for the dialog and its origin (host), aligning\n // items to the bottom of the container. This container will be set as the\n // dialog's \"window\".\n // Because the dialog's full height cannot be fully fit at the\n // bottom or at the top it is positioned at the bottom and the\n // overflow made visible by scrolling.\n container.style.width = '150px';\n container.style.height = '80px';\n container.style.display = 'flex';\n container.style.alignItems = 'end';\n container.style.justifyContent = 'center';\n\n // The dialogs content dimensions exceed the viewport's\n const content = document.createElement('div');\n content.classList.add('dialog-content');\n content.style.padding = '0 1em';\n content.innerHTML = 'Hello, World
    I am
    a Dialog!';\n\n dialog.position = Dialogs.Dialog.DialogVerticalPosition.AUTO;\n dialog.showConnector = true;\n dialog.origin = host;\n\n // Set the dialog's \"window\" to be the container element we just created.\n dialog.windowBoundsService = new DialogExampleWindowBoundsServiceFactory(container);\n\n host.addEventListener('click', () => dialog.setDialogVisible(true));\n dialog.addEventListener('clickoutsidedialog', () => dialog.setDialogVisible(false));\n\n dialog.appendChild(content);\n container.appendChild(host);\n container.appendChild(dialog);\n Helpers.renderElementIntoDOM(container);\n await coordinator.done();\n\n // Open the dialog and check its position.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n\n // Test the capped dimensions\n assert.strictEqual(dialog.bestVerticalPosition, Dialogs.Dialog.DialogVerticalPosition.BOTTOM);\n });\n // Fails on bots https://crbug.com/1441801.\n it.skip(\n '[crbug.com/1441801]: sets the max width and height correctly when the dialog\\'s content dimensions exceed the viewport and the dialog is displayed as a modal',\n async () => {\n const devtoolsDialog = new Dialogs.Dialog.Dialog();\n const WINDOW_WIDTH = 500;\n // This container will be set as the dialog's \"window\", or the representation\n // of DevTools bounding element.\n container.style.width = `${WINDOW_WIDTH}px`;\n container.style.height = `${WINDOW_WIDTH}px`;\n const host = document.createElement('div');\n host.textContent = 'Hover me';\n host.style.width = '100px';\n\n const content = document.createElement('div');\n content.classList.add('dialog-content');\n content.style.width = '600px';\n content.style.height = '600px';\n content.innerHTML = 'Hello, World
    I am
    a Dialog!';\n\n devtoolsDialog.origin = Dialogs.Dialog.MODAL;\n\n // Set the dialog's \"window\" to be the container element we just created.\n devtoolsDialog.windowBoundsService = new DialogExampleWindowBoundsServiceFactory(container);\n\n host.addEventListener('click', () => devtoolsDialog.setDialogVisible(true));\n devtoolsDialog.addEventListener('clickoutsidedialog', () => devtoolsDialog.setDialogVisible(false));\n\n container.appendChild(host);\n container.appendChild(devtoolsDialog);\n Helpers.renderElementIntoDOM(container);\n await coordinator.done();\n devtoolsDialog.appendChild(content);\n\n // Open the dialog and check its position.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n const dialog = devtoolsDialog.shadowRoot?.querySelector('dialog');\n if (!dialog) {\n assert.fail('Dialog not found');\n return;\n }\n assert.strictEqual(\n dialog.clientWidth,\n WINDOW_WIDTH - Dialogs.Dialog.DIALOG_PADDING_FROM_WINDOW + 2 * Dialogs.Dialog.DIALOG_SIDE_PADDING);\n assert.strictEqual(\n dialog.clientHeight,\n WINDOW_WIDTH - Dialogs.Dialog.DIALOG_PADDING_FROM_WINDOW + 2 * Dialogs.Dialog.DIALOG_VERTICAL_PADDING);\n });\n describe('with an anchor and possible overflow', () => {\n const CONTAINER_WIDTH = 500;\n const HOST_OFFSET = 100;\n const HOST_HEIGHT = 100;\n const devtoolsDialog = new Dialogs.Dialog.Dialog();\n let host: HTMLElement;\n let container: HTMLElement;\n beforeEach(async () => {\n // This container will be set as the dialog's \"window\", or the representation\n // of DevTools bounding element.\n container = document.createElement('div');\n container.style.width = `${CONTAINER_WIDTH}px`;\n container.style.height = `${CONTAINER_WIDTH}px`;\n container.style.position = 'fixed';\n container.style.top = '0';\n container.style.left = '0';\n\n host = document.createElement('div');\n host.textContent = 'Click me';\n host.style.width = `${HOST_HEIGHT}px`;\n host.style.height = `${HOST_HEIGHT}px`;\n host.style.position = 'absolute';\n host.style.top = `${HOST_OFFSET}px`;\n host.style.left = `${HOST_OFFSET}px`;\n\n // The dialogs content dimensions exceed the container's\n const content = document.createElement('div');\n content.classList.add('dialog-content');\n content.style.width = '600px';\n content.style.height = '600px';\n content.innerHTML = 'Hello, World
    I am
    a Dialog!';\n\n devtoolsDialog.origin = host;\n devtoolsDialog.horizontalAlignment = Dialogs.Dialog.DialogHorizontalAlignment.CENTER;\n\n // Set the dialog's \"window\" to be the container element we just created.\n devtoolsDialog.windowBoundsService = new DialogExampleWindowBoundsServiceFactory(container);\n\n host.addEventListener('click', () => devtoolsDialog.setDialogVisible(true));\n devtoolsDialog.addEventListener('clickoutsidedialog', () => devtoolsDialog.setDialogVisible(false));\n\n container.appendChild(host);\n container.appendChild(devtoolsDialog);\n Helpers.renderElementIntoDOM(container);\n await coordinator.done();\n devtoolsDialog.appendChild(content);\n });\n it('sets the max width and height correctly when the dialog\\'s content dimensions exceed the viewport and the dialog is anchored to the left',\n async () => {\n devtoolsDialog.horizontalAlignment = Dialogs.Dialog.DialogHorizontalAlignment.LEFT;\n // Open the dialog and check its position.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n const dialog = devtoolsDialog.shadowRoot?.querySelector('dialog');\n if (!dialog) {\n assert.fail('Dialog not found');\n return;\n }\n // Test the capped dimensions\n const {left: dialogLeft, width: dialogWidth} = dialog.getBoundingClientRect();\n const dialogLeftBorderLimitPosition = dialogWidth + dialogLeft + Dialogs.Dialog.DIALOG_PADDING_FROM_WINDOW -\n 2 * Dialogs.Dialog.DIALOG_SIDE_PADDING;\n assert.strictEqual(dialogLeftBorderLimitPosition, CONTAINER_WIDTH);\n assert.strictEqual(\n dialog.clientHeight,\n CONTAINER_WIDTH - Dialogs.Dialog.CONNECTOR_HEIGHT - HOST_HEIGHT - HOST_OFFSET +\n 2 * Dialogs.Dialog.DIALOG_VERTICAL_PADDING);\n });\n it('sets the max width and height correctly when the dialog\\'s content dimensions exceed the viewport and the dialog is anchored to the right',\n async () => {\n devtoolsDialog.horizontalAlignment = Dialogs.Dialog.DialogHorizontalAlignment.RIGHT;\n await coordinator.done();\n // Open the dialog and check its position.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n const dialog = devtoolsDialog.shadowRoot?.querySelector('dialog');\n if (!dialog) {\n assert.fail('Dialog not found');\n return;\n }\n // Test the capped dimensions\n const dialogRight = host.getBoundingClientRect().right;\n const containerLeft = container.getBoundingClientRect().left;\n assert.strictEqual(\n dialog.clientWidth,\n (dialogRight - containerLeft) - Dialogs.Dialog.DIALOG_PADDING_FROM_WINDOW +\n 2 * Dialogs.Dialog.DIALOG_SIDE_PADDING);\n });\n it('sets the dialog\\'s horizontal position correctly to prevent overlap with DevTools when alinged to the left.',\n async () => {\n devtoolsDialog.horizontalAlignment = Dialogs.Dialog.DialogHorizontalAlignment.LEFT;\n host.style.left = '-10px';\n\n await coordinator.done();\n // Open the dialog and check its position.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n const dialog = devtoolsDialog.shadowRoot?.querySelector('dialog');\n if (!dialog) {\n assert.fail('Dialog not found');\n return;\n }\n // Test the capped dimensions\n const dialogLeft = dialog.getBoundingClientRect().left;\n const containerLeft = container.getBoundingClientRect().left;\n assert.isAtLeast(dialogLeft, containerLeft);\n });\n it('sets the dialog\\'s horizontal position correctly to prevent overlap with DevTools when alinged to the right.',\n async () => {\n devtoolsDialog.horizontalAlignment = Dialogs.Dialog.DialogHorizontalAlignment.RIGHT;\n const containerWidth = container.clientWidth;\n host.style.left = `${containerWidth + 10}px`;\n\n await coordinator.done();\n // Open the dialog and check its position.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n const dialog = devtoolsDialog.shadowRoot?.querySelector('dialog');\n if (!dialog) {\n assert.fail('Dialog not found');\n return;\n }\n // Test the capped dimensions\n const dialogRight = dialog.getBoundingClientRect().right;\n const dialogRightEdgePosition =\n dialogRight - 2 * Dialogs.Dialog.DIALOG_SIDE_PADDING - Dialogs.Dialog.DIALOG_PADDING_FROM_WINDOW / 2;\n assert.isAtMost(dialogRightEdgePosition, containerWidth);\n });\n it('sets the dialog\\'s horizontal position correctly to prevent overlapping with DevTools on the right when alinged to the center.',\n async () => {\n const containerWidth = container.clientWidth;\n host.style.left = `${containerWidth + 260}px`;\n\n await coordinator.done();\n // Open the dialog and check its position.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n const dialog = devtoolsDialog.shadowRoot?.querySelector('dialog');\n if (!dialog) {\n assert.fail('Dialog not found');\n return;\n }\n // Test the capped dimensions\n const dialogRight = dialog.getBoundingClientRect().right;\n const dialogRightEdgePosition =\n dialogRight - 2 * Dialogs.Dialog.DIALOG_SIDE_PADDING - Dialogs.Dialog.DIALOG_PADDING_FROM_WINDOW / 2;\n\n assert.isAtMost(dialogRightEdgePosition, containerWidth);\n });\n it('sets the dialog\\'s horizontal position correctly to prevent overlapping with DevTools on the left when alinged to the center.',\n async () => {\n host.style.left = '-260px';\n\n await coordinator.done();\n // Open the dialog and check its position.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n const dialog = devtoolsDialog.shadowRoot?.querySelector('dialog');\n if (!dialog) {\n assert.fail('Dialog not found');\n return;\n }\n // Test the capped dimensions\n const containerLeft = container.getBoundingClientRect().left;\n const dialogLeft = dialog.getBoundingClientRect().left;\n\n assert.isAtLeast(dialogLeft, containerLeft);\n });\n });\n\n it('updates the dialog client rect automatically when its dimensions change', async function() {\n host.addEventListener('click', () => dialog.setDialogVisible(true));\n const dialogContent = document.createElement('div');\n dialogContent.style.display = 'block';\n dialogContent.style.minWidth = '10px';\n dialogContent.style.minHeight = '10px';\n dialogContent.style.fontSize = '10px';\n dialogContent.innerText = 'Hello';\n\n dialog.append(dialogContent);\n container.appendChild(host);\n container.appendChild(dialog);\n Helpers.renderElementIntoDOM(container);\n await coordinator.done();\n\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n\n const initialWidth = dialog.getDialogBounds().width;\n const initialHeight = dialog.getDialogBounds().height;\n\n // Increase the font size to increase the dialog's dimensions\n dialogContent.style.fontSize = '200px';\n\n // Wait for the resize handling to take effect.\n await new Promise(res => setTimeout(res, 200));\n\n const finalWidth = dialog.getDialogBounds().width;\n const finalHeight = dialog.getDialogBounds().height;\n\n assert.isAbove(finalWidth, initialWidth);\n assert.isAbove(finalHeight, initialHeight);\n });\n });\n\n describe('closing the dialog with the ESC key', () => {\n let devtoolsDialog: Dialogs.Dialog.Dialog;\n beforeEach(async () => {\n devtoolsDialog = new Dialogs.Dialog.Dialog();\n const container = document.createElement('div');\n\n const host = document.createElement('div');\n\n const content = document.createElement('div');\n content.innerHTML = 'Hello, World
    I am
    a Dialog!';\n\n devtoolsDialog.origin = host;\n\n host.addEventListener('click', () => devtoolsDialog.setDialogVisible(true));\n devtoolsDialog.addEventListener('clickoutsidedialog', () => devtoolsDialog.setDialogVisible(false));\n\n container.appendChild(host);\n container.appendChild(devtoolsDialog);\n Helpers.renderElementIntoDOM(container);\n await coordinator.done();\n devtoolsDialog.appendChild(content);\n\n // Open the dialog.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n });\n\n it('closes the dialog by default when the ESC key is pressed', async () => {\n let dialog = devtoolsDialog.shadowRoot?.querySelector('dialog[open]');\n if (!dialog) {\n assert.fail('Dialog not found');\n return;\n }\n\n Helpers.dispatchKeyDownEvent(dialog, {key: Platform.KeyboardUtilities.ESCAPE_KEY, bubbles: true, composed: true});\n await coordinator.done();\n dialog = devtoolsDialog.shadowRoot?.querySelector('dialog[open]');\n if (dialog) {\n assert.fail('Dialog did not close');\n return;\n }\n });\n\n it('closes the dialog by default when the ESC key is pressed from document.body', async () => {\n let dialog = devtoolsDialog.shadowRoot?.querySelector('dialog[open]');\n if (!dialog) {\n assert.fail('Dialog not found');\n return;\n }\n Helpers.dispatchKeyDownEvent(\n document.body, {key: Platform.KeyboardUtilities.ESCAPE_KEY, bubbles: true, composed: true});\n await coordinator.done();\n dialog = devtoolsDialog.shadowRoot?.querySelector('dialog[open]');\n if (dialog) {\n assert.fail('Dialog did not close');\n return;\n }\n });\n\n it('closes the dialog by default when the ESC key is pressed anywhere within the devtools bounding element',\n async () => {\n let dialog = devtoolsDialog.shadowRoot?.querySelector('dialog[open]');\n if (!dialog) {\n assert.fail('Dialog not found');\n return;\n }\n\n const boundingElement = devtoolsDialog.windowBoundsService.getDevToolsBoundingElement();\n Helpers.dispatchKeyDownEvent(\n boundingElement, {key: Platform.KeyboardUtilities.ESCAPE_KEY, bubbles: true, composed: true});\n await coordinator.done();\n dialog = devtoolsDialog.shadowRoot?.querySelector('dialog[open]');\n if (dialog) {\n assert.fail('Dialog did not close');\n return;\n }\n });\n\n it('does not close the dialog when the ESC key is pressed if the closeOnESC prop is set to false', async () => {\n let dialog = devtoolsDialog.shadowRoot?.querySelector('dialog[open]');\n devtoolsDialog.closeOnESC = false;\n if (!dialog) {\n assert.fail('Dialog not found');\n return;\n }\n\n Helpers.dispatchKeyDownEvent(dialog, {key: Platform.KeyboardUtilities.ESCAPE_KEY});\n await coordinator.done();\n dialog = devtoolsDialog.shadowRoot?.querySelector('dialog[open]');\n if (!dialog) {\n assert.fail('Dialog was closed');\n return;\n }\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"Dialog.test.js","sourceRoot":"","sources":["../../../../../../../front_end/ui/components/dialogs/Dialog.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Platform from '../../../core/platform/platform.js';\nimport type * as WindowBoundsService from '../../../services/window_bounds/window_bounds.js';\nimport * as Helpers from '../../../testing/DOMHelpers.js'; // eslint-disable-line rulesdir/es_modules_import\nimport * as Coordinator from '../render_coordinator/render_coordinator.js';\n\nimport * as Dialogs from './dialogs.js';\n\nconst coordinator = Coordinator.RenderCoordinator.RenderCoordinator.instance();\nclass DialogExampleWindowBoundsServiceFactory implements WindowBoundsService.WindowBoundsService.WindowBoundsService {\n constructor(private boundingElement: HTMLElement) {\n }\n getDevToolsBoundingElement(): HTMLElement {\n return this.boundingElement;\n }\n}\n\ndescribe('Dialog', () => {\n describe('positioning', () => {\n let dialog: Dialogs.Dialog.Dialog;\n let container: HTMLDivElement;\n let host: HTMLDivElement;\n beforeEach(() => {\n dialog = new Dialogs.Dialog.Dialog();\n container = document.createElement('div');\n container.style.width = '500px';\n container.style.height = '500px';\n container.style.display = 'flex';\n container.style.alignItems = 'center';\n container.style.justifyContent = 'center';\n\n host = document.createElement('div');\n host.textContent = 'Hover me';\n host.style.width = '100px';\n host.style.height = '100px';\n\n dialog.position = Dialogs.Dialog.DialogVerticalPosition.TOP;\n dialog.showConnector = true;\n dialog.origin = host;\n });\n it('places the Dialog hit area correctly', async () => {\n host.addEventListener('click', () => dialog.setDialogVisible(true));\n dialog.addEventListener('clickoutsidedialog', () => dialog.setDialogVisible(false));\n\n container.appendChild(host);\n container.appendChild(dialog);\n Helpers.renderElementIntoDOM(container);\n await coordinator.done();\n\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n\n const hostBounds = host.getBoundingClientRect();\n const hitAreaBounds = dialog.getHitArea();\n\n // Make sure the hit area contains the host fully.\n assert.isAtMost(hitAreaBounds.top, hostBounds.top);\n assert.isAtLeast(hitAreaBounds.bottom, hostBounds.top + hostBounds.height);\n\n assert.isAtMost(hitAreaBounds.left, hostBounds.left);\n assert.isAtLeast(hitAreaBounds.right, hostBounds.left + hostBounds.width);\n });\n it('sets the automatic horizontal alignment correctly', async () => {\n // Create the container for the dialog and its origin (host).\n // This container will be set as the dialog's \"window\".\n // With the host in the left border of the window, the Dialog\n // should deploy from left to right (left horizontal alignment).\n container.style.display = 'block';\n host.style.position = 'relative';\n host.style.left = '0';\n\n const content = document.createElement('div');\n content.classList.add('dialog-content');\n content.style.padding = '0 1em';\n content.innerHTML = 'Hi';\n\n dialog.horizontalAlignment = Dialogs.Dialog.DialogHorizontalAlignment.AUTO;\n dialog.showConnector = true;\n dialog.origin = host;\n\n // Set the dialog's \"window\" to be the container element we just created.\n dialog.windowBoundsService = new DialogExampleWindowBoundsServiceFactory(container);\n\n host.addEventListener('click', () => dialog.setDialogVisible(true));\n dialog.addEventListener('clickoutsidedialog', () => dialog.setDialogVisible(false));\n\n dialog.appendChild(content);\n container.appendChild(host);\n container.appendChild(dialog);\n Helpers.renderElementIntoDOM(container);\n await coordinator.done();\n\n // Open the dialog and check its position.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n\n // Test the dialog is deployed left to right, since this way there is more space.\n assert.strictEqual(dialog.bestHorizontalAlignment, Dialogs.Dialog.DialogHorizontalAlignment.LEFT);\n\n // Close the dialog\n Helpers.dispatchKeyDownEvent(dialog, {key: Platform.KeyboardUtilities.ESCAPE_KEY, bubbles: true, composed: true});\n await coordinator.done();\n\n // With the host in the right border of the window, the Dialog\n // should deploy from right to left (left horizontal alignment).\n host.style.position = 'relative';\n host.style.left = '450px';\n await coordinator.done();\n\n // Open the dialog and check its position.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n\n // Test the dialog is deployed right to left.\n assert.strictEqual(dialog.bestHorizontalAlignment, Dialogs.Dialog.DialogHorizontalAlignment.RIGHT);\n });\n\n it('sets the automatic vertical position correctly when it fits on top', async () => {\n // Create the container for the dialog and its origin (host), aligning\n // items to the bottom of the container. This container will be set as the\n // dialog's \"window\".\n // By default the dialog is placed at the bottom of its origin, but doing\n // so means it wouldn't fit in its window. Because if shown on top would\n // fit in its window it should be automatically positioned there.\n container.style.width = '150px';\n container.style.height = '300px';\n container.style.display = 'flex';\n container.style.alignItems = 'end';\n container.style.justifyContent = 'center';\n\n // The dialogs content dimensions exceed the viewport's\n const content = document.createElement('div');\n content.classList.add('dialog-content');\n content.style.padding = '0 1em';\n content.innerHTML = 'Hello, World
    I am
    a Dialog!';\n\n dialog.position = Dialogs.Dialog.DialogVerticalPosition.AUTO;\n dialog.showConnector = true;\n dialog.origin = host;\n\n // Set the dialog's \"window\" to be the container element we just created.\n dialog.windowBoundsService = new DialogExampleWindowBoundsServiceFactory(container);\n\n host.addEventListener('click', () => dialog.setDialogVisible(true));\n dialog.addEventListener('clickoutsidedialog', () => dialog.setDialogVisible(false));\n\n dialog.appendChild(content);\n container.appendChild(host);\n container.appendChild(dialog);\n Helpers.renderElementIntoDOM(container);\n await coordinator.done();\n\n // Open the dialog and check its position.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n\n // Test the capped dimensions\n assert.strictEqual(dialog.bestVerticalPosition, Dialogs.Dialog.DialogVerticalPosition.TOP);\n });\n\n it('sets the automatic vertical position correctly when it does not fit on top', async () => {\n // Create the container for the dialog and its origin (host), aligning\n // items to the bottom of the container. This container will be set as the\n // dialog's \"window\".\n // Because the dialog's full height cannot be fully fit at the\n // bottom or at the top it is positioned at the bottom and the\n // overflow made visible by scrolling.\n container.style.width = '150px';\n container.style.height = '80px';\n container.style.display = 'flex';\n container.style.alignItems = 'end';\n container.style.justifyContent = 'center';\n\n // The dialogs content dimensions exceed the viewport's\n const content = document.createElement('div');\n content.classList.add('dialog-content');\n content.style.padding = '0 1em';\n content.innerHTML = 'Hello, World
    I am
    a Dialog!';\n\n dialog.position = Dialogs.Dialog.DialogVerticalPosition.AUTO;\n dialog.showConnector = true;\n dialog.origin = host;\n\n // Set the dialog's \"window\" to be the container element we just created.\n dialog.windowBoundsService = new DialogExampleWindowBoundsServiceFactory(container);\n\n host.addEventListener('click', () => dialog.setDialogVisible(true));\n dialog.addEventListener('clickoutsidedialog', () => dialog.setDialogVisible(false));\n\n dialog.appendChild(content);\n container.appendChild(host);\n container.appendChild(dialog);\n Helpers.renderElementIntoDOM(container);\n await coordinator.done();\n\n // Open the dialog and check its position.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n\n // Test the capped dimensions\n assert.strictEqual(dialog.bestVerticalPosition, Dialogs.Dialog.DialogVerticalPosition.BOTTOM);\n });\n // Fails on bots https://crbug.com/1441801.\n it.skip(\n '[crbug.com/1441801]: sets the max width and height correctly when the dialog\\'s content dimensions exceed the viewport and the dialog is displayed as a modal',\n async () => {\n const devtoolsDialog = new Dialogs.Dialog.Dialog();\n const WINDOW_WIDTH = 500;\n // This container will be set as the dialog's \"window\", or the representation\n // of DevTools bounding element.\n container.style.width = `${WINDOW_WIDTH}px`;\n container.style.height = `${WINDOW_WIDTH}px`;\n const host = document.createElement('div');\n host.textContent = 'Hover me';\n host.style.width = '100px';\n\n const content = document.createElement('div');\n content.classList.add('dialog-content');\n content.style.width = '600px';\n content.style.height = '600px';\n content.innerHTML = 'Hello, World
    I am
    a Dialog!';\n\n devtoolsDialog.origin = Dialogs.Dialog.MODAL;\n\n // Set the dialog's \"window\" to be the container element we just created.\n devtoolsDialog.windowBoundsService = new DialogExampleWindowBoundsServiceFactory(container);\n\n host.addEventListener('click', () => devtoolsDialog.setDialogVisible(true));\n devtoolsDialog.addEventListener('clickoutsidedialog', () => devtoolsDialog.setDialogVisible(false));\n\n container.appendChild(host);\n container.appendChild(devtoolsDialog);\n Helpers.renderElementIntoDOM(container);\n await coordinator.done();\n devtoolsDialog.appendChild(content);\n\n // Open the dialog and check its position.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n const dialog = devtoolsDialog.shadowRoot?.querySelector('dialog');\n if (!dialog) {\n assert.fail('Dialog not found');\n return;\n }\n assert.strictEqual(\n dialog.clientWidth,\n WINDOW_WIDTH - Dialogs.Dialog.DIALOG_PADDING_FROM_WINDOW + 2 * Dialogs.Dialog.DIALOG_SIDE_PADDING);\n assert.strictEqual(\n dialog.clientHeight,\n WINDOW_WIDTH - Dialogs.Dialog.DIALOG_PADDING_FROM_WINDOW + 2 * Dialogs.Dialog.DIALOG_VERTICAL_PADDING);\n });\n describe('with an anchor and possible overflow', () => {\n const CONTAINER_WIDTH = 500;\n const HOST_OFFSET = 100;\n const HOST_HEIGHT = 100;\n const devtoolsDialog = new Dialogs.Dialog.Dialog();\n let host: HTMLElement;\n let container: HTMLElement;\n beforeEach(async () => {\n // This container will be set as the dialog's \"window\", or the representation\n // of DevTools bounding element.\n container = document.createElement('div');\n container.style.width = `${CONTAINER_WIDTH}px`;\n container.style.height = `${CONTAINER_WIDTH}px`;\n container.style.position = 'fixed';\n container.style.top = '0';\n container.style.left = '0';\n\n host = document.createElement('div');\n host.textContent = 'Click me';\n host.style.width = `${HOST_HEIGHT}px`;\n host.style.height = `${HOST_HEIGHT}px`;\n host.style.position = 'absolute';\n host.style.top = `${HOST_OFFSET}px`;\n host.style.left = `${HOST_OFFSET}px`;\n\n // The dialogs content dimensions exceed the container's\n const content = document.createElement('div');\n content.classList.add('dialog-content');\n content.style.width = '600px';\n content.style.height = '600px';\n content.innerHTML = 'Hello, World
    I am
    a Dialog!';\n\n devtoolsDialog.origin = host;\n devtoolsDialog.horizontalAlignment = Dialogs.Dialog.DialogHorizontalAlignment.CENTER;\n\n // Set the dialog's \"window\" to be the container element we just created.\n devtoolsDialog.windowBoundsService = new DialogExampleWindowBoundsServiceFactory(container);\n\n host.addEventListener('click', () => devtoolsDialog.setDialogVisible(true));\n devtoolsDialog.addEventListener('clickoutsidedialog', () => devtoolsDialog.setDialogVisible(false));\n\n container.appendChild(host);\n container.appendChild(devtoolsDialog);\n Helpers.renderElementIntoDOM(container);\n await coordinator.done();\n devtoolsDialog.appendChild(content);\n });\n it('sets the max width and height correctly when the dialog\\'s content dimensions exceed the viewport and the dialog is anchored to the left',\n async () => {\n devtoolsDialog.horizontalAlignment = Dialogs.Dialog.DialogHorizontalAlignment.LEFT;\n // Open the dialog and check its position.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n const dialog = devtoolsDialog.shadowRoot?.querySelector('dialog');\n if (!dialog) {\n assert.fail('Dialog not found');\n return;\n }\n // Test the capped dimensions\n const {left: dialogLeft, width: dialogWidth} = dialog.getBoundingClientRect();\n const dialogLeftBorderLimitPosition = dialogWidth + dialogLeft + Dialogs.Dialog.DIALOG_PADDING_FROM_WINDOW -\n 2 * Dialogs.Dialog.DIALOG_SIDE_PADDING;\n assert.strictEqual(dialogLeftBorderLimitPosition, CONTAINER_WIDTH);\n assert.strictEqual(\n dialog.clientHeight,\n CONTAINER_WIDTH - Dialogs.Dialog.CONNECTOR_HEIGHT - HOST_HEIGHT - HOST_OFFSET +\n 2 * Dialogs.Dialog.DIALOG_VERTICAL_PADDING);\n });\n it('sets the max width and height correctly when the dialog\\'s content dimensions exceed the viewport and the dialog is anchored to the right',\n async () => {\n devtoolsDialog.horizontalAlignment = Dialogs.Dialog.DialogHorizontalAlignment.RIGHT;\n await coordinator.done();\n // Open the dialog and check its position.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n const dialog = devtoolsDialog.shadowRoot?.querySelector('dialog');\n if (!dialog) {\n assert.fail('Dialog not found');\n return;\n }\n // Test the capped dimensions\n const dialogRight = host.getBoundingClientRect().right;\n const containerLeft = container.getBoundingClientRect().left;\n assert.strictEqual(\n dialog.clientWidth,\n (dialogRight - containerLeft) - Dialogs.Dialog.DIALOG_PADDING_FROM_WINDOW +\n 2 * Dialogs.Dialog.DIALOG_SIDE_PADDING);\n });\n it('sets the dialog\\'s horizontal position correctly to prevent overlap with DevTools when alinged to the left.',\n async () => {\n devtoolsDialog.horizontalAlignment = Dialogs.Dialog.DialogHorizontalAlignment.LEFT;\n host.style.left = '-10px';\n\n await coordinator.done();\n // Open the dialog and check its position.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n const dialog = devtoolsDialog.shadowRoot?.querySelector('dialog');\n if (!dialog) {\n assert.fail('Dialog not found');\n return;\n }\n // Test the capped dimensions\n const dialogLeft = dialog.getBoundingClientRect().left;\n const containerLeft = container.getBoundingClientRect().left;\n assert.isAtLeast(dialogLeft, containerLeft);\n });\n it('sets the dialog\\'s horizontal position correctly to prevent overlap with DevTools when alinged to the right.',\n async () => {\n devtoolsDialog.horizontalAlignment = Dialogs.Dialog.DialogHorizontalAlignment.RIGHT;\n const containerWidth = container.clientWidth;\n host.style.left = `${containerWidth + 10}px`;\n\n await coordinator.done();\n // Open the dialog and check its position.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n const dialog = devtoolsDialog.shadowRoot?.querySelector('dialog');\n if (!dialog) {\n assert.fail('Dialog not found');\n return;\n }\n // Test the capped dimensions\n const dialogRight = dialog.getBoundingClientRect().right;\n const dialogRightEdgePosition =\n dialogRight - 2 * Dialogs.Dialog.DIALOG_SIDE_PADDING - Dialogs.Dialog.DIALOG_PADDING_FROM_WINDOW / 2;\n assert.isAtMost(dialogRightEdgePosition, containerWidth);\n });\n it('sets the dialog\\'s horizontal position correctly to prevent overlapping with DevTools on the right when alinged to the center.',\n async () => {\n const containerWidth = container.clientWidth;\n host.style.left = `${containerWidth + 260}px`;\n\n await coordinator.done();\n // Open the dialog and check its position.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n const dialog = devtoolsDialog.shadowRoot?.querySelector('dialog');\n if (!dialog) {\n assert.fail('Dialog not found');\n return;\n }\n // Test the capped dimensions\n const dialogRight = dialog.getBoundingClientRect().right;\n const dialogRightEdgePosition =\n dialogRight - 2 * Dialogs.Dialog.DIALOG_SIDE_PADDING - Dialogs.Dialog.DIALOG_PADDING_FROM_WINDOW / 2;\n\n assert.isAtMost(dialogRightEdgePosition, containerWidth);\n });\n it('sets the dialog\\'s horizontal position correctly to prevent overlapping with DevTools on the left when alinged to the center.',\n async () => {\n host.style.left = '-260px';\n\n await coordinator.done();\n // Open the dialog and check its position.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n const dialog = devtoolsDialog.shadowRoot?.querySelector('dialog');\n if (!dialog) {\n assert.fail('Dialog not found');\n return;\n }\n // Test the capped dimensions\n const containerLeft = container.getBoundingClientRect().left;\n const dialogLeft = dialog.getBoundingClientRect().left;\n\n assert.isAtLeast(dialogLeft, containerLeft);\n });\n });\n\n it('updates the dialog client rect automatically when its dimensions change', async function() {\n host.addEventListener('click', () => dialog.setDialogVisible(true));\n const dialogContent = document.createElement('div');\n dialogContent.style.display = 'block';\n dialogContent.style.minWidth = '10px';\n dialogContent.style.minHeight = '10px';\n dialogContent.style.fontSize = '10px';\n dialogContent.innerText = 'Hello';\n\n dialog.append(dialogContent);\n container.appendChild(host);\n container.appendChild(dialog);\n Helpers.renderElementIntoDOM(container);\n await coordinator.done();\n\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n\n const initialWidth = dialog.getDialogBounds().width;\n const initialHeight = dialog.getDialogBounds().height;\n\n // Increase the font size to increase the dialog's dimensions\n dialogContent.style.fontSize = '200px';\n\n // Wait for the resize handling to take effect.\n await new Promise(res => setTimeout(res, 200));\n\n const finalWidth = dialog.getDialogBounds().width;\n const finalHeight = dialog.getDialogBounds().height;\n\n assert.isAbove(finalWidth, initialWidth);\n assert.isAbove(finalHeight, initialHeight);\n });\n });\n\n describe('closing the dialog with the ESC key', () => {\n let devtoolsDialog: Dialogs.Dialog.Dialog;\n beforeEach(async () => {\n devtoolsDialog = new Dialogs.Dialog.Dialog();\n const container = document.createElement('div');\n\n const host = document.createElement('div');\n\n const content = document.createElement('div');\n content.innerHTML = 'Hello, World
    I am
    a Dialog!';\n\n devtoolsDialog.origin = host;\n\n host.addEventListener('click', () => devtoolsDialog.setDialogVisible(true));\n devtoolsDialog.addEventListener('clickoutsidedialog', () => devtoolsDialog.setDialogVisible(false));\n\n container.appendChild(host);\n container.appendChild(devtoolsDialog);\n Helpers.renderElementIntoDOM(container);\n await coordinator.done();\n devtoolsDialog.appendChild(content);\n\n // Open the dialog.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n });\n\n it('closes the dialog by default when the ESC key is pressed', async () => {\n let dialog = devtoolsDialog.shadowRoot?.querySelector('dialog[open]');\n if (!dialog) {\n assert.fail('Dialog not found');\n return;\n }\n\n Helpers.dispatchKeyDownEvent(dialog, {key: Platform.KeyboardUtilities.ESCAPE_KEY, bubbles: true, composed: true});\n await coordinator.done();\n dialog = devtoolsDialog.shadowRoot?.querySelector('dialog[open]');\n if (dialog) {\n assert.fail('Dialog did not close');\n return;\n }\n });\n\n it('closes the dialog by default when the ESC key is pressed from document.body', async () => {\n let dialog = devtoolsDialog.shadowRoot?.querySelector('dialog[open]');\n if (!dialog) {\n assert.fail('Dialog not found');\n return;\n }\n Helpers.dispatchKeyDownEvent(\n document.body, {key: Platform.KeyboardUtilities.ESCAPE_KEY, bubbles: true, composed: true});\n await coordinator.done();\n dialog = devtoolsDialog.shadowRoot?.querySelector('dialog[open]');\n if (dialog) {\n assert.fail('Dialog did not close');\n return;\n }\n });\n\n it('closes the dialog by default when the ESC key is pressed anywhere within the devtools bounding element',\n async () => {\n let dialog = devtoolsDialog.shadowRoot?.querySelector('dialog[open]');\n if (!dialog) {\n assert.fail('Dialog not found');\n return;\n }\n\n const boundingElement = devtoolsDialog.windowBoundsService.getDevToolsBoundingElement();\n Helpers.dispatchKeyDownEvent(\n boundingElement, {key: Platform.KeyboardUtilities.ESCAPE_KEY, bubbles: true, composed: true});\n await coordinator.done();\n dialog = devtoolsDialog.shadowRoot?.querySelector('dialog[open]');\n if (dialog) {\n assert.fail('Dialog did not close');\n return;\n }\n });\n\n it('does not close the dialog when the ESC key is pressed if the closeOnESC prop is set to false', async () => {\n let dialog = devtoolsDialog.shadowRoot?.querySelector('dialog[open]');\n devtoolsDialog.closeOnESC = false;\n if (!dialog) {\n assert.fail('Dialog not found');\n return;\n }\n\n Helpers.dispatchKeyDownEvent(dialog, {key: Platform.KeyboardUtilities.ESCAPE_KEY});\n await coordinator.done();\n dialog = devtoolsDialog.shadowRoot?.querySelector('dialog[open]');\n if (!dialog) {\n assert.fail('Dialog was closed');\n return;\n }\n });\n });\n});\n\ndescribe('closing the dialog with click', () => {\n let devtoolsDialog: Dialogs.Dialog.Dialog;\n beforeEach(async () => {\n devtoolsDialog = new Dialogs.Dialog.Dialog();\n const container = document.createElement('div');\n\n const host = document.createElement('div');\n\n const content = document.createElement('div');\n content.innerHTML = 'Hello, World
    I am
    a Dialog!';\n\n devtoolsDialog.origin = Dialogs.Dialog.MODAL;\n\n host.addEventListener('click', () => devtoolsDialog.setDialogVisible(true));\n devtoolsDialog.addEventListener('clickoutsidedialog', () => devtoolsDialog.setDialogVisible(false));\n\n container.appendChild(host);\n container.appendChild(devtoolsDialog);\n Helpers.renderElementIntoDOM(container);\n await coordinator.done();\n devtoolsDialog.appendChild(content);\n\n // Open the dialog.\n Helpers.dispatchClickEvent(host);\n await coordinator.done();\n });\n\n it('Only closes the dialog if the click falls outside its content', async () => {\n let dialog = devtoolsDialog.shadowRoot?.querySelector('dialog[open]');\n if (!dialog) {\n assert.fail('Dialog not found');\n return;\n }\n const {x, width, bottom} = dialog.getBoundingClientRect();\n\n // Click just inside must not close the dialog.\n Helpers.dispatchClickEvent(dialog, {clientX: x + width / 2, clientY: bottom - 1});\n await coordinator.done();\n dialog = devtoolsDialog.shadowRoot?.querySelector('dialog[open]');\n if (!dialog) {\n assert.fail('Dialog closed when it should not');\n return;\n }\n Helpers.dispatchClickEvent(dialog, {clientX: x + width / 2, clientY: bottom + 1});\n await coordinator.done();\n\n // Click just outside must close the dialog.\n dialog = devtoolsDialog.shadowRoot?.querySelector('dialog[open]');\n if (dialog) {\n assert.fail('Dialog did not close');\n return;\n }\n });\n});\n"]} \ No newline at end of file diff --git a/public/ui/components/docs/breadcrumbs_perf/initial-breadcrumb-perf.js b/public/ui/components/docs/breadcrumbs_perf/initial-breadcrumb-perf.js index c3638a831..aac73903a 100644 --- a/public/ui/components/docs/breadcrumbs_perf/initial-breadcrumb-perf.js +++ b/public/ui/components/docs/breadcrumbs_perf/initial-breadcrumb-perf.js @@ -1,14 +1,14 @@ // 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 * as TraceEngine from '../../../../../front_end/models/trace/trace.js'; +import * as Trace from '../../../../../front_end/models/trace/trace.js'; import * as TimelineComponents from '../../../../../front_end/panels/timeline/components/components.js'; const breadcrumbsUI = new TimelineComponents.BreadcrumbsUI.BreadcrumbsUI(); document.getElementById('container')?.appendChild(breadcrumbsUI); const traceWindow = { - min: TraceEngine.Types.Timing.MicroSeconds(3), - max: TraceEngine.Types.Timing.MicroSeconds(9), - range: TraceEngine.Types.Timing.MicroSeconds(6), + min: Trace.Types.Timing.MicroSeconds(3), + max: Trace.Types.Timing.MicroSeconds(9), + range: Trace.Types.Timing.MicroSeconds(6), }; const breadcrumb = { window: traceWindow, diff --git a/public/ui/components/docs/breadcrumbs_perf/initial-breadcrumb-perf.js.map b/public/ui/components/docs/breadcrumbs_perf/initial-breadcrumb-perf.js.map index 72b935d4b..3b70230e8 100644 --- a/public/ui/components/docs/breadcrumbs_perf/initial-breadcrumb-perf.js.map +++ b/public/ui/components/docs/breadcrumbs_perf/initial-breadcrumb-perf.js.map @@ -1 +1 @@ -{"version":3,"file":"initial-breadcrumb-perf.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/components/docs/breadcrumbs_perf/initial-breadcrumb-perf.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,WAAW,MAAM,gDAAgD,CAAC;AAC9E,OAAO,KAAK,kBAAkB,MAAM,mEAAmE,CAAC;AAExG,MAAM,aAAa,GAAG,IAAI,kBAAkB,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC;AAC3E,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC;AAEjE,MAAM,WAAW,GAAqD;IACpE,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;IAC7C,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;IAC7C,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;CAChD,CAAC;AAEF,MAAM,UAAU,GAAsC;IACpD,MAAM,EAAE,WAAW;IACnB,KAAK,EAAE,IAAI;CACZ,CAAC;AAEF,aAAa,CAAC,IAAI,GAAG;IACnB,iBAAiB,EAAE,UAAU;IAC7B,gBAAgB,EAAE,UAAU;CAC7B,CAAC","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceEngine from '../../../../../front_end/models/trace/trace.js';\nimport * as TimelineComponents from '../../../../../front_end/panels/timeline/components/components.js';\n\nconst breadcrumbsUI = new TimelineComponents.BreadcrumbsUI.BreadcrumbsUI();\ndocument.getElementById('container')?.appendChild(breadcrumbsUI);\n\nconst traceWindow: TraceEngine.Types.Timing.TraceWindowMicroSeconds = {\n min: TraceEngine.Types.Timing.MicroSeconds(3),\n max: TraceEngine.Types.Timing.MicroSeconds(9),\n range: TraceEngine.Types.Timing.MicroSeconds(6),\n};\n\nconst breadcrumb: TraceEngine.Types.File.Breadcrumb = {\n window: traceWindow,\n child: null,\n};\n\nbreadcrumbsUI.data = {\n initialBreadcrumb: breadcrumb,\n activeBreadcrumb: breadcrumb,\n};\n"]} \ No newline at end of file +{"version":3,"file":"initial-breadcrumb-perf.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/components/docs/breadcrumbs_perf/initial-breadcrumb-perf.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,KAAK,MAAM,gDAAgD,CAAC;AACxE,OAAO,KAAK,kBAAkB,MAAM,mEAAmE,CAAC;AAExG,MAAM,aAAa,GAAG,IAAI,kBAAkB,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC;AAC3E,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC;AAEjE,MAAM,WAAW,GAA+C;IAC9D,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;IACvC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;IACvC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;CAC1C,CAAC;AAEF,MAAM,UAAU,GAAgC;IAC9C,MAAM,EAAE,WAAW;IACnB,KAAK,EAAE,IAAI;CACZ,CAAC;AAEF,aAAa,CAAC,IAAI,GAAG;IACnB,iBAAiB,EAAE,UAAU;IAC7B,gBAAgB,EAAE,UAAU;CAC7B,CAAC","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../../../../front_end/models/trace/trace.js';\nimport * as TimelineComponents from '../../../../../front_end/panels/timeline/components/components.js';\n\nconst breadcrumbsUI = new TimelineComponents.BreadcrumbsUI.BreadcrumbsUI();\ndocument.getElementById('container')?.appendChild(breadcrumbsUI);\n\nconst traceWindow: Trace.Types.Timing.TraceWindowMicroSeconds = {\n min: Trace.Types.Timing.MicroSeconds(3),\n max: Trace.Types.Timing.MicroSeconds(9),\n range: Trace.Types.Timing.MicroSeconds(6),\n};\n\nconst breadcrumb: Trace.Types.File.Breadcrumb = {\n window: traceWindow,\n child: null,\n};\n\nbreadcrumbsUI.data = {\n initialBreadcrumb: breadcrumb,\n activeBreadcrumb: breadcrumb,\n};\n"]} \ No newline at end of file diff --git a/public/ui/components/docs/breadcrumbs_perf/nested-breadcrumbs-perf.js b/public/ui/components/docs/breadcrumbs_perf/nested-breadcrumbs-perf.js index a5fc347d5..4fb324bb1 100644 --- a/public/ui/components/docs/breadcrumbs_perf/nested-breadcrumbs-perf.js +++ b/public/ui/components/docs/breadcrumbs_perf/nested-breadcrumbs-perf.js @@ -1,19 +1,19 @@ // 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 * as TraceEngine from '../../../../../front_end/models/trace/trace.js'; +import * as Trace from '../../../../../front_end/models/trace/trace.js'; import * as TimelineComponents from '../../../../../front_end/panels/timeline/components/components.js'; const breadcrumbsUI = new TimelineComponents.BreadcrumbsUI.BreadcrumbsUI(); document.getElementById('container')?.appendChild(breadcrumbsUI); const traceWindow2 = { - min: TraceEngine.Types.Timing.MicroSeconds(4), - max: TraceEngine.Types.Timing.MicroSeconds(8), - range: TraceEngine.Types.Timing.MicroSeconds(4), + min: Trace.Types.Timing.MicroSeconds(4), + max: Trace.Types.Timing.MicroSeconds(8), + range: Trace.Types.Timing.MicroSeconds(4), }; const traceWindow = { - min: TraceEngine.Types.Timing.MicroSeconds(3), - max: TraceEngine.Types.Timing.MicroSeconds(9), - range: TraceEngine.Types.Timing.MicroSeconds(6), + min: Trace.Types.Timing.MicroSeconds(3), + max: Trace.Types.Timing.MicroSeconds(9), + range: Trace.Types.Timing.MicroSeconds(6), }; const breadcrumb2 = { window: traceWindow2, diff --git a/public/ui/components/docs/breadcrumbs_perf/nested-breadcrumbs-perf.js.map b/public/ui/components/docs/breadcrumbs_perf/nested-breadcrumbs-perf.js.map index e4c970dd6..0964a786b 100644 --- a/public/ui/components/docs/breadcrumbs_perf/nested-breadcrumbs-perf.js.map +++ b/public/ui/components/docs/breadcrumbs_perf/nested-breadcrumbs-perf.js.map @@ -1 +1 @@ -{"version":3,"file":"nested-breadcrumbs-perf.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/components/docs/breadcrumbs_perf/nested-breadcrumbs-perf.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,WAAW,MAAM,gDAAgD,CAAC;AAC9E,OAAO,KAAK,kBAAkB,MAAM,mEAAmE,CAAC;AAExG,MAAM,aAAa,GAAG,IAAI,kBAAkB,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC;AAC3E,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC;AAEjE,MAAM,YAAY,GAAqD;IACrE,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;IAC7C,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;IAC7C,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;CAChD,CAAC;AAEF,MAAM,WAAW,GAAqD;IACpE,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;IAC7C,GAAG,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;IAC7C,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;CAChD,CAAC;AAEF,MAAM,WAAW,GAAsC;IACrD,MAAM,EAAE,YAAY;IACpB,KAAK,EAAE,IAAI;CACZ,CAAC;AAEF,MAAM,UAAU,GAAsC;IACpD,MAAM,EAAE,WAAW;IACnB,KAAK,EAAE,WAAW;CACnB,CAAC;AAEF,aAAa,CAAC,IAAI,GAAG;IACnB,iBAAiB,EAAE,UAAU;IAC7B,gBAAgB,EAAE,UAAU;CAC7B,CAAC","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceEngine from '../../../../../front_end/models/trace/trace.js';\nimport * as TimelineComponents from '../../../../../front_end/panels/timeline/components/components.js';\n\nconst breadcrumbsUI = new TimelineComponents.BreadcrumbsUI.BreadcrumbsUI();\ndocument.getElementById('container')?.appendChild(breadcrumbsUI);\n\nconst traceWindow2: TraceEngine.Types.Timing.TraceWindowMicroSeconds = {\n min: TraceEngine.Types.Timing.MicroSeconds(4),\n max: TraceEngine.Types.Timing.MicroSeconds(8),\n range: TraceEngine.Types.Timing.MicroSeconds(4),\n};\n\nconst traceWindow: TraceEngine.Types.Timing.TraceWindowMicroSeconds = {\n min: TraceEngine.Types.Timing.MicroSeconds(3),\n max: TraceEngine.Types.Timing.MicroSeconds(9),\n range: TraceEngine.Types.Timing.MicroSeconds(6),\n};\n\nconst breadcrumb2: TraceEngine.Types.File.Breadcrumb = {\n window: traceWindow2,\n child: null,\n};\n\nconst breadcrumb: TraceEngine.Types.File.Breadcrumb = {\n window: traceWindow,\n child: breadcrumb2,\n};\n\nbreadcrumbsUI.data = {\n initialBreadcrumb: breadcrumb,\n activeBreadcrumb: breadcrumb,\n};\n"]} \ No newline at end of file +{"version":3,"file":"nested-breadcrumbs-perf.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/components/docs/breadcrumbs_perf/nested-breadcrumbs-perf.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,KAAK,MAAM,gDAAgD,CAAC;AACxE,OAAO,KAAK,kBAAkB,MAAM,mEAAmE,CAAC;AAExG,MAAM,aAAa,GAAG,IAAI,kBAAkB,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC;AAC3E,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC;AAEjE,MAAM,YAAY,GAA+C;IAC/D,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;IACvC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;IACvC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;CAC1C,CAAC;AAEF,MAAM,WAAW,GAA+C;IAC9D,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;IACvC,GAAG,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;IACvC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC;CAC1C,CAAC;AAEF,MAAM,WAAW,GAAgC;IAC/C,MAAM,EAAE,YAAY;IACpB,KAAK,EAAE,IAAI;CACZ,CAAC;AAEF,MAAM,UAAU,GAAgC;IAC9C,MAAM,EAAE,WAAW;IACnB,KAAK,EAAE,WAAW;CACnB,CAAC;AAEF,aAAa,CAAC,IAAI,GAAG;IACnB,iBAAiB,EAAE,UAAU;IAC7B,gBAAgB,EAAE,UAAU;CAC7B,CAAC","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../../../../front_end/models/trace/trace.js';\nimport * as TimelineComponents from '../../../../../front_end/panels/timeline/components/components.js';\n\nconst breadcrumbsUI = new TimelineComponents.BreadcrumbsUI.BreadcrumbsUI();\ndocument.getElementById('container')?.appendChild(breadcrumbsUI);\n\nconst traceWindow2: Trace.Types.Timing.TraceWindowMicroSeconds = {\n min: Trace.Types.Timing.MicroSeconds(4),\n max: Trace.Types.Timing.MicroSeconds(8),\n range: Trace.Types.Timing.MicroSeconds(4),\n};\n\nconst traceWindow: Trace.Types.Timing.TraceWindowMicroSeconds = {\n min: Trace.Types.Timing.MicroSeconds(3),\n max: Trace.Types.Timing.MicroSeconds(9),\n range: Trace.Types.Timing.MicroSeconds(6),\n};\n\nconst breadcrumb2: Trace.Types.File.Breadcrumb = {\n window: traceWindow2,\n child: null,\n};\n\nconst breadcrumb: Trace.Types.File.Breadcrumb = {\n window: traceWindow,\n child: breadcrumb2,\n};\n\nbreadcrumbsUI.data = {\n initialBreadcrumb: breadcrumb,\n activeBreadcrumb: breadcrumb,\n};\n"]} \ No newline at end of file diff --git a/public/ui/components/docs/freestyler/basic.js b/public/ui/components/docs/freestyler/basic.js index d8597b7a3..588aa0e7a 100644 --- a/public/ui/components/docs/freestyler/basic.js +++ b/public/ui/components/docs/freestyler/basic.js @@ -16,7 +16,6 @@ const messages = [ { entity: "model" /* Freestyler.ChatMessageEntity.MODEL */, suggestingFix: true, - aborted: false, steps: [ { isLoading: false, @@ -37,6 +36,7 @@ const component = new Freestyler.FreestylerChatUi({ onAcceptConsentClick: noop, onCancelClick: noop, onFixThisIssueClick: noop, + onSelectedNetworkRequestClick: noop, inspectElementToggled: false, state: "chat-view" /* Freestyler.State.CHAT_VIEW */, aidaAvailability: "available" /* Host.AidaClient.AidaAccessPreconditions.AVAILABLE */, diff --git a/public/ui/components/docs/freestyler/basic.js.map b/public/ui/components/docs/freestyler/basic.js.map index 2cf7249ef..ea52ef4e5 100644 --- a/public/ui/components/docs/freestyler/basic.js.map +++ b/public/ui/components/docs/freestyler/basic.js.map @@ -1 +1 @@ -{"version":3,"file":"basic.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/components/docs/freestyler/basic.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,IAAI,MAAM,+BAA+B,CAAC;AAEtD,OAAO,KAAK,UAAU,MAAM,6CAA6C,CAAC;AAC1E,OAAO,KAAK,eAAe,MAAM,2CAA2C,CAAC;AAC7E,OAAO,KAAK,gBAAgB,MAAM,0BAA0B,CAAC;AAE7D,MAAM,gBAAgB,CAAC,oBAAoB,CAAC,KAAK,EAAE,CAAC;AACpD,MAAM,eAAe,CAAC,oBAAoB,EAAE,CAAC;AAE7C,MAAM,IAAI,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;AAEtB,MAAM,QAAQ,GAA6B;IACzC;QACE,MAAM,gDAAmC;QACzC,IAAI,EAAE,qDAAqD;KAC5D;IACD;QACE,MAAM,kDAAoC;QAC1C,aAAa,EAAE,IAAI;QACnB,OAAO,EAAE,KAAK;QACd,KAAK,EAAE;YACL;gBACE,SAAS,EAAE,KAAK;gBAChB,KAAK,EAAE,yBAAyB;gBAChC,OAAO,EACH,uHAAuH;gBAC3H,IAAI,EACA,qIAAqI;gBACzI,MAAM,EAAE,yDAAyD;aAClE;SACF;QACD,MAAM,EACF,82BAA82B;QACl3B,KAAK,EAAE,CAAC,mBAAmB;KAE5B;CACF,CAAC;AAEF,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,gBAAgB,CAAC;IAChD,YAAY,EAAE,IAAI;IAClB,qBAAqB,EAAE,IAAI;IAC3B,gBAAgB,EAAE,IAAI;IACtB,oBAAoB,EAAE,IAAI;IAC1B,aAAa,EAAE,IAAI;IACnB,mBAAmB,EAAE,IAAI;IACzB,qBAAqB,EAAE,KAAK;IAC5B,KAAK,8CAA4B;IACjC,gBAAgB,qEAAmD;IACnE,QAAQ;IACR,eAAe,EAAE,EAAqC;IACtD,sBAAsB,EAAE,EAAkD;IAC1E,SAAS,oDAAiC;IAC1C,SAAS,EAAE,KAAK;IAChB,mBAAmB,EAAE,KAAK;IAC1B,QAAQ,EAAE,EAAE;CACb,CAAC,CAAC;AAEH,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC","sourcesContent":["// Copyright 2021 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Host from '../../../../core/host/host.js';\nimport type * as SDK from '../../../../core/sdk/sdk.js';\nimport * as Freestyler from '../../../../panels/freestyler/freestyler.js';\nimport * as FrontendHelpers from '../../../../testing/EnvironmentHelpers.js';\nimport * as ComponentHelpers from '../../helpers/helpers.js';\n\nawait ComponentHelpers.ComponentServerSetup.setup();\nawait FrontendHelpers.initializeGlobalVars();\n\nconst noop = () => {};\n\nconst messages: Freestyler.ChatMessage[] = [\n {\n entity: Freestyler.ChatMessageEntity.USER,\n text: 'Explain the line wrapping behavior of this element.',\n },\n {\n entity: Freestyler.ChatMessageEntity.MODEL,\n suggestingFix: true,\n aborted: false,\n steps: [\n {\n isLoading: false,\n title: 'Checking element styles',\n thought:\n 'I need to check the element\\'s `white-space` and `overflow-wrap` properties to understand its line wrapping behavior.',\n code:\n 'const data = {\\n whiteSpace: window.getComputedStyle($0).whiteSpace,\\n overflowWrap: window.getComputedStyle($0).overflowWrap\\n};',\n output: '{\"whiteSpace\":\"break-spaces\",\"overflowWrap\":\"anywhere\"}',\n },\n ],\n answer:\n '# Explanation\\n\\n## Before\\n\\nA little bit text here\\n\\n## Next\\n\\nThe element\\'s line wrapping behavior is determined by the following CSS properties:\\n\\n* **`white-space: break-spaces;`**: This property tells the browser to preserve spaces and newlines within the text and to break lines at these points, as well as at normal word boundaries.\\n\\n* **`overflow-wrap: anywhere;`**: This property allows the browser to break lines within words if necessary to prevent overflow. This is useful for long words or URLs that might otherwise extend beyond the container\\'s width.\\n\\nHere\\'s an example of how these properties work together:\\n\\n\\n`````\\ncss\\n.element {\\n white-space: break-spaces;\\n overflow-wrap: anywhere;\\n}\\n`````\\n\\n\\nWith these properties, the text within the element will wrap at spaces, newlines, and within words if necessary to fit within the container.',\n rpcId: -5412527540357623608,\n\n },\n];\n\nconst component = new Freestyler.FreestylerChatUi({\n onTextSubmit: noop,\n onInspectElementClick: noop,\n onFeedbackSubmit: noop,\n onAcceptConsentClick: noop,\n onCancelClick: noop,\n onFixThisIssueClick: noop,\n inspectElementToggled: false,\n state: Freestyler.State.CHAT_VIEW,\n aidaAvailability: Host.AidaClient.AidaAccessPreconditions.AVAILABLE,\n messages,\n selectedElement: {} as unknown as SDK.DOMModel.DOMNode,\n selectedNetworkRequest: {} as unknown as SDK.NetworkRequest.NetworkRequest,\n agentType: Freestyler.AgentType.FREESTYLER,\n isLoading: false,\n canShowFeedbackForm: false,\n userInfo: {},\n});\n\ndocument.getElementById('container')?.appendChild(component);\n"]} \ No newline at end of file +{"version":3,"file":"basic.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/components/docs/freestyler/basic.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,IAAI,MAAM,+BAA+B,CAAC;AAEtD,OAAO,KAAK,UAAU,MAAM,6CAA6C,CAAC;AAC1E,OAAO,KAAK,eAAe,MAAM,2CAA2C,CAAC;AAC7E,OAAO,KAAK,gBAAgB,MAAM,0BAA0B,CAAC;AAE7D,MAAM,gBAAgB,CAAC,oBAAoB,CAAC,KAAK,EAAE,CAAC;AACpD,MAAM,eAAe,CAAC,oBAAoB,EAAE,CAAC;AAE7C,MAAM,IAAI,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;AAEtB,MAAM,QAAQ,GAA6B;IACzC;QACE,MAAM,gDAAmC;QACzC,IAAI,EAAE,qDAAqD;KAC5D;IACD;QACE,MAAM,kDAAoC;QAC1C,aAAa,EAAE,IAAI;QACnB,KAAK,EAAE;YACL;gBACE,SAAS,EAAE,KAAK;gBAChB,KAAK,EAAE,yBAAyB;gBAChC,OAAO,EACH,uHAAuH;gBAC3H,IAAI,EACA,qIAAqI;gBACzI,MAAM,EAAE,yDAAyD;aAClE;SACF;QACD,MAAM,EACF,82BAA82B;QACl3B,KAAK,EAAE,CAAC,mBAAmB;KAE5B;CACF,CAAC;AAEF,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,gBAAgB,CAAC;IAChD,YAAY,EAAE,IAAI;IAClB,qBAAqB,EAAE,IAAI;IAC3B,gBAAgB,EAAE,IAAI;IACtB,oBAAoB,EAAE,IAAI;IAC1B,aAAa,EAAE,IAAI;IACnB,mBAAmB,EAAE,IAAI;IACzB,6BAA6B,EAAE,IAAI;IACnC,qBAAqB,EAAE,KAAK;IAC5B,KAAK,8CAA4B;IACjC,gBAAgB,qEAAmD;IACnE,QAAQ;IACR,eAAe,EAAE,EAAqC;IACtD,sBAAsB,EAAE,EAAkD;IAC1E,SAAS,oDAAiC;IAC1C,SAAS,EAAE,KAAK;IAChB,mBAAmB,EAAE,KAAK;IAC1B,QAAQ,EAAE,EAAE;CACb,CAAC,CAAC;AAEH,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC","sourcesContent":["// Copyright 2021 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Host from '../../../../core/host/host.js';\nimport type * as SDK from '../../../../core/sdk/sdk.js';\nimport * as Freestyler from '../../../../panels/freestyler/freestyler.js';\nimport * as FrontendHelpers from '../../../../testing/EnvironmentHelpers.js';\nimport * as ComponentHelpers from '../../helpers/helpers.js';\n\nawait ComponentHelpers.ComponentServerSetup.setup();\nawait FrontendHelpers.initializeGlobalVars();\n\nconst noop = () => {};\n\nconst messages: Freestyler.ChatMessage[] = [\n {\n entity: Freestyler.ChatMessageEntity.USER,\n text: 'Explain the line wrapping behavior of this element.',\n },\n {\n entity: Freestyler.ChatMessageEntity.MODEL,\n suggestingFix: true,\n steps: [\n {\n isLoading: false,\n title: 'Checking element styles',\n thought:\n 'I need to check the element\\'s `white-space` and `overflow-wrap` properties to understand its line wrapping behavior.',\n code:\n 'const data = {\\n whiteSpace: window.getComputedStyle($0).whiteSpace,\\n overflowWrap: window.getComputedStyle($0).overflowWrap\\n};',\n output: '{\"whiteSpace\":\"break-spaces\",\"overflowWrap\":\"anywhere\"}',\n },\n ],\n answer:\n '# Explanation\\n\\n## Before\\n\\nA little bit text here\\n\\n## Next\\n\\nThe element\\'s line wrapping behavior is determined by the following CSS properties:\\n\\n* **`white-space: break-spaces;`**: This property tells the browser to preserve spaces and newlines within the text and to break lines at these points, as well as at normal word boundaries.\\n\\n* **`overflow-wrap: anywhere;`**: This property allows the browser to break lines within words if necessary to prevent overflow. This is useful for long words or URLs that might otherwise extend beyond the container\\'s width.\\n\\nHere\\'s an example of how these properties work together:\\n\\n\\n`````\\ncss\\n.element {\\n white-space: break-spaces;\\n overflow-wrap: anywhere;\\n}\\n`````\\n\\n\\nWith these properties, the text within the element will wrap at spaces, newlines, and within words if necessary to fit within the container.',\n rpcId: -5412527540357623608,\n\n },\n];\n\nconst component = new Freestyler.FreestylerChatUi({\n onTextSubmit: noop,\n onInspectElementClick: noop,\n onFeedbackSubmit: noop,\n onAcceptConsentClick: noop,\n onCancelClick: noop,\n onFixThisIssueClick: noop,\n onSelectedNetworkRequestClick: noop,\n inspectElementToggled: false,\n state: Freestyler.State.CHAT_VIEW,\n aidaAvailability: Host.AidaClient.AidaAccessPreconditions.AVAILABLE,\n messages,\n selectedElement: {} as unknown as SDK.DOMModel.DOMNode,\n selectedNetworkRequest: {} as unknown as SDK.NetworkRequest.NetworkRequest,\n agentType: Freestyler.AgentType.FREESTYLER,\n isLoading: false,\n canShowFeedbackForm: false,\n userInfo: {},\n});\n\ndocument.getElementById('container')?.appendChild(component);\n"]} \ No newline at end of file diff --git a/public/ui/components/docs/freestyler/empty_state.js b/public/ui/components/docs/freestyler/empty_state.js index 856c38448..8842ded70 100644 --- a/public/ui/components/docs/freestyler/empty_state.js +++ b/public/ui/components/docs/freestyler/empty_state.js @@ -15,6 +15,7 @@ const component = new Freestyler.FreestylerChatUi({ onAcceptConsentClick: noop, onCancelClick: noop, onFixThisIssueClick: noop, + onSelectedNetworkRequestClick: noop, inspectElementToggled: false, state: "chat-view" /* Freestyler.State.CHAT_VIEW */, aidaAvailability: "available" /* Host.AidaClient.AidaAccessPreconditions.AVAILABLE */, diff --git a/public/ui/components/docs/freestyler/empty_state.js.map b/public/ui/components/docs/freestyler/empty_state.js.map index d1f4983fc..8cb0a12f4 100644 --- a/public/ui/components/docs/freestyler/empty_state.js.map +++ b/public/ui/components/docs/freestyler/empty_state.js.map @@ -1 +1 @@ -{"version":3,"file":"empty_state.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/components/docs/freestyler/empty_state.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,IAAI,MAAM,+BAA+B,CAAC;AAEtD,OAAO,KAAK,UAAU,MAAM,6CAA6C,CAAC;AAC1E,OAAO,KAAK,eAAe,MAAM,2CAA2C,CAAC;AAC7E,OAAO,KAAK,gBAAgB,MAAM,0BAA0B,CAAC;AAE7D,MAAM,gBAAgB,CAAC,oBAAoB,CAAC,KAAK,EAAE,CAAC;AACpD,MAAM,eAAe,CAAC,oBAAoB,EAAE,CAAC;AAE7C,MAAM,IAAI,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;AAEtB,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,gBAAgB,CAAC;IAChD,YAAY,EAAE,IAAI;IAClB,qBAAqB,EAAE,IAAI;IAC3B,gBAAgB,EAAE,IAAI;IACtB,oBAAoB,EAAE,IAAI;IAC1B,aAAa,EAAE,IAAI;IACnB,mBAAmB,EAAE,IAAI;IACzB,qBAAqB,EAAE,KAAK;IAC5B,KAAK,8CAA4B;IACjC,gBAAgB,qEAAmD;IACnE,QAAQ,EAAE,EAAE;IACZ,eAAe,EAAE,EAAqC;IACtD,sBAAsB,EAAE,EAAkD;IAC1E,SAAS,oDAAiC;IAC1C,SAAS,EAAE,KAAK;IAChB,mBAAmB,EAAE,KAAK;IAC1B,QAAQ,EAAE,EAAE;CACb,CAAC,CAAC;AAEH,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC","sourcesContent":["// Copyright 2021 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Host from '../../../../core/host/host.js';\nimport type * as SDK from '../../../../core/sdk/sdk.js';\nimport * as Freestyler from '../../../../panels/freestyler/freestyler.js';\nimport * as FrontendHelpers from '../../../../testing/EnvironmentHelpers.js';\nimport * as ComponentHelpers from '../../helpers/helpers.js';\n\nawait ComponentHelpers.ComponentServerSetup.setup();\nawait FrontendHelpers.initializeGlobalVars();\n\nconst noop = () => {};\n\nconst component = new Freestyler.FreestylerChatUi({\n onTextSubmit: noop,\n onInspectElementClick: noop,\n onFeedbackSubmit: noop,\n onAcceptConsentClick: noop,\n onCancelClick: noop,\n onFixThisIssueClick: noop,\n inspectElementToggled: false,\n state: Freestyler.State.CHAT_VIEW,\n aidaAvailability: Host.AidaClient.AidaAccessPreconditions.AVAILABLE,\n messages: [],\n selectedElement: {} as unknown as SDK.DOMModel.DOMNode,\n selectedNetworkRequest: {} as unknown as SDK.NetworkRequest.NetworkRequest,\n agentType: Freestyler.AgentType.FREESTYLER,\n isLoading: false,\n canShowFeedbackForm: false,\n userInfo: {},\n});\n\ndocument.getElementById('container')?.appendChild(component);\n"]} \ No newline at end of file +{"version":3,"file":"empty_state.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/components/docs/freestyler/empty_state.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,IAAI,MAAM,+BAA+B,CAAC;AAEtD,OAAO,KAAK,UAAU,MAAM,6CAA6C,CAAC;AAC1E,OAAO,KAAK,eAAe,MAAM,2CAA2C,CAAC;AAC7E,OAAO,KAAK,gBAAgB,MAAM,0BAA0B,CAAC;AAE7D,MAAM,gBAAgB,CAAC,oBAAoB,CAAC,KAAK,EAAE,CAAC;AACpD,MAAM,eAAe,CAAC,oBAAoB,EAAE,CAAC;AAE7C,MAAM,IAAI,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;AAEtB,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,gBAAgB,CAAC;IAChD,YAAY,EAAE,IAAI;IAClB,qBAAqB,EAAE,IAAI;IAC3B,gBAAgB,EAAE,IAAI;IACtB,oBAAoB,EAAE,IAAI;IAC1B,aAAa,EAAE,IAAI;IACnB,mBAAmB,EAAE,IAAI;IACzB,6BAA6B,EAAE,IAAI;IACnC,qBAAqB,EAAE,KAAK;IAC5B,KAAK,8CAA4B;IACjC,gBAAgB,qEAAmD;IACnE,QAAQ,EAAE,EAAE;IACZ,eAAe,EAAE,EAAqC;IACtD,sBAAsB,EAAE,EAAkD;IAC1E,SAAS,oDAAiC;IAC1C,SAAS,EAAE,KAAK;IAChB,mBAAmB,EAAE,KAAK;IAC1B,QAAQ,EAAE,EAAE;CACb,CAAC,CAAC;AAEH,QAAQ,CAAC,cAAc,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC","sourcesContent":["// Copyright 2021 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Host from '../../../../core/host/host.js';\nimport type * as SDK from '../../../../core/sdk/sdk.js';\nimport * as Freestyler from '../../../../panels/freestyler/freestyler.js';\nimport * as FrontendHelpers from '../../../../testing/EnvironmentHelpers.js';\nimport * as ComponentHelpers from '../../helpers/helpers.js';\n\nawait ComponentHelpers.ComponentServerSetup.setup();\nawait FrontendHelpers.initializeGlobalVars();\n\nconst noop = () => {};\n\nconst component = new Freestyler.FreestylerChatUi({\n onTextSubmit: noop,\n onInspectElementClick: noop,\n onFeedbackSubmit: noop,\n onAcceptConsentClick: noop,\n onCancelClick: noop,\n onFixThisIssueClick: noop,\n onSelectedNetworkRequestClick: noop,\n inspectElementToggled: false,\n state: Freestyler.State.CHAT_VIEW,\n aidaAvailability: Host.AidaClient.AidaAccessPreconditions.AVAILABLE,\n messages: [],\n selectedElement: {} as unknown as SDK.DOMModel.DOMNode,\n selectedNetworkRequest: {} as unknown as SDK.NetworkRequest.NetworkRequest,\n agentType: Freestyler.AgentType.FREESTYLER,\n isLoading: false,\n canShowFeedbackForm: false,\n userInfo: {},\n});\n\ndocument.getElementById('container')?.appendChild(component);\n"]} \ No newline at end of file diff --git a/public/ui/components/docs/performance_panel/flamechart.js b/public/ui/components/docs/performance_panel/flamechart.js index ab43f905f..b2702690c 100644 --- a/public/ui/components/docs/performance_panel/flamechart.js +++ b/public/ui/components/docs/performance_panel/flamechart.js @@ -1,7 +1,7 @@ // 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 * as TraceEngine from '../../../../models/trace/trace.js'; +import * as Trace from '../../../../models/trace/trace.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'; @@ -73,7 +73,7 @@ function renderDecorationExample() { [ { type: "CANDY" /* PerfUI.FlameChart.FlameChartDecorationType.CANDY */, - startAtTime: TraceEngine.Types.Timing.MicroSeconds(25_000), + startAtTime: Trace.Types.Timing.MicroSeconds(25_000), }, { type: "WARNING_TRIANGLE" /* PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE */ }, ], @@ -85,13 +85,13 @@ function renderDecorationExample() { [ { type: "CANDY" /* PerfUI.FlameChart.FlameChartDecorationType.CANDY */, - startAtTime: TraceEngine.Types.Timing.MicroSeconds(15_000), + startAtTime: Trace.Types.Timing.MicroSeconds(15_000), }, ], [ { type: "CANDY" /* PerfUI.FlameChart.FlameChartDecorationType.CANDY */, - startAtTime: TraceEngine.Types.Timing.MicroSeconds(10_000), + startAtTime: Trace.Types.Timing.MicroSeconds(10_000), }, { type: "HIDDEN_DESCENDANTS_ARROW" /* PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW */ }, ], @@ -101,7 +101,7 @@ function renderDecorationExample() { [ { type: "CANDY" /* PerfUI.FlameChart.FlameChartDecorationType.CANDY */, - startAtTime: TraceEngine.Types.Timing.MicroSeconds(10_000), + startAtTime: Trace.Types.Timing.MicroSeconds(10_000), }, { type: "HIDDEN_DESCENDANTS_ARROW" /* PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW */ }, { type: "WARNING_TRIANGLE" /* PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE */ }, @@ -116,14 +116,14 @@ function renderDecorationExample() { [ { type: "CANDY" /* PerfUI.FlameChart.FlameChartDecorationType.CANDY */, - startAtTime: TraceEngine.Types.Timing.MicroSeconds(1_000), + startAtTime: Trace.Types.Timing.MicroSeconds(1_000), }, { type: "HIDDEN_DESCENDANTS_ARROW" /* PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW */ }, ], [ { type: "CANDY" /* PerfUI.FlameChart.FlameChartDecorationType.CANDY */, - startAtTime: TraceEngine.Types.Timing.MicroSeconds(1_000), + startAtTime: Trace.Types.Timing.MicroSeconds(1_000), }, { type: "HIDDEN_DESCENDANTS_ARROW" /* PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW */ }, { type: "WARNING_TRIANGLE" /* PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE */ }, @@ -132,8 +132,8 @@ function renderDecorationExample() { { type: "WARNING_TRIANGLE" /* PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE */, // This triangle should start 1/4 of hte event, and end at 3/4 of the event. - customStartTime: TraceEngine.Types.Timing.MicroSeconds(25_250), - customEndTime: TraceEngine.Types.Timing.MicroSeconds(25_750), + customStartTime: Trace.Types.Timing.MicroSeconds(25_250), + customEndTime: Trace.Types.Timing.MicroSeconds(25_750), }, ], ], diff --git a/public/ui/components/docs/performance_panel/flamechart.js.map b/public/ui/components/docs/performance_panel/flamechart.js.map index 0cc3779de..cff3a46a1 100644 --- a/public/ui/components/docs/performance_panel/flamechart.js.map +++ b/public/ui/components/docs/performance_panel/flamechart.js.map @@ -1 +1 @@ -{"version":3,"file":"flamechart.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/components/docs/performance_panel/flamechart.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Platform from '../../../../core/platform/platform.js';\nimport * as TraceEngine from '../../../../models/trace/trace.js';\nimport * as EnvironmentHelpers from '../../../../testing/EnvironmentHelpers.js';\nimport * as TraceHelpers from '../../../../testing/TraceHelpers.js';\nimport * as PerfUI from '../../../legacy/components/perf_ui/perf_ui.js';\nimport * as ComponentSetup from '../../helpers/helpers.js';\n\nawait EnvironmentHelpers.initializeGlobalVars();\nawait ComponentSetup.ComponentServerSetup.setup();\n\nconst defaultGroupStyle = {\n height: 17,\n padding: 4,\n collapsible: false,\n color: 'black',\n backgroundColor: 'grey',\n nestingLevel: 0,\n itemsHeight: 17,\n};\n\n/**\n * Render a basic flame chart with 3 events on the same level\n **/\nfunction renderBasicExample() {\n class FakeProviderWithBasicEvents extends TraceHelpers.FakeFlameChartProvider {\n override timelineData(): PerfUI.FlameChart.FlameChartTimelineData|null {\n return PerfUI.FlameChart.FlameChartTimelineData.create({\n entryLevels: [0, 0, 0, 1, 1, 1, 2, 2, 2],\n entryStartTimes: [5, 60, 80, 5, 60, 80, 5, 60, 80],\n entryTotalTimes: [50, 10, 10, 50, 10, 10, 50, 10, 10],\n groups: [\n {\n name: 'Test Group 0' as Platform.UIString.LocalizedString,\n startLevel: 0,\n style: {...defaultGroupStyle, collapsible: true},\n },\n {\n name: 'Test Group 1' as Platform.UIString.LocalizedString,\n startLevel: 1,\n style: {...defaultGroupStyle, collapsible: true, color: 'red', backgroundColor: 'green'},\n },\n {\n name: 'Test Group 2' as Platform.UIString.LocalizedString,\n startLevel: 2,\n style: {...defaultGroupStyle, collapsible: true, color: 'blue', backgroundColor: 'yellow'},\n },\n ],\n });\n }\n }\n\n const container = document.querySelector('div#basic');\n if (!container) {\n throw new Error('No container');\n }\n const delegate = new TraceHelpers.MockFlameChartDelegate();\n const dataProvider = new FakeProviderWithBasicEvents();\n const flameChart = new PerfUI.FlameChart.FlameChart(dataProvider, delegate);\n\n flameChart.markAsRoot();\n flameChart.setWindowTimes(0, 100);\n flameChart.show(container);\n flameChart.update();\n}\n\n/**\n * Render a flame chart with events with decorations.\n **/\nfunction renderDecorationExample() {\n class FakeProviderWithDecorations extends TraceHelpers.FakeFlameChartProvider {\n override timelineData(): PerfUI.FlameChart.FlameChartTimelineData|null {\n return PerfUI.FlameChart.FlameChartTimelineData.create({\n entryLevels: [0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2],\n entryStartTimes: [5, 55, 70, 5, 30, 55, 75, 5, 10, 15, 20, 25],\n entryTotalTimes: [45, 10, 20, 20, 20, 5, 15, 4, 4, 4, 4, 1],\n entryDecorations: [\n [\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,\n startAtTime: TraceEngine.Types.Timing.MicroSeconds(25_000),\n },\n {type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE},\n ],\n [{type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE}],\n [\n {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},\n {type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE},\n ],\n [\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,\n startAtTime: TraceEngine.Types.Timing.MicroSeconds(15_000),\n },\n ],\n [\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,\n startAtTime: TraceEngine.Types.Timing.MicroSeconds(10_000),\n },\n {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},\n ],\n [\n {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},\n ],\n [\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,\n startAtTime: TraceEngine.Types.Timing.MicroSeconds(10_000),\n },\n {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},\n {type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE},\n ],\n [\n {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},\n ],\n [\n {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},\n {type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE},\n ],\n [\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,\n startAtTime: TraceEngine.Types.Timing.MicroSeconds(1_000),\n },\n {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},\n ],\n [\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,\n startAtTime: TraceEngine.Types.Timing.MicroSeconds(1_000),\n },\n {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},\n {type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE},\n ],\n [\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE,\n // This triangle should start 1/4 of hte event, and end at 3/4 of the event.\n customStartTime: TraceEngine.Types.Timing.MicroSeconds(25_250),\n customEndTime: TraceEngine.Types.Timing.MicroSeconds(25_750),\n },\n ],\n ],\n groups: [{\n name: 'Testing Candy Stripe, warning triangles and hidden descendants arrow decorations' as\n Platform.UIString.LocalizedString,\n startLevel: 0,\n style: defaultGroupStyle,\n }],\n });\n }\n }\n\n const container = document.querySelector('div#decorations');\n if (!container) {\n throw new Error('No container');\n }\n const delegate = new TraceHelpers.MockFlameChartDelegate();\n const dataProvider = new FakeProviderWithDecorations();\n const flameChart = new PerfUI.FlameChart.FlameChart(dataProvider, delegate);\n\n flameChart.markAsRoot();\n flameChart.setWindowTimes(0, 100);\n flameChart.show(container);\n flameChart.update();\n}\n\n/**\n * Render a flame chart with nested track.\n **/\nfunction renderNestedExample() {\n class FakeProviderWithNestedGroup extends TraceHelpers.FakeFlameChartProvider {\n override timelineData(): PerfUI.FlameChart.FlameChartTimelineData|null {\n return PerfUI.FlameChart.FlameChartTimelineData.create({\n entryLevels: [0, 1, 2],\n entryStartTimes: [5, 5, 5],\n entryTotalTimes: [50, 50, 50],\n groups: [\n {\n name: 'Test Group 0' as Platform.UIString.LocalizedString,\n startLevel: 0,\n style: {...defaultGroupStyle, collapsible: true},\n },\n {\n name: 'Test Nested Group 1' as Platform.UIString.LocalizedString,\n startLevel: 0,\n style: {...defaultGroupStyle, collapsible: true, color: 'red', backgroundColor: 'green'},\n },\n {\n name: 'Test Group 2' as Platform.UIString.LocalizedString,\n startLevel: 2,\n style: {...defaultGroupStyle, collapsible: true, color: 'blue', backgroundColor: 'yellow'},\n },\n ],\n });\n }\n }\n\n const container = document.querySelector('div#nested');\n if (!container) {\n throw new Error('No container');\n }\n const delegate = new TraceHelpers.MockFlameChartDelegate();\n const dataProvider = new FakeProviderWithNestedGroup();\n const flameChart = new PerfUI.FlameChart.FlameChart(dataProvider, delegate);\n\n flameChart.markAsRoot();\n flameChart.setWindowTimes(0, 100);\n flameChart.show(container);\n flameChart.update();\n}\n\n/**\n * Render a flame chart with nested case and buttons to hide/unhide and reorder\n * tracks\n **/\nfunction renderTrackCustomizationExample() {\n class FakeProviderWithBasicEvents extends TraceHelpers.FakeFlameChartProvider {\n override timelineData(): PerfUI.FlameChart.FlameChartTimelineData|null {\n return PerfUI.FlameChart.FlameChartTimelineData.create({\n entryLevels: [0, 0, 1, 1, 2, 2, 3, 3],\n entryStartTimes: [5, 60, 5, 60, 5, 60],\n entryTotalTimes: [50, 10, 50, 10, 50, 10],\n groups: [\n {\n name: 'Test Group 0' as Platform.UIString.LocalizedString,\n startLevel: 0,\n expanded: true,\n style: {...defaultGroupStyle, collapsible: true},\n },\n {\n name: 'Test Group 1' as Platform.UIString.LocalizedString,\n startLevel: 1,\n expanded: true,\n style: {...defaultGroupStyle, collapsible: true, color: 'red', backgroundColor: 'green'},\n },\n {\n name: 'Test Group 2' as Platform.UIString.LocalizedString,\n startLevel: 2,\n expanded: true,\n style: {...defaultGroupStyle, collapsible: true, color: 'blue', backgroundColor: 'yellow'},\n },\n {\n name: 'Test Group 3' as Platform.UIString.LocalizedString,\n startLevel: 2,\n expanded: true,\n style: {...defaultGroupStyle, nestingLevel: 1},\n },\n ],\n });\n }\n }\n\n const container = document.querySelector('div#track-customization');\n if (!container) {\n throw new Error('No container');\n }\n const delegate = new TraceHelpers.MockFlameChartDelegate();\n const dataProvider = new FakeProviderWithBasicEvents();\n const flameChart = new PerfUI.FlameChart.FlameChart(dataProvider, delegate);\n\n flameChart.markAsRoot();\n flameChart.setWindowTimes(0, 100);\n flameChart.show(container);\n flameChart.update();\n\n const indexInput = document.querySelector('#indexOfTrack') as HTMLInputElement;\n const buttonHide = document.querySelector('#hide');\n buttonHide?.addEventListener('click', () => {\n const index = Number(indexInput.value);\n flameChart.hideGroup(index);\n });\n const buttonUnhide = document.querySelector('#unhide');\n buttonUnhide?.addEventListener('click', () => {\n const index = Number(indexInput.value);\n flameChart.showGroup(index);\n });\n\n const buttonForMoveUp = document.querySelector('#testForMoveUp');\n buttonForMoveUp?.addEventListener('click', () => {\n const index = Number(indexInput.value);\n flameChart.moveGroupUp(index);\n });\n const buttonForMoveDown = document.querySelector('#testForMoveDown');\n buttonForMoveDown?.addEventListener('click', () => {\n const index = Number(indexInput.value);\n flameChart.moveGroupDown(index);\n });\n}\n\n/**\n * Render a flame chart with event initiators of different sizes.\n * Some initiator and initiated events are hidden.\n **/\nfunction renderInitiatorsExample() {\n class FakeProviderWithVariousTasksForInitiators extends TraceHelpers.FakeFlameChartProvider {\n override timelineData(): PerfUI.FlameChart.FlameChartTimelineData|null {\n return PerfUI.FlameChart.FlameChartTimelineData.create({\n entryLevels: [0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 3],\n entryStartTimes: [5, 5, 5, 15, 15, 15, 40, 40, 40, 55.4, 55.4, 55.4, 80, 80, 80, 17],\n entryTotalTimes: [6, 6, 6, 5, 5, 20, 15, 15, 15, 2, 2, 2, 10, 10, 10, 10],\n entryDecorations: [\n [],\n [],\n [\n {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},\n ],\n [],\n [],\n [],\n [],\n [],\n [\n {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},\n ],\n [],\n [],\n [\n {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},\n ],\n [\n {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},\n ],\n ],\n initiatorsData: [\n {initiatorIndex: 2, eventIndex: 3, isInitiatorHidden: true},\n {initiatorIndex: 1, eventIndex: 13},\n {initiatorIndex: 3, eventIndex: 6},\n {initiatorIndex: 3, eventIndex: 8, isEntryHidden: true},\n {initiatorIndex: 6, eventIndex: 11},\n {initiatorIndex: 11, eventIndex: 12, isInitiatorHidden: true, isEntryHidden: true},\n {initiatorIndex: 5, eventIndex: 15},\n ],\n groups: [{\n name: 'Testing initiators' as Platform.UIString.LocalizedString,\n startLevel: 0,\n style: defaultGroupStyle,\n }],\n });\n }\n\n override maxStackDepth(): number {\n return 4;\n }\n }\n\n const container = document.querySelector('div#initiators');\n if (!container) {\n throw new Error('No container');\n }\n const delegate = new TraceHelpers.MockFlameChartDelegate();\n const dataProvider = new FakeProviderWithVariousTasksForInitiators();\n const flameChart = new PerfUI.FlameChart.FlameChart(dataProvider, delegate);\n\n flameChart.markAsRoot();\n flameChart.setSelectedEntry(14);\n flameChart.setWindowTimes(0, 100);\n flameChart.show(container);\n flameChart.update();\n}\n\nrenderBasicExample();\nrenderDecorationExample();\nrenderNestedExample();\nrenderTrackCustomizationExample();\nrenderInitiatorsExample();\n"]} \ No newline at end of file +{"version":3,"file":"flamechart.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/components/docs/performance_panel/flamechart.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Platform from '../../../../core/platform/platform.js';\nimport * as Trace from '../../../../models/trace/trace.js';\nimport * as EnvironmentHelpers from '../../../../testing/EnvironmentHelpers.js';\nimport * as TraceHelpers from '../../../../testing/TraceHelpers.js';\nimport * as PerfUI from '../../../legacy/components/perf_ui/perf_ui.js';\nimport * as ComponentSetup from '../../helpers/helpers.js';\n\nawait EnvironmentHelpers.initializeGlobalVars();\nawait ComponentSetup.ComponentServerSetup.setup();\n\nconst defaultGroupStyle = {\n height: 17,\n padding: 4,\n collapsible: false,\n color: 'black',\n backgroundColor: 'grey',\n nestingLevel: 0,\n itemsHeight: 17,\n};\n\n/**\n * Render a basic flame chart with 3 events on the same level\n **/\nfunction renderBasicExample() {\n class FakeProviderWithBasicEvents extends TraceHelpers.FakeFlameChartProvider {\n override timelineData(): PerfUI.FlameChart.FlameChartTimelineData|null {\n return PerfUI.FlameChart.FlameChartTimelineData.create({\n entryLevels: [0, 0, 0, 1, 1, 1, 2, 2, 2],\n entryStartTimes: [5, 60, 80, 5, 60, 80, 5, 60, 80],\n entryTotalTimes: [50, 10, 10, 50, 10, 10, 50, 10, 10],\n groups: [\n {\n name: 'Test Group 0' as Platform.UIString.LocalizedString,\n startLevel: 0,\n style: {...defaultGroupStyle, collapsible: true},\n },\n {\n name: 'Test Group 1' as Platform.UIString.LocalizedString,\n startLevel: 1,\n style: {...defaultGroupStyle, collapsible: true, color: 'red', backgroundColor: 'green'},\n },\n {\n name: 'Test Group 2' as Platform.UIString.LocalizedString,\n startLevel: 2,\n style: {...defaultGroupStyle, collapsible: true, color: 'blue', backgroundColor: 'yellow'},\n },\n ],\n });\n }\n }\n\n const container = document.querySelector('div#basic');\n if (!container) {\n throw new Error('No container');\n }\n const delegate = new TraceHelpers.MockFlameChartDelegate();\n const dataProvider = new FakeProviderWithBasicEvents();\n const flameChart = new PerfUI.FlameChart.FlameChart(dataProvider, delegate);\n\n flameChart.markAsRoot();\n flameChart.setWindowTimes(0, 100);\n flameChart.show(container);\n flameChart.update();\n}\n\n/**\n * Render a flame chart with events with decorations.\n **/\nfunction renderDecorationExample() {\n class FakeProviderWithDecorations extends TraceHelpers.FakeFlameChartProvider {\n override timelineData(): PerfUI.FlameChart.FlameChartTimelineData|null {\n return PerfUI.FlameChart.FlameChartTimelineData.create({\n entryLevels: [0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2],\n entryStartTimes: [5, 55, 70, 5, 30, 55, 75, 5, 10, 15, 20, 25],\n entryTotalTimes: [45, 10, 20, 20, 20, 5, 15, 4, 4, 4, 4, 1],\n entryDecorations: [\n [\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,\n startAtTime: Trace.Types.Timing.MicroSeconds(25_000),\n },\n {type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE},\n ],\n [{type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE}],\n [\n {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},\n {type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE},\n ],\n [\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,\n startAtTime: Trace.Types.Timing.MicroSeconds(15_000),\n },\n ],\n [\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,\n startAtTime: Trace.Types.Timing.MicroSeconds(10_000),\n },\n {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},\n ],\n [\n {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},\n ],\n [\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,\n startAtTime: Trace.Types.Timing.MicroSeconds(10_000),\n },\n {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},\n {type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE},\n ],\n [\n {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},\n ],\n [\n {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},\n {type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE},\n ],\n [\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,\n startAtTime: Trace.Types.Timing.MicroSeconds(1_000),\n },\n {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},\n ],\n [\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.CANDY,\n startAtTime: Trace.Types.Timing.MicroSeconds(1_000),\n },\n {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},\n {type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE},\n ],\n [\n {\n type: PerfUI.FlameChart.FlameChartDecorationType.WARNING_TRIANGLE,\n // This triangle should start 1/4 of hte event, and end at 3/4 of the event.\n customStartTime: Trace.Types.Timing.MicroSeconds(25_250),\n customEndTime: Trace.Types.Timing.MicroSeconds(25_750),\n },\n ],\n ],\n groups: [{\n name: 'Testing Candy Stripe, warning triangles and hidden descendants arrow decorations' as\n Platform.UIString.LocalizedString,\n startLevel: 0,\n style: defaultGroupStyle,\n }],\n });\n }\n }\n\n const container = document.querySelector('div#decorations');\n if (!container) {\n throw new Error('No container');\n }\n const delegate = new TraceHelpers.MockFlameChartDelegate();\n const dataProvider = new FakeProviderWithDecorations();\n const flameChart = new PerfUI.FlameChart.FlameChart(dataProvider, delegate);\n\n flameChart.markAsRoot();\n flameChart.setWindowTimes(0, 100);\n flameChart.show(container);\n flameChart.update();\n}\n\n/**\n * Render a flame chart with nested track.\n **/\nfunction renderNestedExample() {\n class FakeProviderWithNestedGroup extends TraceHelpers.FakeFlameChartProvider {\n override timelineData(): PerfUI.FlameChart.FlameChartTimelineData|null {\n return PerfUI.FlameChart.FlameChartTimelineData.create({\n entryLevels: [0, 1, 2],\n entryStartTimes: [5, 5, 5],\n entryTotalTimes: [50, 50, 50],\n groups: [\n {\n name: 'Test Group 0' as Platform.UIString.LocalizedString,\n startLevel: 0,\n style: {...defaultGroupStyle, collapsible: true},\n },\n {\n name: 'Test Nested Group 1' as Platform.UIString.LocalizedString,\n startLevel: 0,\n style: {...defaultGroupStyle, collapsible: true, color: 'red', backgroundColor: 'green'},\n },\n {\n name: 'Test Group 2' as Platform.UIString.LocalizedString,\n startLevel: 2,\n style: {...defaultGroupStyle, collapsible: true, color: 'blue', backgroundColor: 'yellow'},\n },\n ],\n });\n }\n }\n\n const container = document.querySelector('div#nested');\n if (!container) {\n throw new Error('No container');\n }\n const delegate = new TraceHelpers.MockFlameChartDelegate();\n const dataProvider = new FakeProviderWithNestedGroup();\n const flameChart = new PerfUI.FlameChart.FlameChart(dataProvider, delegate);\n\n flameChart.markAsRoot();\n flameChart.setWindowTimes(0, 100);\n flameChart.show(container);\n flameChart.update();\n}\n\n/**\n * Render a flame chart with nested case and buttons to hide/unhide and reorder\n * tracks\n **/\nfunction renderTrackCustomizationExample() {\n class FakeProviderWithBasicEvents extends TraceHelpers.FakeFlameChartProvider {\n override timelineData(): PerfUI.FlameChart.FlameChartTimelineData|null {\n return PerfUI.FlameChart.FlameChartTimelineData.create({\n entryLevels: [0, 0, 1, 1, 2, 2, 3, 3],\n entryStartTimes: [5, 60, 5, 60, 5, 60],\n entryTotalTimes: [50, 10, 50, 10, 50, 10],\n groups: [\n {\n name: 'Test Group 0' as Platform.UIString.LocalizedString,\n startLevel: 0,\n expanded: true,\n style: {...defaultGroupStyle, collapsible: true},\n },\n {\n name: 'Test Group 1' as Platform.UIString.LocalizedString,\n startLevel: 1,\n expanded: true,\n style: {...defaultGroupStyle, collapsible: true, color: 'red', backgroundColor: 'green'},\n },\n {\n name: 'Test Group 2' as Platform.UIString.LocalizedString,\n startLevel: 2,\n expanded: true,\n style: {...defaultGroupStyle, collapsible: true, color: 'blue', backgroundColor: 'yellow'},\n },\n {\n name: 'Test Group 3' as Platform.UIString.LocalizedString,\n startLevel: 2,\n expanded: true,\n style: {...defaultGroupStyle, nestingLevel: 1},\n },\n ],\n });\n }\n }\n\n const container = document.querySelector('div#track-customization');\n if (!container) {\n throw new Error('No container');\n }\n const delegate = new TraceHelpers.MockFlameChartDelegate();\n const dataProvider = new FakeProviderWithBasicEvents();\n const flameChart = new PerfUI.FlameChart.FlameChart(dataProvider, delegate);\n\n flameChart.markAsRoot();\n flameChart.setWindowTimes(0, 100);\n flameChart.show(container);\n flameChart.update();\n\n const indexInput = document.querySelector('#indexOfTrack') as HTMLInputElement;\n const buttonHide = document.querySelector('#hide');\n buttonHide?.addEventListener('click', () => {\n const index = Number(indexInput.value);\n flameChart.hideGroup(index);\n });\n const buttonUnhide = document.querySelector('#unhide');\n buttonUnhide?.addEventListener('click', () => {\n const index = Number(indexInput.value);\n flameChart.showGroup(index);\n });\n\n const buttonForMoveUp = document.querySelector('#testForMoveUp');\n buttonForMoveUp?.addEventListener('click', () => {\n const index = Number(indexInput.value);\n flameChart.moveGroupUp(index);\n });\n const buttonForMoveDown = document.querySelector('#testForMoveDown');\n buttonForMoveDown?.addEventListener('click', () => {\n const index = Number(indexInput.value);\n flameChart.moveGroupDown(index);\n });\n}\n\n/**\n * Render a flame chart with event initiators of different sizes.\n * Some initiator and initiated events are hidden.\n **/\nfunction renderInitiatorsExample() {\n class FakeProviderWithVariousTasksForInitiators extends TraceHelpers.FakeFlameChartProvider {\n override timelineData(): PerfUI.FlameChart.FlameChartTimelineData|null {\n return PerfUI.FlameChart.FlameChartTimelineData.create({\n entryLevels: [0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 3],\n entryStartTimes: [5, 5, 5, 15, 15, 15, 40, 40, 40, 55.4, 55.4, 55.4, 80, 80, 80, 17],\n entryTotalTimes: [6, 6, 6, 5, 5, 20, 15, 15, 15, 2, 2, 2, 10, 10, 10, 10],\n entryDecorations: [\n [],\n [],\n [\n {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},\n ],\n [],\n [],\n [],\n [],\n [],\n [\n {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},\n ],\n [],\n [],\n [\n {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},\n ],\n [\n {type: PerfUI.FlameChart.FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW},\n ],\n ],\n initiatorsData: [\n {initiatorIndex: 2, eventIndex: 3, isInitiatorHidden: true},\n {initiatorIndex: 1, eventIndex: 13},\n {initiatorIndex: 3, eventIndex: 6},\n {initiatorIndex: 3, eventIndex: 8, isEntryHidden: true},\n {initiatorIndex: 6, eventIndex: 11},\n {initiatorIndex: 11, eventIndex: 12, isInitiatorHidden: true, isEntryHidden: true},\n {initiatorIndex: 5, eventIndex: 15},\n ],\n groups: [{\n name: 'Testing initiators' as Platform.UIString.LocalizedString,\n startLevel: 0,\n style: defaultGroupStyle,\n }],\n });\n }\n\n override maxStackDepth(): number {\n return 4;\n }\n }\n\n const container = document.querySelector('div#initiators');\n if (!container) {\n throw new Error('No container');\n }\n const delegate = new TraceHelpers.MockFlameChartDelegate();\n const dataProvider = new FakeProviderWithVariousTasksForInitiators();\n const flameChart = new PerfUI.FlameChart.FlameChart(dataProvider, delegate);\n\n flameChart.markAsRoot();\n flameChart.setSelectedEntry(14);\n flameChart.setWindowTimes(0, 100);\n flameChart.show(container);\n flameChart.update();\n}\n\nrenderBasicExample();\nrenderDecorationExample();\nrenderNestedExample();\nrenderTrackCustomizationExample();\nrenderInitiatorsExample();\n"]} \ No newline at end of file diff --git a/public/ui/components/docs/performance_panel/layout_shift_details.js b/public/ui/components/docs/performance_panel/layout_shift_details.js index 3e585134b..16162774e 100644 --- a/public/ui/components/docs/performance_panel/layout_shift_details.js +++ b/public/ui/components/docs/performance_panel/layout_shift_details.js @@ -15,10 +15,10 @@ async function renderDetails() { if (!container) { throw new Error('No container'); } - const { traceData, insights } = await TraceLoader.TraceLoader.traceEngine(/* mocha context */ null, 'shift-attribution.json.gz'); - const shiftEventIframe = traceData.LayoutShifts.clusters[0].worstShiftEvent; + const { parsedTrace, insights } = await TraceLoader.TraceLoader.traceEngine(/* mocha context */ null, 'shift-attribution.json.gz'); + const shiftEventIframe = parsedTrace.LayoutShifts.clusters[0].worstShiftEvent; const details = new TimelineComponents.LayoutShiftDetails.LayoutShiftDetails(); - details.setData(shiftEventIframe, insights, traceData, false); + details.setData(shiftEventIframe, insights, parsedTrace, false); container.appendChild(details); } await renderDetails(); diff --git a/public/ui/components/docs/performance_panel/layout_shift_details.js.map b/public/ui/components/docs/performance_panel/layout_shift_details.js.map index d5ef71799..bd2ad8d2f 100644 --- a/public/ui/components/docs/performance_panel/layout_shift_details.js.map +++ b/public/ui/components/docs/performance_panel/layout_shift_details.js.map @@ -1 +1 @@ -{"version":3,"file":"layout_shift_details.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/components/docs/performance_panel/layout_shift_details.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAG7B,OAAO,KAAK,kBAAkB,MAAM,sDAAsD,CAAC;AAC3F,OAAO,KAAK,kBAAkB,MAAM,2CAA2C,CAAC;AAChF,OAAO,KAAK,WAAW,MAAM,oCAAoC,CAAC;AAClE,OAAO,KAAK,cAAc,MAAM,0BAA0B,CAAC;AAE3D,MAAM,kBAAkB,CAAC,oBAAoB,EAAE,CAAC;AAChD,MAAM,cAAc,CAAC,oBAAoB,CAAC,KAAK,EAAE,CAAC;AAElD;;IAEI;AACJ,KAAK,UAAU,aAAa;IAC1B,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;IACvD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC;IAClC,CAAC;IAED,MAAM,EAAC,SAAS,EAAE,QAAQ,EAAC,GACvB,MAAM,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC,mBAAmB,CAAC,IAAI,EAAE,2BAA2B,CAAC,CAAC;IAErG,MAAM,gBAAgB,GAClB,SAAS,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,eAAqE,CAAC;IAC7G,MAAM,OAAO,GAAG,IAAI,kBAAkB,CAAC,kBAAkB,CAAC,kBAAkB,EAAE,CAAC;IAC/E,OAAO,CAAC,OAAO,CAAC,gBAAgB,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;IAE9D,SAAS,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,aAAa,EAAE,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as TraceEngine from '../../../../models/trace/trace.js';\nimport * as TimelineComponents from '../../../../panels/timeline/components/components.js';\nimport * as EnvironmentHelpers from '../../../../testing/EnvironmentHelpers.js';\nimport * as TraceLoader from '../../../../testing/TraceLoader.js';\nimport * as ComponentSetup from '../../helpers/helpers.js';\n\nawait EnvironmentHelpers.initializeGlobalVars();\nawait ComponentSetup.ComponentServerSetup.setup();\n\n/**\n * Render details for a Layout shift event.\n **/\nasync function renderDetails() {\n const container = document.querySelector('#container');\n if (!container) {\n throw new Error('No container');\n }\n\n const {traceData, insights} =\n await TraceLoader.TraceLoader.traceEngine(/* mocha context */ null, 'shift-attribution.json.gz');\n\n const shiftEventIframe =\n traceData.LayoutShifts.clusters[0].worstShiftEvent as TraceEngine.Types.TraceEvents.SyntheticLayoutShift;\n const details = new TimelineComponents.LayoutShiftDetails.LayoutShiftDetails();\n details.setData(shiftEventIframe, insights, traceData, false);\n\n container.appendChild(details);\n}\n\nawait renderDetails();\n"]} \ No newline at end of file +{"version":3,"file":"layout_shift_details.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/components/docs/performance_panel/layout_shift_details.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAG7B,OAAO,KAAK,kBAAkB,MAAM,sDAAsD,CAAC;AAC3F,OAAO,KAAK,kBAAkB,MAAM,2CAA2C,CAAC;AAChF,OAAO,KAAK,WAAW,MAAM,oCAAoC,CAAC;AAClE,OAAO,KAAK,cAAc,MAAM,0BAA0B,CAAC;AAE3D,MAAM,kBAAkB,CAAC,oBAAoB,EAAE,CAAC;AAChD,MAAM,cAAc,CAAC,oBAAoB,CAAC,KAAK,EAAE,CAAC;AAElD;;IAEI;AACJ,KAAK,UAAU,aAAa;IAC1B,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;IACvD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC;IAClC,CAAC;IAED,MAAM,EAAC,WAAW,EAAE,QAAQ,EAAC,GACzB,MAAM,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC,mBAAmB,CAAC,IAAI,EAAE,2BAA2B,CAAC,CAAC;IAErG,MAAM,gBAAgB,GAClB,WAAW,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,eAA0D,CAAC;IACpG,MAAM,OAAO,GAAG,IAAI,kBAAkB,CAAC,kBAAkB,CAAC,kBAAkB,EAAE,CAAC;IAC/E,OAAO,CAAC,OAAO,CAAC,gBAAgB,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;IAEhE,SAAS,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,aAAa,EAAE,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Trace from '../../../../models/trace/trace.js';\nimport * as TimelineComponents from '../../../../panels/timeline/components/components.js';\nimport * as EnvironmentHelpers from '../../../../testing/EnvironmentHelpers.js';\nimport * as TraceLoader from '../../../../testing/TraceLoader.js';\nimport * as ComponentSetup from '../../helpers/helpers.js';\n\nawait EnvironmentHelpers.initializeGlobalVars();\nawait ComponentSetup.ComponentServerSetup.setup();\n\n/**\n * Render details for a Layout shift event.\n **/\nasync function renderDetails() {\n const container = document.querySelector('#container');\n if (!container) {\n throw new Error('No container');\n }\n\n const {parsedTrace, insights} =\n await TraceLoader.TraceLoader.traceEngine(/* mocha context */ null, 'shift-attribution.json.gz');\n\n const shiftEventIframe =\n parsedTrace.LayoutShifts.clusters[0].worstShiftEvent as Trace.Types.Events.SyntheticLayoutShift;\n const details = new TimelineComponents.LayoutShiftDetails.LayoutShiftDetails();\n details.setData(shiftEventIframe, insights, parsedTrace, false);\n\n container.appendChild(details);\n}\n\nawait renderDetails();\n"]} \ No newline at end of file diff --git a/public/ui/components/docs/performance_panel/network_request_details.js b/public/ui/components/docs/performance_panel/network_request_details.js index 252eac10e..67a2d0df0 100644 --- a/public/ui/components/docs/performance_panel/network_request_details.js +++ b/public/ui/components/docs/performance_panel/network_request_details.js @@ -18,11 +18,11 @@ async function renderDetails() { if (!container) { throw new Error('No container'); } - const { traceData } = await TraceLoader.TraceLoader.traceEngine(/* mocha context */ null, 'lcp-images.json.gz'); - const networkEvent = traceData.NetworkRequests.byTime[0]; - const maybeTarget = Timeline.TargetForEvent.targetForEvent(traceData, networkEvent); + const { parsedTrace } = await TraceLoader.TraceLoader.traceEngine(/* mocha context */ null, 'lcp-images.json.gz'); + const networkEvent = parsedTrace.NetworkRequests.byTime[0]; + const maybeTarget = Timeline.TargetForEvent.targetForEvent(parsedTrace, networkEvent); const details = new TimelineComponents.NetworkRequestDetails.NetworkRequestDetails(detailsLinkifier); - await details.setData(traceData, networkEvent, maybeTarget); + await details.setData(parsedTrace, networkEvent, maybeTarget); container.appendChild(details); } await renderDetails(); diff --git a/public/ui/components/docs/performance_panel/network_request_details.js.map b/public/ui/components/docs/performance_panel/network_request_details.js.map index 294f94383..2eaca29c9 100644 --- a/public/ui/components/docs/performance_panel/network_request_details.js.map +++ b/public/ui/components/docs/performance_panel/network_request_details.js.map @@ -1 +1 @@ -{"version":3,"file":"network_request_details.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/components/docs/performance_panel/network_request_details.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,kBAAkB,MAAM,sDAAsD,CAAC;AAC3F,OAAO,KAAK,QAAQ,MAAM,yCAAyC,CAAC;AACpE,OAAO,KAAK,kBAAkB,MAAM,2CAA2C,CAAC;AAChF,OAAO,KAAK,WAAW,MAAM,oCAAoC,CAAC;AAClE,OAAO,KAAK,UAAU,MAAM,iDAAiD,CAAC;AAC9E,OAAO,KAAK,cAAc,MAAM,0BAA0B,CAAC;AAE3D,MAAM,kBAAkB,CAAC,oBAAoB,EAAE,CAAC;AAChD,MAAM,cAAc,CAAC,oBAAoB,CAAC,KAAK,EAAE,CAAC;AAClD,MAAM,gBAAgB,GAAG,IAAI,UAAU,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC;AAE9D;;IAEI;AACJ,KAAK,UAAU,aAAa;IAC1B,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;IACvD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC;IAClC,CAAC;IAED,MAAM,EAAC,SAAS,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC,mBAAmB,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;IAC9G,MAAM,YAAY,GAAG,SAAS,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACzD,MAAM,WAAW,GAAG,QAAQ,CAAC,cAAc,CAAC,cAAc,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IAEpF,MAAM,OAAO,GAAG,IAAI,kBAAkB,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,gBAAgB,CAAC,CAAC;IACrG,MAAM,OAAO,CAAC,OAAO,CAAC,SAAS,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;IAE5D,SAAS,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,aAAa,EAAE,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TimelineComponents from '../../../../panels/timeline/components/components.js';\nimport * as Timeline from '../../../../panels/timeline/timeline.js';\nimport * as EnvironmentHelpers from '../../../../testing/EnvironmentHelpers.js';\nimport * as TraceLoader from '../../../../testing/TraceLoader.js';\nimport * as Components from '../../../../ui/legacy/components/utils/utils.js';\nimport * as ComponentSetup from '../../helpers/helpers.js';\n\nawait EnvironmentHelpers.initializeGlobalVars();\nawait ComponentSetup.ComponentServerSetup.setup();\nconst detailsLinkifier = new Components.Linkifier.Linkifier();\n\n/**\n * Render details for a basic network request\n **/\nasync function renderDetails() {\n const container = document.querySelector('#container');\n if (!container) {\n throw new Error('No container');\n }\n\n const {traceData} = await TraceLoader.TraceLoader.traceEngine(/* mocha context */ null, 'lcp-images.json.gz');\n const networkEvent = traceData.NetworkRequests.byTime[0];\n const maybeTarget = Timeline.TargetForEvent.targetForEvent(traceData, networkEvent);\n\n const details = new TimelineComponents.NetworkRequestDetails.NetworkRequestDetails(detailsLinkifier);\n await details.setData(traceData, networkEvent, maybeTarget);\n\n container.appendChild(details);\n}\n\nawait renderDetails();\n"]} \ No newline at end of file +{"version":3,"file":"network_request_details.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/components/docs/performance_panel/network_request_details.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,kBAAkB,MAAM,sDAAsD,CAAC;AAC3F,OAAO,KAAK,QAAQ,MAAM,yCAAyC,CAAC;AACpE,OAAO,KAAK,kBAAkB,MAAM,2CAA2C,CAAC;AAChF,OAAO,KAAK,WAAW,MAAM,oCAAoC,CAAC;AAClE,OAAO,KAAK,UAAU,MAAM,iDAAiD,CAAC;AAC9E,OAAO,KAAK,cAAc,MAAM,0BAA0B,CAAC;AAE3D,MAAM,kBAAkB,CAAC,oBAAoB,EAAE,CAAC;AAChD,MAAM,cAAc,CAAC,oBAAoB,CAAC,KAAK,EAAE,CAAC;AAClD,MAAM,gBAAgB,GAAG,IAAI,UAAU,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC;AAE9D;;IAEI;AACJ,KAAK,UAAU,aAAa;IAC1B,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;IACvD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC;IAClC,CAAC;IAED,MAAM,EAAC,WAAW,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC,mBAAmB,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC;IAChH,MAAM,YAAY,GAAG,WAAW,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAC3D,MAAM,WAAW,GAAG,QAAQ,CAAC,cAAc,CAAC,cAAc,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IAEtF,MAAM,OAAO,GAAG,IAAI,kBAAkB,CAAC,qBAAqB,CAAC,qBAAqB,CAAC,gBAAgB,CAAC,CAAC;IACrG,MAAM,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,YAAY,EAAE,WAAW,CAAC,CAAC;IAE9D,SAAS,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,aAAa,EAAE,CAAC","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TimelineComponents from '../../../../panels/timeline/components/components.js';\nimport * as Timeline from '../../../../panels/timeline/timeline.js';\nimport * as EnvironmentHelpers from '../../../../testing/EnvironmentHelpers.js';\nimport * as TraceLoader from '../../../../testing/TraceLoader.js';\nimport * as Components from '../../../../ui/legacy/components/utils/utils.js';\nimport * as ComponentSetup from '../../helpers/helpers.js';\n\nawait EnvironmentHelpers.initializeGlobalVars();\nawait ComponentSetup.ComponentServerSetup.setup();\nconst detailsLinkifier = new Components.Linkifier.Linkifier();\n\n/**\n * Render details for a basic network request\n **/\nasync function renderDetails() {\n const container = document.querySelector('#container');\n if (!container) {\n throw new Error('No container');\n }\n\n const {parsedTrace} = await TraceLoader.TraceLoader.traceEngine(/* mocha context */ null, 'lcp-images.json.gz');\n const networkEvent = parsedTrace.NetworkRequests.byTime[0];\n const maybeTarget = Timeline.TargetForEvent.targetForEvent(parsedTrace, networkEvent);\n\n const details = new TimelineComponents.NetworkRequestDetails.NetworkRequestDetails(detailsLinkifier);\n await details.setData(parsedTrace, networkEvent, maybeTarget);\n\n container.appendChild(details);\n}\n\nawait renderDetails();\n"]} \ No newline at end of file diff --git a/public/ui/components/docs/performance_panel/network_request_tooltip.js b/public/ui/components/docs/performance_panel/network_request_tooltip.js index 1c6e07ec8..edac714ad 100644 --- a/public/ui/components/docs/performance_panel/network_request_tooltip.js +++ b/public/ui/components/docs/performance_panel/network_request_tooltip.js @@ -15,8 +15,8 @@ async function renderTooltips1() { if (!container) { throw new Error('No container'); } - const { traceData } = await TraceLoader.TraceLoader.traceEngine(/* mocha context */ null, 'lcp-images.json.gz'); - const networkEvent = traceData.NetworkRequests.byTime[0]; + const { parsedTrace } = await TraceLoader.TraceLoader.traceEngine(/* mocha context */ null, 'lcp-images.json.gz'); + const networkEvent = parsedTrace.NetworkRequests.byTime[0]; const tooltip = new TimelineComponents.NetworkRequestTooltip.NetworkRequestTooltip(); tooltip.networkRequest = networkEvent; container.appendChild(tooltip); @@ -29,8 +29,8 @@ async function renderTooltips2() { if (!container) { throw new Error('No container'); } - const { traceData } = await TraceLoader.TraceLoader.traceEngine(/* mocha context */ null, 'render-blocking-in-iframe.json.gz'); - const networkEvent = traceData.NetworkRequests.byTime[1]; + const { parsedTrace } = await TraceLoader.TraceLoader.traceEngine(/* mocha context */ null, 'render-blocking-in-iframe.json.gz'); + const networkEvent = parsedTrace.NetworkRequests.byTime[1]; const tooltip = new TimelineComponents.NetworkRequestTooltip.NetworkRequestTooltip(); tooltip.networkRequest = networkEvent; container.appendChild(tooltip); @@ -43,8 +43,8 @@ async function renderTooltips3() { if (!container) { throw new Error('No container'); } - const { traceData } = await TraceLoader.TraceLoader.traceEngine(/* mocha context */ null, 'changing-priority.json.gz'); - const networkEvent = traceData.NetworkRequests.byTime.find(request => { + const { parsedTrace } = await TraceLoader.TraceLoader.traceEngine(/* mocha context */ null, 'changing-priority.json.gz'); + const networkEvent = parsedTrace.NetworkRequests.byTime.find(request => { return request.args.data.url === 'https://via.placeholder.com/3000.jpg'; }); if (!networkEvent) { diff --git a/public/ui/components/docs/performance_panel/network_request_tooltip.js.map b/public/ui/components/docs/performance_panel/network_request_tooltip.js.map index e80275034..95995c346 100644 --- a/public/ui/components/docs/performance_panel/network_request_tooltip.js.map +++ b/public/ui/components/docs/performance_panel/network_request_tooltip.js.map @@ -1 +1 @@ -{"version":3,"file":"network_request_tooltip.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/components/docs/performance_panel/network_request_tooltip.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TimelineComponents from '../../../../panels/timeline/components/components.js';\nimport * as EnvironmentHelpers from '../../../../testing/EnvironmentHelpers.js';\nimport * as TraceLoader from '../../../../testing/TraceLoader.js';\nimport * as ComponentSetup from '../../helpers/helpers.js';\n\nawait EnvironmentHelpers.initializeGlobalVars();\nawait ComponentSetup.ComponentServerSetup.setup();\n\n/**\n * Render tooltip for a basic network request\n **/\nasync function renderTooltips1() {\n const container = document.querySelector('#container1');\n if (!container) {\n throw new Error('No container');\n }\n\n const {traceData} = await TraceLoader.TraceLoader.traceEngine(/* mocha context */ null, 'lcp-images.json.gz');\n const networkEvent = traceData.NetworkRequests.byTime[0];\n\n const tooltip = new TimelineComponents.NetworkRequestTooltip.NetworkRequestTooltip();\n tooltip.networkRequest = networkEvent;\n\n container.appendChild(tooltip);\n}\n\n/**\n * Render tooltip for a render-blocking network request\n **/\nasync function renderTooltips2() {\n const container = document.querySelector('#container2');\n if (!container) {\n throw new Error('No container');\n }\n\n const {traceData} =\n await TraceLoader.TraceLoader.traceEngine(/* mocha context */ null, 'render-blocking-in-iframe.json.gz');\n const networkEvent = traceData.NetworkRequests.byTime[1];\n\n const tooltip = new TimelineComponents.NetworkRequestTooltip.NetworkRequestTooltip();\n tooltip.networkRequest = networkEvent;\n\n container.appendChild(tooltip);\n}\n\n/**\n * Render tooltip for a priority changed network request\n **/\nasync function renderTooltips3() {\n const container = document.querySelector('#container3');\n if (!container) {\n throw new Error('No container');\n }\n\n const {traceData} = await TraceLoader.TraceLoader.traceEngine(/* mocha context */ null, 'changing-priority.json.gz');\n const networkEvent = traceData.NetworkRequests.byTime.find(request => {\n return request.args.data.url === 'https://via.placeholder.com/3000.jpg';\n });\n if (!networkEvent) {\n throw new Error('The priority change event is not found');\n }\n\n const tooltip = new TimelineComponents.NetworkRequestTooltip.NetworkRequestTooltip();\n tooltip.networkRequest = networkEvent;\n\n container.appendChild(tooltip);\n}\n\nawait renderTooltips1();\nawait renderTooltips2();\nawait renderTooltips3();\n"]} \ No newline at end of file +{"version":3,"file":"network_request_tooltip.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/components/docs/performance_panel/network_request_tooltip.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2024 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TimelineComponents from '../../../../panels/timeline/components/components.js';\nimport * as EnvironmentHelpers from '../../../../testing/EnvironmentHelpers.js';\nimport * as TraceLoader from '../../../../testing/TraceLoader.js';\nimport * as ComponentSetup from '../../helpers/helpers.js';\n\nawait EnvironmentHelpers.initializeGlobalVars();\nawait ComponentSetup.ComponentServerSetup.setup();\n\n/**\n * Render tooltip for a basic network request\n **/\nasync function renderTooltips1() {\n const container = document.querySelector('#container1');\n if (!container) {\n throw new Error('No container');\n }\n\n const {parsedTrace} = await TraceLoader.TraceLoader.traceEngine(/* mocha context */ null, 'lcp-images.json.gz');\n const networkEvent = parsedTrace.NetworkRequests.byTime[0];\n\n const tooltip = new TimelineComponents.NetworkRequestTooltip.NetworkRequestTooltip();\n tooltip.networkRequest = networkEvent;\n\n container.appendChild(tooltip);\n}\n\n/**\n * Render tooltip for a render-blocking network request\n **/\nasync function renderTooltips2() {\n const container = document.querySelector('#container2');\n if (!container) {\n throw new Error('No container');\n }\n\n const {parsedTrace} =\n await TraceLoader.TraceLoader.traceEngine(/* mocha context */ null, 'render-blocking-in-iframe.json.gz');\n const networkEvent = parsedTrace.NetworkRequests.byTime[1];\n\n const tooltip = new TimelineComponents.NetworkRequestTooltip.NetworkRequestTooltip();\n tooltip.networkRequest = networkEvent;\n\n container.appendChild(tooltip);\n}\n\n/**\n * Render tooltip for a priority changed network request\n **/\nasync function renderTooltips3() {\n const container = document.querySelector('#container3');\n if (!container) {\n throw new Error('No container');\n }\n\n const {parsedTrace} =\n await TraceLoader.TraceLoader.traceEngine(/* mocha context */ null, 'changing-priority.json.gz');\n const networkEvent = parsedTrace.NetworkRequests.byTime.find(request => {\n return request.args.data.url === 'https://via.placeholder.com/3000.jpg';\n });\n if (!networkEvent) {\n throw new Error('The priority change event is not found');\n }\n\n const tooltip = new TimelineComponents.NetworkRequestTooltip.NetworkRequestTooltip();\n tooltip.networkRequest = networkEvent;\n\n container.appendChild(tooltip);\n}\n\nawait renderTooltips1();\nawait renderTooltips2();\nawait renderTooltips3();\n"]} \ No newline at end of file diff --git a/public/ui/components/docs/performance_panel/overview.js b/public/ui/components/docs/performance_panel/overview.js index 399652df5..b8a65f5e1 100644 --- a/public/ui/components/docs/performance_panel/overview.js +++ b/public/ui/components/docs/performance_panel/overview.js @@ -1,7 +1,7 @@ // 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 * as TraceEngine from '../../../../models/trace/trace.js'; +import * as Trace from '../../../../models/trace/trace.js'; import * as Timeline from '../../../../panels/timeline/timeline.js'; import * as TraceBounds from '../../../../services/trace_bounds/trace_bounds.js'; import * as EnvironmentHelpers from '../../../../testing/EnvironmentHelpers.js'; @@ -22,27 +22,27 @@ async function renderMiniMap(containerSelector, options) { if (!container) { throw new Error('could not find container'); } - const { traceData } = await TraceLoader.TraceLoader.traceEngine(null, fileName); - const mainThread = TraceEngine.Handlers.Threads.threadsInRenderer(traceData.Renderer, traceData.AuctionWorklets) - .find(t => t.type === "MAIN_THREAD" /* TraceEngine.Handlers.Threads.ThreadType.MAIN_THREAD */); + const { parsedTrace } = await TraceLoader.TraceLoader.traceEngine(null, fileName); + const mainThread = Trace.Handlers.Threads.threadsInRenderer(parsedTrace.Renderer, parsedTrace.AuctionWorklets) + .find(t => t.type === "MAIN_THREAD" /* Trace.Handlers.Threads.ThreadType.MAIN_THREAD */); if (!mainThread) { throw new Error('Could not find main thread.'); } const minimap = new Timeline.TimelineMiniMap.TimelineMiniMap(); minimap.markAsRoot(); minimap.show(container); - TraceBounds.TraceBounds.BoundsManager.instance().resetWithNewBounds(traceData.Meta.traceBounds); - const zoomedWindow = TraceEngine.Extras.MainThreadActivity.calculateWindow(traceData.Meta.traceBounds, mainThread.entries); + TraceBounds.TraceBounds.BoundsManager.instance().resetWithNewBounds(parsedTrace.Meta.traceBounds); + const zoomedWindow = Trace.Extras.MainThreadActivity.calculateWindow(parsedTrace.Meta.traceBounds, mainThread.entries); TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(zoomedWindow); minimap.setData({ - traceParsedData: traceData, + parsedTrace, settings: { showMemory: options.showMemory, showScreenshots: true, }, }); if (customStartWindowTime && customEndWindowTime) { - TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(TraceEngine.Helpers.Timing.traceWindowFromMilliSeconds(TraceEngine.Types.Timing.MilliSeconds(Number(customStartWindowTime)), TraceEngine.Types.Timing.MilliSeconds(Number(customEndWindowTime)))); + TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(Trace.Helpers.Timing.traceWindowFromMilliSeconds(Trace.Types.Timing.MilliSeconds(Number(customStartWindowTime)), Trace.Types.Timing.MilliSeconds(Number(customEndWindowTime)))); } } await renderMiniMap('.container', { showMemory: false }); diff --git a/public/ui/components/docs/performance_panel/overview.js.map b/public/ui/components/docs/performance_panel/overview.js.map index 3d77335df..7c362e7d0 100644 --- a/public/ui/components/docs/performance_panel/overview.js.map +++ b/public/ui/components/docs/performance_panel/overview.js.map @@ -1 +1 @@ -{"version":3,"file":"overview.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/components/docs/performance_panel/overview.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceEngine from '../../../../models/trace/trace.js';\nimport * as Timeline from '../../../../panels/timeline/timeline.js';\nimport * as TraceBounds from '../../../../services/trace_bounds/trace_bounds.js';\nimport * as EnvironmentHelpers from '../../../../testing/EnvironmentHelpers.js';\nimport * as TraceLoader from '../../../../testing/TraceLoader.js';\nimport * as ComponentSetup from '../../helpers/helpers.js';\n\nawait EnvironmentHelpers.initializeGlobalVars();\nawait ComponentSetup.ComponentServerSetup.setup();\nconst container = document.querySelector('div.container');\nif (!container) {\n throw new Error('could not find container');\n}\n\nconst params = new URLSearchParams(window.location.search);\nconst fileName = (params.get('trace') || 'web-dev') + '.json.gz';\nconst customStartWindowTime = params.get('windowStart');\nconst customEndWindowTime = params.get('windowEnd');\n\nasync function renderMiniMap(containerSelector: string, options: {showMemory: boolean}) {\n const container = document.querySelector(containerSelector);\n if (!container) {\n throw new Error('could not find container');\n }\n const {traceData} = await TraceLoader.TraceLoader.traceEngine(null, fileName);\n\n const mainThread = TraceEngine.Handlers.Threads.threadsInRenderer(traceData.Renderer, traceData.AuctionWorklets)\n .find(t => t.type === TraceEngine.Handlers.Threads.ThreadType.MAIN_THREAD);\n if (!mainThread) {\n throw new Error('Could not find main thread.');\n }\n const minimap = new Timeline.TimelineMiniMap.TimelineMiniMap();\n minimap.markAsRoot();\n minimap.show(container);\n TraceBounds.TraceBounds.BoundsManager.instance().resetWithNewBounds(traceData.Meta.traceBounds);\n\n const zoomedWindow = TraceEngine.Extras.MainThreadActivity.calculateWindow(\n traceData.Meta.traceBounds,\n mainThread.entries,\n );\n TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(zoomedWindow);\n\n minimap.setData({\n traceParsedData: traceData,\n settings: {\n showMemory: options.showMemory,\n showScreenshots: true,\n },\n });\n if (customStartWindowTime && customEndWindowTime) {\n TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(\n TraceEngine.Helpers.Timing.traceWindowFromMilliSeconds(\n TraceEngine.Types.Timing.MilliSeconds(Number(customStartWindowTime)),\n TraceEngine.Types.Timing.MilliSeconds(Number(customEndWindowTime)),\n ),\n );\n }\n}\n\nawait renderMiniMap('.container', {showMemory: false});\nawait renderMiniMap('.container-with-memory', {showMemory: true});\n"]} \ No newline at end of file +{"version":3,"file":"overview.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/components/docs/performance_panel/overview.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../../../models/trace/trace.js';\nimport * as Timeline from '../../../../panels/timeline/timeline.js';\nimport * as TraceBounds from '../../../../services/trace_bounds/trace_bounds.js';\nimport * as EnvironmentHelpers from '../../../../testing/EnvironmentHelpers.js';\nimport * as TraceLoader from '../../../../testing/TraceLoader.js';\nimport * as ComponentSetup from '../../helpers/helpers.js';\n\nawait EnvironmentHelpers.initializeGlobalVars();\nawait ComponentSetup.ComponentServerSetup.setup();\nconst container = document.querySelector('div.container');\nif (!container) {\n throw new Error('could not find container');\n}\n\nconst params = new URLSearchParams(window.location.search);\nconst fileName = (params.get('trace') || 'web-dev') + '.json.gz';\nconst customStartWindowTime = params.get('windowStart');\nconst customEndWindowTime = params.get('windowEnd');\n\nasync function renderMiniMap(containerSelector: string, options: {showMemory: boolean}) {\n const container = document.querySelector(containerSelector);\n if (!container) {\n throw new Error('could not find container');\n }\n const {parsedTrace} = await TraceLoader.TraceLoader.traceEngine(null, fileName);\n\n const mainThread = Trace.Handlers.Threads.threadsInRenderer(parsedTrace.Renderer, parsedTrace.AuctionWorklets)\n .find(t => t.type === Trace.Handlers.Threads.ThreadType.MAIN_THREAD);\n if (!mainThread) {\n throw new Error('Could not find main thread.');\n }\n const minimap = new Timeline.TimelineMiniMap.TimelineMiniMap();\n minimap.markAsRoot();\n minimap.show(container);\n TraceBounds.TraceBounds.BoundsManager.instance().resetWithNewBounds(parsedTrace.Meta.traceBounds);\n\n const zoomedWindow = Trace.Extras.MainThreadActivity.calculateWindow(\n parsedTrace.Meta.traceBounds,\n mainThread.entries,\n );\n TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(zoomedWindow);\n\n minimap.setData({\n parsedTrace,\n settings: {\n showMemory: options.showMemory,\n showScreenshots: true,\n },\n });\n if (customStartWindowTime && customEndWindowTime) {\n TraceBounds.TraceBounds.BoundsManager.instance().setTimelineVisibleWindow(\n Trace.Helpers.Timing.traceWindowFromMilliSeconds(\n Trace.Types.Timing.MilliSeconds(Number(customStartWindowTime)),\n Trace.Types.Timing.MilliSeconds(Number(customEndWindowTime)),\n ),\n );\n }\n}\n\nawait renderMiniMap('.container', {showMemory: false});\nawait renderMiniMap('.container-with-memory', {showMemory: true});\n"]} \ No newline at end of file diff --git a/public/ui/components/docs/performance_panel/timeline_history_manager.js b/public/ui/components/docs/performance_panel/timeline_history_manager.js index 59c7b7ead..22063491f 100644 --- a/public/ui/components/docs/performance_panel/timeline_history_manager.js +++ b/public/ui/components/docs/performance_panel/timeline_history_manager.js @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. import * as Root from '../../../../core/root/root.js'; -import * as TraceEngine from '../../../../models/trace/trace.js'; +import * as Trace from '../../../../models/trace/trace.js'; import * as Timeline from '../../../../panels/timeline/timeline.js'; import * as FrontendHelpers from '../../../../testing/EnvironmentHelpers.js'; import * as TraceLoader from '../../../../testing/TraceLoader.js'; @@ -21,30 +21,30 @@ UI.ActionRegistration.registerActionExtension({ return new Timeline.TimelinePanel.ActionDelegate(); }, }); -const { traceData: traceParsedData1 } = await TraceLoader.TraceLoader.traceEngine(null, 'multiple-navigations.json.gz'); -TraceLoader.TraceLoader.initTraceBoundsManager(traceParsedData1); +const { parsedTrace: parsedTrace1 } = await TraceLoader.TraceLoader.traceEngine(null, 'multiple-navigations.json.gz'); +TraceLoader.TraceLoader.initTraceBoundsManager(parsedTrace1); new Timeline.TimelineHistoryManager.TimelineHistoryManager().addRecording({ data: { - traceParseDataIndex: 0, + parsedTraceIndex: 0, type: 'TRACE_INDEX', }, - filmStripForPreview: TraceEngine.Extras.FilmStrip.fromTraceData(traceParsedData1), - traceParsedData: traceParsedData1, + filmStripForPreview: Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace1), + parsedTrace: parsedTrace1, startTime: null, }); -const { traceData: traceParsedData2 } = await TraceLoader.TraceLoader.traceEngine(null, 'web-dev.json.gz'); -TraceLoader.TraceLoader.initTraceBoundsManager(traceParsedData2); +const { parsedTrace: parsedTrace2 } = await TraceLoader.TraceLoader.traceEngine(null, 'web-dev.json.gz'); +TraceLoader.TraceLoader.initTraceBoundsManager(parsedTrace2); const container = document.querySelector('.container'); if (!container) { throw new Error('could not find container'); } new Timeline.TimelineHistoryManager.TimelineHistoryManager().addRecording({ data: { - traceParseDataIndex: 1, + parsedTraceIndex: 1, type: 'TRACE_INDEX', }, - filmStripForPreview: TraceEngine.Extras.FilmStrip.fromTraceData(traceParsedData2), - traceParsedData: traceParsedData2, + filmStripForPreview: Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace2), + parsedTrace: parsedTrace2, startTime: null, }); await Timeline.TimelineHistoryManager.DropDown.show([0, 1], 1, container); diff --git a/public/ui/components/docs/performance_panel/timeline_history_manager.js.map b/public/ui/components/docs/performance_panel/timeline_history_manager.js.map index acd99128b..91e561bb2 100644 --- a/public/ui/components/docs/performance_panel/timeline_history_manager.js.map +++ b/public/ui/components/docs/performance_panel/timeline_history_manager.js.map @@ -1 +1 @@ -{"version":3,"file":"timeline_history_manager.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/components/docs/performance_panel/timeline_history_manager.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,IAAI,MAAM,+BAA+B,CAAC;AACtD,OAAO,KAAK,WAAW,MAAM,mCAAmC,CAAC;AACjE,OAAO,KAAK,QAAQ,MAAM,yCAAyC,CAAC;AACpE,OAAO,KAAK,eAAe,MAAM,2CAA2C,CAAC;AAC7E,OAAO,KAAK,WAAW,MAAM,oCAAoC,CAAC;AAClE,OAAO,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAChD,OAAO,KAAK,cAAc,MAAM,0BAA0B,CAAC;AAE3D,MAAM,eAAe,CAAC,oBAAoB,EAAE,CAAC;AAC7C,MAAM,cAAc,CAAC,oBAAoB,CAAC,KAAK,EAAE,CAAC;AAElD,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,UAAU,kFAAoD,IAAI,CAAC,CAAC;AAE7F,EAAE,CAAC,kBAAkB,CAAC,uBAAuB,CAAC;IAC5C,QAAQ,EAAE,uBAAuB;IACjC,QAAQ,sEAAkD;IAC1D,YAAY;QACV,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;IAChD,CAAC;IACD,KAAK,CAAC,kBAAkB;QACtB,OAAO,IAAI,QAAQ,CAAC,aAAa,CAAC,cAAc,EAAE,CAAC;IACrD,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,EAAC,SAAS,EAAE,gBAAgB,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,8BAA8B,CAAC,CAAC;AACtH,WAAW,CAAC,WAAW,CAAC,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;AAEjE,IAAI,QAAQ,CAAC,sBAAsB,CAAC,sBAAsB,EAAE,CAAC,YAAY,CAAC;IACxE,IAAI,EAAE;QACJ,mBAAmB,EAAE,CAAC;QACtB,IAAI,EAAE,aAAa;KACpB;IACD,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,gBAAgB,CAAC;IACjF,eAAe,EAAE,gBAAgB;IACjC,SAAS,EAAE,IAAI;CAChB,CAAC,CAAC;AAEH,MAAM,EAAC,SAAS,EAAE,gBAAgB,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;AACzG,WAAW,CAAC,WAAW,CAAC,sBAAsB,CAAC,gBAAgB,CAAC,CAAC;AACjE,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;AACvD,IAAI,CAAC,SAAS,EAAE,CAAC;IACf,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;AAC9C,CAAC;AAED,IAAI,QAAQ,CAAC,sBAAsB,CAAC,sBAAsB,EAAE,CAAC,YAAY,CAAC;IACxE,IAAI,EAAE;QACJ,mBAAmB,EAAE,CAAC;QACtB,IAAI,EAAE,aAAa;KACpB;IACD,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,gBAAgB,CAAC;IACjF,eAAe,EAAE,gBAAgB;IACjC,SAAS,EAAE,IAAI;CAChB,CAAC,CAAC;AACH,MAAM,QAAQ,CAAC,sBAAsB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Root from '../../../../core/root/root.js';\nimport * as TraceEngine from '../../../../models/trace/trace.js';\nimport * as Timeline from '../../../../panels/timeline/timeline.js';\nimport * as FrontendHelpers from '../../../../testing/EnvironmentHelpers.js';\nimport * as TraceLoader from '../../../../testing/TraceLoader.js';\nimport * as UI from '../../../legacy/legacy.js';\nimport * as ComponentSetup from '../../helpers/helpers.js';\n\nawait FrontendHelpers.initializeGlobalVars();\nawait ComponentSetup.ComponentServerSetup.setup();\n\nRoot.Runtime.experiments.setEnabled(Root.Runtime.ExperimentName.TIMELINE_OBSERVATIONS, true);\n\nUI.ActionRegistration.registerActionExtension({\n actionId: 'timeline.show-history',\n category: UI.ActionRegistration.ActionCategory.PERFORMANCE,\n contextTypes() {\n return [Timeline.TimelinePanel.TimelinePanel];\n },\n async loadActionDelegate() {\n return new Timeline.TimelinePanel.ActionDelegate();\n },\n});\n\nconst {traceData: traceParsedData1} = await TraceLoader.TraceLoader.traceEngine(null, 'multiple-navigations.json.gz');\nTraceLoader.TraceLoader.initTraceBoundsManager(traceParsedData1);\n\nnew Timeline.TimelineHistoryManager.TimelineHistoryManager().addRecording({\n data: {\n traceParseDataIndex: 0,\n type: 'TRACE_INDEX',\n },\n filmStripForPreview: TraceEngine.Extras.FilmStrip.fromTraceData(traceParsedData1),\n traceParsedData: traceParsedData1,\n startTime: null,\n});\n\nconst {traceData: traceParsedData2} = await TraceLoader.TraceLoader.traceEngine(null, 'web-dev.json.gz');\nTraceLoader.TraceLoader.initTraceBoundsManager(traceParsedData2);\nconst container = document.querySelector('.container');\nif (!container) {\n throw new Error('could not find container');\n}\n\nnew Timeline.TimelineHistoryManager.TimelineHistoryManager().addRecording({\n data: {\n traceParseDataIndex: 1,\n type: 'TRACE_INDEX',\n },\n filmStripForPreview: TraceEngine.Extras.FilmStrip.fromTraceData(traceParsedData2),\n traceParsedData: traceParsedData2,\n startTime: null,\n});\nawait Timeline.TimelineHistoryManager.DropDown.show([0, 1], 1, container);\n"]} \ No newline at end of file +{"version":3,"file":"timeline_history_manager.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/components/docs/performance_panel/timeline_history_manager.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,IAAI,MAAM,+BAA+B,CAAC;AACtD,OAAO,KAAK,KAAK,MAAM,mCAAmC,CAAC;AAC3D,OAAO,KAAK,QAAQ,MAAM,yCAAyC,CAAC;AACpE,OAAO,KAAK,eAAe,MAAM,2CAA2C,CAAC;AAC7E,OAAO,KAAK,WAAW,MAAM,oCAAoC,CAAC;AAClE,OAAO,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAChD,OAAO,KAAK,cAAc,MAAM,0BAA0B,CAAC;AAE3D,MAAM,eAAe,CAAC,oBAAoB,EAAE,CAAC;AAC7C,MAAM,cAAc,CAAC,oBAAoB,CAAC,KAAK,EAAE,CAAC;AAElD,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,UAAU,kFAAoD,IAAI,CAAC,CAAC;AAE7F,EAAE,CAAC,kBAAkB,CAAC,uBAAuB,CAAC;IAC5C,QAAQ,EAAE,uBAAuB;IACjC,QAAQ,sEAAkD;IAC1D,YAAY;QACV,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;IAChD,CAAC;IACD,KAAK,CAAC,kBAAkB;QACtB,OAAO,IAAI,QAAQ,CAAC,aAAa,CAAC,cAAc,EAAE,CAAC;IACrD,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,EAAC,WAAW,EAAE,YAAY,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,8BAA8B,CAAC,CAAC;AACpH,WAAW,CAAC,WAAW,CAAC,sBAAsB,CAAC,YAAY,CAAC,CAAC;AAE7D,IAAI,QAAQ,CAAC,sBAAsB,CAAC,sBAAsB,EAAE,CAAC,YAAY,CAAC;IACxE,IAAI,EAAE;QACJ,gBAAgB,EAAE,CAAC;QACnB,IAAI,EAAE,aAAa;KACpB;IACD,mBAAmB,EAAE,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC,YAAY,CAAC;IACzE,WAAW,EAAE,YAAY;IACzB,SAAS,EAAE,IAAI;CAChB,CAAC,CAAC;AAEH,MAAM,EAAC,WAAW,EAAE,YAAY,EAAC,GAAG,MAAM,WAAW,CAAC,WAAW,CAAC,WAAW,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC;AACvG,WAAW,CAAC,WAAW,CAAC,sBAAsB,CAAC,YAAY,CAAC,CAAC;AAC7D,MAAM,SAAS,GAAG,QAAQ,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;AACvD,IAAI,CAAC,SAAS,EAAE,CAAC;IACf,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;AAC9C,CAAC;AAED,IAAI,QAAQ,CAAC,sBAAsB,CAAC,sBAAsB,EAAE,CAAC,YAAY,CAAC;IACxE,IAAI,EAAE;QACJ,gBAAgB,EAAE,CAAC;QACnB,IAAI,EAAE,aAAa;KACpB;IACD,mBAAmB,EAAE,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,eAAe,CAAC,YAAY,CAAC;IACzE,WAAW,EAAE,YAAY;IACzB,SAAS,EAAE,IAAI;CAChB,CAAC,CAAC;AACH,MAAM,QAAQ,CAAC,sBAAsB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Root from '../../../../core/root/root.js';\nimport * as Trace from '../../../../models/trace/trace.js';\nimport * as Timeline from '../../../../panels/timeline/timeline.js';\nimport * as FrontendHelpers from '../../../../testing/EnvironmentHelpers.js';\nimport * as TraceLoader from '../../../../testing/TraceLoader.js';\nimport * as UI from '../../../legacy/legacy.js';\nimport * as ComponentSetup from '../../helpers/helpers.js';\n\nawait FrontendHelpers.initializeGlobalVars();\nawait ComponentSetup.ComponentServerSetup.setup();\n\nRoot.Runtime.experiments.setEnabled(Root.Runtime.ExperimentName.TIMELINE_OBSERVATIONS, true);\n\nUI.ActionRegistration.registerActionExtension({\n actionId: 'timeline.show-history',\n category: UI.ActionRegistration.ActionCategory.PERFORMANCE,\n contextTypes() {\n return [Timeline.TimelinePanel.TimelinePanel];\n },\n async loadActionDelegate() {\n return new Timeline.TimelinePanel.ActionDelegate();\n },\n});\n\nconst {parsedTrace: parsedTrace1} = await TraceLoader.TraceLoader.traceEngine(null, 'multiple-navigations.json.gz');\nTraceLoader.TraceLoader.initTraceBoundsManager(parsedTrace1);\n\nnew Timeline.TimelineHistoryManager.TimelineHistoryManager().addRecording({\n data: {\n parsedTraceIndex: 0,\n type: 'TRACE_INDEX',\n },\n filmStripForPreview: Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace1),\n parsedTrace: parsedTrace1,\n startTime: null,\n});\n\nconst {parsedTrace: parsedTrace2} = await TraceLoader.TraceLoader.traceEngine(null, 'web-dev.json.gz');\nTraceLoader.TraceLoader.initTraceBoundsManager(parsedTrace2);\nconst container = document.querySelector('.container');\nif (!container) {\n throw new Error('could not find container');\n}\n\nnew Timeline.TimelineHistoryManager.TimelineHistoryManager().addRecording({\n data: {\n parsedTraceIndex: 1,\n type: 'TRACE_INDEX',\n },\n filmStripForPreview: Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace2),\n parsedTrace: parsedTrace2,\n startTime: null,\n});\nawait Timeline.TimelineHistoryManager.DropDown.show([0, 1], 1, container);\n"]} \ No newline at end of file diff --git a/public/ui/components/issue_counter/IssueCounter.js b/public/ui/components/issue_counter/IssueCounter.js index 49ee6a11f..426cc2877 100644 --- a/public/ui/components/issue_counter/IssueCounter.js +++ b/public/ui/components/issue_counter/IssueCounter.js @@ -38,7 +38,6 @@ function toIconGroup({ iconName, color, width, height }, sizeOverride) { } return { iconName, iconColor: color, iconWidth: width, iconHeight: height }; } -// @ts-ignore Remove this comment once Intl.ListFormat is in type defs. const listFormat = new Intl.ListFormat(navigator.language, { type: 'unit', style: 'short' }); export function getIssueCountsEnumeration(issuesManager, omitEmpty = true) { const counts = [ diff --git a/public/ui/components/issue_counter/IssueCounter.js.map b/public/ui/components/issue_counter/IssueCounter.js.map index 89c589ffc..2f096f523 100644 --- a/public/ui/components/issue_counter/IssueCounter.js.map +++ b/public/ui/components/issue_counter/IssueCounter.js.map @@ -1 +1 @@ -{"version":3,"file":"IssueCounter.js","sourceRoot":"","sources":["../../../../../../../front_end/ui/components/issue_counter/IssueCounter.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,MAAM,MAAM,gCAAgC,CAAC;AACzD,OAAO,KAAK,IAAI,MAAM,4BAA4B,CAAC;AACnD,OAAO,KAAK,aAAa,MAAM,kDAAkD,CAAC;AAClF,OAAO,KAAK,OAAO,MAAM,4BAA4B,CAAC;AAGtD,OAAO,kBAAkB,MAAM,uBAAuB,CAAC;AAEvD,MAAM,SAAS,GAAG;IAChB;;OAEG;IACH,UAAU,EAAE,+DAA+D;IAC3E;;OAEG;IACH,eAAe,EAAE,yEAAyE;IAC1F;;OAEG;IACH,oBAAoB,EAAE,mFAAmF;CAC1G,CAAC;AACF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,6CAA6C,EAAE,SAAS,CAAC,CAAC;AACnG,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AAEtE,MAAM,UAAU,oBAAoB,CAAC,SAAwC;IAC3E,QAAQ,SAAS,EAAE,CAAC;QAClB;YACE,OAAO,EAAC,QAAQ,EAAE,oBAAoB,EAAE,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAC,CAAC;QACrG;YACE,OAAO,EAAC,QAAQ,EAAE,0BAA0B,EAAE,KAAK,EAAE,qBAAqB,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAC,CAAC;QAC7G;YACE,OAAO,EAAC,QAAQ,EAAE,mBAAmB,EAAE,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAC,CAAC;IACrG,CAAC;AACH,CAAC;AAED,SAAS,WAAW,CAAC,EAAC,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAA+B,EAAE,YAAqB;IAExG,IAAI,YAAY,EAAE,CAAC;QACjB,OAAO,EAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAC,CAAC;IACzF,CAAC;IACD,OAAO,EAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAC,CAAC;AAC5E,CAAC;AAmBD,uEAAuE;AACvE,MAAM,UAAU,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAC,CAAC,CAAC;AAE3F,MAAM,UAAU,yBAAyB,CACrC,aAAwD,EAAE,YAAqB,IAAI;IACrF,MAAM,MAAM,GAA6B;QACvC,aAAa,CAAC,cAAc,4DAA0C;QACtE,aAAa,CAAC,cAAc,sEAA+C;QAC3E,aAAa,CAAC,cAAc,+DAA2C;KACxE,CAAC;IACF,MAAM,OAAO,GAAG;QACd,UAAU,CAAC,SAAS,CAAC,UAAU,EAAE,EAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,EAAC,CAAC;QACzD,UAAU,CAAC,SAAS,CAAC,eAAe,EAAE,EAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,EAAC,CAAC;QAC9D,UAAU,CAAC,SAAS,CAAC,oBAAoB,EAAE,EAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,EAAC,CAAC;KACpE,CAAC;IACF,OAAO,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AACvF,CAAC;AAED,MAAM,OAAO,YAAa,SAAQ,WAAW;IAC3C,MAAM,CAAU,UAAU,GAAG,OAAO,CAAC,OAAO,CAAA,wBAAwB,CAAC;IAC5D,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,EAAC,IAAI,EAAE,MAAM,EAAC,CAAC,CAAC;IACrD,aAAa,GAA2B,SAAS,CAAC;IAClD,gBAAgB,GAA2B,SAAS,CAAC;IACrD,YAAY,GAAW,EAAE,CAAC;IAC1B,UAAU,CAAuC;IACjD,OAAO,GAA6B,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9C,YAAY,4CAAuC;IACnD,cAAc,GAAwD,SAAS,CAAC;IAChF,eAAe,GAAqB,SAAS,CAAC;IAC9C,iBAAiB,CAAmB;IACpC,QAAQ,GAAG,KAAK,CAAC;IAEjB,cAAc;QACZ,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,KAAK,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5D,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,CAAC;IACH,CAAC;IAED,iBAAiB;QACf,IAAI,CAAC,OAAO,CAAC,kBAAkB,GAAG,CAAC,kBAAkB,CAAC,CAAC;IACzD,CAAC;IAED,IAAI,IAAI,CAAC,IAAsB;QAC7B,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,YAAY,CAAC;QACvC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,WAAW,IAAI,EAAE,CAAC;QAC3C,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,eAAe,CAAC;QAC7C,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,WAAW,4CAA0B,CAAC;QAC/D,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,cAAc,CAAC;QAC3C,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,gBAAgB,CAAC;QAC/C,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACtC,IAAI,IAAI,CAAC,cAAc,KAAK,IAAI,CAAC,aAAa,EAAE,CAAC;YAC/C,IAAI,CAAC,cAAc,EAAE,mBAAmB,qFACqB,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;YACxF,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC;YACzC,IAAI,CAAC,cAAc,CAAC,gBAAgB,qFACyB,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;QAC1F,CAAC;QACD,IAAI,IAAI,CAAC,gBAAgB,KAAK,CAAC,EAAE,CAAC;YAChC,IAAI,CAAC,UAAU,GAAG,IAAI,MAAM,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,gBAAgB,IAAI,GAAG,CAAC,CAAC;QACjF,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC9B,CAAC;QACD,IAAI,CAAC,cAAc,EAAE,CAAC;IACxB,CAAC;IAED,IAAI,IAAI;QACN,OAAO;YACL,YAAY,EAAE,IAAI,CAAC,aAAa;YAChC,WAAW,EAAE,IAAI,CAAC,YAAY;YAC9B,eAAe,EAAE,IAAI,CAAC,gBAAgB;YACtC,WAAW,EAAE,IAAI,CAAC,YAAY;YAC9B,cAAc,EAAE,IAAI,CAAC,eAAe;YACpC,gBAAgB,EAAE,IAAI,CAAC,iBAAiB;YACxC,OAAO,EAAE,IAAI,CAAC,QAAQ;YACtB,aAAa,EAAE,IAAI,CAAC,cAA2D;SAChF,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;YACzB,OAAO;QACT,CAAC;QACD,IAAI,CAAC,OAAO,GAAG;YACb,IAAI,CAAC,cAAc,CAAC,cAAc,4DAA0C;YAC5E,IAAI,CAAC,cAAc,CAAC,cAAc,sEAA+C;YACjF,IAAI,CAAC,cAAc,CAAC,cAAc,+DAA2C;SAC9E,CAAC;QACF,MAAM,UAAU,GAAG;;;;SAIlB,CAAC;QACF,MAAM,aAAa,GAAG,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAE1E,MAAM,aAAa,GAAG,CAAC,IAAmC,EAAE,KAAa,EAAoB,EAAE;YAC7F,QAAQ,IAAI,CAAC,YAAY,EAAE,CAAC;gBAC1B;oBACE,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;gBAC5C;oBACE,OAAO,GAAG,KAAK,EAAE,CAAC;gBACpB;oBACE,OAAO,IAAI,KAAK,aAAa,CAAC,CAAC,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;YAC3D,CAAC;QACH,CAAC,CAAC;QACF,MAAM,QAAQ,GAAG,KAAK,CAAC;QACvB,MAAM,IAAI,GAAyC;YACjD,MAAM,EAAE;gBACN;oBACE,GAAG,WAAW,CAAC,oBAAoB,4DAA0C,EAAE,QAAQ,CAAC;oBACxF,IAAI,EAAE,aAAa,6DAA2C,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;iBAC/E;gBACD;oBACE,GAAG,WAAW,CAAC,oBAAoB,sEAA+C,EAAE,QAAQ,CAAC;oBAC7F,IAAI,EAAE,aAAa,uEAAgD,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;iBACpF;gBACD;oBACE,GAAG,WAAW,CAAC,oBAAoB,+DAA2C,EAAE,QAAQ,CAAC;oBACzF,IAAI,EAAE,aAAa,gEAA4C,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;iBAChF;aACF;YACD,YAAY,EAAE,IAAI,CAAC,aAAa;YAChC,WAAW,EAAE,IAAI,CAAC,YAAY;YAC9B,cAAc,EAAE,IAAI,CAAC,eAAe;YACpC,OAAO,EAAE,IAAI,CAAC,QAAQ;SACvB,CAAC;QACF,OAAO,CAAC,MAAM,CACV,OAAO,CAAC,IAAI,CAAA;6BACS,IAA4C,oBAC7D,IAAI,CAAC,eAAe;SACvB,EACD,IAAI,CAAC,OAAO,EAAE,EAAC,IAAI,EAAE,IAAI,EAAC,CAAC,CAAC;QAChC,IAAI,CAAC,gBAAgB,EAAE,EAAE,CAAC;IAC5B,CAAC;;AAGH,cAAc,CAAC,MAAM,CAAC,wBAAwB,EAAE,YAAY,CAAC,CAAC","sourcesContent":["// Copyright 2021 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../../core/common/common.js';\nimport * as i18n from '../../../core/i18n/i18n.js';\nimport * as IssuesManager from '../../../models/issues_manager/issues_manager.js';\nimport * as LitHtml from '../../lit-html/lit-html.js';\nimport type * as IconButton from '../icon_button/icon_button.js';\n\nimport issueCounterStyles from './issueCounter.css.js';\n\nconst UIStrings = {\n /**\n *@description Label for link to Issues tab, specifying how many issues there are.\n */\n pageErrors: '{issueCount, plural, =1 {# page error} other {# page errors}}',\n /**\n *@description Label for link to Issues tab, specifying how many issues there are.\n */\n breakingChanges: '{issueCount, plural, =1 {# breaking change} other {# breaking changes}}',\n /**\n *@description Label for link to Issues tab, specifying how many issues there are.\n */\n possibleImprovements: '{issueCount, plural, =1 {# possible improvement} other {# possible improvements}}',\n};\nconst str_ = i18n.i18n.registerUIStrings('ui/components/issue_counter/IssueCounter.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function getIssueKindIconData(issueKind: IssuesManager.Issue.IssueKind): IconButton.Icon.IconWithName {\n switch (issueKind) {\n case IssuesManager.Issue.IssueKind.PAGE_ERROR:\n return {iconName: 'issue-cross-filled', color: 'var(--icon-error)', width: '20px', height: '20px'};\n case IssuesManager.Issue.IssueKind.BREAKING_CHANGE:\n return {iconName: 'issue-exclamation-filled', color: 'var(--icon-warning)', width: '20px', height: '20px'};\n case IssuesManager.Issue.IssueKind.IMPROVEMENT:\n return {iconName: 'issue-text-filled', color: 'var(--icon-info)', width: '20px', height: '20px'};\n }\n}\n\nfunction toIconGroup({iconName, color, width, height}: IconButton.Icon.IconWithName, sizeOverride?: string):\n IconButton.IconButton.IconWithTextData {\n if (sizeOverride) {\n return {iconName, iconColor: color, iconWidth: sizeOverride, iconHeight: sizeOverride};\n }\n return {iconName, iconColor: color, iconWidth: width, iconHeight: height};\n}\n\nexport const enum DisplayMode {\n OMIT_EMPTY = 'OmitEmpty',\n SHOW_ALWAYS = 'ShowAlways',\n ONLY_MOST_IMPORTANT = 'OnlyMostImportant',\n}\n\nexport interface IssueCounterData {\n clickHandler?: () => void;\n tooltipCallback?: () => void;\n leadingText?: string;\n displayMode?: DisplayMode;\n issuesManager: IssuesManager.IssuesManager.IssuesManager;\n throttlerTimeout?: number;\n accessibleName?: string;\n compact?: boolean;\n}\n\n// @ts-ignore Remove this comment once Intl.ListFormat is in type defs.\nconst listFormat = new Intl.ListFormat(navigator.language, {type: 'unit', style: 'short'});\n\nexport function getIssueCountsEnumeration(\n issuesManager: IssuesManager.IssuesManager.IssuesManager, omitEmpty: boolean = true): string {\n const counts: [number, number, number] = [\n issuesManager.numberOfIssues(IssuesManager.Issue.IssueKind.PAGE_ERROR),\n issuesManager.numberOfIssues(IssuesManager.Issue.IssueKind.BREAKING_CHANGE),\n issuesManager.numberOfIssues(IssuesManager.Issue.IssueKind.IMPROVEMENT),\n ];\n const phrases = [\n i18nString(UIStrings.pageErrors, {issueCount: counts[0]}),\n i18nString(UIStrings.breakingChanges, {issueCount: counts[1]}),\n i18nString(UIStrings.possibleImprovements, {issueCount: counts[2]}),\n ];\n return listFormat.format(phrases.filter((_, i) => omitEmpty ? counts[i] > 0 : true));\n}\n\nexport class IssueCounter extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-issue-counter`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n #clickHandler: undefined|(() => void) = undefined;\n #tooltipCallback: undefined|(() => void) = undefined;\n #leadingText: string = '';\n #throttler: undefined|Common.Throttler.Throttler;\n #counts: [number, number, number] = [0, 0, 0];\n #displayMode: DisplayMode = DisplayMode.OMIT_EMPTY;\n #issuesManager: IssuesManager.IssuesManager.IssuesManager|undefined = undefined;\n #accessibleName: string|undefined = undefined;\n #throttlerTimeout: number|undefined;\n #compact = false;\n\n scheduleUpdate(): void {\n if (this.#throttler) {\n void this.#throttler.schedule(async () => this.#render());\n } else {\n this.#render();\n }\n }\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [issueCounterStyles];\n }\n\n set data(data: IssueCounterData) {\n this.#clickHandler = data.clickHandler;\n this.#leadingText = data.leadingText ?? '';\n this.#tooltipCallback = data.tooltipCallback;\n this.#displayMode = data.displayMode ?? DisplayMode.OMIT_EMPTY;\n this.#accessibleName = data.accessibleName;\n this.#throttlerTimeout = data.throttlerTimeout;\n this.#compact = Boolean(data.compact);\n if (this.#issuesManager !== data.issuesManager) {\n this.#issuesManager?.removeEventListener(\n IssuesManager.IssuesManager.Events.ISSUES_COUNT_UPDATED, this.scheduleUpdate, this);\n this.#issuesManager = data.issuesManager;\n this.#issuesManager.addEventListener(\n IssuesManager.IssuesManager.Events.ISSUES_COUNT_UPDATED, this.scheduleUpdate, this);\n }\n if (data.throttlerTimeout !== 0) {\n this.#throttler = new Common.Throttler.Throttler(data.throttlerTimeout ?? 100);\n } else {\n this.#throttler = undefined;\n }\n this.scheduleUpdate();\n }\n\n get data(): IssueCounterData {\n return {\n clickHandler: this.#clickHandler,\n leadingText: this.#leadingText,\n tooltipCallback: this.#tooltipCallback,\n displayMode: this.#displayMode,\n accessibleName: this.#accessibleName,\n throttlerTimeout: this.#throttlerTimeout,\n compact: this.#compact,\n issuesManager: this.#issuesManager as IssuesManager.IssuesManager.IssuesManager,\n };\n }\n\n #render(): void {\n if (!this.#issuesManager) {\n return;\n }\n this.#counts = [\n this.#issuesManager.numberOfIssues(IssuesManager.Issue.IssueKind.PAGE_ERROR),\n this.#issuesManager.numberOfIssues(IssuesManager.Issue.IssueKind.BREAKING_CHANGE),\n this.#issuesManager.numberOfIssues(IssuesManager.Issue.IssueKind.IMPROVEMENT),\n ];\n const importance = [\n IssuesManager.Issue.IssueKind.PAGE_ERROR,\n IssuesManager.Issue.IssueKind.BREAKING_CHANGE,\n IssuesManager.Issue.IssueKind.IMPROVEMENT,\n ];\n const mostImportant = importance[this.#counts.findIndex(x => x > 0) ?? 2];\n\n const countToString = (kind: IssuesManager.Issue.IssueKind, count: number): string|undefined => {\n switch (this.#displayMode) {\n case DisplayMode.OMIT_EMPTY:\n return count > 0 ? `${count}` : undefined;\n case DisplayMode.SHOW_ALWAYS:\n return `${count}`;\n case DisplayMode.ONLY_MOST_IMPORTANT:\n return kind === mostImportant ? `${count}` : undefined;\n }\n };\n const iconSize = '2ex';\n const data: IconButton.IconButton.IconButtonData = {\n groups: [\n {\n ...toIconGroup(getIssueKindIconData(IssuesManager.Issue.IssueKind.PAGE_ERROR), iconSize),\n text: countToString(IssuesManager.Issue.IssueKind.PAGE_ERROR, this.#counts[0]),\n },\n {\n ...toIconGroup(getIssueKindIconData(IssuesManager.Issue.IssueKind.BREAKING_CHANGE), iconSize),\n text: countToString(IssuesManager.Issue.IssueKind.BREAKING_CHANGE, this.#counts[1]),\n },\n {\n ...toIconGroup(getIssueKindIconData(IssuesManager.Issue.IssueKind.IMPROVEMENT), iconSize),\n text: countToString(IssuesManager.Issue.IssueKind.IMPROVEMENT, this.#counts[2]),\n },\n ],\n clickHandler: this.#clickHandler,\n leadingText: this.#leadingText,\n accessibleName: this.#accessibleName,\n compact: this.#compact,\n };\n LitHtml.render(\n LitHtml.html`\n \n `,\n this.#shadow, {host: this});\n this.#tooltipCallback?.();\n }\n}\n\ncustomElements.define('devtools-issue-counter', IssueCounter);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-issue-counter': IssueCounter;\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"IssueCounter.js","sourceRoot":"","sources":["../../../../../../../front_end/ui/components/issue_counter/IssueCounter.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2021 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../../core/common/common.js';\nimport * as i18n from '../../../core/i18n/i18n.js';\nimport * as IssuesManager from '../../../models/issues_manager/issues_manager.js';\nimport * as LitHtml from '../../lit-html/lit-html.js';\nimport type * as IconButton from '../icon_button/icon_button.js';\n\nimport issueCounterStyles from './issueCounter.css.js';\n\nconst UIStrings = {\n /**\n *@description Label for link to Issues tab, specifying how many issues there are.\n */\n pageErrors: '{issueCount, plural, =1 {# page error} other {# page errors}}',\n /**\n *@description Label for link to Issues tab, specifying how many issues there are.\n */\n breakingChanges: '{issueCount, plural, =1 {# breaking change} other {# breaking changes}}',\n /**\n *@description Label for link to Issues tab, specifying how many issues there are.\n */\n possibleImprovements: '{issueCount, plural, =1 {# possible improvement} other {# possible improvements}}',\n};\nconst str_ = i18n.i18n.registerUIStrings('ui/components/issue_counter/IssueCounter.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\nexport function getIssueKindIconData(issueKind: IssuesManager.Issue.IssueKind): IconButton.Icon.IconWithName {\n switch (issueKind) {\n case IssuesManager.Issue.IssueKind.PAGE_ERROR:\n return {iconName: 'issue-cross-filled', color: 'var(--icon-error)', width: '20px', height: '20px'};\n case IssuesManager.Issue.IssueKind.BREAKING_CHANGE:\n return {iconName: 'issue-exclamation-filled', color: 'var(--icon-warning)', width: '20px', height: '20px'};\n case IssuesManager.Issue.IssueKind.IMPROVEMENT:\n return {iconName: 'issue-text-filled', color: 'var(--icon-info)', width: '20px', height: '20px'};\n }\n}\n\nfunction toIconGroup({iconName, color, width, height}: IconButton.Icon.IconWithName, sizeOverride?: string):\n IconButton.IconButton.IconWithTextData {\n if (sizeOverride) {\n return {iconName, iconColor: color, iconWidth: sizeOverride, iconHeight: sizeOverride};\n }\n return {iconName, iconColor: color, iconWidth: width, iconHeight: height};\n}\n\nexport const enum DisplayMode {\n OMIT_EMPTY = 'OmitEmpty',\n SHOW_ALWAYS = 'ShowAlways',\n ONLY_MOST_IMPORTANT = 'OnlyMostImportant',\n}\n\nexport interface IssueCounterData {\n clickHandler?: () => void;\n tooltipCallback?: () => void;\n leadingText?: string;\n displayMode?: DisplayMode;\n issuesManager: IssuesManager.IssuesManager.IssuesManager;\n throttlerTimeout?: number;\n accessibleName?: string;\n compact?: boolean;\n}\n\nconst listFormat = new Intl.ListFormat(navigator.language, {type: 'unit', style: 'short'});\n\nexport function getIssueCountsEnumeration(\n issuesManager: IssuesManager.IssuesManager.IssuesManager, omitEmpty: boolean = true): string {\n const counts: [number, number, number] = [\n issuesManager.numberOfIssues(IssuesManager.Issue.IssueKind.PAGE_ERROR),\n issuesManager.numberOfIssues(IssuesManager.Issue.IssueKind.BREAKING_CHANGE),\n issuesManager.numberOfIssues(IssuesManager.Issue.IssueKind.IMPROVEMENT),\n ];\n const phrases = [\n i18nString(UIStrings.pageErrors, {issueCount: counts[0]}),\n i18nString(UIStrings.breakingChanges, {issueCount: counts[1]}),\n i18nString(UIStrings.possibleImprovements, {issueCount: counts[2]}),\n ];\n return listFormat.format(phrases.filter((_, i) => omitEmpty ? counts[i] > 0 : true));\n}\n\nexport class IssueCounter extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-issue-counter`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n #clickHandler: undefined|(() => void) = undefined;\n #tooltipCallback: undefined|(() => void) = undefined;\n #leadingText: string = '';\n #throttler: undefined|Common.Throttler.Throttler;\n #counts: [number, number, number] = [0, 0, 0];\n #displayMode: DisplayMode = DisplayMode.OMIT_EMPTY;\n #issuesManager: IssuesManager.IssuesManager.IssuesManager|undefined = undefined;\n #accessibleName: string|undefined = undefined;\n #throttlerTimeout: number|undefined;\n #compact = false;\n\n scheduleUpdate(): void {\n if (this.#throttler) {\n void this.#throttler.schedule(async () => this.#render());\n } else {\n this.#render();\n }\n }\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [issueCounterStyles];\n }\n\n set data(data: IssueCounterData) {\n this.#clickHandler = data.clickHandler;\n this.#leadingText = data.leadingText ?? '';\n this.#tooltipCallback = data.tooltipCallback;\n this.#displayMode = data.displayMode ?? DisplayMode.OMIT_EMPTY;\n this.#accessibleName = data.accessibleName;\n this.#throttlerTimeout = data.throttlerTimeout;\n this.#compact = Boolean(data.compact);\n if (this.#issuesManager !== data.issuesManager) {\n this.#issuesManager?.removeEventListener(\n IssuesManager.IssuesManager.Events.ISSUES_COUNT_UPDATED, this.scheduleUpdate, this);\n this.#issuesManager = data.issuesManager;\n this.#issuesManager.addEventListener(\n IssuesManager.IssuesManager.Events.ISSUES_COUNT_UPDATED, this.scheduleUpdate, this);\n }\n if (data.throttlerTimeout !== 0) {\n this.#throttler = new Common.Throttler.Throttler(data.throttlerTimeout ?? 100);\n } else {\n this.#throttler = undefined;\n }\n this.scheduleUpdate();\n }\n\n get data(): IssueCounterData {\n return {\n clickHandler: this.#clickHandler,\n leadingText: this.#leadingText,\n tooltipCallback: this.#tooltipCallback,\n displayMode: this.#displayMode,\n accessibleName: this.#accessibleName,\n throttlerTimeout: this.#throttlerTimeout,\n compact: this.#compact,\n issuesManager: this.#issuesManager as IssuesManager.IssuesManager.IssuesManager,\n };\n }\n\n #render(): void {\n if (!this.#issuesManager) {\n return;\n }\n this.#counts = [\n this.#issuesManager.numberOfIssues(IssuesManager.Issue.IssueKind.PAGE_ERROR),\n this.#issuesManager.numberOfIssues(IssuesManager.Issue.IssueKind.BREAKING_CHANGE),\n this.#issuesManager.numberOfIssues(IssuesManager.Issue.IssueKind.IMPROVEMENT),\n ];\n const importance = [\n IssuesManager.Issue.IssueKind.PAGE_ERROR,\n IssuesManager.Issue.IssueKind.BREAKING_CHANGE,\n IssuesManager.Issue.IssueKind.IMPROVEMENT,\n ];\n const mostImportant = importance[this.#counts.findIndex(x => x > 0) ?? 2];\n\n const countToString = (kind: IssuesManager.Issue.IssueKind, count: number): string|undefined => {\n switch (this.#displayMode) {\n case DisplayMode.OMIT_EMPTY:\n return count > 0 ? `${count}` : undefined;\n case DisplayMode.SHOW_ALWAYS:\n return `${count}`;\n case DisplayMode.ONLY_MOST_IMPORTANT:\n return kind === mostImportant ? `${count}` : undefined;\n }\n };\n const iconSize = '2ex';\n const data: IconButton.IconButton.IconButtonData = {\n groups: [\n {\n ...toIconGroup(getIssueKindIconData(IssuesManager.Issue.IssueKind.PAGE_ERROR), iconSize),\n text: countToString(IssuesManager.Issue.IssueKind.PAGE_ERROR, this.#counts[0]),\n },\n {\n ...toIconGroup(getIssueKindIconData(IssuesManager.Issue.IssueKind.BREAKING_CHANGE), iconSize),\n text: countToString(IssuesManager.Issue.IssueKind.BREAKING_CHANGE, this.#counts[1]),\n },\n {\n ...toIconGroup(getIssueKindIconData(IssuesManager.Issue.IssueKind.IMPROVEMENT), iconSize),\n text: countToString(IssuesManager.Issue.IssueKind.IMPROVEMENT, this.#counts[2]),\n },\n ],\n clickHandler: this.#clickHandler,\n leadingText: this.#leadingText,\n accessibleName: this.#accessibleName,\n compact: this.#compact,\n };\n LitHtml.render(\n LitHtml.html`\n \n `,\n this.#shadow, {host: this});\n this.#tooltipCallback?.();\n }\n}\n\ncustomElements.define('devtools-issue-counter', IssueCounter);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-issue-counter': IssueCounter;\n }\n}\n"]} \ No newline at end of file diff --git a/public/ui/components/markdown_view/MarkdownView.d.ts b/public/ui/components/markdown_view/MarkdownView.d.ts index 213ac520d..4ca23736b 100644 --- a/public/ui/components/markdown_view/MarkdownView.d.ts +++ b/public/ui/components/markdown_view/MarkdownView.d.ts @@ -32,7 +32,7 @@ export declare class MarkdownLitRenderer { renderToken(token: Marked.Marked.Token): LitHtml.TemplateResult; } /** - * Renderer used in Console Insights and Freestyler for the text generated by an LLM. + * Renderer used in Console Insights and AI assistant for the text generated by an LLM. */ export declare class MarkdownInsightRenderer extends MarkdownLitRenderer { renderToken(token: Marked.Marked.Token): LitHtml.TemplateResult; diff --git a/public/ui/components/markdown_view/MarkdownView.js b/public/ui/components/markdown_view/MarkdownView.js index 24d97e367..d3420dabe 100644 --- a/public/ui/components/markdown_view/MarkdownView.js +++ b/public/ui/components/markdown_view/MarkdownView.js @@ -140,7 +140,7 @@ export class MarkdownLitRenderer { } } /** - * Renderer used in Console Insights and Freestyler for the text generated by an LLM. + * Renderer used in Console Insights and AI assistant for the text generated by an LLM. */ export class MarkdownInsightRenderer extends MarkdownLitRenderer { renderToken(token) { diff --git a/public/ui/components/markdown_view/MarkdownView.js.map b/public/ui/components/markdown_view/MarkdownView.js.map index 5b3cdfb2f..3185892bd 100644 --- a/public/ui/components/markdown_view/MarkdownView.js.map +++ b/public/ui/components/markdown_view/MarkdownView.js.map @@ -1 +1 @@ -{"version":3,"file":"MarkdownView.js","sourceRoot":"","sources":["../../../../../../../front_end/ui/components/markdown_view/MarkdownView.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Marked from '../../../third_party/marked/marked.js';\nimport * as UI from '../../legacy/legacy.js';\nimport * as LitHtml from '../../lit-html/lit-html.js';\n\nimport {CodeBlock} from './CodeBlock.js';\nimport {MarkdownImage, type MarkdownImageData} from './MarkdownImage.js';\nimport {MarkdownLink, type MarkdownLinkData} from './MarkdownLink.js';\nimport markdownViewStyles from './markdownView.css.js';\n\nconst html = LitHtml.html;\nconst render = LitHtml.render;\n\nexport interface MarkdownViewData {\n tokens: Marked.Marked.Token[];\n renderer?: MarkdownLitRenderer;\n}\n\nexport class MarkdownView extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-markdown-view`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n\n #tokenData: readonly Marked.Marked.Token[] = [];\n #renderer = new MarkdownLitRenderer();\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [markdownViewStyles];\n }\n\n set data(data: MarkdownViewData) {\n this.#tokenData = data.tokens;\n if (data.renderer) {\n this.#renderer = data.renderer;\n }\n this.#update();\n }\n\n #update(): void {\n this.#render();\n }\n\n #render(): void {\n // Disabled until https://crbug.com/1079231 is fixed.\n // clang-format off\n render(html`\n
    \n ${this.#tokenData.map(token => this.#renderer.renderToken(token))}\n
    \n `, this.#shadow, {host: this});\n // clang-format on\n }\n}\n\ncustomElements.define('devtools-markdown-view', MarkdownView);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-markdown-view': MarkdownView;\n }\n}\n\n/**\n * Default renderer is used for the IssuesPanel and allows only well-known images and links to be embedded.\n */\nexport class MarkdownLitRenderer {\n renderChildTokens(token: Marked.Marked.Token): LitHtml.TemplateResult[] {\n if ('tokens' in token && token.tokens) {\n return token.tokens.map(token => this.renderToken(token));\n }\n throw new Error('Tokens not found');\n }\n\n /**\n * Unescape will get rid of the escaping done by Marked to avoid double escaping due to escaping it also with Lit-html.\n * Table taken from: front_end/third_party/marked/package/src/helpers.js\n */\n unescape(text: string): string {\n const escapeReplacements = new Map([\n ['&', '&'],\n ['<', '<'],\n ['>', '>'],\n ['"', '\"'],\n [''', '\\''],\n ]);\n return text.replace(/&(amp|lt|gt|quot|#39);/g, (matchedString: string) => {\n const replacement = escapeReplacements.get(matchedString);\n return replacement ? replacement : matchedString;\n });\n }\n\n renderText(token: Marked.Marked.Token): LitHtml.TemplateResult {\n if ('tokens' in token && token.tokens) {\n return html`${this.renderChildTokens(token)}`;\n }\n // Due to unescaping, unescaped html entities (see escapeReplacements' keys) will be rendered\n // as their corresponding symbol while the rest will be rendered as verbatim.\n // Marked's escape function can be found in front_end/third_party/marked/package/src/helpers.js\n return html`${this.unescape('text' in token ? token.text : '')}`;\n }\n\n renderHeading(heading: Marked.Marked.Tokens.Heading): LitHtml.TemplateResult {\n switch (heading.depth) {\n case 1:\n return html`

    ${this.renderText(heading)}

    `;\n case 2:\n return html`

    ${this.renderText(heading)}

    `;\n case 3:\n return html`

    ${this.renderText(heading)}

    `;\n case 4:\n return html`

    ${this.renderText(heading)}

    `;\n case 5:\n return html`
    ${this.renderText(heading)}
    `;\n default:\n return html`
    ${this.renderText(heading)}
    `;\n }\n }\n\n renderCodeBlock(token: Marked.Marked.Tokens.Code): LitHtml.TemplateResult {\n // clang-format off\n return html`<${CodeBlock.litTagName}\n .code=${this.unescape(token.text)}\n .codeLang=${token.lang}>\n `;\n // clang-format one\n }\n\n templateForToken(token: Marked.Marked.MarkedToken): LitHtml.TemplateResult|null {\n switch (token.type) {\n case 'paragraph':\n return html`

    ${this.renderChildTokens(token)}`;\n case 'list':\n return html`

      ${token.items.map(token => {\n return this.renderToken(token);\n })}
    `;\n case 'list_item':\n return html`
  • ${this.renderChildTokens(token)}`;\n case 'text':\n return this.renderText(token);\n case 'codespan':\n return html`${this.unescape(token.text)}`;\n case 'code':\n return this.renderCodeBlock(token);\n case 'space':\n return html``;\n case 'link':\n return html`<${MarkdownLink.litTagName} .data=${{key: token.href, title: token.text} as MarkdownLinkData}>`;\n case 'image':\n return html`<${MarkdownImage.litTagName} .data=${{key: token.href, title: token.text} as MarkdownImageData}>`;\n case 'heading':\n return this.renderHeading(token);\n case 'strong':\n return html`${this.renderText(token)}`;\n case 'em':\n return html`${this.renderText(token)}`;\n default:\n return null;\n }\n }\n\n renderToken(token: Marked.Marked.Token): LitHtml.TemplateResult {\n const template = this.templateForToken(token as Marked.Marked.MarkedToken);\n if (template === null) {\n throw new Error(`Markdown token type '${token.type}' not supported.`);\n }\n return template;\n }\n}\n\n/**\n * Renderer used in Console Insights and Freestyler for the text generated by an LLM.\n */\nexport class MarkdownInsightRenderer extends MarkdownLitRenderer {\n override renderToken(token: Marked.Marked.Token): LitHtml.TemplateResult {\n const template = this.templateForToken(token);\n if (template === null) {\n return LitHtml.html`${token.raw}`;\n }\n return template;\n }\n\n override templateForToken(token: Marked.Marked.Token): LitHtml.TemplateResult|null {\n switch (token.type) {\n case 'heading':\n return html`${this.renderText(token)}`;\n case 'link':\n case 'image':\n return LitHtml.html`${\n UI.XLink.XLink.create(token.href, token.text, undefined, undefined, 'link-in-explanation')}`;\n case 'code':\n return LitHtml.html`<${CodeBlock.litTagName}\n .code=${this.unescape(token.text)}\n .codeLang=${token.lang}\n .displayNotice=${true}>\n `;\n }\n return super.templateForToken(token as Marked.Marked.MarkedToken);\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"MarkdownView.js","sourceRoot":"","sources":["../../../../../../../front_end/ui/components/markdown_view/MarkdownView.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2020 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport type * as Marked from '../../../third_party/marked/marked.js';\nimport * as UI from '../../legacy/legacy.js';\nimport * as LitHtml from '../../lit-html/lit-html.js';\n\nimport {CodeBlock} from './CodeBlock.js';\nimport {MarkdownImage, type MarkdownImageData} from './MarkdownImage.js';\nimport {MarkdownLink, type MarkdownLinkData} from './MarkdownLink.js';\nimport markdownViewStyles from './markdownView.css.js';\n\nconst html = LitHtml.html;\nconst render = LitHtml.render;\n\nexport interface MarkdownViewData {\n tokens: Marked.Marked.Token[];\n renderer?: MarkdownLitRenderer;\n}\n\nexport class MarkdownView extends HTMLElement {\n static readonly litTagName = LitHtml.literal`devtools-markdown-view`;\n readonly #shadow = this.attachShadow({mode: 'open'});\n\n #tokenData: readonly Marked.Marked.Token[] = [];\n #renderer = new MarkdownLitRenderer();\n\n connectedCallback(): void {\n this.#shadow.adoptedStyleSheets = [markdownViewStyles];\n }\n\n set data(data: MarkdownViewData) {\n this.#tokenData = data.tokens;\n if (data.renderer) {\n this.#renderer = data.renderer;\n }\n this.#update();\n }\n\n #update(): void {\n this.#render();\n }\n\n #render(): void {\n // Disabled until https://crbug.com/1079231 is fixed.\n // clang-format off\n render(html`\n
    \n ${this.#tokenData.map(token => this.#renderer.renderToken(token))}\n
    \n `, this.#shadow, {host: this});\n // clang-format on\n }\n}\n\ncustomElements.define('devtools-markdown-view', MarkdownView);\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'devtools-markdown-view': MarkdownView;\n }\n}\n\n/**\n * Default renderer is used for the IssuesPanel and allows only well-known images and links to be embedded.\n */\nexport class MarkdownLitRenderer {\n renderChildTokens(token: Marked.Marked.Token): LitHtml.TemplateResult[] {\n if ('tokens' in token && token.tokens) {\n return token.tokens.map(token => this.renderToken(token));\n }\n throw new Error('Tokens not found');\n }\n\n /**\n * Unescape will get rid of the escaping done by Marked to avoid double escaping due to escaping it also with Lit-html.\n * Table taken from: front_end/third_party/marked/package/src/helpers.js\n */\n unescape(text: string): string {\n const escapeReplacements = new Map([\n ['&', '&'],\n ['<', '<'],\n ['>', '>'],\n ['"', '\"'],\n [''', '\\''],\n ]);\n return text.replace(/&(amp|lt|gt|quot|#39);/g, (matchedString: string) => {\n const replacement = escapeReplacements.get(matchedString);\n return replacement ? replacement : matchedString;\n });\n }\n\n renderText(token: Marked.Marked.Token): LitHtml.TemplateResult {\n if ('tokens' in token && token.tokens) {\n return html`${this.renderChildTokens(token)}`;\n }\n // Due to unescaping, unescaped html entities (see escapeReplacements' keys) will be rendered\n // as their corresponding symbol while the rest will be rendered as verbatim.\n // Marked's escape function can be found in front_end/third_party/marked/package/src/helpers.js\n return html`${this.unescape('text' in token ? token.text : '')}`;\n }\n\n renderHeading(heading: Marked.Marked.Tokens.Heading): LitHtml.TemplateResult {\n switch (heading.depth) {\n case 1:\n return html`

    ${this.renderText(heading)}

    `;\n case 2:\n return html`

    ${this.renderText(heading)}

    `;\n case 3:\n return html`

    ${this.renderText(heading)}

    `;\n case 4:\n return html`

    ${this.renderText(heading)}

    `;\n case 5:\n return html`
    ${this.renderText(heading)}
    `;\n default:\n return html`
    ${this.renderText(heading)}
    `;\n }\n }\n\n renderCodeBlock(token: Marked.Marked.Tokens.Code): LitHtml.TemplateResult {\n // clang-format off\n return html`<${CodeBlock.litTagName}\n .code=${this.unescape(token.text)}\n .codeLang=${token.lang}>\n `;\n // clang-format one\n }\n\n templateForToken(token: Marked.Marked.MarkedToken): LitHtml.TemplateResult|null {\n switch (token.type) {\n case 'paragraph':\n return html`

    ${this.renderChildTokens(token)}`;\n case 'list':\n return html`

      ${token.items.map(token => {\n return this.renderToken(token);\n })}
    `;\n case 'list_item':\n return html`
  • ${this.renderChildTokens(token)}`;\n case 'text':\n return this.renderText(token);\n case 'codespan':\n return html`${this.unescape(token.text)}`;\n case 'code':\n return this.renderCodeBlock(token);\n case 'space':\n return html``;\n case 'link':\n return html`<${MarkdownLink.litTagName} .data=${{key: token.href, title: token.text} as MarkdownLinkData}>`;\n case 'image':\n return html`<${MarkdownImage.litTagName} .data=${{key: token.href, title: token.text} as MarkdownImageData}>`;\n case 'heading':\n return this.renderHeading(token);\n case 'strong':\n return html`${this.renderText(token)}`;\n case 'em':\n return html`${this.renderText(token)}`;\n default:\n return null;\n }\n }\n\n renderToken(token: Marked.Marked.Token): LitHtml.TemplateResult {\n const template = this.templateForToken(token as Marked.Marked.MarkedToken);\n if (template === null) {\n throw new Error(`Markdown token type '${token.type}' not supported.`);\n }\n return template;\n }\n}\n\n/**\n * Renderer used in Console Insights and AI assistant for the text generated by an LLM.\n */\nexport class MarkdownInsightRenderer extends MarkdownLitRenderer {\n override renderToken(token: Marked.Marked.Token): LitHtml.TemplateResult {\n const template = this.templateForToken(token);\n if (template === null) {\n return LitHtml.html`${token.raw}`;\n }\n return template;\n }\n\n override templateForToken(token: Marked.Marked.Token): LitHtml.TemplateResult|null {\n switch (token.type) {\n case 'heading':\n return html`${this.renderText(token)}`;\n case 'link':\n case 'image':\n return LitHtml.html`${\n UI.XLink.XLink.create(token.href, token.text, undefined, undefined, 'link-in-explanation')}`;\n case 'code':\n return LitHtml.html`<${CodeBlock.litTagName}\n .code=${this.unescape(token.text)}\n .codeLang=${token.lang}\n .displayNotice=${true}>\n `;\n }\n return super.templateForToken(token as Marked.Marked.MarkedToken);\n }\n}\n"]} \ No newline at end of file diff --git a/public/ui/components/markdown_view/markdownView.css.js b/public/ui/components/markdown_view/markdownView.css.js index 25adbad1d..cee2a4f99 100644 --- a/public/ui/components/markdown_view/markdownView.css.js +++ b/public/ui/components/markdown_view/markdownView.css.js @@ -30,7 +30,7 @@ styles.replaceSync( .message ul { list-style-type: none; - padding-inline-start: 1em; + padding-inline-start: var(--sys-size-8); } .message ul ul { diff --git a/public/ui/legacy/components/perf_ui/FilmStripView.d.ts b/public/ui/legacy/components/perf_ui/FilmStripView.d.ts index a5b54adea..5e25a119c 100644 --- a/public/ui/legacy/components/perf_ui/FilmStripView.d.ts +++ b/public/ui/legacy/components/perf_ui/FilmStripView.d.ts @@ -1,5 +1,5 @@ import * as Common from '../../../../core/common/common.js'; -import * as TraceEngine from '../../../../models/trace/trace.js'; +import * as Trace from '../../../../models/trace/trace.js'; import * as UI from '../../legacy.js'; declare const FilmStripView_base: (new (...args: any[]) => { "__#13@#events": Common.ObjectWrapper.ObjectWrapper; @@ -15,8 +15,8 @@ export declare class FilmStripView extends FilmStripView_base { private zeroTime; constructor(); static setImageData(imageElement: HTMLImageElement, dataUri: string | null): void; - setModel(filmStrip: TraceEngine.Extras.FilmStrip.Data): void; - createFrameElement(frame: TraceEngine.Extras.FilmStrip.Frame): HTMLButtonElement; + setModel(filmStrip: Trace.Extras.FilmStrip.Data): void; + createFrameElement(frame: Trace.Extras.FilmStrip.Frame): HTMLButtonElement; update(): void; private onMouseEvent; private onDoubleClick; @@ -39,7 +39,7 @@ export declare class Dialog { private readonly widget; private index; private dialog; - static fromFilmStrip(filmStrip: TraceEngine.Extras.FilmStrip.Data, selectedFrameIndex: number): Dialog; + static fromFilmStrip(filmStrip: Trace.Extras.FilmStrip.Data, selectedFrameIndex: number): Dialog; private constructor(); hide(): void; private resize; diff --git a/public/ui/legacy/components/perf_ui/FilmStripView.js b/public/ui/legacy/components/perf_ui/FilmStripView.js index 66b402fab..99a1a5fc5 100644 --- a/public/ui/legacy/components/perf_ui/FilmStripView.js +++ b/public/ui/legacy/components/perf_ui/FilmStripView.js @@ -4,7 +4,7 @@ import * as Common from '../../../../core/common/common.js'; import * as Host from '../../../../core/host/host.js'; import * as i18n from '../../../../core/i18n/i18n.js'; -import * as TraceEngine from '../../../../models/trace/trace.js'; +import * as Trace from '../../../../models/trace/trace.js'; import * as VisualLogging from '../../../visual_logging/visual_logging.js'; import * as UI from '../../legacy.js'; import filmStripViewStyles from './filmStripView.css.legacy.js'; @@ -35,7 +35,7 @@ const str_ = i18n.i18n.registerUIStrings('ui/legacy/components/perf_ui/FilmStrip const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_); export class FilmStripView extends Common.ObjectWrapper.eventMixin(UI.Widget.HBox) { statusLabel; - zeroTime = TraceEngine.Types.Timing.MilliSeconds(0); + zeroTime = Trace.Types.Timing.MilliSeconds(0); #filmStrip = null; constructor() { super(true); @@ -51,7 +51,7 @@ export class FilmStripView extends Common.ObjectWrapper.eventMixin(UI.Widget.HBo } setModel(filmStrip) { this.#filmStrip = filmStrip; - this.zeroTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(filmStrip.zeroTime); + this.zeroTime = Trace.Helpers.Timing.microSecondsToMilliseconds(filmStrip.zeroTime); if (!this.#filmStrip.frames.length) { this.reset(); return; @@ -59,7 +59,7 @@ export class FilmStripView extends Common.ObjectWrapper.eventMixin(UI.Widget.HBo this.update(); } createFrameElement(frame) { - const time = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.screenshotEvent.ts); + const time = Trace.Helpers.Timing.microSecondsToMilliseconds(frame.screenshotEvent.ts); const frameTime = i18n.TimeUtilities.millisToString(time - this.zeroTime); const element = document.createElement('button'); element.classList.add('frame'); @@ -103,7 +103,7 @@ export class FilmStripView extends Common.ObjectWrapper.eventMixin(UI.Widget.HBo Dialog.fromFilmStrip(this.#filmStrip, filmStripFrame.index); } reset() { - this.zeroTime = TraceEngine.Types.Timing.MilliSeconds(0); + this.zeroTime = Trace.Types.Timing.MilliSeconds(0); this.contentElement.removeChildren(); this.contentElement.appendChild(this.statusLabel); } @@ -119,10 +119,10 @@ export class Dialog { #data; static fromFilmStrip(filmStrip, selectedFrameIndex) { const data = { - source: 'TraceEngine', + source: 'Trace', frames: filmStrip.frames, index: selectedFrameIndex, - zeroTime: TraceEngine.Helpers.Timing.microSecondsToMilliseconds(filmStrip.zeroTime), + zeroTime: Trace.Helpers.Timing.microSecondsToMilliseconds(filmStrip.zeroTime), }; return new Dialog(data); } @@ -220,7 +220,7 @@ export class Dialog { } render() { const frame = this.#data.frames[this.index]; - const timestamp = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.screenshotEvent.ts); + const timestamp = Trace.Helpers.Timing.microSecondsToMilliseconds(frame.screenshotEvent.ts); this.fragment.$('time').textContent = i18n.TimeUtilities.millisToString(timestamp - this.#zeroTime()); const image = this.fragment.$('image'); image.setAttribute('data-frame-index', this.index.toString()); diff --git a/public/ui/legacy/components/perf_ui/FilmStripView.js.map b/public/ui/legacy/components/perf_ui/FilmStripView.js.map index a79046ffe..86064e46d 100644 --- a/public/ui/legacy/components/perf_ui/FilmStripView.js.map +++ b/public/ui/legacy/components/perf_ui/FilmStripView.js.map @@ -1 +1 @@ -{"version":3,"file":"FilmStripView.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/legacy/components/perf_ui/FilmStripView.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2015 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../../../core/common/common.js';\nimport * as Host from '../../../../core/host/host.js';\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport * as TraceEngine from '../../../../models/trace/trace.js';\nimport * as VisualLogging from '../../../visual_logging/visual_logging.js';\nimport * as UI from '../../legacy.js';\n\nimport filmStripViewStyles from './filmStripView.css.legacy.js';\n\nconst UIStrings = {\n /**\n *@description Element title in Film Strip View of the Performance panel\n */\n doubleclickToZoomImageClickTo: 'Doubleclick to zoom image. Click to view preceding requests.',\n /**\n *@description Aria label for captured screenshots in network panel.\n *@example {3ms} PH1\n */\n screenshotForSSelectToView: 'Screenshot for {PH1} - select to view preceding requests.',\n /**\n *@description Text for one or a group of screenshots\n */\n screenshot: 'Screenshot',\n /**\n *@description Prev button title in Film Strip View of the Performance panel\n */\n previousFrame: 'Previous frame',\n /**\n *@description Next button title in Film Strip View of the Performance panel\n */\n nextFrame: 'Next frame',\n};\nconst str_ = i18n.i18n.registerUIStrings('ui/legacy/components/perf_ui/FilmStripView.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nexport class FilmStripView extends Common.ObjectWrapper.eventMixin(UI.Widget.HBox) {\n private statusLabel: HTMLElement;\n private zeroTime: TraceEngine.Types.Timing.MilliSeconds = TraceEngine.Types.Timing.MilliSeconds(0);\n #filmStrip: TraceEngine.Extras.FilmStrip.Data|null = null;\n\n constructor() {\n super(true);\n this.registerRequiredCSS(filmStripViewStyles);\n this.contentElement.classList.add('film-strip-view');\n this.statusLabel = this.contentElement.createChild('div', 'label');\n this.reset();\n }\n\n static setImageData(imageElement: HTMLImageElement, dataUri: string|null): void {\n if (dataUri) {\n imageElement.src = dataUri;\n }\n }\n\n setModel(filmStrip: TraceEngine.Extras.FilmStrip.Data): void {\n this.#filmStrip = filmStrip;\n this.zeroTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(filmStrip.zeroTime);\n\n if (!this.#filmStrip.frames.length) {\n this.reset();\n return;\n }\n this.update();\n }\n\n createFrameElement(frame: TraceEngine.Extras.FilmStrip.Frame): HTMLButtonElement {\n const time = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.screenshotEvent.ts);\n const frameTime = i18n.TimeUtilities.millisToString(time - this.zeroTime);\n const element = document.createElement('button');\n element.classList.add('frame');\n UI.Tooltip.Tooltip.install(element, i18nString(UIStrings.doubleclickToZoomImageClickTo));\n element.createChild('div', 'time').textContent = frameTime;\n element.tabIndex = 0;\n element.setAttribute('jslog', `${VisualLogging.preview('film-strip').track({click: true, dblclick: true})}`);\n element.setAttribute('aria-label', i18nString(UIStrings.screenshotForSSelectToView, {PH1: frameTime}));\n UI.ARIAUtils.markAsButton(element);\n const imageElement = (element.createChild('div', 'thumbnail').createChild('img') as HTMLImageElement);\n imageElement.alt = i18nString(UIStrings.screenshot);\n element.addEventListener('mousedown', this.onMouseEvent.bind(this, Events.FRAME_SELECTED, time), false);\n element.addEventListener('mouseenter', this.onMouseEvent.bind(this, Events.FRAME_ENTER, time), false);\n element.addEventListener('mouseout', this.onMouseEvent.bind(this, Events.FRAME_EXIT, time), false);\n element.addEventListener('dblclick', this.onDoubleClick.bind(this, frame), false);\n element.addEventListener('focusin', this.onMouseEvent.bind(this, Events.FRAME_ENTER, time), false);\n element.addEventListener('focusout', this.onMouseEvent.bind(this, Events.FRAME_EXIT, time), false);\n\n FilmStripView.setImageData(imageElement, frame.screenshotEvent.args.dataUri);\n return element;\n }\n\n update(): void {\n const frames = this.#filmStrip?.frames;\n if (!frames || frames.length < 1) {\n return;\n }\n\n const frameElements = frames.map(frame => this.createFrameElement(frame));\n this.contentElement.removeChildren();\n for (const element of frameElements) {\n this.contentElement.appendChild(element);\n }\n }\n\n private onMouseEvent(eventName: string|symbol, timestamp: number): void {\n // TODO(crbug.com/1228674): Use type-safe event dispatch and remove .\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.dispatchEventToListeners(eventName, timestamp);\n }\n\n private onDoubleClick(filmStripFrame: TraceEngine.Extras.FilmStrip.Frame): void {\n if (!this.#filmStrip) {\n return;\n }\n Dialog.fromFilmStrip(this.#filmStrip, filmStripFrame.index);\n }\n\n reset(): void {\n this.zeroTime = TraceEngine.Types.Timing.MilliSeconds(0);\n this.contentElement.removeChildren();\n this.contentElement.appendChild(this.statusLabel);\n }\n\n setStatusText(text: string): void {\n this.statusLabel.textContent = text;\n }\n}\n\nexport const enum Events {\n FRAME_SELECTED = 'FrameSelected',\n FRAME_ENTER = 'FrameEnter',\n FRAME_EXIT = 'FrameExit',\n}\n\nexport type EventTypes = {\n [Events.FRAME_SELECTED]: number,\n [Events.FRAME_ENTER]: number,\n [Events.FRAME_EXIT]: number,\n};\n\ninterface DialogTraceEngineData {\n source: 'TraceEngine';\n index: number;\n zeroTime: TraceEngine.Types.Timing.MilliSeconds;\n frames: readonly TraceEngine.Extras.FilmStrip.Frame[];\n}\n\nexport class Dialog {\n private fragment: UI.Fragment.Fragment;\n private readonly widget: UI.XWidget.XWidget;\n private index: number;\n private dialog: UI.Dialog.Dialog|null = null;\n\n #data: DialogTraceEngineData;\n\n static fromFilmStrip(filmStrip: TraceEngine.Extras.FilmStrip.Data, selectedFrameIndex: number): Dialog {\n const data: DialogTraceEngineData = {\n source: 'TraceEngine',\n frames: filmStrip.frames,\n index: selectedFrameIndex,\n zeroTime: TraceEngine.Helpers.Timing.microSecondsToMilliseconds(filmStrip.zeroTime),\n };\n return new Dialog(data);\n }\n\n private constructor(data: DialogTraceEngineData) {\n this.#data = data;\n this.index = data.index;\n const prevButton = UI.UIUtils.createTextButton('\\u25C0', this.onPrevFrame.bind(this));\n UI.Tooltip.Tooltip.install(prevButton, i18nString(UIStrings.previousFrame));\n const nextButton = UI.UIUtils.createTextButton('\\u25B6', this.onNextFrame.bind(this));\n UI.Tooltip.Tooltip.install(nextButton, i18nString(UIStrings.nextFrame));\n this.fragment = UI.Fragment.Fragment.build`\n \n \n \n \n \n ${prevButton}\n \n ${nextButton}\n \n \n `;\n this.widget = (this.fragment.element() as UI.XWidget.XWidget);\n (this.widget as HTMLElement).tabIndex = 0;\n this.widget.addEventListener('keydown', this.keyDown.bind(this), false);\n this.dialog = null;\n\n void this.render();\n }\n\n hide(): void {\n if (this.dialog) {\n this.dialog.hide();\n }\n }\n\n #framesCount(): number {\n return this.#data.frames.length;\n }\n\n #zeroTime(): TraceEngine.Types.Timing.MilliSeconds {\n return this.#data.zeroTime;\n }\n\n private resize(): void {\n if (!this.dialog) {\n this.dialog = new UI.Dialog.Dialog();\n this.dialog.contentElement.appendChild(this.widget);\n this.dialog.setDefaultFocusedElement(this.widget);\n this.dialog.show();\n }\n this.dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.MEASURE_CONTENT);\n }\n\n private keyDown(event: Event): void {\n const keyboardEvent = (event as KeyboardEvent);\n switch (keyboardEvent.key) {\n case 'ArrowLeft':\n if (Host.Platform.isMac() && keyboardEvent.metaKey) {\n this.onFirstFrame();\n } else {\n this.onPrevFrame();\n }\n break;\n\n case 'ArrowRight':\n if (Host.Platform.isMac() && keyboardEvent.metaKey) {\n this.onLastFrame();\n } else {\n this.onNextFrame();\n }\n break;\n\n case 'Home':\n this.onFirstFrame();\n break;\n\n case 'End':\n this.onLastFrame();\n break;\n }\n }\n\n private onPrevFrame(): void {\n if (this.index > 0) {\n --this.index;\n }\n void this.render();\n }\n\n private onNextFrame(): void {\n if (this.index < this.#framesCount() - 1) {\n ++this.index;\n }\n void this.render();\n }\n\n private onFirstFrame(): void {\n this.index = 0;\n void this.render();\n }\n\n private onLastFrame(): void {\n this.index = this.#framesCount() - 1;\n void this.render();\n }\n\n private render(): void {\n const frame = this.#data.frames[this.index];\n const timestamp = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(frame.screenshotEvent.ts);\n this.fragment.$('time').textContent = i18n.TimeUtilities.millisToString(timestamp - this.#zeroTime());\n const image = (this.fragment.$('image') as HTMLImageElement);\n image.setAttribute('data-frame-index', this.index.toString());\n FilmStripView.setImageData(image, frame.screenshotEvent.args.dataUri);\n this.resize();\n }\n}\n"]} \ No newline at end of file +{"version":3,"file":"FilmStripView.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/legacy/components/perf_ui/FilmStripView.ts"],"names":[],"mappings":"AAAA,4DAA4D;AAC5D,yEAAyE;AACzE,6BAA6B;AAE7B,OAAO,KAAK,MAAM,MAAM,mCAAmC,CAAC;AAC5D,OAAO,KAAK,IAAI,MAAM,+BAA+B,CAAC;AACtD,OAAO,KAAK,IAAI,MAAM,+BAA+B,CAAC;AACtD,OAAO,KAAK,KAAK,MAAM,mCAAmC,CAAC;AAC3D,OAAO,KAAK,aAAa,MAAM,2CAA2C,CAAC;AAC3E,OAAO,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAEtC,OAAO,mBAAmB,MAAM,+BAA+B,CAAC;AAEhE,MAAM,SAAS,GAAG;IAChB;;OAEG;IACH,6BAA6B,EAAE,8DAA8D;IAC7F;;;OAGG;IACH,0BAA0B,EAAE,2DAA2D;IACvF;;OAEG;IACH,UAAU,EAAE,YAAY;IACxB;;OAEG;IACH,aAAa,EAAE,gBAAgB;IAC/B;;OAEG;IACH,SAAS,EAAE,YAAY;CACxB,CAAC;AACF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,+CAA+C,EAAE,SAAS,CAAC,CAAC;AACrG,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;AACtE,MAAM,OAAO,aAAc,SAAQ,MAAM,CAAC,aAAa,CAAC,UAAU,CAAoC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC;IAC3G,WAAW,CAAc;IACzB,QAAQ,GAAoC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IACvF,UAAU,GAAqC,IAAI,CAAC;IAEpD;QACE,KAAK,CAAC,IAAI,CAAC,CAAC;QACZ,IAAI,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,CAAC;QAC9C,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QACrD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACnE,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IAED,MAAM,CAAC,YAAY,CAAC,YAA8B,EAAE,OAAoB;QACtE,IAAI,OAAO,EAAE,CAAC;YACZ,YAAY,CAAC,GAAG,GAAG,OAAO,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,QAAQ,CAAC,SAAsC;QAC7C,IAAI,CAAC,UAAU,GAAG,SAAS,CAAC;QAC5B,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAEpF,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACnC,IAAI,CAAC,KAAK,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QACD,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;IAED,kBAAkB,CAAC,KAAmC;QACpD,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,KAAK,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;QACvF,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC1E,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACjD,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC/B,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,SAAS,CAAC,6BAA6B,CAAC,CAAC,CAAC;QACzF,OAAO,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,WAAW,GAAG,SAAS,CAAC;QAC3D,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO,CAAC,YAAY,CAAC,OAAO,EAAE,GAAG,aAAa,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,EAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAC,CAAC,EAAE,CAAC,CAAC;QAC7G,OAAO,CAAC,YAAY,CAAC,YAAY,EAAE,UAAU,CAAC,SAAS,CAAC,0BAA0B,EAAE,EAAC,GAAG,EAAE,SAAS,EAAC,CAAC,CAAC,CAAC;QACvG,EAAE,CAAC,SAAS,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QACnC,MAAM,YAAY,GAAI,OAAO,CAAC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC,WAAW,CAAC,KAAK,CAAsB,CAAC;QACtG,YAAY,CAAC,GAAG,GAAG,UAAU,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;QACpD,OAAO,CAAC,gBAAgB,CAAC,WAAW,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,+CAAyB,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;QACxG,OAAO,CAAC,gBAAgB,CAAC,YAAY,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,yCAAsB,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;QACtG,OAAO,CAAC,gBAAgB,CAAC,UAAU,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,uCAAqB,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;QACnG,OAAO,CAAC,gBAAgB,CAAC,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;QAClF,OAAO,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,yCAAsB,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;QACnG,OAAO,CAAC,gBAAgB,CAAC,UAAU,EAAE,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,uCAAqB,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;QAEnG,aAAa,CAAC,YAAY,CAAC,YAAY,EAAE,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7E,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,MAAM;QACJ,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,MAAM,CAAC;QACvC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACjC,OAAO;QACT,CAAC;QAED,MAAM,aAAa,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC;QAC1E,IAAI,CAAC,cAAc,CAAC,cAAc,EAAE,CAAC;QACrC,KAAK,MAAM,OAAO,IAAI,aAAa,EAAE,CAAC;YACpC,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAC3C,CAAC;IACH,CAAC;IAEO,YAAY,CAAC,SAAwB,EAAE,SAAiB;QAC9D,0EAA0E;QAC1E,8DAA8D;QAC9D,IAAI,CAAC,wBAAwB,CAAM,SAAS,EAAE,SAAS,CAAC,CAAC;IAC3D,CAAC;IAEO,aAAa,CAAC,cAA4C;QAChE,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACrB,OAAO;QACT,CAAC;QACD,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,CAAC,KAAK,CAAC,CAAC;IAC9D,CAAC;IAED,KAAK;QACH,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACnD,IAAI,CAAC,cAAc,CAAC,cAAc,EAAE,CAAC;QACrC,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACpD,CAAC;IAED,aAAa,CAAC,IAAY;QACxB,IAAI,CAAC,WAAW,CAAC,WAAW,GAAG,IAAI,CAAC;IACtC,CAAC;CACF;AAqBD,MAAM,OAAO,MAAM;IACT,QAAQ,CAAuB;IACtB,MAAM,CAAqB;IACpC,KAAK,CAAS;IACd,MAAM,GAA0B,IAAI,CAAC;IAE7C,KAAK,CAAoB;IAEzB,MAAM,CAAC,aAAa,CAAC,SAAsC,EAAE,kBAA0B;QACrF,MAAM,IAAI,GAAsB;YAC9B,MAAM,EAAE,OAAO;YACf,MAAM,EAAE,SAAS,CAAC,MAAM;YACxB,KAAK,EAAE,kBAAkB;YACzB,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,SAAS,CAAC,QAAQ,CAAC;SAC9E,CAAC;QACF,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED,YAAoB,IAAuB;QACzC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACxB,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACtF,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,UAAU,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC;QAC5E,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACtF,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC;QACxE,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAA;;;;;;YAMlC,UAAU;;YAEV,UAAU;;;KAGjB,CAAC;QACF,IAAI,CAAC,MAAM,GAAI,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAyB,CAAC;QAC7D,IAAI,CAAC,MAAsB,CAAC,QAAQ,GAAG,CAAC,CAAC;QAC1C,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,CAAC,CAAC;QACxE,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QAEnB,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;IACrB,CAAC;IAED,IAAI;QACF,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChB,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACrB,CAAC;IACH,CAAC;IAED,YAAY;QACV,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;IAClC,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC;IAC7B,CAAC;IAEO,MAAM;QACZ,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,GAAG,IAAI,EAAE,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACrC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACpD,IAAI,CAAC,MAAM,CAAC,wBAAwB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAClD,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACrB,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,eAAe,kEAA2C,CAAC;IACzE,CAAC;IAEO,OAAO,CAAC,KAAY;QAC1B,MAAM,aAAa,GAAI,KAAuB,CAAC;QAC/C,QAAQ,aAAa,CAAC,GAAG,EAAE,CAAC;YAC1B,KAAK,WAAW;gBACd,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,aAAa,CAAC,OAAO,EAAE,CAAC;oBACnD,IAAI,CAAC,YAAY,EAAE,CAAC;gBACtB,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,WAAW,EAAE,CAAC;gBACrB,CAAC;gBACD,MAAM;YAER,KAAK,YAAY;gBACf,IAAI,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,aAAa,CAAC,OAAO,EAAE,CAAC;oBACnD,IAAI,CAAC,WAAW,EAAE,CAAC;gBACrB,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,WAAW,EAAE,CAAC;gBACrB,CAAC;gBACD,MAAM;YAER,KAAK,MAAM;gBACT,IAAI,CAAC,YAAY,EAAE,CAAC;gBACpB,MAAM;YAER,KAAK,KAAK;gBACR,IAAI,CAAC,WAAW,EAAE,CAAC;gBACnB,MAAM;QACV,CAAC;IACH,CAAC;IAEO,WAAW;QACjB,IAAI,IAAI,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;YACnB,EAAE,IAAI,CAAC,KAAK,CAAC;QACf,CAAC;QACD,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;IACrB,CAAC;IAEO,WAAW;QACjB,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE,GAAG,CAAC,EAAE,CAAC;YACzC,EAAE,IAAI,CAAC,KAAK,CAAC;QACf,CAAC;QACD,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;IACrB,CAAC;IAEO,YAAY;QAClB,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC;QACf,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;IACrB,CAAC;IAEO,WAAW;QACjB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;QACrC,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC;IACrB,CAAC;IAEO,MAAM;QACZ,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC5C,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,KAAK,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;QAC5F,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,WAAW,GAAG,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;QACtG,MAAM,KAAK,GAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAsB,CAAC;QAC7D,KAAK,CAAC,YAAY,CAAC,kBAAkB,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC9D,aAAa,CAAC,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACtE,IAAI,CAAC,MAAM,EAAE,CAAC;IAChB,CAAC;CACF","sourcesContent":["// Copyright 2015 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Common from '../../../../core/common/common.js';\nimport * as Host from '../../../../core/host/host.js';\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport * as Trace from '../../../../models/trace/trace.js';\nimport * as VisualLogging from '../../../visual_logging/visual_logging.js';\nimport * as UI from '../../legacy.js';\n\nimport filmStripViewStyles from './filmStripView.css.legacy.js';\n\nconst UIStrings = {\n /**\n *@description Element title in Film Strip View of the Performance panel\n */\n doubleclickToZoomImageClickTo: 'Doubleclick to zoom image. Click to view preceding requests.',\n /**\n *@description Aria label for captured screenshots in network panel.\n *@example {3ms} PH1\n */\n screenshotForSSelectToView: 'Screenshot for {PH1} - select to view preceding requests.',\n /**\n *@description Text for one or a group of screenshots\n */\n screenshot: 'Screenshot',\n /**\n *@description Prev button title in Film Strip View of the Performance panel\n */\n previousFrame: 'Previous frame',\n /**\n *@description Next button title in Film Strip View of the Performance panel\n */\n nextFrame: 'Next frame',\n};\nconst str_ = i18n.i18n.registerUIStrings('ui/legacy/components/perf_ui/FilmStripView.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\nexport class FilmStripView extends Common.ObjectWrapper.eventMixin(UI.Widget.HBox) {\n private statusLabel: HTMLElement;\n private zeroTime: Trace.Types.Timing.MilliSeconds = Trace.Types.Timing.MilliSeconds(0);\n #filmStrip: Trace.Extras.FilmStrip.Data|null = null;\n\n constructor() {\n super(true);\n this.registerRequiredCSS(filmStripViewStyles);\n this.contentElement.classList.add('film-strip-view');\n this.statusLabel = this.contentElement.createChild('div', 'label');\n this.reset();\n }\n\n static setImageData(imageElement: HTMLImageElement, dataUri: string|null): void {\n if (dataUri) {\n imageElement.src = dataUri;\n }\n }\n\n setModel(filmStrip: Trace.Extras.FilmStrip.Data): void {\n this.#filmStrip = filmStrip;\n this.zeroTime = Trace.Helpers.Timing.microSecondsToMilliseconds(filmStrip.zeroTime);\n\n if (!this.#filmStrip.frames.length) {\n this.reset();\n return;\n }\n this.update();\n }\n\n createFrameElement(frame: Trace.Extras.FilmStrip.Frame): HTMLButtonElement {\n const time = Trace.Helpers.Timing.microSecondsToMilliseconds(frame.screenshotEvent.ts);\n const frameTime = i18n.TimeUtilities.millisToString(time - this.zeroTime);\n const element = document.createElement('button');\n element.classList.add('frame');\n UI.Tooltip.Tooltip.install(element, i18nString(UIStrings.doubleclickToZoomImageClickTo));\n element.createChild('div', 'time').textContent = frameTime;\n element.tabIndex = 0;\n element.setAttribute('jslog', `${VisualLogging.preview('film-strip').track({click: true, dblclick: true})}`);\n element.setAttribute('aria-label', i18nString(UIStrings.screenshotForSSelectToView, {PH1: frameTime}));\n UI.ARIAUtils.markAsButton(element);\n const imageElement = (element.createChild('div', 'thumbnail').createChild('img') as HTMLImageElement);\n imageElement.alt = i18nString(UIStrings.screenshot);\n element.addEventListener('mousedown', this.onMouseEvent.bind(this, Events.FRAME_SELECTED, time), false);\n element.addEventListener('mouseenter', this.onMouseEvent.bind(this, Events.FRAME_ENTER, time), false);\n element.addEventListener('mouseout', this.onMouseEvent.bind(this, Events.FRAME_EXIT, time), false);\n element.addEventListener('dblclick', this.onDoubleClick.bind(this, frame), false);\n element.addEventListener('focusin', this.onMouseEvent.bind(this, Events.FRAME_ENTER, time), false);\n element.addEventListener('focusout', this.onMouseEvent.bind(this, Events.FRAME_EXIT, time), false);\n\n FilmStripView.setImageData(imageElement, frame.screenshotEvent.args.dataUri);\n return element;\n }\n\n update(): void {\n const frames = this.#filmStrip?.frames;\n if (!frames || frames.length < 1) {\n return;\n }\n\n const frameElements = frames.map(frame => this.createFrameElement(frame));\n this.contentElement.removeChildren();\n for (const element of frameElements) {\n this.contentElement.appendChild(element);\n }\n }\n\n private onMouseEvent(eventName: string|symbol, timestamp: number): void {\n // TODO(crbug.com/1228674): Use type-safe event dispatch and remove .\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.dispatchEventToListeners(eventName, timestamp);\n }\n\n private onDoubleClick(filmStripFrame: Trace.Extras.FilmStrip.Frame): void {\n if (!this.#filmStrip) {\n return;\n }\n Dialog.fromFilmStrip(this.#filmStrip, filmStripFrame.index);\n }\n\n reset(): void {\n this.zeroTime = Trace.Types.Timing.MilliSeconds(0);\n this.contentElement.removeChildren();\n this.contentElement.appendChild(this.statusLabel);\n }\n\n setStatusText(text: string): void {\n this.statusLabel.textContent = text;\n }\n}\n\nexport const enum Events {\n FRAME_SELECTED = 'FrameSelected',\n FRAME_ENTER = 'FrameEnter',\n FRAME_EXIT = 'FrameExit',\n}\n\nexport type EventTypes = {\n [Events.FRAME_SELECTED]: number,\n [Events.FRAME_ENTER]: number,\n [Events.FRAME_EXIT]: number,\n};\n\ninterface DialogParsedTrace {\n source: 'Trace';\n index: number;\n zeroTime: Trace.Types.Timing.MilliSeconds;\n frames: readonly Trace.Extras.FilmStrip.Frame[];\n}\n\nexport class Dialog {\n private fragment: UI.Fragment.Fragment;\n private readonly widget: UI.XWidget.XWidget;\n private index: number;\n private dialog: UI.Dialog.Dialog|null = null;\n\n #data: DialogParsedTrace;\n\n static fromFilmStrip(filmStrip: Trace.Extras.FilmStrip.Data, selectedFrameIndex: number): Dialog {\n const data: DialogParsedTrace = {\n source: 'Trace',\n frames: filmStrip.frames,\n index: selectedFrameIndex,\n zeroTime: Trace.Helpers.Timing.microSecondsToMilliseconds(filmStrip.zeroTime),\n };\n return new Dialog(data);\n }\n\n private constructor(data: DialogParsedTrace) {\n this.#data = data;\n this.index = data.index;\n const prevButton = UI.UIUtils.createTextButton('\\u25C0', this.onPrevFrame.bind(this));\n UI.Tooltip.Tooltip.install(prevButton, i18nString(UIStrings.previousFrame));\n const nextButton = UI.UIUtils.createTextButton('\\u25B6', this.onNextFrame.bind(this));\n UI.Tooltip.Tooltip.install(nextButton, i18nString(UIStrings.nextFrame));\n this.fragment = UI.Fragment.Fragment.build`\n \n \n \n \n \n ${prevButton}\n \n ${nextButton}\n \n \n `;\n this.widget = (this.fragment.element() as UI.XWidget.XWidget);\n (this.widget as HTMLElement).tabIndex = 0;\n this.widget.addEventListener('keydown', this.keyDown.bind(this), false);\n this.dialog = null;\n\n void this.render();\n }\n\n hide(): void {\n if (this.dialog) {\n this.dialog.hide();\n }\n }\n\n #framesCount(): number {\n return this.#data.frames.length;\n }\n\n #zeroTime(): Trace.Types.Timing.MilliSeconds {\n return this.#data.zeroTime;\n }\n\n private resize(): void {\n if (!this.dialog) {\n this.dialog = new UI.Dialog.Dialog();\n this.dialog.contentElement.appendChild(this.widget);\n this.dialog.setDefaultFocusedElement(this.widget);\n this.dialog.show();\n }\n this.dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.MEASURE_CONTENT);\n }\n\n private keyDown(event: Event): void {\n const keyboardEvent = (event as KeyboardEvent);\n switch (keyboardEvent.key) {\n case 'ArrowLeft':\n if (Host.Platform.isMac() && keyboardEvent.metaKey) {\n this.onFirstFrame();\n } else {\n this.onPrevFrame();\n }\n break;\n\n case 'ArrowRight':\n if (Host.Platform.isMac() && keyboardEvent.metaKey) {\n this.onLastFrame();\n } else {\n this.onNextFrame();\n }\n break;\n\n case 'Home':\n this.onFirstFrame();\n break;\n\n case 'End':\n this.onLastFrame();\n break;\n }\n }\n\n private onPrevFrame(): void {\n if (this.index > 0) {\n --this.index;\n }\n void this.render();\n }\n\n private onNextFrame(): void {\n if (this.index < this.#framesCount() - 1) {\n ++this.index;\n }\n void this.render();\n }\n\n private onFirstFrame(): void {\n this.index = 0;\n void this.render();\n }\n\n private onLastFrame(): void {\n this.index = this.#framesCount() - 1;\n void this.render();\n }\n\n private render(): void {\n const frame = this.#data.frames[this.index];\n const timestamp = Trace.Helpers.Timing.microSecondsToMilliseconds(frame.screenshotEvent.ts);\n this.fragment.$('time').textContent = i18n.TimeUtilities.millisToString(timestamp - this.#zeroTime());\n const image = (this.fragment.$('image') as HTMLImageElement);\n image.setAttribute('data-frame-index', this.index.toString());\n FilmStripView.setImageData(image, frame.screenshotEvent.args.dataUri);\n this.resize();\n }\n}\n"]} \ No newline at end of file diff --git a/public/ui/legacy/components/perf_ui/FilmStripView.test.js b/public/ui/legacy/components/perf_ui/FilmStripView.test.js index 3411da0c3..a012c5079 100644 --- a/public/ui/legacy/components/perf_ui/FilmStripView.test.js +++ b/public/ui/legacy/components/perf_ui/FilmStripView.test.js @@ -1,7 +1,7 @@ // 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 * as TraceEngine from '../../../../models/trace/trace.js'; +import * as Trace from '../../../../models/trace/trace.js'; import { dispatchClickEvent, dispatchKeyDownEvent, querySelectorErrorOnMissing, raf, renderElementIntoDOM, } from '../../../../testing/DOMHelpers.js'; import { describeWithEnvironment } from '../../../../testing/EnvironmentHelpers.js'; import { TraceLoader } from '../../../../testing/TraceLoader.js'; @@ -19,8 +19,8 @@ describeWithEnvironment('FilmStripView', function () { return filmStripView; } it('generates frames and timestamps', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const filmStrip = await renderView(TraceEngine.Extras.FilmStrip.fromTraceData(traceData)); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const filmStrip = await renderView(Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace)); const renderedFrames = Array.from(filmStrip.contentElement.querySelectorAll('button.frame')); assert.lengthOf(renderedFrames, 5); const expectedTimeLabelsForFrames = [ @@ -34,7 +34,7 @@ describeWithEnvironment('FilmStripView', function () { // data. And that the time label is as expected. renderedFrames.forEach((frame, index) => { const img = querySelectorErrorOnMissing(frame, 'img'); - assert.isTrue(img.src.includes(traceData.Screenshots[index].args.dataUri)); + assert.isTrue(img.src.includes(parsedTrace.Screenshots[index].args.dataUri)); const timeElement = querySelectorErrorOnMissing(frame, '.time'); // Remove whitespace to avoid having to compare with   in the // expected text. @@ -44,7 +44,7 @@ describeWithEnvironment('FilmStripView', function () { filmStrip.detach(); }); describe('FilmStripView Dialog', function () { - async function renderDialogWithTraceEngine(filmStrip, selectedFrameIndex) { + async function renderDialogWithTrace(filmStrip, selectedFrameIndex) { const dialogWidget = PerfUI.FilmStripView.Dialog.fromFilmStrip(filmStrip, selectedFrameIndex); // Give the dialog time to render await raf(); @@ -57,17 +57,17 @@ describeWithEnvironment('FilmStripView', function () { return { dialog: dialogWidget, shadowRoot: containerShadowRoot }; } it('renders and shows the provided frame by default', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const filmStrip = TraceEngine.Extras.FilmStrip.fromTraceData(traceData); - const { dialog, shadowRoot } = await renderDialogWithTraceEngine(filmStrip, 0); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const filmStrip = Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace); + const { dialog, shadowRoot } = await renderDialogWithTrace(filmStrip, 0); const renderedImage = shadowRoot.querySelector('[data-film-strip-dialog-img]'); - assert.isTrue(renderedImage?.currentSrc.includes(traceData.Screenshots[0].args.dataUri)); + assert.isTrue(renderedImage?.currentSrc.includes(parsedTrace.Screenshots[0].args.dataUri)); dialog.hide(); }); it('does not let the user navigate back if they are at the first frame already', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const filmStrip = TraceEngine.Extras.FilmStrip.fromTraceData(traceData); - const { dialog, shadowRoot } = await renderDialogWithTraceEngine(filmStrip, 0); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const filmStrip = Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace); + const { dialog, shadowRoot } = await renderDialogWithTrace(filmStrip, 0); const previousBtn = shadowRoot.querySelector('devtools-button'); assert.isTrue(previousBtn?.textContent === '◀' || previousBtn?.textContent === '◀'); if (!previousBtn) { @@ -76,13 +76,13 @@ describeWithEnvironment('FilmStripView', function () { dispatchClickEvent(previousBtn); await raf(); const renderedImage = shadowRoot.querySelector('[data-film-strip-dialog-img]'); - assert.isTrue(renderedImage?.currentSrc.includes(traceData.Screenshots[0].args.dataUri)); + assert.isTrue(renderedImage?.currentSrc.includes(parsedTrace.Screenshots[0].args.dataUri)); dialog.hide(); }); it('lets the user navigate back to the previous frame with the mouse', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const filmStrip = TraceEngine.Extras.FilmStrip.fromTraceData(traceData); - const { dialog, shadowRoot } = await renderDialogWithTraceEngine(filmStrip, 1); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const filmStrip = Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace); + const { dialog, shadowRoot } = await renderDialogWithTrace(filmStrip, 1); const previousBtn = shadowRoot.querySelector('devtools-button'); assert.isTrue(previousBtn?.textContent === '◀' || previousBtn?.textContent === '◀'); if (!previousBtn) { @@ -91,13 +91,13 @@ describeWithEnvironment('FilmStripView', function () { dispatchClickEvent(previousBtn); await raf(); const renderedImage = shadowRoot.querySelector('[data-film-strip-dialog-img]'); - assert.isTrue(renderedImage?.currentSrc.includes(traceData.Screenshots[0].args.dataUri)); + assert.isTrue(renderedImage?.currentSrc.includes(parsedTrace.Screenshots[0].args.dataUri)); dialog.hide(); }); it('lets the user navigate back to the previous frame with the keyboard', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const filmStrip = TraceEngine.Extras.FilmStrip.fromTraceData(traceData); - const { dialog, shadowRoot } = await renderDialogWithTraceEngine(filmStrip, 1); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const filmStrip = Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace); + const { dialog, shadowRoot } = await renderDialogWithTrace(filmStrip, 1); const renderedImage = shadowRoot.querySelector('[data-film-strip-dialog-img]'); if (!renderedImage) { throw new Error('Could not find film-strip-dialog img'); @@ -107,13 +107,13 @@ describeWithEnvironment('FilmStripView', function () { bubbles: true, }); await raf(); - assert.isTrue(renderedImage?.currentSrc.includes(traceData.Screenshots[0].args.dataUri)); + assert.isTrue(renderedImage?.currentSrc.includes(parsedTrace.Screenshots[0].args.dataUri)); dialog.hide(); }); it('lets the user navigate forwards to the next frame with the mouse', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const filmStrip = TraceEngine.Extras.FilmStrip.fromTraceData(traceData); - const { dialog, shadowRoot } = await renderDialogWithTraceEngine(filmStrip, 0); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const filmStrip = Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace); + const { dialog, shadowRoot } = await renderDialogWithTrace(filmStrip, 0); const nextBtn = shadowRoot.querySelectorAll('devtools-button')[1]; assert.isTrue(nextBtn.textContent === '▶' || nextBtn.textContent === '▶'); if (!nextBtn) { @@ -122,16 +122,16 @@ describeWithEnvironment('FilmStripView', function () { dispatchClickEvent(nextBtn); await raf(); const renderedImage = shadowRoot.querySelector('[data-film-strip-dialog-img]'); - assert.isTrue(renderedImage?.currentSrc.includes(traceData.Screenshots[1].args.dataUri)); + assert.isTrue(renderedImage?.currentSrc.includes(parsedTrace.Screenshots[1].args.dataUri)); dialog.hide(); }); it('does not let the user go beyond the last image', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const filmStrip = TraceEngine.Extras.FilmStrip.fromTraceData(traceData); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const filmStrip = Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace); const numberOfFrames = filmStrip.frames.length; - const { dialog, shadowRoot } = await renderDialogWithTraceEngine(filmStrip, numberOfFrames - 1); + const { dialog, shadowRoot } = await renderDialogWithTrace(filmStrip, numberOfFrames - 1); let renderedImage = shadowRoot.querySelector('[data-film-strip-dialog-img]'); - assert.isTrue(renderedImage?.currentSrc.includes(traceData.Screenshots[numberOfFrames - 1].args.dataUri)); + assert.isTrue(renderedImage?.currentSrc.includes(parsedTrace.Screenshots[numberOfFrames - 1].args.dataUri)); const nextBtn = shadowRoot.querySelectorAll('devtools-button')[1]; assert.isTrue(nextBtn.textContent === '▶' || nextBtn.textContent === '▶'); if (!nextBtn) { @@ -140,13 +140,13 @@ describeWithEnvironment('FilmStripView', function () { dispatchClickEvent(nextBtn); await raf(); renderedImage = shadowRoot.querySelector('[data-film-strip-dialog-img]'); - assert.isTrue(renderedImage?.currentSrc.includes(traceData.Screenshots[numberOfFrames - 1].args.dataUri)); + assert.isTrue(renderedImage?.currentSrc.includes(parsedTrace.Screenshots[numberOfFrames - 1].args.dataUri)); dialog.hide(); }); it('lets the user navigate forwards to the next frame with the keyboard', async function () { - const { traceData } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); - const filmStrip = TraceEngine.Extras.FilmStrip.fromTraceData(traceData); - const { dialog, shadowRoot } = await renderDialogWithTraceEngine(filmStrip, 0); + const { parsedTrace } = await TraceLoader.traceEngine(this, 'web-dev.json.gz'); + const filmStrip = Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace); + const { dialog, shadowRoot } = await renderDialogWithTrace(filmStrip, 0); const renderedImage = shadowRoot.querySelector('[data-film-strip-dialog-img]'); if (!renderedImage) { throw new Error('Could not find film-strip-dialog img'); @@ -156,7 +156,7 @@ describeWithEnvironment('FilmStripView', function () { bubbles: true, }); await raf(); - assert.isTrue(renderedImage?.currentSrc.includes(traceData.Screenshots[1].args.dataUri)); + assert.isTrue(renderedImage?.currentSrc.includes(parsedTrace.Screenshots[1].args.dataUri)); dialog.hide(); }); }); diff --git a/public/ui/legacy/components/perf_ui/FilmStripView.test.js.map b/public/ui/legacy/components/perf_ui/FilmStripView.test.js.map index 033dc49af..44696bc1e 100644 --- a/public/ui/legacy/components/perf_ui/FilmStripView.test.js.map +++ b/public/ui/legacy/components/perf_ui/FilmStripView.test.js.map @@ -1 +1 @@ -{"version":3,"file":"FilmStripView.test.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/legacy/components/perf_ui/FilmStripView.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as TraceEngine from '../../../../models/trace/trace.js';\nimport {\n dispatchClickEvent,\n dispatchKeyDownEvent,\n querySelectorErrorOnMissing,\n raf,\n renderElementIntoDOM,\n} from '../../../../testing/DOMHelpers.js';\nimport {describeWithEnvironment} from '../../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../../testing/TraceLoader.js';\n\nimport * as PerfUI from './perf_ui.js';\n\ndescribeWithEnvironment('FilmStripView', function() {\n async function renderView(filmStripData: TraceEngine.Extras.FilmStrip.Data):\n Promise {\n const filmStripView = new PerfUI.FilmStripView.FilmStripView();\n filmStripView.setModel(filmStripData);\n const container = document.createElement('div');\n renderElementIntoDOM(container);\n filmStripView.markAsRoot();\n filmStripView.show(container);\n // Give the film strip time to render.\n await raf();\n return filmStripView;\n }\n\n it('generates frames and timestamps', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const filmStrip = await renderView(TraceEngine.Extras.FilmStrip.fromTraceData(traceData));\n const renderedFrames = Array.from(filmStrip.contentElement.querySelectorAll('button.frame'));\n assert.lengthOf(renderedFrames, 5);\n const expectedTimeLabelsForFrames = [\n '0ms',\n '139ms',\n '222ms',\n '239ms',\n '289ms',\n ];\n // Ensure for each frame that we rendered the right snapshot from the trace\n // data. And that the time label is as expected.\n renderedFrames.forEach((frame, index) => {\n const img = querySelectorErrorOnMissing(frame, 'img');\n assert.isTrue(img.src.includes(traceData.Screenshots[index].args.dataUri));\n\n const timeElement = querySelectorErrorOnMissing(frame, '.time');\n // Remove whitespace to avoid having to compare with   in the\n // expected text.\n assert.strictEqual(timeElement.innerText.replace(/\\s/, ''), expectedTimeLabelsForFrames[index]);\n });\n assert.deepStrictEqual(1, 1);\n\n filmStrip.detach();\n });\n\n describe('FilmStripView Dialog', function() {\n async function renderDialogWithTraceEngine(\n filmStrip: TraceEngine.Extras.FilmStrip.Data,\n selectedFrameIndex: number): Promise<{dialog: PerfUI.FilmStripView.Dialog, shadowRoot: ShadowRoot}> {\n const dialogWidget = PerfUI.FilmStripView.Dialog.fromFilmStrip(filmStrip, selectedFrameIndex);\n // Give the dialog time to render\n await raf();\n\n // Creating the dialog widget is enough to cause it to render, so now we can find the Dialog HTML.\n const container = document.body.querySelector('[data-devtools-glass-pane]');\n const containerShadowRoot = container?.shadowRoot;\n if (!containerShadowRoot) {\n throw new Error('Could not find the Dialog shadowRoot');\n }\n return {dialog: dialogWidget, shadowRoot: containerShadowRoot};\n }\n\n it('renders and shows the provided frame by default', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const filmStrip = TraceEngine.Extras.FilmStrip.fromTraceData(traceData);\n const {dialog, shadowRoot} = await renderDialogWithTraceEngine(filmStrip, 0);\n const renderedImage = shadowRoot.querySelector('[data-film-strip-dialog-img]');\n assert.isTrue(renderedImage?.currentSrc.includes(traceData.Screenshots[0].args.dataUri));\n dialog.hide();\n });\n\n it('does not let the user navigate back if they are at the first frame already', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const filmStrip = TraceEngine.Extras.FilmStrip.fromTraceData(traceData);\n const {dialog, shadowRoot} = await renderDialogWithTraceEngine(filmStrip, 0);\n const previousBtn = shadowRoot.querySelector('devtools-button');\n assert.isTrue(previousBtn?.textContent === '◀' || previousBtn?.textContent === '◀');\n if (!previousBtn) {\n throw new Error('Could not find previous button');\n }\n dispatchClickEvent(previousBtn);\n await raf();\n const renderedImage = shadowRoot.querySelector('[data-film-strip-dialog-img]');\n assert.isTrue(renderedImage?.currentSrc.includes(traceData.Screenshots[0].args.dataUri));\n dialog.hide();\n });\n\n it('lets the user navigate back to the previous frame with the mouse', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const filmStrip = TraceEngine.Extras.FilmStrip.fromTraceData(traceData);\n const {dialog, shadowRoot} = await renderDialogWithTraceEngine(filmStrip, 1);\n const previousBtn = shadowRoot.querySelector('devtools-button');\n assert.isTrue(previousBtn?.textContent === '◀' || previousBtn?.textContent === '◀');\n if (!previousBtn) {\n throw new Error('Could not find previous button');\n }\n dispatchClickEvent(previousBtn);\n await raf();\n const renderedImage = shadowRoot.querySelector('[data-film-strip-dialog-img]');\n assert.isTrue(renderedImage?.currentSrc.includes(traceData.Screenshots[0].args.dataUri));\n dialog.hide();\n });\n\n it('lets the user navigate back to the previous frame with the keyboard', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const filmStrip = TraceEngine.Extras.FilmStrip.fromTraceData(traceData);\n const {dialog, shadowRoot} = await renderDialogWithTraceEngine(filmStrip, 1);\n const renderedImage = shadowRoot.querySelector('[data-film-strip-dialog-img]');\n if (!renderedImage) {\n throw new Error('Could not find film-strip-dialog img');\n }\n dispatchKeyDownEvent(renderedImage, {\n key: 'ArrowLeft',\n bubbles: true,\n });\n await raf();\n assert.isTrue(renderedImage?.currentSrc.includes(traceData.Screenshots[0].args.dataUri));\n dialog.hide();\n });\n\n it('lets the user navigate forwards to the next frame with the mouse', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const filmStrip = TraceEngine.Extras.FilmStrip.fromTraceData(traceData);\n const {dialog, shadowRoot} = await renderDialogWithTraceEngine(filmStrip, 0);\n\n const nextBtn = shadowRoot.querySelectorAll('devtools-button')[1];\n assert.isTrue(nextBtn.textContent === '▶' || nextBtn.textContent === '▶');\n if (!nextBtn) {\n throw new Error('Could not find next button');\n }\n dispatchClickEvent(nextBtn);\n await raf();\n const renderedImage = shadowRoot.querySelector('[data-film-strip-dialog-img]');\n assert.isTrue(renderedImage?.currentSrc.includes(traceData.Screenshots[1].args.dataUri));\n dialog.hide();\n });\n\n it('does not let the user go beyond the last image', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const filmStrip = TraceEngine.Extras.FilmStrip.fromTraceData(traceData);\n const numberOfFrames = filmStrip.frames.length;\n const {dialog, shadowRoot} = await renderDialogWithTraceEngine(filmStrip, numberOfFrames - 1);\n\n let renderedImage = shadowRoot.querySelector('[data-film-strip-dialog-img]');\n assert.isTrue(renderedImage?.currentSrc.includes(traceData.Screenshots[numberOfFrames - 1].args.dataUri));\n\n const nextBtn = shadowRoot.querySelectorAll('devtools-button')[1];\n assert.isTrue(nextBtn.textContent === '▶' || nextBtn.textContent === '▶');\n if (!nextBtn) {\n throw new Error('Could not find next button');\n }\n dispatchClickEvent(nextBtn);\n await raf();\n renderedImage = shadowRoot.querySelector('[data-film-strip-dialog-img]');\n assert.isTrue(renderedImage?.currentSrc.includes(traceData.Screenshots[numberOfFrames - 1].args.dataUri));\n dialog.hide();\n });\n\n it('lets the user navigate forwards to the next frame with the keyboard', async function() {\n const {traceData} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const filmStrip = TraceEngine.Extras.FilmStrip.fromTraceData(traceData);\n const {dialog, shadowRoot} = await renderDialogWithTraceEngine(filmStrip, 0);\n const renderedImage = shadowRoot.querySelector('[data-film-strip-dialog-img]');\n if (!renderedImage) {\n throw new Error('Could not find film-strip-dialog img');\n }\n dispatchKeyDownEvent(renderedImage, {\n key: 'ArrowRight',\n bubbles: true,\n });\n await raf();\n assert.isTrue(renderedImage?.currentSrc.includes(traceData.Screenshots[1].args.dataUri));\n dialog.hide();\n });\n });\n});\n"]} \ No newline at end of file +{"version":3,"file":"FilmStripView.test.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/legacy/components/perf_ui/FilmStripView.test.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2023 The Chromium Authors. All rights reserved.\n// Use of this source code is governed by a BSD-style license that can be\n// found in the LICENSE file.\n\nimport * as Trace from '../../../../models/trace/trace.js';\nimport {\n dispatchClickEvent,\n dispatchKeyDownEvent,\n querySelectorErrorOnMissing,\n raf,\n renderElementIntoDOM,\n} from '../../../../testing/DOMHelpers.js';\nimport {describeWithEnvironment} from '../../../../testing/EnvironmentHelpers.js';\nimport {TraceLoader} from '../../../../testing/TraceLoader.js';\n\nimport * as PerfUI from './perf_ui.js';\n\ndescribeWithEnvironment('FilmStripView', function() {\n async function renderView(filmStripData: Trace.Extras.FilmStrip.Data): Promise {\n const filmStripView = new PerfUI.FilmStripView.FilmStripView();\n filmStripView.setModel(filmStripData);\n const container = document.createElement('div');\n renderElementIntoDOM(container);\n filmStripView.markAsRoot();\n filmStripView.show(container);\n // Give the film strip time to render.\n await raf();\n return filmStripView;\n }\n\n it('generates frames and timestamps', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const filmStrip = await renderView(Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace));\n const renderedFrames = Array.from(filmStrip.contentElement.querySelectorAll('button.frame'));\n assert.lengthOf(renderedFrames, 5);\n const expectedTimeLabelsForFrames = [\n '0ms',\n '139ms',\n '222ms',\n '239ms',\n '289ms',\n ];\n // Ensure for each frame that we rendered the right snapshot from the trace\n // data. And that the time label is as expected.\n renderedFrames.forEach((frame, index) => {\n const img = querySelectorErrorOnMissing(frame, 'img');\n assert.isTrue(img.src.includes(parsedTrace.Screenshots[index].args.dataUri));\n\n const timeElement = querySelectorErrorOnMissing(frame, '.time');\n // Remove whitespace to avoid having to compare with   in the\n // expected text.\n assert.strictEqual(timeElement.innerText.replace(/\\s/, ''), expectedTimeLabelsForFrames[index]);\n });\n assert.deepStrictEqual(1, 1);\n\n filmStrip.detach();\n });\n\n describe('FilmStripView Dialog', function() {\n async function renderDialogWithTrace(filmStrip: Trace.Extras.FilmStrip.Data, selectedFrameIndex: number):\n Promise<{dialog: PerfUI.FilmStripView.Dialog, shadowRoot: ShadowRoot}> {\n const dialogWidget = PerfUI.FilmStripView.Dialog.fromFilmStrip(filmStrip, selectedFrameIndex);\n // Give the dialog time to render\n await raf();\n\n // Creating the dialog widget is enough to cause it to render, so now we can find the Dialog HTML.\n const container = document.body.querySelector('[data-devtools-glass-pane]');\n const containerShadowRoot = container?.shadowRoot;\n if (!containerShadowRoot) {\n throw new Error('Could not find the Dialog shadowRoot');\n }\n return {dialog: dialogWidget, shadowRoot: containerShadowRoot};\n }\n\n it('renders and shows the provided frame by default', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const filmStrip = Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace);\n const {dialog, shadowRoot} = await renderDialogWithTrace(filmStrip, 0);\n const renderedImage = shadowRoot.querySelector('[data-film-strip-dialog-img]');\n assert.isTrue(renderedImage?.currentSrc.includes(parsedTrace.Screenshots[0].args.dataUri));\n dialog.hide();\n });\n\n it('does not let the user navigate back if they are at the first frame already', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const filmStrip = Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace);\n const {dialog, shadowRoot} = await renderDialogWithTrace(filmStrip, 0);\n const previousBtn = shadowRoot.querySelector('devtools-button');\n assert.isTrue(previousBtn?.textContent === '◀' || previousBtn?.textContent === '◀');\n if (!previousBtn) {\n throw new Error('Could not find previous button');\n }\n dispatchClickEvent(previousBtn);\n await raf();\n const renderedImage = shadowRoot.querySelector('[data-film-strip-dialog-img]');\n assert.isTrue(renderedImage?.currentSrc.includes(parsedTrace.Screenshots[0].args.dataUri));\n dialog.hide();\n });\n\n it('lets the user navigate back to the previous frame with the mouse', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const filmStrip = Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace);\n const {dialog, shadowRoot} = await renderDialogWithTrace(filmStrip, 1);\n const previousBtn = shadowRoot.querySelector('devtools-button');\n assert.isTrue(previousBtn?.textContent === '◀' || previousBtn?.textContent === '◀');\n if (!previousBtn) {\n throw new Error('Could not find previous button');\n }\n dispatchClickEvent(previousBtn);\n await raf();\n const renderedImage = shadowRoot.querySelector('[data-film-strip-dialog-img]');\n assert.isTrue(renderedImage?.currentSrc.includes(parsedTrace.Screenshots[0].args.dataUri));\n dialog.hide();\n });\n\n it('lets the user navigate back to the previous frame with the keyboard', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const filmStrip = Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace);\n const {dialog, shadowRoot} = await renderDialogWithTrace(filmStrip, 1);\n const renderedImage = shadowRoot.querySelector('[data-film-strip-dialog-img]');\n if (!renderedImage) {\n throw new Error('Could not find film-strip-dialog img');\n }\n dispatchKeyDownEvent(renderedImage, {\n key: 'ArrowLeft',\n bubbles: true,\n });\n await raf();\n assert.isTrue(renderedImage?.currentSrc.includes(parsedTrace.Screenshots[0].args.dataUri));\n dialog.hide();\n });\n\n it('lets the user navigate forwards to the next frame with the mouse', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const filmStrip = Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace);\n const {dialog, shadowRoot} = await renderDialogWithTrace(filmStrip, 0);\n\n const nextBtn = shadowRoot.querySelectorAll('devtools-button')[1];\n assert.isTrue(nextBtn.textContent === '▶' || nextBtn.textContent === '▶');\n if (!nextBtn) {\n throw new Error('Could not find next button');\n }\n dispatchClickEvent(nextBtn);\n await raf();\n const renderedImage = shadowRoot.querySelector('[data-film-strip-dialog-img]');\n assert.isTrue(renderedImage?.currentSrc.includes(parsedTrace.Screenshots[1].args.dataUri));\n dialog.hide();\n });\n\n it('does not let the user go beyond the last image', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const filmStrip = Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace);\n const numberOfFrames = filmStrip.frames.length;\n const {dialog, shadowRoot} = await renderDialogWithTrace(filmStrip, numberOfFrames - 1);\n\n let renderedImage = shadowRoot.querySelector('[data-film-strip-dialog-img]');\n assert.isTrue(renderedImage?.currentSrc.includes(parsedTrace.Screenshots[numberOfFrames - 1].args.dataUri));\n\n const nextBtn = shadowRoot.querySelectorAll('devtools-button')[1];\n assert.isTrue(nextBtn.textContent === '▶' || nextBtn.textContent === '▶');\n if (!nextBtn) {\n throw new Error('Could not find next button');\n }\n dispatchClickEvent(nextBtn);\n await raf();\n renderedImage = shadowRoot.querySelector('[data-film-strip-dialog-img]');\n assert.isTrue(renderedImage?.currentSrc.includes(parsedTrace.Screenshots[numberOfFrames - 1].args.dataUri));\n dialog.hide();\n });\n\n it('lets the user navigate forwards to the next frame with the keyboard', async function() {\n const {parsedTrace} = await TraceLoader.traceEngine(this, 'web-dev.json.gz');\n const filmStrip = Trace.Extras.FilmStrip.fromParsedTrace(parsedTrace);\n const {dialog, shadowRoot} = await renderDialogWithTrace(filmStrip, 0);\n const renderedImage = shadowRoot.querySelector('[data-film-strip-dialog-img]');\n if (!renderedImage) {\n throw new Error('Could not find film-strip-dialog img');\n }\n dispatchKeyDownEvent(renderedImage, {\n key: 'ArrowRight',\n bubbles: true,\n });\n await raf();\n assert.isTrue(renderedImage?.currentSrc.includes(parsedTrace.Screenshots[1].args.dataUri));\n dialog.hide();\n });\n });\n});\n"]} \ No newline at end of file diff --git a/public/ui/legacy/components/perf_ui/FlameChart.d.ts b/public/ui/legacy/components/perf_ui/FlameChart.d.ts index 012693028..38ed705b7 100644 --- a/public/ui/legacy/components/perf_ui/FlameChart.d.ts +++ b/public/ui/legacy/components/perf_ui/FlameChart.d.ts @@ -30,7 +30,7 @@ import * as Common from '../../../../core/common/common.js'; import * as Platform from '../../../../core/platform/platform.js'; import type * as TimelineModel from '../../../../models/timeline_model/timeline_model.js'; -import * as TraceEngine from '../../../../models/trace/trace.js'; +import * as Trace from '../../../../models/trace/trace.js'; import * as UI from '../../legacy.js'; import { type ChartViewportDelegate } from './ChartViewport.js'; import { type Calculator } from './TimelineGrid.js'; @@ -87,7 +87,7 @@ export declare const enum FilterAction { } export interface UserFilterAction { type: FilterAction; - entry: TraceEngine.Types.TraceEvents.TraceEventData; + entry: Trace.Types.Events.Event; } export interface PossibleFilterActions { [FilterAction.MERGE_FUNCTION]: boolean; @@ -96,6 +96,11 @@ export interface PossibleFilterActions { [FilterAction.RESET_CHILDREN]: boolean; [FilterAction.UNDO_ALL_ACTIONS]: boolean; } +export interface PositionOverride { + x: number; + width: number; +} +export type DrawOverride = (context: CanvasRenderingContext2D, x: number, y: number, width: number, height: number) => PositionOverride; declare const FlameChart_base: (new (...args: any[]) => { "__#13@#events": Common.ObjectWrapper.ObjectWrapper; addEventListener(eventType: T, listener: (arg0: Common.EventTarget.EventTargetEvent) => void, thisObject?: Object): Common.EventTarget.EventDescriptor; @@ -140,6 +145,7 @@ export declare class FlameChart extends FlameChart_base implements Calculator, C private selectedEntryIndex; private rawTimelineDataLength; private readonly markerPositions; + private readonly customDrawnPositions; private lastMouseOffsetX; private selectedGroupIndex; private keyboardFocusedGroup; @@ -418,10 +424,7 @@ export declare class FlameChart extends FlameChart_base implements Calculator, C groupIsLastVisibleTopLevel(group?: Group): boolean; setSelectedEntry(entryIndex: number): void; private entryHasDecoration; - getMarkerPixelsForEntryIndex(entryIndex: number): { - x: number; - width: number; - } | null; + getCustomDrawnPositionForEntryIndex(entryIndex: number): PositionOverride | null; /** * Update position of an Element. By default, the element is treated as a full entry and it's dimentions are set to the full entry width/length/height. * If isDecoration parameter is set to true, the element will be positioned on the right side of the entry and have a square shape where width == height of the entry. @@ -459,10 +462,10 @@ export declare class FlameChart extends FlameChart_base implements Calculator, C private enabled; computePosition(time: number): number; formatValue(value: number, precision?: number): string; - maximumBoundary(): TraceEngine.Types.Timing.MilliSeconds; - minimumBoundary(): TraceEngine.Types.Timing.MilliSeconds; - zeroTime(): TraceEngine.Types.Timing.MilliSeconds; - boundarySpan(): TraceEngine.Types.Timing.MilliSeconds; + maximumBoundary(): Trace.Types.Timing.MilliSeconds; + minimumBoundary(): Trace.Types.Timing.MilliSeconds; + zeroTime(): Trace.Types.Timing.MilliSeconds; + boundarySpan(): Trace.Types.Timing.MilliSeconds; } export declare const RulerHeight = 15; export declare const MinimalTimeWindowMs = 0.5; @@ -497,12 +500,12 @@ export declare const enum FlameChartDecorationType { **/ export type FlameChartDecoration = { type: FlameChartDecorationType.CANDY; - startAtTime: TraceEngine.Types.Timing.MicroSeconds; - endAtTime?: TraceEngine.Types.Timing.MicroSeconds; + startAtTime: Trace.Types.Timing.MicroSeconds; + endAtTime?: Trace.Types.Timing.MicroSeconds; } | { type: FlameChartDecorationType.WARNING_TRIANGLE; - customStartTime?: TraceEngine.Types.Timing.MicroSeconds; - customEndTime?: TraceEngine.Types.Timing.MicroSeconds; + customStartTime?: Trace.Types.Timing.MicroSeconds; + customEndTime?: Trace.Types.Timing.MicroSeconds; } | { type: FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW; }; @@ -534,12 +537,12 @@ export declare class FlameChartTimelineData { } export interface DataProviderSearchResult { index: number; - startTimeMilli: TraceEngine.Types.Timing.MilliSeconds; + startTimeMilli: Trace.Types.Timing.MilliSeconds; provider: 'main' | 'network' | 'other'; } export interface DataProviderSearchResult { index: number; - startTimeMilli: TraceEngine.Types.Timing.MilliSeconds; + startTimeMilli: Trace.Types.Timing.MilliSeconds; provider: 'main' | 'network' | 'other'; } export interface FlameChartDataProvider { @@ -558,17 +561,18 @@ export interface FlameChartDataProvider { forceDecoration(entryIndex: number): boolean; forceDrawableLevel?(level: number): boolean; textColor(entryIndex: number): string; - mainFrameNavigationStartEvents?(): readonly TraceEngine.Types.TraceEvents.TraceEventNavigationStart[]; + mainFrameNavigationStartEvents?(): readonly Trace.Types.Events.NavigationStart[]; hasTrackConfigurationMode(): boolean; - eventByIndex?(entryIndex: number): TraceEngine.Types.TraceEvents.TraceEventData | TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame | null; - indexForEvent?(event: TraceEngine.Types.TraceEvents.TraceEventData | TraceEngine.Types.TraceEvents.LegacyTimelineFrame): number | null; + eventByIndex?(entryIndex: number): Trace.Types.Events.Event | Trace.Handlers.ModelHandlers.Frames.TimelineFrame | null; + indexForEvent?(event: Trace.Types.Events.Event | Trace.Types.Events.LegacyTimelineFrame): number | null; buildFlowForInitiator?(index: number): unknown; customizedContextMenu?(event: MouseEvent, eventIndex: number, groupIndex: number): UI.ContextMenu.ContextMenu | undefined; - search?(visibleWindow: TraceEngine.Types.Timing.TraceWindowMicroSeconds, filter: TimelineModel.TimelineModelFilter.TimelineModelFilter): DataProviderSearchResult[]; + search?(visibleWindow: Trace.Types.Timing.TraceWindowMicroSeconds, filter: TimelineModel.TimelineModelFilter.TimelineModelFilter): DataProviderSearchResult[]; modifyTree?(action: FilterAction, entryIndex: number): void; findPossibleContextMenuActions?(node: number): PossibleFilterActions | void; handleFlameChartTransformKeyboardEvent?(event: KeyboardEvent, entryIndex: number, groupIndex: number): void; groupForEvent?(entryIndex: number): Group | null; + getDrawOverride?(entryIndex: number): DrawOverride | undefined; } export interface FlameChartMarker { startTime(): number; @@ -614,7 +618,10 @@ export declare const enum Events { MOUSE_MOVE = "MouseMove" } export type EventTypes = { - [Events.ENTRY_LABEL_ANNOTATION_ADDED]: number; + [Events.ENTRY_LABEL_ANNOTATION_ADDED]: { + entryIndex: number; + withLinkCreationButton: boolean; + }; [Events.ENTRIES_LINK_ANNOTATION_CREATED]: { entryFromIndex: number; }; @@ -630,11 +637,11 @@ export type EventTypes = { scrollOffsetPixels: number; allGroupsCollapsed: boolean; }; - traceWindow: TraceEngine.Types.Timing.TraceWindowMicroSeconds; + traceWindow: Trace.Types.Timing.TraceWindowMicroSeconds; }; [Events.MOUSE_MOVE]: { mouseEvent: MouseEvent; - timeInMicroSeconds: TraceEngine.Types.Timing.MicroSeconds; + timeInMicroSeconds: Trace.Types.Timing.MicroSeconds; }; }; export interface Group { diff --git a/public/ui/legacy/components/perf_ui/FlameChart.js b/public/ui/legacy/components/perf_ui/FlameChart.js index fa947f0d6..08a951a3e 100644 --- a/public/ui/legacy/components/perf_ui/FlameChart.js +++ b/public/ui/legacy/components/perf_ui/FlameChart.js @@ -31,7 +31,7 @@ import * as Common from '../../../../core/common/common.js'; import * as i18n from '../../../../core/i18n/i18n.js'; import * as Platform from '../../../../core/platform/platform.js'; import * as Root from '../../../../core/root/root.js'; -import * as TraceEngine from '../../../../models/trace/trace.js'; +import * as Trace from '../../../../models/trace/trace.js'; import * as Buttons from '../../../components/buttons/buttons.js'; import * as UI from '../../legacy.js'; import * as ThemeSupport from '../../theme_support/theme_support.js'; @@ -174,6 +174,7 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox) selectedEntryIndex; rawTimelineDataLength; markerPositions; + customDrawnPositions; lastMouseOffsetX; selectedGroupIndex; keyboardFocusedGroup; @@ -203,6 +204,7 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox) // Stored because we cache this value to save extra lookups and layoffs. #canvasBoundingClientRect = null; #selectedElementOutlineEnabled = true; + #indexToDrawOverride = new Map(); constructor(dataProvider, flameChartDelegate, optionalConfig = {}) { super(true); this.#font = `${DEFAULT_FONT_SIZE} ${getFontFamilyForCanvas()}`; @@ -266,6 +268,7 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox) this.#searchResultEntryIndex = -1; this.rawTimelineDataLength = 0; this.markerPositions = new Map(); + this.customDrawnPositions = new Map(); this.lastMouseOffsetX = 0; this.selectedGroupIndex = -1; this.lastPopoverState = { @@ -283,7 +286,12 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox) this.hideHighlight(); } canvasBoundingClientRect() { - if (this.#canvasBoundingClientRect) { + // If we have a rect already, and it has width & height, use it by default. + // The reason we check the dimensions is because otherwise if this method was + // called before the FlameChart was fully rendered it might have been + // calculated with a width or height of 0, and that is clearly incorrect. + if (this.#canvasBoundingClientRect && this.#canvasBoundingClientRect.width > 0 && + this.#canvasBoundingClientRect.height > 0) { return this.#canvasBoundingClientRect; } this.#canvasBoundingClientRect = this.canvas.getBoundingClientRect(); @@ -486,10 +494,10 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox) if (this.chartViewport.isDragging()) { return; } - const timeMilliSeconds = TraceEngine.Types.Timing.MilliSeconds(this.chartViewport.pixelToTime(mouseEvent.offsetX)); + const timeMilliSeconds = Trace.Types.Timing.MilliSeconds(this.chartViewport.pixelToTime(mouseEvent.offsetX)); this.dispatchEventToListeners("MouseMove" /* Events.MOUSE_MOVE */, { mouseEvent, - timeInMicroSeconds: TraceEngine.Helpers.Timing.millisecondsToMicroseconds(timeMilliSeconds), + timeInMicroSeconds: Trace.Helpers.Timing.millisecondsToMicroseconds(timeMilliSeconds), }); // Check if the mouse is hovering any group's header area const { groupIndex, hoverType } = this.coordinatesToGroupIndexAndHoverType(mouseEvent.offsetX, mouseEvent.offsetY); @@ -683,7 +691,7 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox) */ if (this.highlightedEntryIndex !== -1) { this.#selectGroup(groupIndex); - this.dispatchEventToListeners("EntryLabelAnnotationAdded" /* Events.ENTRY_LABEL_ANNOTATION_ADDED */, this.highlightedEntryIndex); + this.dispatchEventToListeners("EntryLabelAnnotationAdded" /* Events.ENTRY_LABEL_ANNOTATION_ADDED */, { entryIndex: this.highlightedEntryIndex, withLinkCreationButton: true }); } } /** @@ -1032,7 +1040,7 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox) if (Root.Runtime.experiments.isEnabled("perf-panel-annotations" /* Root.Runtime.ExperimentName.TIMELINE_ANNOTATIONS */)) { const annotationSection = this.contextMenu.section('annotations'); const labelEntryAnnotationOption = annotationSection.appendItem(i18nString(UIStrings.labelEntry), () => { - this.dispatchEventToListeners("EntryLabelAnnotationAdded" /* Events.ENTRY_LABEL_ANNOTATION_ADDED */, this.selectedEntryIndex); + this.dispatchEventToListeners("EntryLabelAnnotationAdded" /* Events.ENTRY_LABEL_ANNOTATION_ADDED */, { entryIndex: this.selectedEntryIndex, withLinkCreationButton: false }); }); labelEntryAnnotationOption.setShortcut('Double Click'); const linkEntriesAnnotationOption = annotationSection.appendItem(i18nString(UIStrings.linkEntries), () => { @@ -1334,7 +1342,16 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox) if (offsetFromLevel > this.levelHeight(cursorLevel)) { return -1; } - // Check markers first. + // Check custom drawn entries first. + for (const [index, pos] of this.customDrawnPositions) { + if (timelineData.entryLevels[index] !== cursorLevel) { + continue; + } + if (pos.x <= x && x < pos.x + pos.width) { + return index; + } + } + // Check markers. for (const [index, pos] of this.markerPositions) { if (timelineData.entryLevels[index] !== cursorLevel) { continue; @@ -1597,7 +1614,7 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox) // that as all being collapsed. allGroupsCollapsed: this.rawTimelineData?.groups.every(g => !g.expanded) ?? true, }, - traceWindow: TraceEngine.Helpers.Timing.traceWindowFromMilliSeconds(this.minimumBoundary(), this.maximumBoundary()), + traceWindow: Trace.Helpers.Timing.traceWindowFromMilliSeconds(this.minimumBoundary(), this.maximumBoundary()), }); const canvasWidth = this.offsetWidth; const canvasHeight = this.offsetHeight; @@ -1642,6 +1659,7 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox) this.#drawGenericEvents(context, timelineData, color, indexes); } this.dispatchEventToListeners("ChartPlayableStateChange" /* Events.CHART_PLAYABLE_STATE_CHANGED */, wideEntryExists); + this.#drawCustomSymbols(context, timelineData); this.drawMarkers(context, timelineData, markerIndices); this.drawEventTitles(context, timelineData, titleIndices, canvasWidth); // If there is a `forceDecoration` function, it will be called in `drawEventTitles`, which will overwrite the @@ -1664,7 +1682,7 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox) const hasNextNavStartTime = navStartTimes.length > navStartTimeIndex + 1; if (hasNextNavStartTime) { const nextNavStartTime = navStartTimes[navStartTimeIndex + 1]; - const nextNavStartTimeStartTimestamp = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(nextNavStartTime.ts); + const nextNavStartTimeStartTimestamp = Trace.Helpers.Timing.microSecondsToMilliseconds(nextNavStartTime.ts); if (time > nextNavStartTimeStartTimestamp) { navStartTimeIndex++; } @@ -1672,7 +1690,7 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox) // Adjust the time by the nearest nav start marker's value. const nearestMarker = navStartTimes[navStartTimeIndex]; if (nearestMarker) { - const nearestMarkerStartTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(nearestMarker.ts); + const nearestMarkerStartTime = Trace.Helpers.Timing.microSecondsToMilliseconds(nearestMarker.ts); time -= nearestMarkerStartTime - this.zeroTime(); } return this.formatValue(time, dividersData.precision); @@ -1701,6 +1719,10 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox) context.beginPath(); for (let i = 0; i < indexes.length; ++i) { const entryIndex = indexes[i]; + // If there is a draw override, then this is not a generic event. + if (this.#indexToDrawOverride.has(entryIndex)) { + continue; + } this.#drawEventRect(context, timelineData, entryIndex); } context.fillStyle = color; @@ -1732,7 +1754,7 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox) for (const decoration of decorationsForEvent) { switch (decoration.type) { case "CANDY" /* FlameChartDecorationType.CANDY */: { - const candyStripeStartTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(decoration.startAtTime); + const candyStripeStartTime = Trace.Helpers.Timing.microSecondsToMilliseconds(decoration.startAtTime); if (duration < candyStripeStartTime) { // If the duration of the event is less than the start time to draw the candy stripes, then we have no stripes to draw. continue; @@ -1747,7 +1769,7 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox) const barXStart = this.timeToPositionClipped(entryStartTime + candyStripeStartTime); // If a custom end time was passed in, that is when we stop striping, else we stripe until the very end of the entry. const stripingEndTime = decoration.endAtTime ? - TraceEngine.Helpers.Timing.microSecondsToMilliseconds(decoration.endAtTime) : + Trace.Helpers.Timing.microSecondsToMilliseconds(decoration.endAtTime) : entryStartTime + duration; const barXEnd = this.timeToPositionClipped(stripingEndTime); this.#drawEventRect(context, timelineData, entryIndex, { @@ -1764,7 +1786,7 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox) if (typeof decoration.customEndTime !== 'undefined') { // The user can pass a customEndTime to tell us where the event's box ends and therefore where we should // draw the triangle. So therefore we calculate the width by taking the end time off the start time. - const endTimeMilli = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(decoration.customEndTime); + const endTimeMilli = Trace.Helpers.Timing.microSecondsToMilliseconds(decoration.customEndTime); endTimePixels = this.timeToPositionClipped(endTimeMilli); barWidth = endTimePixels - barX; } @@ -1774,7 +1796,7 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox) // The user can pass a customStartTime to tell us where the event's box start and therefore where we // should draw the triangle. So therefore we calculate the width by taking the end time off the start // time. - const startTimeMilli = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(decoration.customStartTime); + const startTimeMilli = Trace.Helpers.Timing.microSecondsToMilliseconds(decoration.customStartTime); const startTimePixels = this.timeToPositionClipped(startTimeMilli); triangleWidth = Math.min(endTimePixels - startTimePixels, 8); } @@ -2159,7 +2181,7 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox) // Markers are sorted top to bottom, right to left. for (let m = markerIndices.length - 1; m >= 0; --m) { const entryIndex = markerIndices[m]; - const title = this.dataProvider.entryTitle(entryIndex); + const title = this.entryTitle(entryIndex); if (!title) { continue; } @@ -2185,6 +2207,22 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox) context.stroke(); context.restore(); } + #drawCustomSymbols(context, timelineData) { + const { entryStartTimes, entryLevels } = timelineData; + this.customDrawnPositions.clear(); + context.save(); + for (const [entryIndex, drawOverride] of this.#indexToDrawOverride.entries()) { + const entryStartTime = entryStartTimes[entryIndex]; + const level = entryLevels[entryIndex]; + const x = this.chartViewport.timeToPosition(entryStartTime); + const y = this.levelToOffset(level); + const height = this.levelHeight(level); + const width = this.#eventBarWidth(timelineData, entryIndex); + const pos = drawOverride(context, x, y, width, height); + this.customDrawnPositions.set(entryIndex, pos); + } + context.restore(); + } /** * Draws the titles of trace events in the timeline. Also calls `decorateEntry` on the data * provider, which can do any custom drawing on the corresponding entry's area (e.g. draw screenshots @@ -2597,9 +2635,14 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox) this.rawTimelineDataLength = timelineData.entryStartTimes.length; this.forceDecorationCache = new Array(this.rawTimelineDataLength); this.entryColorsCache = new Array(this.rawTimelineDataLength); + this.#indexToDrawOverride.clear(); for (let i = 0; i < this.rawTimelineDataLength; ++i) { this.forceDecorationCache[i] = this.dataProvider.forceDecoration(i) ?? false; this.entryColorsCache[i] = this.dataProvider.entryColor(i); + const drawOverride = this.dataProvider.getDrawOverride?.(i); + if (drawOverride) { + this.#indexToDrawOverride.set(i, drawOverride); + } } const entryCounters = new Uint32Array(this.dataProvider.maxStackDepth() + 1); for (let i = 0; i < timelineData.entryLevels.length; ++i) { @@ -2966,7 +3009,11 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox) } return false; } - getMarkerPixelsForEntryIndex(entryIndex) { + getCustomDrawnPositionForEntryIndex(entryIndex) { + const customPos = this.customDrawnPositions.get(entryIndex); + if (customPos) { + return customPos; + } return this.markerPositions.get(entryIndex) ?? null; } /** @@ -2991,7 +3038,12 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox) let barX = 0; let barWidth = 0; let visible = true; - if (Number.isNaN(duration)) { + const customPos = this.customDrawnPositions.get(entryIndex); + if (customPos) { + barX = customPos.x; + barWidth = customPos.width; + } + else if (Number.isNaN(duration)) { const position = this.markerPositions.get(entryIndex); if (position) { barX = position.x; @@ -3147,16 +3199,16 @@ export class FlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox) return this.dataProvider.formatValue(value - this.zeroTime(), precision); } maximumBoundary() { - return TraceEngine.Types.Timing.MilliSeconds(this.chartViewport.windowRightTime()); + return Trace.Types.Timing.MilliSeconds(this.chartViewport.windowRightTime()); } minimumBoundary() { - return TraceEngine.Types.Timing.MilliSeconds(this.chartViewport.windowLeftTime()); + return Trace.Types.Timing.MilliSeconds(this.chartViewport.windowLeftTime()); } zeroTime() { - return TraceEngine.Types.Timing.MilliSeconds(this.dataProvider.minimumBoundary()); + return Trace.Types.Timing.MilliSeconds(this.dataProvider.minimumBoundary()); } boundarySpan() { - return TraceEngine.Types.Timing.MilliSeconds(this.maximumBoundary() - this.minimumBoundary()); + return Trace.Types.Timing.MilliSeconds(this.maximumBoundary() - this.minimumBoundary()); } } export const RulerHeight = 15; diff --git a/public/ui/legacy/components/perf_ui/FlameChart.js.map b/public/ui/legacy/components/perf_ui/FlameChart.js.map index c358d0f2a..4a80ba715 100644 --- a/public/ui/legacy/components/perf_ui/FlameChart.js.map +++ b/public/ui/legacy/components/perf_ui/FlameChart.js.map @@ -1 +1 @@ -{"version":3,"file":"FlameChart.js","sourceRoot":"","sources":["../../../../../../../../front_end/ui/legacy/components/perf_ui/FlameChart.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Copyright (C) 2013 Google Inc. All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions are\n * met:\n *\n * * Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above\n * copyright notice, this list of conditions and the following disclaimer\n * in the documentation and/or other materials provided with the\n * distribution.\n * * Neither the name of Google Inc. nor the names of its\n * contributors may be used to endorse or promote products derived from\n * this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nimport * as Common from '../../../../core/common/common.js';\nimport * as i18n from '../../../../core/i18n/i18n.js';\nimport * as Platform from '../../../../core/platform/platform.js';\nimport * as Root from '../../../../core/root/root.js';\nimport type * as TimelineModel from '../../../../models/timeline_model/timeline_model.js';\nimport * as TraceEngine from '../../../../models/trace/trace.js';\nimport * as Buttons from '../../../components/buttons/buttons.js';\nimport * as UI from '../../legacy.js';\nimport * as ThemeSupport from '../../theme_support/theme_support.js';\n\nimport {drawExpansionArrow, drawIcon, drawLegends, horizontalLine} from './CanvasHelper.js';\nimport {ChartViewport, type ChartViewportDelegate} from './ChartViewport.js';\nimport flameChartStyles from './flameChart.css.legacy.js';\nimport {DEFAULT_FONT_SIZE, getFontFamilyForCanvas} from './Font.js';\nimport {type Calculator, TimelineGrid} from './TimelineGrid.js';\n\nconst UIStrings = {\n /**\n *@description Aria accessible name in Flame Chart of the Performance panel\n */\n flameChart: 'Flame Chart',\n /**\n *@description Text for the screen reader to announce a hovered group\n *@example {Network} PH1\n */\n sHovered: '{PH1} hovered',\n /**\n *@description Text for screen reader to announce a selected group.\n *@example {Network} PH1\n */\n sSelected: '{PH1} selected',\n /**\n *@description Text for screen reader to announce an expanded group\n *@example {Network} PH1\n */\n sExpanded: '{PH1} expanded',\n /**\n *@description Text for screen reader to announce a collapsed group\n *@example {Network} PH1\n */\n sCollapsed: '{PH1} collapsed',\n /**\n *@description Text for an action that adds a label annotation to an entry in the Flame Chart\n */\n labelEntry: 'Label entry',\n /**\n *@description Text for an action that adds link annotation between entries in the Flame Chart\n */\n linkEntries: 'Link entries',\n /**\n *@description Shown in the context menu when right clicking on a track header to enable the user to enter the track configuration mode.\n */\n enterTrackConfigurationMode: 'Configure tracks…',\n /**\n *@description Shown in the context menu when right clicking on a track header to allow the user to exit track configuration mode.\n */\n exitTrackConfigurationMode: 'Finish configuring tracks',\n};\nconst str_ = i18n.i18n.registerUIStrings('ui/legacy/components/perf_ui/FlameChart.ts', UIStrings);\nconst i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);\n\n/**\n * The expansion arrow is drawn from the center, so the indent is in fact the center of the arrow.\n * See `drawExpansionArrow` function to understand how we draw the arrow.\n * |headerLeftPadding|Arrow|\n * |expansionArrowIndent|\n *\n * When we are in edit mode, we render 3 icons to the left of the track's title.\n * When we are in normal mode, there are no icons to the left of the track's title.\n **/\n\n// Placed to the left of the track header.\nconst HEADER_LEFT_PADDING = 6;\nexport const ARROW_SIDE = 8;\n\nconst EXPANSION_ARROW_INDENT = HEADER_LEFT_PADDING + ARROW_SIDE / 2;\nconst HEADER_LABEL_X_PADDING = 3;\nconst HEADER_LABEL_Y_PADDING = 2;\n\n// The width of each of the edit mode icons.\nexport const EDIT_ICON_WIDTH = 16;\n// This gap might seem quite small - but the icons themselves have some\n// whitespace either side, so we don't need a huge gap.\nconst GAP_BETWEEN_EDIT_ICONS = 3;\n// The UP icon is first, and is rendered in from the left just as the track text.\nconst UP_ICON_LEFT = HEADER_LEFT_PADDING;\n// The DOWN icon is after the UP icon, hence we take the up icon's position,\n// add its width and then the gap between them.\nconst DOWN_ICON_LEFT = UP_ICON_LEFT + EDIT_ICON_WIDTH + GAP_BETWEEN_EDIT_ICONS;\n// The HIDE icon is after the DOWN icon, hence we take the up icon's position,\n// add its width and then the gap between them.\nconst HIDE_ICON_LEFT = DOWN_ICON_LEFT + EDIT_ICON_WIDTH + GAP_BETWEEN_EDIT_ICONS;\n\n// Represents the total width taken by the 3 icons (up, down, hide/show, and\n// the gap between them.)\n// We calculate this by taking the space to the left of the hide icon (which\n// encompasses UP/DOWN icons), adding on the width of the HIDE icon, and then a\n// bit of extra padding.\nconst EDIT_MODE_TOTAL_ICON_WIDTH = HIDE_ICON_LEFT + EDIT_ICON_WIDTH + GAP_BETWEEN_EDIT_ICONS;\n\n// These are copied from front_end/images/*.svg, because we need to draw them with canvas.\n// arrow-up.svg\nconst moveUpIconPath = 'M9.25 17V5.875L7.062 8.062L6 7L10 3L14 7L12.938 8.062L10.75 5.875V17H9.25Z';\n// arrow-down.svg\nconst moveDownIconPath = 'M9.25 3V14.125L7.062 11.938L6 13L10 17L14 13L12.938 11.938L10.75 14.125V3H9.25Z';\n// eye-crossed.svg\nconst hideIconPath =\n 'M13.2708 11.1459L11.9792 9.85419C12.0347 9.32641 11.875 8.87155 11.5 8.4896C11.125 8.10766 10.6736 7.94446 10.1458 8.00002L8.85417 6.70835C9.03472 6.63891 9.22222 6.58683 9.41667 6.5521C9.61111 6.51738 9.80556 6.50002 10 6.50002C10.9722 6.50002 11.7986 6.8403 12.4792 7.52085C13.1597 8.20141 13.5 9.0278 13.5 10C13.5 10.1945 13.4826 10.3889 13.4479 10.5834C13.4132 10.7778 13.3542 10.9653 13.2708 11.1459ZM16.0417 13.9167L14.9583 12.8334C15.4583 12.4445 15.9132 12.0174 16.3229 11.5521C16.7326 11.0868 17.0764 10.5695 17.3542 10C16.6736 8.59724 15.6701 7.49655 14.3438 6.69794C13.0174 5.89933 11.5694 5.50002 10 5.50002C9.63889 5.50002 9.28472 5.52085 8.9375 5.56252C8.59028 5.60419 8.25 5.67363 7.91667 5.77085L6.70833 4.56252C7.23611 4.35419 7.77431 4.20835 8.32292 4.12502C8.87153 4.04169 9.43056 4.00002 10 4.00002C11.9861 4.00002 13.8021 4.53821 15.4479 5.6146C17.0938 6.69099 18.2778 8.1528 19 10C18.6944 10.7917 18.2882 11.5104 17.7813 12.1563C17.2743 12.8021 16.6944 13.3889 16.0417 13.9167ZM16 18.125L13.2917 15.4167C12.7639 15.6111 12.2257 15.757 11.6771 15.8542C11.1285 15.9514 10.5694 16 10 16C8.01389 16 6.19792 15.4618 4.55208 14.3854C2.90625 13.309 1.72222 11.8472 1 10C1.30556 9.20835 1.70833 8.48613 2.20833 7.83335C2.70833 7.18058 3.29167 6.5903 3.95833 6.06252L1.875 3.97919L2.9375 2.91669L17.0625 17.0625L16 18.125ZM5.02083 7.14585C4.53472 7.53474 4.08333 7.96183 3.66667 8.4271C3.25 8.89238 2.90972 9.41669 2.64583 10C3.32639 11.4028 4.32986 12.5035 5.65625 13.3021C6.98264 14.1007 8.43056 14.5 10 14.5C10.3611 14.5 10.7153 14.4757 11.0625 14.4271C11.4097 14.3785 11.7569 14.3125 12.1042 14.2292L11.1667 13.2917C10.9722 13.3611 10.7778 13.4132 10.5833 13.4479C10.3889 13.4827 10.1944 13.5 10 13.5C9.02778 13.5 8.20139 13.1597 7.52083 12.4792C6.84028 11.7986 6.5 10.9722 6.5 10C6.5 9.80558 6.52431 9.61113 6.57292 9.41669C6.62153 9.22224 6.66667 9.0278 6.70833 8.83335L5.02083 7.14585Z';\n// eye.svg\nconst showIconPath =\n 'M10 13.5C10.972 13.5 11.7983 13.1597 12.479 12.479C13.1597 11.7983 13.5 10.972 13.5 10C13.5 9.028 13.1597 8.20167 12.479 7.521C11.7983 6.84033 10.972 6.5 10 6.5C9.028 6.5 8.20167 6.84033 7.521 7.521C6.84033 8.20167 6.5 9.028 6.5 10C6.5 10.972 6.84033 11.7983 7.521 12.479C8.20167 13.1597 9.028 13.5 10 13.5ZM10 12C9.44467 12 8.97233 11.8057 8.583 11.417C8.19433 11.0277 8 10.5553 8 10C8 9.44467 8.19433 8.97233 8.583 8.583C8.97233 8.19433 9.44467 8 10 8C10.5553 8 11.0277 8.19433 11.417 8.583C11.8057 8.97233 12 9.44467 12 10C12 10.5553 11.8057 11.0277 11.417 11.417C11.0277 11.8057 10.5553 12 10 12ZM10 16C8.014 16 6.20833 15.455 4.583 14.365C2.95833 13.2743 1.764 11.8193 1 10C1.764 8.18067 2.95833 6.72567 4.583 5.635C6.20833 4.545 8.014 4 10 4C11.986 4 13.7917 4.545 15.417 5.635C17.0417 6.72567 18.236 8.18067 19 10C18.236 11.8193 17.0417 13.2743 15.417 14.365C13.7917 15.455 11.986 16 10 16ZM10 14.5C11.5553 14.5 12.9927 14.0973 14.312 13.292C15.632 12.486 16.646 11.3887 17.354 10C16.646 8.61133 15.632 7.514 14.312 6.708C12.9927 5.90267 11.5553 5.5 10 5.5C8.44467 5.5 7.00733 5.90267 5.688 6.708C4.368 7.514 3.354 8.61133 2.646 10C3.354 11.3887 4.368 12.486 5.688 13.292C7.00733 14.0973 8.44467 14.5 10 14.5Z';\n\n// The gap between the track header and the legends\nconst LEGEND_LEFT_PADDING = 16;\n\n// export for test.\nexport const enum HoverType {\n TRACK_CONFIG_UP_BUTTON = 'TRACK_CONFIG_UP_BUTTON',\n TRACK_CONFIG_DOWN_BUTTON = 'TRACK_CONFIG_DOWN_BUTTON',\n TRACK_CONFIG_HIDE_BUTTON = 'TRACK_CONFIG_HIDE_BUTTON',\n TRACK_CONFIG_SHOW_BUTTON = 'TRACK_CONFIG_SHOW_BUTTON',\n INSIDE_TRACK_HEADER = 'INSIDE_TRACK_HEADER',\n INSIDE_TRACK = 'INSIDE_TRACK',\n OUTSIDE_TRACKS = 'OUTSIDE_TRACKS',\n ERROR = 'ERROR',\n}\n\nexport class FlameChartDelegate {\n windowChanged(_startTime: number, _endTime: number, _animate: boolean): void {\n }\n updateRangeSelection(_startTime: number, _endTime: number): void {\n }\n updateSelectedGroup(_flameChart: FlameChart, _group: Group|null): void {\n }\n}\n\ninterface GroupExpansionState {\n [groupName: string]: boolean;\n}\ninterface GroupHiddenState {\n [groupName: string]: boolean;\n}\n\ninterface PopoverState {\n // Index of the last entry the popover was shown over.\n entryIndex: number;\n // Index of the last group the popover was shown over.\n groupIndex: number;\n hiddenEntriesPopover: boolean;\n}\ninterface GroupTreeNode {\n index: number;\n nestingLevel: number;\n startLevel: number;\n endLevel: number;\n // The order in children is the visible order of them.\n children: GroupTreeNode[];\n}\n\nexport interface OptionalFlameChartConfig {\n /**\n * The FlameChart will highlight the entry that is selected by default. In\n * some cases (Performance Panel) we manage this ourselves with the Overlays\n * system, so we disable the built in one.\n */\n selectedElementOutline?: boolean;\n groupExpansionSetting?: Common.Settings.Setting;\n /**\n * The element to use when populating and positioning the mouse tooltip.\n */\n tooltipElement?: HTMLElement;\n /**\n * Used to disable the cursor element in ChartViewport and instead use the new overlays system.\n */\n useOverlaysForCursorRuler?: boolean;\n}\n\nexport const enum FilterAction {\n MERGE_FUNCTION = 'MERGE_FUNCTION',\n COLLAPSE_FUNCTION = 'COLLAPSE_FUNCTION',\n COLLAPSE_REPEATING_DESCENDANTS = 'COLLAPSE_REPEATING_DESCENDANTS',\n RESET_CHILDREN = 'RESET_CHILDREN',\n UNDO_ALL_ACTIONS = 'UNDO_ALL_ACTIONS',\n}\n\nexport interface UserFilterAction {\n type: FilterAction;\n entry: TraceEngine.Types.TraceEvents.TraceEventData;\n}\n\n// Object used to indicate to the Context Menu if an action is possible on the selected entry.\nexport interface PossibleFilterActions {\n [FilterAction.MERGE_FUNCTION]: boolean;\n [FilterAction.COLLAPSE_FUNCTION]: boolean;\n [FilterAction.COLLAPSE_REPEATING_DESCENDANTS]: boolean;\n [FilterAction.RESET_CHILDREN]: boolean;\n [FilterAction.UNDO_ALL_ACTIONS]: boolean;\n}\n\nexport class FlameChart extends Common.ObjectWrapper.eventMixin(UI.Widget.VBox)\n implements Calculator, ChartViewportDelegate {\n private readonly groupExpansionSetting?: Common.Settings.Setting;\n private groupExpansionState: GroupExpansionState;\n private groupHiddenState: GroupHiddenState;\n private readonly flameChartDelegate: FlameChartDelegate;\n private chartViewport: ChartViewport;\n private dataProvider: FlameChartDataProvider;\n private candyStripePattern: CanvasPattern|null;\n private contextMenu?: UI.ContextMenu.ContextMenu;\n private viewportElement: HTMLElement;\n private canvas: HTMLCanvasElement;\n private popoverElement: HTMLElement;\n private readonly markerHighlighElement: HTMLElement;\n readonly highlightElement: HTMLElement;\n readonly revealDescendantsArrowHighlightElement: HTMLElement;\n private readonly selectedElement: HTMLElement|null = null;\n private rulerEnabled: boolean;\n private barHeight: number;\n // Additional space around an entry that is added for operations with entry.\n // It allows for less pecision while selecting/hovering over an entry.\n private hitMarginPx: number;\n private textBaseline: number;\n private textPadding: number;\n private highlightedMarkerIndex: number;\n /**\n * Represents the index of the entry that the user's mouse cursor is over.\n * Note that this is updated as the user moves their cursor: they do not have\n * to click for this to be updated.\n **/\n private highlightedEntryIndex: number;\n /**\n * Represents the index of the entry that is selected. For an entry to be\n * selected, it has to be clicked by the user.\n **/\n private selectedEntryIndex: number;\n private rawTimelineDataLength: number;\n private readonly markerPositions: Map;\n private lastMouseOffsetX: number;\n private selectedGroupIndex: number;\n private keyboardFocusedGroup: number;\n private offsetWidth!: number;\n private offsetHeight!: number;\n private dragStartX!: number;\n private dragStartY!: number;\n private lastMouseOffsetY!: number;\n private minimumBoundaryInternal!: number;\n private maxDragOffset!: number;\n private timelineLevels?: number[][]|null;\n private visibleLevelOffsets?: Uint32Array|null;\n private visibleLevels?: boolean[]|null;\n private visibleLevelHeights?: Uint32Array;\n private groupOffsets?: Uint32Array|null;\n private rawTimelineData?: FlameChartTimelineData|null;\n private forceDecorationCache?: boolean[]|null;\n private entryColorsCache?: string[]|null;\n private totalTime?: number;\n private lastPopoverState: PopoverState;\n\n #tooltipPopoverYAdjustment: number = 0;\n\n #font: string;\n #groupTreeRoot?: GroupTreeNode|null;\n #searchResultEntryIndex: number;\n #searchResultHighlightElements: HTMLElement[] = [];\n #inTrackConfigEditMode: boolean = false;\n\n // Stored because we cache this value to save extra lookups and layoffs.\n #canvasBoundingClientRect: DOMRect|null = null;\n #selectedElementOutlineEnabled = true;\n\n constructor(\n dataProvider: FlameChartDataProvider, flameChartDelegate: FlameChartDelegate,\n optionalConfig: OptionalFlameChartConfig = {}) {\n super(true);\n this.#font = `${DEFAULT_FONT_SIZE} ${getFontFamilyForCanvas()}`;\n this.registerRequiredCSS(flameChartStyles);\n this.contentElement.classList.add('flame-chart-main-pane');\n if (typeof optionalConfig.selectedElementOutline === 'boolean') {\n this.#selectedElementOutlineEnabled = optionalConfig.selectedElementOutline;\n }\n\n this.groupExpansionSetting = optionalConfig.groupExpansionSetting;\n this.groupExpansionState = optionalConfig.groupExpansionSetting?.get() || {};\n this.groupHiddenState = {};\n this.flameChartDelegate = flameChartDelegate;\n\n // The ChartViewport has its own built-in ruler for when the user holds\n // shift and moves the mouse. We want to disable that if we are within the\n // performance panel where we use overlays, but enable it otherwise.\n let enableCursorElement = true;\n if (typeof optionalConfig.useOverlaysForCursorRuler === 'boolean') {\n enableCursorElement = !optionalConfig.useOverlaysForCursorRuler;\n }\n this.chartViewport = new ChartViewport(this, {\n enableCursorElement,\n });\n this.chartViewport.show(this.contentElement);\n\n this.dataProvider = dataProvider;\n\n this.viewportElement = this.chartViewport.viewportElement;\n this.canvas = (this.viewportElement.createChild('canvas', 'fill') as HTMLCanvasElement);\n this.candyStripePattern = null;\n\n this.canvas.tabIndex = 0;\n UI.ARIAUtils.setLabel(this.canvas, i18nString(UIStrings.flameChart));\n UI.ARIAUtils.markAsTree(this.canvas);\n this.setDefaultFocusedElement(this.canvas);\n this.canvas.classList.add('flame-chart-canvas');\n this.canvas.addEventListener('mousemove', this.onMouseMove.bind(this), false);\n this.canvas.addEventListener('mouseout', this.onMouseOut.bind(this), false);\n this.canvas.addEventListener('click', this.onClick.bind(this), false);\n this.canvas.addEventListener('dblclick', this.#onDblClick.bind(this), false);\n this.canvas.addEventListener('keydown', this.onKeyDown.bind(this), false);\n this.canvas.addEventListener('contextmenu', this.onContextMenu.bind(this), false);\n\n this.popoverElement =\n optionalConfig.tooltipElement || this.viewportElement.createChild('div', 'flame-chart-entry-info');\n this.markerHighlighElement = this.viewportElement.createChild('div', 'flame-chart-marker-highlight-element');\n this.highlightElement = this.viewportElement.createChild('div', 'flame-chart-highlight-element');\n this.revealDescendantsArrowHighlightElement =\n this.viewportElement.createChild('div', 'reveal-descendants-arrow-highlight-element');\n\n if (this.#selectedElementOutlineEnabled) {\n this.selectedElement = this.viewportElement.createChild('div', 'flame-chart-selected-element');\n }\n\n this.canvas.addEventListener('focus', () => {\n this.dispatchEventToListeners(Events.CANVAS_FOCUSED);\n }, false);\n\n UI.UIUtils.installDragHandle(\n this.viewportElement, this.startDragging.bind(this), this.dragging.bind(this), this.endDragging.bind(this),\n null);\n\n this.rulerEnabled = true;\n this.barHeight = 17;\n this.hitMarginPx = 3;\n this.textBaseline = 5;\n this.textPadding = 5;\n this.chartViewport.setWindowTimes(\n dataProvider.minimumBoundary(), dataProvider.minimumBoundary() + dataProvider.totalTime());\n\n this.highlightedMarkerIndex = -1;\n this.highlightedEntryIndex = -1;\n this.selectedEntryIndex = -1;\n this.#searchResultEntryIndex = -1;\n this.rawTimelineDataLength = 0;\n this.markerPositions = new Map();\n\n this.lastMouseOffsetX = 0;\n this.selectedGroupIndex = -1;\n this.lastPopoverState = {\n entryIndex: -1,\n groupIndex: -1,\n hiddenEntriesPopover: false,\n };\n\n // Keyboard focused group is used to navigate groups irrespective of whether they are selectable or not\n this.keyboardFocusedGroup = -1;\n\n ThemeSupport.ThemeSupport.instance().addEventListener(ThemeSupport.ThemeChangeEvent.eventName, () => {\n this.scheduleUpdate();\n });\n }\n\n override willHide(): void {\n this.hideHighlight();\n }\n\n canvasBoundingClientRect(): DOMRect|null {\n if (this.#canvasBoundingClientRect) {\n return this.#canvasBoundingClientRect;\n }\n this.#canvasBoundingClientRect = this.canvas.getBoundingClientRect();\n return this.#canvasBoundingClientRect;\n }\n\n /**\n * In some cases we need to manually adjust the positioning of the tooltip\n * vertically to account for the fact that it might be rendered not relative\n * to just this flame chart. This is true of the main flame chart in the\n * Performance Panel where the element is rendered in a higher-stack container\n * and we need to manually adjust its Y position to correctly put the tooltip\n * in the right place.\n */\n setTooltipYPixelAdjustment(y: number): void {\n if (y === this.#tooltipPopoverYAdjustment) {\n return;\n }\n\n this.#tooltipPopoverYAdjustment = y;\n // Reposition the popover if it has any children (otherwise it is not visible)\n if (this.popoverElement.children.length) {\n this.updatePopoverOffset();\n }\n }\n\n getBarHeight(): number {\n return this.barHeight;\n }\n\n setBarHeight(value: number): void {\n this.barHeight = value;\n }\n\n setTextBaseline(value: number): void {\n this.textBaseline = value;\n }\n\n setTextPadding(value: number): void {\n this.textPadding = value;\n }\n\n enableRuler(enable: boolean): void {\n this.rulerEnabled = enable;\n }\n\n alwaysShowVerticalScroll(): void {\n this.chartViewport.alwaysShowVerticalScroll();\n }\n\n disableRangeSelection(): void {\n this.chartViewport.disableRangeSelection();\n }\n\n highlightEntry(entryIndex: number): void {\n if (this.highlightedEntryIndex === entryIndex) {\n return;\n }\n if (!this.dataProvider.entryColor(entryIndex)) {\n return;\n }\n this.highlightedEntryIndex = entryIndex;\n this.updateElementPosition(this.highlightElement, this.highlightedEntryIndex);\n this.dispatchEventToListeners(Events.ENTRY_HOVERED, entryIndex);\n }\n\n highlightAllEntries(entries: number[]): void {\n for (const entry of entries) {\n const searchElement = this.viewportElement.createChild('div', 'flame-chart-search-element');\n this.#searchResultHighlightElements.push(searchElement);\n searchElement.id = entry.toString();\n this.updateElementPosition(searchElement, entry);\n }\n }\n\n removeSearchResultHighlights(): void {\n for (const element of this.#searchResultHighlightElements) {\n element.remove();\n }\n this.#searchResultHighlightElements = [];\n }\n\n hideHighlight(): void {\n if (this.#searchResultEntryIndex === -1) {\n this.popoverElement.removeChildren();\n this.lastPopoverState = {\n entryIndex: -1,\n groupIndex: -1,\n hiddenEntriesPopover: false,\n };\n }\n if (this.highlightedEntryIndex === -1) {\n return;\n }\n this.highlightedEntryIndex = -1;\n this.updateElementPosition(this.highlightElement, this.highlightedEntryIndex);\n this.dispatchEventToListeners(Events.ENTRY_HOVERED, -1);\n }\n\n private createCandyStripePattern(): CanvasPattern {\n // Set the candy stripe pattern to 17px so it repeats well.\n const size = 17;\n const candyStripeCanvas = document.createElement('canvas');\n candyStripeCanvas.width = size;\n candyStripeCanvas.height = size;\n const ctx = candyStripeCanvas.getContext('2d') as CanvasRenderingContext2D;\n\n // Rotate the stripe by 45deg to the right.\n ctx.translate(size * 0.5, size * 0.5);\n ctx.rotate(Math.PI * 0.25);\n ctx.translate(-size * 0.5, -size * 0.5);\n\n ctx.fillStyle = 'rgba(255, 0, 0, 0.8)';\n for (let x = -size; x < size * 2; x += 3) {\n ctx.fillRect(x, -size, 1, size * 3);\n }\n // Because we're using a canvas, we know createPattern won't return null\n // https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-createpattern-dev\n return ctx.createPattern(candyStripeCanvas, 'repeat') as CanvasPattern;\n }\n\n private resetCanvas(): void {\n const ratio = window.devicePixelRatio;\n const width = Math.round(this.offsetWidth * ratio);\n const height = Math.round(this.offsetHeight * ratio);\n this.canvas.width = width;\n this.canvas.height = height;\n this.canvas.style.width = `${width / ratio}px`;\n this.canvas.style.height = `${height / ratio}px`;\n }\n\n windowChanged(startTime: number, endTime: number, animate: boolean): void {\n this.flameChartDelegate.windowChanged(startTime, endTime, animate);\n }\n\n updateRangeSelection(startTime: number, endTime: number): void {\n this.flameChartDelegate.updateRangeSelection(startTime, endTime);\n }\n\n setSize(width: number, height: number): void {\n this.offsetWidth = width;\n this.offsetHeight = height;\n }\n\n private startDragging(event: MouseEvent): boolean {\n this.hideHighlight();\n this.maxDragOffset = 0;\n this.dragStartX = event.pageX;\n this.dragStartY = event.pageY;\n return true;\n }\n\n private dragging(event: MouseEvent): void {\n const dx = event.pageX - this.dragStartX;\n const dy = event.pageY - this.dragStartY;\n this.maxDragOffset = Math.max(this.maxDragOffset, Math.sqrt(dx * dx + dy * dy));\n }\n\n private endDragging(_event: MouseEvent): void {\n this.updateHighlight();\n }\n\n timelineData(rebuid?: boolean): FlameChartTimelineData|null {\n if (!this.dataProvider) {\n return null;\n }\n const timelineData = this.dataProvider.timelineData(rebuid);\n if (timelineData !== this.rawTimelineData ||\n (timelineData && timelineData.entryStartTimes.length !== this.rawTimelineDataLength)) {\n this.processTimelineData(timelineData);\n }\n return this.rawTimelineData || null;\n }\n\n revealEntryVertically(entryIndex: number): void {\n const timelineData = this.timelineData();\n if (!timelineData) {\n return;\n }\n const level = timelineData.entryLevels[entryIndex];\n this.chartViewport.setScrollOffset(this.levelToOffset(level), this.levelHeight(level), true);\n }\n\n revealEntry(entryIndex: number): void {\n const timelineData = this.timelineData();\n if (!timelineData) {\n return;\n }\n const timeLeft = this.chartViewport.windowLeftTime();\n const timeRight = this.chartViewport.windowRightTime();\n const entryStartTime = timelineData.entryStartTimes[entryIndex];\n const entryTotalTime = timelineData.entryTotalTimes[entryIndex];\n const entryEndTime = entryStartTime + entryTotalTime;\n let minEntryTimeWindow = Math.min(entryTotalTime, timeRight - timeLeft);\n\n const level = timelineData.entryLevels[entryIndex];\n this.chartViewport.setScrollOffset(this.levelToOffset(level), this.levelHeight(level));\n\n const minVisibleWidthPx = 30;\n const futurePixelToTime = (timeRight - timeLeft) / this.offsetWidth;\n minEntryTimeWindow = Math.max(minEntryTimeWindow, futurePixelToTime * minVisibleWidthPx);\n if (timeLeft > entryEndTime) {\n const delta = timeLeft - entryEndTime + minEntryTimeWindow;\n this.windowChanged(timeLeft - delta, timeRight - delta, /* animate */ true);\n } else if (timeRight < entryStartTime) {\n const delta = entryStartTime - timeRight + minEntryTimeWindow;\n this.windowChanged(timeLeft + delta, timeRight + delta, /* animate */ true);\n }\n }\n\n setWindowTimes(startTime: number, endTime: number, animate?: boolean): void {\n this.chartViewport.setWindowTimes(startTime, endTime, animate);\n this.updateHighlight();\n }\n\n /**\n * Handle the mouse move event. The handle priority will be:\n * 1. Track configuration icons -> show tooltip for the icons\n * 2. Inside a track header -> mouse style will be a \"pointer\", indicating track can be focused\n * 3. Inside a track -> update the highlight of hovered event\n */\n private onMouseMove(mouseEvent: MouseEvent): void {\n this.#searchResultEntryIndex = -1;\n this.lastMouseOffsetX = mouseEvent.offsetX;\n this.lastMouseOffsetY = mouseEvent.offsetY;\n if (!this.enabled()) {\n return;\n }\n if (this.chartViewport.isDragging()) {\n return;\n }\n\n const timeMilliSeconds = TraceEngine.Types.Timing.MilliSeconds(this.chartViewport.pixelToTime(mouseEvent.offsetX));\n\n this.dispatchEventToListeners(Events.MOUSE_MOVE, {\n mouseEvent,\n timeInMicroSeconds: TraceEngine.Helpers.Timing.millisecondsToMicroseconds(timeMilliSeconds),\n });\n\n // Check if the mouse is hovering any group's header area\n const {groupIndex, hoverType} = this.coordinatesToGroupIndexAndHoverType(mouseEvent.offsetX, mouseEvent.offsetY);\n switch (hoverType) {\n case HoverType.TRACK_CONFIG_UP_BUTTON:\n case HoverType.TRACK_CONFIG_DOWN_BUTTON:\n case HoverType.TRACK_CONFIG_HIDE_BUTTON:\n case HoverType.TRACK_CONFIG_SHOW_BUTTON: {\n this.hideHighlight();\n this.viewportElement.style.cursor = 'pointer';\n const iconTooltipElement = this.#prepareIconInfo(groupIndex, hoverType);\n if (iconTooltipElement) {\n this.popoverElement.appendChild(iconTooltipElement);\n this.updatePopoverOffset();\n }\n return;\n }\n case HoverType.INSIDE_TRACK_HEADER:\n this.updateHighlight();\n this.viewportElement.style.cursor = 'pointer';\n return;\n case HoverType.INSIDE_TRACK:\n this.updateHighlight();\n return;\n }\n }\n\n #prepareIconInfo(groupIndex: number, iconType: HoverType): Element|null {\n const group = this.rawTimelineData?.groups[groupIndex];\n if (!group) {\n return null;\n }\n\n // Only show first 20 characters to make the tooltip not too long.\n const maxTitleChars = 20;\n const displayName = Platform.StringUtilities.trimMiddle(group.name, maxTitleChars);\n\n let iconTooltip = '';\n switch (iconType) {\n case HoverType.TRACK_CONFIG_UP_BUTTON:\n iconTooltip = `Move ${displayName} track up`;\n break;\n case HoverType.TRACK_CONFIG_DOWN_BUTTON:\n iconTooltip = `Move ${displayName} track down`;\n break;\n case HoverType.TRACK_CONFIG_HIDE_BUTTON:\n if (this.groupIsLastVisibleTopLevel(group)) {\n iconTooltip = 'Can not hide the last top level track';\n } else {\n iconTooltip = `Hide ${displayName} track`;\n }\n break;\n case HoverType.TRACK_CONFIG_SHOW_BUTTON:\n iconTooltip = `Show ${displayName} track`;\n break;\n default:\n return null;\n }\n const element = document.createElement('div');\n element.createChild('span', 'timeline-info-title').textContent = iconTooltip;\n\n return element;\n }\n\n private updateHighlight(): void {\n const entryIndex = this.coordinatesToEntryIndex(this.lastMouseOffsetX, this.lastMouseOffsetY);\n // Each time the entry highlight is updated, we need to check if the mouse is hovering over a\n // button that indicates hidden child elements and if so, update the button highlight.\n this.updateHiddenChildrenArrowHighlighPosition(entryIndex);\n\n // No entry is hovered.\n if (entryIndex === -1) {\n this.hideHighlight();\n\n const {groupIndex, hoverType} =\n this.coordinatesToGroupIndexAndHoverType(this.lastMouseOffsetX, this.lastMouseOffsetY);\n if (hoverType === HoverType.INSIDE_TRACK_HEADER) {\n this.#updatePopoverForGroup(groupIndex);\n }\n if (groupIndex >= 0 && this.rawTimelineData && this.rawTimelineData.groups &&\n this.rawTimelineData.groups[groupIndex].selectable) {\n // This means the mouse is in a selectable group's area, and not hovering any entry.\n this.viewportElement.style.cursor = 'pointer';\n } else {\n // This means the mouse is not hovering any selectable track, and not hovering any entry.\n this.viewportElement.style.cursor = 'default';\n }\n return;\n }\n\n // Some entry is hovered.\n if (this.chartViewport.isDragging()) {\n return;\n }\n this.#updatePopoverForEntry(entryIndex);\n this.viewportElement.style.cursor = this.dataProvider.canJumpToEntry(entryIndex) ? 'pointer' : 'default';\n this.highlightEntry(entryIndex);\n }\n\n private onMouseOut(): void {\n this.lastMouseOffsetX = -1;\n this.lastMouseOffsetY = -1;\n this.hideHighlight();\n }\n\n showPopoverForSearchResult(selectedSearchResult: number): void {\n this.#searchResultEntryIndex = selectedSearchResult;\n this.#updatePopoverForEntry(selectedSearchResult);\n }\n\n #updatePopoverForEntry(entryIndex: number): void {\n // Just update position if cursor is hovering the same entry.\n const isMouseOverRevealChildrenArrow = this.isMouseOverRevealChildrenArrow(this.lastMouseOffsetX, entryIndex);\n if (entryIndex === this.lastPopoverState.entryIndex &&\n isMouseOverRevealChildrenArrow === this.lastPopoverState.hiddenEntriesPopover) {\n return this.updatePopoverOffset();\n }\n this.popoverElement.removeChildren();\n const data = this.timelineData();\n if (!data) {\n return;\n }\n const group = data.groups.at(this.selectedGroupIndex);\n // If the mouse is hovering over the hidden descendants arrow, get an element that shows how many children are hidden, otherwise an element with the event name and length\n const entryInfo = (isMouseOverRevealChildrenArrow && group) ?\n this.dataProvider.prepareHighlightedHiddenEntriesArrowInfo &&\n this.dataProvider.prepareHighlightedHiddenEntriesArrowInfo(entryIndex) :\n this.dataProvider.prepareHighlightedEntryInfo(entryIndex);\n if (entryInfo) {\n this.popoverElement.appendChild(entryInfo);\n this.updatePopoverOffset();\n }\n this.lastPopoverState = {\n entryIndex,\n groupIndex: -1,\n hiddenEntriesPopover: isMouseOverRevealChildrenArrow,\n };\n }\n\n #updatePopoverForGroup(groupIndex: number): void {\n // Just update position if cursor is hovering the group name.\n if (groupIndex === this.lastPopoverState.groupIndex) {\n return this.updatePopoverOffset();\n }\n this.popoverElement.removeChildren();\n const data = this.timelineData();\n if (!data) {\n return;\n }\n const group = data.groups.at(groupIndex);\n if (group?.description) {\n this.popoverElement.innerText = (group?.description);\n this.updatePopoverOffset();\n }\n this.lastPopoverState = {\n groupIndex,\n entryIndex: -1,\n hiddenEntriesPopover: false,\n };\n }\n\n private updatePopoverOffset(): void {\n let mouseX = this.lastMouseOffsetX;\n let mouseY = this.lastMouseOffsetY;\n\n // If the popover is being updated from a search, we calculate the coordinates manually\n if (this.#searchResultEntryIndex !== -1) {\n const coordinate = this.entryIndexToCoordinates(this.selectedEntryIndex);\n const {x: canvasViewportOffsetX, y: canvasViewportOffsetY} = this.canvas.getBoundingClientRect();\n mouseX = coordinate?.x ? coordinate.x - canvasViewportOffsetX : mouseX;\n mouseY = coordinate?.y ? coordinate.y - canvasViewportOffsetY : mouseY;\n }\n\n const parentWidth = this.popoverElement.parentElement ? this.popoverElement.parentElement.clientWidth : 0;\n const parentHeight = this.popoverElement.parentElement ? this.popoverElement.parentElement.clientHeight : 0;\n const infoWidth = this.popoverElement.clientWidth;\n const infoHeight = this.popoverElement.clientHeight;\n const /** @const */ offsetX = 10;\n const /** @const */ offsetY = 6;\n let x;\n let y;\n for (let quadrant = 0; quadrant < 4; ++quadrant) {\n const dx = quadrant & 2 ? -offsetX - infoWidth : offsetX;\n const dy = quadrant & 1 ? -offsetY - infoHeight : offsetY;\n x = Platform.NumberUtilities.clamp(mouseX + dx, 0, parentWidth - infoWidth);\n y = Platform.NumberUtilities.clamp(mouseY + dy, 0, parentHeight - infoHeight);\n if (x >= mouseX || mouseX >= x + infoWidth || y >= mouseY || mouseY >= y + infoHeight) {\n break;\n }\n }\n this.popoverElement.style.left = x + 'px';\n this.popoverElement.style.top = (y || 0) + this.#tooltipPopoverYAdjustment + 'px';\n }\n\n /**\n * Handle double mouse click event in flame chart.\n */\n #onDblClick(mouseEvent: MouseEvent): void {\n this.focus();\n const {groupIndex} = this.coordinatesToGroupIndexAndHoverType(mouseEvent.offsetX, mouseEvent.offsetY);\n\n /**\n * When a hovered entry on any track is double clicked, create a label for it.\n *\n * Checking the existance of `highlightedEntryIndex` is enough to make sure that the double\n * click happenned on the entry since an entry is only highlighted if the mouse is hovering it.\n */\n if (this.highlightedEntryIndex !== -1) {\n this.#selectGroup(groupIndex);\n this.dispatchEventToListeners(Events.ENTRY_LABEL_ANNOTATION_ADDED, this.highlightedEntryIndex);\n }\n }\n\n /**\n * Handle mouse click event in flame chart\n *\n * And the handle priority will be:\n * 1. Track configuration icons -> Config a track\n * 1.1 if it's edit mode ignore others.\n * 2. Inside a track header -> Select and Expand/Collapse a track\n * 3. Inside a track -> Select a track\n * 3.1 shift + click -> Select the time range of clicked event\n * 3.2 click -> update highlight (handle in other functions)\n */\n private onClick(mouseEvent: MouseEvent): void {\n this.focus();\n // onClick comes after dragStart and dragEnd events.\n // So if there was drag (mouse move) in the middle of that events\n // we skip the click. Otherwise we jump to the sources.\n const clickThreshold = 5;\n if (this.maxDragOffset > clickThreshold) {\n return;\n }\n\n // If any button is clicked, we should handle the action only and ignore others.\n const {groupIndex, hoverType} = this.coordinatesToGroupIndexAndHoverType(mouseEvent.offsetX, mouseEvent.offsetY);\n if (groupIndex >= 0) {\n switch (hoverType) {\n case HoverType.TRACK_CONFIG_UP_BUTTON:\n this.moveGroupUp(groupIndex);\n return;\n case HoverType.TRACK_CONFIG_DOWN_BUTTON:\n this.moveGroupDown(groupIndex);\n return;\n case HoverType.TRACK_CONFIG_HIDE_BUTTON:\n if (this.groupIsLastVisibleTopLevel(this.rawTimelineData?.groups[groupIndex])) {\n // If this is the last visible top-level group, we will not allow you hiding the track.\n return;\n }\n this.hideGroup(groupIndex);\n return;\n case HoverType.TRACK_CONFIG_SHOW_BUTTON:\n this.showGroup(groupIndex);\n return;\n case HoverType.INSIDE_TRACK_HEADER:\n this.#selectGroup(groupIndex);\n this.toggleGroupExpand(groupIndex);\n return;\n case HoverType.INSIDE_TRACK: {\n this.#selectGroup(groupIndex);\n\n const timelineData = this.timelineData();\n if (mouseEvent.shiftKey && this.highlightedEntryIndex !== -1 && timelineData) {\n const start = timelineData.entryStartTimes[this.highlightedEntryIndex];\n const end = start + timelineData.entryTotalTimes[this.highlightedEntryIndex];\n this.chartViewport.setRangeSelection(start, end);\n } else {\n this.chartViewport.onClick(mouseEvent);\n this.dispatchEventToListeners(Events.ENTRY_INVOKED, this.highlightedEntryIndex);\n }\n return;\n }\n }\n }\n }\n\n #selectGroup(groupIndex: number): void {\n if (groupIndex < 0 || this.selectedGroupIndex === groupIndex) {\n return;\n }\n if (!this.rawTimelineData) {\n return;\n }\n\n const groups = this.rawTimelineData.groups;\n if (!groups) {\n return;\n }\n\n this.keyboardFocusedGroup = groupIndex;\n this.scrollGroupIntoView(groupIndex);\n const groupName = groups[groupIndex].name;\n if (!groups[groupIndex].selectable) {\n this.deselectAllGroups();\n UI.ARIAUtils.alert(i18nString(UIStrings.sHovered, {PH1: groupName}));\n } else {\n this.selectedGroupIndex = groupIndex;\n this.flameChartDelegate.updateSelectedGroup(this, groups[groupIndex]);\n this.draw();\n UI.ARIAUtils.alert(i18nString(UIStrings.sSelected, {PH1: groupName}));\n }\n }\n\n private deselectAllGroups(): void {\n this.selectedGroupIndex = -1;\n this.flameChartDelegate.updateSelectedGroup(this, null);\n this.draw();\n }\n\n private deselectAllEntries(): void {\n this.selectedEntryIndex = -1;\n this.rawTimelineData?.resetFlowData();\n this.draw();\n }\n\n private isGroupFocused(index: number): boolean {\n return index === this.selectedGroupIndex || index === this.keyboardFocusedGroup;\n }\n\n private scrollGroupIntoView(index: number): void {\n if (index < 0) {\n return;\n }\n\n if (!this.rawTimelineData) {\n return;\n }\n\n const groups = this.rawTimelineData.groups;\n const groupOffsets = this.groupOffsets;\n if (!groupOffsets || !groups) {\n return;\n }\n const groupTop = groupOffsets[index];\n\n let nextOffset = groupOffsets[index + 1];\n if (index === groups.length - 1) {\n nextOffset += groups[index].style.padding;\n }\n\n // For the top group, scroll all the way to the top of the chart\n // to accommodate the bar with time markers\n const scrollTop = index === 0 ? 0 : groupTop;\n\n const scrollHeight = Math.min(nextOffset - scrollTop, this.chartViewport.chartHeight());\n this.chartViewport.setScrollOffset(scrollTop, scrollHeight);\n }\n\n /**\n * Toggle a group's expanded state.\n * @param groupIndex - the index of this group in the timelineData.groups\n * array. Note that this is the array index, and not the startLevel of the\n * group.\n */\n toggleGroupExpand(groupIndex: number): void {\n if (groupIndex < 0 || !this.isGroupCollapsible(groupIndex)) {\n return;\n }\n\n if (!this.rawTimelineData || !this.rawTimelineData.groups) {\n return;\n }\n\n this.expandGroup(groupIndex, !this.rawTimelineData.groups[groupIndex].expanded /* setExpanded */);\n }\n\n private expandGroup(\n groupIndex: number, setExpanded: boolean|undefined = true, propagatedExpand: boolean|undefined = false): void {\n if (groupIndex < 0 || !this.isGroupCollapsible(groupIndex)) {\n return;\n }\n\n if (!this.rawTimelineData) {\n return;\n }\n\n const groups = this.rawTimelineData.groups;\n if (!groups) {\n return;\n }\n\n const group = groups[groupIndex];\n group.expanded = setExpanded;\n\n this.groupExpansionState[group.name] = group.expanded;\n if (this.groupExpansionSetting) {\n this.groupExpansionSetting.set(this.groupExpansionState);\n }\n this.updateLevelPositions();\n\n this.updateHighlight();\n if (!group.expanded) {\n const timelineData = this.timelineData();\n if (timelineData) {\n const level = timelineData.entryLevels[this.selectedEntryIndex];\n if (this.selectedEntryIndex >= 0 && level >= group.startLevel &&\n (groupIndex >= groups.length - 1 || groups[groupIndex + 1].startLevel > level)) {\n this.selectedEntryIndex = -1;\n // Reset all flow arrows when we deselect the entry.\n this.rawTimelineData.resetFlowData();\n }\n }\n }\n\n this.updateHeight();\n this.draw();\n\n this.scrollGroupIntoView(groupIndex);\n // We only want to read expanded/collapsed state on user inputted expand/collapse\n if (!propagatedExpand) {\n const groupName = groups[groupIndex].name;\n const content = group.expanded ? i18nString(UIStrings.sExpanded, {PH1: groupName}) :\n i18nString(UIStrings.sCollapsed, {PH1: groupName});\n UI.ARIAUtils.alert(content);\n }\n }\n\n moveGroupUp(groupIndex: number): void {\n if (groupIndex < 0) {\n return;\n }\n\n if (!this.rawTimelineData || !this.rawTimelineData.groups) {\n return;\n }\n\n if (!this.#groupTreeRoot) {\n return;\n }\n\n for (let i = 0; i < this.#groupTreeRoot.children.length; i++) {\n const child = this.#groupTreeRoot.children[i];\n if (child.index === groupIndex) {\n // exchange with previous one, only second or later group can do so\n if (i >= 1) {\n this.#groupTreeRoot.children[i] = this.#groupTreeRoot.children[i - 1];\n this.#groupTreeRoot.children[i - 1] = child;\n break;\n }\n }\n }\n\n this.updateLevelPositions();\n\n this.updateHighlight();\n this.updateHeight();\n this.draw();\n }\n\n moveGroupDown(groupIndex: number): void {\n if (groupIndex < 0) {\n return;\n }\n\n if (!this.rawTimelineData || !this.rawTimelineData.groups) {\n return;\n }\n\n if (!this.#groupTreeRoot) {\n return;\n }\n\n for (let i = 0; i < this.#groupTreeRoot.children.length; i++) {\n const child = this.#groupTreeRoot.children[i];\n if (child.index === groupIndex) {\n // exchange with previous one, only second to last or before group can do so\n if (i <= this.#groupTreeRoot.children.length - 2) {\n this.#groupTreeRoot.children[i] = this.#groupTreeRoot.children[i + 1];\n this.#groupTreeRoot.children[i + 1] = child;\n break;\n }\n }\n }\n\n this.updateLevelPositions();\n\n this.updateHighlight();\n this.updateHeight();\n this.draw();\n }\n\n hideGroup(groupIndex: number): void {\n this.#toggleGroupHiddenState(groupIndex, /* hidden= */ true);\n }\n\n showGroup(groupIndex: number): void {\n this.#toggleGroupHiddenState(groupIndex, /* hidden= */ false);\n }\n\n #toggleGroupHiddenState(groupIndex: number, hidden: boolean): void {\n if (groupIndex < 0) {\n return;\n }\n\n if (!this.rawTimelineData || !this.rawTimelineData.groups) {\n return;\n }\n\n const groups = this.rawTimelineData.groups;\n if (!groups) {\n return;\n }\n\n const group = groups[groupIndex];\n group.hidden = hidden;\n\n // We need to store this state again because somehow timelineData() is\n // called multiple times when rendering the flame chart, and timelineData()\n // will overwrite the groups with the data from |dataProvider|.\n // So we need this groupHiddenState to reapply hidden state in the processTimelineData()\n this.groupHiddenState[group.name] = group.hidden;\n this.updateLevelPositions();\n\n this.updateHighlight();\n this.updateHeight();\n this.draw();\n }\n\n modifyTree(treeAction: FilterAction, index: number): void {\n const data = this.timelineData();\n if (!data || !this.dataProvider.modifyTree) {\n return;\n }\n this.dataProvider.modifyTree(treeAction, index);\n this.update();\n }\n\n #buildEnterEditModeContextMenu(event: MouseEvent): void {\n if (this.#inTrackConfigEditMode) {\n return;\n }\n\n this.contextMenu = new UI.ContextMenu.ContextMenu(event, {useSoftMenu: true});\n const label = i18nString(UIStrings.enterTrackConfigurationMode);\n this.contextMenu.defaultSection().appendItem(label, () => {\n this.#enterEditMode();\n }, {\n jslogContext: 'track-configuration-enter',\n });\n void this.contextMenu.show();\n }\n\n #buildExitEditModeContextMenu(event: MouseEvent): void {\n if (this.#inTrackConfigEditMode === false) {\n return;\n }\n this.contextMenu = new UI.ContextMenu.ContextMenu(event, {useSoftMenu: true});\n const label = i18nString(UIStrings.exitTrackConfigurationMode);\n this.contextMenu.defaultSection().appendItem(label, () => {\n this.#exitEditMode();\n }, {\n jslogContext: 'track-configuration-exit',\n });\n void this.contextMenu.show();\n }\n\n #hasTrackConfigurationMode(): boolean {\n // Track Configuration mode is off by default: a provider must define the\n // function and have it return `true` to enable it.\n return Boolean(this.dataProvider.hasTrackConfigurationMode && this.dataProvider.hasTrackConfigurationMode());\n }\n\n onContextMenu(event: MouseEvent): void {\n const {groupIndex, hoverType} = this.coordinatesToGroupIndexAndHoverType(event.offsetX, event.offsetY);\n\n // If the user is in edit mode, allow a right click anywhere to exit the mode.\n if (this.#inTrackConfigEditMode) {\n this.#buildExitEditModeContextMenu(event);\n return;\n }\n\n // If we are not in edit mode, and the user right clicks on the header,\n // allow them to enter edit mode.\n // Data providers can disable the ability to enter this mode, hence the\n // extra check. For example, in the DevTools Performance Panel the network\n // data provider & flame chart does not support this mode, but the main one\n // does.\n if (hoverType === HoverType.INSIDE_TRACK_HEADER && this.#hasTrackConfigurationMode()) {\n this.#buildEnterEditModeContextMenu(event);\n }\n\n if (this.highlightedEntryIndex === -1) {\n // If the user has not selected an individual entry, we do not show any\n // context menu, so finish here.\n return;\n }\n\n // Update the selected index to match the highlighted index, which\n // represents the entry under the cursor where the user has right clicked\n // to trigger a context menu.\n this.dispatchEventToListeners(Events.ENTRY_INVOKED, this.highlightedEntryIndex);\n this.setSelectedEntry(this.highlightedEntryIndex);\n // Update the selected group as well.\n this.#selectGroup(groupIndex);\n\n // Build the context menu for right clicking individual entries.\n // The context menu only applies if the user is hovering over an individual\n // entry, and we are not in edit mode (which we know we cannot be in given\n // the conditional checks above)\n // If the flame chart provider can build a customized context menu for the\n // given entry, we will use that, otherwise just do nothing and fall back to\n // default context menu.\n // We need to use |selectedEntryIndex| instead of |highlightedEntryIndex|.\n // The reason is when we call the |setSelectedEntry| and |#selectGroup|,\n // the flame chart will be redrawn, so the |highlightedEntryIndex| will be\n // reset to -1.\n // In real life, because we might trigger the |mousemove| event again, the\n // |highlightedEntryIndex| might be correct, but to make the code easier\n // to maintain, let's use |selectedEntryIndex|.\n this.contextMenu = this.dataProvider.customizedContextMenu?.(event, this.selectedEntryIndex, groupIndex) ??\n new UI.ContextMenu.ContextMenu(event, {useSoftMenu: true});\n\n if (Root.Runtime.experiments.isEnabled(Root.Runtime.ExperimentName.TIMELINE_ANNOTATIONS)) {\n const annotationSection = this.contextMenu.section('annotations');\n\n const labelEntryAnnotationOption = annotationSection.appendItem(i18nString(UIStrings.labelEntry), () => {\n this.dispatchEventToListeners(Events.ENTRY_LABEL_ANNOTATION_ADDED, this.selectedEntryIndex);\n });\n\n labelEntryAnnotationOption.setShortcut('Double Click');\n\n const linkEntriesAnnotationOption = annotationSection.appendItem(i18nString(UIStrings.linkEntries), () => {\n this.dispatchEventToListeners(\n Events.ENTRIES_LINK_ANNOTATION_CREATED, {entryFromIndex: this.selectedEntryIndex});\n });\n linkEntriesAnnotationOption.setShortcut('Double Click');\n }\n\n void this.contextMenu.show();\n }\n\n #handleFlameChartTransformEvent(event: KeyboardEvent): void {\n // TODO(crbug.com/1469887): Indicate Shortcuts to the user when the designs are complete.\n if (this.selectedEntryIndex === -1) {\n return;\n }\n this.dataProvider.handleFlameChartTransformKeyboardEvent?.(event, this.selectedEntryIndex, this.selectedGroupIndex);\n }\n\n private onKeyDown(e: KeyboardEvent): void {\n if (!UI.KeyboardShortcut.KeyboardShortcut.hasNoModifiers(e) || !this.timelineData()) {\n return;\n }\n\n let eventHandled = this.handleSelectionNavigation(e);\n\n // Handle keyboard navigation in groups\n if (!eventHandled && this.rawTimelineData && this.rawTimelineData.groups) {\n eventHandled = this.handleKeyboardGroupNavigation(e);\n }\n\n if (!eventHandled) {\n this.#handleFlameChartTransformEvent(e);\n }\n }\n\n bindCanvasEvent(eventName: string, onEvent: (arg0: Event) => void): void {\n this.canvas.addEventListener(eventName, onEvent);\n }\n\n drawTrackOnCanvas(trackName: string, context: CanvasRenderingContext2D, minWidth: number):\n {top: number, height: number, visibleEntries: Set}|null {\n const timelineData = this.timelineData();\n if (!timelineData) {\n return null;\n }\n const canvasWidth = this.offsetWidth;\n const canvasHeight = this.offsetHeight;\n context.save();\n const ratio = window.devicePixelRatio;\n context.scale(ratio, ratio);\n context.fillStyle = 'rgba(0, 0, 0, 0)';\n context.fillRect(0, 0, canvasWidth, canvasHeight);\n context.font = this.#font;\n\n const groups = this.rawTimelineData?.groups || [];\n const groupOffsets = this.groupOffsets;\n if (!groups.length || !groupOffsets) {\n return null;\n }\n const trackIndex = groups.findIndex(g => g.name.includes(trackName));\n if (trackIndex < 0) {\n return null;\n }\n this.scrollGroupIntoView(trackIndex);\n const group = groups[trackIndex];\n const startLevel = group.startLevel;\n const endLevel = groups[trackIndex + 1].startLevel;\n const groupTop = groupOffsets[trackIndex];\n const nextOffset = groupOffsets[trackIndex + 1];\n\n const {colorBuckets, titleIndices} = this.getDrawableData(context, timelineData);\n\n const entryIndexIsInTrack = (index: number): boolean => {\n const barWidth = Math.min(this.#eventBarWidth(timelineData, index), canvasWidth);\n return timelineData.entryLevels[index] >= startLevel && timelineData.entryLevels[index] < endLevel &&\n barWidth > minWidth;\n };\n let allFilteredIndexes: number[] = [];\n for (const [color, {indexes}] of colorBuckets) {\n const filteredIndexes = indexes.filter(entryIndexIsInTrack);\n allFilteredIndexes = [...allFilteredIndexes, ...filteredIndexes];\n this.#drawGenericEvents(context, timelineData, color, filteredIndexes);\n }\n const filteredTitleIndices = titleIndices.filter(entryIndexIsInTrack);\n this.drawEventTitles(context, timelineData, filteredTitleIndices, canvasWidth);\n context.restore();\n return {top: groupOffsets[trackIndex], height: nextOffset - groupTop, visibleEntries: new Set(allFilteredIndexes)};\n }\n\n private handleKeyboardGroupNavigation(event: Event): boolean {\n const keyboardEvent = (event as KeyboardEvent);\n let handled = false;\n let entrySelected = false;\n\n if (keyboardEvent.code === 'ArrowUp') {\n handled = this.selectPreviousGroup();\n } else if (keyboardEvent.code === 'ArrowDown') {\n handled = this.selectNextGroup();\n } else if (keyboardEvent.code === 'ArrowLeft') {\n if (this.keyboardFocusedGroup >= 0) {\n this.expandGroup(this.keyboardFocusedGroup, false /* setExpanded */);\n handled = true;\n }\n } else if (keyboardEvent.code === 'ArrowRight') {\n if (this.keyboardFocusedGroup >= 0) {\n this.expandGroup(this.keyboardFocusedGroup, true /* setExpanded */);\n this.selectFirstChild();\n handled = true;\n }\n } else if (keyboardEvent.key === 'Enter') {\n entrySelected = this.selectFirstEntryInCurrentGroup();\n handled = entrySelected;\n }\n\n if (handled && !entrySelected) {\n this.deselectAllEntries();\n }\n\n if (handled) {\n keyboardEvent.consume(true);\n }\n\n return handled;\n }\n\n private selectFirstEntryInCurrentGroup(): boolean {\n if (!this.rawTimelineData) {\n return false;\n }\n\n const allGroups = this.rawTimelineData.groups;\n\n if (this.keyboardFocusedGroup < 0 || !allGroups) {\n return false;\n }\n\n const group = allGroups[this.keyboardFocusedGroup];\n const startLevelInGroup = group.startLevel;\n\n // Return if no levels in this group\n if (startLevelInGroup < 0) {\n return false;\n }\n\n // Make sure this is the innermost nested group with this startLevel\n // This is because a parent group also contains levels of all its child groups\n // So check if the next group has the same level, if it does, user should\n // go to that child group to select this entry\n if (this.keyboardFocusedGroup < allGroups.length - 1 &&\n allGroups[this.keyboardFocusedGroup + 1].startLevel === startLevelInGroup) {\n return false;\n }\n\n if (!this.timelineLevels) {\n return false;\n }\n\n // Get first (default) entry in startLevel of selected group\n const firstEntryIndex = this.timelineLevels[startLevelInGroup][0];\n\n this.expandGroup(this.keyboardFocusedGroup, true /* setExpanded */);\n this.setSelectedEntry(firstEntryIndex);\n return true;\n }\n\n private selectPreviousGroup(): boolean {\n if (this.keyboardFocusedGroup <= 0) {\n return false;\n }\n\n const groupIndexToSelect = this.getGroupIndexToSelect(-1 /* offset */);\n this.#selectGroup(groupIndexToSelect);\n return true;\n }\n\n private selectNextGroup(): boolean {\n if (!this.rawTimelineData || !this.rawTimelineData.groups) {\n return false;\n }\n\n if (this.keyboardFocusedGroup >= this.rawTimelineData.groups.length - 1) {\n return false;\n }\n\n const groupIndexToSelect = this.getGroupIndexToSelect(1 /* offset */);\n this.#selectGroup(groupIndexToSelect);\n return true;\n }\n\n private getGroupIndexToSelect(offset: number): number {\n if (!this.rawTimelineData || !this.rawTimelineData.groups) {\n throw new Error('No raw timeline data');\n }\n const allGroups = this.rawTimelineData.groups;\n let groupIndexToSelect = this.keyboardFocusedGroup;\n let groupName, groupWithSubNestingLevel;\n\n do {\n groupIndexToSelect += offset;\n groupName = this.rawTimelineData.groups[groupIndexToSelect].name;\n groupWithSubNestingLevel = this.keyboardFocusedGroup !== -1 &&\n allGroups[groupIndexToSelect].style.nestingLevel > allGroups[this.keyboardFocusedGroup].style.nestingLevel;\n } while (groupIndexToSelect > 0 && groupIndexToSelect < allGroups.length - 1 &&\n (!groupName || groupWithSubNestingLevel));\n\n return groupIndexToSelect;\n }\n\n private selectFirstChild(): void {\n if (!this.rawTimelineData || !this.rawTimelineData.groups) {\n return;\n }\n\n const allGroups = this.rawTimelineData.groups;\n if (this.keyboardFocusedGroup < 0 || this.keyboardFocusedGroup >= allGroups.length - 1) {\n return;\n }\n\n const groupIndexToSelect = this.keyboardFocusedGroup + 1;\n if (allGroups[groupIndexToSelect].style.nestingLevel > allGroups[this.keyboardFocusedGroup].style.nestingLevel) {\n this.#selectGroup(groupIndexToSelect);\n }\n }\n\n private handleSelectionNavigation(event: KeyboardEvent): boolean {\n if (this.selectedEntryIndex === -1) {\n return false;\n }\n const timelineData = this.timelineData();\n if (!timelineData) {\n return false;\n }\n\n function timeComparator(time: number, entryIndex: number): number {\n if (!timelineData) {\n throw new Error('No timeline data');\n }\n return time - timelineData.entryStartTimes[entryIndex];\n }\n\n function entriesIntersect(entry1: number, entry2: number): boolean {\n if (!timelineData) {\n throw new Error('No timeline data');\n }\n\n const start1 = timelineData.entryStartTimes[entry1];\n const start2 = timelineData.entryStartTimes[entry2];\n const end1 = start1 + timelineData.entryTotalTimes[entry1];\n const end2 = start2 + timelineData.entryTotalTimes[entry2];\n return start1 < end2 && start2 < end1;\n }\n\n const keyboardEvent = (event as KeyboardEvent);\n const keys = UI.KeyboardShortcut.Keys;\n if (keyboardEvent.keyCode === keys.Left.code || keyboardEvent.keyCode === keys.Right.code) {\n const level = timelineData.entryLevels[this.selectedEntryIndex];\n const levelIndexes = this.timelineLevels ? this.timelineLevels[level] : [];\n let indexOnLevel = Platform.ArrayUtilities.lowerBound(levelIndexes, this.selectedEntryIndex, (a, b) => a - b);\n indexOnLevel += keyboardEvent.keyCode === keys.Left.code ? -1 : 1;\n event.consume(true);\n if (indexOnLevel >= 0 && indexOnLevel < levelIndexes.length) {\n this.dispatchEventToListeners(Events.ENTRY_SELECTED, levelIndexes[indexOnLevel]);\n }\n return true;\n }\n\n if (keyboardEvent.keyCode === keys.Up.code || keyboardEvent.keyCode === keys.Down.code) {\n let level = timelineData.entryLevels[this.selectedEntryIndex];\n level += keyboardEvent.keyCode === keys.Up.code ? -1 : 1;\n if (level < 0 || (this.timelineLevels && level >= this.timelineLevels.length)) {\n this.deselectAllEntries();\n keyboardEvent.consume(true);\n return true;\n }\n const entryTime = timelineData.entryStartTimes[this.selectedEntryIndex] +\n timelineData.entryTotalTimes[this.selectedEntryIndex] / 2;\n const levelIndexes = this.timelineLevels ? this.timelineLevels[level] : [];\n let indexOnLevel = Platform.ArrayUtilities.upperBound(levelIndexes, entryTime, timeComparator) - 1;\n if (!entriesIntersect(this.selectedEntryIndex, levelIndexes[indexOnLevel])) {\n ++indexOnLevel;\n if (indexOnLevel >= levelIndexes.length ||\n !entriesIntersect(this.selectedEntryIndex, levelIndexes[indexOnLevel])) {\n if (keyboardEvent.code === 'ArrowDown') {\n return false;\n }\n\n // Stay in the current group and give focus to the parent group instead of entries\n this.deselectAllEntries();\n keyboardEvent.consume(true);\n return true;\n }\n }\n keyboardEvent.consume(true);\n this.dispatchEventToListeners(Events.ENTRY_SELECTED, levelIndexes[indexOnLevel]);\n return true;\n }\n if (event.key === 'Enter') {\n event.consume(true);\n this.dispatchEventToListeners(Events.ENTRY_INVOKED, this.selectedEntryIndex);\n return true;\n }\n return false;\n }\n\n /**\n * Given offset of the cursor, returns the index of the entry.\n * This function is public for test purpose.\n * @param x\n * @param y\n * @returns the index of the entry\n */\n coordinatesToEntryIndex(x: number, y: number): number {\n if (x < 0 || y < 0) {\n return -1;\n }\n const timelineData = this.timelineData();\n if (!timelineData) {\n return -1;\n }\n y += this.chartViewport.scrollOffset();\n if (!this.visibleLevelOffsets || !this.visibleLevelHeights || !this.visibleLevels) {\n throw new Error('No visible level offsets or heights');\n }\n\n // The real order of the levels might be changed.\n // So we just check each level, and check if the y is between the start and the end of this level. If yes, this is\n // the level we want to find.\n let cursorLevel = -1;\n for (let i = 0; i < this.dataProvider.maxStackDepth(); i++) {\n if (y >= this.visibleLevelOffsets[i] &&\n y < this.visibleLevelOffsets[i] + (this.visibleLevels[i] ? this.visibleLevelHeights[i] : 0)) {\n cursorLevel = i;\n break;\n }\n }\n\n if (cursorLevel < 0 || !this.visibleLevels[cursorLevel]) {\n return -1;\n }\n const offsetFromLevel = y - this.visibleLevelOffsets[cursorLevel];\n if (offsetFromLevel > this.levelHeight(cursorLevel)) {\n return -1;\n }\n\n // Check markers first.\n for (const [index, pos] of this.markerPositions) {\n if (timelineData.entryLevels[index] !== cursorLevel) {\n continue;\n }\n if (pos.x <= x && x < pos.x + pos.width) {\n return index as number;\n }\n }\n\n // Check regular entries.\n const entryStartTimes = timelineData.entryStartTimes;\n const entriesOnLevel: number[] = this.timelineLevels ? this.timelineLevels[cursorLevel] : [];\n if (!entriesOnLevel || !entriesOnLevel.length) {\n return -1;\n }\n\n const cursorTime = this.chartViewport.pixelToTime(x);\n const indexOnLevel = Math.max(\n Platform.ArrayUtilities.upperBound(\n entriesOnLevel, cursorTime, (time, entryIndex) => time - entryStartTimes[entryIndex]) -\n 1,\n 0);\n\n function checkEntryHit(this: FlameChart, entryIndex: number|undefined): boolean {\n if (entryIndex === undefined) {\n return false;\n }\n\n if (!timelineData) {\n return false;\n }\n\n const startTime = entryStartTimes[entryIndex];\n const duration = timelineData.entryTotalTimes[entryIndex];\n const startX = this.chartViewport.timeToPosition(startTime);\n const endX = this.chartViewport.timeToPosition(startTime + duration);\n return startX - this.hitMarginPx < x && x < endX + this.hitMarginPx;\n }\n\n let entryIndex: number = entriesOnLevel[indexOnLevel];\n if (checkEntryHit.call(this, entryIndex)) {\n return entryIndex;\n }\n entryIndex = entriesOnLevel[indexOnLevel + 1];\n if (checkEntryHit.call(this, entryIndex)) {\n return entryIndex;\n }\n return -1;\n }\n\n /**\n * Given an entry's index and an X coordinate of a mouse click, returns\n * whether the mouse is hovering over the arrow button that reveals hidden children\n */\n isMouseOverRevealChildrenArrow(x: number, index: number): boolean {\n // Check if given entry has an arrow\n if (!this.entryHasDecoration(index, FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW)) {\n return false;\n }\n const timelineData = this.timelineData();\n if (!timelineData) {\n return false;\n }\n const startTime = timelineData.entryStartTimes[index];\n const duration = timelineData.entryTotalTimes[index];\n const endX = this.chartViewport.timeToPosition(startTime + duration);\n // The arrow icon is square, thefore the width is equal to the bar height\n const barHeight = this.#eventBarHeight(timelineData, index);\n const arrowWidth = barHeight;\n if (endX - arrowWidth - this.hitMarginPx < x && x < endX + this.hitMarginPx) {\n return true;\n }\n return false;\n }\n\n /**\n * Given an entry's index, returns its coordinates relative to the\n * viewport.\n * This function is public for test purpose.\n */\n entryIndexToCoordinates(entryIndex: number): {x: number, y: number}|null {\n const timelineData = this.timelineData();\n const {x: canvasViewportOffsetX, y: canvasViewportOffsetY} = this.canvas.getBoundingClientRect();\n if (!timelineData || !this.visibleLevelOffsets) {\n return null;\n }\n\n const x = this.chartViewport.timeToPosition(timelineData.entryStartTimes[entryIndex]) + canvasViewportOffsetX;\n const y = this.visibleLevelOffsets[timelineData.entryLevels[entryIndex]] - this.chartViewport.scrollOffset() +\n canvasViewportOffsetY;\n return {x, y};\n }\n\n /**\n * Given an entry's index, returns its title\n */\n entryTitle(entryIndex: number): string|null {\n return this.dataProvider.entryTitle(entryIndex);\n }\n\n /**\n * Returns the offset of the canvas relative to the viewport.\n */\n getCanvasOffset(): {x: number, y: number} {\n return this.canvas.getBoundingClientRect();\n }\n\n getCanvas(): HTMLCanvasElement {\n return this.canvas;\n }\n\n /**\n * Returns the y scroll of the chart viewport.\n */\n getScrollOffset(): number {\n return this.chartViewport.scrollOffset();\n }\n\n getContextMenu(): UI.ContextMenu.ContextMenu|undefined {\n return this.contextMenu;\n }\n\n /**\n * Given offset of the cursor, returns the index of the group and the hover type of current mouse position.\n * Will return -1 for index and HoverType.OUTSIDE_TRACKS if no group is hovered/clicked.\n * And the handle priority will be:\n * 1. Track configuration icons\n * 2. Inside a track header (track label and the expansion arrow)\n * 3. Inside a track\n * 4. Outside all tracks\n *\n * This function is public for test purpose.\n * @param x\n * @param y\n * @returns the index of the group and the button user clicked. If there is no button the button type will be\n * undefined.\n */\n coordinatesToGroupIndexAndHoverType(x: number, y: number): {groupIndex: number, hoverType: HoverType} {\n if (!this.rawTimelineData || !this.rawTimelineData.groups || !this.groupOffsets) {\n return {groupIndex: -1, hoverType: HoverType.ERROR};\n }\n\n if (x < 0 || y < 0) {\n return {groupIndex: -1, hoverType: HoverType.ERROR};\n }\n y += this.chartViewport.scrollOffset();\n const groups = this.rawTimelineData.groups || [];\n\n // The real order of the groups is the preorder traversal, and it will match the order in the sortedGroup.\n // So we first do a preorder traversal to get an array of GroupIndex. And then based on the visual index we got\n // before, we can get the real group index.\n if (this.#groupTreeRoot) {\n const sortedGroupIndexes: number[] = [];\n\n function traverse(root: GroupTreeNode): void {\n sortedGroupIndexes.push(root.index);\n for (const child of root.children) {\n traverse(child);\n }\n }\n traverse(this.#groupTreeRoot);\n // Skip the one whose index is -1, because we added to represent the top\n // level to be the parent of all groups.\n sortedGroupIndexes.shift();\n\n // This shouldn't happen, because the tree should have the fake root and all groups. Add a sanity check to avoid\n // error.\n if (sortedGroupIndexes.length !== groups.length) {\n console.warn('The data from the group tree doesn\\'t match the data from DataProvider.');\n return {groupIndex: -1, hoverType: HoverType.ERROR};\n }\n\n // Add an extra index, which is equal to the length of the |groups|, this\n // will be used for the coordinates after the last group.\n // If the coordinates after the last group, it will return in later check\n // `groupIndex >= groups.length` anyway. But add one more element to make\n // this array same length as the |groupOffsets|.\n sortedGroupIndexes.push(groups.length);\n\n for (let i = 0; i < sortedGroupIndexes.length; i++) {\n const groupIndex = sortedGroupIndexes[i];\n const nextIndex = sortedGroupIndexes[i + 1] ?? sortedGroupIndexes.length;\n\n if (y >= this.groupOffsets[groupIndex] && y < this.groupOffsets[nextIndex]) {\n // This section is used to calculate the position of current group's header\n // If we are in edit mode, the track label is pushed right to make room for the icons.\n const context = (this.canvas.getContext('2d') as CanvasRenderingContext2D);\n context.save();\n context.font = this.#font;\n const headerRight = HEADER_LEFT_PADDING + (this.#inTrackConfigEditMode ? EDIT_MODE_TOTAL_ICON_WIDTH : 0) +\n this.labelWidthForGroup(context, groups[groupIndex]);\n context.restore();\n\n const mouseInHeaderRow =\n y >= this.groupOffsets[groupIndex] && y < this.groupOffsets[groupIndex] + groups[groupIndex].style.height;\n\n if (this.#inTrackConfigEditMode) {\n if (mouseInHeaderRow) {\n if (UP_ICON_LEFT <= x && x < UP_ICON_LEFT + EDIT_ICON_WIDTH) {\n return {groupIndex, hoverType: HoverType.TRACK_CONFIG_UP_BUTTON};\n }\n if (DOWN_ICON_LEFT <= x && x < DOWN_ICON_LEFT + EDIT_ICON_WIDTH) {\n return {groupIndex, hoverType: HoverType.TRACK_CONFIG_DOWN_BUTTON};\n }\n if (HIDE_ICON_LEFT <= x && x < HIDE_ICON_LEFT + EDIT_ICON_WIDTH) {\n return {\n groupIndex,\n hoverType: groups[groupIndex].hidden ? HoverType.TRACK_CONFIG_SHOW_BUTTON :\n HoverType.TRACK_CONFIG_HIDE_BUTTON,\n };\n }\n if (mouseInHeaderRow && x <= headerRight) {\n return {groupIndex, hoverType: HoverType.INSIDE_TRACK_HEADER};\n }\n }\n // Ignore any other actions when user is customizing the tracks.\n // For example, we won't toggle the expand status in the editing mode.\n } else {\n // User is not in edit mode so they can either be in the header, or in the track.\n if (mouseInHeaderRow && x <= headerRight) {\n return {groupIndex, hoverType: HoverType.INSIDE_TRACK_HEADER};\n }\n return {groupIndex, hoverType: HoverType.INSIDE_TRACK};\n }\n }\n }\n }\n\n return {groupIndex: -1, hoverType: HoverType.OUTSIDE_TRACKS};\n }\n\n #enterEditMode(): void {\n const div = document.createElement('div');\n div.classList.add('flame-chart-edit-confirm');\n const button = new Buttons.Button.Button();\n button.data = {\n variant: Buttons.Button.Variant.PRIMARY,\n jslogContext: 'track-configuration-exit',\n };\n button.innerText = i18nString(UIStrings.exitTrackConfigurationMode);\n div.appendChild(button);\n button.addEventListener('click', () => {\n this.#exitEditMode();\n });\n\n this.viewportElement.appendChild(div);\n this.#inTrackConfigEditMode = true;\n this.updateLevelPositions();\n this.draw();\n }\n\n #removeEditModeButton(): void {\n const confirmButton = this.viewportElement.querySelector('.flame-chart-edit-confirm');\n if (confirmButton) {\n this.viewportElement.removeChild(confirmButton);\n }\n }\n\n #exitEditMode(): void {\n this.#removeEditModeButton();\n this.#inTrackConfigEditMode = false;\n this.updateLevelPositions();\n this.draw();\n }\n\n private markerIndexBeforeTime(time: number): number {\n const timelineData = this.timelineData();\n if (!timelineData) {\n throw new Error('No timeline data');\n }\n\n const markers = timelineData.markers;\n if (!markers) {\n throw new Error('No timeline markers');\n }\n\n return Platform.ArrayUtilities.lowerBound(\n timelineData.markers, time, (markerTimestamp, marker) => markerTimestamp - marker.startTime());\n }\n\n /**\n * Draw the whole flame chart.\n * Make sure |setWindowTimes| is called with correct time range before this function.\n */\n private draw(): void {\n const timelineData = this.timelineData();\n if (!timelineData) {\n return;\n }\n this.resetCanvas();\n\n this.dispatchEventToListeners(Events.LATEST_DRAW_DIMENSIONS, {\n chart: {\n widthPixels: this.offsetWidth,\n heightPixels: this.offsetHeight,\n scrollOffsetPixels: this.chartViewport.scrollOffset(),\n // If there are no groups because we have no timeline data, we treat\n // that as all being collapsed.\n allGroupsCollapsed: this.rawTimelineData?.groups.every(g => !g.expanded) ?? true,\n },\n traceWindow:\n TraceEngine.Helpers.Timing.traceWindowFromMilliSeconds(this.minimumBoundary(), this.maximumBoundary()),\n });\n const canvasWidth = this.offsetWidth;\n const canvasHeight = this.offsetHeight;\n const context = (this.canvas.getContext('2d') as CanvasRenderingContext2D);\n\n context.save();\n const ratio = window.devicePixelRatio;\n const top = this.chartViewport.scrollOffset();\n context.scale(ratio, ratio);\n // Clear the canvas area by drawing a white square first\n context.fillStyle = 'rgba(0, 0, 0, 0)';\n context.fillRect(0, 0, canvasWidth, canvasHeight);\n context.translate(0, -top);\n context.font = this.#font;\n\n const {markerIndices, colorBuckets, titleIndices} = this.getDrawableData(context, timelineData);\n\n context.save();\n this.forEachGroupInViewport((offset, index, group, isFirst, groupHeight) => {\n if (this.isGroupFocused(index)) {\n context.fillStyle =\n ThemeSupport.ThemeSupport.instance().getComputedValue('--selected-group-background', this.contentElement);\n context.fillRect(0, offset, canvasWidth, groupHeight - group.style.padding);\n }\n });\n context.restore();\n\n const groups = this.rawTimelineData?.groups || [];\n const trackIndex = groups.findIndex(g => g.name.includes('Main'));\n const group = groups.at(trackIndex);\n const startLevel = group?.startLevel;\n const endLevel = groups.at(trackIndex + 1)?.startLevel;\n const entryIndexIsInTrack = (index: number): boolean => {\n if (trackIndex < 0 || startLevel === undefined || endLevel === undefined) {\n return false;\n }\n const barWidth = Math.min(this.#eventBarWidth(timelineData, index), canvasWidth);\n return timelineData.entryLevels[index] >= startLevel && timelineData.entryLevels[index] < endLevel &&\n barWidth > 10;\n };\n let wideEntryExists: boolean = false;\n for (const [color, {indexes}] of colorBuckets) {\n if (!wideEntryExists) {\n wideEntryExists = indexes.some(entryIndexIsInTrack);\n }\n this.#drawGenericEvents(context, timelineData, color, indexes);\n }\n this.dispatchEventToListeners(Events.CHART_PLAYABLE_STATE_CHANGED, wideEntryExists);\n\n this.drawMarkers(context, timelineData, markerIndices);\n\n this.drawEventTitles(context, timelineData, titleIndices, canvasWidth);\n\n // If there is a `forceDecoration` function, it will be called in `drawEventTitles`, which will overwrite the\n // default decorations, so we need to call this function after the `drawEventTitles`.\n const allIndexes = Array.from(colorBuckets.values()).map(x => x.indexes).flat();\n this.#drawDecorations(context, timelineData, allIndexes);\n context.restore();\n\n this.drawGroupHeaders(canvasWidth, canvasHeight);\n this.drawFlowEvents(context, timelineData);\n this.drawMarkerLines();\n const dividersData = TimelineGrid.calculateGridOffsets(this);\n const navStartTimes = this.dataProvider.mainFrameNavigationStartEvents?.() || [];\n\n let navStartTimeIndex = 0;\n const drawAdjustedTime = (time: number): string => {\n if (navStartTimes.length === 0) {\n return this.formatValue(time, dividersData.precision);\n }\n\n // Track when the time crosses the boundary to the next nav start record,\n // and when it does, move the nav start array index accordingly.\n const hasNextNavStartTime = navStartTimes.length > navStartTimeIndex + 1;\n if (hasNextNavStartTime) {\n const nextNavStartTime = navStartTimes[navStartTimeIndex + 1];\n const nextNavStartTimeStartTimestamp =\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds(nextNavStartTime.ts);\n if (time > nextNavStartTimeStartTimestamp) {\n navStartTimeIndex++;\n }\n }\n\n // Adjust the time by the nearest nav start marker's value.\n const nearestMarker = navStartTimes[navStartTimeIndex];\n if (nearestMarker) {\n const nearestMarkerStartTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(nearestMarker.ts);\n time -= nearestMarkerStartTime - this.zeroTime();\n }\n\n return this.formatValue(time, dividersData.precision);\n };\n\n TimelineGrid.drawCanvasGrid(context, dividersData);\n if (this.rulerEnabled) {\n TimelineGrid.drawCanvasHeaders(context, dividersData, drawAdjustedTime, 3, RulerHeight);\n }\n\n this.updateElementPosition(this.highlightElement, this.highlightedEntryIndex);\n this.updateElementPosition(this.selectedElement, this.selectedEntryIndex);\n\n if (this.#searchResultEntryIndex !== -1) {\n this.showPopoverForSearchResult(this.#searchResultEntryIndex);\n }\n for (const element of this.#searchResultHighlightElements) {\n this.updateElementPosition(element, Number(element.id));\n }\n this.updateMarkerHighlight();\n }\n\n /**\n * Draws generic flame chart events, that is, the plain rectangles that fill several parts\n * in the timeline like the Main Thread flamechart and the timings track.\n * Drawn on a color by color basis to minimize the amount of times context.style is switched.\n */\n #drawGenericEvents(\n context: CanvasRenderingContext2D, timelineData: FlameChartTimelineData, color: string, indexes: number[]): void {\n context.save();\n context.beginPath();\n for (let i = 0; i < indexes.length; ++i) {\n const entryIndex = indexes[i];\n this.#drawEventRect(context, timelineData, entryIndex);\n }\n context.fillStyle = color;\n context.fill();\n context.restore();\n }\n\n /**\n * Draws decorations onto events. {@see FlameChartDecoration}.\n */\n #drawDecorations(context: CanvasRenderingContext2D, timelineData: FlameChartTimelineData, indexes: number[]): void {\n const {entryTotalTimes, entryStartTimes, entryLevels} = timelineData;\n context.save();\n for (let i = 0; i < indexes.length; ++i) {\n const entryIndex = indexes[i];\n const decorationsForEvent = timelineData.entryDecorations.at(entryIndex);\n if (!decorationsForEvent || decorationsForEvent.length < 1) {\n continue;\n }\n if (decorationsForEvent.length > 1) {\n sortDecorationsForRenderingOrder(decorationsForEvent);\n }\n const entryStartTime = entryStartTimes[entryIndex];\n const duration = entryTotalTimes[entryIndex];\n const barX = this.timeToPositionClipped(entryStartTime);\n const barLevel = entryLevels[entryIndex];\n const barHeight = this.#eventBarHeight(timelineData, entryIndex);\n const barY = this.levelToOffset(barLevel);\n let barWidth = this.#eventBarWidth(timelineData, entryIndex);\n\n for (const decoration of decorationsForEvent) {\n switch (decoration.type) {\n case FlameChartDecorationType.CANDY: {\n const candyStripeStartTime = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(decoration.startAtTime);\n if (duration < candyStripeStartTime) {\n // If the duration of the event is less than the start time to draw the candy stripes, then we have no stripes to draw.\n continue;\n }\n if (!this.candyStripePattern) {\n this.candyStripePattern = this.createCandyStripePattern();\n }\n\n context.save();\n context.beginPath();\n // Draw a rectangle over the event, starting at the X value of the\n // event's start time + the startDuration of the candy striping.\n const barXStart = this.timeToPositionClipped(entryStartTime + candyStripeStartTime);\n\n // If a custom end time was passed in, that is when we stop striping, else we stripe until the very end of the entry.\n const stripingEndTime = decoration.endAtTime ?\n TraceEngine.Helpers.Timing.microSecondsToMilliseconds(decoration.endAtTime) :\n entryStartTime + duration;\n const barXEnd = this.timeToPositionClipped(stripingEndTime);\n this.#drawEventRect(context, timelineData, entryIndex, {\n startX: barXStart,\n width: barXEnd - barXStart,\n });\n context.fillStyle = this.candyStripePattern;\n context.fill();\n context.restore();\n break;\n }\n case FlameChartDecorationType.WARNING_TRIANGLE: {\n let endTimePixels = barX + barWidth;\n if (typeof decoration.customEndTime !== 'undefined') {\n // The user can pass a customEndTime to tell us where the event's box ends and therefore where we should\n // draw the triangle. So therefore we calculate the width by taking the end time off the start time.\n const endTimeMilli = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(decoration.customEndTime);\n endTimePixels = this.timeToPositionClipped(endTimeMilli);\n barWidth = endTimePixels - barX;\n }\n const triangleHeight = 8;\n let triangleWidth = 8;\n if (typeof decoration.customStartTime !== 'undefined') {\n // The user can pass a customStartTime to tell us where the event's box start and therefore where we\n // should draw the triangle. So therefore we calculate the width by taking the end time off the start\n // time.\n const startTimeMilli = TraceEngine.Helpers.Timing.microSecondsToMilliseconds(decoration.customStartTime);\n const startTimePixels = this.timeToPositionClipped(startTimeMilli);\n triangleWidth = Math.min(endTimePixels - startTimePixels, 8);\n }\n context.save();\n context.beginPath();\n context.rect(barX, barY, barWidth, barHeight);\n context.clip();\n context.beginPath();\n context.fillStyle = 'red';\n context.moveTo(barX + barWidth - triangleWidth, barY);\n context.lineTo(barX + barWidth, barY);\n context.lineTo(barX + barWidth, barY + triangleHeight);\n context.fill();\n context.restore();\n break;\n }\n case FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW: {\n context.save();\n context.beginPath();\n context.rect(barX, barY, barWidth, barHeight);\n const arrowSize = barHeight;\n // If the bar is wider than double the arrow button, draw the button. Otherwise, draw a corner triangle to indicate some entries are hidden\n if (barWidth > arrowSize * 2) {\n const triangleSize = 7;\n const triangleHorizontalPadding = 5;\n const triangleVerrticalPadding = 6;\n context.clip();\n context.beginPath();\n context.fillStyle = '#474747';\n const arrowAX = barX + barWidth - triangleSize - triangleHorizontalPadding;\n const arrowAY = barY + triangleVerrticalPadding;\n context.moveTo(arrowAX, arrowAY);\n const arrowBX = barX + barWidth - triangleHorizontalPadding;\n const arrowBY = barY + triangleVerrticalPadding;\n context.lineTo(arrowBX, arrowBY);\n const arrowCX = barX + barWidth - triangleHorizontalPadding - triangleSize / 2;\n const arrowCY = barY + barHeight - triangleVerrticalPadding;\n context.lineTo(arrowCX, arrowCY);\n } else {\n const triangleSize = 8;\n context.clip();\n context.beginPath();\n context.fillStyle = '#474747';\n context.moveTo(barX + barWidth - triangleSize, barY + barHeight);\n context.lineTo(barX + barWidth, barY + barHeight);\n context.lineTo(barX + barWidth, barY + triangleSize);\n }\n context.fill();\n context.restore();\n break;\n }\n }\n }\n }\n context.restore();\n }\n\n /**\n * Draws (but does not fill) a rectangle for a given event onto the provided\n * context. Because sometimes we need to draw a portion of the rect, it\n * optionally allows the start X and width of the rect to be overriden by\n * custom pixel values. It currently does not allow the start Y and height to\n * be changed because we have no need to do so, but this can be extended in\n * the future if required.\n **/\n #drawEventRect(\n context: CanvasRenderingContext2D, timelineData: FlameChartTimelineData, entryIndex: number, overrides?: {\n startX?: number,\n width?: number,\n }): void {\n const {entryTotalTimes, entryStartTimes, entryLevels} = timelineData;\n const duration = entryTotalTimes[entryIndex];\n if (isNaN(duration)) {\n return;\n }\n const entryStartTime = entryStartTimes[entryIndex];\n const barX = overrides?.startX ?? this.timeToPositionClipped(entryStartTime);\n const barLevel = entryLevels[entryIndex];\n const barHeight = this.#eventBarHeight(timelineData, entryIndex);\n const barY = this.levelToOffset(barLevel);\n const barWidth = overrides?.width ?? this.#eventBarWidth(timelineData, entryIndex);\n if (barWidth === 0) {\n return;\n }\n // We purposefully leave a 1px gap off the height so there is a small gap\n // visually between events vertically in the panel.\n // Similarly, we leave 0.5 pixels off the width so that there is a small\n // gap between events. Otherwise if a trace has a lot of events it looks\n // like one solid block and is not very easy to distinguish when events\n // start and end.\n context.rect(barX, barY, barWidth - 0.5, barHeight - 1);\n }\n\n #eventBarHeight(timelineData: FlameChartTimelineData, entryIndex: number): number {\n const {entryLevels} = timelineData;\n const barLevel = entryLevels[entryIndex];\n const barHeight = this.levelHeight(barLevel);\n return barHeight;\n }\n\n entryWidth(entryIndex: number): number {\n const timelineData = this.timelineData();\n if (!timelineData) {\n return 0;\n }\n return this.#eventBarWidth(timelineData, entryIndex);\n }\n\n #eventBarWidth(timelineData: FlameChartTimelineData, entryIndex: number): number {\n const {entryTotalTimes, entryStartTimes} = timelineData;\n const duration = entryTotalTimes[entryIndex];\n const entryStartTime = entryStartTimes[entryIndex];\n const barXStart = this.timeToPositionClipped(entryStartTime);\n const barXEnd = this.timeToPositionClipped(entryStartTime + duration);\n // Ensure that the width of the bar is at least one pixel.\n const barWidth = Math.max(barXEnd - barXStart, 1);\n return barWidth;\n }\n\n /**\n * Preprocess the data to be drawn to speed the rendering time.\n * Especifically:\n * - Groups events into color buckets.\n * - Discards non visible events.\n * - Gathers marker events (LCP, FCP, DCL, etc.).\n * - Gathers event titles that should be rendered.\n */\n private getDrawableData(context: CanvasRenderingContext2D, timelineData: FlameChartTimelineData):\n {colorBuckets: Map, titleIndices: number[], markerIndices: number[]} {\n // These are the event indexes of events that we are drawing onto the timeline that:\n // 1) have text within them\n // 2) are visually wide enough in pixels to make it worth rendering the text.\n const titleIndices: number[] = [];\n\n // These point to events that represent single points in the timeline, most\n // often an event such as DCL/LCP.\n const markerIndices: number[] = [];\n const {entryTotalTimes, entryStartTimes} = timelineData;\n\n const top = this.chartViewport.scrollOffset();\n\n const textPadding = this.textPadding;\n // How wide in pixels / long in duration an event needs to be to make it\n // worthwhile rendering the text inside it.\n const minTextWidth = 2 * textPadding + UI.UIUtils.measureTextWidth(context, '…');\n const minTextWidthDuration = this.chartViewport.pixelToTimeOffset(minTextWidth);\n\n // As we parse each event, we bucket them into groups based on the color we\n // will render them with. The key of this map will be a color, and all\n // events stored in the `indexes` array for that color will be painted as\n // such. This way, when rendering events, we can render them based on\n // color, and ensure the minimum amount of changes to context.fillStyle.\n const colorBuckets = new Map();\n for (let level = 0; level < this.dataProvider.maxStackDepth(); ++level) {\n // Since tracks can be reordered the |visibleLevelOffsets| is not necessarily sorted, so we need to check all levels.\n // Note that to check if a level is off the top of the screen, we can't\n // just check its offset, because then the level will disappear the\n // moment it is 1px off the top of the screen. So instead we check that\n // the entire height of the level is off the top of the screen before\n // skipping it.\n if (this.levelToOffset(level) + this.levelHeight(level) < top ||\n this.levelToOffset(level) > top + this.offsetHeight) {\n continue;\n }\n if (!this.visibleLevels || !this.visibleLevels[level]) {\n continue;\n }\n if (!this.timelineLevels) {\n break;\n }\n\n // Entries are ordered by start time within a level, so find the last visible entry.\n const levelIndexes = this.timelineLevels[level];\n const rightIndexOnLevel = Platform.ArrayUtilities.lowerBound(\n levelIndexes, this.chartViewport.windowRightTime(),\n (time, entryIndex) => time - entryStartTimes[entryIndex]) -\n 1;\n let lastDrawOffset = Infinity;\n for (let entryIndexOnLevel = rightIndexOnLevel; entryIndexOnLevel >= 0; --entryIndexOnLevel) {\n const entryIndex = levelIndexes[entryIndexOnLevel];\n const duration = entryTotalTimes[entryIndex];\n // Markers are single events in time (e.g. LCP): they do not have a duration.\n if (isNaN(duration)) {\n markerIndices.push(entryIndex);\n continue;\n }\n\n if (duration >= minTextWidthDuration || this.forceDecorationCache?.[entryIndex]) {\n // If the event is big enough visually to have its text rendered,\n // or if it's in the array of event indexes that we forcibly render (as defined by the data provider)\n // then we store its index. Later on, we'll loop through all\n // `titleIndices` to render the text for each event.\n titleIndices.push(entryIndex);\n }\n\n const entryStartTime = entryStartTimes[entryIndex];\n const entryOffsetRight = entryStartTime + duration;\n const levelForcedDrawable = Boolean(this.dataProvider.forceDrawableLevel?.(level));\n if (entryOffsetRight <= this.chartViewport.windowLeftTime() && !levelForcedDrawable) {\n // If the event is entirely to the left of the visible window, and the level is not forced to be drawn, we can stop processing this level.\n break;\n }\n\n const barX = this.timeToPositionClipped(entryStartTime);\n // Check if the entry entirely fits into an already drawn pixel, we can just skip drawing it.\n if (barX >= lastDrawOffset) {\n continue;\n }\n lastDrawOffset = barX;\n\n if (this.entryColorsCache) {\n const color = this.entryColorsCache[entryIndex];\n let bucket = colorBuckets.get(color);\n if (!bucket) {\n bucket = {indexes: []};\n colorBuckets.set(color, bucket);\n }\n bucket.indexes.push(entryIndex);\n }\n }\n }\n return {colorBuckets, titleIndices, markerIndices};\n }\n\n /**\n * The function to draw the group headers. It will draw the title by default.\n * And when a group is hovered, it will add a edit button.\n * And will draw the move up/down, hide and save button if user enter the editing mode.\n * @param width\n * @param height\n * @param hoveredGroupIndex This is used to show the edit icon for hovered group. If it is undefined or -1, it means\n * there is no group being hovered.\n */\n private drawGroupHeaders(width: number, height: number): void {\n const context = (this.canvas.getContext('2d') as CanvasRenderingContext2D);\n const top = this.chartViewport.scrollOffset();\n const ratio = window.devicePixelRatio;\n if (!this.rawTimelineData) {\n return;\n }\n\n const groups = this.rawTimelineData.groups || [];\n if (!groups.length) {\n return;\n }\n\n const groupOffsets = this.groupOffsets;\n if (groupOffsets === null || groupOffsets === undefined) {\n return;\n }\n const lastGroupOffset = groupOffsets[groupOffsets.length - 1];\n\n context.save();\n context.scale(ratio, ratio);\n context.translate(0, -top);\n context.font = this.#font;\n\n context.fillStyle = ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-cdt-base-container');\n // Fill the gap between groups.\n this.forEachGroupInViewport((offset, index, group) => {\n const paddingHeight = group.style.padding;\n if (paddingHeight < 5) {\n return;\n }\n context.fillRect(0, offset - paddingHeight + 2, width, paddingHeight - 4);\n });\n // Fill the gap between last group and the bottom of canvas view.\n if (groups.length && lastGroupOffset < top + height) {\n context.fillRect(0, lastGroupOffset + 2, width, top + height - lastGroupOffset);\n }\n\n // The separating line between top level groups.\n context.strokeStyle = ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-neutral-container');\n context.beginPath();\n // Draw a separator line at the beginning of each top-level group (except the first one).\n this.forEachGroupInViewport((offset, index, group, isFirst) => {\n if (isFirst || group.style.padding < 4) {\n return;\n }\n horizontalLine(context, width, offset - 2.5);\n });\n // Draw a separator line at the end of all groups.\n horizontalLine(context, width, lastGroupOffset + 1.5);\n context.stroke();\n\n this.forEachGroupInViewport((offset, index, group) => {\n if (group.style.useFirstLineForOverview) {\n return;\n }\n if (!this.isGroupCollapsible(index) || group.expanded) {\n if (!group.style.shareHeaderLine && this.isGroupFocused(index)) {\n context.fillStyle = group.style.backgroundColor;\n context.fillRect(0, offset, width, group.style.height);\n }\n return;\n }\n let nextGroup = index + 1;\n while (nextGroup < groups.length && groups[nextGroup].style.nestingLevel > group.style.nestingLevel) {\n nextGroup++;\n }\n const endLevel = nextGroup < groups.length ? groups[nextGroup].startLevel : this.dataProvider.maxStackDepth();\n this.drawCollapsedOverviewForGroup(group, offset, endLevel);\n });\n\n context.save();\n // If there is only one track, we won't allow the track reordering or hiding.\n const trackConfigurationAllowed = groups.length > 1;\n\n // When it is normal mode, there are no icons to the left of a track.\n // When it is in edit mode, there are three icons to customize the groups.\n const iconsWidth = this.#inTrackConfigEditMode ? EDIT_MODE_TOTAL_ICON_WIDTH : 0;\n this.forEachGroupInViewport((offset, index, group) => {\n context.font = this.#font;\n if (this.isGroupCollapsible(index) && !group.expanded || group.style.shareHeaderLine) {\n // In edit mode, we draw an extra rectangle for the save icon.\n const labelBackgroundWidth = this.labelWidthForGroup(context, group);\n if (this.isGroupFocused(index)) {\n context.fillStyle =\n ThemeSupport.ThemeSupport.instance().getComputedValue('--selected-group-background', this.contentElement);\n } else {\n const parsedColor = Common.Color.parse(group.style.backgroundColor);\n if (parsedColor) {\n context.fillStyle = (parsedColor.setAlpha(0.8).asString() as string);\n }\n }\n context.fillRect(\n iconsWidth + HEADER_LEFT_PADDING, offset + HEADER_LABEL_Y_PADDING, labelBackgroundWidth,\n group.style.height - 2 * HEADER_LABEL_Y_PADDING);\n }\n context.fillStyle = (this.#inTrackConfigEditMode && group.hidden) ?\n ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-token-subtle', this.contentElement) :\n group.style.color;\n\n // The arrow is drawn from the center, so the indent is in fact the center of the arrow. See `drawExpansionArrow`\n // function to understand how we draw the arrow.\n // So the header looks like this:\n // |ICON_WIDTH|expansionArrowIndent * (nesting level + 1)|\n // |headerLeftPadding|EDIT ICON| |Arrow|LabelXPadding|Title|LabelXPadding|\n // ^ titleStart\n const titleStart = iconsWidth + EXPANSION_ARROW_INDENT * (group.style.nestingLevel + 1) + ARROW_SIDE / 2 +\n HEADER_LABEL_X_PADDING;\n context.fillText(group.name, titleStart, offset + group.style.height - this.textBaseline);\n if (this.#inTrackConfigEditMode && group.hidden) {\n // Draw a strikethrough line for the hidden tracks.\n context.fillRect(\n titleStart, offset + group.style.height / 2, UI.UIUtils.measureTextWidth(context, group.name), 1);\n }\n\n if (group.legends && group.expanded) {\n drawLegends(\n context, HEADER_LEFT_PADDING + this.labelWidthForGroup(context, group) + LEGEND_LEFT_PADDING, offset,\n group.legends);\n }\n // The icon and track title will look like this\n // Normal mode:\n // Track title\n // Edit mode:\n // [ Up ][Down][Hide]Track title\n if (trackConfigurationAllowed) {\n if (this.#inTrackConfigEditMode) {\n const iconColor = group.hidden ? '--sys-color-token-subtle' : '--sys-color-on-surface';\n // We only allow to reorder the top level groups.\n if (group.style.nestingLevel === 0) {\n drawIcon(context, UP_ICON_LEFT, offset, EDIT_ICON_WIDTH, moveUpIconPath, iconColor);\n drawIcon(context, DOWN_ICON_LEFT, offset, EDIT_ICON_WIDTH, moveDownIconPath, iconColor);\n }\n // If this is the last visible top-level group, we will disable the hide action.\n drawIcon(\n context, HIDE_ICON_LEFT, offset, EDIT_ICON_WIDTH, group.hidden ? showIconPath : hideIconPath,\n this.groupIsLastVisibleTopLevel(group) ? '--sys-color-state-disabled' : iconColor);\n }\n }\n });\n context.restore();\n\n context.fillStyle = ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-token-subtle');\n this.forEachGroupInViewport((offset, index, group) => {\n if (this.isGroupCollapsible(index)) {\n drawExpansionArrow(\n context, iconsWidth + EXPANSION_ARROW_INDENT * (group.style.nestingLevel + 1),\n offset + group.style.height - this.textBaseline - ARROW_SIDE / 2,\n this.#inTrackConfigEditMode ? false : Boolean(group.expanded));\n }\n });\n\n context.strokeStyle = ThemeSupport.ThemeSupport.instance().getComputedValue('--sys-color-neutral-outline');\n context.beginPath();\n context.stroke();\n\n this.forEachGroupInViewport((offset, index, group, isFirst, groupHeight) => {\n if (this.isGroupFocused(index)) {\n const lineWidth = 2;\n const bracketLength = 10;\n context.fillStyle =\n ThemeSupport.ThemeSupport.instance().getComputedValue('--selected-group-border', this.contentElement);\n // The selected group indicator will be blue and in this kind of shape. And we will draw it with three\n // rectangles.\n // +-+---+\n // |-|---+\n // | |\n // | |\n // |-|---+\n // +-+---+\n\n // The vertical stroke\n context.fillRect(0, offset - lineWidth, lineWidth, groupHeight - group.style.padding + 2 * lineWidth);\n // The top horizontal stroke\n context.fillRect(0, offset - lineWidth, bracketLength, lineWidth);\n // The top horizontal stroke\n context.fillRect(0, offset + groupHeight - group.style.padding, bracketLength, lineWidth);\n }\n });\n\n context.restore();\n }\n\n /**\n * Draws page load events in the Timings track (LCP, FCP, DCL, etc.)\n */\n private drawMarkers(context: CanvasRenderingContext2D, timelineData: FlameChartTimelineData, markerIndices: number[]):\n void {\n const {entryStartTimes, entryLevels} = timelineData;\n this.markerPositions.clear();\n context.textBaseline = 'alphabetic';\n context.save();\n context.beginPath();\n let lastMarkerLevel = -1;\n let lastMarkerX: number = -Infinity;\n // Markers are sorted top to bottom, right to left.\n for (let m = markerIndices.length - 1; m >= 0; --m) {\n const entryIndex = markerIndices[m];\n const title = this.dataProvider.entryTitle(entryIndex);\n if (!title) {\n continue;\n }\n const entryStartTime = entryStartTimes[entryIndex];\n const level = entryLevels[entryIndex];\n if (lastMarkerLevel !== level) {\n lastMarkerX = -Infinity;\n }\n const x = Math.max(this.chartViewport.timeToPosition(entryStartTime), lastMarkerX);\n const y = this.levelToOffset(level);\n const h = this.levelHeight(level);\n const padding = 4;\n const width = Math.ceil(UI.UIUtils.measureTextWidth(context, title)) + 2 * padding;\n lastMarkerX = x + width + 1;\n lastMarkerLevel = level;\n this.markerPositions.set(entryIndex, {x, width});\n context.fillStyle = this.dataProvider.entryColor(entryIndex);\n context.fillRect(x, y, width, h - 1);\n context.fillStyle = 'white';\n context.fillText(title, x + padding, y + h - this.textBaseline);\n }\n context.strokeStyle = 'rgba(0, 0, 0, 0.2)';\n context.stroke();\n context.restore();\n }\n\n /**\n * Draws the titles of trace events in the timeline. Also calls `decorateEntry` on the data\n * provider, which can do any custom drawing on the corresponding entry's area (e.g. draw screenshots\n * in the Performance Panel timeline).\n *\n * Takes in the width of the entire canvas so that we know if an event does\n * not fit into the viewport entirely, the max width we can draw is that\n * width, not the width of the event itself.\n */\n private drawEventTitles(\n context: CanvasRenderingContext2D, timelineData: FlameChartTimelineData, titleIndices: number[],\n canvasWidth: number): void {\n const timeToPixel = this.chartViewport.timeToPixel();\n const textPadding = this.textPadding;\n context.save();\n context.beginPath();\n const {entryStartTimes, entryLevels} = timelineData;\n for (let i = 0; i < titleIndices.length; ++i) {\n const entryIndex = titleIndices[i];\n const entryStartTime = entryStartTimes[entryIndex];\n const barX = this.timeToPositionClipped(entryStartTime);\n // Ensure that the title does not go off screen, if the width of the\n // event is wider than the width of the canvas, use the canvas width as\n // our maximum width.\n const barWidth = Math.min(this.#eventBarWidth(timelineData, entryIndex), canvasWidth);\n const barLevel = entryLevels[entryIndex];\n const barY = this.levelToOffset(barLevel);\n let text = this.dataProvider.entryTitle(entryIndex);\n const barHeight = this.#eventBarHeight(timelineData, entryIndex);\n if (text && text.length) {\n context.font = this.#font;\n const hasArrowDecoration =\n this.entryHasDecoration(entryIndex, FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW);\n // Set the max width to be the width of the bar plus some padding. If the bar has an arrow decoration and the bar is wide enough for the larger\n // version of the decoration that is a square button, also substract the width of the decoration.\n // Because the decoration is square, it's width is equal to this.barHeight\n const maxBarWidth = (hasArrowDecoration && barWidth > barHeight * 2) ? barWidth - textPadding - this.barHeight :\n barWidth - 2 * textPadding;\n text = UI.UIUtils.trimTextMiddle(\n context,\n text,\n maxBarWidth,\n );\n }\n const unclippedBarX = this.chartViewport.timeToPosition(entryStartTime);\n if (this.dataProvider.decorateEntry(\n entryIndex, context, text, barX, barY, barWidth, barHeight, unclippedBarX, timeToPixel)) {\n continue;\n }\n if (!text || !text.length) {\n continue;\n }\n context.fillStyle = this.dataProvider.textColor(entryIndex);\n context.fillText(text, barX + textPadding, barY + barHeight - this.textBaseline);\n }\n\n context.restore();\n }\n\n /**\n * @callback GroupCallback\n * @param groupTop pixels between group top and the top of the flame chart.\n * @param groupIndex\n * @param group\n * @param isFirstGroup if the group is the first one of this nesting level.\n * @param height pixels of height of this group\n */\n /**\n * Process the pixels of start and end, and other data of each group, which are used in drawing the group.\n * @param {GroupCallback} callback\n */\n private forEachGroup(\n callback: (groupTop: number, groupIndex: number, group: Group, isFirstGroup: boolean, height: number) => void):\n void {\n if (!this.rawTimelineData) {\n return;\n }\n const groups = this.rawTimelineData.groups || [];\n if (!groups.length) {\n return;\n }\n const groupOffsets = this.groupOffsets;\n if (!groupOffsets) {\n return;\n }\n\n const groupStack: {\n nestingLevel: number,\n visible: boolean,\n }[] = [{nestingLevel: -1, visible: true}];\n for (let i = 0; i < groups.length; ++i) {\n const groupTop = groupOffsets[i];\n const group = groups[i];\n let firstGroup = true;\n let last: {\n nestingLevel: number,\n visible: boolean,\n } = groupStack[groupStack.length - 1];\n while (last && last.nestingLevel >= group.style.nestingLevel) {\n groupStack.pop();\n firstGroup = false;\n last = groupStack[groupStack.length - 1];\n }\n last = groupStack[groupStack.length - 1];\n const parentGroupVisible = last ? last.visible : false;\n const thisGroupVisible = !group.hidden && parentGroupVisible && (!this.isGroupCollapsible(i) || group.expanded);\n groupStack.push({nestingLevel: group.style.nestingLevel, visible: Boolean(thisGroupVisible)});\n\n if (!this.#groupTreeRoot) {\n return;\n }\n const sortedGroupIndexes: number[] = [];\n\n function traverse(root: GroupTreeNode): void {\n sortedGroupIndexes.push(root.index);\n for (const child of root.children) {\n traverse(child);\n }\n }\n traverse(this.#groupTreeRoot);\n // Skip the one whose index is -1, because we added to represent the top\n // level to be the parent of all groups.\n sortedGroupIndexes.shift();\n\n // This shouldn't happen, because the tree should have the fake root and all groups. Add a sanity check to avoid\n // error.\n if (sortedGroupIndexes.length !== groups.length) {\n console.warn('The data from the group tree doesn\\'t match the data from DataProvider.');\n return;\n }\n\n // Add an extra index, which is equal to the length of the |groups|, this\n // will be used for the coordinates after the last group.\n // If the coordinates after the last group, it will return in later check\n // `groupIndex >= groups.length` anyway. But add one more element to make\n // this array same length as the |groupOffsets|.\n sortedGroupIndexes.push(groups.length);\n\n const currentIndex = sortedGroupIndexes.indexOf(i);\n const nextOffset = groupOffsets[sortedGroupIndexes[currentIndex + 1]];\n // In edit mode all the groups are visible.\n if (!this.#inTrackConfigEditMode && (!parentGroupVisible || group.hidden)) {\n continue;\n }\n callback(groupTop, i, group, firstGroup, nextOffset - groupTop);\n }\n }\n\n private forEachGroupInViewport(\n callback: (offset: number, index: number, group: Group, isFirst: boolean, groupHeight: number) => void): void {\n const top = this.chartViewport.scrollOffset();\n this.forEachGroup((groupTop, index, group, firstGroup, height) => {\n if (groupTop - group.style.padding > top + this.offsetHeight) {\n return;\n }\n if (groupTop + height < top) {\n return;\n }\n callback(groupTop, index, group, firstGroup, height);\n });\n }\n\n /**\n * Returns the width of the title label of the group, which include the left padding, arrow and the group header text.\n * This function is public for test reason.\n * |ICON_WIDTH|expansionArrowIndent * (nestingLevel + 1)|\n * |headerLeftPadding|EDIT ICON| |Arrow|LabelXPadding|Title|LabelXPadding|\n * |<-- labelWidth -->|\n * @param context canvas context\n * @param group\n * @returns the width of the label of the group.\n */\n labelWidthForGroup(context: CanvasRenderingContext2D, group: Group): number {\n return EXPANSION_ARROW_INDENT * (group.style.nestingLevel + 1) + ARROW_SIDE / 2 + HEADER_LABEL_X_PADDING +\n UI.UIUtils.measureTextWidth(context, group.name) + HEADER_LABEL_X_PADDING - HEADER_LEFT_PADDING;\n }\n\n private drawCollapsedOverviewForGroup(group: Group, y: number, endLevel: number): void {\n const range = new Common.SegmentedRange.SegmentedRange(mergeCallback);\n const timeWindowLeft = this.chartViewport.windowLeftTime();\n const timeWindowRight = this.chartViewport.windowRightTime();\n const context = (this.canvas.getContext('2d') as CanvasRenderingContext2D);\n const groupBarHeight = group.style.height;\n if (!this.rawTimelineData) {\n return;\n }\n const entryStartTimes = this.rawTimelineData.entryStartTimes;\n const entryTotalTimes = this.rawTimelineData.entryTotalTimes;\n const timeToPixel = this.chartViewport.timeToPixel();\n\n for (let level = group.startLevel; level < endLevel; ++level) {\n const levelIndexes: number[] = this.timelineLevels ? this.timelineLevels[level] : [];\n const rightIndexOnLevel =\n Platform.ArrayUtilities.lowerBound(\n levelIndexes, timeWindowRight, (time, entryIndex) => time - entryStartTimes[entryIndex]) -\n 1;\n let lastDrawOffset: number = Infinity;\n\n for (let entryIndexOnLevel = rightIndexOnLevel; entryIndexOnLevel >= 0; --entryIndexOnLevel) {\n const entryIndex = levelIndexes[entryIndexOnLevel];\n const entryStartTime = entryStartTimes[entryIndex];\n const barX = this.timeToPositionClipped(entryStartTime);\n const entryEndTime = entryStartTime + entryTotalTimes[entryIndex];\n if (isNaN(entryEndTime) || barX >= lastDrawOffset) {\n continue;\n }\n if (entryEndTime <= timeWindowLeft) {\n break;\n }\n lastDrawOffset = barX;\n const color = this.entryColorsCache ? this.entryColorsCache[entryIndex] : '';\n const endBarX = this.timeToPositionClipped(entryEndTime);\n if (group.style.useDecoratorsForOverview && this.dataProvider.forceDecoration(entryIndex)) {\n const unclippedBarX = this.chartViewport.timeToPosition(entryStartTime);\n const barWidth = this.#eventBarWidth(this.rawTimelineData, entryIndex);\n\n context.beginPath();\n context.fillStyle = color;\n context.fillRect(barX, y, barWidth, groupBarHeight - 1);\n this.dataProvider.decorateEntry(\n entryIndex, context, '', barX, y, barWidth, groupBarHeight, unclippedBarX, timeToPixel);\n continue;\n }\n range.append(new Common.SegmentedRange.Segment(barX, endBarX, color));\n }\n }\n\n const segments = range.segments().slice().sort((a, b) => a.data.localeCompare(b.data));\n let lastColor;\n context.beginPath();\n for (let i = 0; i < segments.length; ++i) {\n const segment = segments[i];\n if (lastColor !== segments[i].data) {\n context.fill();\n context.beginPath();\n lastColor = segments[i].data;\n context.fillStyle = lastColor;\n }\n context.rect(segment.begin, y, segment.end - segment.begin, groupBarHeight);\n }\n context.fill();\n\n function mergeCallback(a: Common.SegmentedRange.Segment, b: Common.SegmentedRange.Segment):\n Common.SegmentedRange.Segment|null {\n return a.data === b.data && a.end + 0.4 > b.end ? a : null;\n }\n }\n\n private drawFlowEvents(context: CanvasRenderingContext2D, timelineData: FlameChartTimelineData): void {\n const td = this.timelineData();\n if (!td) {\n return;\n }\n\n const {entryTotalTimes, entryStartTimes, entryLevels} = timelineData;\n const ratio = window.devicePixelRatio;\n const top = this.chartViewport.scrollOffset();\n const arrowLineWidth = 6;\n const arrowWidth = 3;\n\n context.save();\n context.scale(ratio, ratio);\n context.translate(0, -top);\n\n context.fillStyle = '#7f5050';\n context.strokeStyle = '#7f5050';\n\n for (let i = 0; i < td.initiatorsData.length; ++i) {\n const initiatorsData = td.initiatorsData[i];\n\n // Draw an arrow in an 'elbow connector' shape if the initiator ends before the initiated event starts, like this\n // ---\n // |\n // --->\n // Otherwise directly draw from the initiator start to initiated start, like this:\n // |\n // |\n // ---->\n const initiatorStartTime = entryStartTimes[initiatorsData.initiatorIndex];\n const initiatorEndTime =\n entryStartTimes[initiatorsData.initiatorIndex] + entryTotalTimes[initiatorsData.initiatorIndex];\n const initiatedStartTime = entryStartTimes[initiatorsData.eventIndex];\n\n const initiatorEndsBeforeInitiatedStart = initiatorEndTime < initiatedStartTime;\n const initiatorArrowStartTime = initiatorEndsBeforeInitiatedStart ?\n initiatorEndTime :\n // The blue indicator's width is 2, so add a little bit offset to start the arrow.\n Math.max(initiatorStartTime, this.chartViewport.pixelToTime(5));\n const initiatorArrowEndTime = initiatedStartTime;\n\n // Do not draw the initiator if it is out of the viewport\n if (initiatorArrowEndTime < this.chartViewport.windowLeftTime()) {\n continue;\n }\n let startX = this.chartViewport.timeToPosition(initiatorArrowStartTime);\n let endX = this.chartViewport.timeToPosition(initiatorArrowEndTime);\n\n // Draw a circle around 'collapsed entries' arrow to indicate that the initiated entry is hidden\n if (initiatorsData.isInitiatorHidden) {\n const {circleEndX} = this.drawCircleAroundCollapseArrow(initiatorsData.initiatorIndex, context, timelineData);\n // If the circle exists around the initiator, start the initiator arrow from the circle end\n if (circleEndX) {\n startX = circleEndX;\n }\n }\n if (initiatorsData.isEntryHidden) {\n const {circleStartX} = this.drawCircleAroundCollapseArrow(initiatorsData.eventIndex, context, timelineData);\n // If the circle exists around the initiated event, draw the initiator arrow until the circle beginning\n if (circleStartX) {\n endX = circleStartX;\n }\n }\n\n const startLevel = entryLevels[initiatorsData.initiatorIndex];\n const endLevel = entryLevels[initiatorsData.eventIndex];\n const startY = this.levelToOffset(startLevel) + this.levelHeight(startLevel) / 2;\n const endY = this.levelToOffset(endLevel) + this.levelHeight(endLevel) / 2;\n const lineLength = endX - startX;\n\n // Make line an arrow if the line is long enough to fit the arrow head. Otherwise, draw a thinner line without the arrow head.\n if (lineLength > arrowWidth) {\n context.lineWidth = 0.5;\n context.beginPath();\n context.moveTo(endX, endY);\n context.lineTo(endX - arrowLineWidth, endY - 3);\n context.lineTo(endX - arrowLineWidth, endY + 3);\n context.fill();\n } else {\n context.lineWidth = 0.2;\n }\n\n if (initiatorEndsBeforeInitiatedStart) {\n // ---\n // |\n // --->\n context.beginPath();\n context.moveTo(startX, startY);\n context.lineTo(startX + lineLength / 2, startY);\n context.lineTo(startX + lineLength / 2, endY);\n context.lineTo(endX, endY);\n context.stroke();\n } else {\n // |\n // |\n // ---->\n context.beginPath();\n context.moveTo(startX, startY);\n context.lineTo(startX, endY);\n context.lineTo(endX, endY);\n context.stroke();\n }\n }\n context.restore();\n }\n\n private drawCircleAroundCollapseArrow(\n entryIndex: number, context: CanvasRenderingContext2D,\n timelineData: FlameChartTimelineData): {circleStartX?: number, circleEndX?: number} {\n const decorationsForEvent = timelineData.entryDecorations.at(entryIndex);\n // The circle is only drawn when the initiator arrow is going to/from some hidden entry. Make sure that the entry also has a decoration for hidden children.\n if (!decorationsForEvent ||\n !decorationsForEvent.find(\n decoration => decoration.type === FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW)) {\n // This should not happen, break if it does.\n return {};\n }\n\n const {entryStartTimes, entryLevels} = timelineData;\n // The large version of 'hidden entries' is displayed\n // only when the bar width is over double the height.\n // We do not want to draw the circle if the arrow is not visible.\n const barWidth = this.#eventBarWidth(timelineData, entryIndex);\n if (barWidth < this.barHeight * 2) {\n return {};\n }\n\n const entryStartTime = entryStartTimes[entryIndex];\n const barX = this.timeToPositionClipped(entryStartTime);\n const barLevel = entryLevels[entryIndex];\n const barHeight = this.#eventBarHeight(timelineData, entryIndex);\n const barY = this.levelToOffset(barLevel);\n\n context.save();\n context.beginPath();\n context.rect(barX, barY, barWidth, barHeight);\n context.clip();\n context.lineWidth = 1;\n context.beginPath();\n context.fillStyle = '#474747';\n const triangleCenterX = barX + barWidth - this.barHeight / 2;\n const triangleCenterY = barY + this.barHeight / 2;\n const circleRadius = 6;\n context.beginPath();\n context.arc(triangleCenterX, triangleCenterY, circleRadius, 0, 2 * Math.PI);\n context.stroke();\n context.restore();\n\n return {circleStartX: triangleCenterX - circleRadius, circleEndX: triangleCenterX + circleRadius};\n }\n\n /**\n * Draws the vertical dashed lines in the timeline marking where the \"Marker\" events\n * happened in time.\n */\n private drawMarkerLines(): void {\n const timelineData = this.timelineData();\n if (!timelineData) {\n return;\n }\n const markers = timelineData.markers;\n const left = this.markerIndexBeforeTime(this.minimumBoundary());\n const rightBoundary = this.maximumBoundary();\n const timeToPixel = this.chartViewport.timeToPixel();\n\n const context = (this.canvas.getContext('2d') as CanvasRenderingContext2D);\n context.save();\n const ratio = window.devicePixelRatio;\n context.scale(ratio, ratio);\n context.translate(0, 3);\n const height = RulerHeight - 1;\n for (let i = left; i < markers.length; i++) {\n const timestamp = markers[i].startTime();\n if (timestamp > rightBoundary) {\n break;\n }\n markers[i].draw(context, this.chartViewport.timeToPosition(timestamp), height, timeToPixel);\n }\n context.restore();\n }\n\n private updateMarkerHighlight(): void {\n const element = this.markerHighlighElement;\n if (element.parentElement) {\n element.remove();\n }\n const markerIndex = this.highlightedMarkerIndex;\n if (markerIndex === -1) {\n return;\n }\n const timelineData = this.timelineData();\n if (!timelineData) {\n return;\n }\n const marker = timelineData.markers[markerIndex];\n const barX = this.timeToPositionClipped(marker.startTime());\n UI.Tooltip.Tooltip.install(element, marker.title() || '');\n const style = element.style;\n style.left = barX + 'px';\n style.backgroundColor = marker.color();\n this.viewportElement.appendChild(element);\n }\n\n private processTimelineData(timelineData: FlameChartTimelineData|null): void {\n if (!timelineData) {\n this.timelineLevels = null;\n this.visibleLevelOffsets = null;\n this.visibleLevels = null;\n this.groupOffsets = null;\n this.rawTimelineData = null;\n this.forceDecorationCache = null;\n this.entryColorsCache = null;\n this.rawTimelineDataLength = 0;\n this.#groupTreeRoot = null;\n this.selectedGroupIndex = -1;\n this.keyboardFocusedGroup = -1;\n this.flameChartDelegate.updateSelectedGroup(this, null);\n return;\n }\n\n this.rawTimelineData = timelineData;\n this.rawTimelineDataLength = timelineData.entryStartTimes.length;\n this.forceDecorationCache = new Array(this.rawTimelineDataLength);\n this.entryColorsCache = new Array(this.rawTimelineDataLength);\n for (let i = 0; i < this.rawTimelineDataLength; ++i) {\n this.forceDecorationCache[i] = this.dataProvider.forceDecoration(i) ?? false;\n this.entryColorsCache[i] = this.dataProvider.entryColor(i);\n }\n\n const entryCounters = new Uint32Array(this.dataProvider.maxStackDepth() + 1);\n for (let i = 0; i < timelineData.entryLevels.length; ++i) {\n ++entryCounters[timelineData.entryLevels[i]];\n }\n const levelIndexes = new Array(entryCounters.length);\n for (let i = 0; i < levelIndexes.length; ++i) {\n levelIndexes[i] = new Uint32Array(entryCounters[i]);\n entryCounters[i] = 0;\n }\n\n for (let i = 0; i < timelineData.entryLevels.length; ++i) {\n const level = timelineData.entryLevels[i];\n levelIndexes[level][entryCounters[level]++] = i;\n }\n this.timelineLevels = levelIndexes;\n const groups = this.rawTimelineData.groups || [];\n for (let i = 0; i < groups.length; ++i) {\n const expanded = this.groupExpansionState[groups[i].name];\n const hidden = this.groupHiddenState[groups[i].name];\n if (expanded !== undefined) {\n groups[i].expanded = expanded;\n }\n if (hidden !== undefined) {\n groups[i].hidden = hidden;\n }\n }\n\n if (!this.#groupTreeRoot) {\n this.#groupTreeRoot = this.buildGroupTree(groups);\n } else {\n // When the |groupTreeRoot| is already existing, and a \"new\" timeline data comes, this means the new timeline data\n // is just a modification of original, so we should update the tree instead of rebuild it.\n // For example,\n // [\n // { name: 'Test Group 0', startLevel: 0, ...},\n // { name: 'Test Group 1', startLevel: 1, ...},\n // { name: 'Test Group 2', startLevel: 2, ...},\n // ], and [\n // { name: 'Test Group 0', startLevel: 0, ...},\n // { name: 'Test Group 1', startLevel: 2, ...},\n // { name: 'Test Group 2', startLevel: 4, ...},\n // ],\n // are the same.\n // But they and [\n // { name: 'Test Group 0', startLevel: 0, ...},\n // { name: 'Test Group 2', startLevel: 1, ...},\n // { name: 'Test Group 1', startLevel: 2, ...},\n // ] are different.\n // But if the |groups| is changed (this means the group order inside the |groups| is changed), it means the\n // timeline data is a real new one, then please call |reset()| before rendering.\n this.updateGroupTree(groups, this.#groupTreeRoot);\n }\n\n this.updateLevelPositions();\n this.updateHeight();\n\n // If this is a new trace, we will call the reset()(See TimelineFlameChartView > setModel()), which will set the\n // |selectedGroupIndex| to -1.\n // So when |selectedGroupIndex| is not -1, it means it is the same trace file, but might have some modification\n // (like reorder the track, merge an entry, etc).\n if (this.selectedGroupIndex === -1) {\n this.selectedGroupIndex = timelineData.selectedGroup ? groups.indexOf(timelineData.selectedGroup) : -1;\n }\n\n this.keyboardFocusedGroup = this.selectedGroupIndex;\n this.flameChartDelegate.updateSelectedGroup(this, timelineData.selectedGroup);\n }\n\n /**\n * Builds a tree node for a group. For each group the start level is inclusive and the end level is exclusive.\n * @param group\n * @param index index of the group in the |FlameChartTimelineData.groups[]|\n * @param endLevel The end level of this group, which is also the start level of the next group or the end of all\n * groups\n * @returns the tree node for the group\n */\n #buildGroupTreeNode(group: Group, index: number, endLevel: number): GroupTreeNode {\n return {\n index,\n nestingLevel: group.style.nestingLevel,\n startLevel: group.startLevel,\n endLevel,\n children: [],\n };\n }\n\n /**\n * Builds a tree for the given group array, the tree will be builded based on the nesting level.\n * We will add one fake root to represent the top level parent, and the for each tree node, its children means the\n * group nested in. The order of the children matters because it represent the order of groups.\n * So for example if there are Group 0-7, Group 0, 3, 4 have nestingLevel 0, Group 1, 2, 5, 6, 7 have nestingLevel 1.\n * Then we will get a tree like this.\n * -1(fake root to represent the top level parent)\n * / | \\\n * / | \\\n * 0 3 4\n * / \\ / | \\\n * 1 2 5 6 7\n * This function is public for test purpose.\n * @param groups the array of all groups, it should be the one from FlameChartTimelineData\n * @returns the root of the Group tree. The root is the fake one we added, which represent the parent for all groups\n */\n buildGroupTree(groups: Group[]): GroupTreeNode {\n // Add an extra top level. This will be used as a parent for all groups, and\n // will be used to contain the levels that not belong to any group.\n const treeRoot: GroupTreeNode = {\n index: -1,\n nestingLevel: -1,\n startLevel: 0,\n // If there is no |groups| (for example the JS Profiler), it means all the\n // levels belong to the top level, so just use the max level as the end.\n endLevel: groups.length ? groups[0].startLevel : this.dataProvider.maxStackDepth(),\n children: [],\n };\n const groupStack: GroupTreeNode[] = [treeRoot];\n for (let i = 0; i < groups.length; i++) {\n const group = groups[i];\n const currentGroupNestingLevel = group.style.nestingLevel;\n let parentGroup: GroupTreeNode = groupStack[groupStack.length - 1];\n while (parentGroup && parentGroup.nestingLevel >= currentGroupNestingLevel) {\n groupStack.pop();\n parentGroup = groupStack[groupStack.length - 1];\n }\n\n const nextGroup = groups[i + 1];\n // If this group is the last one, it means all the remaining levels belong\n // to this level, so just use the max level as the end.\n const endLevel = nextGroup?.startLevel ?? this.dataProvider.maxStackDepth();\n const currentGroupNode = this.#buildGroupTreeNode(group, i, endLevel);\n parentGroup.children.push(currentGroupNode);\n groupStack.push(currentGroupNode);\n }\n return treeRoot;\n }\n\n /**\n * Updates the tree for the given group array.\n * For a new timeline data, if the groups remains the same (the same here mean the group order inside the |groups|,\n * the start level, style and other attribute can be changed), but other parts are different.\n * For example the |entryLevels[]| or |maxStackDepth| is changed, then we should update the group tree instead of\n * re-build it.\n * So we can keep the order that user manually set.\n * To do this, we go through the tree, and update the start and end level of each group.\n * This function is public for test purpose.\n * @param groups the array of all groups, it should be the one from FlameChartTimelineData\n * @returns the root of the Group tree. The root is the fake one we added, which represent the parent for all groups\n */\n updateGroupTree(groups: Group[], root: GroupTreeNode): void {\n const maxStackDepth = this.dataProvider.maxStackDepth();\n\n function traverse(treeNode: GroupTreeNode): void {\n const index = treeNode.index;\n if (index < 0) {\n // For the extra top level. This will be used as a parent for all\n // groups, so it will start from level 0.\n treeNode.startLevel = 0;\n // If there is no |groups| (for example the JS Profiler), it means all the\n // levels belong to the top level, so just use the max level as the end.\n treeNode.endLevel = groups.length ? groups[0].startLevel : maxStackDepth;\n } else {\n // This shouldn't happen. If this happen, it means the |groups| from data provider is changed. Add a sanity\n // check to avoid error.\n if (!groups[index]) {\n console.warn(\n 'The |groups| is changed. ' +\n 'Please make sure the flamechart is reset after data change in the data provider');\n return;\n }\n treeNode.startLevel = groups[index].startLevel;\n const nextGroup = groups[index + 1];\n // If this group is the last one, it means all the remaining levels belong\n // to this level, so just use the max level as the end.\n treeNode.endLevel = nextGroup?.startLevel ?? maxStackDepth;\n }\n for (const child of treeNode.children) {\n traverse(child);\n }\n }\n traverse(root);\n }\n\n /**\n * Given a tree, do a preorder traversal, and process the group and the levels in this group.\n * So for a tree like this:\n * -1\n * / | \\\n * / | \\\n * 0 3 4\n * / \\ / | \\\n * 1 2 5 6 7\n * The traverse order will be: -1, 0, 1, 2, 3, 4, 5, 6, 7.\n * @param groupNode TreeNode for current group\n * @param currentOffset\n * @param parentGroupIsVisible used to determine if current group's header and its levels are visible\n * @returns the offset (in pixels) after processing current group\n */\n #traverseGroupTreeAndUpdateLevelPositionsForTheGroup(\n groupNode: GroupTreeNode, currentOffset: number, parentGroupIsVisible: boolean): number {\n if (!this.visibleLevels || !this.visibleLevelOffsets || !this.visibleLevelHeights || !this.groupOffsets) {\n return currentOffset;\n }\n\n const groups = this.rawTimelineData?.groups;\n if (!groups) {\n return currentOffset;\n }\n\n // This shouldn't happen. If this happen, it means the group tree is outdated. Add a sanity check to avoid error.\n if (groupNode.index >= groups.length) {\n console.warn(\n 'The data from the group tree is outdated. ' +\n 'Please make sure the flamechart is reset after data change in the data provider');\n return currentOffset;\n }\n\n if (groupNode.index >= 0) {\n this.groupOffsets[groupNode.index] = currentOffset;\n // If |shareHeaderLine| is false, we add the height of one more level to\n // the current offset, which will be used for the start level of current\n // group.\n // For edit mode, we will show all the groups whose name are not empty.\n if ((this.#inTrackConfigEditMode && groups[groupNode.index].name) ||\n (!groups[groupNode.index].hidden && parentGroupIsVisible && !groups[groupNode.index].style.shareHeaderLine)) {\n currentOffset += groups[groupNode.index].style.height;\n }\n }\n\n // If this is the top level, it is always shown.\n // Otherwise, if the parent group is visible and current group is not hidden, and this group is expanded, then this\n // group is visible.\n let thisGroupIsVisible = false;\n if (groupNode.index < 0) {\n thisGroupIsVisible = true;\n } else {\n const thisGroupIsExpanded = !(this.isGroupCollapsible(groupNode.index) && !groups[groupNode.index].expanded);\n thisGroupIsVisible = !groups[groupNode.index].hidden && thisGroupIsExpanded;\n }\n const thisGroupLevelsAreVisible = thisGroupIsVisible && parentGroupIsVisible;\n\n for (let level = groupNode.startLevel; level < groupNode.endLevel; level++) {\n // This shouldn't happen. If this happen, it means the group tree is outdated. Add a sanity check to avoid error.\n if (level >= this.dataProvider.maxStackDepth()) {\n console.warn(\n 'The data from the group tree is outdated. ' +\n 'Please make sure the flamechart is reset after data change in the data provider');\n return currentOffset;\n }\n\n // Handle offset and visibility of each level inside this group.\n const isFirstOnLevel = level === groupNode.startLevel;\n // If this is the top level group, all the levels in this group are always shown.\n // Otherwise it depends on the visibility of parent group and this group.\n let thisLevelIsVisible;\n if (groupNode.index < 0) {\n thisLevelIsVisible = true;\n } else {\n const isFirstLevelAndForOverview = isFirstOnLevel && groups[groupNode.index].style.useFirstLineForOverview;\n thisLevelIsVisible = !groups[groupNode.index].hidden &&\n (parentGroupIsVisible && (thisGroupLevelsAreVisible || isFirstLevelAndForOverview));\n }\n\n let height;\n if (groups[groupNode.index]) {\n // |shareHeaderLine| is false means the first level of this group is on the next level of the header.\n const isFirstLevelAndNotShareHeaderLine = isFirstOnLevel && !groups[groupNode.index].style.shareHeaderLine;\n // A group is collapsed means only ite header is visible.\n const thisGroupIsCollapsed = this.isGroupCollapsible(groupNode.index) && !groups[groupNode.index].expanded;\n\n if (isFirstLevelAndNotShareHeaderLine || thisGroupIsCollapsed) {\n // This means this level is only the header, so we use the height of the header for this level.\n height = groups[groupNode.index].style.height;\n } else {\n height = groups[groupNode.index].style.itemsHeight ?? this.barHeight;\n }\n } else {\n height = this.barHeight;\n }\n\n // If it's in edit mode, all the levels are hidden.\n this.visibleLevels[level] = this.#inTrackConfigEditMode ? false : Boolean(thisLevelIsVisible);\n this.visibleLevelOffsets[level] = currentOffset;\n this.visibleLevelHeights[level] = this.#inTrackConfigEditMode ? 0 : height;\n\n // If this level not belong to any group, it is always shown, otherwise we need to check if it is visible.\n if (groupNode.index < 0 ||\n (!groups[groupNode.index].hidden) &&\n (thisLevelIsVisible ||\n (parentGroupIsVisible && groups[groupNode.index].style.shareHeaderLine && isFirstOnLevel))) {\n currentOffset += this.visibleLevelHeights[level];\n }\n }\n\n if (groupNode.children.length === 0) {\n return currentOffset;\n }\n\n for (const child of groupNode.children) {\n // If the child is not the first child, we will add a padding top.\n // For edit mode, we will show all the groups whose name are not empty.\n if ((this.#inTrackConfigEditMode && groups[child.index].name) ||\n (thisGroupLevelsAreVisible && !groups[child.index]?.hidden && child !== groupNode.children[0])) {\n currentOffset += (groups[child.index].style.padding ?? 0);\n }\n currentOffset =\n this.#traverseGroupTreeAndUpdateLevelPositionsForTheGroup(child, currentOffset, thisGroupLevelsAreVisible);\n }\n return currentOffset;\n }\n\n private updateLevelPositions(): void {\n if (!this.#groupTreeRoot) {\n console.warn('Please make sure the new timeline data is processed before update the level positions.');\n return;\n }\n const levelCount = this.dataProvider.maxStackDepth();\n const groups = this.rawTimelineData?.groups || [];\n // Add an extra number in visibleLevelOffsets to store the end of last level\n this.visibleLevelOffsets = new Uint32Array(levelCount + 1);\n this.visibleLevelHeights = new Uint32Array(levelCount);\n this.visibleLevels = new Array(levelCount);\n // Add an extra number in groupOffsets to store the end of last group\n this.groupOffsets = new Uint32Array(groups.length + 1);\n let currentOffset = this.rulerEnabled ? RulerHeight + 2 : 2;\n // The root is always visible, so just simply set the |parentGroupIsVisible| to visible.\n currentOffset = this.#traverseGroupTreeAndUpdateLevelPositionsForTheGroup(\n this.#groupTreeRoot, currentOffset, /* parentGroupIsVisible= */ true);\n\n // Set the final offset to the last element of |groupOffsets| and\n // |visibleLevelOffsets|. This number represent the end of last group and\n // level.\n this.groupOffsets[groups.length] = currentOffset;\n this.visibleLevelOffsets[levelCount] = currentOffset;\n }\n\n private isGroupCollapsible(index: number): boolean|undefined {\n if (!this.rawTimelineData || index < 0) {\n return;\n }\n\n const groups = this.rawTimelineData.groups || [];\n const style = groups[index].style;\n if (!style.shareHeaderLine || !style.collapsible) {\n return Boolean(style.collapsible);\n }\n const isLastGroup = index + 1 >= groups.length;\n if (!isLastGroup && groups[index + 1].style.nestingLevel > style.nestingLevel) {\n return true;\n }\n const nextGroupLevel = isLastGroup ? this.dataProvider.maxStackDepth() : groups[index + 1].startLevel;\n if (nextGroupLevel !== groups[index].startLevel + 1) {\n return true;\n }\n // For groups that only have one line and share header line, pretend these are not collapsible\n // unless the itemsHeight does not match the headerHeight\n return style.height !== style.itemsHeight;\n }\n\n groupIsLastVisibleTopLevel(group?: Group): boolean {\n if (!group) {\n return true;\n }\n const visibleTopLevelGroupNumber =\n this.#groupTreeRoot?.children.filter(track => !this.rawTimelineData?.groups[track.index].hidden).length;\n return visibleTopLevelGroupNumber === 1 && group.style.nestingLevel === 0 && !group.hidden;\n }\n\n setSelectedEntry(entryIndex: number): void {\n // Check if the button that resets children of the entry is clicked. We need to check it even if the entry\n // clicked is not selected to avoid needing to double click\n if (this.isMouseOverRevealChildrenArrow(this.lastMouseOffsetX, entryIndex)) {\n this.modifyTree(FilterAction.RESET_CHILDREN, entryIndex);\n }\n if (this.selectedEntryIndex === entryIndex) {\n return;\n }\n if (entryIndex !== -1) {\n this.chartViewport.hideRangeSelection();\n }\n this.selectedEntryIndex = entryIndex;\n this.revealEntry(entryIndex);\n this.updateElementPosition(this.selectedElement, this.selectedEntryIndex);\n this.update();\n }\n\n private entryHasDecoration(entryIndex: number, decorationType: FlameChartDecorationType): boolean {\n const timelineData = this.timelineData();\n if (!timelineData) {\n return false;\n }\n\n const decorationsForEvent = timelineData.entryDecorations.at(entryIndex);\n if (decorationsForEvent && decorationsForEvent.length >= 1) {\n return decorationsForEvent.some(decoration => decoration.type === decorationType);\n }\n\n return false;\n }\n\n getMarkerPixelsForEntryIndex(entryIndex: number): {x: number, width: number}|null {\n return this.markerPositions.get(entryIndex) ?? null;\n }\n\n /**\n * Update position of an Element. By default, the element is treated as a full entry and it's dimentions are set to the full entry width/length/height.\n * If isDecoration parameter is set to true, the element will be positioned on the right side of the entry and have a square shape where width == height of the entry.\n */\n private updateElementPosition(element: Element|null, entryIndex: number, isDecoration?: boolean): void {\n if (!element) {\n return;\n }\n const elementMinWidthPx = 2;\n element.classList.add('hidden');\n if (entryIndex === -1) {\n return;\n }\n const timelineData = this.timelineData();\n if (!timelineData) {\n return;\n }\n\n const startTime = timelineData.entryStartTimes[entryIndex];\n const duration = timelineData.entryTotalTimes[entryIndex];\n let barX = 0;\n let barWidth = 0;\n let visible = true;\n if (Number.isNaN(duration)) {\n const position = this.markerPositions.get(entryIndex);\n if (position) {\n barX = position.x;\n barWidth = position.width;\n } else {\n visible = false;\n }\n } else {\n barX = this.chartViewport.timeToPosition(startTime);\n barWidth = duration * this.chartViewport.timeToPixel();\n }\n if (barX + barWidth <= 0 || barX >= this.offsetWidth) {\n return;\n }\n const barCenter = barX + barWidth / 2;\n barWidth = Math.max(barWidth, elementMinWidthPx);\n barX = barCenter - barWidth / 2;\n const entryLevel = timelineData.entryLevels[entryIndex];\n const barY = this.levelToOffset(entryLevel) - this.chartViewport.scrollOffset();\n const barHeight = this.levelHeight(entryLevel);\n const style = (element as HTMLElement).style;\n\n if (isDecoration) {\n style.top = barY + 'px';\n style.width = barHeight + 'px';\n style.height = barHeight + 'px';\n style.left = barX + barWidth - barHeight + 'px';\n } else {\n style.top = barY + 'px';\n style.width = barWidth + 'px';\n style.height = barHeight - 1 + 'px';\n style.left = barX + 'px';\n }\n element.classList.toggle('hidden', !visible);\n this.viewportElement.appendChild(element);\n }\n\n // Updates the highlight of an Arrow button that is shown on an entry if it has hidden child entries\n private updateHiddenChildrenArrowHighlighPosition(entryIndex: number): void {\n this.revealDescendantsArrowHighlightElement.classList.add('hidden');\n /**\n * No need to update the hidden descendants arrow highlight if\n * 1. No entry is highlighted\n * 2. Mouse is not hovering over the arrow button\n */\n if (entryIndex === -1 || !this.isMouseOverRevealChildrenArrow(this.lastMouseOffsetX, entryIndex)) {\n return;\n }\n this.updateElementPosition(this.revealDescendantsArrowHighlightElement, entryIndex, true);\n }\n\n private timeToPositionClipped(time: number): number {\n return Platform.NumberUtilities.clamp(this.chartViewport.timeToPosition(time), 0, this.offsetWidth);\n }\n\n /**\n * Returns the amount of pixels a group is vertically offset in the flame chart.\n * Now this function is only used for tests.\n */\n groupIndexToOffsetForTest(groupIndex: number): number {\n if (!this.groupOffsets) {\n throw new Error('No visible group offsets');\n }\n return this.groupOffsets[groupIndex];\n }\n\n /**\n * Set the edit mode.\n * Now this function is only used for tests.\n */\n setEditModeForTest(editMode: boolean): void {\n this.#inTrackConfigEditMode = editMode;\n }\n\n /**\n * Returns the visibility of a level in the.\n * flame chart.\n */\n levelIsVisible(level: number): boolean {\n if (!this.visibleLevels) {\n throw new Error('No level visiblibities');\n }\n return this.visibleLevels[level];\n }\n\n /**\n * Returns the amount of pixels a level is vertically offset in the.\n * flame chart.\n */\n levelToOffset(level: number): number {\n if (!this.visibleLevelOffsets) {\n throw new Error('No visible level offsets');\n }\n return this.visibleLevelOffsets[level];\n }\n\n levelHeight(level: number): number {\n if (!this.visibleLevelHeights) {\n throw new Error('No visible level heights');\n }\n return this.visibleLevelHeights[level];\n }\n\n private updateBoundaries(): void {\n this.totalTime = this.dataProvider.totalTime();\n this.minimumBoundaryInternal = this.dataProvider.minimumBoundary();\n this.chartViewport.setBoundaries(this.minimumBoundaryInternal, this.totalTime);\n }\n\n private updateHeight(): void {\n const height = this.levelToOffset(this.dataProvider.maxStackDepth()) + 2;\n this.chartViewport.setContentHeight(height);\n }\n\n override onResize(): void {\n // Clear the rect cache because we have been resized.\n this.#canvasBoundingClientRect = null;\n this.scheduleUpdate();\n }\n\n update(): void {\n if (!this.timelineData()) {\n return;\n }\n this.updateHeight();\n this.updateBoundaries();\n this.draw();\n if (!this.chartViewport.isDragging()) {\n this.updateHighlight();\n }\n }\n\n // Reset the whole flame chart.\n // It will reset the viewport, which will reset the scrollTop and scrollLeft. So should be careful when call this\n // function. But when the data is \"real\" changed, especially when groups[] is changed, make sure call this before\n // re-rendering.\n // This will also clear all the selected entry, group, etc.\n // Remember to call |setWindowTimes| before draw the flame chart again.\n reset(): void {\n if (this.#inTrackConfigEditMode) {\n this.#removeEditModeButton();\n this.#inTrackConfigEditMode = false;\n }\n\n this.chartViewport.reset();\n this.rawTimelineData = null;\n this.rawTimelineDataLength = 0;\n this.#groupTreeRoot = null;\n this.highlightedMarkerIndex = -1;\n this.highlightedEntryIndex = -1;\n this.selectedEntryIndex = -1;\n this.selectedGroupIndex = -1;\n }\n\n scheduleUpdate(): void {\n this.chartViewport.scheduleUpdate();\n }\n\n private enabled(): boolean {\n return this.rawTimelineDataLength !== 0;\n }\n\n computePosition(time: number): number {\n return this.chartViewport.timeToPosition(time);\n }\n\n formatValue(value: number, precision?: number): string {\n return this.dataProvider.formatValue(value - this.zeroTime(), precision);\n }\n\n maximumBoundary(): TraceEngine.Types.Timing.MilliSeconds {\n return TraceEngine.Types.Timing.MilliSeconds(this.chartViewport.windowRightTime());\n }\n\n minimumBoundary(): TraceEngine.Types.Timing.MilliSeconds {\n return TraceEngine.Types.Timing.MilliSeconds(this.chartViewport.windowLeftTime());\n }\n\n zeroTime(): TraceEngine.Types.Timing.MilliSeconds {\n return TraceEngine.Types.Timing.MilliSeconds(this.dataProvider.minimumBoundary());\n }\n\n boundarySpan(): TraceEngine.Types.Timing.MilliSeconds {\n return TraceEngine.Types.Timing.MilliSeconds(this.maximumBoundary() - this.minimumBoundary());\n }\n}\n\nexport const RulerHeight = 15;\nexport const MinimalTimeWindowMs = 0.5;\n\n/**\n * initiatorIndex is the index of the initiator entry and\n * eventIndex is the entry initiated by it.\n * However, if isEntryHidden or isInitiatorHidden are set to true,\n * it means that the actual initiator or initiated entry is hidden\n * by some context menu action and the indexes in initiatorIndex\n * or/and eventIndex are for the entries that are the closest\n * modified by an actions ancestors to them.\n */\nexport interface FlameChartInitiatorData {\n initiatorIndex: number;\n eventIndex: number;\n isEntryHidden?: boolean;\n isInitiatorHidden?: boolean;\n}\n\nexport const enum FlameChartDecorationType {\n CANDY = 'CANDY',\n WARNING_TRIANGLE = 'WARNING_TRIANGLE',\n HIDDEN_DESCENDANTS_ARROW = 'HIDDEN_DESCENDANTS_ARROW',\n}\n\n/**\n * Represents a decoration that can be added to event. Each event can have as\n * many decorations as required.\n *\n * It is anticipated in the future that we will add to this as we want to\n * annotate events in more ways.\n *\n * This work is being tracked in crbug.com/1434297.\n **/\nexport type FlameChartDecoration = {\n type: FlameChartDecorationType.CANDY,\n // We often only want to highlight problem parts of events, so this time sets\n // the minimum time at which the candystriping will start. If you want to\n // candystripe the entire event, set this to 0.\n startAtTime: TraceEngine.Types.Timing.MicroSeconds,\n // Optionally set the end time for the striping. If this is not provided, the entire entry will be striped.\n endAtTime?: TraceEngine.Types.Timing.MicroSeconds,\n}|{\n type: FlameChartDecorationType.WARNING_TRIANGLE,\n customStartTime?: TraceEngine.Types.Timing.MicroSeconds,\n customEndTime?: TraceEngine.Types.Timing.MicroSeconds,\n}|{\n type: FlameChartDecorationType.HIDDEN_DESCENDANTS_ARROW,\n};\n\n// We have to ensure we draw the decorations in a particular order; warning\n// triangles always go on top of any candy stripes.\nconst decorationDrawOrder: Record = {\n CANDY: 1,\n WARNING_TRIANGLE: 2,\n HIDDEN_DESCENDANTS_ARROW: 3,\n};\n\nexport function sortDecorationsForRenderingOrder(decorations: FlameChartDecoration[]): void {\n decorations.sort((decoration1, decoration2) => {\n return decorationDrawOrder[decoration1.type] - decorationDrawOrder[decoration2.type];\n });\n}\n\nexport class FlameChartTimelineData {\n entryLevels: number[]|Uint16Array;\n entryTotalTimes: number[]|Float32Array;\n entryStartTimes: number[]|Float64Array;\n /**\n * An array of entry decorations, where each item in the array is an array of\n * decorations for the event at that index.\n **/\n entryDecorations: FlameChartDecoration[][];\n groups: Group[];\n markers: FlameChartMarker[];\n\n // These four arrays are used to draw the initiator arrows, and if there are\n // multiple arrows, they should be a chain.\n initiatorsData: FlameChartInitiatorData[];\n\n selectedGroup: Group|null;\n private constructor(\n entryLevels: number[]|Uint16Array, entryTotalTimes: number[]|Float32Array, entryStartTimes: number[]|Float64Array,\n groups: Group[]|null, entryDecorations: FlameChartDecoration[][] = [],\n initiatorsData: FlameChartInitiatorData[] = []) {\n this.entryLevels = entryLevels;\n this.entryTotalTimes = entryTotalTimes;\n this.entryStartTimes = entryStartTimes;\n this.entryDecorations = entryDecorations;\n this.groups = groups || [];\n this.markers = [];\n this.initiatorsData = initiatorsData || [];\n this.selectedGroup = null;\n }\n\n // TODO(crbug.com/1501055) Thinking about refactor this class, so we can avoid create a new object when modifying the\n // flame chart.\n static create(data: {\n entryLevels: FlameChartTimelineData['entryLevels'],\n entryTotalTimes: FlameChartTimelineData['entryTotalTimes'],\n entryStartTimes: FlameChartTimelineData['entryStartTimes'],\n groups: FlameChartTimelineData['groups']|null,\n entryDecorations?: FlameChartDecoration[][],\n initiatorsData?: FlameChartTimelineData['initiatorsData'],\n }): FlameChartTimelineData {\n return new FlameChartTimelineData(\n data.entryLevels, data.entryTotalTimes, data.entryStartTimes, data.groups, data.entryDecorations || [],\n data.initiatorsData || []);\n }\n\n // TODO(crbug.com/1501055) Thinking about refactor this class, so we can avoid create a new object when modifying the\n // flame chart.\n static createEmpty(): FlameChartTimelineData {\n return new FlameChartTimelineData(\n [], // entry levels: what level on the timeline is an event on,\n [], // entry total times: the total duration of an event,\n [], // entry start times: the start time of a given event,\n [], // groups: a list of flame chart groups, which roughly correlate to each individual track\n );\n }\n\n resetFlowData(): void {\n this.initiatorsData = [];\n }\n}\n\nexport interface DataProviderSearchResult {\n index: number;\n startTimeMilli: TraceEngine.Types.Timing.MilliSeconds;\n provider: 'main'|'network'|'other';\n}\n\nexport interface DataProviderSearchResult {\n index: number;\n startTimeMilli: TraceEngine.Types.Timing.MilliSeconds;\n provider: 'main'|'network'|'other';\n}\n\nexport interface FlameChartDataProvider {\n minimumBoundary(): number;\n\n totalTime(): number;\n\n formatValue(value: number, precision?: number): string;\n\n maxStackDepth(): number;\n\n timelineData(rebuild?: boolean): FlameChartTimelineData|null;\n\n prepareHighlightedEntryInfo(entryIndex: number): Element|null;\n\n prepareHighlightedHiddenEntriesArrowInfo?(entryIndex: number): Element|null;\n\n canJumpToEntry(entryIndex: number): boolean;\n\n entryTitle(entryIndex: number): string|null;\n\n entryFont(entryIndex: number): string|null;\n\n entryColor(entryIndex: number): string;\n\n decorateEntry(\n entryIndex: number, context: CanvasRenderingContext2D, text: string|null, barX: number, barY: number,\n barWidth: number, barHeight: number, unclippedBarX: number, timeToPixelRatio: number): boolean;\n\n forceDecoration(entryIndex: number): boolean;\n\n forceDrawableLevel?(level: number): boolean;\n\n textColor(entryIndex: number): string;\n\n mainFrameNavigationStartEvents?(): readonly TraceEngine.Types.TraceEvents.TraceEventNavigationStart[];\n\n hasTrackConfigurationMode(): boolean;\n\n // The following functions are optional and are used in Performance panel.\n eventByIndex?(entryIndex: number): TraceEngine.Types.TraceEvents.TraceEventData\n |TraceEngine.Handlers.ModelHandlers.Frames.TimelineFrame|null;\n\n indexForEvent?(event: TraceEngine.Types.TraceEvents.TraceEventData|\n TraceEngine.Types.TraceEvents.LegacyTimelineFrame): number|null;\n\n buildFlowForInitiator?(index: number): unknown;\n\n customizedContextMenu?\n (event: MouseEvent, eventIndex: number, groupIndex: number): UI.ContextMenu.ContextMenu|undefined;\n\n search?\n (visibleWindow: TraceEngine.Types.Timing.TraceWindowMicroSeconds,\n filter: TimelineModel.TimelineModelFilter.TimelineModelFilter): DataProviderSearchResult[];\n\n // The following three functions are used for the flame chart entry customization.\n modifyTree?(action: FilterAction, entryIndex: number): void;\n\n findPossibleContextMenuActions?(node: number): PossibleFilterActions|void;\n\n handleFlameChartTransformKeyboardEvent?(event: KeyboardEvent, entryIndex: number, groupIndex: number): void;\n\n groupForEvent?(entryIndex: number): Group|null;\n}\n\nexport interface FlameChartMarker {\n startTime(): number;\n color(): string;\n title(): string|null;\n draw(context: CanvasRenderingContext2D, x: number, height: number, pixelsPerMillisecond: number): void;\n}\n\nexport const enum Events {\n /**\n * Emitted when the element of the FlameChart is focused by the user.\n **/\n CANVAS_FOCUSED = 'CanvasFocused',\n /**\n * Emitted when an event is selected by either mouse click, or hitting\n * on the keyboard - e.g. the same actions that would invoke a\n *
  • ${h}
    ${value}${value}
    ${h}
    ${value}${value}